##// END OF EJS Templates
convert: fix non-ASCII filenames retrieval from git sources (issue 1360)
Patrick Mezard -
r7242:d1dff8c4 default
parent child Browse files
Show More
@@ -1,142 +1,146 b''
1 1 # git support for the convert extension
2 2
3 3 import os
4 4 from mercurial import util
5 5
6 6 from common import NoRepo, commit, converter_source, checktool
7 7
8 8 class convert_git(converter_source):
9 9 # Windows does not support GIT_DIR= construct while other systems
10 10 # cannot remove environment variable. Just assume none have
11 11 # both issues.
12 12 if hasattr(os, 'unsetenv'):
13 13 def gitcmd(self, s):
14 14 prevgitdir = os.environ.get('GIT_DIR')
15 15 os.environ['GIT_DIR'] = self.path
16 16 try:
17 17 return util.popen(s, 'rb')
18 18 finally:
19 19 if prevgitdir is None:
20 20 del os.environ['GIT_DIR']
21 21 else:
22 22 os.environ['GIT_DIR'] = prevgitdir
23 23 else:
24 24 def gitcmd(self, s):
25 25 return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
26 26
27 27 def __init__(self, ui, path, rev=None):
28 28 super(convert_git, self).__init__(ui, path, rev=rev)
29 29
30 30 if os.path.isdir(path + "/.git"):
31 31 path += "/.git"
32 32 if not os.path.exists(path + "/objects"):
33 33 raise NoRepo("%s does not look like a Git repo" % path)
34 34
35 35 checktool('git', 'git')
36 36
37 37 self.path = path
38 38
39 39 def getheads(self):
40 40 if not self.rev:
41 41 return self.gitcmd('git rev-parse --branches').read().splitlines()
42 42 else:
43 43 fh = self.gitcmd("git rev-parse --verify %s" % self.rev)
44 44 return [fh.read()[:-1]]
45 45
46 46 def catfile(self, rev, type):
47 47 if rev == "0" * 40: raise IOError()
48 48 fh = self.gitcmd("git cat-file %s %s" % (type, rev))
49 49 return fh.read()
50 50
51 51 def getfile(self, name, rev):
52 52 return self.catfile(rev, "blob")
53 53
54 54 def getmode(self, name, rev):
55 55 return self.modecache[(name, rev)]
56 56
57 57 def getchanges(self, version):
58 58 self.modecache = {}
59 fh = self.gitcmd("git diff-tree --root -m -r %s" % version)
59 fh = self.gitcmd("git diff-tree -z --root -m -r %s" % version)
60 60 changes = []
61 61 seen = {}
62 for l in fh:
63 if "\t" not in l:
64 continue
65 m, f = l[:-1].split("\t")
66 if f in seen:
62 entry = None
63 for l in fh.read().split('\x00'):
64 if not entry:
65 if not l.startswith(':'):
66 continue
67 entry = l
67 68 continue
68 seen[f] = 1
69 m = m.split()
70 h = m[3]
71 p = (m[1] == "100755")
72 s = (m[1] == "120000")
73 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
74 changes.append((f, h))
69 f = l
70 if f not in seen:
71 seen[f] = 1
72 entry = entry.split()
73 h = entry[3]
74 p = (entry[1] == "100755")
75 s = (entry[1] == "120000")
76 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
77 changes.append((f, h))
78 entry = None
75 79 return (changes, {})
76 80
77 81 def getcommit(self, version):
78 82 c = self.catfile(version, "commit") # read the commit hash
79 83 end = c.find("\n\n")
80 84 message = c[end+2:]
81 85 message = self.recode(message)
82 86 l = c[:end].splitlines()
83 87 manifest = l[0].split()[1]
84 88 parents = []
85 89 for e in l[1:]:
86 90 n, v = e.split(" ", 1)
87 91 if n == "author":
88 92 p = v.split()
89 93 tm, tz = p[-2:]
90 94 author = " ".join(p[:-2])
91 95 if author[0] == "<": author = author[1:-1]
92 96 author = self.recode(author)
93 97 if n == "committer":
94 98 p = v.split()
95 99 tm, tz = p[-2:]
96 100 committer = " ".join(p[:-2])
97 101 if committer[0] == "<": committer = committer[1:-1]
98 102 committer = self.recode(committer)
99 103 message += "\ncommitter: %s\n" % committer
100 104 if n == "parent": parents.append(v)
101 105
102 106 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
103 107 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
104 108 date = tm + " " + str(tz)
105 109
106 110 c = commit(parents=parents, date=date, author=author, desc=message,
107 111 rev=version)
108 112 return c
109 113
110 114 def gettags(self):
111 115 tags = {}
112 116 fh = self.gitcmd('git ls-remote --tags "%s"' % self.path)
113 117 prefix = 'refs/tags/'
114 118 for line in fh:
115 119 line = line.strip()
116 120 if not line.endswith("^{}"):
117 121 continue
118 122 node, tag = line.split(None, 1)
119 123 if not tag.startswith(prefix):
120 124 continue
121 125 tag = tag[len(prefix):-3]
122 126 tags[tag] = node
123 127
124 128 return tags
125 129
126 130 def getchangedfiles(self, version, i):
127 131 changes = []
128 132 if i is None:
129 133 fh = self.gitcmd("git diff-tree --root -m -r %s" % version)
130 134 for l in fh:
131 135 if "\t" not in l:
132 136 continue
133 137 m, f = l[:-1].split("\t")
134 138 changes.append(f)
135 139 fh.close()
136 140 else:
137 141 fh = self.gitcmd('git diff-tree --name-only --root -r %s "%s^%s" --'
138 142 % (version, version, i+1))
139 143 changes = [f.rstrip('\n') for f in fh]
140 144 fh.close()
141 145
142 146 return changes
General Comments 0
You need to be logged in to leave comments. Login now