##// END OF EJS Templates
convert: use git diff-tree -Cn% instead of --find-copies=n% for older git...
Thomas Arendsen Hein -
r23206:a7f25a31 stable
parent child Browse files
Show More
@@ -1,385 +1,385 b''
1 # git.py - git support for the convert extension
1 # git.py - git support for the convert extension
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import os
8 import os
9 import subprocess
9 import subprocess
10 from mercurial import util, config
10 from mercurial import util, config
11 from mercurial.node import hex, nullid
11 from mercurial.node import hex, nullid
12 from mercurial.i18n import _
12 from mercurial.i18n import _
13
13
14 from common import NoRepo, commit, converter_source, checktool
14 from common import NoRepo, commit, converter_source, checktool
15
15
16 class submodule(object):
16 class submodule(object):
17 def __init__(self, path, node, url):
17 def __init__(self, path, node, url):
18 self.path = path
18 self.path = path
19 self.node = node
19 self.node = node
20 self.url = url
20 self.url = url
21
21
22 def hgsub(self):
22 def hgsub(self):
23 return "%s = [git]%s" % (self.path, self.url)
23 return "%s = [git]%s" % (self.path, self.url)
24
24
25 def hgsubstate(self):
25 def hgsubstate(self):
26 return "%s %s" % (self.node, self.path)
26 return "%s %s" % (self.node, self.path)
27
27
28 class convert_git(converter_source):
28 class convert_git(converter_source):
29 # Windows does not support GIT_DIR= construct while other systems
29 # Windows does not support GIT_DIR= construct while other systems
30 # cannot remove environment variable. Just assume none have
30 # cannot remove environment variable. Just assume none have
31 # both issues.
31 # both issues.
32 if util.safehasattr(os, 'unsetenv'):
32 if util.safehasattr(os, 'unsetenv'):
33 def gitopen(self, s, err=None):
33 def gitopen(self, s, err=None):
34 prevgitdir = os.environ.get('GIT_DIR')
34 prevgitdir = os.environ.get('GIT_DIR')
35 os.environ['GIT_DIR'] = self.path
35 os.environ['GIT_DIR'] = self.path
36 try:
36 try:
37 if err == subprocess.PIPE:
37 if err == subprocess.PIPE:
38 (stdin, stdout, stderr) = util.popen3(s)
38 (stdin, stdout, stderr) = util.popen3(s)
39 return stdout
39 return stdout
40 elif err == subprocess.STDOUT:
40 elif err == subprocess.STDOUT:
41 return self.popen_with_stderr(s)
41 return self.popen_with_stderr(s)
42 else:
42 else:
43 return util.popen(s, 'rb')
43 return util.popen(s, 'rb')
44 finally:
44 finally:
45 if prevgitdir is None:
45 if prevgitdir is None:
46 del os.environ['GIT_DIR']
46 del os.environ['GIT_DIR']
47 else:
47 else:
48 os.environ['GIT_DIR'] = prevgitdir
48 os.environ['GIT_DIR'] = prevgitdir
49
49
50 def gitpipe(self, s):
50 def gitpipe(self, s):
51 prevgitdir = os.environ.get('GIT_DIR')
51 prevgitdir = os.environ.get('GIT_DIR')
52 os.environ['GIT_DIR'] = self.path
52 os.environ['GIT_DIR'] = self.path
53 try:
53 try:
54 return util.popen3(s)
54 return util.popen3(s)
55 finally:
55 finally:
56 if prevgitdir is None:
56 if prevgitdir is None:
57 del os.environ['GIT_DIR']
57 del os.environ['GIT_DIR']
58 else:
58 else:
59 os.environ['GIT_DIR'] = prevgitdir
59 os.environ['GIT_DIR'] = prevgitdir
60
60
61 else:
61 else:
62 def gitopen(self, s, err=None):
62 def gitopen(self, s, err=None):
63 if err == subprocess.PIPE:
63 if err == subprocess.PIPE:
64 (sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s))
64 (sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s))
65 return so
65 return so
66 elif err == subprocess.STDOUT:
66 elif err == subprocess.STDOUT:
67 return self.popen_with_stderr(s)
67 return self.popen_with_stderr(s)
68 else:
68 else:
69 return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
69 return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
70
70
71 def gitpipe(self, s):
71 def gitpipe(self, s):
72 return util.popen3('GIT_DIR=%s %s' % (self.path, s))
72 return util.popen3('GIT_DIR=%s %s' % (self.path, s))
73
73
74 def popen_with_stderr(self, s):
74 def popen_with_stderr(self, s):
75 p = subprocess.Popen(s, shell=True, bufsize=-1,
75 p = subprocess.Popen(s, shell=True, bufsize=-1,
76 close_fds=util.closefds,
76 close_fds=util.closefds,
77 stdin=subprocess.PIPE,
77 stdin=subprocess.PIPE,
78 stdout=subprocess.PIPE,
78 stdout=subprocess.PIPE,
79 stderr=subprocess.STDOUT,
79 stderr=subprocess.STDOUT,
80 universal_newlines=False,
80 universal_newlines=False,
81 env=None)
81 env=None)
82 return p.stdout
82 return p.stdout
83
83
84 def gitread(self, s):
84 def gitread(self, s):
85 fh = self.gitopen(s)
85 fh = self.gitopen(s)
86 data = fh.read()
86 data = fh.read()
87 return data, fh.close()
87 return data, fh.close()
88
88
89 def __init__(self, ui, path, rev=None):
89 def __init__(self, ui, path, rev=None):
90 super(convert_git, self).__init__(ui, path, rev=rev)
90 super(convert_git, self).__init__(ui, path, rev=rev)
91
91
92 if os.path.isdir(path + "/.git"):
92 if os.path.isdir(path + "/.git"):
93 path += "/.git"
93 path += "/.git"
94 if not os.path.exists(path + "/objects"):
94 if not os.path.exists(path + "/objects"):
95 raise NoRepo(_("%s does not look like a Git repository") % path)
95 raise NoRepo(_("%s does not look like a Git repository") % path)
96
96
97 # The default value (50) is based on the default for 'git diff'.
97 # The default value (50) is based on the default for 'git diff'.
98 similarity = ui.configint('convert', 'git.similarity', default=50)
98 similarity = ui.configint('convert', 'git.similarity', default=50)
99 if similarity < 0 or similarity > 100:
99 if similarity < 0 or similarity > 100:
100 raise util.Abort(_('similarity must be between 0 and 100'))
100 raise util.Abort(_('similarity must be between 0 and 100'))
101 if similarity > 0:
101 if similarity > 0:
102 self.simopt = '--find-copies=%d%%' % similarity
102 self.simopt = '-C%d%%' % similarity
103 findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
103 findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
104 False)
104 False)
105 if findcopiesharder:
105 if findcopiesharder:
106 self.simopt += ' --find-copies-harder'
106 self.simopt += ' --find-copies-harder'
107 else:
107 else:
108 self.simopt = ''
108 self.simopt = ''
109
109
110 checktool('git', 'git')
110 checktool('git', 'git')
111
111
112 self.path = path
112 self.path = path
113 self.submodules = []
113 self.submodules = []
114
114
115 self.catfilepipe = self.gitpipe('git cat-file --batch')
115 self.catfilepipe = self.gitpipe('git cat-file --batch')
116
116
117 def after(self):
117 def after(self):
118 for f in self.catfilepipe:
118 for f in self.catfilepipe:
119 f.close()
119 f.close()
120
120
121 def getheads(self):
121 def getheads(self):
122 if not self.rev:
122 if not self.rev:
123 heads, ret = self.gitread('git rev-parse --branches --remotes')
123 heads, ret = self.gitread('git rev-parse --branches --remotes')
124 heads = heads.splitlines()
124 heads = heads.splitlines()
125 else:
125 else:
126 heads, ret = self.gitread("git rev-parse --verify %s" % self.rev)
126 heads, ret = self.gitread("git rev-parse --verify %s" % self.rev)
127 heads = [heads[:-1]]
127 heads = [heads[:-1]]
128 if ret:
128 if ret:
129 raise util.Abort(_('cannot retrieve git heads'))
129 raise util.Abort(_('cannot retrieve git heads'))
130 return heads
130 return heads
131
131
132 def catfile(self, rev, type):
132 def catfile(self, rev, type):
133 if rev == hex(nullid):
133 if rev == hex(nullid):
134 raise IOError
134 raise IOError
135 self.catfilepipe[0].write(rev+'\n')
135 self.catfilepipe[0].write(rev+'\n')
136 self.catfilepipe[0].flush()
136 self.catfilepipe[0].flush()
137 info = self.catfilepipe[1].readline().split()
137 info = self.catfilepipe[1].readline().split()
138 if info[1] != type:
138 if info[1] != type:
139 raise util.Abort(_('cannot read %r object at %s') % (type, rev))
139 raise util.Abort(_('cannot read %r object at %s') % (type, rev))
140 size = int(info[2])
140 size = int(info[2])
141 data = self.catfilepipe[1].read(size)
141 data = self.catfilepipe[1].read(size)
142 if len(data) < size:
142 if len(data) < size:
143 raise util.Abort(_('cannot read %r object at %s: unexpected size')
143 raise util.Abort(_('cannot read %r object at %s: unexpected size')
144 % (type, rev))
144 % (type, rev))
145 # read the trailing newline
145 # read the trailing newline
146 self.catfilepipe[1].read(1)
146 self.catfilepipe[1].read(1)
147 return data
147 return data
148
148
149 def getfile(self, name, rev):
149 def getfile(self, name, rev):
150 if rev == hex(nullid):
150 if rev == hex(nullid):
151 return None, None
151 return None, None
152 if name == '.hgsub':
152 if name == '.hgsub':
153 data = '\n'.join([m.hgsub() for m in self.submoditer()])
153 data = '\n'.join([m.hgsub() for m in self.submoditer()])
154 mode = ''
154 mode = ''
155 elif name == '.hgsubstate':
155 elif name == '.hgsubstate':
156 data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
156 data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
157 mode = ''
157 mode = ''
158 else:
158 else:
159 data = self.catfile(rev, "blob")
159 data = self.catfile(rev, "blob")
160 mode = self.modecache[(name, rev)]
160 mode = self.modecache[(name, rev)]
161 return data, mode
161 return data, mode
162
162
163 def submoditer(self):
163 def submoditer(self):
164 null = hex(nullid)
164 null = hex(nullid)
165 for m in sorted(self.submodules, key=lambda p: p.path):
165 for m in sorted(self.submodules, key=lambda p: p.path):
166 if m.node != null:
166 if m.node != null:
167 yield m
167 yield m
168
168
169 def parsegitmodules(self, content):
169 def parsegitmodules(self, content):
170 """Parse the formatted .gitmodules file, example file format:
170 """Parse the formatted .gitmodules file, example file format:
171 [submodule "sub"]\n
171 [submodule "sub"]\n
172 \tpath = sub\n
172 \tpath = sub\n
173 \turl = git://giturl\n
173 \turl = git://giturl\n
174 """
174 """
175 self.submodules = []
175 self.submodules = []
176 c = config.config()
176 c = config.config()
177 # Each item in .gitmodules starts with \t that cant be parsed
177 # Each item in .gitmodules starts with \t that cant be parsed
178 c.parse('.gitmodules', content.replace('\t',''))
178 c.parse('.gitmodules', content.replace('\t',''))
179 for sec in c.sections():
179 for sec in c.sections():
180 s = c[sec]
180 s = c[sec]
181 if 'url' in s and 'path' in s:
181 if 'url' in s and 'path' in s:
182 self.submodules.append(submodule(s['path'], '', s['url']))
182 self.submodules.append(submodule(s['path'], '', s['url']))
183
183
184 def retrievegitmodules(self, version):
184 def retrievegitmodules(self, version):
185 modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
185 modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
186 if ret:
186 if ret:
187 raise util.Abort(_('cannot read submodules config file in %s') %
187 raise util.Abort(_('cannot read submodules config file in %s') %
188 version)
188 version)
189 self.parsegitmodules(modules)
189 self.parsegitmodules(modules)
190 for m in self.submodules:
190 for m in self.submodules:
191 node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path))
191 node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path))
192 if ret:
192 if ret:
193 continue
193 continue
194 m.node = node.strip()
194 m.node = node.strip()
195
195
196 def getchanges(self, version, full):
196 def getchanges(self, version, full):
197 if full:
197 if full:
198 raise util.Abort(_("convert from git do not support --full"))
198 raise util.Abort(_("convert from git do not support --full"))
199 self.modecache = {}
199 self.modecache = {}
200 fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % (
200 fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % (
201 self.simopt, version))
201 self.simopt, version))
202 changes = []
202 changes = []
203 copies = {}
203 copies = {}
204 seen = set()
204 seen = set()
205 entry = None
205 entry = None
206 subexists = [False]
206 subexists = [False]
207 subdeleted = [False]
207 subdeleted = [False]
208 difftree = fh.read().split('\x00')
208 difftree = fh.read().split('\x00')
209 lcount = len(difftree)
209 lcount = len(difftree)
210 i = 0
210 i = 0
211
211
212 def add(entry, f, isdest):
212 def add(entry, f, isdest):
213 seen.add(f)
213 seen.add(f)
214 h = entry[3]
214 h = entry[3]
215 p = (entry[1] == "100755")
215 p = (entry[1] == "100755")
216 s = (entry[1] == "120000")
216 s = (entry[1] == "120000")
217 renamesource = (not isdest and entry[4][0] == 'R')
217 renamesource = (not isdest and entry[4][0] == 'R')
218
218
219 if f == '.gitmodules':
219 if f == '.gitmodules':
220 subexists[0] = True
220 subexists[0] = True
221 if entry[4] == 'D' or renamesource:
221 if entry[4] == 'D' or renamesource:
222 subdeleted[0] = True
222 subdeleted[0] = True
223 changes.append(('.hgsub', hex(nullid)))
223 changes.append(('.hgsub', hex(nullid)))
224 else:
224 else:
225 changes.append(('.hgsub', ''))
225 changes.append(('.hgsub', ''))
226 elif entry[1] == '160000' or entry[0] == ':160000':
226 elif entry[1] == '160000' or entry[0] == ':160000':
227 subexists[0] = True
227 subexists[0] = True
228 else:
228 else:
229 if renamesource:
229 if renamesource:
230 h = hex(nullid)
230 h = hex(nullid)
231 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
231 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
232 changes.append((f, h))
232 changes.append((f, h))
233
233
234 while i < lcount:
234 while i < lcount:
235 l = difftree[i]
235 l = difftree[i]
236 i += 1
236 i += 1
237 if not entry:
237 if not entry:
238 if not l.startswith(':'):
238 if not l.startswith(':'):
239 continue
239 continue
240 entry = l.split()
240 entry = l.split()
241 continue
241 continue
242 f = l
242 f = l
243 if f not in seen:
243 if f not in seen:
244 add(entry, f, False)
244 add(entry, f, False)
245 # A file can be copied multiple times, or modified and copied
245 # A file can be copied multiple times, or modified and copied
246 # simultaneously. So f can be repeated even if fdest isn't.
246 # simultaneously. So f can be repeated even if fdest isn't.
247 if entry[4][0] in 'RC':
247 if entry[4][0] in 'RC':
248 # rename or copy: next line is the destination
248 # rename or copy: next line is the destination
249 fdest = difftree[i]
249 fdest = difftree[i]
250 i += 1
250 i += 1
251 if fdest not in seen:
251 if fdest not in seen:
252 add(entry, fdest, True)
252 add(entry, fdest, True)
253 # .gitmodules isn't imported at all, so it being copied to
253 # .gitmodules isn't imported at all, so it being copied to
254 # and fro doesn't really make sense
254 # and fro doesn't really make sense
255 if f != '.gitmodules' and fdest != '.gitmodules':
255 if f != '.gitmodules' and fdest != '.gitmodules':
256 copies[fdest] = f
256 copies[fdest] = f
257 entry = None
257 entry = None
258 if fh.close():
258 if fh.close():
259 raise util.Abort(_('cannot read changes in %s') % version)
259 raise util.Abort(_('cannot read changes in %s') % version)
260
260
261 if subexists[0]:
261 if subexists[0]:
262 if subdeleted[0]:
262 if subdeleted[0]:
263 changes.append(('.hgsubstate', hex(nullid)))
263 changes.append(('.hgsubstate', hex(nullid)))
264 else:
264 else:
265 self.retrievegitmodules(version)
265 self.retrievegitmodules(version)
266 changes.append(('.hgsubstate', ''))
266 changes.append(('.hgsubstate', ''))
267 return (changes, copies)
267 return (changes, copies)
268
268
269 def getcommit(self, version):
269 def getcommit(self, version):
270 c = self.catfile(version, "commit") # read the commit hash
270 c = self.catfile(version, "commit") # read the commit hash
271 end = c.find("\n\n")
271 end = c.find("\n\n")
272 message = c[end + 2:]
272 message = c[end + 2:]
273 message = self.recode(message)
273 message = self.recode(message)
274 l = c[:end].splitlines()
274 l = c[:end].splitlines()
275 parents = []
275 parents = []
276 author = committer = None
276 author = committer = None
277 for e in l[1:]:
277 for e in l[1:]:
278 n, v = e.split(" ", 1)
278 n, v = e.split(" ", 1)
279 if n == "author":
279 if n == "author":
280 p = v.split()
280 p = v.split()
281 tm, tz = p[-2:]
281 tm, tz = p[-2:]
282 author = " ".join(p[:-2])
282 author = " ".join(p[:-2])
283 if author[0] == "<": author = author[1:-1]
283 if author[0] == "<": author = author[1:-1]
284 author = self.recode(author)
284 author = self.recode(author)
285 if n == "committer":
285 if n == "committer":
286 p = v.split()
286 p = v.split()
287 tm, tz = p[-2:]
287 tm, tz = p[-2:]
288 committer = " ".join(p[:-2])
288 committer = " ".join(p[:-2])
289 if committer[0] == "<": committer = committer[1:-1]
289 if committer[0] == "<": committer = committer[1:-1]
290 committer = self.recode(committer)
290 committer = self.recode(committer)
291 if n == "parent":
291 if n == "parent":
292 parents.append(v)
292 parents.append(v)
293
293
294 if committer and committer != author:
294 if committer and committer != author:
295 message += "\ncommitter: %s\n" % committer
295 message += "\ncommitter: %s\n" % committer
296 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
296 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
297 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
297 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
298 date = tm + " " + str(tz)
298 date = tm + " " + str(tz)
299
299
300 c = commit(parents=parents, date=date, author=author, desc=message,
300 c = commit(parents=parents, date=date, author=author, desc=message,
301 rev=version)
301 rev=version)
302 return c
302 return c
303
303
304 def numcommits(self):
304 def numcommits(self):
305 return len([None for _ in self.gitopen('git rev-list --all')])
305 return len([None for _ in self.gitopen('git rev-list --all')])
306
306
307 def gettags(self):
307 def gettags(self):
308 tags = {}
308 tags = {}
309 alltags = {}
309 alltags = {}
310 fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
310 fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
311 err=subprocess.STDOUT)
311 err=subprocess.STDOUT)
312 prefix = 'refs/tags/'
312 prefix = 'refs/tags/'
313
313
314 # Build complete list of tags, both annotated and bare ones
314 # Build complete list of tags, both annotated and bare ones
315 for line in fh:
315 for line in fh:
316 line = line.strip()
316 line = line.strip()
317 if line.startswith("error:") or line.startswith("fatal:"):
317 if line.startswith("error:") or line.startswith("fatal:"):
318 raise util.Abort(_('cannot read tags from %s') % self.path)
318 raise util.Abort(_('cannot read tags from %s') % self.path)
319 node, tag = line.split(None, 1)
319 node, tag = line.split(None, 1)
320 if not tag.startswith(prefix):
320 if not tag.startswith(prefix):
321 continue
321 continue
322 alltags[tag[len(prefix):]] = node
322 alltags[tag[len(prefix):]] = node
323 if fh.close():
323 if fh.close():
324 raise util.Abort(_('cannot read tags from %s') % self.path)
324 raise util.Abort(_('cannot read tags from %s') % self.path)
325
325
326 # Filter out tag objects for annotated tag refs
326 # Filter out tag objects for annotated tag refs
327 for tag in alltags:
327 for tag in alltags:
328 if tag.endswith('^{}'):
328 if tag.endswith('^{}'):
329 tags[tag[:-3]] = alltags[tag]
329 tags[tag[:-3]] = alltags[tag]
330 else:
330 else:
331 if tag + '^{}' in alltags:
331 if tag + '^{}' in alltags:
332 continue
332 continue
333 else:
333 else:
334 tags[tag] = alltags[tag]
334 tags[tag] = alltags[tag]
335
335
336 return tags
336 return tags
337
337
338 def getchangedfiles(self, version, i):
338 def getchangedfiles(self, version, i):
339 changes = []
339 changes = []
340 if i is None:
340 if i is None:
341 fh = self.gitopen("git diff-tree --root -m -r %s" % version)
341 fh = self.gitopen("git diff-tree --root -m -r %s" % version)
342 for l in fh:
342 for l in fh:
343 if "\t" not in l:
343 if "\t" not in l:
344 continue
344 continue
345 m, f = l[:-1].split("\t")
345 m, f = l[:-1].split("\t")
346 changes.append(f)
346 changes.append(f)
347 else:
347 else:
348 fh = self.gitopen('git diff-tree --name-only --root -r %s '
348 fh = self.gitopen('git diff-tree --name-only --root -r %s '
349 '"%s^%s" --' % (version, version, i + 1))
349 '"%s^%s" --' % (version, version, i + 1))
350 changes = [f.rstrip('\n') for f in fh]
350 changes = [f.rstrip('\n') for f in fh]
351 if fh.close():
351 if fh.close():
352 raise util.Abort(_('cannot read changes in %s') % version)
352 raise util.Abort(_('cannot read changes in %s') % version)
353
353
354 return changes
354 return changes
355
355
356 def getbookmarks(self):
356 def getbookmarks(self):
357 bookmarks = {}
357 bookmarks = {}
358
358
359 # Interesting references in git are prefixed
359 # Interesting references in git are prefixed
360 prefix = 'refs/heads/'
360 prefix = 'refs/heads/'
361 prefixlen = len(prefix)
361 prefixlen = len(prefix)
362
362
363 # factor two commands
363 # factor two commands
364 gitcmd = { 'remote/': 'git ls-remote --heads origin',
364 gitcmd = { 'remote/': 'git ls-remote --heads origin',
365 '': 'git show-ref'}
365 '': 'git show-ref'}
366
366
367 # Origin heads
367 # Origin heads
368 for reftype in gitcmd:
368 for reftype in gitcmd:
369 try:
369 try:
370 fh = self.gitopen(gitcmd[reftype], err=subprocess.PIPE)
370 fh = self.gitopen(gitcmd[reftype], err=subprocess.PIPE)
371 for line in fh:
371 for line in fh:
372 line = line.strip()
372 line = line.strip()
373 rev, name = line.split(None, 1)
373 rev, name = line.split(None, 1)
374 if not name.startswith(prefix):
374 if not name.startswith(prefix):
375 continue
375 continue
376 name = '%s%s' % (reftype, name[prefixlen:])
376 name = '%s%s' % (reftype, name[prefixlen:])
377 bookmarks[name] = rev
377 bookmarks[name] = rev
378 except Exception:
378 except Exception:
379 pass
379 pass
380
380
381 return bookmarks
381 return bookmarks
382
382
383 def checkrevformat(self, revstr, mapname='splicemap'):
383 def checkrevformat(self, revstr, mapname='splicemap'):
384 """ git revision string is a 40 byte hex """
384 """ git revision string is a 40 byte hex """
385 self.checkhexformat(revstr, mapname)
385 self.checkhexformat(revstr, mapname)
General Comments 0
You need to be logged in to leave comments. Login now