Mercurial > hgsubversion
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. |