blob: 7feaffb1e1f170090d0d4e0572da4d336ab5e7f6 [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
Shawn O. Pearced237b692009-04-17 18:49:50 -070018
Zac Livingston9ead97b2017-06-13 08:29:04 -060019HEAD = 'HEAD'
20R_CHANGES = 'refs/changes/'
21R_HEADS = 'refs/heads/'
22R_TAGS = 'refs/tags/'
23R_PUB = 'refs/published/'
24R_M = 'refs/remotes/m/'
Shawn O. Pearced237b692009-04-17 18:49:50 -070025
26
27class GitRefs(object):
28 def __init__(self, gitdir):
29 self._gitdir = gitdir
30 self._phyref = None
31 self._symref = None
32 self._mtime = {}
33
34 @property
35 def all(self):
Shawn O. Pearce0f3dd232009-04-17 20:32:44 -070036 self._EnsureLoaded()
Shawn O. Pearced237b692009-04-17 18:49:50 -070037 return self._phyref
38
39 def get(self, name):
40 try:
41 return self.all[name]
42 except KeyError:
43 return ''
44
Shawn O. Pearcefbcde472009-04-17 20:58:02 -070045 def deleted(self, name):
46 if self._phyref is not None:
47 if name in self._phyref:
48 del self._phyref[name]
49
50 if name in self._symref:
51 del self._symref[name]
52
53 if name in self._mtime:
54 del self._mtime[name]
55
Shawn O. Pearce0f3dd232009-04-17 20:32:44 -070056 def symref(self, name):
57 try:
58 self._EnsureLoaded()
59 return self._symref[name]
60 except KeyError:
61 return ''
62
63 def _EnsureLoaded(self):
64 if self._phyref is None or self._NeedUpdate():
65 self._LoadAll()
66
Shawn O. Pearced237b692009-04-17 18:49:50 -070067 def _NeedUpdate(self):
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070068 Trace(': scan refs %s', self._gitdir)
69
Chirayu Desai217ea7d2013-03-01 19:14:38 +053070 for name, mtime in self._mtime.items():
Shawn O. Pearced237b692009-04-17 18:49:50 -070071 try:
72 if mtime != os.path.getmtime(os.path.join(self._gitdir, name)):
73 return True
74 except OSError:
75 return True
76 return False
77
78 def _LoadAll(self):
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070079 Trace(': load refs %s', self._gitdir)
80
Shawn O. Pearced237b692009-04-17 18:49:50 -070081 self._phyref = {}
82 self._symref = {}
83 self._mtime = {}
84
85 self._ReadPackedRefs()
86 self._ReadLoose('refs/')
87 self._ReadLoose1(os.path.join(self._gitdir, HEAD), HEAD)
88
89 scan = self._symref
90 attempts = 0
91 while scan and attempts < 5:
92 scan_next = {}
Chirayu Desai217ea7d2013-03-01 19:14:38 +053093 for name, dest in scan.items():
Shawn O. Pearced237b692009-04-17 18:49:50 -070094 if dest in self._phyref:
95 self._phyref[name] = self._phyref[dest]
96 else:
97 scan_next[name] = dest
98 scan = scan_next
99 attempts += 1
100
101 def _ReadPackedRefs(self):
102 path = os.path.join(self._gitdir, 'packed-refs')
103 try:
Chirayu Desai0eb35cb2013-11-19 18:46:29 +0530104 fd = open(path, 'r')
Shawn O. Pearced237b692009-04-17 18:49:50 -0700105 mtime = os.path.getmtime(path)
106 except IOError:
107 return
108 except OSError:
109 return
110 try:
111 for line in fd:
Chirayu Desai217ea7d2013-03-01 19:14:38 +0530112 line = str(line)
Shawn O. Pearced237b692009-04-17 18:49:50 -0700113 if line[0] == '#':
114 continue
115 if line[0] == '^':
116 continue
117
118 line = line[:-1]
119 p = line.split(' ')
David Pursehouse8a68ff92012-09-24 12:15:13 +0900120 ref_id = p[0]
Shawn O. Pearced237b692009-04-17 18:49:50 -0700121 name = p[1]
122
David Pursehouse8a68ff92012-09-24 12:15:13 +0900123 self._phyref[name] = ref_id
Shawn O. Pearced237b692009-04-17 18:49:50 -0700124 finally:
125 fd.close()
126 self._mtime['packed-refs'] = mtime
127
128 def _ReadLoose(self, prefix):
129 base = os.path.join(self._gitdir, prefix)
130 for name in os.listdir(base):
131 p = os.path.join(base, name)
132 if os.path.isdir(p):
133 self._mtime[prefix] = os.path.getmtime(base)
134 self._ReadLoose(prefix + name + '/')
135 elif name.endswith('.lock'):
136 pass
137 else:
138 self._ReadLoose1(p, prefix + name)
139
140 def _ReadLoose1(self, path, name):
141 try:
Renaud Paquay2a4be942016-11-01 13:48:15 -0700142 fd = open(path)
David Pursehouse1d947b32012-10-25 12:23:11 +0900143 except IOError:
Shawn O. Pearced237b692009-04-17 18:49:50 -0700144 return
Shawn O. Pearcecc14fa92011-11-29 12:32:56 -0800145
Shawn O. Pearced237b692009-04-17 18:49:50 -0700146 try:
Shawn O. Pearcecc14fa92011-11-29 12:32:56 -0800147 try:
148 mtime = os.path.getmtime(path)
David Pursehouse8a68ff92012-09-24 12:15:13 +0900149 ref_id = fd.readline()
David Pursehouse1d947b32012-10-25 12:23:11 +0900150 except (IOError, OSError):
Shawn O. Pearcecc14fa92011-11-29 12:32:56 -0800151 return
Shawn O. Pearced237b692009-04-17 18:49:50 -0700152 finally:
153 fd.close()
154
Chirayu Desai217ea7d2013-03-01 19:14:38 +0530155 try:
156 ref_id = ref_id.decode()
157 except AttributeError:
158 pass
David Pursehouse8a68ff92012-09-24 12:15:13 +0900159 if not ref_id:
Shawn O. Pearced237b692009-04-17 18:49:50 -0700160 return
David Pursehouse8a68ff92012-09-24 12:15:13 +0900161 ref_id = ref_id[:-1]
Shawn O. Pearced237b692009-04-17 18:49:50 -0700162
David Pursehouse8a68ff92012-09-24 12:15:13 +0900163 if ref_id.startswith('ref: '):
164 self._symref[name] = ref_id[5:]
Shawn O. Pearced237b692009-04-17 18:49:50 -0700165 else:
David Pursehouse8a68ff92012-09-24 12:15:13 +0900166 self._phyref[name] = ref_id
Shawn O. Pearced237b692009-04-17 18:49:50 -0700167 self._mtime[name] = mtime