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