in eden/scm/edenscm/mercurial/cmdutil.py [0:0]
def tryimportone(ui, repo, hunk, parents, opts, msgs, updatefunc):
"""Utility function used by commands.import to import a single patch
This function is explicitly defined here to help the evolve extension to
wrap this part of the import logic.
The API is currently a bit ugly because it a simple code translation from
the import command. Feel free to make it better.
:hunk: a patch (as a binary string)
:parents: nodes that will be parent of the created commit
:opts: the full dict of option passed to the import command
:msgs: list to save commit message to.
(used in case we need to save it when failing)
:updatefunc: a function that update a repo to a given node
updatefunc(<repo>, <node>)
"""
# avoid cycle context -> cmdutil
from . import context
extractdata = patch.extract(ui, hunk)
tmpname = extractdata.get("filename")
message = extractdata.get("message")
user = opts.get("user") or extractdata.get("user")
date = opts.get("date") or extractdata.get("date")
branch = extractdata.get("branch")
nodeid = extractdata.get("nodeid")
p1 = extractdata.get("p1")
p2 = extractdata.get("p2")
nocommit = opts.get("no_commit")
update = not opts.get("bypass")
strip = opts["strip"]
prefix = opts["prefix"]
sim = float(opts.get("similarity") or 0)
if not tmpname:
return (None, None, False)
rejects = False
try:
cmdline_message = logmessage(repo, opts)
if cmdline_message:
# pickup the cmdline msg
message = cmdline_message
elif message:
# pickup the patch msg
message = message.strip()
else:
# launch the editor
message = None
ui.debug("message:\n%s\n" % message)
if len(parents) == 1:
parents.append(repo[nullid])
if opts.get("exact"):
if not nodeid or not p1:
raise error.Abort(_("not a Mercurial patch"))
p1 = repo[p1]
p2 = repo[p2 or nullid]
elif p2:
try:
p1 = repo[p1]
p2 = repo[p2]
# Without any options, consider p2 only if the
# patch is being applied on top of the recorded
# first parent.
if p1 != parents[0]:
p1 = parents[0]
p2 = repo[nullid]
except error.RepoError:
p1, p2 = parents
if p2.node() == nullid:
ui.warn(
_(
"warning: import the patch as a normal revision\n"
"(use --exact to import the patch as a merge)\n"
)
)
else:
p1, p2 = parents
n = None
if update:
if p1 != parents[0]:
updatefunc(repo, p1.node())
if p2 != parents[1]:
repo.setparents(p1.node(), p2.node())
if opts.get("exact"):
repo.dirstate.setbranch(branch or "default")
partial = opts.get("partial", False)
files = set()
try:
patch.patch(
ui,
repo,
tmpname,
strip=strip,
prefix=prefix,
files=files,
eolmode=None,
similarity=sim / 100.0,
)
except error.PatchError as e:
if not partial:
raise error.Abort(str(e))
if partial:
rejects = True
files = list(files)
if nocommit:
if message:
msgs.append(message)
else:
if opts.get("exact") or p2:
# If you got here, you either use --force and know what
# you are doing or used --exact or a merge patch while
# being updated to its first parent.
m = None
else:
m = scmutil.matchfiles(repo, files or [])
editform = mergeeditform(repo[None], "import.normal")
if opts.get("exact"):
editor = None
else:
editor = getcommiteditor(editform=editform, **opts)
extra = {}
for idfunc in extrapreimport:
extrapreimportmap[idfunc](repo, extractdata, extra, opts)
overrides = {}
if partial:
overrides[("ui", "allowemptycommit")] = True
with repo.ui.configoverride(overrides, "import"):
n = repo.commit(
message, user, date, match=m, editor=editor, extra=extra
)
for idfunc in extrapostimport:
extrapostimportmap[idfunc](repo[n])
else:
if opts.get("exact"):
branch = branch or "default"
else:
branch = p1.branch()
store = patch.filestore()
try:
files = set()
try:
patch.patchrepo(
ui, repo, p1, store, tmpname, strip, prefix, files, eolmode=None
)
except error.PatchError as e:
raise error.Abort(str(e))
if opts.get("exact"):
editor = None
else:
editor = getcommiteditor(editform="import.bypass")
memctx = context.memctx(
repo,
(p1.node(), p2.node()),
message,
files=files,
filectxfn=store,
user=user,
date=date,
branch=branch,
editor=editor,
)
n = memctx.commit()
finally:
store.close()
if opts.get("exact") and nocommit:
# --exact with --no-commit is still useful in that it does merge
# and branch bits
ui.warn(_("warning: can't check exact import with --no-commit\n"))
elif opts.get("exact") and hex(n) != nodeid:
# Write the commit out. The "Abort" should not cancel the transaction.
# This is the behavior tested by test-import-merge.t (issue3616).
# It's a questionable behavior, though.
tr = repo.currenttransaction()
tr.close()
raise error.Abort(_("patch is damaged or loses information"))
msg = _("applied to working directory")
if n:
# i18n: refers to a short changeset id
msg = _("created %s") % short(n)
return (msg, n, rejects)
finally:
os.unlink(tmpname)