Mercurial > hgsubversion
comparison hg_delta_editor.py @ 331:75f082b5897e
Switch to using url scheme wrappers instead of duplicating each command we wrap.
The 'hg svn url' command has been killed; the replacement is
'.hg/hgrc'. More stuff related to its disappearance has been stripped,
including two tests.
HgChangeReceiver now takes a UUID argument, which it uses to ensure
that remote repositories remain unchanged. This is a temporary
solution, and I'm not entirely satisfied with how it's done either.
Access to the UUID file has been isolated in a HgChangeReceiver
property.
Some more tests have been updated to use ui.pushbuffer()/popbuffer(),
and to pass through the Mercurial API.
Moved the arguments to wrappers.pull() to the UI configuration.
Also, remove HgChangeReceiver.opts in favour of a 'usebranchnames'
instance & configuration variable. The name is taken from the
ConvertExtension.
| author | Dan Villiom Podlaski Christiansen <danchr@gmail.com> |
|---|---|
| date | Fri, 15 May 2009 19:18:43 +0200 |
| parents | 5f8f2fd4fd54 |
| children | 9ef720a611e0 |
comparison
equal
deleted
inserted
replaced
| 330:5f8f2fd4fd54 | 331:75f082b5897e |
|---|---|
| 9 from mercurial import hg | 9 from mercurial import hg |
| 10 from mercurial import ui | 10 from mercurial import ui |
| 11 from mercurial import util as hgutil | 11 from mercurial import util as hgutil |
| 12 from mercurial import revlog | 12 from mercurial import revlog |
| 13 from mercurial import node | 13 from mercurial import node |
| 14 from mercurial import error | |
| 14 from svn import delta | 15 from svn import delta |
| 15 from svn import core | 16 from svn import core |
| 16 | 17 |
| 17 import svnexternals | 18 import svnexternals |
| 18 import util | 19 import util |
| 72 except ValueError: | 73 except ValueError: |
| 73 return 0 | 74 return 0 |
| 74 | 75 |
| 75 def __init__(self, path=None, repo=None, ui_=None, | 76 def __init__(self, path=None, repo=None, ui_=None, |
| 76 subdir='', author_host='', | 77 subdir='', author_host='', |
| 77 tag_locations=['tags'], | 78 tag_locations=[], |
| 78 authors=None, | 79 authors=None, filemap=None, uuid=None): |
| 79 filemap=None): | |
| 80 """path is the path to the target hg repo. | 80 """path is the path to the target hg repo. |
| 81 | 81 |
| 82 subdir is the subdirectory of the edits *on the svn server*. | 82 subdir is the subdirectory of the edits *on the svn server*. |
| 83 It is needed for stripping paths off in certain cases. | 83 It is needed for stripping paths off in certain cases. |
| 84 """ | 84 """ |
| 85 if repo and repo.ui and not ui_: | 85 if repo and repo.ui and not ui_: |
| 86 ui_ = repo.ui | 86 ui_ = repo.ui |
| 87 if not ui_: | 87 if not ui_: |
| 88 ui_ = ui.ui() | 88 ui_ = ui.ui() |
| 89 self.ui = ui_ | 89 self.ui = ui_ |
| 90 self.__setup_repo(repo or path) | 90 self.__setup_repo(repo or path, uuid) |
| 91 | |
| 92 if not author_host: | |
| 93 author_host = self.ui.config('hgsubversion', 'defaulthost', uuid) | |
| 94 if not authors: | |
| 95 authors = self.ui.config('hgsubversion', 'authormap') | |
| 96 if not filemap: | |
| 97 filemap = self.ui.config('hgsubversion', 'filemap') | |
| 98 if not tag_locations: | |
| 99 tag_locations = self.ui.config('hgsubversion', 'tagpaths', ['tags']) | |
| 100 self.usebranchnames = self.ui.configbool('hgsubversion', | |
| 101 'usebranchnames', True) | |
| 91 | 102 |
| 92 self.subdir = subdir | 103 self.subdir = subdir |
| 93 if self.subdir and self.subdir[0] == '/': | 104 if self.subdir and self.subdir[0] == '/': |
| 94 self.subdir = self.subdir[1:] | 105 self.subdir = self.subdir[1:] |
| 95 self.revmap = {} | |
| 96 if os.path.exists(self.revmap_file): | |
| 97 self.revmap = util.parse_revmap(self.revmap_file) | |
| 98 self.branches = {} | 106 self.branches = {} |
| 99 if os.path.exists(self.branch_info_file): | 107 if os.path.exists(self.branch_info_file): |
| 100 f = open(self.branch_info_file) | 108 f = open(self.branch_info_file) |
| 101 self.branches = pickle.load(f) | 109 self.branches = pickle.load(f) |
| 102 f.close() | 110 f.close() |
| 135 self.lastdate = date | 143 self.lastdate = date |
| 136 else: | 144 else: |
| 137 date = self.lastdate | 145 date = self.lastdate |
| 138 return date | 146 return date |
| 139 | 147 |
| 140 def __setup_repo(self, arg): | 148 def __setup_repo(self, arg, uuid): |
| 141 """Verify the repo is going to work out for us. | 149 """Verify the repo is going to work out for us. |
| 142 | 150 |
| 143 This method will fail an assertion if the repo exists but doesn't have | 151 This method will fail an assertion if the repo exists but doesn't have |
| 144 the Subversion metadata. | 152 the Subversion metadata. |
| 145 """ | 153 """ |
| 152 self.path = os.path.normpath(os.path.join(self.repo.path, '..')) | 160 self.path = os.path.normpath(os.path.join(self.repo.path, '..')) |
| 153 else: #pragma: no cover | 161 else: #pragma: no cover |
| 154 raise TypeError("editor requires either a path or a repository " | 162 raise TypeError("editor requires either a path or a repository " |
| 155 "specified") | 163 "specified") |
| 156 | 164 |
| 157 if os.path.isdir(self.meta_data_dir) and os.listdir(self.meta_data_dir): | 165 if not os.path.isdir(self.meta_data_dir): |
| 158 assert os.path.isfile(self.revmap_file) | 166 os.makedirs(self.meta_data_dir) |
| 159 assert os.path.isfile(self.svn_url_file) | 167 self._set_uuid(uuid) |
| 160 assert os.path.isfile(self.uuid_file) | 168 |
| 169 if os.path.isfile(self.revmap_file): | |
| 170 self.revmap = util.parse_revmap(self.revmap_file) | |
| 161 else: | 171 else: |
| 162 os.makedirs(os.path.dirname(self.uuid_file)) | 172 self.revmap = {} |
| 163 f = open(self.revmap_file, 'w') | 173 f = open(self.revmap_file, 'w') |
| 164 f.write('%s\n' % util.REVMAP_FILE_VERSION) | 174 f.write('%s\n' % util.REVMAP_FILE_VERSION) |
| 165 f.flush() | 175 f.flush() |
| 166 f.close() | 176 f.close() |
| 167 | 177 |
| 634 parents = (ha, closed) | 644 parents = (ha, closed) |
| 635 def del_all_files(*args): | 645 def del_all_files(*args): |
| 636 raise IOError | 646 raise IOError |
| 637 files = parentctx.manifest().keys() | 647 files = parentctx.manifest().keys() |
| 638 extra = {} | 648 extra = {} |
| 639 if not self.opts.get('svn_no_branchnames', False): | 649 if self.usebranchnames: |
| 640 extra['branch'] = 'closed-branches' | 650 extra['branch'] = 'closed-branches' |
| 641 current_ctx = context.memctx(self.repo, | 651 current_ctx = context.memctx(self.repo, |
| 642 parents, | 652 parents, |
| 643 rev.message or ' ', | 653 rev.message or ' ', |
| 644 files, | 654 files, |
| 656 | 666 |
| 657 parents = (self.get_parent_revision(rev.revnum, branch), | 667 parents = (self.get_parent_revision(rev.revnum, branch), |
| 658 revlog.nullid) | 668 revlog.nullid) |
| 659 if parents[0] in closed_revs and branch in self.branches_to_delete: | 669 if parents[0] in closed_revs and branch in self.branches_to_delete: |
| 660 continue | 670 continue |
| 661 extra = util.build_extra(rev.revnum, branch, | 671 extra = util.build_extra(rev.revnum, branch, self.uuid, self.subdir) |
| 662 open(self.uuid_file).read(), | |
| 663 self.subdir) | |
| 664 if branch is not None: | 672 if branch is not None: |
| 665 if (branch not in self.branches | 673 if (branch not in self.branches |
| 666 and branch not in self.repo.branchtags()): | 674 and branch not in self.repo.branchtags()): |
| 667 continue | 675 continue |
| 668 parent_ctx = self.repo.changectx(parents[0]) | 676 parent_ctx = self.repo.changectx(parents[0]) |
| 689 data = parent_ctx.filectx(path).data() | 697 data = parent_ctx.filectx(path).data() |
| 690 return context.memfilectx(path=path, | 698 return context.memfilectx(path=path, |
| 691 data=data, | 699 data=data, |
| 692 islink=is_link, isexec=is_exec, | 700 islink=is_link, isexec=is_exec, |
| 693 copied=copied) | 701 copied=copied) |
| 694 if self.opts.get('svn_no_branchnames', False): | 702 if not self.usebranchnames: |
| 695 extra.pop('branch', None) | 703 extra.pop('branch', None) |
| 696 current_ctx = context.memctx(self.repo, | 704 current_ctx = context.memctx(self.repo, |
| 697 parents, | 705 parents, |
| 698 rev.message or '...', | 706 rev.message or '...', |
| 699 files.keys(), | 707 files.keys(), |
| 715 raise IOError | 723 raise IOError |
| 716 # True here meant nuke all files, shouldn't happen with branch closing | 724 # True here meant nuke all files, shouldn't happen with branch closing |
| 717 if self.commit_branches_empty[branch]: #pragma: no cover | 725 if self.commit_branches_empty[branch]: #pragma: no cover |
| 718 raise hgutil.Abort('Empty commit to an open branch attempted. ' | 726 raise hgutil.Abort('Empty commit to an open branch attempted. ' |
| 719 'Please report this issue.') | 727 'Please report this issue.') |
| 720 extra = util.build_extra(rev.revnum, branch, | 728 extra = util.build_extra(rev.revnum, branch, self.uuid, self.subdir) |
| 721 open(self.uuid_file).read(), | 729 if not self.usebranchnames: |
| 722 self.subdir) | |
| 723 if self.opts.get('svn_no_branchnames', False): | |
| 724 extra.pop('branch', None) | 730 extra.pop('branch', None) |
| 725 current_ctx = context.memctx(self.repo, | 731 current_ctx = context.memctx(self.repo, |
| 726 (ha, node.nullid), | 732 (ha, node.nullid), |
| 727 rev.message or ' ', | 733 rev.message or ' ', |
| 728 [], | 734 [], |
| 781 | 787 |
| 782 def revmap_file(self): | 788 def revmap_file(self): |
| 783 return self.meta_file_named('rev_map') | 789 return self.meta_file_named('rev_map') |
| 784 revmap_file = property(revmap_file) | 790 revmap_file = property(revmap_file) |
| 785 | 791 |
| 786 def svn_url_file(self): | 792 def _get_uuid(self): |
| 787 return self.meta_file_named('url') | 793 return open(self.meta_file_named('uuid')).read() |
| 788 svn_url_file = property(svn_url_file) | 794 |
| 789 | 795 def _set_uuid(self, uuid): |
| 790 def uuid_file(self): | 796 if not uuid: |
| 791 return self.meta_file_named('uuid') | 797 return self._get_uuid() |
| 792 uuid_file = property(uuid_file) | 798 elif os.path.isfile(self.meta_file_named('uuid')): |
| 799 stored_uuid = self._get_uuid() | |
| 800 assert stored_uuid | |
| 801 if uuid != stored_uuid: | |
| 802 raise hgutil.Abort('unable to operate on unrelated repository') | |
| 803 else: | |
| 804 return stored_uuid | |
| 805 else: | |
| 806 if uuid: | |
| 807 f = open(self.meta_file_named('uuid'), 'w') | |
| 808 f.write(uuid) | |
| 809 f.flush() | |
| 810 f.close() | |
| 811 return self._get_uuid() | |
| 812 else: | |
| 813 raise hgutil.Abort('unable to operate on unrelated repository') | |
| 814 | |
| 815 uuid = property(_get_uuid, _set_uuid, None, | |
| 816 'Error-checked UUID of source Subversion repository.') | |
| 793 | 817 |
| 794 def branch_info_file(self): | 818 def branch_info_file(self): |
| 795 return self.meta_file_named('branch_info') | 819 return self.meta_file_named('branch_info') |
| 796 branch_info_file = property(branch_info_file) | 820 branch_info_file = property(branch_info_file) |
| 797 | 821 |
| 800 tag_info_file = property(tag_info_file) | 824 tag_info_file = property(tag_info_file) |
| 801 | 825 |
| 802 def tag_locations_file(self): | 826 def tag_locations_file(self): |
| 803 return self.meta_file_named('tag_locations') | 827 return self.meta_file_named('tag_locations') |
| 804 tag_locations_file = property(tag_locations_file) | 828 tag_locations_file = property(tag_locations_file) |
| 805 | |
| 806 def url(self): | |
| 807 return open(self.svn_url_file).read() | |
| 808 url = property(url) | |
| 809 | 829 |
| 810 def authors_file(self): | 830 def authors_file(self): |
| 811 return self.meta_file_named('authors') | 831 return self.meta_file_named('authors') |
| 812 authors_file = property(authors_file) | 832 authors_file = property(authors_file) |
| 813 | 833 |
