def export_hg_commit(self, rev): self.ui.note(_("converting revision %s\n") % hex(rev)) oldenc = self.swap_out_encoding() ctx = self.repo.changectx(rev) extra = ctx.extra() commit = Commit() (time, timezone) = ctx.date() commit.author = self.get_git_author(ctx) commit.author_time = int(time) commit.author_timezone = -timezone if 'committer' in extra: # fixup timezone (name, timestamp, timezone) = extra['committer'].rsplit(' ', 2) commit.committer = name commit.commit_time = timestamp # work around a timezone format change if int(timezone) % 60 != 0: #pragma: no cover timezone = parse_timezone(timezone) # Newer versions of Dulwich return a tuple here if isinstance(timezone, tuple): timezone, neg_utc = timezone commit._commit_timezone_neg_utc = neg_utc else: timezone = -int(timezone) commit.commit_timezone = timezone else: commit.committer = commit.author commit.commit_time = commit.author_time commit.commit_timezone = commit.author_timezone commit.parents = [] for parent in self.get_git_parents(ctx): hgsha = hex(parent.node()) git_sha = self.map_git_get(hgsha) if git_sha: commit.parents.append(git_sha) commit.message = self.get_git_message(ctx) if 'encoding' in extra: commit.encoding = extra['encoding'] tree_sha = commit_tree(self.git.object_store, self.iterblobs(ctx)) commit.tree = tree_sha self.git.object_store.add_object(commit) self.map_set(commit.id, ctx.hex()) self.swap_out_encoding(oldenc) return commit.id
def test_commit_zero_utc_timezone(self): c = Commit() c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba" c.message = b"Some message" c.committer = b"Committer <Committer>" c.commit_time = 4 c.commit_timezone = 0 c._commit_timezone_neg_utc = True c.author_time = 5 c.author_timezone = 60 * 2 c.author = b"Author <author>" self.assertRoundtripCommit(c)
def __setitem__(self, path, raw): # XXX: I don't have much idea, what I'm doing here and I might # just corrupt your repository... # Mark directory as special (None, None) marker value if raw is None: super(Head, self).__setitem__(path, (None, None)) return # Get old mode or use the default try: mode = super(Head, self).__getitem__(path)[1] except KeyError: mode = 0100644 # Get existing entries for the content tree entries = [(key, sha_mode[0], cleanup_mode(sha_mode[1])) for key, sha_mode in super(Head, self).iteritems() if sha_mode[0] is not None and key is not path] # Get author # TODO: refactor to use plone.api or maybe use product_config from Products.CMFCore.utils import getToolByName portal_members = getToolByName(getSite(), 'portal_membership') member = portal_members.getAuthenticatedMember() author = '{0:s} <{1:s}>'.format( member.getProperty('fullname', '') or member.getId(), member.getProperty('email', '') or '*****@*****.**' ) # Get timezone tz_diff = dateutil.tz.tzlocal().utcoffset(datetime.datetime.now()) # Create commit commit = Commit() commit.author = author commit.committer = commit.author commit.commit_time = int(time.time()) commit.author_time = commit.commit_time commit.commit_timezone = tz_diff.seconds commit.author_timezone = tz_diff.seconds if tz_diff < datetime.timedelta(0): commit._author_timezone_neg_utc = True commit._commit_timezone_neg_utc = True commit.encoding = 'UTF-8' commit.message = 'Update {0:s}'.format(path) commit.parents = [self._head] # Create blob and commit tree blob = Blob.from_string(raw) entries.append((path, blob.id, cleanup_mode(mode))) commit.tree = commit_tree(self._repo.object_store, entries) # Save blob and commit self._repo.object_store.add_object(blob) self._repo.object_store.add_object(commit) def determine_wants(haves): # Set new head for the branch return {self.__name__: commit.id} # Push to remote refs = self.__parent__._client.send_pack( self.__parent__._host_path, determine_wants, self._repo.object_store.generate_pack_contents, progress=logger.info ) # Update heads for ref, sha in refs.items(): if sha in self._repo.object_store: self._repo.refs[ref] = sha # Update "index" super(Head, self).__setitem__(path, (blob.id, mode))
def export_commit(self, rev, tree_sha, parent_lookup, lossy, verifiers): """Turn a Bazaar revision in to a Git commit :param tree_sha: Tree sha for the commit :param parent_lookup: Function for looking up the GIT sha equiv of a bzr revision :param lossy: Whether to store roundtripping information. :param verifiers: Verifiers info :return dulwich.objects.Commit represent the revision: """ from dulwich.objects import Commit, Tag commit = Commit() commit.tree = tree_sha if not lossy: metadata = CommitSupplement() metadata.verifiers = verifiers else: metadata = None parents = [] for p in rev.parent_ids: try: git_p = parent_lookup(p) except KeyError: git_p = None if metadata is not None: metadata.explicit_parent_ids = rev.parent_ids if git_p is not None: if len(git_p) != 40: raise AssertionError("unexpected length for %r" % git_p) parents.append(git_p) commit.parents = parents try: encoding = rev.properties[u'git-explicit-encoding'] except KeyError: encoding = rev.properties.get(u'git-implicit-encoding', 'utf-8') try: commit.encoding = rev.properties[u'git-explicit-encoding'].encode( 'ascii') except KeyError: pass commit.committer = fix_person_identifier(rev.committer.encode( encoding)) commit.author = fix_person_identifier( rev.get_apparent_authors()[0].encode(encoding)) # TODO(jelmer): Don't use this hack. long = getattr(__builtins__, 'long', int) commit.commit_time = long(rev.timestamp) if u'author-timestamp' in rev.properties: commit.author_time = long(rev.properties[u'author-timestamp']) else: commit.author_time = commit.commit_time commit._commit_timezone_neg_utc = ( u"commit-timezone-neg-utc" in rev.properties) commit.commit_timezone = rev.timezone commit._author_timezone_neg_utc = ( u"author-timezone-neg-utc" in rev.properties) if u'author-timezone' in rev.properties: commit.author_timezone = int(rev.properties[u'author-timezone']) else: commit.author_timezone = commit.commit_timezone if u'git-gpg-signature' in rev.properties: commit.gpgsig = rev.properties[u'git-gpg-signature'].encode( 'utf-8', 'surrogateescape') commit.message = self._encode_commit_message(rev, rev.message, encoding) if not isinstance(commit.message, bytes): raise TypeError(commit.message) if metadata is not None: try: mapping_registry.parse_revision_id(rev.revision_id) except errors.InvalidRevisionId: metadata.revision_id = rev.revision_id mapping_properties = set( [u'author', u'author-timezone', u'author-timezone-neg-utc', u'commit-timezone-neg-utc', u'git-implicit-encoding', u'git-gpg-signature', u'git-explicit-encoding', u'author-timestamp', u'file-modes']) for k, v in rev.properties.items(): if k not in mapping_properties: metadata.properties[k] = v if not lossy and metadata: if self.roundtripping: commit.message = inject_bzr_metadata(commit.message, metadata, encoding) else: raise NoPushSupport( None, None, self, revision_id=rev.revision_id) if not isinstance(commit.message, bytes): raise TypeError(commit.message) i = 0 propname = u'git-mergetag-0' while propname in rev.properties: commit.mergetag.append(Tag.from_string(rev.properties[propname])) i += 1 propname = u'git-mergetag-%d' % i if u'git-extra' in rev.properties: commit.extra.extend( [l.split(b' ', 1) for l in rev.properties[u'git-extra'].splitlines()]) return commit
def __setitem__(self, path, raw): # XXX: I don't have much idea, what I'm doing here and I might # just corrupt your repository... # Mark directory as special (None, None) marker value if raw is None: super(Head, self).__setitem__(path, (None, None)) return # Get old mode or use the default try: mode = super(Head, self).__getitem__(path)[1] except KeyError: mode = 0100644 # Get existing entries for the content tree entries = [(key, sha_mode[0], cleanup_mode(sha_mode[1])) for key, sha_mode in super(Head, self).iteritems() if sha_mode[0] is not None and key is not path] # Get author # TODO: refactor to use plone.api or maybe use product_config from Products.CMFCore.utils import getToolByName portal_members = getToolByName(getSite(), 'portal_membership') member = portal_members.getAuthenticatedMember() author = '{0:s} <{1:s}>'.format( member.getProperty('fullname', '') or member.getId(), member.getProperty('email', '') or '*****@*****.**') # Get timezone tz_diff = dateutil.tz.tzlocal().utcoffset(datetime.datetime.now()) # Create commit commit = Commit() commit.author = author commit.committer = commit.author commit.commit_time = int(time.time()) commit.author_time = commit.commit_time commit.commit_timezone = tz_diff.seconds commit.author_timezone = tz_diff.seconds if tz_diff < datetime.timedelta(0): commit._author_timezone_neg_utc = True commit._commit_timezone_neg_utc = True commit.encoding = 'UTF-8' commit.message = 'Update {0:s}'.format(path) commit.parents = [self._head] # Create blob and commit tree blob = Blob.from_string(raw) entries.append((path, blob.id, cleanup_mode(mode))) commit.tree = commit_tree(self._repo.object_store, entries) # Save blob and commit self._repo.object_store.add_object(blob) self._repo.object_store.add_object(commit) def determine_wants(haves): # Set new head for the branch return {self.__name__: commit.id} # Push to remote refs = self.__parent__._client.send_pack( self.__parent__._host_path, determine_wants, self._repo.object_store.generate_pack_contents, progress=logger.info) # Update heads for ref, sha in refs.items(): if sha in self._repo.object_store: self._repo.refs[ref] = sha # Update "index" super(Head, self).__setitem__(path, (blob.id, mode))
def export_hg_commit(self, rev, exporter): self.ui.note(_("converting revision %s\n") % hex(rev)) oldenc = self.swap_out_encoding() ctx = self.repo.changectx(rev) extra = ctx.extra() commit = Commit() (time, timezone) = ctx.date() # work around to bad timezone offets - dulwich does not handle # sub minute based timezones. In the one known case, it was a # manual edit that led to the unusual value. Based on that, # there is no reason to round one way or the other, so do the # simplest and round down. timezone -= (timezone % 60) commit.author = self.get_git_author(ctx) commit.author_time = int(time) commit.author_timezone = -timezone if 'committer' in extra: if RE_HGGIT_COMMITTER_LINE.search(extra['committer']): # fixup timezone (name, timestamp, timezone) = extra['committer'].rsplit(' ', 2) commit.committer = name commit.commit_time = timestamp # work around a timezone format change if int(timezone) % 60 != 0: # pragma: no cover timezone = parse_timezone(timezone) # Newer versions of Dulwich return a tuple here if isinstance(timezone, tuple): timezone, neg_utc = timezone commit._commit_timezone_neg_utc = neg_utc else: timezone = -int(timezone) commit.commit_timezone = timezone else: commit.committer = extra['committer'] commit.commit_time = commit.author_time commit.commit_timezone = commit.author_timezone else: commit.committer = commit.author commit.commit_time = commit.author_time commit.commit_timezone = commit.author_timezone commit.parents = [] for parent in self.get_git_parents(ctx): hgsha = hex(parent.node()) git_sha = self.map_git_get(hgsha) if git_sha: if git_sha not in self.git.object_store: raise hgutil.Abort(_('Parent SHA-1 not present in Git' 'repo: %s' % git_sha)) commit.parents.append(git_sha) commit.message = self.get_git_message(ctx) if 'encoding' in extra: commit.encoding = extra['encoding'] for obj, nodeid in exporter.update_changeset(ctx): self.git.object_store.add_object(obj) tree_sha = exporter.root_tree_sha if tree_sha not in self.git.object_store: raise hgutil.Abort(_('Tree SHA-1 not present in Git repo: %s' % tree_sha)) commit.tree = tree_sha self.git.object_store.add_object(commit) self.map_set(commit.id, ctx.hex()) self.swap_out_encoding(oldenc) return commit.id
def export_hg_commit(self, rev, exporter): self.ui.note(_("converting revision %s\n") % hex_(rev)) oldenc = self.swap_out_encoding() ctx = self.repo.changectx(rev) extra = ctx.extra() commit = Commit() (time, timezone) = ctx.date() # work around to bad timezone offets - dulwich does not handle # sub minute based timezones. In the one known case, it was a # manual edit that led to the unusual value. Based on that, # there is no reason to round one way or the other, so do the # simplest and round down. timezone -= (timezone % 60) commit.author = self.get_git_author(ctx) commit.author_time = int(time) commit.author_timezone = -timezone if 'committer' in extra: # fixup timezone (name, timestamp, timezone) = extra['committer'].rsplit(' ', 2) commit.committer = name commit.commit_time = timestamp # work around a timezone format change if int(timezone) % 60 != 0: #pragma: no cover timezone = parse_timezone(timezone) # Newer versions of Dulwich return a tuple here if isinstance(timezone, tuple): timezone, neg_utc = timezone commit._commit_timezone_neg_utc = neg_utc else: timezone = -int(timezone) commit.commit_timezone = timezone else: commit.committer = commit.author commit.commit_time = commit.author_time commit.commit_timezone = commit.author_timezone commit.parents = [] for parent in self.get_git_parents(ctx): hgsha = hex_(parent.node()) git_sha = self.map_git_get(hgsha) if git_sha: if git_sha not in self.git.object_store: raise hgutil.Abort( _('Parent SHA-1 not present in Git' 'repo: %s' % git_sha)) commit.parents.append(git_sha) commit.message = self.get_git_message(ctx) if 'encoding' in extra: commit.encoding = extra['encoding'] for obj, nodeid in exporter.update_changeset(ctx): self.git.object_store.add_object(obj) tree_sha = exporter.root_tree_sha if tree_sha not in self.git.object_store: raise hgutil.Abort( _('Tree SHA-1 not present in Git repo: %s' % tree_sha)) commit.tree = tree_sha self.git.object_store.add_object(commit) self.map_set(commit.id, ctx.hex()) self.swap_out_encoding(oldenc) return commit.id