Changeset View
Changeset View
Standalone View
Standalone View
mercurial/merge.py
Show First 20 Lines • Show All 349 Lines • ▼ Show 20 Line(s) | for fold, f in sorted(foldmap.items()): | ||||
_(b"case-folding collision between %s and directory of %s") | _(b"case-folding collision between %s and directory of %s") | ||||
% (lastfull, f) | % (lastfull, f) | ||||
) | ) | ||||
foldprefix = fold + b'/' | foldprefix = fold + b'/' | ||||
unfoldprefix = f + b'/' | unfoldprefix = f + b'/' | ||||
lastfull = f | lastfull = f | ||||
def driverpreprocess(repo, ms, wctx, labels=None): | |||||
"""run the preprocess step of the merge driver, if any | |||||
This is currently not implemented -- it's an extension point.""" | |||||
return True | |||||
def driverconclude(repo, ms, wctx, labels=None): | |||||
"""run the conclude step of the merge driver, if any | |||||
This is currently not implemented -- it's an extension point.""" | |||||
return True | |||||
def _filesindirs(repo, manifest, dirs): | def _filesindirs(repo, manifest, dirs): | ||||
""" | """ | ||||
Generator that yields pairs of all the files in the manifest that are found | Generator that yields pairs of all the files in the manifest that are found | ||||
inside the directories listed in dirs, and which directory they are found | inside the directories listed in dirs, and which directory they are found | ||||
in. | in. | ||||
""" | """ | ||||
for f in manifest: | for f in manifest: | ||||
for p in pathutil.finddirs(f): | for p in pathutil.finddirs(f): | ||||
▲ Show 20 Lines • Show All 1220 Lines • ▼ Show 20 Line(s) | ): | ||||
updated = mresult.len( | updated = mresult.len( | ||||
( | ( | ||||
mergestatemod.ACTION_GET, | mergestatemod.ACTION_GET, | ||||
mergestatemod.ACTION_EXEC, | mergestatemod.ACTION_EXEC, | ||||
mergestatemod.ACTION_LOCAL_DIR_RENAME_GET, | mergestatemod.ACTION_LOCAL_DIR_RENAME_GET, | ||||
mergestatemod.ACTION_DIR_RENAME_MOVE_LOCAL, | mergestatemod.ACTION_DIR_RENAME_MOVE_LOCAL, | ||||
) | ) | ||||
) | ) | ||||
# the ordering is important here -- ms.mergedriver will raise if the merge | |||||
# driver has changed, and we want to be able to bypass it when overwrite is | |||||
# True | |||||
usemergedriver = not overwrite and mergeactions and ms.mergedriver | |||||
if usemergedriver: | |||||
ms.commit() | |||||
proceed = driverpreprocess(repo, ms, wctx, labels=labels) | |||||
# the driver might leave some files unresolved | |||||
unresolvedf = set(ms.unresolved()) | |||||
if not proceed: | |||||
# XXX setting unresolved to at least 1 is a hack to make sure we | |||||
# error out | |||||
return updateresult( | |||||
updated, merged, removed, max(len(unresolvedf), 1) | |||||
) | |||||
newactions = [] | |||||
for f, args, msg in mergeactions: | |||||
if f in unresolvedf: | |||||
newactions.append((f, args, msg)) | |||||
mergeactions = newactions | |||||
try: | try: | ||||
# premerge | # premerge | ||||
tocomplete = [] | tocomplete = [] | ||||
for f, args, msg in mergeactions: | for f, args, msg in mergeactions: | ||||
repo.ui.debug(b" %s: %s -> m (premerge)\n" % (f, msg)) | repo.ui.debug(b" %s: %s -> m (premerge)\n" % (f, msg)) | ||||
progress.increment(item=f) | progress.increment(item=f) | ||||
if f == b'.hgsubstate': # subrepo states need updating | if f == b'.hgsubstate': # subrepo states need updating | ||||
Show All 13 Lines | try: | ||||
progress.increment(item=f, total=numupdates) | progress.increment(item=f, total=numupdates) | ||||
ms.resolve(f, wctx) | ms.resolve(f, wctx) | ||||
finally: | finally: | ||||
ms.commit() | ms.commit() | ||||
unresolved = ms.unresolvedcount() | unresolved = ms.unresolvedcount() | ||||
if ( | |||||
usemergedriver | |||||
and not unresolved | |||||
and ms.mdstate() != mergestatemod.MERGE_DRIVER_STATE_SUCCESS | |||||
): | |||||
if not driverconclude(repo, ms, wctx, labels=labels): | |||||
# XXX setting unresolved to at least 1 is a hack to make sure we | |||||
# error out | |||||
unresolved = max(unresolved, 1) | |||||
ms.commit() | |||||
msupdated, msmerged, msremoved = ms.counts() | msupdated, msmerged, msremoved = ms.counts() | ||||
updated += msupdated | updated += msupdated | ||||
merged += msmerged | merged += msmerged | ||||
removed += msremoved | removed += msremoved | ||||
extraactions = ms.actions() | extraactions = ms.actions() | ||||
if extraactions: | if extraactions: | ||||
mfiles = { | |||||
a[0] for a in mresult.getactions((mergestatemod.ACTION_MERGE,)) | |||||
} | |||||
for k, acts in pycompat.iteritems(extraactions): | for k, acts in pycompat.iteritems(extraactions): | ||||
for a in acts: | for a in acts: | ||||
mresult.addfile(a[0], k, *a[1:]) | mresult.addfile(a[0], k, *a[1:]) | ||||
if k == mergestatemod.ACTION_GET and wantfiledata: | if k == mergestatemod.ACTION_GET and wantfiledata: | ||||
# no filedata until mergestate is updated to provide it | # no filedata until mergestate is updated to provide it | ||||
for a in acts: | for a in acts: | ||||
getfiledata[a[0]] = None | getfiledata[a[0]] = None | ||||
# Remove these files from actions[ACTION_MERGE] as well. This is | |||||
# important because in recordupdates, files in actions[ACTION_MERGE] | |||||
# are processed after files in other actions, and the merge driver | |||||
# might add files to those actions via extraactions above. This can | |||||
# lead to a file being recorded twice, with poor results. This is | |||||
# especially problematic for actions[ACTION_REMOVE] (currently only | |||||
# possible with the merge driver in the initial merge process; | |||||
# interrupted merges don't go through this flow). | |||||
# | |||||
# The real fix here is to have indexes by both file and action so | |||||
# that when the action for a file is changed it is automatically | |||||
# reflected in the other action lists. But that involves a more | |||||
# complex data structure, so this will do for now. | |||||
# | |||||
# We don't need to do the same operation for 'dc' and 'cd' because | |||||
# those lists aren't consulted again. | |||||
mfiles.difference_update(a[0] for a in acts) | |||||
for a in list(mresult.getactions((mergestatemod.ACTION_MERGE,))): | |||||
if a[0] not in mfiles: | |||||
mresult.removefile(a[0]) | |||||
progress.complete() | progress.complete() | ||||
assert len(getfiledata) == ( | assert len(getfiledata) == ( | ||||
mresult.len((mergestatemod.ACTION_GET,)) if wantfiledata else 0 | mresult.len((mergestatemod.ACTION_GET,)) if wantfiledata else 0 | ||||
) | ) | ||||
return updateresult(updated, merged, removed, unresolved), getfiledata | return updateresult(updated, merged, removed, unresolved), getfiledata | ||||
▲ Show 20 Lines • Show All 598 Lines • Show Last 20 Lines |