##// END OF EJS Templates
convert/gnuarch: correct indentation
Dirkjan Ochtman -
r7588:489c2cfb default
parent child Browse files
Show More
@@ -1,326 +1,326 b''
1 1 # GNU Arch support for the convert extension
2 2
3 3 from common import NoRepo, commandline, commit, converter_source
4 4 from mercurial.i18n import _
5 5 from mercurial import util
6 6 import os, shutil, tempfile, stat, locale
7 7 from email.Parser import Parser
8 8
9 9 class gnuarch_source(converter_source, commandline):
10 10
11 11 class gnuarch_rev:
12 12 def __init__(self, rev):
13 13 self.rev = rev
14 14 self.summary = ''
15 15 self.date = None
16 16 self.author = ''
17 17 self.continuationof = None
18 18 self.add_files = []
19 19 self.mod_files = []
20 20 self.del_files = []
21 21 self.ren_files = {}
22 22 self.ren_dirs = {}
23 23
24 24 def __init__(self, ui, path, rev=None):
25 25 super(gnuarch_source, self).__init__(ui, path, rev=rev)
26 26
27 27 if not os.path.exists(os.path.join(path, '{arch}')):
28 28 raise NoRepo(_("%s does not look like a GNU Arch repo") % path)
29 29
30 30 # Could use checktool, but we want to check for baz or tla.
31 31 self.execmd = None
32 32 if util.find_exe('baz'):
33 33 self.execmd = 'baz'
34 34 else:
35 35 if util.find_exe('tla'):
36 36 self.execmd = 'tla'
37 37 else:
38 38 raise util.Abort(_('cannot find a GNU Arch tool'))
39 39
40 40 commandline.__init__(self, ui, self.execmd)
41 41
42 42 self.path = os.path.realpath(path)
43 43 self.tmppath = None
44 44
45 45 self.treeversion = None
46 46 self.lastrev = None
47 47 self.changes = {}
48 48 self.parents = {}
49 49 self.tags = {}
50 50 self.modecache = {}
51 51 self.catlogparser = Parser()
52 52 self.locale = locale.getpreferredencoding()
53 53 self.archives = []
54 54
55 55 def before(self):
56 56 # Get registered archives
57 57 self.archives = [i.rstrip('\n')
58 58 for i in self.runlines0('archives', '-n')]
59 59
60 60 if self.execmd == 'tla':
61 61 output = self.run0('tree-version', self.path)
62 62 else:
63 63 output = self.run0('tree-version', '-d', self.path)
64 64 self.treeversion = output.strip()
65 65
66 66 # Get name of temporary directory
67 67 version = self.treeversion.split('/')
68 68 self.tmppath = os.path.join(tempfile.gettempdir(),
69 69 'hg-%s' % version[1])
70 70
71 71 # Generate parents dictionary
72 72 self.parents[None] = []
73 73 treeversion = self.treeversion
74 74 child = None
75 75 while treeversion:
76 76 self.ui.status(_('analyzing tree version %s...\n') % treeversion)
77 77
78 78 archive = treeversion.split('/')[0]
79 79 if archive not in self.archives:
80 80 self.ui.status(_('tree analysis stopped because it points to an unregistered archive %s...\n') % archive)
81 81 break
82 82
83 83 # Get the complete list of revisions for that tree version
84 84 output, status = self.runlines('revisions', '-r', '-f', treeversion)
85 85 self.checkexit(status, 'failed retrieveing revisions for %s' % treeversion)
86 86
87 87 # No new iteration unless a revision has a continuation-of header
88 88 treeversion = None
89 89
90 90 for l in output:
91 91 rev = l.strip()
92 92 self.changes[rev] = self.gnuarch_rev(rev)
93 93 self.parents[rev] = []
94 94
95 95 # Read author, date and summary
96 96 catlog, status = self.run('cat-log', '-d', self.path, rev)
97 97 if status:
98 98 catlog = self.run0('cat-archive-log', rev)
99 99 self._parsecatlog(catlog, rev)
100 100
101 101 # Populate the parents map
102 102 self.parents[child].append(rev)
103 103
104 104 # Keep track of the current revision as the child of the next
105 105 # revision scanned
106 106 child = rev
107 107
108 108 # Check if we have to follow the usual incremental history
109 109 # or if we have to 'jump' to a different treeversion given
110 110 # by the continuation-of header.
111 111 if self.changes[rev].continuationof:
112 112 treeversion = '--'.join(self.changes[rev].continuationof.split('--')[:-1])
113 113 break
114 114
115 115 # If we reached a base-0 revision w/o any continuation-of
116 116 # header, it means the tree history ends here.
117 117 if rev[-6:] == 'base-0':
118 118 break
119 119
120 120 def after(self):
121 121 self.ui.debug(_('cleaning up %s\n') % self.tmppath)
122 122 shutil.rmtree(self.tmppath, ignore_errors=True)
123 123
124 124 def getheads(self):
125 125 return self.parents[None]
126 126
127 127 def getfile(self, name, rev):
128 128 if rev != self.lastrev:
129 129 raise util.Abort(_('internal calling inconsistency'))
130 130
131 131 # Raise IOError if necessary (i.e. deleted files).
132 132 if not os.path.exists(os.path.join(self.tmppath, name)):
133 133 raise IOError
134 134
135 135 data, mode = self._getfile(name, rev)
136 136 self.modecache[(name, rev)] = mode
137 137
138 138 return data
139 139
140 140 def getmode(self, name, rev):
141 141 return self.modecache[(name, rev)]
142 142
143 143 def getchanges(self, rev):
144 144 self.modecache = {}
145 145 self._update(rev)
146 146 changes = []
147 147 copies = {}
148 148
149 149 for f in self.changes[rev].add_files:
150 150 changes.append((f, rev))
151 151
152 152 for f in self.changes[rev].mod_files:
153 153 changes.append((f, rev))
154 154
155 155 for f in self.changes[rev].del_files:
156 156 changes.append((f, rev))
157 157
158 158 for src in self.changes[rev].ren_files:
159 159 to = self.changes[rev].ren_files[src]
160 160 changes.append((src, rev))
161 161 changes.append((to, rev))
162 162 copies[src] = to
163 163
164 164 for src in self.changes[rev].ren_dirs:
165 165 to = self.changes[rev].ren_dirs[src]
166 166 chgs, cps = self._rendirchanges(src, to);
167 167 changes += [(f, rev) for f in chgs]
168 168 for c in cps:
169 169 copies[c] = cps[c]
170 170
171 171 self.lastrev = rev
172 172 return util.sort(changes), copies
173 173
174 174 def getcommit(self, rev):
175 175 changes = self.changes[rev]
176 176 return commit(author = changes.author, date = changes.date,
177 177 desc = changes.summary, parents = self.parents[rev], rev=rev)
178 178
179 179 def gettags(self):
180 180 return self.tags
181 181
182 182 def _execute(self, cmd, *args, **kwargs):
183 183 cmdline = [self.execmd, cmd]
184 184 cmdline += args
185 185 cmdline = [util.shellquote(arg) for arg in cmdline]
186 186 cmdline += ['>', util.nulldev, '2>', util.nulldev]
187 187 cmdline = util.quotecommand(' '.join(cmdline))
188 188 self.ui.debug(cmdline, '\n')
189 189 return os.system(cmdline)
190 190
191 191 def _update(self, rev):
192 192 self.ui.debug(_('applying revision %s...\n') % rev)
193 193 changeset, status = self.runlines('replay', '-d', self.tmppath,
194 194 rev)
195 195 if status:
196 196 # Something went wrong while merging (baz or tla
197 197 # issue?), get latest revision and try from there
198 198 shutil.rmtree(self.tmppath, ignore_errors=True)
199 199 self._obtainrevision(rev)
200 200 else:
201 201 old_rev = self.parents[rev][0]
202 202 self.ui.debug(_('computing changeset between %s and %s...\n')
203 203 % (old_rev, rev))
204 204 self._parsechangeset(changeset, rev)
205 205
206 206 def _getfile(self, name, rev):
207 207 mode = os.lstat(os.path.join(self.tmppath, name)).st_mode
208 208 if stat.S_ISLNK(mode):
209 209 data = os.readlink(os.path.join(self.tmppath, name))
210 210 mode = mode and 'l' or ''
211 211 else:
212 212 data = open(os.path.join(self.tmppath, name), 'rb').read()
213 213 mode = (mode & 0111) and 'x' or ''
214 214 return data, mode
215 215
216 216 def _exclude(self, name):
217 217 exclude = [ '{arch}', '.arch-ids', '.arch-inventory' ]
218 218 for exc in exclude:
219 219 if name.find(exc) != -1:
220 220 return True
221 221 return False
222 222
223 223 def _readcontents(self, path):
224 224 files = []
225 225 contents = os.listdir(path)
226 226 while len(contents) > 0:
227 227 c = contents.pop()
228 228 p = os.path.join(path, c)
229 229 # os.walk could be used, but here we avoid internal GNU
230 230 # Arch files and directories, thus saving a lot time.
231 231 if not self._exclude(p):
232 232 if os.path.isdir(p):
233 233 contents += [os.path.join(c, f) for f in os.listdir(p)]
234 234 else:
235 235 files.append(c)
236 236 return files
237 237
238 238 def _rendirchanges(self, src, dest):
239 239 changes = []
240 240 copies = {}
241 241 files = self._readcontents(os.path.join(self.tmppath, dest))
242 242 for f in files:
243 243 s = os.path.join(src, f)
244 244 d = os.path.join(dest, f)
245 245 changes.append(s)
246 246 changes.append(d)
247 247 copies[s] = d
248 248 return changes, copies
249 249
250 250 def _obtainrevision(self, rev):
251 251 self.ui.debug(_('obtaining revision %s...\n') % rev)
252 252 output = self._execute('get', rev, self.tmppath)
253 253 self.checkexit(output)
254 254 self.ui.debug(_('analysing revision %s...\n') % rev)
255 255 files = self._readcontents(self.tmppath)
256 256 self.changes[rev].add_files += files
257 257
258 258 def _stripbasepath(self, path):
259 259 if path.startswith('./'):
260 260 return path[2:]
261 261 return path
262 262
263 263 def _parsecatlog(self, data, rev):
264 264 try:
265 265 catlog = self.catlogparser.parsestr(data)
266 266 self.changes[rev].date = util.datestr(
267 267 util.strdate(catlog['Standard-date'],
268 268 '%Y-%m-%d %H:%M:%S'))
269 269 self.changes[rev].author = catlog['Creator']
270 270 self.changes[rev].summary = catlog['Summary']
271 271 if catlog.has_key('Continuation-of'):
272 272 self.changes[rev].continuationof = catlog['Continuation-of']
273 except Exception, err:
273 except Exception, err:
274 274 raise util.Abort(_('could not parse cat-log of %s') % rev)
275 275
276 276 def _parsechangeset(self, data, rev):
277 277 for l in data:
278 278 l = l.strip()
279 279 # Added file (ignore added directory)
280 280 if l.startswith('A') and not l.startswith('A/'):
281 281 file = self._stripbasepath(l[1:].strip())
282 282 if not self._exclude(file):
283 283 self.changes[rev].add_files.append(file)
284 284 # Deleted file (ignore deleted directory)
285 285 elif l.startswith('D') and not l.startswith('D/'):
286 286 file = self._stripbasepath(l[1:].strip())
287 287 if not self._exclude(file):
288 288 self.changes[rev].del_files.append(file)
289 289 # Modified binary file
290 290 elif l.startswith('Mb'):
291 291 file = self._stripbasepath(l[2:].strip())
292 292 if not self._exclude(file):
293 293 self.changes[rev].mod_files.append(file)
294 294 # Modified link
295 295 elif l.startswith('M->'):
296 296 file = self._stripbasepath(l[3:].strip())
297 297 if not self._exclude(file):
298 298 self.changes[rev].mod_files.append(file)
299 299 # Modified file
300 300 elif l.startswith('M'):
301 301 file = self._stripbasepath(l[1:].strip())
302 302 if not self._exclude(file):
303 303 self.changes[rev].mod_files.append(file)
304 304 # Renamed file (or link)
305 305 elif l.startswith('=>'):
306 306 files = l[2:].strip().split(' ')
307 307 if len(files) == 1:
308 308 files = l[2:].strip().split('\t')
309 309 src = self._stripbasepath(files[0])
310 310 dst = self._stripbasepath(files[1])
311 311 if not self._exclude(src) and not self._exclude(dst):
312 312 self.changes[rev].ren_files[src] = dst
313 313 # Conversion from file to link or from link to file (modified)
314 314 elif l.startswith('ch'):
315 315 file = self._stripbasepath(l[2:].strip())
316 316 if not self._exclude(file):
317 317 self.changes[rev].mod_files.append(file)
318 318 # Renamed directory
319 319 elif l.startswith('/>'):
320 320 dirs = l[2:].strip().split(' ')
321 321 if len(dirs) == 1:
322 322 dirs = l[2:].strip().split('\t')
323 323 src = self._stripbasepath(dirs[0])
324 324 dst = self._stripbasepath(dirs[1])
325 325 if not self._exclude(src) and not self._exclude(dst):
326 326 self.changes[rev].ren_dirs[src] = dst
General Comments 0
You need to be logged in to leave comments. Login now