[Request] [++- ] D8567: mergestate: implement trivial in-memory mergestate
durin42 (Augie Fackler)
phabricator at mercurial-scm.org
Mon May 18 22:10:53 UTC 2020
durin42 created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.
REVISION SUMMARY
This is the dumbest possible "mergestate" implementation: it doesn't actually
handle conflict storage in the slightest, but for the current in-memory merge
cases it works great, and prevents us from accidentally touching .hg/merge
while doing non-wdir operations.
NOT DONE: this breaks tests in future changes in the series, currently getting
stuck on the "premerge()" method in the mergestate object.
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D8567
AFFECTED FILES
mercurial/mergestate.py
CHANGE DETAILS
diff --git a/mercurial/mergestate.py b/mercurial/mergestate.py
--- a/mercurial/mergestate.py
+++ b/mercurial/mergestate.py
@@ -85,7 +85,40 @@
}
-class mergestate(object):
+class _basemergestate(object):
+ def __init__(self, repo):
+ self._repo = repo
+ self._readmergedriver = None
+
+ @util.propertycache
+ def mergedriver(self):
+ # protect against the following:
+ # - A configures a malicious merge driver in their hgrc, then
+ # pauses the merge
+ # - A edits their hgrc to remove references to the merge driver
+ # - A gives a copy of their entire repo, including .hg, to B
+ # - B inspects .hgrc and finds it to be clean
+ # - B then continues the merge and the malicious merge driver
+ # gets invoked
+ configmergedriver = self._repo.ui.config(
+ b'experimental', b'mergedriver'
+ )
+ if (
+ self._readmergedriver is not None
+ and self._readmergedriver != configmergedriver
+ ):
+ raise error.ConfigError(
+ _(b"merge driver changed since merge started"),
+ hint=_(b"revert merge driver change or abort merge"),
+ )
+
+ return configmergedriver
+
+ def reset(self, node=None, other=None, labels=None):
+ self._readmergedriver = None
+
+
+class mergestate(_basemergestate):
'''track 3-way merge state of individual files
The merge state is stored on disk when needed. Two files are used: one with
@@ -154,11 +187,12 @@
"""Initialize the merge state.
Do not use this directly! Instead call read() or clean()."""
- self._repo = repo
+ super(mergestate, self).__init__(repo)
self._dirty = False
self._labels = None
def reset(self, node=None, other=None, labels=None):
+ super(mergestate, self).reset(node=node, other=other, labels=labels)
self._state = {}
self._stateextras = {}
self._local = None
@@ -170,7 +204,6 @@
if node:
self._local = node
self._other = other
- self._readmergedriver = None
if self.mergedriver:
self._mdstate = MERGE_DRIVER_STATE_SUCCESS
else:
@@ -355,30 +388,6 @@
return records
@util.propertycache
- def mergedriver(self):
- # protect against the following:
- # - A configures a malicious merge driver in their hgrc, then
- # pauses the merge
- # - A edits their hgrc to remove references to the merge driver
- # - A gives a copy of their entire repo, including .hg, to B
- # - B inspects .hgrc and finds it to be clean
- # - B then continues the merge and the malicious merge driver
- # gets invoked
- configmergedriver = self._repo.ui.config(
- b'experimental', b'mergedriver'
- )
- if (
- self._readmergedriver is not None
- and self._readmergedriver != configmergedriver
- ):
- raise error.ConfigError(
- _(b"merge driver changed since merge started"),
- hint=_(b"revert merge driver change or abort merge"),
- )
-
- return configmergedriver
-
- @util.propertycache
def local(self):
if self._local is None:
msg = b"local accessed but self._local isn't set"
@@ -857,3 +866,35 @@
repo.dirstate.copy(f0, f)
else:
repo.dirstate.normal(f)
+
+
+class memmergestate(_basemergestate):
+ def __init__(self, repo):
+ super(memmergestate, self).__init__(repo)
+ self.reset()
+
+ def add(self, fcl, fco, fca, fd):
+ """add a new (potentially?) conflicting file to the merge state"""
+ self._conflicts.add(fcl.path())
+
+ # Since memmergestate isn't mutable yet, these are all trivial
+ # implementations used by the "happy path" in merge code.
+ def reset(self, node=None, other=None, labels=None):
+ super(memmergestate, self).reset(node=node, other=other, labels=labels)
+ self._conflicts = set()
+
+ def commit(self):
+ if self._conflicts:
+ error.InMemoryMergeConflictsError(
+ 'cannot commit memmergestate with conflicts, have %d conflicts'
+ % self.unresolvedcount()
+ )
+
+ def counts(self):
+ return 0, 0, 0
+
+ def unresolvedcount(self):
+ return len(self._conflicts)
+
+ def actions(self):
+ return {}
To: durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mercurial-scm.org/pipermail/mercurial-patches/attachments/20200518/6a7d5444/attachment-0001.html>
More information about the Mercurial-patches
mailing list