comparison fetch_command.py @ 174:f80132c5fea5

Convert svn:externals properties into a .hgsvnexternals file
author Patrick Mezard <pmezard@gmail.com>
date Fri, 02 Jan 2009 15:54:05 -0600
parents f1919e1c35bf
children c4115b3918e9
comparison
equal deleted inserted replaced
173:f244eaee5069 174:f80132c5fea5
10 from svn import core 10 from svn import core
11 from svn import delta 11 from svn import delta
12 12
13 import hg_delta_editor 13 import hg_delta_editor
14 import svnwrap 14 import svnwrap
15 import svnexternals
15 import util 16 import util
16 17
17 18
18 def print_your_svn_is_old_message(ui): #pragma: no cover 19 def print_your_svn_is_old_message(ui): #pragma: no cover
19 ui.status("In light of that, I'll fall back and do diffs, but it won't do " 20 ui.status("In light of that, I'll fall back and do diffs, but it won't do "
423 if not hg_editor.aresamefiles(sourcectx, parentctx, sources): 424 if not hg_editor.aresamefiles(sourcectx, parentctx, sources):
424 continue 425 continue
425 hgcopies.update(copies) 426 hgcopies.update(copies)
426 return hgcopies 427 return hgcopies
427 428
429 def stupid_fetch_externals(svn, branchpath, r, parentctx):
430 """Extract svn:externals for the current revision and branch
431
432 Return an externalsfile instance or None if there are no externals
433 to convert and never were.
434 """
435 externals = svnexternals.externalsfile()
436 if '.hgsvnexternals' in parentctx:
437 externals.read(parentctx['.hgsvnexternals'].data())
438 # Detect property additions only, changes are handled by checking
439 # existing entries individually. Projects are unlikely to store
440 # externals on many different root directories, so we trade code
441 # duplication and complexity for a constant lookup price at every
442 # revision in the common case.
443 dirs = set(externals)
444 if parentctx.node() == revlog.nullid:
445 dirs.update([p for p,k in svn.list_files(branchpath, r.revnum) if k == 'd'])
446 dirs.add('')
447 else:
448 branchprefix = branchpath + '/'
449 for path, e in r.paths.iteritems():
450 if e.action == 'D':
451 continue
452 if not path.startswith(branchprefix) and path != branchpath:
453 continue
454 kind = svn.checkpath(path, r.revnum)
455 if kind != 'd':
456 continue
457 path = path[len(branchprefix):]
458 dirs.add(path)
459 if e.action == 'M':
460 continue
461 for child, k in svn.list_files(branchprefix + path, r.revnum):
462 if k == 'd':
463 dirs.add((path + '/' + child).strip('/'))
464
465 # Retrieve new or updated values
466 for dir in dirs:
467 try:
468 values = svn.list_props(branchpath + '/' + dir, r.revnum)
469 externals[dir] = values.get('svn:externals', '')
470 except IOError:
471 externals[dir] = ''
472
473 if not externals and '.hgsvnexternals' not in parentctx:
474 # Do not create empty externals files
475 return None
476 return externals
477
428 def stupid_fetch_branchrev(svn, hg_editor, branch, branchpath, r, parentctx): 478 def stupid_fetch_branchrev(svn, hg_editor, branch, branchpath, r, parentctx):
429 """Extract all 'branch' content at a given revision. 479 """Extract all 'branch' content at a given revision.
430 480
431 Return a tuple (files, filectxfn) where 'files' is the list of all files 481 Return a tuple (files, filectxfn) where 'files' is the list of all files
432 in the branch at the given revision, and 'filectxfn' is a memctx compatible 482 in the branch at the given revision, and 'filectxfn' is a memctx compatible
447 path = path[len(branchprefix):] 497 path = path[len(branchprefix):]
448 if kind == 'f': 498 if kind == 'f':
449 files.append(path) 499 files.append(path)
450 elif kind == 'd': 500 elif kind == 'd':
451 if e.action == 'M': 501 if e.action == 'M':
452 # Ignore property changes for now
453 continue 502 continue
454 dirpath = branchprefix + path 503 dirpath = branchprefix + path
455 for child, k in svn.list_files(dirpath, r.revnum): 504 for child, k in svn.list_files(dirpath, r.revnum):
456 if k == 'f': 505 if k == 'f':
457 files.append(path + '/' + child) 506 files.append(path + '/' + child)
493 # remove everything. 542 # remove everything.
494 deleted_branches[b] = parentctx.node() 543 deleted_branches[b] = parentctx.node()
495 continue 544 continue
496 else: 545 else:
497 try: 546 try:
498 files_touched, filectxfn = stupid_diff_branchrev( 547 files_touched, filectxfn2 = stupid_diff_branchrev(
499 ui, svn, hg_editor, b, r, parentctx) 548 ui, svn, hg_editor, b, r, parentctx)
500 except BadPatchApply, e: 549 except BadPatchApply, e:
501 # Either this revision or the previous one does not exist. 550 # Either this revision or the previous one does not exist.
502 ui.status("fetching entire rev: %s.\n" % e.message) 551 ui.status("fetching entire rev: %s.\n" % e.message)
503 files_touched, filectxfn = stupid_fetch_branchrev( 552 files_touched, filectxfn2 = stupid_fetch_branchrev(
504 svn, hg_editor, b, branches[b], r, parentctx) 553 svn, hg_editor, b, branches[b], r, parentctx)
505 554
555 externals = stupid_fetch_externals(svn, branches[b], r, parentctx)
556 if externals is not None:
557 files_touched.append('.hgsvnexternals')
558
559 def filectxfn(repo, memctx, path):
560 if path == '.hgsvnexternals':
561 return context.memfilectx(path=path, data=externals.write(),
562 islink=False, isexec=False, copied=None)
563 return filectxfn2(repo, memctx, path)
564
506 extra = util.build_extra(r.revnum, b, svn.uuid, svn.subdir) 565 extra = util.build_extra(r.revnum, b, svn.uuid, svn.subdir)
507 if '' in files_touched: 566 if '' in files_touched:
508 files_touched.remove('') 567 files_touched.remove('')
509 if parentctx.node() != node.nullid or files_touched: 568 if parentctx.node() != node.nullid or files_touched:
510 # TODO(augie) remove this debug code? Or maybe it's sane to have it. 569 # TODO(augie) remove this debug code? Or maybe it's sane to have it.