comparison hgext/convert/git.py @ 4534:cc9b79216a76

Split convert extension into common and repository type modules
author Brendan Cully <brendan@kublai.com>
date Sun, 10 Jun 2007 20:08:47 -0700
parents hgext/convert/__init__.py@c3a78a49d7f0
children 06a0e0557edc
comparison
equal deleted inserted replaced
4533:36abb07c79d4 4534:cc9b79216a76
1 # git support for the convert extension
2
3 import os
4
5 from common import NoRepo, commit, converter_source
6
7 def recode(s):
8 try:
9 return s.decode("utf-8").encode("utf-8")
10 except:
11 try:
12 return s.decode("latin-1").encode("utf-8")
13 except:
14 return s.decode("utf-8", "replace").encode("utf-8")
15
16 class convert_git(converter_source):
17 def __init__(self, ui, path):
18 if os.path.isdir(path + "/.git"):
19 path += "/.git"
20 self.path = path
21 self.ui = ui
22 if not os.path.exists(path + "/objects"):
23 raise NoRepo("couldn't open GIT repo %s" % path)
24
25 def getheads(self):
26 fh = os.popen("GIT_DIR=%s git-rev-parse --verify HEAD" % self.path)
27 return [fh.read()[:-1]]
28
29 def catfile(self, rev, type):
30 if rev == "0" * 40: raise IOError()
31 fh = os.popen("GIT_DIR=%s git-cat-file %s %s 2>/dev/null"
32 % (self.path, type, rev))
33 return fh.read()
34
35 def getfile(self, name, rev):
36 return self.catfile(rev, "blob")
37
38 def getmode(self, name, rev):
39 return self.modecache[(name, rev)]
40
41 def getchanges(self, version):
42 self.modecache = {}
43 fh = os.popen("GIT_DIR=%s git-diff-tree --root -m -r %s"
44 % (self.path, version))
45 changes = []
46 for l in fh:
47 if "\t" not in l: continue
48 m, f = l[:-1].split("\t")
49 m = m.split()
50 h = m[3]
51 p = (m[1] == "100755")
52 s = (m[1] == "120000")
53 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
54 changes.append((f, h))
55 return changes
56
57 def getcommit(self, version):
58 c = self.catfile(version, "commit") # read the commit hash
59 end = c.find("\n\n")
60 message = c[end+2:]
61 message = recode(message)
62 l = c[:end].splitlines()
63 manifest = l[0].split()[1]
64 parents = []
65 for e in l[1:]:
66 n, v = e.split(" ", 1)
67 if n == "author":
68 p = v.split()
69 tm, tz = p[-2:]
70 author = " ".join(p[:-2])
71 if author[0] == "<": author = author[1:-1]
72 author = recode(author)
73 if n == "committer":
74 p = v.split()
75 tm, tz = p[-2:]
76 committer = " ".join(p[:-2])
77 if committer[0] == "<": committer = committer[1:-1]
78 committer = recode(committer)
79 message += "\ncommitter: %s\n" % committer
80 if n == "parent": parents.append(v)
81
82 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
83 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
84 date = tm + " " + str(tz)
85
86 c = commit(parents=parents, date=date, author=author, desc=message)
87 return c
88
89 def gettags(self):
90 tags = {}
91 fh = os.popen('git-ls-remote --tags "%s" 2>/dev/null' % self.path)
92 prefix = 'refs/tags/'
93 for line in fh:
94 line = line.strip()
95 if not line.endswith("^{}"):
96 continue
97 node, tag = line.split(None, 1)
98 if not tag.startswith(prefix):
99 continue
100 tag = tag[len(prefix):-3]
101 tags[tag] = node
102
103 return tags