blob: e2b62ab229f8de5883d7de49d6c557aace958c9a [file] [log] [blame]
Mike Frysingerf6013762019-06-13 02:30:51 -04001# -*- coding:utf-8 -*-
Shawn O. Pearced237b692009-04-17 18:49:50 -07002#
3# Copyright (C) 2009 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import os
Mike Frysinger8a11f6f2019-08-27 00:26:15 -040018from repo_trace import Trace
Renaud Paquaybed8b622018-09-27 10:46:58 -070019import platform_utils
Shawn O. Pearced237b692009-04-17 18:49:50 -070020
David Pursehouse54a4e602020-02-12 14:31:05 +090021HEAD = 'HEAD'
Zac Livingston9ead97b2017-06-13 08:29:04 -060022R_CHANGES = 'refs/changes/'
David Pursehouse54a4e602020-02-12 14:31:05 +090023R_HEADS = 'refs/heads/'
24R_TAGS = 'refs/tags/'
25R_PUB = 'refs/published/'
Mike Frysinger21b7fbe2020-02-26 23:53:36 -050026R_WORKTREE = 'refs/worktree/'
27R_WORKTREE_M = R_WORKTREE + 'm/'
David Pursehouse54a4e602020-02-12 14:31:05 +090028R_M = 'refs/remotes/m/'
Shawn O. Pearced237b692009-04-17 18:49:50 -070029
30
31class GitRefs(object):
32 def __init__(self, gitdir):
33 self._gitdir = gitdir
34 self._phyref = None
35 self._symref = None
36 self._mtime = {}
37
38 @property
39 def all(self):
Shawn O. Pearce0f3dd232009-04-17 20:32:44 -070040 self._EnsureLoaded()
Shawn O. Pearced237b692009-04-17 18:49:50 -070041 return self._phyref
42
43 def get(self, name):
44 try:
45 return self.all[name]
46 except KeyError:
47 return ''
48
Shawn O. Pearcefbcde472009-04-17 20:58:02 -070049 def deleted(self, name):
50 if self._phyref is not None:
51 if name in self._phyref:
52 del self._phyref[name]
53
54 if name in self._symref:
55 del self._symref[name]
56
57 if name in self._mtime:
58 del self._mtime[name]
59
Shawn O. Pearce0f3dd232009-04-17 20:32:44 -070060 def symref(self, name):
61 try:
62 self._EnsureLoaded()
63 return self._symref[name]
64 except KeyError:
65 return ''
66
67 def _EnsureLoaded(self):
68 if self._phyref is None or self._NeedUpdate():
69 self._LoadAll()
70
Shawn O. Pearced237b692009-04-17 18:49:50 -070071 def _NeedUpdate(self):
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070072 Trace(': scan refs %s', self._gitdir)
73
Chirayu Desai217ea7d2013-03-01 19:14:38 +053074 for name, mtime in self._mtime.items():
Shawn O. Pearced237b692009-04-17 18:49:50 -070075 try:
76 if mtime != os.path.getmtime(os.path.join(self._gitdir, name)):
77 return True
78 except OSError:
79 return True
80 return False
81
82 def _LoadAll(self):
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070083 Trace(': load refs %s', self._gitdir)
84
Shawn O. Pearced237b692009-04-17 18:49:50 -070085 self._phyref = {}
86 self._symref = {}
87 self._mtime = {}
88
89 self._ReadPackedRefs()
90 self._ReadLoose('refs/')
91 self._ReadLoose1(os.path.join(self._gitdir, HEAD), HEAD)
92
93 scan = self._symref
94 attempts = 0
95 while scan and attempts < 5:
96 scan_next = {}
Chirayu Desai217ea7d2013-03-01 19:14:38 +053097 for name, dest in scan.items():
Shawn O. Pearced237b692009-04-17 18:49:50 -070098 if dest in self._phyref:
99 self._phyref[name] = self._phyref[dest]
100 else:
101 scan_next[name] = dest
102 scan = scan_next
103 attempts += 1
104
105 def _ReadPackedRefs(self):
106 path = os.path.join(self._gitdir, 'packed-refs')
107 try:
Chirayu Desai0eb35cb2013-11-19 18:46:29 +0530108 fd = open(path, 'r')
Shawn O. Pearced237b692009-04-17 18:49:50 -0700109 mtime = os.path.getmtime(path)
110 except IOError:
111 return
112 except OSError:
113 return
114 try:
115 for line in fd:
Chirayu Desai217ea7d2013-03-01 19:14:38 +0530116 line = str(line)
Shawn O. Pearced237b692009-04-17 18:49:50 -0700117 if line[0] == '#':
118 continue
119 if line[0] == '^':
120 continue
121
122 line = line[:-1]
123 p = line.split(' ')
David Pursehouse8a68ff92012-09-24 12:15:13 +0900124 ref_id = p[0]
Shawn O. Pearced237b692009-04-17 18:49:50 -0700125 name = p[1]
126
David Pursehouse8a68ff92012-09-24 12:15:13 +0900127 self._phyref[name] = ref_id
Shawn O. Pearced237b692009-04-17 18:49:50 -0700128 finally:
129 fd.close()
130 self._mtime['packed-refs'] = mtime
131
132 def _ReadLoose(self, prefix):
133 base = os.path.join(self._gitdir, prefix)
Renaud Paquaybed8b622018-09-27 10:46:58 -0700134 for name in platform_utils.listdir(base):
Shawn O. Pearced237b692009-04-17 18:49:50 -0700135 p = os.path.join(base, name)
Renaud Paquaybed8b622018-09-27 10:46:58 -0700136 if platform_utils.isdir(p):
Shawn O. Pearced237b692009-04-17 18:49:50 -0700137 self._mtime[prefix] = os.path.getmtime(base)
138 self._ReadLoose(prefix + name + '/')
139 elif name.endswith('.lock'):
140 pass
141 else:
142 self._ReadLoose1(p, prefix + name)
143
144 def _ReadLoose1(self, path, name):
145 try:
Mike Frysinger3164d402019-11-11 05:40:22 -0500146 with open(path) as fd:
Shawn O. Pearcecc14fa92011-11-29 12:32:56 -0800147 mtime = os.path.getmtime(path)
David Pursehouse8a68ff92012-09-24 12:15:13 +0900148 ref_id = fd.readline()
Mike Frysinger3164d402019-11-11 05:40:22 -0500149 except (IOError, OSError):
150 return
Shawn O. Pearced237b692009-04-17 18:49:50 -0700151
Chirayu Desai217ea7d2013-03-01 19:14:38 +0530152 try:
153 ref_id = ref_id.decode()
154 except AttributeError:
155 pass
David Pursehouse8a68ff92012-09-24 12:15:13 +0900156 if not ref_id:
Shawn O. Pearced237b692009-04-17 18:49:50 -0700157 return
David Pursehouse8a68ff92012-09-24 12:15:13 +0900158 ref_id = ref_id[:-1]
Shawn O. Pearced237b692009-04-17 18:49:50 -0700159
David Pursehouse8a68ff92012-09-24 12:15:13 +0900160 if ref_id.startswith('ref: '):
161 self._symref[name] = ref_id[5:]
Shawn O. Pearced237b692009-04-17 18:49:50 -0700162 else:
David Pursehouse8a68ff92012-09-24 12:15:13 +0900163 self._phyref[name] = ref_id
Shawn O. Pearced237b692009-04-17 18:49:50 -0700164 self._mtime[name] = mtime