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