Skip to content

Commit

Permalink
merge: split update() into goto() and merge()
Browse files Browse the repository at this point in the history
Summary:
merge.update() had a lot of complicated arg checking to differentiate simple working copy updates from tricker three way merges. In particular, the eden and nativeupdate code paths only support the simple update case.

To make things clearer, let's separate update() into goto() and merge(). goto() handles the simple case, and moving it to Rust will be the (achievable) goal of some upcoming work. merge() handles the full enchilada, and isn't ripe for Rustification at this point.

Reviewed By: zzl0

Differential Revision: D49058005

fbshipit-source-id: f8106c04c48bfba0e7fad244e1dd9933142674e1
  • Loading branch information
muirdm authored and facebook-github-bot committed Oct 5, 2023
1 parent 5144e52 commit b22ca6b
Show file tree
Hide file tree
Showing 13 changed files with 178 additions and 150 deletions.
6 changes: 2 additions & 4 deletions eden/scm/sapling/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -784,13 +784,11 @@ def _dobackout(ui, repo, node=None, rev=None, **opts):
dsguard = dirstateguard.dirstateguard(repo, "backout")
try:
ui.setconfig("ui", "forcemerge", opts.get("tool", ""), "backout")
stats = mergemod.update(
repo, parent, branchmerge=True, force=True, ancestor=node
)
stats = mergemod.merge(repo, parent, force=True, ancestor=node)
repo.setparents(op1, op2)

# Ensure reverse-renames are preserved during the backout. In theory
# merge.update() should handle this, but it's extremely complex, so
# merge.merge() should handle this, but it's extremely complex, so
# let's just double check it here.
_replayrenames(repo, node)

Expand Down
16 changes: 4 additions & 12 deletions eden/scm/sapling/eden_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,18 @@
instead of doing a normal scan of the filesystem.
"""

from . import error, localrepo, merge as mergemod, progress, pycompat, util
from . import error, merge as mergemod, progress, pycompat, util
from .i18n import _


_repoclass = localrepo.localrepository


# This function is called by merge.update() in the fast path
# This function is called by merge.goto() in the fast path
# to ask the eden daemon to perform the update operation.
@util.timefunction("edenupdate", 0, "ui")
def update(
repo,
node,
branchmerge,
force,
ancestor=None,
mergeancestor=False,
force=False,
labels=None,
updatecheck=None,
wc=None,
):
repo.ui.debug("using eden update code path\n")

Expand Down Expand Up @@ -138,7 +130,7 @@ def update(
repo.dirstate.clear()
# TODO(mbolin): Set the second parent, if appropriate.
repo.setparents(destctx.node())
mergemod.recordupdates(repo, actions, branchmerge)
mergemod.recordupdates(repo, actions, False)

# Clear the update state
util.unlink(vfs.join("updatestate"))
Expand Down
2 changes: 1 addition & 1 deletion eden/scm/sapling/ext/extlib/watchmanclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ def __enter__(self):
def enter(self):
# Make sure we have a wlock prior to sending notifications to watchman.
# We don't want to race with other actors. In the update case,
# merge.update is going to take the wlock almost immediately. We are
# merge.merge/goto is going to take the wlock almost immediately. We are
# effectively extending the lock around several short sanity checks.
if self.oldnode is None:
self.oldnode = self.repo["."].node()
Expand Down
36 changes: 30 additions & 6 deletions eden/scm/sapling/ext/hgevents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@


def extsetup(ui):
extensions.wrapfunction(merge, "update", wrapupdate)
extensions.wrapfunction(merge, "goto", wrapgoto)
extensions.wrapfunction(merge, "merge", wrapmerge)
extensions.wrapfunction(filemerge, "_xmerge", _xmerge)


Expand Down Expand Up @@ -103,11 +104,10 @@ def staterelease():
# and state-leave commands. This allows clients to perform more intelligent
# settling during bulk file change scenarios
# https://facebook.github.io/watchman/docs/cmd/subscribe.html#advanced-settling
def wrapupdate(
def wrapmerge(
orig,
repo,
node,
branchmerge=False,
wc=None,
**kwargs,
):
Expand All @@ -117,7 +117,6 @@ def wrapupdate(
return orig(
repo,
node,
branchmerge=branchmerge,
wc=wc,
**kwargs,
)
Expand All @@ -132,17 +131,42 @@ def wrapupdate(
oldnode=oldnode,
newnode=newnode,
distance=distance,
metadata={"merge": branchmerge},
metadata={"merge": True},
):
return orig(
repo,
node,
branchmerge=branchmerge,
wc=wc,
**kwargs,
)


def wrapgoto(
orig,
repo,
node,
**kwargs,
):
distance = 0
oldnode = repo["."].node()
newnode = repo[node].node()
distance = watchmanclient.calcdistance(repo, oldnode, newnode)

with watchmanclient.state_update(
repo,
name="hg.update",
oldnode=oldnode,
newnode=newnode,
distance=distance,
metadata={"merge": False},
):
return orig(
repo,
node,
**kwargs,
)


def _xmerge(origfunc, repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
# _xmerge is called when an external merge tool is invoked.
with state_filemerge(repo, fcd.path()):
Expand Down
2 changes: 1 addition & 1 deletion eden/scm/sapling/ext/histedit.py
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ def run(self):
with self.repo.wlock(), self.repo.lock(), self.repo.transaction(
"histedit-base"
):
mergemod.update(self.repo, self.node, force=True)
mergemod.goto(self.repo, self.node, force=True)
return self.continueclean()

def continuedirty(self):
Expand Down
7 changes: 3 additions & 4 deletions eden/scm/sapling/ext/rebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -1709,7 +1709,7 @@ def rebasenode(repo, rev, p1, base, state, collapse, dest, wctx):
else:
if repo["."].rev() != p1:
repo.ui.debug(" update to %s\n" % (repo[p1]))
mergemod.update(repo, p1, force=True)
mergemod.goto(repo, p1, force=True)
else:
repo.ui.debug(" already in destination\n")
# This is, alas, necessary to invalidate workingctx's manifest cache,
Expand All @@ -1727,10 +1727,9 @@ def rebasenode(repo, rev, p1, base, state, collapse, dest, wctx):
labels = ["dest", "source"]
# When collapsing in-place, the parent is the common ancestor, we
# have to allow merging with it.
stats = mergemod.update(
stats = mergemod.merge(
repo,
rev,
branchmerge=True,
force=True,
ancestor=base,
mergeancestor=collapse,
Expand Down Expand Up @@ -2159,7 +2158,7 @@ def abort(repo, originalwd, destmap, state, activebookmark=None) -> int:

# Update away from the rebase if necessary
if shouldupdate or needupdate(repo, state):
mergemod.update(repo, originalwd, force=True)
mergemod.goto(repo, originalwd, force=True)

# Strip from the first rebased revision
if rebased:
Expand Down
2 changes: 1 addition & 1 deletion eden/scm/sapling/ext/reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def _moveto(repo, bookmark, ctx, clean=False):
"""
# Move working copy over
if clean:
merge.update(
merge.goto(
repo,
ctx.node(),
force=True,
Expand Down
8 changes: 4 additions & 4 deletions eden/scm/sapling/ext/sparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,22 +368,22 @@ def _calculateupdates(

extensions.wrapfunction(mergemod, "calculateupdates", _calculateupdates)

def _update(orig, repo, node, branchmerge=False, **kwargs):
def _goto(orig, repo, node, **kwargs):
try:
results = orig(repo, node, branchmerge=branchmerge, **kwargs)
results = orig(repo, node, **kwargs)
except Exception:
if _hassparse(repo):
repo._clearpendingprofileconfig()
raise

# If we're updating to a location, clean up any stale temporary includes
# (ex: this happens during hg rebase --abort).
if not branchmerge and hasattr(repo, "sparsematch"):
if hasattr(repo, "sparsematch"):
repo.prunetemporaryincludes()

return results

extensions.wrapfunction(mergemod, "update", _update)
extensions.wrapfunction(mergemod, "goto", _goto)


def _setupcommit(ui) -> None:
Expand Down
7 changes: 5 additions & 2 deletions eden/scm/sapling/ext/undo.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,12 @@ def log(orig, *args, **kwargs):
#
# To detect a write command, wrap all possible entries:
# - transaction.__init__
# - merge.update
# - merge.goto
# - merge.merge
w = extensions.wrappedfunction
with w(merge, "update", log), w(transaction.transaction, "__init__", log):
with w(merge, "goto", log), w(merge, "merge", log), w(
transaction.transaction, "__init__", log
):
try:
result = orig(lui, repo, cmd, fullargs, *args)
finally:
Expand Down
4 changes: 2 additions & 2 deletions eden/scm/sapling/hg.py
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ def updaterepo(repo, node, overwrite, updatecheck=None):
When overwrite is set, changes are clobbered, merged else
returns stats (see pydoc merge.applyupdates)"""
return mergemod.update(
return mergemod.goto(
repo,
node,
force=overwrite,
Expand Down Expand Up @@ -1009,7 +1009,7 @@ def updatetotally(
def merge(repo, node, force=False, remind: bool = True, labels=None):
"""Branch merge with node, resolving changes. Return true if any
unresolved conflicts."""
stats = mergemod.update(repo, node, branchmerge=True, force=force, labels=labels)
stats = mergemod.merge(repo, node, force=force, labels=labels)
_showstats(repo, stats)
if stats[3]:
repo.ui.status(
Expand Down
Loading

0 comments on commit b22ca6b

Please sign in to comment.