##// END OF EJS Templates
convert/git: abort if git submodules are detected (issue2150)...
Augie Fackler -
r16292:101c8a1b stable
parent child Browse files
Show More
@@ -1,205 +1,207 b''
1 1 # git.py - git support for the convert extension
2 2 #
3 3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 import os
9 9 from mercurial import util
10 10 from mercurial.node import hex, nullid
11 11 from mercurial.i18n import _
12 12
13 13 from common import NoRepo, commit, converter_source, checktool
14 14
15 15 class convert_git(converter_source):
16 16 # Windows does not support GIT_DIR= construct while other systems
17 17 # cannot remove environment variable. Just assume none have
18 18 # both issues.
19 19 if util.safehasattr(os, 'unsetenv'):
20 20 def gitopen(self, s, noerr=False):
21 21 prevgitdir = os.environ.get('GIT_DIR')
22 22 os.environ['GIT_DIR'] = self.path
23 23 try:
24 24 if noerr:
25 25 (stdin, stdout, stderr) = util.popen3(s)
26 26 return stdout
27 27 else:
28 28 return util.popen(s, 'rb')
29 29 finally:
30 30 if prevgitdir is None:
31 31 del os.environ['GIT_DIR']
32 32 else:
33 33 os.environ['GIT_DIR'] = prevgitdir
34 34 else:
35 35 def gitopen(self, s, noerr=False):
36 36 if noerr:
37 37 (sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s))
38 38 return so
39 39 else:
40 40 return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
41 41
42 42 def gitread(self, s):
43 43 fh = self.gitopen(s)
44 44 data = fh.read()
45 45 return data, fh.close()
46 46
47 47 def __init__(self, ui, path, rev=None):
48 48 super(convert_git, self).__init__(ui, path, rev=rev)
49 49
50 50 if os.path.isdir(path + "/.git"):
51 51 path += "/.git"
52 52 if not os.path.exists(path + "/objects"):
53 53 raise NoRepo(_("%s does not look like a Git repository") % path)
54 54
55 55 checktool('git', 'git')
56 56
57 57 self.path = path
58 58
59 59 def getheads(self):
60 60 if not self.rev:
61 61 heads, ret = self.gitread('git rev-parse --branches --remotes')
62 62 heads = heads.splitlines()
63 63 else:
64 64 heads, ret = self.gitread("git rev-parse --verify %s" % self.rev)
65 65 heads = [heads[:-1]]
66 66 if ret:
67 67 raise util.Abort(_('cannot retrieve git heads'))
68 68 return heads
69 69
70 70 def catfile(self, rev, type):
71 71 if rev == hex(nullid):
72 72 raise IOError()
73 73 data, ret = self.gitread("git cat-file %s %s" % (type, rev))
74 74 if ret:
75 75 raise util.Abort(_('cannot read %r object at %s') % (type, rev))
76 76 return data
77 77
78 78 def getfile(self, name, rev):
79 79 data = self.catfile(rev, "blob")
80 80 mode = self.modecache[(name, rev)]
81 81 return data, mode
82 82
83 83 def getchanges(self, version):
84 84 self.modecache = {}
85 85 fh = self.gitopen("git diff-tree -z --root -m -r %s" % version)
86 86 changes = []
87 87 seen = set()
88 88 entry = None
89 89 for l in fh.read().split('\x00'):
90 90 if not entry:
91 91 if not l.startswith(':'):
92 92 continue
93 93 entry = l
94 94 continue
95 95 f = l
96 96 if f not in seen:
97 97 seen.add(f)
98 98 entry = entry.split()
99 99 h = entry[3]
100 if entry[1] == '160000':
101 raise util.Abort('git submodules are not supported!')
100 102 p = (entry[1] == "100755")
101 103 s = (entry[1] == "120000")
102 104 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
103 105 changes.append((f, h))
104 106 entry = None
105 107 if fh.close():
106 108 raise util.Abort(_('cannot read changes in %s') % version)
107 109 return (changes, {})
108 110
109 111 def getcommit(self, version):
110 112 c = self.catfile(version, "commit") # read the commit hash
111 113 end = c.find("\n\n")
112 114 message = c[end + 2:]
113 115 message = self.recode(message)
114 116 l = c[:end].splitlines()
115 117 parents = []
116 118 author = committer = None
117 119 for e in l[1:]:
118 120 n, v = e.split(" ", 1)
119 121 if n == "author":
120 122 p = v.split()
121 123 tm, tz = p[-2:]
122 124 author = " ".join(p[:-2])
123 125 if author[0] == "<": author = author[1:-1]
124 126 author = self.recode(author)
125 127 if n == "committer":
126 128 p = v.split()
127 129 tm, tz = p[-2:]
128 130 committer = " ".join(p[:-2])
129 131 if committer[0] == "<": committer = committer[1:-1]
130 132 committer = self.recode(committer)
131 133 if n == "parent":
132 134 parents.append(v)
133 135
134 136 if committer and committer != author:
135 137 message += "\ncommitter: %s\n" % committer
136 138 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
137 139 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
138 140 date = tm + " " + str(tz)
139 141
140 142 c = commit(parents=parents, date=date, author=author, desc=message,
141 143 rev=version)
142 144 return c
143 145
144 146 def gettags(self):
145 147 tags = {}
146 148 fh = self.gitopen('git ls-remote --tags "%s"' % self.path)
147 149 prefix = 'refs/tags/'
148 150 for line in fh:
149 151 line = line.strip()
150 152 if not line.endswith("^{}"):
151 153 continue
152 154 node, tag = line.split(None, 1)
153 155 if not tag.startswith(prefix):
154 156 continue
155 157 tag = tag[len(prefix):-3]
156 158 tags[tag] = node
157 159 if fh.close():
158 160 raise util.Abort(_('cannot read tags from %s') % self.path)
159 161
160 162 return tags
161 163
162 164 def getchangedfiles(self, version, i):
163 165 changes = []
164 166 if i is None:
165 167 fh = self.gitopen("git diff-tree --root -m -r %s" % version)
166 168 for l in fh:
167 169 if "\t" not in l:
168 170 continue
169 171 m, f = l[:-1].split("\t")
170 172 changes.append(f)
171 173 else:
172 174 fh = self.gitopen('git diff-tree --name-only --root -r %s "%s^%s" --'
173 175 % (version, version, i + 1))
174 176 changes = [f.rstrip('\n') for f in fh]
175 177 if fh.close():
176 178 raise util.Abort(_('cannot read changes in %s') % version)
177 179
178 180 return changes
179 181
180 182 def getbookmarks(self):
181 183 bookmarks = {}
182 184
183 185 # Interesting references in git are prefixed
184 186 prefix = 'refs/heads/'
185 187 prefixlen = len(prefix)
186 188
187 189 # factor two commands
188 190 gitcmd = { 'remote/': 'git ls-remote --heads origin',
189 191 '': 'git show-ref'}
190 192
191 193 # Origin heads
192 194 for reftype in gitcmd:
193 195 try:
194 196 fh = self.gitopen(gitcmd[reftype], noerr=True)
195 197 for line in fh:
196 198 line = line.strip()
197 199 rev, name = line.split(None, 1)
198 200 if not name.startswith(prefix):
199 201 continue
200 202 name = '%s%s' % (reftype, name[prefixlen:])
201 203 bookmarks[name] = rev
202 204 except:
203 205 pass
204 206
205 207 return bookmarks
General Comments 0
You need to be logged in to leave comments. Login now