changelog: support making git commits in Python

Summary: This allows writing git commits using `changelog.add`.

Reviewed By: DurhamG

Differential Revision: D33237325

fbshipit-source-id: a220a88d89410b0acb5380d3cc63cea5983f09f7
This commit is contained in:
Jun Wu 2021-12-21 12:35:00 -08:00 committed by Facebook GitHub Bot
parent 30dedd17d6
commit b3fd1d9517
2 changed files with 57 additions and 7 deletions

View File

@ -267,3 +267,48 @@ def hgcommittext(manifest, files, desc, user, date, extra):
l = [hex(manifest), user, parseddate] + sorted(files) + ["", desc]
text = encodeutf8("\n".join(l), errors="surrogateescape")
return text
def gitdatestr(datestr):
"""convert datestr to git date str used in commits"""
utc, offset = util.parsedate(datestr)
if offset >= 0:
offsetsign = "+"
else:
offsetsign = "-"
offset = -offset
offsethour = offset // 60
offsetminute = offset % 60
return "%d %s%02d%02d" % (utc, offsetsign, offsethour, offsetminute)
def gituser(userstr):
"""ensure the userstr contains '<>' for email, required by git"""
if userstr.endswith(">") and " <" in userstr:
return userstr
else:
return "%s <>" % userstr
def gitcommittext(tree, parents, desc, user, date, extra):
"""construct raw text (bytes) used by git commit"""
# Example:
# tree 97e8739f1945a4ba78c9bc1c670718c5dc5c08eb
# parent 402aab067c4f60fa8ed4868e76b54064fa06a245
# author svcscm svcscm <svcscm@fb.com> 1626293346 -0700
# committer Facebook GitHub Bot <facebook-github-bot@users.noreply.github.com> 1626293437 -0700
#
# Updating submodules
committer = extra and extra.get("committer") or user
committerdate = extra and extra.get("committer_date") or date
text = "tree %s\n%sauthor %s %s\ncommitter %s %s\n\n%s\n" % (
hex(tree),
"".join("parent %s\n" % hex(p) for p in parents),
gituser(user),
gitdatestr(date),
gituser(committer),
gitdatestr(committerdate),
stripdesc(desc),
)
text = encodeutf8(text, errors="surrogateescape")
return text

View File

@ -26,7 +26,7 @@ from . import (
visibility,
vfs as vfsmod,
)
from .changelog import changelogrevision, hgcommittext, readfiles
from .changelog import changelogrevision, hgcommittext, gitcommittext, readfiles
from .i18n import _
from .node import hex, nullid, nullrev, wdirid, wdirrev
from .pycompat import encodeutf8
@ -54,8 +54,7 @@ class changelog(object):
self.svfs = svfs
self.inner = inner
self._uiconfig = uiconfig
# Do not verify hg hash if git hash is being used.
self._verifyhghash = not git.isgit(repo)
self._isgit = git.isgit(repo)
# Number of commit texts to buffer. Useful for bounding memory usage.
self._groupbuffersize = uiconfig.configint("pull", "buffer-commit-count")
self._reporef = weakref.ref(repo)
@ -388,9 +387,14 @@ class changelog(object):
def add(
self, manifest, files, desc, transaction, p1, p2, user, date=None, extra=None
):
text = hgcommittext(manifest, files, desc, user, date, extra)
node = revlog.hash(text, p1, p2)
parents = [p for p in (p1, p2) if p != nullid]
if self._isgit:
# 'files' is not used by git
text = gitcommittext(manifest, parents, desc, user, date, extra)
node = git.hashobj(b"commit", text)
else:
text = hgcommittext(manifest, files, desc, user, date, extra)
node = revlog.hash(text, p1, p2)
# Avoid updating "tip" is node is known locally.
# Strictly speaking this should check with the remote server for lazy
@ -470,8 +474,9 @@ class changelog(object):
text = self.inner.getcommitrawtext(node)
if text is None:
raise error.LookupError(node, self.indexfile, _("no node"))
# check HG SHA1 hash
if self._verifyhghash:
# Do not verify hg hash if git hash is being used.
if not self._isgit:
# check HG SHA1 hash
p1, p2 = self.parents(node)[:2]
if revlog.hash(text, p1, p2) != node:
if (