Mercurial > hgsubversion
diff hg_delta_editor.py @ 133:2242dd1163c6
hg_delta_editor: fix bad parent revision calculation in the case of a branch
recycling a name.
Also implemented marking branches as closed in both replay and stupid paths.
author | Augie Fackler <durin42@gmail.com> |
---|---|
date | Wed, 10 Dec 2008 14:29:05 -0600 |
parents | 4d42dbbb5127 |
children | cf6fe8457570 |
line wrap: on
line diff
--- a/hg_delta_editor.py +++ b/hg_delta_editor.py @@ -107,11 +107,11 @@ class HgChangeReceiver(delta.Editor): self.author_host = author_host def __setup_repo(self, repo_path): - '''Verify the repo is going to work out for us. + """Verify the repo is going to work out for us. This method will fail an assertion if the repo exists but doesn't have the Subversion metadata. - ''' + """ if os.path.isdir(repo_path) and len(os.listdir(repo_path)): self.repo = hg.repository(self.ui, repo_path) assert os.path.isfile(self.revmap_file) @@ -141,6 +141,7 @@ class HgChangeReceiver(delta.Editor): self.missing_plaintexts = set() self.commit_branches_empty = {} self.base_revision = None + self.branches_to_delete = set() def _save_metadata(self): '''Save the Subversion metadata. This should really be called after @@ -164,11 +165,11 @@ class HgChangeReceiver(delta.Editor): return self._split_branch_path(path)[:2] def _split_branch_path(self, path): - '''Figure out which branch inside our repo this path represents, and + """Figure out which branch inside our repo this path represents, and also figure out which path inside that branch it is. Raises an exception if it can't perform its job. - ''' + """ path = self._normalize_path(path) if path.startswith('trunk'): p = path[len('trunk'):] @@ -186,8 +187,8 @@ class HgChangeReceiver(delta.Editor): return None, None, None def set_current_rev(self, rev): - '''Set the revision we're currently converting. - ''' + """Set the revision we're currently converting. + """ self.current_rev = rev def set_file(self, path, data, isexec=False, islink=False): @@ -236,19 +237,23 @@ class HgChangeReceiver(delta.Editor): continue if num <= number and num > real_num: real_num = num - if real_num == 0: - if branch in self.branches: - parent_branch = self.branches[branch][0] - parent_branch_rev = self.branches[branch][1] - if parent_branch_rev <= 0: - return None, None - branch_created_rev = self.branches[branch][2] - if parent_branch == 'trunk': - parent_branch = None - if branch_created_rev <= number+1 and branch != parent_branch: - return self.get_parent_svn_branch_and_rev( - parent_branch_rev+1, - parent_branch) + if branch in self.branches: + parent_branch = self.branches[branch][0] + parent_branch_rev = self.branches[branch][1] + # check to see if this branch already existed and is the same + if parent_branch_rev < real_num: + return real_num, branch + # if that wasn't true, then this is the a new branch with the + # same name as some old deleted branch + if parent_branch_rev <= 0 and real_num == 0: + return None, None + branch_created_rev = self.branches[branch][2] + if parent_branch == 'trunk': + parent_branch = None + if branch_created_rev <= number+1 and branch != parent_branch: + return self.get_parent_svn_branch_and_rev( + parent_branch_rev+1, + parent_branch) if real_num != 0: return real_num, branch return None, None @@ -265,12 +270,12 @@ class HgChangeReceiver(delta.Editor): paths = revision.paths added_branches = {} added_tags = {} + self.branches_to_delete = set() tags_to_delete = set() - branches_to_delete = set() for p in sorted(paths): fi, br = self._path_and_branch_for_path(p) if fi is not None: - if fi == '' and br not in self.branches: + if fi == '' and paths[p].action != 'D': src_p = paths[p].copyfrom_path src_rev = paths[p].copyfrom_rev src_tag = self._is_path_tag(src_p) @@ -294,7 +299,7 @@ class HgChangeReceiver(delta.Editor): elif fi == '' and br in self.branches: br2 = br or 'default' if br2 not in self.repo.branchtags() and paths[p].action == 'D': - branches_to_delete.add(br) + self.branches_to_delete.add(br) else: t_name = self._is_path_tag(p) if t_name == False: @@ -320,7 +325,7 @@ class HgChangeReceiver(delta.Editor): tags_to_delete.add(t_name) for t in tags_to_delete: del self.tags[t] - for br in branches_to_delete: + for br in self.branches_to_delete: del self.branches[br] self.tags.update(added_tags) self.branches.update(added_branches) @@ -359,9 +364,12 @@ class HgChangeReceiver(delta.Editor): parents = (self.get_parent_revision(rev.revnum, branch), revlog.nullid) if branch is not None: - if branch not in self.branches and branch not in self.repo.branchtags(): + if (branch not in self.branches + and branch not in self.repo.branchtags()): continue extra['branch'] = branch + if (branch in self.branches_to_delete): + continue parent_ctx = self.repo.changectx(parents[0]) def filectxfn(repo, memctx, path): current_file = files[path] @@ -396,6 +404,29 @@ class HgChangeReceiver(delta.Editor): if (rev.revnum, branch) not in self.revmap: self.add_to_revmap(rev.revnum, branch, new_hash) # now we handle branches that need to be committed without any files + for branch in self.branches_to_delete: + closed = revlog.nullid + if 'closed-branches' in self.repo.branchtags(): + closed = self.repo['closed-branches'].node() + ha = self.get_parent_revision(rev.revnum, branch) + parentctx = self.repo.changectx(ha) + if parentctx.children(): + continue + parents = (ha, closed) + def del_all_files(*args): + raise IOError + files = parentctx.manifest().keys() + current_ctx = context.memctx(self.repo, + parents, + rev.message or ' ', + files, + del_all_files, + '%s%s' % (rev.author, + self.author_host), + date, + {'branch': 'closed-branches'}) + new_hash = self.repo.commitctx(current_ctx) + self.ui.status('Marked branch %s as closed.' % (branch or 'default')) for branch in self.commit_branches_empty: ha = self.get_parent_revision(rev.revnum, branch) if ha == node.nullid: @@ -404,8 +435,11 @@ class HgChangeReceiver(delta.Editor): def del_all_files(*args): raise IOError extra = {} - if branch: - extra['branch'] = branch + if parent_ctx.children(): + # Target isn't an active head, no need to do things to it. + continue + if branch in self.branches_to_delete: + extra['branch'] = 'closed-branch' # True here means nuke all files files = [] if self.commit_branches_empty[branch]: @@ -468,6 +502,8 @@ class HgChangeReceiver(delta.Editor): @stash_exception_on_self def delete_entry(self, path, revision_bogus, parent_baton, pool=None): br_path, branch = self._path_and_branch_for_path(path) + if br_path == '': + self.branches_to_delete.add(branch) if br_path is not None: ha = self.get_parent_revision(self.current_rev.revnum, branch) if ha == revlog.nullid: