comparison hgext/convert/subversion.py @ 4786:62e1b6412b62

convert: svn: add an early return to move most changeset parsing out an indent level
author Brendan Cully <brendan@kublai.com>
date Tue, 03 Jul 2007 11:36:06 -0700
parents a67f185d0474
children c5dd8e184279
comparison
equal deleted inserted replaced
4785:a67f185d0474 4786:62e1b6412b62
216 216
217 copyfrom = {} # Map of entrypath, revision for finding source of deleted revisions. 217 copyfrom = {} # Map of entrypath, revision for finding source of deleted revisions.
218 copies = {} 218 copies = {}
219 entries = [] 219 entries = []
220 self.ui.debug("Parsing revision %d\n" % revnum) 220 self.ui.debug("Parsing revision %d\n" % revnum)
221 if orig_paths is not None: 221 if orig_paths is None:
222 rev = self.rev(revnum) 222 return
223 try: 223
224 branch = self.module.split("/")[-1] 224 rev = self.rev(revnum)
225 if branch == 'trunk': 225 try:
226 branch = '' 226 branch = self.module.split("/")[-1]
227 except IndexError: 227 if branch == 'trunk':
228 branch = None 228 branch = ''
229 except IndexError:
230 branch = None
229 231
230 for path in orig_paths: 232 for path in orig_paths:
231 # self.ui.write("path %s\n" % path) 233 # self.ui.write("path %s\n" % path)
232 if path == self.module: # Follow branching back in history 234 if path == self.module: # Follow branching back in history
233 ent = orig_paths[path]
234 if ent:
235 if ent.copyfrom_path:
236 self.modulemap[ent.copyfrom_rev] = ent.copyfrom_path
237 else:
238 self.ui.debug("No copyfrom path, don't know what to do.\n")
239 # Maybe it was added and there is no more history.
240 entrypath = get_entry_from_path(path, module=self.module)
241 # self.ui.write("entrypath %s\n" % entrypath)
242 if entrypath is None:
243 # Outside our area of interest
244 self.ui.debug("boring@%s: %s\n" % (revnum, path))
245 continue
246 entry = entrypath.decode(self.encoding)
247 ent = orig_paths[path] 235 ent = orig_paths[path]
248 if not entrypath: 236 if ent:
249 # TODO: branch creation event
250 pass
251
252 kind = svn.ra.check_path(self.ra, entrypath, revnum)
253 if kind == svn.core.svn_node_file:
254 if ent.copyfrom_path: 237 if ent.copyfrom_path:
255 copyfrom_path = get_entry_from_path(ent.copyfrom_path) 238 self.modulemap[ent.copyfrom_rev] = ent.copyfrom_path
256 if copyfrom_path: 239 else:
257 self.ui.debug("Copied to %s from %s@%s\n" % (entry, copyfrom_path, ent.copyfrom_rev)) 240 self.ui.debug("No copyfrom path, don't know what to do.\n")
258 # It's probably important for hg that the source 241 # Maybe it was added and there is no more history.
259 # exists in the revision's parent, not just the 242 entrypath = get_entry_from_path(path, module=self.module)
260 # ent.copyfrom_rev 243 # self.ui.write("entrypath %s\n" % entrypath)
261 fromkind = svn.ra.check_path(self.ra, copyfrom_path, ent.copyfrom_rev) 244 if entrypath is None:
262 if fromkind != 0: 245 # Outside our area of interest
263 copies[self.recode(entry)] = self.recode(copyfrom_path) 246 self.ui.debug("boring@%s: %s\n" % (revnum, path))
247 continue
248 entry = entrypath.decode(self.encoding)
249 ent = orig_paths[path]
250 if not entrypath:
251 # TODO: branch creation event
252 pass
253
254 kind = svn.ra.check_path(self.ra, entrypath, revnum)
255 if kind == svn.core.svn_node_file:
256 if ent.copyfrom_path:
257 copyfrom_path = get_entry_from_path(ent.copyfrom_path)
258 if copyfrom_path:
259 self.ui.debug("Copied to %s from %s@%s\n" % (entry, copyfrom_path, ent.copyfrom_rev))
260 # It's probably important for hg that the source
261 # exists in the revision's parent, not just the
262 # ent.copyfrom_rev
263 fromkind = svn.ra.check_path(self.ra, copyfrom_path, ent.copyfrom_rev)
264 if fromkind != 0:
265 copies[self.recode(entry)] = self.recode(copyfrom_path)
266 entries.append(self.recode(entry))
267 elif kind == 0: # gone, but had better be a deleted *file*
268 self.ui.debug("gone from %s\n" % ent.copyfrom_rev)
269
270 fromrev = revnum - 1
271 # might always need to be revnum - 1 in these 3 lines?
272 old_module = self.modulemap.get(fromrev, self.module)
273 basepath = old_module + "/" + get_entry_from_path(path, module=self.module)
274 entrypath = old_module + "/" + get_entry_from_path(path, module=self.module)
275
276 def lookup_parts(p):
277 rc = None
278 parts = p.split("/")
279 for i in range(len(parts)):
280 part = "/".join(parts[:i])
281 info = part, copyfrom.get(part, None)
282 if info[1] is not None:
283 self.ui.debug("Found parent directory %s\n" % info)
284 rc = info
285 return rc
286
287 self.ui.debug("base, entry %s %s\n" % (basepath, entrypath))
288
289 frompath, froment = lookup_parts(entrypath) or (None, revnum - 1)
290
291 # need to remove fragment from lookup_parts and replace with copyfrom_path
292 if frompath is not None:
293 self.ui.debug("munge-o-matic\n")
294 self.ui.debug(entrypath + '\n')
295 self.ui.debug(entrypath[len(frompath):] + '\n')
296 entrypath = froment.copyfrom_path + entrypath[len(frompath):]
297 fromrev = froment.copyfrom_rev
298 self.ui.debug("Info: %s %s %s %s\n" % (frompath, froment, ent, entrypath))
299
300 fromkind = svn.ra.check_path(self.ra, entrypath, fromrev)
301 if fromkind == svn.core.svn_node_file: # a deleted file
264 entries.append(self.recode(entry)) 302 entries.append(self.recode(entry))
265 elif kind == 0: # gone, but had better be a deleted *file* 303 else:
266 self.ui.debug("gone from %s\n" % ent.copyfrom_rev) 304 # print "Deleted/moved non-file:", revnum, path, ent
267 305 # children = self._find_children(path, revnum - 1)
268 fromrev = revnum - 1 306 # print "find children %s@%d from %d action %s" % (path, revnum, ent.copyfrom_rev, ent.action)
269 # might always need to be revnum - 1 in these 3 lines? 307 # Sometimes this is tricky. For example: in
270 old_module = self.modulemap.get(fromrev, self.module) 308 # The Subversion Repository revision 6940 a dir
271 basepath = old_module + "/" + get_entry_from_path(path, module=self.module) 309 # was copied and one of its files was deleted
272 entrypath = old_module + "/" + get_entry_from_path(path, module=self.module) 310 # from the new location in the same commit. This
273 311 # code can't deal with that yet.
274 def lookup_parts(p): 312 if ent.action == 'C':
275 rc = None 313 children = self._find_children(path, fromrev)
276 parts = p.split("/")
277 for i in range(len(parts)):
278 part = "/".join(parts[:i])
279 info = part, copyfrom.get(part, None)
280 if info[1] is not None:
281 self.ui.debug("Found parent directory %s\n" % info)
282 rc = info
283 return rc
284
285 self.ui.debug("base, entry %s %s\n" % (basepath, entrypath))
286
287 frompath, froment = lookup_parts(entrypath) or (None, revnum - 1)
288
289 # need to remove fragment from lookup_parts and replace with copyfrom_path
290 if frompath is not None:
291 self.ui.debug("munge-o-matic\n")
292 self.ui.debug(entrypath + '\n')
293 self.ui.debug(entrypath[len(frompath):] + '\n')
294 entrypath = froment.copyfrom_path + entrypath[len(frompath):]
295 fromrev = froment.copyfrom_rev
296 self.ui.debug("Info: %s %s %s %s\n" % (frompath, froment, ent, entrypath))
297
298 fromkind = svn.ra.check_path(self.ra, entrypath, fromrev)
299 if fromkind == svn.core.svn_node_file: # a deleted file
300 entries.append(self.recode(entry))
301 else: 314 else:
302 # print "Deleted/moved non-file:", revnum, path, ent 315 oroot = entrypath.strip('/')
303 # children = self._find_children(path, revnum - 1) 316 nroot = path.strip('/')
304 # print "find children %s@%d from %d action %s" % (path, revnum, ent.copyfrom_rev, ent.action) 317 children = self._find_children(oroot, fromrev)
305 # Sometimes this is tricky. For example: in 318 children = [s.replace(oroot,nroot) for s in children]
306 # The Subversion Repository revision 6940 a dir 319 # Mark all [files, not directories] as deleted.
307 # was copied and one of its files was deleted
308 # from the new location in the same commit. This
309 # code can't deal with that yet.
310 if ent.action == 'C':
311 children = self._find_children(path, fromrev)
312 else:
313 oroot = entrypath.strip('/')
314 nroot = path.strip('/')
315 children = self._find_children(oroot, fromrev)
316 children = [s.replace(oroot,nroot) for s in children]
317 # Mark all [files, not directories] as deleted.
318 for child in children:
319 # Can we move a child directory and its
320 # parent in the same commit? (probably can). Could
321 # cause problems if instead of revnum -1,
322 # we have to look in (copyfrom_path, revnum - 1)
323 entrypath = get_entry_from_path("/" + child, module=old_module)
324 if entrypath:
325 entry = self.recode(entrypath.decode(self.encoding))
326 if entry in copies:
327 # deleted file within a copy
328 del copies[entry]
329 else:
330 entries.append(entry)
331 elif kind == svn.core.svn_node_dir:
332 # Should probably synthesize normal file entries
333 # and handle as above to clean up copy/rename handling.
334
335 # If the directory just had a prop change,
336 # then we shouldn't need to look for its children.
337 # Also this could create duplicate entries. Not sure
338 # whether this will matter. Maybe should make entries a set.
339 # print "Changed directory", revnum, path, ent.action, ent.copyfrom_path, ent.copyfrom_rev
340 # This will fail if a directory was copied
341 # from another branch and then some of its files
342 # were deleted in the same transaction.
343 children = self._find_children(path, revnum)
344 children.sort()
345 for child in children: 320 for child in children:
346 # Can we move a child directory and its 321 # Can we move a child directory and its
347 # parent in the same commit? (probably can). Could 322 # parent in the same commit? (probably can). Could
348 # cause problems if instead of revnum -1, 323 # cause problems if instead of revnum -1,
349 # we have to look in (copyfrom_path, revnum - 1) 324 # we have to look in (copyfrom_path, revnum - 1)
350 entrypath = get_entry_from_path("/" + child, module=self.module) 325 entrypath = get_entry_from_path("/" + child, module=old_module)
351 # print child, self.module, entrypath
352 if entrypath: 326 if entrypath:
353 # Need to filter out directories here... 327 entry = self.recode(entrypath.decode(self.encoding))
354 kind = svn.ra.check_path(self.ra, entrypath, revnum) 328 if entry in copies:
355 if kind != svn.core.svn_node_dir: 329 # deleted file within a copy
356 entries.append(self.recode(entrypath)) 330 del copies[entry]
357 331 else:
358 # Copies here (must copy all from source) 332 entries.append(entry)
359 # Probably not a real problem for us if 333 elif kind == svn.core.svn_node_dir:
360 # source does not exist 334 # Should probably synthesize normal file entries
361 335 # and handle as above to clean up copy/rename handling.
362 # Can do this with the copy command "hg copy" 336
363 # if ent.copyfrom_path: 337 # If the directory just had a prop change,
364 # copyfrom_entry = get_entry_from_path(ent.copyfrom_path.decode(self.encoding), 338 # then we shouldn't need to look for its children.
365 # module=self.module) 339 # Also this could create duplicate entries. Not sure
366 # copyto_entry = entrypath 340 # whether this will matter. Maybe should make entries a set.
367 # 341 # print "Changed directory", revnum, path, ent.action, ent.copyfrom_path, ent.copyfrom_rev
368 # print "copy directory", copyfrom_entry, 'to', copyto_entry 342 # This will fail if a directory was copied
369 # 343 # from another branch and then some of its files
370 # copies.append((copyfrom_entry, copyto_entry)) 344 # were deleted in the same transaction.
371 345 children = self._find_children(path, revnum)
372 if ent.copyfrom_path: 346 children.sort()
373 copyfrom_path = ent.copyfrom_path.decode(self.encoding) 347 for child in children:
374 copyfrom_entry = get_entry_from_path(copyfrom_path, module=self.module) 348 # Can we move a child directory and its
375 if copyfrom_entry: 349 # parent in the same commit? (probably can). Could
376 copyfrom[path] = ent 350 # cause problems if instead of revnum -1,
377 self.ui.debug("mark %s came from %s\n" % (path, copyfrom[path])) 351 # we have to look in (copyfrom_path, revnum - 1)
378 352 entrypath = get_entry_from_path("/" + child, module=self.module)
379 # Good, /probably/ a regular copy. Really should check 353 # print child, self.module, entrypath
380 # to see whether the parent revision actually contains 354 if entrypath:
381 # the directory in question. 355 # Need to filter out directories here...
382 children = self._find_children(self.recode(copyfrom_path), ent.copyfrom_rev) 356 kind = svn.ra.check_path(self.ra, entrypath, revnum)
383 children.sort() 357 if kind != svn.core.svn_node_dir:
384 for child in children: 358 entries.append(self.recode(entrypath))
385 entrypath = get_entry_from_path("/" + child, module=self.module) 359
386 if entrypath: 360 # Copies here (must copy all from source)
387 entry = entrypath.decode(self.encoding) 361 # Probably not a real problem for us if
388 # print "COPY COPY From", copyfrom_entry, entry 362 # source does not exist
389 copyto_path = path + entry[len(copyfrom_entry):] 363
390 copyto_entry = get_entry_from_path(copyto_path, module=self.module) 364 # Can do this with the copy command "hg copy"
391 # print "COPY", entry, "COPY To", copyto_entry 365 # if ent.copyfrom_path:
392 copies[self.recode(copyto_entry)] = self.recode(entry) 366 # copyfrom_entry = get_entry_from_path(ent.copyfrom_path.decode(self.encoding),
393 # copy from quux splort/quuxfile 367 # module=self.module)
394 368 # copyto_entry = entrypath
395 self.modulemap[revnum] = self.module # track backwards in time 369 #
396 # a list of (filename, id) where id lets us retrieve the file. 370 # print "copy directory", copyfrom_entry, 'to', copyto_entry
397 # eg in git, id is the object hash. for svn it'll be the 371 #
398 self.files[rev] = zip(entries, [rev] * len(entries)) 372 # copies.append((copyfrom_entry, copyto_entry))
399 if not entries: 373
400 return 374 if ent.copyfrom_path:
401 375 copyfrom_path = ent.copyfrom_path.decode(self.encoding)
402 # Example SVN datetime. Includes microseconds. 376 copyfrom_entry = get_entry_from_path(copyfrom_path, module=self.module)
403 # ISO-8601 conformant 377 if copyfrom_entry:
404 # '2007-01-04T17:35:00.902377Z' 378 copyfrom[path] = ent
405 date = util.parsedate(date[:18] + " UTC", ["%Y-%m-%dT%H:%M:%S"]) 379 self.ui.debug("mark %s came from %s\n" % (path, copyfrom[path]))
406 380
407 log = message and self.recode(message) 381 # Good, /probably/ a regular copy. Really should check
408 author = author and self.recode(author) or '' 382 # to see whether the parent revision actually contains
409 383 # the directory in question.
410 cset = commit(author=author, 384 children = self._find_children(self.recode(copyfrom_path), ent.copyfrom_rev)
411 date=util.datestr(date), 385 children.sort()
412 desc=log, 386 for child in children:
413 parents=[], 387 entrypath = get_entry_from_path("/" + child, module=self.module)
414 copies=copies, 388 if entrypath:
415 branch=branch) 389 entry = entrypath.decode(self.encoding)
416 390 # print "COPY COPY From", copyfrom_entry, entry
417 if self.child_cset and self.child_rev != rev: 391 copyto_path = path + entry[len(copyfrom_entry):]
418 self.child_cset.parents = [rev] 392 copyto_entry = get_entry_from_path(copyto_path, module=self.module)
419 self.commits[self.child_rev] = self.child_cset 393 # print "COPY", entry, "COPY To", copyto_entry
420 self.child_cset = cset 394 copies[self.recode(copyto_entry)] = self.recode(entry)
421 self.child_rev = rev 395 # copy from quux splort/quuxfile
396
397 self.modulemap[revnum] = self.module # track backwards in time
398 # a list of (filename, id) where id lets us retrieve the file.
399 # eg in git, id is the object hash. for svn it'll be the
400 self.files[rev] = zip(entries, [rev] * len(entries))
401 if not entries:
402 return
403
404 # Example SVN datetime. Includes microseconds.
405 # ISO-8601 conformant
406 # '2007-01-04T17:35:00.902377Z'
407 date = util.parsedate(date[:18] + " UTC", ["%Y-%m-%dT%H:%M:%S"])
408
409 log = message and self.recode(message)
410 author = author and self.recode(author) or ''
411
412 cset = commit(author=author,
413 date=util.datestr(date),
414 desc=log,
415 parents=[],
416 copies=copies,
417 branch=branch)
418
419 if self.child_cset and self.child_rev != rev:
420 self.child_cset.parents = [rev]
421 self.commits[self.child_rev] = self.child_cset
422 self.child_cset = cset
423 self.child_rev = rev
422 424
423 try: 425 try:
424 discover_changed_paths = True 426 discover_changed_paths = True
425 strict_node_history = False 427 strict_node_history = False
426 svn.ra.get_log(self.ra, [self.module], from_revnum, to_revnum, 428 svn.ra.get_log(self.ra, [self.module], from_revnum, to_revnum,