in eden/scm/edenscm/mercurial/localrepo.py [0:0]
def commitctx(self, ctx, error=False):
"""Add a new revision to current repository.
Revision information is passed via the context argument.
"""
tr = None
p1, p2 = ctx.p1(), ctx.p2()
user = ctx.user()
descriptionlimit = self.ui.configbytes("commit", "description-size-limit")
if descriptionlimit:
descriptionlen = len(ctx.description())
if descriptionlen > descriptionlimit:
raise errormod.Abort(
_("commit message length (%s) exceeds configured limit (%s)")
% (descriptionlen, descriptionlimit)
)
extraslimit = self.ui.configbytes("commit", "extras-size-limit")
if extraslimit:
extraslen = sum(len(k) + len(v) for k, v in pycompat.iteritems(ctx.extra()))
if extraslen > extraslimit:
raise errormod.Abort(
_("commit extras total size (%s) exceeds configured limit (%s)")
% (extraslen, extraslimit)
)
isgit = git.isgitformat(self)
lock = self.lock()
try:
tr = self.transaction("commit")
trp = weakref.proxy(tr)
if ctx.manifestnode():
# reuse an existing manifest revision
mn = ctx.manifestnode()
files = ctx.files()
elif ctx.files():
m1ctx = p1.manifestctx()
m2ctx = p2.manifestctx()
mctx = m1ctx.copy()
m = mctx.read()
m1 = m1ctx.read()
m2 = m2ctx.read()
# Validate that the files that are checked in can be interpreted
# as utf8. This is to protect against potential crashes as we
# move to utf8 file paths. Changing encoding is a beast on top
# of storage format.
try:
for f in ctx.added():
if isinstance(f, bytes):
f.decode("utf-8")
except UnicodeDecodeError as inst:
raise errormod.Abort(
_("invalid file name encoding: %s!") % inst.object
)
# check in files
added = []
changed = []
removed = []
drop = []
def handleremove(f):
if f in m1 or f in m2:
removed.append(f)
if f in m:
del m[f]
drop.append(f)
for f in ctx.removed():
handleremove(f)
for f in sorted(ctx.modified() + ctx.added()):
if ctx[f] is None:
# in memctx this means removal
handleremove(f)
else:
added.append(f)
linkrev = len(self)
self.ui.note(_("committing files:\n"))
if not isgit:
# Prefetch rename data, since _filecommit will look for it.
# (git does not need this step)
if util.safehasattr(self.fileslog, "metadatastore"):
keys = []
for f in added:
fctx = ctx[f]
if fctx.filenode() is not None:
keys.append((fctx.path(), fctx.filenode()))
self.fileslog.metadatastore.prefetch(keys)
for f in added:
self.ui.note(f + "\n")
try:
fctx = ctx[f]
if isgit:
filenode = self._filecommitgit(fctx)
else:
filenode = self._filecommit(
fctx, m1, m2, linkrev, trp, changed
)
m[f] = filenode
m.setflag(f, fctx.flags())
except OSError:
self.ui.warn(_("trouble committing %s!\n") % f)
raise
except IOError as inst:
errcode = getattr(inst, "errno", errno.ENOENT)
if error or errcode and errcode != errno.ENOENT:
self.ui.warn(_("trouble committing %s!\n") % f)
raise
# update manifest
self.ui.note(_("committing manifest\n"))
removed = sorted(removed)
drop = sorted(drop)
if added or drop:
if isgit:
mn = mctx.writegit()
else:
mn = (
mctx.write(
trp,
linkrev,
p1.manifestnode(),
p2.manifestnode(),
added,
drop,
)
or p1.manifestnode()
)
else:
mn = p1.manifestnode()
files = changed + removed
else:
mn = p1.manifestnode()
files = []
# update changelog
self.ui.note(_("committing changelog\n"))
self.changelog.delayupdate(tr)
extra = ctx.extra().copy()
n = self.changelog.add(
mn,
files,
ctx.description(),
trp,
p1.node(),
p2.node(),
user,
ctx.date(),
extra,
)
xp1, xp2 = p1.hex(), p2 and p2.hex() or ""
self.hook("pretxncommit", throw=True, node=hex(n), parent1=xp1, parent2=xp2)
# set the new commit is proper phase
targetphase = phases.newcommitphase(self.ui)
if targetphase:
# retract boundary do not alter parent changeset.
# if a parent have higher the resulting phase will
# be compliant anyway
#
# if minimal phase was 0 we don't need to retract anything
phases.registernew(self, tr, targetphase, [n])
# Newly committed commits should be visible.
if targetphase > phases.public:
visibility.add(self, [n])
mutinfo = ctx.mutinfo()
if mutinfo is not None:
entry = mutation.createentry(n, mutinfo)
mutation.recordentries(self, [entry], skipexisting=False)
tr.close()
# Generate and log interesting data.
loginfo = ctx.loginfo()
path = os.path.commonprefix([os.path.dirname(p) for p in files])
if len(path) > 0:
loginfo.update({"common_directory_path": path})
diffnumber = diffprops.parserevfromcommitmsg(ctx.description())
if diffnumber is not None:
loginfo.update({"phabricator_diff_number": diffnumber})
self.ui.log("commit_info", node=hex(n), author=user, **loginfo)
return n
finally:
if tr:
tr.release()
lock.release()