def upgrade_marks(self, hgrepo): if self.marks_version == 1: # Convert from integer reversions to hgsha1 log("Upgrading marks-hg from hg sequence number to SHA1", "WARNING") self.marks_to_revisions = dict( (mark, hghex(hgrepo.changelog.node(int(rev)))) for mark, rev in self.marks_to_revisions.iteritems()) self.revisions_to_marks = dict( (hghex(hgrepo.changelog.node(int(rev))), mark) for rev, mark in self.revisions_to_marks.iteritems()) self.marks_version = 2 log("Upgrade complete", "WARNING")
def upgrade_marks(self, hgremote): if self.marks_version == 1: # Convert from integer reversions to hgsha1 log("Upgrading marks-hg from hg sequence number to SHA1", "WARNING") self.marks_to_revisions = dict( (mark, hghex(hgremote.repo.changelog.node(int(rev)))) for mark, rev in self.marks_to_revisions.iteritems()) self.revisions_to_marks = dict( (hghex(hgremote.repo.changelog.node(int(rev))), mark) for rev, mark in self.revisions_to_marks.iteritems()) self.marks_version = 2 log("Upgrade complete", "WARNING") if self.marks_version == 2: # Convert tips to use gitify refs as keys log("Upgrading marks-hg tips", "WARNING") self.tips = dict( ("%s/%s" % (hgremote.prefix, reftype_and_name), tip) for reftype_and_name, tip in self.tips.iteritems()) self.marks_version = 3 log("Upgrade complete", "WARNING")
def process(self): self.marks.store() # checkpoint new_branch = False push_bookmarks = [] self.parser.read_line() for line in self.parser.read_block('done'): command = line.split()[0] if command not in ('blob', 'commit', 'reset', 'tag', 'feature'): die('unhandled command: %s' % line) getattr(self, 'do_%s' % command)() for ref, node in self.parsed_refs.iteritems(): if ref.startswith('refs/heads/branches'): branch = ref[len('refs/heads/branches'):] if git_to_hg_spaces(branch) not in self.hgremote.branches: new_branch = True elif ref.startswith('refs/heads/'): bookmark = ref[len('refs/heads/'):] old = self.hgremote.bookmarks.get(bookmark) old = old.hex() if old else '' if not pushbookmark(self.repo, bookmark, old, node): continue push_bookmarks.append((bookmark, old, hghex(node))) elif ref.startswith('refs/tags/'): self.write_tag(ref) else: # transport-helper/fast-export bugs log("Fast-export unexpected ref: %s" % ref, "WARNING") continue success = False try: self.repo.push(self.hgremote.peer, force=False, newbranch=new_branch) for bookmark, old, new in push_bookmarks: self.hgremote.peer.pushkey('bookmarks', bookmark, old, new) self.marks.store() success = True except Abort as e: # mercurial.error.Abort: push creates new remote head f14531ca4e2d! if e.message.startswith("push creates new remote head"): self.marks.load() # restore from checkpoint # strip revs, implementation finds min revision from list if self.processed_nodes: self.repo.mq.strip(self.repo, self.processed_nodes) else: die("unknown hg exception: %s" % e) # TODO: handle network/other errors? for ref in self.parsed_refs: if success: output("ok %s" % ref) else: output("error %s non-fast forward" % ref) # TODO: other errors as well output() if not success: # wait until fast-export finishes to muck with the marks file self.remove_processed_git_marks()
def write_tag(self, name, node): branch = self.repo[node].branch() # Calling self.repo.tag() doesn't append the tag to the correct # commit. So I copied some of localrepo._tag into here. # But that method, like much of mercurial's code, is ugly. # So I then rewrote it. tags_revision = revsingle(self.repo, hghex(branch_tip(self.repo, branch))) if '.hgtags' in tags_revision: old_tags = tags_revision['.hgtags'].data() else: old_tags = '' newtags = [old_tags] if old_tags and old_tags[-1] != '\n': newtags.append('\n') encoded_tag = encoding.fromlocal(name) tag_line = '%s %s' % (hghex(node), encoded_tag) if tag_line in old_tags: return # Don't commit a tag that was previously committed newtags.append(tag_line) def get_filectx(repo, memctx, file): return memfilectx(file, ''.join(newtags)) if name in self.parsed_tags: author, message = self.parsed_tags[name] user, date, tz = author date_tz = (date, tz) else: message = "Added tag %s for changeset %s" % (name, hgshort(node)) user = self.hgrc.get("ui", "username", None) date_tz = None # XXX insert current date here ctx = memctx(self.repo, (branch_tip(self.repo, branch), self.NULL_PARENT), message, ['.hgtags'], get_filectx, user, date_tz, {'branch': branch}) tmp = encoding.encoding encoding.encoding = 'utf-8' node = self.repo.commitctx(ctx) encoding.encoding = tmp
def write_tag(self, ref): node = self.parsed_refs[ref] tag = git_to_hg_spaces(ref[len('refs/tags/'):]) branch = self.repo[node].branch() # Calling self.repo.tag() doesn't append the tag to the correct # commit. So I copied some of localrepo._tag into here. # But that method, like much of mercurial's code, is ugly. # So I then rewrote it. tags_revision = revsingle(self.repo, hghex(branch_tip(self.repo, branch))) if '.hgtags' in tags_revision: old_tags = tags_revision['.hgtags'].data() else: old_tags = '' newtags = [old_tags] if old_tags and old_tags[-1] != '\n': newtags.append('\n') encoded_tag = encoding.fromlocal(tag) tag_line = '%s %s' % (hghex(node), encoded_tag) if tag_line in old_tags: return # Don't commit a tag that was previously committed newtags.append(tag_line) def get_filectx(repo, memctx, file): return memfilectx(file, ''.join(newtags)) if tag in self.parsed_tags: author, message = self.parsed_tags[tag] user, date, tz = author date_tz = (date, tz) else: message = "Added tag %s for changeset %s" % (tag, hgshort(node)) user = None date_tz = None ctx = memctx(self.repo, (branch_tip(self.repo, branch), self.NULL_PARENT), message, ['.hgtags'], get_filectx, user, date_tz, {'branch': branch}) tmp = encoding.encoding encoding.encoding = 'utf-8' node = self.repo.commitctx(ctx) encoding.encoding = tmp
def process(self): self.marks.store() # checkpoint new_branch = False push_bookmarks = [] self.parser.read_line() for line in self.parser.read_block('done'): command = line.split()[0] if command not in ('blob', 'commit', 'reset', 'tag', 'feature'): die('unhandled command: %s' % line) getattr(self, 'do_%s' % command)() updated_refs = {} for ref, node in self.parsed_refs.iteritems(): if ref.startswith(self.hgremote.prefix): # This seems to be a git fast-export bug continue name, reftype = ref_to_name_reftype(ref) name = git_to_hg_spaces(name) if reftype == BRANCH: if name not in self.hgremote.branches: new_branch = True elif reftype == BOOKMARK: old = self.hgremote.bookmarks.get(name) old = old.hex() if old else '' if not pushbookmark(self.repo, name, old, node): continue push_bookmarks.append((name, old, hghex(node))) elif reftype == TAG: self.write_tag(name, node) else: assert False, "unexpected reftype: %s" % reftype updated_refs[ref] = node success = False try: self.repo.push(self.hgremote.peer, force=False, newbranch=new_branch) for bookmark, old, new in push_bookmarks: self.hgremote.peer.pushkey('bookmarks', bookmark, old, new) self.marks.store() success = True except Abort as e: # mercurial.error.Abort: push creates new remote head f14531ca4e2d! if e.message.startswith("push creates new remote head"): self.marks.load() # restore from checkpoint # strip revs, implementation finds min revision from list if self.processed_nodes: self.repo.mq.strip(self.repo, self.processed_nodes) else: die("unknown hg exception: %s" % e) # TODO: handle network/other errors? for ref, node in updated_refs.items(): if success: status = "" name, reftype = ref_to_name_reftype(ref) gitify_ref = self.hgremote.make_gitify_ref(name, reftype) last_known_rev = self.marks.tips.get(gitify_ref) new_rev = self.repo[node].rev() if last_known_rev is not None and last_known_rev == new_rev: # up to date status tells git that nothing has changed # during the push for this ref, which prevents it from # printing pointless status info to the user such as: # * [new branch] master -> master status = " up to date" output("ok %s%s" % (ref, status)) else: output("error %s non-fast forward" % ref) # TODO: other errors as well output() if not success: # wait until fast-export finishes to muck with the marks file self.remove_processed_git_marks()
def is_marked(self, revision): return hghex(revision) in self.revisions_to_marks
def new_mark(self, revision, mark): self.revisions_to_marks[hghex(revision)] = mark self.marks_to_revisions[mark] = hghex(revision) self.last_mark = mark
def get_mark(self, revision): self.last_mark += 1 self.revisions_to_marks[hghex(revision)] = self.last_mark return self.last_mark
def revision_to_mark(self, revision): return self.revisions_to_marks[hghex(revision)]