blob: e0a85d7a3f1e39075e557d627dbb79553cdf627c [file] [log] [blame]
Shawn O. Pearced237b692009-04-17 18:49:50 -07001#
2# Copyright (C) 2009 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import os
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070017from trace import Trace
Renaud Paquaybed8b622018-09-27 10:46:58 -070018import platform_utils
Shawn O. Pearced237b692009-04-17 18:49:50 -070019
Zac Livingston9ead97b2017-06-13 08:29:04 -060020HEAD = 'HEAD'
21R_CHANGES = 'refs/changes/'
22R_HEADS = 'refs/heads/'
23R_TAGS = 'refs/tags/'
24R_PUB = 'refs/published/'
25R_M = 'refs/remotes/m/'
Shawn O. Pearced237b692009-04-17 18:49:50 -070026
27
28class GitRefs(object):
29 def __init__(self, gitdir):
30 self._gitdir = gitdir
31 self._phyref = None
32 self._symref = None
33 self._mtime = {}
34
35 @property
36 def all(self):
Shawn O. Pearce0f3dd232009-04-17 20:32:44 -070037 self._EnsureLoaded()
Shawn O. Pearced237b692009-04-17 18:49:50 -070038 return self._phyref
39
40 def get(self, name):
41 try:
42 return self.all[name]
43 except KeyError:
44 return ''
45
Shawn O. Pearcefbcde472009-04-17 20:58:02 -070046 def deleted(self, name):
47 if self._phyref is not None:
48 if name in self._phyref:
49 del self._phyref[name]
50
51 if name in self._symref:
52 del self._symref[name]
53
54 if name in self._mtime:
55 del self._mtime[name]
56
Shawn O. Pearce0f3dd232009-04-17 20:32:44 -070057 def symref(self, name):
58 try:
59 self._EnsureLoaded()
60 return self._symref[name]
61 except KeyError:
62 return ''
63
64 def _EnsureLoaded(self):
65 if self._phyref is None or self._NeedUpdate():
66 self._LoadAll()
67
Shawn O. Pearced237b692009-04-17 18:49:50 -070068 def _NeedUpdate(self):
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070069 Trace(': scan refs %s', self._gitdir)
70
Chirayu Desai217ea7d2013-03-01 19:14:38 +053071 for name, mtime in self._mtime.items():
Shawn O. Pearced237b692009-04-17 18:49:50 -070072 try:
73 if mtime != os.path.getmtime(os.path.join(self._gitdir, name)):
74 return True
75 except OSError:
76 return True
77 return False
78
79 def _LoadAll(self):
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070080 Trace(': load refs %s', self._gitdir)
81
Shawn O. Pearced237b692009-04-17 18:49:50 -070082 self._phyref = {}
83 self._symref = {}
84 self._mtime = {}
85
86 self._ReadPackedRefs()
87 self._ReadLoose('refs/')
88 self._ReadLoose1(os.path.join(self._gitdir, HEAD), HEAD)
89
90 scan = self._symref
91 attempts = 0
92 while scan and attempts < 5:
93 scan_next = {}
Chirayu Desai217ea7d2013-03-01 19:14:38 +053094 for name, dest in scan.items():
Shawn O. Pearced237b692009-04-17 18:49:50 -070095 if dest in self._phyref:
96 self._phyref[name] = self._phyref[dest]
97 else:
98 scan_next[name] = dest
99 scan = scan_next
100 attempts += 1
101
102 def _ReadPackedRefs(self):
103 path = os.path.join(self._gitdir, 'packed-refs')
104 try:
Chirayu Desai0eb35cb2013-11-19 18:46:29 +0530105 fd = open(path, 'r')
Shawn O. Pearced237b692009-04-17 18:49:50 -0700106 mtime = os.path.getmtime(path)
107 except IOError:
108 return
109 except OSError:
110 return
111 try:
112 for line in fd:
Chirayu Desai217ea7d2013-03-01 19:14:38 +0530113 line = str(line)
Shawn O. Pearced237b692009-04-17 18:49:50 -0700114 if line[0] == '#':
115 continue
116 if line[0] == '^':
117 continue
118
119 line = line[:-1]
120 p = line.split(' ')
David Pursehouse8a68ff92012-09-24 12:15:13 +0900121 ref_id = p[0]
Shawn O. Pearced237b692009-04-17 18:49:50 -0700122 name = p[1]
123
David Pursehouse8a68ff92012-09-24 12:15:13 +0900124 self._phyref[name] = ref_id
Shawn O. Pearced237b692009-04-17 18:49:50 -0700125 finally:
126 fd.close()
127 self._mtime['packed-refs'] = mtime
128
129 def _ReadLoose(self, prefix):
130 base = os.path.join(self._gitdir, prefix)
Renaud Paquaybed8b622018-09-27 10:46:58 -0700131 for name in platform_utils.listdir(base):
Shawn O. Pearced237b692009-04-17 18:49:50 -0700132 p = os.path.join(base, name)
Renaud Paquaybed8b622018-09-27 10:46:58 -0700133 if platform_utils.isdir(p):
Shawn O. Pearced237b692009-04-17 18:49:50 -0700134 self._mtime[prefix] = os.path.getmtime(base)
135 self._ReadLoose(prefix + name + '/')
136 elif name.endswith('.lock'):
137 pass
138 else:
139 self._ReadLoose1(p, prefix + name)
140
141 def _ReadLoose1(self, path, name):
142 try:
Renaud Paquay2a4be942016-11-01 13:48:15 -0700143 fd = open(path)
David Pursehouse1d947b32012-10-25 12:23:11 +0900144 except IOError:
Shawn O. Pearced237b692009-04-17 18:49:50 -0700145 return
Shawn O. Pearcecc14fa92011-11-29 12:32:56 -0800146
Shawn O. Pearced237b692009-04-17 18:49:50 -0700147 try:
Shawn O. Pearcecc14fa92011-11-29 12:32:56 -0800148 try:
149 mtime = os.path.getmtime(path)
David Pursehouse8a68ff92012-09-24 12:15:13 +0900150 ref_id = fd.readline()
David Pursehouse1d947b32012-10-25 12:23:11 +0900151 except (IOError, OSError):
Shawn O. Pearcecc14fa92011-11-29 12:32:56 -0800152 return
Shawn O. Pearced237b692009-04-17 18:49:50 -0700153 finally:
154 fd.close()
155
Chirayu Desai217ea7d2013-03-01 19:14:38 +0530156 try:
157 ref_id = ref_id.decode()
158 except AttributeError:
159 pass
David Pursehouse8a68ff92012-09-24 12:15:13 +0900160 if not ref_id:
Shawn O. Pearced237b692009-04-17 18:49:50 -0700161 return
David Pursehouse8a68ff92012-09-24 12:15:13 +0900162 ref_id = ref_id[:-1]
Shawn O. Pearced237b692009-04-17 18:49:50 -0700163
David Pursehouse8a68ff92012-09-24 12:15:13 +0900164 if ref_id.startswith('ref: '):
165 self._symref[name] = ref_id[5:]
Shawn O. Pearced237b692009-04-17 18:49:50 -0700166 else:
David Pursehouse8a68ff92012-09-24 12:15:13 +0900167 self._phyref[name] = ref_id
Shawn O. Pearced237b692009-04-17 18:49:50 -0700168 self._mtime[name] = mtime