##// END OF EJS Templates
rust-status: use bare hg status fastpath from Python...
rust-status: use bare hg status fastpath from Python This change also adds a test case for subrepos. Repeating the benchmark information from the `hg-core` commit: On the Netbeans repository: C: 840ms Rust+C: 556ms Mozilla Central with the one pattern that causes a fallback removed: C: 2.315s Rust+C: 1.700s Differential Revision: https://phab.mercurial-scm.org/D7931

File last commit:

r44937:9d2b2df2 default
r45017:4d1634e5 default
Show More
merge.py
2787 lines | 97.7 KiB | text/x-python | PythonLexer
Matt Mackall
Move merge code to its own module...
r2775 # merge.py - directory-level update/merge handling for Mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
Matt Mackall
Move merge code to its own module...
r2775 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
Move merge code to its own module...
r2775
Gregory Szorc
merge: use absolute_import
r25959 from __future__ import absolute_import
import errno
import shutil
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 import stat
Pierre-Yves David
merge: introduce new format for the state file...
r20590 import struct
Gregory Szorc
merge: use absolute_import
r25959 from .i18n import _
from .node import (
Durham Goode
dirstate: change added/modified placeholder hash length to 20 bytes...
r30361 addednodeid,
Gregory Szorc
merge: use absolute_import
r25959 bin,
hex,
Durham Goode
merge: change modified indicator to be 20 bytes...
r30362 modifiednodeid,
Siddharth Agarwal
mergestate: allow storing and retrieving change/delete conflicts...
r27031 nullhex,
Gregory Szorc
merge: use absolute_import
r25959 nullid,
nullrev,
)
Gregory Szorc
py3: manually import pycompat.delattr where it is needed...
r43360 from .pycompat import delattr
Augie Fackler
formatting: blacken the codebase...
r43346 from .thirdparty import attr
Gregory Szorc
merge: use absolute_import
r25959 from . import (
copies,
Matt Harbison
py3: rename pycompat.getcwd() to encoding.getcwd() (API)...
r39843 encoding,
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 error,
Gregory Szorc
merge: use absolute_import
r25959 filemerge,
Durham Goode
merge: remove uses of manifest.matches...
r31257 match as matchmod,
obsutil: move 'foreground' to the new modules...
r33147 obsutil,
Martin von Zweigbergk
utils: move finddirs() to pathutil...
r44032 pathutil,
Pulkit Goyal
py3: use pycompat.getcwd() instead of os.getcwd()...
r30519 pycompat,
Siddharth Agarwal
batchget: add support for backing up files...
r27656 scmutil,
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 subrepoutil,
Gregory Szorc
merge: use absolute_import
r25959 util,
worker,
)
Augie Fackler
core: migrate uses of hashlib.sha1 to hashutil.sha1...
r44517 from .utils import hashutil
Matt Mackall
merge: introduce mergestate
r6512
Pierre-Yves David
merge: introduce new format for the state file...
r20590 _pack = struct.pack
_unpack = struct.unpack
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
merge: add "other" file node in the merge state file...
r20593 def _droponode(data):
# used for compatibility for v1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bits = data.split(b'\0')
Pierre-Yves David
merge: add "other" file node in the merge state file...
r20593 bits = bits[:-2] + bits[-1:]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'\0'.join(bits)
Pierre-Yves David
merge: add "other" file node in the merge state file...
r20593
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
merge: use constants for merge state record types...
r37127 # Merge state record types. See ``mergestate`` docs for more.
RECORD_LOCAL = b'L'
RECORD_OTHER = b'O'
RECORD_MERGED = b'F'
RECORD_CHANGEDELETE_CONFLICT = b'C'
RECORD_MERGE_DRIVER_MERGE = b'D'
RECORD_PATH_CONFLICT = b'P'
RECORD_MERGE_DRIVER_STATE = b'm'
RECORD_FILE_VALUES = b'f'
RECORD_LABELS = b'l'
RECORD_OVERRIDE = b't'
RECORD_UNSUPPORTED_MANDATORY = b'X'
RECORD_UNSUPPORTED_ADVISORY = b'x'
Gregory Szorc
merge: use constants for merge driver state...
r37128 MERGE_DRIVER_STATE_UNMARKED = b'u'
MERGE_DRIVER_STATE_MARKED = b'm'
MERGE_DRIVER_STATE_SUCCESS = b's'
Gregory Szorc
merge: use constants for merge record state...
r37129 MERGE_RECORD_UNRESOLVED = b'u'
MERGE_RECORD_RESOLVED = b'r'
MERGE_RECORD_UNRESOLVED_PATH = b'pu'
MERGE_RECORD_RESOLVED_PATH = b'pr'
MERGE_RECORD_DRIVER_RESOLVED = b'd'
Gregory Szorc
merge: use constants for actions...
r37130 ACTION_FORGET = b'f'
ACTION_REMOVE = b'r'
ACTION_ADD = b'a'
ACTION_GET = b'g'
ACTION_PATH_CONFLICT = b'p'
ACTION_PATH_CONFLICT_RESOLVE = b'pr'
ACTION_ADD_MODIFIED = b'am'
ACTION_CREATED = b'c'
ACTION_DELETED_CHANGED = b'dc'
ACTION_CHANGED_DELETED = b'cd'
ACTION_MERGE = b'm'
ACTION_LOCAL_DIR_RENAME_GET = b'dg'
ACTION_DIR_RENAME_MOVE_LOCAL = b'dm'
ACTION_KEEP = b'k'
ACTION_EXEC = b'e'
ACTION_CREATED_MERGE = b'cm'
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
merge: introduce mergestate
r6512 class mergestate(object):
Pierre-Yves David
merge: introduce new format for the state file...
r20590 '''track 3-way merge state of individual files
Siddharth Agarwal
mergestate: move binary format documentation into _readrecordsv2...
r27022 The merge state is stored on disk when needed. Two files are used: one with
an old format (version 1), and one with a new format (version 2). Version 2
stores a superset of the data in version 1, including new kinds of records
in the future. For more about the new format, see the documentation for
`_readrecordsv2`.
Pierre-Yves David
merge: introduce new format for the state file...
r20590
Siddharth Agarwal
mergestate: move binary format documentation into _readrecordsv2...
r27022 Each record can contain arbitrary content, and has an associated type. This
`type` should be a letter. If `type` is uppercase, the record is mandatory:
versions of Mercurial that don't support it should abort. If `type` is
lowercase, the record can be safely ignored.
Pierre-Yves David
merge: introduce new format for the state file...
r20590
Siddharth Agarwal
mergestate: move binary format documentation into _readrecordsv2...
r27022 Currently known records:
Pierre-Yves David
merge: introduce new format for the state file...
r20590
L: the node of the "local" part of the merge (hexified version)
Pierre-Yves David
merge: record the "other" node in merge state...
r20591 O: the node of the "other" part of the merge (hexified version)
Pierre-Yves David
merge: introduce new format for the state file...
r20590 F: a file to be merged entry
Siddharth Agarwal
mergestate: allow storing and retrieving change/delete conflicts...
r27031 C: a change/delete or delete/change conflict
Siddharth Agarwal
merge.mergestate: add support for persisting driver-resolved files...
r26650 D: a file that the external merge driver will merge internally
(experimental)
Mark Thomas
merge: add pathconflict merge state...
r34546 P: a path conflict (file vs directory)
Siddharth Agarwal
merge.mergestate: add support for persisting a custom merge driver...
r26649 m: the external merge driver defined for this merge plus its run state
(experimental)
Mads Kiilerich
spelling: fixes of non-dictionary words
r30332 f: a (filename, dictionary) tuple of optional values for a given file
Siddharth Agarwal
mergestate: handle additional record types specially...
r27027 X: unsupported mandatory record type (used in tests)
x: unsupported advisory record type (used in tests)
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 l: the labels for the parts of the merge.
Siddharth Agarwal
merge.mergestate: add support for persisting a custom merge driver...
r26649
Merge driver run states (experimental):
u: driver-resolved files unmarked -- needs to be run next time we're about
to resolve or commit
m: driver-resolved files marked -- only needs to be run before commit
s: success/skipped -- does not need to be run any more
Siddharth Agarwal
mergestate: move binary format documentation into _readrecordsv2...
r27022
Mark Thomas
merge: add pathconflict merge state...
r34546 Merge record states (stored in self._state, indexed by filename):
u: unresolved conflict
r: resolved conflict
pu: unresolved path conflict (file conflicts with directory)
pr: resolved path conflict
d: driver-resolved conflict
The resolve command transitions between 'u' and 'r' for conflicts and
'pu' and 'pr' for path conflicts.
Pierre-Yves David
merge: introduce new format for the state file...
r20590 '''
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 statepathv1 = b'merge/state'
statepathv2 = b'merge/state2'
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Siddharth Agarwal
mergestate: add a constructor that sets up a clean merge state...
r26987 @staticmethod
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 def clean(repo, node=None, other=None, labels=None):
Siddharth Agarwal
mergestate: add a constructor that sets up a clean merge state...
r26987 """Initialize a brand new merge state, removing any existing state on
disk."""
ms = mergestate(repo)
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 ms.reset(node, other, labels)
Siddharth Agarwal
mergestate: add a constructor that sets up a clean merge state...
r26987 return ms
Siddharth Agarwal
mergestate: add a constructor that reads state from disk...
r26991 @staticmethod
def read(repo):
"""Initialize the merge state, reading it from disk."""
ms = mergestate(repo)
Siddharth Agarwal
mergestate: move _read() call to read constructor...
r27005 ms._read()
Siddharth Agarwal
mergestate: add a constructor that reads state from disk...
r26991 return ms
Matt Mackall
merge: introduce mergestate
r6512 def __init__(self, repo):
Siddharth Agarwal
mergestate: move _read() call to read constructor...
r27005 """Initialize the merge state.
Do not use this directly! Instead call read() or clean()."""
Matt Mackall
merge: introduce mergestate
r6512 self._repo = repo
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = False
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 self._labels = None
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 def reset(self, node=None, other=None, labels=None):
Matt Mackall
merge: introduce mergestate
r6512 self._state = {}
Durham Goode
merge: add state extras merge state data...
r28009 self._stateextras = {}
Gregory Szorc
mergestate: consistently set variables to None...
r21261 self._local = None
self._other = None
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 self._labels = labels
Martin von Zweigbergk
py3: don't use bytes with vars() or __dict__...
r43744 for var in ('localctx', 'otherctx'):
Siddharth Agarwal
mergestate: add a cached property accessor for the local context...
r27130 if var in vars(self):
delattr(self, var)
Matt Mackall
resolve: move reset to localrepo.commit...
r7848 if node:
self._local = node
Pierre-Yves David
merge: record the "other" node in merge state...
r20591 self._other = other
Siddharth Agarwal
merge.mergestate: only check for merge driver when property is accessed...
r26768 self._readmergedriver = None
Siddharth Agarwal
merge.mergestate: set merge driver state to 's' if there's none present...
r26769 if self.mergedriver:
Gregory Szorc
merge: use constants for merge driver state...
r37128 self._mdstate = MERGE_DRIVER_STATE_SUCCESS
Siddharth Agarwal
merge.mergestate: set merge driver state to 's' if there's none present...
r26769 else:
Gregory Szorc
merge: use constants for merge driver state...
r37128 self._mdstate = MERGE_DRIVER_STATE_UNMARKED
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shutil.rmtree(self._repo.vfs.join(b'merge'), True)
Siddharth Agarwal
mergestate._resolve: store return code and action for each file...
r27074 self._results = {}
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = False
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Matt Mackall
resolve: new command...
r6518 def _read(self):
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 """Analyse each record content to restore a serialized state from disk
This function process "record" entry produced by the de-serialization
of on disk file.
"""
Matt Mackall
resolve: new command...
r6518 self._state = {}
Durham Goode
merge: add state extras merge state data...
r28009 self._stateextras = {}
Gregory Szorc
mergestate: consistently set variables to None...
r21261 self._local = None
self._other = None
Martin von Zweigbergk
py3: don't use bytes with vars() or __dict__...
r43744 for var in ('localctx', 'otherctx'):
Siddharth Agarwal
mergestate: add a cached property accessor for the local context...
r27130 if var in vars(self):
delattr(self, var)
Siddharth Agarwal
merge.mergestate: only check for merge driver when property is accessed...
r26768 self._readmergedriver = None
Gregory Szorc
merge: use constants for merge driver state...
r37128 self._mdstate = MERGE_DRIVER_STATE_SUCCESS
Siddharth Agarwal
mergestate: raise structured exception for unsupported merge records...
r26986 unsupported = set()
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 records = self._readrecords()
for rtype, record in records:
Gregory Szorc
merge: use constants for merge state record types...
r37127 if rtype == RECORD_LOCAL:
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 self._local = bin(record)
Gregory Szorc
merge: use constants for merge state record types...
r37127 elif rtype == RECORD_OTHER:
Pierre-Yves David
merge: record the "other" node in merge state...
r20591 self._other = bin(record)
Gregory Szorc
merge: use constants for merge state record types...
r37127 elif rtype == RECORD_MERGE_DRIVER_STATE:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bits = record.split(b'\0', 1)
Siddharth Agarwal
merge.mergestate: add support for persisting a custom merge driver...
r26649 mdstate = bits[1]
Gregory Szorc
merge: use constants for merge driver state...
r37128 if len(mdstate) != 1 or mdstate not in (
Augie Fackler
formatting: blacken the codebase...
r43346 MERGE_DRIVER_STATE_UNMARKED,
MERGE_DRIVER_STATE_MARKED,
MERGE_DRIVER_STATE_SUCCESS,
):
Siddharth Agarwal
merge.mergestate: add support for persisting a custom merge driver...
r26649 # the merge driver should be idempotent, so just rerun it
Gregory Szorc
merge: use constants for merge driver state...
r37128 mdstate = MERGE_DRIVER_STATE_UNMARKED
Siddharth Agarwal
merge.mergestate: add support for persisting a custom merge driver...
r26649
Siddharth Agarwal
merge.mergestate: only check for merge driver when property is accessed...
r26768 self._readmergedriver = bits[0]
Siddharth Agarwal
merge.mergestate: add support for persisting a custom merge driver...
r26649 self._mdstate = mdstate
Augie Fackler
formatting: blacken the codebase...
r43346 elif rtype in (
RECORD_MERGED,
RECORD_CHANGEDELETE_CONFLICT,
RECORD_PATH_CONFLICT,
RECORD_MERGE_DRIVER_MERGE,
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bits = record.split(b'\0')
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 self._state[bits[0]] = bits[1:]
Gregory Szorc
merge: use constants for merge state record types...
r37127 elif rtype == RECORD_FILE_VALUES:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 filename, rawextras = record.split(b'\0', 1)
extraparts = rawextras.split(b'\0')
Durham Goode
merge: add state extras merge state data...
r28009 extras = {}
i = 0
while i < len(extraparts):
extras[extraparts[i]] = extraparts[i + 1]
i += 2
self._stateextras[filename] = extras
Gregory Szorc
merge: use constants for merge state record types...
r37127 elif rtype == RECORD_LABELS:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 labels = record.split(b'\0', 2)
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 self._labels = [l for l in labels if len(l) > 0]
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 elif not rtype.islower():
Siddharth Agarwal
mergestate: raise structured exception for unsupported merge records...
r26986 unsupported.add(rtype)
Siddharth Agarwal
mergestate._resolve: store return code and action for each file...
r27074 self._results = {}
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 self._dirty = False
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Siddharth Agarwal
mergestate: raise structured exception for unsupported merge records...
r26986 if unsupported:
raise error.UnsupportedMergeRecords(unsupported)
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 def _readrecords(self):
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 """Read merge state from disk and return a list of record (TYPE, data)
Mads Kiilerich
spelling: fixes from spell checker
r21024 We read data from both v1 and v2 files and decide which one to use.
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652
Mads Kiilerich
spelling: fixes from spell checker
r21024 V1 has been used by version prior to 2.9.1 and contains less data than
v2. We read both versions and check if no data in v2 contradicts
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 v1. If there is not contradiction we can safely assume that both v1
and v2 were written at the same time and use the extract data in v2. If
there is contradiction we ignore v2 content as we assume an old version
Mads Kiilerich
spelling: fixes from spell checker
r21024 of Mercurial has overwritten the mergestate file and left an old v2
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 file around.
returns list of record [(TYPE, data), ...]"""
Pierre-Yves David
merge: introduce new format for the state file...
r20590 v1records = self._readrecordsv1()
v2records = self._readrecordsv2()
Siddharth Agarwal
merge.mergestate: factor out code to validate v1/v2 records...
r26500 if self._v1v2match(v1records, v2records):
return v2records
else:
# v1 file is newer than v2 file, use it
# we have to infer the "other" changeset of the merge
# we cannot do better than that with v1 of the format
mctx = self._repo[None].parents()[-1]
Gregory Szorc
merge: use constants for merge state record types...
r37127 v1records.append((RECORD_OTHER, mctx.hex()))
Siddharth Agarwal
merge.mergestate: factor out code to validate v1/v2 records...
r26500 # add place holder "other" file node information
# nobody is using it yet so we do no need to fetch the data
# if mctx was wrong `mctx[bits[-2]]` may fails.
for idx, r in enumerate(v1records):
Gregory Szorc
merge: use constants for merge state record types...
r37127 if r[0] == RECORD_MERGED:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bits = r[1].split(b'\0')
bits.insert(-2, b'')
v1records[idx] = (r[0], b'\0'.join(bits))
Siddharth Agarwal
merge.mergestate: factor out code to validate v1/v2 records...
r26500 return v1records
def _v1v2match(self, v1records, v2records):
Augie Fackler
formatting: blacken the codebase...
r43346 oldv2 = set() # old format version of v2 record
Pierre-Yves David
merge: add "other" file node in the merge state file...
r20593 for rec in v2records:
Gregory Szorc
merge: use constants for merge state record types...
r37127 if rec[0] == RECORD_LOCAL:
Pierre-Yves David
merge: add "other" file node in the merge state file...
r20593 oldv2.add(rec)
Gregory Szorc
merge: use constants for merge state record types...
r37127 elif rec[0] == RECORD_MERGED:
Pierre-Yves David
merge: add "other" file node in the merge state file...
r20593 # drop the onode data (not contained in v1)
Gregory Szorc
merge: use constants for merge state record types...
r37127 oldv2.add((RECORD_MERGED, _droponode(rec[1])))
Pierre-Yves David
merge: add "other" file node in the merge state file...
r20593 for rec in v1records:
if rec not in oldv2:
Siddharth Agarwal
merge.mergestate: factor out code to validate v1/v2 records...
r26500 return False
Pierre-Yves David
merge: introduce new format for the state file...
r20590 else:
Siddharth Agarwal
merge.mergestate: factor out code to validate v1/v2 records...
r26500 return True
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Pierre-Yves David
merge: introduce new format for the state file...
r20590 def _readrecordsv1(self):
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 """read on disk merge state for version 1 file
returns list of record [(TYPE, data), ...]
Note: the "F" data from this file are one entry short
(no "other file node" entry)
"""
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 records = []
Matt Mackall
resolve: new command...
r6518 try:
Angel Ezquerra
localrepo: remove all external users of localrepo.opener...
r23877 f = self._repo.vfs(self.statepathv1)
Patrick Mezard
merge: replace readline() call, missing from posixfile_nt
r6530 for i, l in enumerate(f):
if i == 0:
Gregory Szorc
merge: use constants for merge state record types...
r37127 records.append((RECORD_LOCAL, l[:-1]))
Patrick Mezard
merge: replace readline() call, missing from posixfile_nt
r6530 else:
Gregory Szorc
merge: use constants for merge state record types...
r37127 records.append((RECORD_MERGED, l[:-1]))
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 f.close()
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as err:
Matt Mackall
resolve: new command...
r6518 if err.errno != errno.ENOENT:
raise
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 return records
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Pierre-Yves David
merge: introduce new format for the state file...
r20590 def _readrecordsv2(self):
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 """read on disk merge state for version 2 file
Siddharth Agarwal
mergestate: move binary format documentation into _readrecordsv2...
r27022 This format is a list of arbitrary records of the form:
[type][length][content]
`type` is a single character, `length` is a 4 byte integer, and
`content` is an arbitrary byte sequence of length `length`.
Siddharth Agarwal
mergestate: handle additional record types specially...
r27027 Mercurial versions prior to 3.7 have a bug where if there are
unsupported mandatory merge records, attempting to clear out the merge
state with hg update --clean or similar aborts. The 't' record type
works around that by writing out what those versions treat as an
advisory record, but later versions interpret as special: the first
character is the 'real' record type and everything onwards is the data.
Siddharth Agarwal
mergestate: move binary format documentation into _readrecordsv2...
r27022 Returns list of records [(TYPE, data), ...]."""
Pierre-Yves David
merge: introduce new format for the state file...
r20590 records = []
try:
Angel Ezquerra
localrepo: remove all external users of localrepo.opener...
r23877 f = self._repo.vfs(self.statepathv2)
Pierre-Yves David
merge: introduce new format for the state file...
r20590 data = f.read()
off = 0
end = len(data)
while off < end:
Augie Fackler
formatting: blacken the codebase...
r43346 rtype = data[off : off + 1]
Pierre-Yves David
merge: introduce new format for the state file...
r20590 off += 1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 length = _unpack(b'>I', data[off : (off + 4)])[0]
Pierre-Yves David
merge: introduce new format for the state file...
r20590 off += 4
Augie Fackler
formatting: blacken the codebase...
r43346 record = data[off : (off + length)]
Olle Lundberg
merge: fix spelling of length
r20607 off += length
Gregory Szorc
merge: use constants for merge state record types...
r37127 if rtype == RECORD_OVERRIDE:
Pulkit Goyal
py3: slice over bytes to prevent getting ascii values...
r36554 rtype, record = record[0:1], record[1:]
Pierre-Yves David
merge: introduce new format for the state file...
r20590 records.append((rtype, record))
f.close()
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as err:
Pierre-Yves David
merge: introduce new format for the state file...
r20590 if err.errno != errno.ENOENT:
raise
return records
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Siddharth Agarwal
merge.mergestate: add support for persisting a custom merge driver...
r26649 @util.propertycache
def mergedriver(self):
Siddharth Agarwal
merge.mergestate: only check for merge driver when property is accessed...
r26768 # 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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 configmergedriver = self._repo.ui.config(
b'experimental', b'mergedriver'
)
Augie Fackler
formatting: blacken the codebase...
r43346 if (
self._readmergedriver is not None
and self._readmergedriver != configmergedriver
):
Siddharth Agarwal
merge.mergestate: only check for merge driver when property is accessed...
r26768 raise error.ConfigError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"merge driver changed since merge started"),
hint=_(b"revert merge driver change or abort merge"),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Siddharth Agarwal
merge.mergestate: only check for merge driver when property is accessed...
r26768
return configmergedriver
Siddharth Agarwal
merge.mergestate: add a way to get the other side of the merge...
r26765 @util.propertycache
Martin von Zweigbergk
mergestate: add accessors for local and other nodeid, not just contexts...
r44696 def local(self):
Siddharth Agarwal
mergestate: add a cached property accessor for the local context...
r27130 if self._local is None:
Martin von Zweigbergk
mergestate: add accessors for local and other nodeid, not just contexts...
r44696 msg = b"local accessed but self._local isn't set"
Jun Wu
merge: use ProgrammingError
r31646 raise error.ProgrammingError(msg)
Martin von Zweigbergk
mergestate: add accessors for local and other nodeid, not just contexts...
r44696 return self._local
@util.propertycache
def localctx(self):
return self._repo[self.local]
@util.propertycache
def other(self):
if self._other is None:
msg = b"other accessed but self._other isn't set"
raise error.ProgrammingError(msg)
return self._other
Siddharth Agarwal
mergestate: add a cached property accessor for the local context...
r27130
@util.propertycache
Siddharth Agarwal
merge.mergestate: add a way to get the other side of the merge...
r26765 def otherctx(self):
Martin von Zweigbergk
mergestate: add accessors for local and other nodeid, not just contexts...
r44696 return self._repo[self.other]
Siddharth Agarwal
merge.mergestate: add support for persisting a custom merge driver...
r26649
Gregory Szorc
resolve: abort when not applicable (BC)...
r21264 def active(self):
"""Whether mergestate is active.
Returns True if there appears to be mergestate. This is a rough proxy
for "is a merge in progress."
"""
Martin von Zweigbergk
mergestate: determine if active without looking for state files on disk...
r44878 return bool(self._local) or bool(self._state)
Gregory Szorc
resolve: abort when not applicable (BC)...
r21264
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 def commit(self):
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 """Write current state on disk (if necessary)"""
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 if self._dirty:
Siddharth Agarwal
mergestate.commit: factor out making the list of records...
r27006 records = self._makerecords()
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 self._writerecords(records)
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = False
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Siddharth Agarwal
mergestate.commit: factor out making the list of records...
r27006 def _makerecords(self):
records = []
Gregory Szorc
merge: use constants for merge state record types...
r37127 records.append((RECORD_LOCAL, hex(self._local)))
records.append((RECORD_OTHER, hex(self._other)))
Siddharth Agarwal
mergestate.commit: factor out making the list of records...
r27006 if self.mergedriver:
Augie Fackler
formatting: blacken the codebase...
r43346 records.append(
(
RECORD_MERGE_DRIVER_STATE,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'\0'.join([self.mergedriver, self._mdstate]),
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Mark Thomas
merge: improve comments in mergestate._makerecords...
r34561 # Write out state items. In all cases, the value of the state map entry
# is written as the contents of the record. The record type depends on
# the type of state that is stored, and capital-letter records are used
# to prevent older versions of Mercurial that do not support the feature
# from loading them.
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for filename, v in pycompat.iteritems(self._state):
Gregory Szorc
merge: use constants for merge record state...
r37129 if v[0] == MERGE_RECORD_DRIVER_RESOLVED:
Mark Thomas
merge: improve comments in mergestate._makerecords...
r34561 # Driver-resolved merge. These are stored in 'D' records.
Augie Fackler
formatting: blacken the codebase...
r43346 records.append(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (RECORD_MERGE_DRIVER_MERGE, b'\0'.join([filename] + v))
Augie Fackler
formatting: blacken the codebase...
r43346 )
elif v[0] in (
MERGE_RECORD_UNRESOLVED_PATH,
MERGE_RECORD_RESOLVED_PATH,
):
Mark Thomas
merge: improve comments in mergestate._makerecords...
r34561 # Path conflicts. These are stored in 'P' records. The current
# resolution state ('pu' or 'pr') is stored within the record.
Augie Fackler
formatting: blacken the codebase...
r43346 records.append(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (RECORD_PATH_CONFLICT, b'\0'.join([filename] + v))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Siddharth Agarwal
mergestate: allow storing and retrieving change/delete conflicts...
r27031 elif v[1] == nullhex or v[6] == nullhex:
Mark Thomas
merge: improve comments in mergestate._makerecords...
r34561 # Change/Delete or Delete/Change conflicts. These are stored in
# 'C' records. v[1] is the local file, and is nullhex when the
# file is deleted locally ('dc'). v[6] is the remote file, and
# is nullhex when the file is deleted remotely ('cd').
Augie Fackler
formatting: blacken the codebase...
r43346 records.append(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (RECORD_CHANGEDELETE_CONFLICT, b'\0'.join([filename] + v))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Siddharth Agarwal
mergestate.commit: factor out making the list of records...
r27006 else:
Mark Thomas
merge: improve comments in mergestate._makerecords...
r34561 # Normal files. These are stored in 'F' records.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 records.append((RECORD_MERGED, b'\0'.join([filename] + v)))
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for filename, extras in sorted(pycompat.iteritems(self._stateextras)):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rawextras = b'\0'.join(
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 b'%s\0%s' % (k, v) for k, v in pycompat.iteritems(extras)
Augie Fackler
formatting: blacken the codebase...
r43346 )
records.append(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (RECORD_FILE_VALUES, b'%s\0%s' % (filename, rawextras))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 if self._labels is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 labels = b'\0'.join(self._labels)
Gregory Szorc
merge: use constants for merge state record types...
r37127 records.append((RECORD_LABELS, labels))
Siddharth Agarwal
mergestate.commit: factor out making the list of records...
r27006 return records
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 def _writerecords(self, records):
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 """Write current state on disk (both v1 and v2)"""
Pierre-Yves David
merge: introduce new format for the state file...
r20590 self._writerecordsv1(records)
self._writerecordsv2(records)
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Pierre-Yves David
merge: introduce new format for the state file...
r20590 def _writerecordsv1(self, records):
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 """Write current state on disk in a version 1 file"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = self._repo.vfs(self.statepathv1, b'wb')
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 irecords = iter(records)
timeless
py3: convert to next() function...
r29216 lrecords = next(irecords)
Gregory Szorc
merge: use constants for merge state record types...
r37127 assert lrecords[0] == RECORD_LOCAL
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(hex(self._local) + b'\n')
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 for rtype, data in irecords:
Gregory Szorc
merge: use constants for merge state record types...
r37127 if rtype == RECORD_MERGED:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(b'%s\n' % _droponode(data))
Pierre-Yves David
merge: change the merge state serialisation to use a record based logic...
r20589 f.close()
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Pierre-Yves David
merge: introduce new format for the state file...
r20590 def _writerecordsv2(self, records):
Siddharth Agarwal
mergestate: handle additional record types specially...
r27027 """Write current state on disk in a version 2 file
See the docstring for _readrecordsv2 for why we use 't'."""
# these are the records that all version 2 clients can read
Gregory Szorc
merge: use constants for merge state record types...
r37127 allowlist = (RECORD_LOCAL, RECORD_OTHER, RECORD_MERGED)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = self._repo.vfs(self.statepathv2, b'wb')
Pierre-Yves David
merge: introduce new format for the state file...
r20590 for key, data in records:
assert len(key) == 1
Gregory Szorc
merge: use constants for merge state record types...
r37127 if key not in allowlist:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 key, data = RECORD_OVERRIDE, b'%s%s' % (key, data)
format = b'>sI%is' % len(data)
Pierre-Yves David
merge: introduce new format for the state file...
r20590 f.write(_pack(format, key, len(data), data))
f.close()
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Daniel Ploch
merge: make local file storage in the .hg/merge directory extensible...
r41190 @staticmethod
def getlocalkey(path):
"""hash the path of a local file context for storage in the .hg/merge
directory."""
Augie Fackler
core: migrate uses of hashlib.sha1 to hashutil.sha1...
r44517 return hex(hashutil.sha1(path).digest())
Daniel Ploch
merge: make local file storage in the .hg/merge directory extensible...
r41190
Mads Kiilerich
merge: merge file flags together with file content...
r18338 def add(self, fcl, fco, fca, fd):
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 """add a new (potentially?) conflicting file the merge state
fcl: file context for local,
fco: file context for remote,
fca: file context for ancestors,
fd: file path of the resulting merge.
note: also write the local version to the `.hg/merge` directory.
"""
Siddharth Agarwal
mergestate.add: store absentfilectxes as nullhex...
r27049 if fcl.isabsent():
Daniel Ploch
merge: make local file storage in the .hg/merge directory extensible...
r41190 localkey = nullhex
Siddharth Agarwal
mergestate.add: store absentfilectxes as nullhex...
r27049 else:
Daniel Ploch
merge: make local file storage in the .hg/merge directory extensible...
r41190 localkey = mergestate.getlocalkey(fcl.path())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._repo.vfs.write(b'merge/' + localkey, fcl.data())
Augie Fackler
formatting: blacken the codebase...
r43346 self._state[fd] = [
MERGE_RECORD_UNRESOLVED,
localkey,
fcl.path(),
fca.path(),
hex(fca.filenode()),
fco.path(),
hex(fco.filenode()),
fcl.flags(),
]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._stateextras[fd] = {b'ancestorlinknode': hex(fca.node())}
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = True
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Mark Thomas
merge: add pathconflict merge state...
r34546 def addpath(self, path, frename, forigin):
"""add a new conflicting path to the merge state
path: the path that conflicts
frename: the filename the conflicting file was renamed to
forigin: origin of the file ('l' or 'r' for local/remote)
"""
Gregory Szorc
merge: use constants for merge record state...
r37129 self._state[path] = [MERGE_RECORD_UNRESOLVED_PATH, frename, forigin]
Mark Thomas
merge: add pathconflict merge state...
r34546 self._dirty = True
Matt Mackall
merge: introduce mergestate
r6512 def __contains__(self, dfile):
return dfile in self._state
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Matt Mackall
merge: introduce mergestate
r6512 def __getitem__(self, dfile):
Matt Mackall
resolve: new command...
r6518 return self._state[dfile][0]
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Matt Mackall
resolve: new command...
r6518 def __iter__(self):
Mads Kiilerich
merge: simplify mergestate iter
r21268 return iter(sorted(self._state))
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Bryan O'Sullivan
merge: add a files method to the mergestate class...
r19285 def files(self):
return self._state.keys()
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Matt Mackall
merge: introduce mergestate
r6512 def mark(self, dfile, state):
Matt Mackall
resolve: new command...
r6518 self._state[dfile][0] = state
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = True
Pierre-Yves David
merge: add blank line between mergestate's method...
r20651
Siddharth Agarwal
merge.mergestate: add a way to get the merge driver state...
r26766 def mdstate(self):
return self._mdstate
Gregory Szorc
resolve: print message when no unresolved files remain (issue4214)...
r21266 def unresolved(self):
"""Obtain the paths of unresolved files."""
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, entry in pycompat.iteritems(self._state):
Augie Fackler
formatting: blacken the codebase...
r43346 if entry[0] in (
MERGE_RECORD_UNRESOLVED,
MERGE_RECORD_UNRESOLVED_PATH,
):
Gregory Szorc
resolve: print message when no unresolved files remain (issue4214)...
r21266 yield f
Siddharth Agarwal
merge.mergestate: add a generator for driver-resolved files...
r26740 def driverresolved(self):
"""Obtain the paths of driver-resolved files."""
for f, entry in self._state.items():
Gregory Szorc
merge: use constants for merge record state...
r37129 if entry[0] == MERGE_RECORD_DRIVER_RESOLVED:
Siddharth Agarwal
merge.mergestate: add a generator for driver-resolved files...
r26740 yield f
Durham Goode
merge: add state extras merge state data...
r28009 def extras(self, filename):
return self._stateextras.setdefault(filename, {})
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 def _resolve(self, preresolve, dfile, wctx):
Pierre-Yves David
merge: adds documentation to the mergestate class...
r20652 """rerun merge process for file path `dfile`"""
Augie Fackler
formatting: blacken the codebase...
r43346 if self[dfile] in (MERGE_RECORD_RESOLVED, MERGE_RECORD_DRIVER_RESOLVED):
Siddharth Agarwal
merge.mergestate._resolve: also return completed status...
r26616 return True, 0
Pierre-Yves David
merge: add "other" file node in the merge state file...
r20593 stateentry = self._state[dfile]
Daniel Ploch
merge: make local file storage in the .hg/merge directory extensible...
r41190 state, localkey, lfile, afile, anode, ofile, onode, flags = stateentry
Pierre-Yves David
resolve: use "other" changeset from merge state (issue4163)...
r20594 octx = self._repo[self._other]
Durham Goode
merge: add file ancestor linknode to mergestate...
r28011 extras = self.extras(dfile)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 anccommitnode = extras.get(b'ancestorlinknode')
Durham Goode
merge: add file ancestor linknode to mergestate...
r28011 if anccommitnode:
actx = self._repo[anccommitnode]
else:
actx = None
Daniel Ploch
merge: make local file storage in the .hg/merge directory extensible...
r41190 fcd = self._filectxorabsent(localkey, wctx, dfile)
Siddharth Agarwal
mergestate._resolve: handle change/delete conflicts...
r27048 fco = self._filectxorabsent(onode, octx, ofile)
# TODO: move this to filectxorabsent
Martin von Zweigbergk
context: avoid using a context object as a changeid...
r37189 fca = self._repo.filectx(afile, fileid=anode, changectx=actx)
Mads Kiilerich
merge: merge file flags together with file content...
r18338 # "premerge" x flags
flo = fco.flags()
fla = fca.flags()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'x' in flags + flo + fla and b'l' not in flags + flo + fla:
Mads Kiilerich
merge: only show "cannot merge flags for %s" warning if flags are different
r30161 if fca.node() == nullid and flags != flo:
Siddharth Agarwal
merge: introduce a preresolve function...
r26617 if preresolve:
self._repo.ui.warn(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'warning: cannot merge flags for %s '
b'without common ancestor - keeping local flags\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% afile
)
Mads Kiilerich
merge: merge file flags together with file content...
r18338 elif flags == fla:
flags = flo
Siddharth Agarwal
merge: introduce a preresolve function...
r26617 if preresolve:
# restore local
Daniel Ploch
merge: make local file storage in the .hg/merge directory extensible...
r41190 if localkey != nullhex:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = self._repo.vfs(b'merge/' + localkey)
Phil Cohen
merge: convert repo.wwrite() calls to wctx[f].write()...
r33083 wctx[dfile].write(f.read(), flags)
Siddharth Agarwal
mergestate._resolve: handle change/delete conflicts...
r27048 f.close()
else:
Phil Cohen
merge: replace repo.wvfs.unlinkpath() with calls to wctx[f].remove()...
r33082 wctx[dfile].remove(ignoremissing=True)
Augie Fackler
formatting: blacken the codebase...
r43346 complete, r, deleted = filemerge.premerge(
self._repo,
wctx,
self._local,
lfile,
fcd,
fco,
fca,
labels=self._labels,
)
Siddharth Agarwal
merge: introduce a preresolve function...
r26617 else:
Augie Fackler
formatting: blacken the codebase...
r43346 complete, r, deleted = filemerge.filemerge(
self._repo,
wctx,
self._local,
lfile,
fcd,
fco,
fca,
labels=self._labels,
)
Matt Mackall
merge: drop resolve state for mergers with identical contents (issue2680)
r13536 if r is None:
# no real conflict
del self._state[dfile]
Durham Goode
merge: add state extras merge state data...
r28009 self._stateextras.pop(dfile, None)
Mads Kiilerich
merge: mark mergestate as dirty when resolve changes _state...
r20792 self._dirty = True
Matt Mackall
merge: drop resolve state for mergers with identical contents (issue2680)
r13536 elif not r:
Gregory Szorc
merge: use constants for merge record state...
r37129 self.mark(dfile, MERGE_RECORD_RESOLVED)
Siddharth Agarwal
merge.mergestate: compute dirstate action...
r27035
if complete:
Siddharth Agarwal
mergestate._resolve: don't return the action any more...
r27075 action = None
Siddharth Agarwal
merge.mergestate: compute dirstate action...
r27035 if deleted:
Siddharth Agarwal
mergestate: explicitly forget 'dc' conflicts where the deleted side is picked...
r27122 if fcd.isabsent():
# dc: local picked. Need to drop if present, which may
# happen on re-resolves.
Gregory Szorc
merge: use constants for actions...
r37130 action = ACTION_FORGET
Siddharth Agarwal
mergestate: explicitly forget 'dc' conflicts where the deleted side is picked...
r27122 else:
Siddharth Agarwal
merge.mergestate: compute dirstate action...
r27035 # cd: remote picked (or otherwise deleted)
Gregory Szorc
merge: use constants for actions...
r37130 action = ACTION_REMOVE
Siddharth Agarwal
merge.mergestate: compute dirstate action...
r27035 else:
Augie Fackler
formatting: blacken the codebase...
r43346 if fcd.isabsent(): # dc: remote picked
Gregory Szorc
merge: use constants for actions...
r37130 action = ACTION_GET
Augie Fackler
formatting: blacken the codebase...
r43346 elif fco.isabsent(): # cd: local picked
Siddharth Agarwal
merge: add a new action type representing files to add/mark as modified...
r27131 if dfile in self.localctx:
Gregory Szorc
merge: use constants for actions...
r37130 action = ACTION_ADD_MODIFIED
Siddharth Agarwal
merge: add a new action type representing files to add/mark as modified...
r27131 else:
Gregory Szorc
merge: use constants for actions...
r37130 action = ACTION_ADD
Siddharth Agarwal
merge.mergestate: compute dirstate action...
r27035 # else: regular merges (no action necessary)
Siddharth Agarwal
mergestate._resolve: store return code and action for each file...
r27074 self._results[dfile] = r, action
Siddharth Agarwal
merge.mergestate: compute dirstate action...
r27035
Siddharth Agarwal
merge.mergestate._resolve: also return completed status...
r26616 return complete, r
Matt Mackall
Move merge code to its own module...
r2775
Siddharth Agarwal
mergestate._resolve: handle change/delete conflicts...
r27048 def _filectxorabsent(self, hexnode, ctx, f):
if hexnode == nullhex:
return filemerge.absentfilectx(ctx, f)
else:
return ctx[f]
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 def preresolve(self, dfile, wctx):
Siddharth Agarwal
merge.mergestate: update docstrings for preresolve and resolve...
r26870 """run premerge process for dfile
Returns whether the merge is complete, and the exit code."""
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 return self._resolve(True, dfile, wctx)
Siddharth Agarwal
merge: introduce a preresolve function...
r26617
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 def resolve(self, dfile, wctx):
Siddharth Agarwal
merge.mergestate: update docstrings for preresolve and resolve...
r26870 """run merge process (assuming premerge was run) for dfile
Returns the exit code of the merge."""
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 return self._resolve(False, dfile, wctx)[1]
Siddharth Agarwal
merge.mergestate: add a wrapper around resolve...
r26615
Siddharth Agarwal
mergestate: add a method to return updated/merged/removed counts...
r27076 def counts(self):
"""return counts for updated, merged and removed files in this
session"""
updated, merged, removed = 0, 0, 0
Gregory Szorc
py3: define and use pycompat.itervalues()...
r43374 for r, action in pycompat.itervalues(self._results):
Siddharth Agarwal
mergestate: add a method to return updated/merged/removed counts...
r27076 if r is None:
updated += 1
elif r == 0:
Gregory Szorc
merge: use constants for actions...
r37130 if action == ACTION_REMOVE:
Siddharth Agarwal
mergestate: add a method to return updated/merged/removed counts...
r27076 removed += 1
else:
merged += 1
return updated, merged, removed
Siddharth Agarwal
mergestate: add a function to return the number of unresolved files...
r27077 def unresolvedcount(self):
"""get unresolved count for this merge (persistent)"""
Martin von Zweigbergk
mergestate: implement unresolvedcount() in terms of unresolved()...
r33311 return len(list(self.unresolved()))
Siddharth Agarwal
mergestate: add a function to return the number of unresolved files...
r27077
Siddharth Agarwal
mergestate: add a method to compute actions to perform on dirstate...
r27079 def actions(self):
"""return lists of actions to perform on the dirstate"""
Gregory Szorc
merge: use constants for actions...
r37130 actions = {
ACTION_REMOVE: [],
ACTION_FORGET: [],
ACTION_ADD: [],
ACTION_ADD_MODIFIED: [],
ACTION_GET: [],
}
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, (r, action) in pycompat.iteritems(self._results):
Siddharth Agarwal
mergestate: add a method to compute actions to perform on dirstate...
r27079 if action is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[action].append((f, None, b"merge result"))
Siddharth Agarwal
mergestate: add a method to compute actions to perform on dirstate...
r27079 return actions
Siddharth Agarwal
mergestate: add a way to record pending dirstate actions...
r27088 def recordactions(self):
"""record remove/add/get actions in the dirstate"""
branchmerge = self._repo.dirstate.p2() != nullid
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 recordupdates(self._repo, self.actions(), branchmerge, None)
Siddharth Agarwal
mergestate: add a way to record pending dirstate actions...
r27088
Siddharth Agarwal
mergestate: add methods to queue files to remove, add or get...
r27090 def queueremove(self, f):
"""queues a file to be removed from the dirstate
Meant for use by custom merge drivers."""
Gregory Szorc
merge: use constants for actions...
r37130 self._results[f] = 0, ACTION_REMOVE
Siddharth Agarwal
mergestate: add methods to queue files to remove, add or get...
r27090
def queueadd(self, f):
"""queues a file to be added to the dirstate
Meant for use by custom merge drivers."""
Gregory Szorc
merge: use constants for actions...
r37130 self._results[f] = 0, ACTION_ADD
Siddharth Agarwal
mergestate: add methods to queue files to remove, add or get...
r27090
def queueget(self, f):
"""queues a file to be marked modified in the dirstate
Meant for use by custom merge drivers."""
Gregory Szorc
merge: use constants for actions...
r37130 self._results[f] = 0, ACTION_GET
Siddharth Agarwal
mergestate: add methods to queue files to remove, add or get...
r27090
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
merge: factor out code to get checkunknown config...
r27740 def _getcheckunknownconfig(repo, section, name):
Boris Feld
configitems: register 'merge.checkunknown' and 'merge.checkignored'...
r34523 config = repo.ui.config(section, name)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 valid = [b'abort', b'ignore', b'warn']
Siddharth Agarwal
merge: factor out code to get checkunknown config...
r27740 if config not in valid:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 validstr = b', '.join([b"'" + v + b"'" for v in valid])
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ConfigError(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b"%s.%s not valid ('%s' is none of %s)")
Augie Fackler
formatting: blacken the codebase...
r43346 % (section, name, config, validstr)
)
Siddharth Agarwal
merge: factor out code to get checkunknown config...
r27740 return config
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
merge: don't overwrite untracked file at directory rename target...
r23653 def _checkunknownfile(repo, wctx, mctx, f, f2=None):
Phil Cohen
merge: don't check for unknown files in IMM...
r35289 if wctx.isinmemory():
# Nothing to do in IMM because nothing in the "working copy" can be an
# unknown file.
#
# Note that we should bail out here, not in ``_checkunknownfiles()``,
# because that function does other useful work.
return False
Martin von Zweigbergk
merge: don't overwrite untracked file at directory rename target...
r23653 if f2 is None:
f2 = f
Augie Fackler
formatting: blacken the codebase...
r43346 return (
repo.wvfs.audit.check(f)
Durham Goode
checkunknown: audit path before checking if it's a file or link...
r28088 and repo.wvfs.isfileorlink(f)
Matt Mackall
merge: fix unknown file merge detection for case-folding systems...
r16284 and repo.dirstate.normalize(f) not in repo.dirstate
Augie Fackler
formatting: blacken the codebase...
r43346 and mctx[f2].cmp(wctx[f])
)
Matt Mackall
merge: refactor unknown file conflict checking...
r16093
Mark Thomas
merge: cache unknown dir checks (issue5716)...
r35181 class _unknowndirschecker(object):
Mark Thomas
merge: add _checkunknowndirs function for detecting path conflicts...
r34551 """
Look for any unknown files or directories that may have a path conflict
with a file. If any path prefix of the file exists as a file or link,
then it conflicts. If the file itself is a directory that contains any
file that is not tracked, then it conflicts.
Returns the shortest path at which a conflict occurs, or None if there is
no conflict.
"""
Augie Fackler
formatting: blacken the codebase...
r43346
Mark Thomas
merge: cache unknown dir checks (issue5716)...
r35181 def __init__(self):
# A set of paths known to be good. This prevents repeated checking of
# dirs. It will be updated with any new dirs that are checked and found
# to be safe.
self._unknowndircache = set()
Mark Thomas
merge: add _checkunknowndirs function for detecting path conflicts...
r34551
Mark Thomas
merge: cache unknown dir checks (issue5716)...
r35181 # A set of paths that are known to be absent. This prevents repeated
# checking of subdirectories that are known not to exist. It will be
# updated with any new dirs that are checked and found to be absent.
self._missingdircache = set()
Mark Thomas
merge: add _checkunknowndirs function for detecting path conflicts...
r34551
Phil Cohen
merge: don't check for unknown files in IMM...
r35289 def __call__(self, repo, wctx, f):
if wctx.isinmemory():
# Nothing to do in IMM for the same reason as ``_checkunknownfile``.
return False
Mark Thomas
merge: cache unknown dir checks (issue5716)...
r35181 # Check for path prefixes that exist as unknown files.
Martin von Zweigbergk
utils: move finddirs() to pathutil...
r44032 for p in reversed(list(pathutil.finddirs(f))):
Mark Thomas
merge: cache unknown dir checks (issue5716)...
r35181 if p in self._missingdircache:
return
if p in self._unknowndircache:
continue
if repo.wvfs.audit.check(p):
Augie Fackler
formatting: blacken the codebase...
r43346 if (
repo.wvfs.isfileorlink(p)
and repo.dirstate.normalize(p) not in repo.dirstate
):
Mark Thomas
merge: cache unknown dir checks (issue5716)...
r35181 return p
if not repo.wvfs.lexists(p):
self._missingdircache.add(p)
return
self._unknowndircache.add(p)
# Check if the file conflicts with a directory containing unknown files.
if repo.wvfs.audit.check(f) and repo.wvfs.isdir(f):
# Does the directory contain any files that are not in the dirstate?
for p, dirs, files in repo.wvfs.walk(f):
for fn in files:
Matt Harbison
merge: pconvert paths in _unknowndirschecker before dirstate-normalizing...
r37104 relf = util.pconvert(repo.wvfs.reljoin(p, fn))
Matt Harbison
merge: add 'isknown=True' to a dirstate.normalize() in _unknowndirschecker...
r37105 relf = repo.dirstate.normalize(relf, isknown=True)
Mark Thomas
merge: cache unknown dir checks (issue5716)...
r35181 if relf not in repo.dirstate:
return f
return None
Mark Thomas
merge: add _checkunknowndirs function for detecting path conflicts...
r34551
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
merge: tell _checkunknownfiles about whether this was merge --force...
r28020 def _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce):
Martin von Zweigbergk
merge: extract method for checking for conflicting untracked file...
r23655 """
Considers any actions that care about the presence of conflicting unknown
files. For some actions, the result is to abort; for others, it is to
choose a different action.
"""
Mark Thomas
merge: rename conflicts to fileconflicts in _checkunknownfiles...
r34552 fileconflicts = set()
Mark Thomas
merge: check for path conflicts when updating (issue5628)...
r34553 pathconflicts = set()
Siddharth Agarwal
merge: move abort/warn checks up to the top level of _checkunknownfiles...
r28018 warnconflicts = set()
abortconflicts = set()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 unknownconfig = _getcheckunknownconfig(repo, b'merge', b'checkunknown')
ignoredconfig = _getcheckunknownconfig(repo, b'merge', b'checkignored')
pathconfig = repo.ui.configbool(
b'experimental', b'merge.checkpathconflicts'
)
Martin von Zweigbergk
merge: extract method for checking for conflicting untracked file...
r23655 if not force:
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
merge: determine what untracked conflicts cause warns and aborts separately...
r27741 def collectconflicts(conflicts, config):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if config == b'abort':
Siddharth Agarwal
merge: determine what untracked conflicts cause warns and aborts separately...
r27741 abortconflicts.update(conflicts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif config == b'warn':
Siddharth Agarwal
merge: determine what untracked conflicts cause warns and aborts separately...
r27741 warnconflicts.update(conflicts)
Mark Thomas
merge: cache unknown dir checks (issue5716)...
r35181 checkunknowndirs = _unknowndirschecker()
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, (m, args, msg) in pycompat.iteritems(actions):
Gregory Szorc
merge: use constants for actions...
r37130 if m in (ACTION_CREATED, ACTION_DELETED_CHANGED):
Martin von Zweigbergk
merge: extract method for checking for conflicting untracked file...
r23655 if _checkunknownfile(repo, wctx, mctx, f):
Mark Thomas
merge: rename conflicts to fileconflicts in _checkunknownfiles...
r34552 fileconflicts.add(f)
Siddharth Agarwal
merge: add a config option to disable path conflict checking...
r34942 elif pathconfig and f not in wctx:
Phil Cohen
merge: don't check for unknown files in IMM...
r35289 path = checkunknowndirs(repo, wctx, f)
Mark Thomas
merge: check for path conflicts when updating (issue5628)...
r34553 if path is not None:
pathconflicts.add(path)
Gregory Szorc
merge: use constants for actions...
r37130 elif m == ACTION_LOCAL_DIR_RENAME_GET:
Martin von Zweigbergk
merge: extract method for checking for conflicting untracked file...
r23655 if _checkunknownfile(repo, wctx, mctx, f, args[0]):
Mark Thomas
merge: rename conflicts to fileconflicts in _checkunknownfiles...
r34552 fileconflicts.add(f)
Martin von Zweigbergk
merge: extract method for checking for conflicting untracked file...
r23655
Mark Thomas
merge: check for path conflicts when updating (issue5628)...
r34553 allconflicts = fileconflicts | pathconflicts
Augie Fackler
formatting: blacken the codebase...
r43346 ignoredconflicts = {c for c in allconflicts if repo.dirstate._ignore(c)}
Mark Thomas
merge: rename conflicts to fileconflicts in _checkunknownfiles...
r34552 unknownconflicts = allconflicts - ignoredconflicts
Siddharth Agarwal
merge: split up checks for unknown and ignored files that differ...
r27742 collectconflicts(ignoredconflicts, ignoredconfig)
collectconflicts(unknownconflicts, unknownconfig)
Siddharth Agarwal
rebase: respect checkunknown and checkignored in more cases...
r28022 else:
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, (m, args, msg) in pycompat.iteritems(actions):
Gregory Szorc
merge: use constants for actions...
r37130 if m == ACTION_CREATED_MERGE:
Siddharth Agarwal
rebase: respect checkunknown and checkignored in more cases...
r28022 fl2, anc = args
different = _checkunknownfile(repo, wctx, mctx, f)
if repo.dirstate._ignore(f):
config = ignoredconfig
else:
config = unknownconfig
# The behavior when force is True is described by this table:
# config different mergeforce | action backup
# * n * | get n
# * y y | merge -
# abort y n | merge - (1)
# warn y n | warn + get y
# ignore y n | get y
#
# (1) this is probably the wrong behavior here -- we should
# probably abort, but some actions like rebases currently
# don't like an abort happening in the middle of
# merge.update.
if not different:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_GET, (fl2, False), b'remote created')
elif mergeforce or config == b'abort':
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_MERGE,
(f, f, None, False, anc),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'remote differs from untracked local',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif config == b'abort':
Siddharth Agarwal
rebase: respect checkunknown and checkignored in more cases...
r28022 abortconflicts.add(f)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if config == b'warn':
Siddharth Agarwal
rebase: respect checkunknown and checkignored in more cases...
r28022 warnconflicts.add(f)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_GET, (fl2, True), b'remote created')
Siddharth Agarwal
merge: determine what untracked conflicts cause warns and aborts separately...
r27741
Siddharth Agarwal
merge: move abort/warn checks up to the top level of _checkunknownfiles...
r28018 for f in sorted(abortconflicts):
Mark Thomas
merge: improve error messages for path conflicts during update...
r34554 warn = repo.ui.warn
if f in pathconflicts:
if repo.wvfs.isfileorlink(f):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 warn(_(b"%s: untracked file conflicts with directory\n") % f)
Mark Thomas
merge: improve error messages for path conflicts during update...
r34554 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 warn(_(b"%s: untracked directory conflicts with file\n") % f)
Mark Thomas
merge: improve error messages for path conflicts during update...
r34554 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 warn(_(b"%s: untracked file differs\n") % f)
Siddharth Agarwal
merge: move abort/warn checks up to the top level of _checkunknownfiles...
r28018 if abortconflicts:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"untracked files in working directory "
b"differ from files in requested revision"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Siddharth Agarwal
merge: move abort/warn checks up to the top level of _checkunknownfiles...
r28018
for f in sorted(warnconflicts):
Mark Thomas
merge: improve error messages for path conflicts during update...
r34554 if repo.wvfs.isfileorlink(f):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(_(b"%s: replacing untracked file\n") % f)
Mark Thomas
merge: improve error messages for path conflicts during update...
r34554 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(_(b"%s: replacing untracked files in directory\n") % f)
Martin von Zweigbergk
merge: extract method for checking for conflicting untracked file...
r23655
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, (m, args, msg) in pycompat.iteritems(actions):
Gregory Szorc
merge: use constants for actions...
r37130 if m == ACTION_CREATED:
Augie Fackler
formatting: blacken the codebase...
r43346 backup = (
f in fileconflicts
or f in pathconflicts
Martin von Zweigbergk
utils: move finddirs() to pathutil...
r44032 or any(p in pathconflicts for p in pathutil.finddirs(f))
Augie Fackler
formatting: blacken the codebase...
r43346 )
(flags,) = args
Gregory Szorc
merge: use constants for actions...
r37130 actions[f] = (ACTION_GET, (flags, backup), msg)
Martin von Zweigbergk
merge: extract method for checking for conflicting untracked file...
r23655
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
merge: privatize some functions, unnest some others
r6269 def _forgetremoved(wctx, mctx, branchmerge):
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107 """
Forget removed files
If we're jumping between revisions (as opposed to merging), and if
neither the working directory nor the target rev has the file,
then we need to remove it from the dirstate, to prevent the
dirstate from listing the file when it is no longer in the
manifest.
Alexis S. L. Carvalho
merge: fix handling of deleted files
r6242
If we're merging, and the other revision has removed a file
that is not present in the working directory, we need to mark it
as removed.
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107 """
Martin von Zweigbergk
merge: let _forgetremoved() work on the file->action dict...
r23640 actions = {}
Gregory Szorc
merge: use constants for actions...
r37130 m = ACTION_FORGET
Mads Kiilerich
merge: use separate lists for each action type...
r21545 if branchmerge:
Gregory Szorc
merge: use constants for actions...
r37130 m = ACTION_REMOVE
Alexis S. L. Carvalho
merge: fix handling of deleted files
r6242 for f in wctx.deleted():
Matt Mackall
merge: simplify some helpers
r6272 if f not in mctx:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = m, None, b"forget deleted"
Alexis S. L. Carvalho
merge: fix handling of deleted files
r6242
if not branchmerge:
for f in wctx.removed():
Matt Mackall
merge: simplify some helpers
r6272 if f not in mctx:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = ACTION_FORGET, None, b"forget removed"
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107
Martin von Zweigbergk
merge: let _forgetremoved() work on the file->action dict...
r23640 return actions
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107
Augie Fackler
formatting: blacken the codebase...
r43346
Mads Kiilerich
merge: handle create+delete prompts in calculateupdates...
r20640 def _checkcollision(repo, wmf, actions):
Martin von Zweigbergk
narrow: filter set of files to check for case-folding to core...
r38056 """
Check for case-folding collisions.
"""
# If the repo is narrowed, filter out files outside the narrowspec.
narrowmatch = repo.narrowmatch()
if not narrowmatch.always():
Augie Fackler
merge: use manifestdict.walk() instead of manifestdict.matches()...
r44769 pmmf = set(wmf.walk(narrowmatch))
Martin von Zweigbergk
narrow: filter set of files to check for case-folding to core...
r38056 if actions:
narrowactions = {}
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for m, actionsfortype in pycompat.iteritems(actions):
Martin von Zweigbergk
narrow: filter set of files to check for case-folding to core...
r38056 narrowactions[m] = []
for (f, args, msg) in actionsfortype:
if narrowmatch(f):
narrowactions[m].append((f, args, msg))
actions = narrowactions
Augie Fackler
merge: use manifestdict.walk() instead of manifestdict.matches()...
r44769 else:
# build provisional merged manifest up
pmmf = set(wmf)
FUJIWARA Katsunori
icasefs: rewrite case-folding collision detection (issue3452)...
r19105
Mads Kiilerich
merge: use separate lists for each action type...
r21545 if actions:
Gregory Szorc
merge: use constants for actions...
r37130 # KEEP and EXEC are no-op
Augie Fackler
formatting: blacken the codebase...
r43346 for m in (
ACTION_ADD,
ACTION_ADD_MODIFIED,
ACTION_FORGET,
ACTION_GET,
ACTION_CHANGED_DELETED,
ACTION_DELETED_CHANGED,
):
Mads Kiilerich
merge: use separate lists for each action type...
r21545 for f, args, msg in actions[m]:
pmmf.add(f)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_REMOVE]:
Mads Kiilerich
merge: use separate lists for each action type...
r21545 pmmf.discard(f)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_DIR_RENAME_MOVE_LOCAL]:
Mads Kiilerich
merge: use separate lists for each action type...
r21545 f2, flags = args
pmmf.discard(f2)
pmmf.add(f)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_LOCAL_DIR_RENAME_GET]:
Mads Kiilerich
merge: use separate lists for each action type...
r21545 pmmf.add(f)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_MERGE]:
Mads Kiilerich
merge: use separate lists for each action type...
r21545 f1, f2, fa, move, anc = args
if move:
pmmf.discard(f1)
pmmf.add(f)
FUJIWARA Katsunori
icasefs: rewrite case-folding collision detection (issue3452)...
r19105
# check case-folding collision in provisional merged manifest
foldmap = {}
Alex Gaynor
merge: removed sorting in casefolding detection, for a slight performance win...
r33807 for f in pmmf:
FUJIWARA Katsunori
icasefs: rewrite case-folding collision detection (issue3452)...
r19105 fold = util.normcase(f)
if fold in foldmap:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"case-folding collision between %s and %s")
Augie Fackler
formatting: blacken the codebase...
r43346 % (f, foldmap[fold])
)
FUJIWARA Katsunori
icasefs: rewrite case-folding collision detection (issue3452)...
r19105 foldmap[fold] = f
Mads Kiilerich
merge: abort on file/directory case folding collisions (issue4892)...
r26661 # check case-folding of directories
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 foldprefix = unfoldprefix = lastfull = b''
Mads Kiilerich
merge: abort on file/directory case folding collisions (issue4892)...
r26661 for fold, f in sorted(foldmap.items()):
if fold.startswith(foldprefix) and not f.startswith(unfoldprefix):
# the folded prefix matches but actual casing is different
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b"case-folding collision between %s and directory of %s")
Augie Fackler
formatting: blacken the codebase...
r43346 % (lastfull, f)
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 foldprefix = fold + b'/'
unfoldprefix = f + b'/'
Mads Kiilerich
merge: abort on file/directory case folding collisions (issue4892)...
r26661 lastfull = f
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
merge: add stubs for preprocess and conclude steps of merge driver...
r26785 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
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
merge: add stubs for preprocess and conclude steps of merge driver...
r26785 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
Augie Fackler
formatting: blacken the codebase...
r43346
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 def _filesindirs(repo, manifest, dirs):
"""
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
in.
"""
for f in manifest:
Martin von Zweigbergk
utils: move finddirs() to pathutil...
r44032 for p in pathutil.finddirs(f):
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 if p in dirs:
yield f, p
break
Augie Fackler
formatting: blacken the codebase...
r43346
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 def checkpathconflicts(repo, wctx, mctx, actions):
"""
Check if any actions introduce path conflicts in the repository, updating
actions to record or handle the path conflict accordingly.
"""
mf = wctx.manifest()
# The set of local files that conflict with a remote directory.
localconflicts = set()
# The set of directories that conflict with a remote file, and so may cause
# conflicts if they still contain any files after the merge.
remoteconflicts = set()
# The set of directories that appear as both a file and a directory in the
# remote manifest. These indicate an invalid remote manifest, which
# can't be updated to cleanly.
invalidconflicts = set()
Mark Thomas
merge: check created file dirs for path conflicts only once (issue5716)...
r35182 # The set of directories that contain files that are being created.
createdfiledirs = set()
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 # The set of files deleted by all the actions.
deletedfiles = set()
for f, (m, args, msg) in actions.items():
Augie Fackler
formatting: blacken the codebase...
r43346 if m in (
ACTION_CREATED,
ACTION_DELETED_CHANGED,
ACTION_MERGE,
ACTION_CREATED_MERGE,
):
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 # This action may create a new local file.
Martin von Zweigbergk
utils: move finddirs() to pathutil...
r44032 createdfiledirs.update(pathutil.finddirs(f))
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 if mf.hasdir(f):
# The file aliases a local directory. This might be ok if all
# the files in the local directory are being deleted. This
# will be checked once we know what all the deleted files are.
remoteconflicts.add(f)
# Track the names of all deleted files.
Gregory Szorc
merge: use constants for actions...
r37130 if m == ACTION_REMOVE:
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 deletedfiles.add(f)
Gregory Szorc
merge: use constants for actions...
r37130 if m == ACTION_MERGE:
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 f1, f2, fa, move, anc = args
if move:
deletedfiles.add(f1)
Gregory Szorc
merge: use constants for actions...
r37130 if m == ACTION_DIR_RENAME_MOVE_LOCAL:
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 f2, flags = args
deletedfiles.add(f2)
Mark Thomas
merge: check created file dirs for path conflicts only once (issue5716)...
r35182 # Check all directories that contain created files for path conflicts.
for p in createdfiledirs:
if p in mf:
if p in mctx:
# A file is in a directory which aliases both a local
# and a remote file. This is an internal inconsistency
# within the remote manifest.
invalidconflicts.add(p)
else:
# A file is in a directory which aliases a local file.
# We will need to rename the local file.
localconflicts.add(p)
Augie Fackler
formatting: blacken the codebase...
r43346 if p in actions and actions[p][0] in (
ACTION_CREATED,
ACTION_DELETED_CHANGED,
ACTION_MERGE,
ACTION_CREATED_MERGE,
):
Mark Thomas
merge: check created file dirs for path conflicts only once (issue5716)...
r35182 # The file is in a directory which aliases a remote file.
# This is an internal inconsistency within the remote
# manifest.
invalidconflicts.add(p)
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 # Rename all local conflicting files that have not been deleted.
for p in localconflicts:
if p not in deletedfiles:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ctxname = bytes(wctx).rstrip(b'+')
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 pnew = util.safename(p, ctxname, wctx, set(actions.keys()))
Augie Fackler
formatting: blacken the codebase...
r43346 actions[pnew] = (
ACTION_PATH_CONFLICT_RESOLVE,
(p,),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'local path conflict',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[p] = (ACTION_PATH_CONFLICT, (pnew, b'l'), b'path conflict')
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556
if remoteconflicts:
# Check if all files in the conflicting directories have been removed.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ctxname = bytes(mctx).rstrip(b'+')
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 for f, p in _filesindirs(repo, mf, remoteconflicts):
if f not in deletedfiles:
m, args, msg = actions[p]
pnew = util.safename(p, ctxname, wctx, set(actions.keys()))
Gregory Szorc
merge: use constants for actions...
r37130 if m in (ACTION_DELETED_CHANGED, ACTION_MERGE):
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 # Action was merge, just update target.
actions[pnew] = (m, args, msg)
else:
# Action was create, change to renamed get action.
fl = args[0]
Augie Fackler
formatting: blacken the codebase...
r43346 actions[pnew] = (
ACTION_LOCAL_DIR_RENAME_GET,
(p, fl),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'remote path conflict',
Augie Fackler
formatting: blacken the codebase...
r43346 )
actions[p] = (
ACTION_PATH_CONFLICT,
(pnew, ACTION_REMOVE),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'path conflict',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556 remoteconflicts.remove(p)
break
if invalidconflicts:
for p in invalidconflicts:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(_(b"%s: is both a file and a directory\n") % p)
raise error.Abort(_(b"destination manifest contains path conflicts"))
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
narrow: filter merge actions in core...
r38055 def _filternarrowactions(narrowmatch, branchmerge, actions):
"""
Filters out actions that can ignored because the repo is narrowed.
Raise an exception if the merge cannot be completed because the repo is
narrowed.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 nooptypes = {b'k'} # TODO: handle with nonconflicttypes
nonconflicttypes = set(b'a am c cm f g r e'.split())
Martin von Zweigbergk
narrow: filter merge actions in core...
r38055 # We mutate the items in the dict during iteration, so iterate
# over a copy.
for f, action in list(actions.items()):
if narrowmatch(f):
pass
elif not branchmerge:
Augie Fackler
formatting: blacken the codebase...
r43346 del actions[f] # just updating, ignore changes outside clone
Martin von Zweigbergk
narrow: filter merge actions in core...
r38055 elif action[0] in nooptypes:
Augie Fackler
formatting: blacken the codebase...
r43346 del actions[f] # merge does not affect file
Martin von Zweigbergk
narrow: filter merge actions in core...
r38055 elif action[0] in nonconflicttypes:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'merge affects file \'%s\' outside narrow, '
b'which is not yet supported'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% f,
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 hint=_(b'merging in the other direction may work'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
narrow: filter merge actions in core...
r38055 else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'conflict in file \'%s\' is outside narrow clone') % f
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
narrow: filter merge actions in core...
r38055
Augie Fackler
formatting: blacken the codebase...
r43346 def manifestmerge(
repo,
wctx,
p2,
pa,
branchmerge,
force,
matcher,
acceptremote,
followcopies,
forcefulldiff=False,
):
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 """
Yuya Nishihara
merge: update doc of manifestmerge() per 18c2184c27dc...
r30096 Merge wctx and p2 with ancestor pa and generate merge action list
Matt Mackall
merge: update some docstrings
r3315
Siddharth Agarwal
manifestmerge: pass in branchmerge and force separately...
r18605 branchmerge and force are as passed in to update
Augie Fackler
merge: rework manifestmerge to use a matcher...
r27346 matcher = matcher to filter file lists
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 acceptremote = accept the incoming changes without prompting
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 """
Augie Fackler
merge: rework manifestmerge to use a matcher...
r27346 if matcher is not None and matcher.always():
matcher = None
Matt Mackall
merge: pull manifest comparison out into separate function
r3105
Siddharth Agarwal
manifestmerge: fix order in which manifests are fetched...
r18651 # manifests fetched in order are going to be faster, so prime the caches
Augie Fackler
formatting: blacken the codebase...
r43346 [
x.manifest()
for x in sorted(wctx.parents() + [p2, pa], key=scmutil.intrev)
]
Siddharth Agarwal
manifestmerge: fix order in which manifests are fetched...
r18651
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 branch_copies1 = copies.branch_copies()
branch_copies2 = copies.branch_copies()
diverge = {}
Siddharth Agarwal
manifestmerge: fix order in which manifests are fetched...
r18651 if followcopies:
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 branch_copies1, branch_copies2, diverge = copies.mergecopies(
repo, wctx, p2, pa
)
Matt Mackall
merge: refactor manifestmerge init to better report effective ancestor
r8753
Pulkit Goyal
py3: convert bool variables to bytes before passing into ui.debug()...
r32641 boolbm = pycompat.bytestr(bool(branchmerge))
boolf = pycompat.bytestr(bool(force))
boolm = pycompat.bytestr(bool(matcher))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b"resolving manifests\n"))
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b" branchmerge: %s, force: %s, partial: %s\n" % (boolbm, boolf, boolm)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
Matt Mackall
merge: refactor manifestmerge init to better report effective ancestor
r8753
Bryan O'Sullivan
merge: rename p1 to wctx in manifestmerge...
r18611 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 copied1 = set(branch_copies1.copy.values())
copied1.update(branch_copies1.movewithdir.values())
copied2 = set(branch_copies2.copy.values())
copied2.update(branch_copies2.movewithdir.values())
Matt Mackall
merge: use contexts for manifestmerge...
r3295
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'.hgsubstate' in m1 and wctx.rev() is None:
Yuya Nishihara
merge: do not fill manifest of committed revision with pseudo node (issue5526)...
r38444 # Check whether sub state is modified, and overwrite the manifest
# to flag the change. If wctx is a committed revision, we shouldn't
# care for the dirty state of the working directory.
Martin von Zweigbergk
merge: use any() instead of for loop when checking for dirty subrepos...
r28226 if any(wctx.sub(s).dirty() for s in wctx.substate):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 m1[b'.hgsubstate'] = modifiednodeid
Matt Mackall
submerge: properly deal with overwrites...
r9783
Durham Goode
rebase: use matcher to optimize manifestmerge...
r32151 # Don't use m2-vs-ma optimization if:
# - ma is the same as m1 or m2, which we're just going to diff again later
# - The caller specifically asks for a full diff, which is useful during bid
# merge.
Augie Fackler
formatting: blacken the codebase...
r43346 if pa not in ([wctx, p2] + wctx.parents()) and not forcefulldiff:
Durham Goode
rebase: use matcher to optimize manifestmerge...
r32151 # Identify which files are relevant to the merge, so we can limit the
# total m1-vs-m2 diff to just those files. This has significant
# performance benefits in large repositories.
relevantfiles = set(ma.diff(m2).keys())
# For copied and moved files, we need to add the source file too.
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 for copykey, copyvalue in pycompat.iteritems(branch_copies1.copy):
Durham Goode
rebase: use matcher to optimize manifestmerge...
r32151 if copyvalue in relevantfiles:
relevantfiles.add(copykey)
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 for movedirkey in branch_copies1.movewithdir:
Durham Goode
rebase: use matcher to optimize manifestmerge...
r32151 relevantfiles.add(movedirkey)
Martin von Zweigbergk
merge: use intersectmatchers() in "m2-vs-ma optimization"...
r32498 filesmatcher = scmutil.matchfiles(repo, relevantfiles)
matcher = matchmod.intersectmatchers(matcher, filesmatcher)
Durham Goode
rebase: use matcher to optimize manifestmerge...
r32151
Durham Goode
merge: remove uses of manifest.matches...
r31257 diff = m1.diff(m2, match=matcher)
Martin von Zweigbergk
merge: write manifestmerge() using dictionary with entry per file...
r23637 actions = {}
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, ((n1, fl1), (n2, fl2)) in pycompat.iteritems(diff):
Augie Fackler
formatting: blacken the codebase...
r43346 if n1 and n2: # file exists on both local and remote side
Martin von Zweigbergk
merge: separate out "both created" cases...
r23396 if f not in ma:
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 # TODO: what if they're renamed from different sources?
fa = branch_copies1.copy.get(
f, None
) or branch_copies2.copy.get(f, None)
Martin von Zweigbergk
merge: break out "both renamed a -> b" case...
r23397 if fa is not None:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_MERGE,
(f, f, fa, False, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'both renamed from %s' % fa,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mads Kiilerich
merge: merge file flags together with file content...
r18338 else:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_MERGE,
(f, f, None, False, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'both created',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
merge: don't use unknown()...
r16094 else:
Martin von Zweigbergk
merge: separate out "both created" cases...
r23396 a = ma[f]
fla = ma.flags(f)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 nol = b'l' not in fl1 + fl2 + fla
Martin von Zweigbergk
merge: indent to prepare for next patch
r23395 if n2 == a and fl2 == fla:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_KEEP, (), b'remote unchanged')
Augie Fackler
formatting: blacken the codebase...
r43346 elif n1 == a and fl1 == fla: # local unchanged - use remote
if n1 == n2: # optimization: keep local content
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (
ACTION_EXEC,
(fl2,),
b'update permissions',
)
Martin von Zweigbergk
merge: indent to prepare for next patch
r23395 else:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_GET,
(fl2, False),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'remote is newer',
Augie Fackler
formatting: blacken the codebase...
r43346 )
elif nol and n2 == a: # remote only changed 'x'
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_EXEC, (fl2,), b'update permissions')
Augie Fackler
formatting: blacken the codebase...
r43346 elif nol and n1 == a: # local only changed 'x'
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_GET, (fl1, False), b'remote is newer')
Augie Fackler
formatting: blacken the codebase...
r43346 else: # both changed something
actions[f] = (
ACTION_MERGE,
(f, f, f, False, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'versions differ',
Augie Fackler
formatting: blacken the codebase...
r43346 )
elif n1: # file exists only on local side
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 if f in copied2:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # we'll deal with it on m2 side
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 elif (
f in branch_copies1.movewithdir
): # directory rename, move local
f2 = branch_copies1.movewithdir[f]
Durham Goode
merge: remove unnecessary matcher checks...
r31515 if f2 in m2:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f2] = (
ACTION_MERGE,
(f, f2, None, True, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'remote directory rename, both created',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
merge: don't ignore conflicting file in remote renamed directory...
r23475 else:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f2] = (
ACTION_DIR_RENAME_MOVE_LOCAL,
(f, fl1),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'remote directory rename - move from %s' % f,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 elif f in branch_copies1.copy:
f2 = branch_copies1.copy[f]
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_MERGE,
(f, f2, f2, False, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'local copied/moved from %s' % f2,
Augie Fackler
formatting: blacken the codebase...
r43346 )
elif f in ma: # clean, a different, no remote
Martin von Zweigbergk
merge: branch code into {n1 and n2, n1, n2} top-level cases...
r23473 if n1 != ma[f]:
if acceptremote:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_REMOVE, None, b'remote delete')
Martin von Zweigbergk
merge: branch code into {n1 and n2, n1, n2} top-level cases...
r23473 else:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_CHANGED_DELETED,
(f, None, f, False, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'prompt changed/deleted',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Durham Goode
dirstate: change added/modified placeholder hash length to 20 bytes...
r30361 elif n1 == addednodeid:
Martin von Zweigbergk
merge: branch code into {n1 and n2, n1, n2} top-level cases...
r23473 # This extra 'a' is added by working copy manifest to mark
# the file as locally added. We should forget it instead of
# deleting it.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_FORGET, None, b'remote deleted')
Mads Kiilerich
merge: handle acceptremove of create+delete early in manifest merge
r20639 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_REMOVE, None, b'other deleted')
Augie Fackler
formatting: blacken the codebase...
r43346 elif n2: # file exists only on remote side
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 if f in copied1:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # we'll deal with it on m1 side
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 elif f in branch_copies2.movewithdir:
f2 = branch_copies2.movewithdir[f]
Durham Goode
merge: remove unnecessary matcher checks...
r31515 if f2 in m1:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f2] = (
ACTION_MERGE,
(f2, f, None, False, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'local directory rename, both created',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
merge: don't overwrite conflicting file in locally renamed directory...
r23476 else:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f2] = (
ACTION_LOCAL_DIR_RENAME_GET,
(f, fl2),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'local directory rename - get from %s' % f,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 elif f in branch_copies2.copy:
f2 = branch_copies2.copy[f]
Durham Goode
merge: remove unnecessary matcher checks...
r31515 if f2 in m2:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_MERGE,
(f2, f, f2, False, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'remote copied from %s' % f2,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
merge: branch code into {n1 and n2, n1, n2} top-level cases...
r23473 else:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_MERGE,
(f2, f, f2, True, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'remote moved from %s' % f2,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
merge: branch code into {n1 and n2, n1, n2} top-level cases...
r23473 elif f not in ma:
# local unknown, remote created: the logic is described by the
# following table:
#
# force branchmerge different | action
Martin von Zweigbergk
merge: collect checking for unknown files at end of manifestmerge()...
r23651 # n * * | create
Martin von Zweigbergk
merge: introduce 'c' action like 'g', but with additional safety...
r23650 # y n * | create
# y y n | create
Martin von Zweigbergk
merge: branch code into {n1 and n2, n1, n2} top-level cases...
r23473 # y y y | merge
#
# Checking whether the files are different is expensive, so we
# don't do that when we can avoid it.
Martin von Zweigbergk
merge: structure 'remote created' code to match table...
r23649 if not force:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_CREATED, (fl2,), b'remote created')
Martin von Zweigbergk
merge: structure 'remote created' code to match table...
r23649 elif not branchmerge:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_CREATED, (fl2,), b'remote created')
Martin von Zweigbergk
merge: branch code into {n1 and n2, n1, n2} top-level cases...
r23473 else:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_CREATED_MERGE,
(fl2, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'remote created, get or merge',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
merge: branch code into {n1 and n2, n1, n2} top-level cases...
r23473 elif n2 != ma[f]:
Gábor Stefanik
graft: support grafting changes to new file in renamed directory (issue5436)
r30581 df = None
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 for d in branch_copies1.dirmove:
Gábor Stefanik
graft: support grafting changes to new file in renamed directory (issue5436)
r30581 if f.startswith(d):
# new file added in a directory that was moved
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 df = branch_copies1.dirmove[d] + f[len(d) :]
Gábor Stefanik
graft: support grafting changes to new file in renamed directory (issue5436)
r30581 break
Durham Goode
merge: remove unnecessary matcher checks...
r31515 if df is not None and df in m1:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[df] = (
ACTION_MERGE,
(df, f, f, False, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'local directory rename - respect move '
b'from %s' % f,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gábor Stefanik
graft: support grafting changes to new file in renamed directory (issue5436)
r30581 elif acceptremote:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = (ACTION_CREATED, (fl2,), b'remote recreating')
Siddharth Agarwal
manifestmerge: handle abort on local unknown, remote created files...
r18606 else:
Augie Fackler
formatting: blacken the codebase...
r43346 actions[f] = (
ACTION_DELETED_CHANGED,
(None, f, f, False, pa.node()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'prompt deleted/changed',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
merge: collect checking for unknown files at end of manifestmerge()...
r23651
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if repo.ui.configbool(b'experimental', b'merge.checkpathconflicts'):
Siddharth Agarwal
merge: add a config option to disable path conflict checking...
r34942 # If we are merging, look for path conflicts.
checkpathconflicts(repo, wctx, p2, actions)
Mark Thomas
merge: check for path conflicts when merging (issue5628)...
r34556
Martin von Zweigbergk
narrow: filter merge actions in core...
r38055 narrowmatch = repo.narrowmatch()
if not narrowmatch.always():
# Updates "actions" in place
_filternarrowactions(narrowmatch, branchmerge, actions)
Martin von Zweigbergk
merge: start using the per-side copy dicts...
r44682 renamedelete = branch_copies1.renamedelete
renamedelete.update(branch_copies2.renamedelete)
Martin von Zweigbergk
merge: don't treat 'diverge' and 'renamedelete' like actions...
r23526 return actions, diverge, renamedelete
Matt Mackall
merge: pull manifest comparison out into separate function
r3105
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
merge: extract _resolvetrivial() function...
r23531 def _resolvetrivial(repo, wctx, mctx, ancestor, actions):
"""Resolves false conflicts where the nodeid changed but the content
remained the same."""
Augie Fackler
merge: make a copy of dict.items() before mutating the dict during iteration...
r36334 # We force a copy of actions.items() because we're going to mutate
# actions as we resolve trivial conflicts.
for f, (m, args, msg) in list(actions.items()):
Augie Fackler
formatting: blacken the codebase...
r43346 if (
m == ACTION_CHANGED_DELETED
and f in ancestor
and not wctx[f].cmp(ancestor[f])
):
Martin von Zweigbergk
merge: extract _resolvetrivial() function...
r23531 # local did change but ended up with same content
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actions[f] = ACTION_REMOVE, None, b'prompt same'
Augie Fackler
formatting: blacken the codebase...
r43346 elif (
m == ACTION_DELETED_CHANGED
and f in ancestor
and not mctx[f].cmp(ancestor[f])
):
Martin von Zweigbergk
merge: extract _resolvetrivial() function...
r23531 # remote did change but ended up with same content
Augie Fackler
formatting: blacken the codebase...
r43346 del actions[f] # don't get = keep local deleted
Martin von Zweigbergk
merge: extract _resolvetrivial() function...
r23531
Augie Fackler
formatting: blacken the codebase...
r43346 def calculateupdates(
repo,
wctx,
mctx,
ancestors,
branchmerge,
force,
acceptremote,
followcopies,
matcher=None,
mergeforce=False,
):
Gregory Szorc
sparse: refactor update actions filtering and call from core...
r33323 """Calculate the actions needed to merge mctx into wctx using ancestors"""
# Avoid cycle.
from . import sparse
Augie Fackler
formatting: blacken the codebase...
r43346 if len(ancestors) == 1: # default
Martin von Zweigbergk
merge: don't treat 'diverge' and 'renamedelete' like actions...
r23526 actions, diverge, renamedelete = manifestmerge(
Augie Fackler
formatting: blacken the codebase...
r43346 repo,
wctx,
mctx,
ancestors[0],
branchmerge,
force,
matcher,
acceptremote,
followcopies,
)
Siddharth Agarwal
merge: tell _checkunknownfiles about whether this was merge --force...
r28020 _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce)
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385
Augie Fackler
formatting: blacken the codebase...
r43346 else: # only when merge.preferancestor=* - the default
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 repo.ui.note(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"note: merging %s and %s using bids from ancestors %s\n")
Augie Fackler
formatting: blacken the codebase...
r43346 % (
wctx,
mctx,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b' and ').join(pycompat.bytestr(anc) for anc in ancestors),
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385
# Call for bids
Augie Fackler
formatting: blacken the codebase...
r43346 fbids = (
{}
) # mapping filename to bids (action method to list af actions)
Martin von Zweigbergk
merge: don't treat 'diverge' and 'renamedelete' like actions...
r23526 diverge, renamedelete = None, None
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 for ancestor in ancestors:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b'\ncalculating bids for ancestor %s\n') % ancestor)
Martin von Zweigbergk
merge: don't treat 'diverge' and 'renamedelete' like actions...
r23526 actions, diverge1, renamedelete1 = manifestmerge(
Augie Fackler
formatting: blacken the codebase...
r43346 repo,
wctx,
mctx,
ancestor,
branchmerge,
force,
matcher,
acceptremote,
followcopies,
forcefulldiff=True,
)
Siddharth Agarwal
merge: tell _checkunknownfiles about whether this was merge --force...
r28020 _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce)
Matt Mackall
bidmerge: choose shortest list of diverge and rename/delete warnings...
r26318
# Track the shortest set of warning on the theory that bid
# merge will correctly incorporate more information
if diverge is None or len(diverge1) < len(diverge):
Martin von Zweigbergk
merge: don't treat 'diverge' and 'renamedelete' like actions...
r23526 diverge = diverge1
Matt Mackall
bidmerge: choose shortest list of diverge and rename/delete warnings...
r26318 if renamedelete is None or len(renamedelete) < len(renamedelete1):
Martin von Zweigbergk
merge: don't treat 'diverge' and 'renamedelete' like actions...
r23526 renamedelete = renamedelete1
Matt Mackall
bidmerge: choose shortest list of diverge and rename/delete warnings...
r26318
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, a in sorted(pycompat.iteritems(actions)):
Martin von Zweigbergk
merge: let bid merge work on the file->action dict...
r23638 m, args, msg = a
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b' %s: %s -> %s\n' % (f, msg, m))
Martin von Zweigbergk
merge: let bid merge work on the file->action dict...
r23638 if f in fbids:
d = fbids[f]
if m in d:
d[m].append(a)
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 else:
Martin von Zweigbergk
merge: let bid merge work on the file->action dict...
r23638 d[m] = [a]
else:
fbids[f] = {m: [a]}
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385
# Pick the best bid for each file
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b'\nauction for merging merge bids\n'))
Martin von Zweigbergk
merge: let bid merge work on the file->action dict...
r23638 actions = {}
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 for f, bids in sorted(fbids.items()):
# bids is a mapping from action method to list af actions
# Consensus?
Augie Fackler
formatting: blacken the codebase...
r43346 if len(bids) == 1: # all bids are the same kind of method
Pulkit Goyal
py3: explicitly convert dict.keys() and dict.items() into a list...
r34350 m, l = list(bids.items())[0]
Augie Fackler
formatting: blacken the codebase...
r43346 if all(a == l[0] for a in l[1:]): # len(bids) is > 1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b" %s: consensus for %s\n") % (f, m))
Martin von Zweigbergk
merge: let bid merge work on the file->action dict...
r23638 actions[f] = l[0]
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 continue
# If keep is an option, just do it.
Gregory Szorc
merge: use constants for actions...
r37130 if ACTION_KEEP in bids:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b" %s: picking 'keep' action\n") % f)
Gregory Szorc
merge: use constants for actions...
r37130 actions[f] = bids[ACTION_KEEP][0]
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 continue
# If there are gets and they all agree [how could they not?], do it.
Gregory Szorc
merge: use constants for actions...
r37130 if ACTION_GET in bids:
ga0 = bids[ACTION_GET][0]
if all(a == ga0 for a in bids[ACTION_GET][1:]):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b" %s: picking 'get' action\n") % f)
Martin von Zweigbergk
merge: let bid merge work on the file->action dict...
r23638 actions[f] = ga0
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 continue
# TODO: Consider other simple actions such as mode changes
# Handle inefficient democrazy.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b' %s: multiple bids for merge action:\n') % f)
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 for m, l in sorted(bids.items()):
for _f, args, msg in l:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(b' %s -> %s\n' % (msg, m))
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 # Pick random action. TODO: Instead, prompt user when resolving
Pulkit Goyal
py3: explicitly convert dict.keys() and dict.items() into a list...
r34350 m, l = list(bids.items())[0]
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b' %s: ambiguous merge - picked %s action\n') % (f, m)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
merge: let bid merge work on the file->action dict...
r23638 actions[f] = l[0]
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385 continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b'end of auction\n\n'))
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385
Martin von Zweigbergk
merge: let _forgetremoved() work on the file->action dict...
r23640 if wctx.rev() is None:
fractions = _forgetremoved(wctx, mctx, branchmerge)
actions.update(fractions)
Augie Fackler
formatting: blacken the codebase...
r43346 prunedactions = sparse.filterupdatesactions(
repo, wctx, mctx, branchmerge, actions
)
Pulkit Goyal
merge: do the trivial resolution after updating sparse checkout...
r38780 _resolvetrivial(repo, wctx, mctx, ancestors[0], actions)
Gregory Szorc
sparse: refactor update actions filtering and call from core...
r33323
return prunedactions, diverge, renamedelete
Martin von Zweigbergk
merge: move calculateupdates() before applyupdated()...
r23385
Augie Fackler
formatting: blacken the codebase...
r43346
Phil Cohen
merge: move cwd-missing detection to helper functions...
r34144 def _getcwd():
try:
Matt Harbison
py3: rename pycompat.getcwd() to encoding.getcwd() (API)...
r39843 return encoding.getcwd()
Phil Cohen
merge: move cwd-missing detection to helper functions...
r34144 except OSError as err:
if err.errno == errno.ENOENT:
return None
raise
Augie Fackler
formatting: blacken the codebase...
r43346
Phil Cohen
merge: pass wctx to batchremove and batchget...
r33081 def batchremove(repo, wctx, actions):
Mads Kiilerich
merge: separate worker functions for batch remove and batch get...
r21392 """apply removes to the working directory
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630
yields tuples for progress updates
"""
Bryan O'Sullivan
merge: don't fiddle with name lookups or i18n in hot loops...
r18640 verbose = repo.ui.verbose
Phil Cohen
merge: move cwd-missing detection to helper functions...
r34144 cwd = _getcwd()
Bryan O'Sullivan
merge: report non-interactive progress in chunks...
r18633 i = 0
Mads Kiilerich
merge: use separate lists for each action type...
r21545 for f, args, msg in actions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> r\n" % (f, msg))
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 if verbose:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b"removing %s\n") % f)
Phil Cohen
workingfilectx: add audit() as a wrapper for wvfs.audit()
r33086 wctx[f].audit()
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 try:
Phil Cohen
merge: replace repo.wvfs.unlinkpath() with calls to wctx[f].remove()...
r33082 wctx[f].remove(ignoremissing=True)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as inst:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"update failed to remove %s: %s!\n") % (f, inst.strerror)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mads Kiilerich
merge: separate worker functions for batch remove and batch get...
r21392 if i == 100:
yield i, f
i = 0
i += 1
if i > 0:
yield i, f
Phil Cohen
merge: move cwd-missing detection to helper functions...
r34144
if cwd and not _getcwd():
# cwd was removed in the course of removing files; print a helpful
# warning.
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"current directory was removed\n"
b"(consider changing to repo root: %s)\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% repo.root
)
Mads Kiilerich
merge: separate worker functions for batch remove and batch get...
r21392
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 def batchget(repo, mctx, wctx, wantfiledata, actions):
Mads Kiilerich
merge: separate worker functions for batch remove and batch get...
r21392 """apply gets to the working directory
mctx is the context to get from
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 Yields arbitrarily many (False, tuple) for progress updates, followed by
exactly one (True, filedata). When wantfiledata is false, filedata is an
Valentin Gatien-Baron
update: fix spurious unclean status bug shown by previous commit...
r42722 empty dict. When wantfiledata is true, filedata[f] is a triple (mode, size,
mtime) of the file f written for each action.
Mads Kiilerich
merge: separate worker functions for batch remove and batch get...
r21392 """
Valentin Gatien-Baron
update: fix spurious unclean status bug shown by previous commit...
r42722 filedata = {}
Mads Kiilerich
merge: separate worker functions for batch remove and batch get...
r21392 verbose = repo.ui.verbose
fctx = mctx.filectx
Siddharth Agarwal
batchget: add support for backing up files...
r27656 ui = repo.ui
Mads Kiilerich
merge: separate worker functions for batch remove and batch get...
r21392 i = 0
Gregory Szorc
merge: perform background file closing in batchget...
r28200 with repo.wvfs.backgroundclosing(ui, expectedcount=len(actions)):
Gregory Szorc
merge: indent code in batchget()...
r28199 for f, (flags, backup), msg in actions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> g\n" % (f, msg))
Gregory Szorc
merge: indent code in batchget()...
r28199 if verbose:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b"getting %s\n") % f)
Siddharth Agarwal
batchget: add support for backing up files...
r27656
Gregory Szorc
merge: indent code in batchget()...
r28199 if backup:
Mark Thomas
merge: backup conflicting directories when getting files...
r34550 # If a file or directory exists with the same name, back that
# up. Otherwise, look to see if there is a file that conflicts
# with a directory this file is in, and if so, back that up.
Martin von Zweigbergk
merge: don't unnecessarily calculate absolute path...
r41711 conflicting = f
Mark Thomas
merge: backup conflicting directories when getting files...
r34550 if not repo.wvfs.lexists(f):
Martin von Zweigbergk
utils: move finddirs() to pathutil...
r44032 for p in pathutil.finddirs(f):
Mark Thomas
merge: backup conflicting directories when getting files...
r34550 if repo.wvfs.isfileorlink(p):
Martin von Zweigbergk
merge: don't unnecessarily calculate absolute path...
r41711 conflicting = p
Mark Thomas
merge: backup conflicting directories when getting files...
r34550 break
Martin von Zweigbergk
merge: don't unnecessarily calculate absolute path...
r41711 if repo.wvfs.lexists(conflicting):
Martin von Zweigbergk
merge: migrate to scmutil.backuppath()...
r41750 orig = scmutil.backuppath(ui, repo, conflicting)
util.rename(repo.wjoin(conflicting), orig)
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 wfctx = wctx[f]
wfctx.clearunknown()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 atomictemp = ui.configbool(b"experimental", b"update.atomic-file")
Augie Fackler
formatting: blacken the codebase...
r43346 size = wfctx.write(
fctx(f).data(),
flags,
backgroundclose=True,
atomictemp=atomictemp,
)
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 if wantfiledata:
s = wfctx.lstat()
mode = s.st_mode
mtime = s[stat.ST_MTIME]
Augie Fackler
formatting: blacken the codebase...
r43346 filedata[f] = (mode, size, mtime) # for dirstate.normal
Gregory Szorc
merge: indent code in batchget()...
r28199 if i == 100:
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 yield False, (i, f)
Gregory Szorc
merge: indent code in batchget()...
r28199 i = 0
i += 1
Bryan O'Sullivan
merge: report non-interactive progress in chunks...
r18633 if i > 0:
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 yield False, (i, f)
yield True, filedata
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
merge: invoke scmutil.fileprefetchhooks() prior to applying updates...
r36159 def _prefetchfiles(repo, ctx, actions):
Matt Harbison
scmutil: teach the file prefetch hook to handle multiple commits...
r37780 """Invoke ``scmutil.prefetchfiles()`` for the files relevant to the dict
Matt Harbison
merge: invoke scmutil.fileprefetchhooks() prior to applying updates...
r36159 of merge actions. ``ctx`` is the context being merged in."""
# Skipping 'a', 'am', 'f', 'r', 'dm', 'e', 'k', 'p' and 'pr', because they
# don't touch the context to be merged in. 'cd' is skipped, because
# changed/deleted never resolves to something from the remote side.
Augie Fackler
formatting: blacken the codebase...
r43346 oplist = [
actions[a]
for a in (
ACTION_GET,
ACTION_DELETED_CHANGED,
ACTION_LOCAL_DIR_RENAME_GET,
ACTION_MERGE,
)
]
Matt Harbison
scmutil: teach the file prefetch hook to handle multiple commits...
r37780 prefetch = scmutil.prefetchfiles
matchfiles = scmutil.matchfiles
Augie Fackler
formatting: blacken the codebase...
r43346 prefetch(
repo,
[ctx.rev()],
matchfiles(repo, [f for sublist in oplist for f, args, msg in sublist]),
)
Phil Cohen
merge: flush any deferred writes before, and after, running any workers...
r34126
Gregory Szorc
merge: return an attrs class from update() and applyupdates()...
r37125 @attr.s(frozen=True)
class updateresult(object):
updatedcount = attr.ib()
mergedcount = attr.ib()
removedcount = attr.ib()
unresolvedcount = attr.ib()
Gregory Szorc
merge: deprecate accessing update results by index...
r37143 def isempty(self):
Augie Fackler
formatting: blacken the codebase...
r43346 return not (
self.updatedcount
or self.mergedcount
or self.removedcount
or self.unresolvedcount
)
Gregory Szorc
merge: deprecate accessing update results by index...
r37143
Martin von Zweigbergk
merge: extract helper for creating empty "actions" dict...
r41068 def emptyactions():
"""create an actions dict, to be populated and passed to applyupdates()"""
Augie Fackler
cleanup: run pyupgrade on our source tree to clean up varying things...
r44937 return {
m: []
Augie Fackler
formatting: blacken the codebase...
r43346 for m in (
ACTION_ADD,
ACTION_ADD_MODIFIED,
ACTION_FORGET,
ACTION_GET,
ACTION_CHANGED_DELETED,
ACTION_DELETED_CHANGED,
ACTION_REMOVE,
ACTION_DIR_RENAME_MOVE_LOCAL,
ACTION_LOCAL_DIR_RENAME_GET,
ACTION_MERGE,
ACTION_EXEC,
ACTION_KEEP,
ACTION_PATH_CONFLICT,
ACTION_PATH_CONFLICT_RESOLVE,
)
Augie Fackler
cleanup: run pyupgrade on our source tree to clean up varying things...
r44937 }
Martin von Zweigbergk
merge: extract helper for creating empty "actions" dict...
r41068
Augie Fackler
formatting: blacken the codebase...
r43346
def applyupdates(
repo, actions, wctx, mctx, overwrite, wantfiledata, labels=None
):
Peter Arrenbrecht
merge: pass constant cset ancestor to fctx.ancestor
r11454 """apply the merge action list to the working directory
wctx is the working copy context
mctx is the context to be merged into the working copy
Greg Ward
merge: document some internal return values.
r13162
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 Return a tuple of (counts, filedata), where counts is a tuple
(updated, merged, removed, unresolved) that describes how many
files were affected by the update, and filedata is as described in
batchget.
Peter Arrenbrecht
merge: pass constant cset ancestor to fctx.ancestor
r11454 """
Matt Mackall
merge: update some docstrings
r3315
Matt Harbison
merge: invoke scmutil.fileprefetchhooks() prior to applying updates...
r36159 _prefetchfiles(repo, mctx, actions)
Siddharth Agarwal
merge.applyupdates: use counters from mergestate...
r27078 updated, merged, removed = 0, 0, 0
Simon Farnsworth
merge: save merge part labels for later reuse...
r28634 ms = mergestate.clean(repo, wctx.p1().node(), mctx.node(), labels)
Matt Mackall
merge: introduce mergestate
r6512 moves = []
Mads Kiilerich
merge: use separate lists for each action type...
r21545 for m, l in actions.items():
l.sort()
Matt Mackall
merge: introduce mergestate
r6512
Siddharth Agarwal
merge: move almost all change/delete conflicts to resolve phase (BC) (API)...
r27137 # 'cd' and 'dc' actions are treated like other merge conflicts
Gregory Szorc
merge: use constants for actions...
r37130 mergeactions = sorted(actions[ACTION_CHANGED_DELETED])
mergeactions.extend(sorted(actions[ACTION_DELETED_CHANGED]))
mergeactions.extend(actions[ACTION_MERGE])
Siddharth Agarwal
merge: move almost all change/delete conflicts to resolve phase (BC) (API)...
r27137 for f, args, msg in mergeactions:
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 f1, f2, fa, move, anc = args
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if f == b'.hgsubstate': # merged internally
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 continue
Siddharth Agarwal
merge.applyupdates: create absentfilectxes for change/delete conflicts...
r27091 if f1 is None:
fcl = filemerge.absentfilectx(wctx, fa)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" preserving %s for resolve of %s\n" % (f1, f))
Siddharth Agarwal
merge.applyupdates: create absentfilectxes for change/delete conflicts...
r27091 fcl = wctx[f1]
if f2 is None:
fco = filemerge.absentfilectx(mctx, fa)
else:
fco = mctx[f2]
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 actx = repo[anc]
if fa in actx:
fca = actx[fa]
else:
Siddharth Agarwal
merge.applyupdates: create absentfilectxes for change/delete conflicts...
r27091 # TODO: move to absentfilectx
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 fca = repo.filectx(f1, fileid=nullrev)
ms.add(fcl, fco, fca, f)
if f1 != f and move:
moves.append(f1)
Matt Mackall
merge: introduce mergestate
r6512
# remove renamed files after safely stored
for f in moves:
Phil Cohen
workingfilectx: add exists, lexists...
r33283 if wctx[f].lexists():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"removing %s\n" % f)
Phil Cohen
workingfilectx: add audit() as a wrapper for wvfs.audit()
r33086 wctx[f].audit()
Phil Cohen
merge: replace repo.wvfs.unlinkpath() with calls to wctx[f].remove()...
r33082 wctx[f].remove()
Matt Mackall
merge: do early copy to deal with issue636...
r5042
Augie Fackler
formatting: blacken the codebase...
r43346 numupdates = sum(len(l) for m, l in actions.items() if m != ACTION_KEEP)
progress = repo.ui.makeprogress(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'updating'), unit=_(b'files'), total=numupdates
Augie Fackler
formatting: blacken the codebase...
r43346 )
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if [a for a in actions[ACTION_REMOVE] if a[0] == b'.hgsubstate']:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 subrepoutil.submerge(repo, wctx, mctx, wctx, overwrite, labels)
Bryan O'Sullivan
merge: handle subrepo merges and .hgsubstate specially...
r18632
Mark Thomas
merge: add merge action 'p' to record path conflicts during update...
r34548 # record path conflicts
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_PATH_CONFLICT]:
Mark Thomas
merge: add merge action 'p' to record path conflicts during update...
r34548 f1, fo = args
s = repo.ui.status
Augie Fackler
formatting: blacken the codebase...
r43346 s(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"%s: path conflict - a file or link has the same name as a "
b"directory\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% f
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if fo == b'l':
s(_(b"the local file has been renamed to %s\n") % f1)
Mark Thomas
merge: add merge action 'p' to record path conflicts during update...
r34548 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 s(_(b"the remote file has been renamed to %s\n") % f1)
s(_(b"resolve manually then use 'hg resolve --mark %s'\n") % f)
Mark Thomas
merge: add merge action 'p' to record path conflicts during update...
r34548 ms.addpath(f, f1, fo)
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f)
Mark Thomas
merge: add merge action 'p' to record path conflicts during update...
r34548
Phil Cohen
merge: don't use workers in in-memory mode...
r34787 # When merging in-memory, we can't support worker processes, so set the
# per-item cost at 0 in that case.
cost = 0 if wctx.isinmemory() else 0.001
Mark Thomas
merge: add merge action 'pr' to rename files during update...
r34549 # remove in parallel (must come before resolving path conflicts and getting)
Augie Fackler
formatting: blacken the codebase...
r43346 prog = worker.worker(
repo.ui, cost, batchremove, (repo, wctx), actions[ACTION_REMOVE]
)
FUJIWARA Katsunori
merge: increase safety of parallel updating/removing on icasefs...
r19095 for i, item in prog:
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(step=i, item=item)
Gregory Szorc
merge: use constants for actions...
r37130 removed = len(actions[ACTION_REMOVE])
Mads Kiilerich
merge: move constant assignments a bit and use them more
r21390
Mark Thomas
merge: add merge action 'pr' to rename files during update...
r34549 # resolve path conflicts (must come before getting)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_PATH_CONFLICT_RESOLVE]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> pr\n" % (f, msg))
Augie Fackler
formatting: blacken the codebase...
r43346 (f0,) = args
Mark Thomas
merge: add merge action 'pr' to rename files during update...
r34549 if wctx[f0].lexists():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b"moving %s to %s\n") % (f0, f))
Mark Thomas
merge: add merge action 'pr' to rename files during update...
r34549 wctx[f].audit()
wctx[f].write(wctx.filectx(f0).data(), wctx.filectx(f0).flags())
wctx[f0].remove()
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f)
Mark Thomas
merge: add merge action 'pr' to rename files during update...
r34549
Gregory Szorc
merge: mark file gets as not thread safe (issue5933)...
r38755 # get in parallel.
Augie Fackler
formatting: blacken the codebase...
r43346 threadsafe = repo.ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'experimental', b'worker.wdir-get-thread-safe'
Augie Fackler
formatting: blacken the codebase...
r43346 )
prog = worker.worker(
repo.ui,
cost,
batchget,
(repo, mctx, wctx, wantfiledata),
actions[ACTION_GET],
threadsafe=threadsafe,
hasretval=True,
)
Valentin Gatien-Baron
update: fix spurious unclean status bug shown by previous commit...
r42722 getfiledata = {}
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 for final, res in prog:
if final:
getfiledata = res
else:
i, item = res
progress.increment(step=i, item=item)
Gregory Szorc
merge: use constants for actions...
r37130 updated = len(actions[ACTION_GET])
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if [a for a in actions[ACTION_GET] if a[0] == b'.hgsubstate']:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 subrepoutil.submerge(repo, wctx, mctx, wctx, overwrite, labels)
Bryan O'Sullivan
merge: handle subrepo merges and .hgsubstate specially...
r18632
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # forget (manifest only, just log it) (must come first)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_FORGET]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> f\n" % (f, msg))
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # re-add (manifest only, just log it)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_ADD]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> a\n" % (f, msg))
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Siddharth Agarwal
merge: add a new action type representing files to add/mark as modified...
r27131 # re-add/mark as modified (manifest only, just log it)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_ADD_MODIFIED]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> am\n" % (f, msg))
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f)
Siddharth Agarwal
merge: add a new action type representing files to add/mark as modified...
r27131
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # keep (noop, just log it)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_KEEP]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> k\n" % (f, msg))
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # no progress
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # directory rename, move local
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_DIR_RENAME_MOVE_LOCAL]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> dm\n" % (f, msg))
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f)
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 f0, flags = args
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b"moving %s to %s\n") % (f0, f))
Phil Cohen
workingfilectx: add audit() as a wrapper for wvfs.audit()
r33086 wctx[f].audit()
Phil Cohen
merge: convert repo.wwrite() calls to wctx[f].write()...
r33083 wctx[f].write(wctx.filectx(f0).data(), flags)
Phil Cohen
merge: replace repo.wvfs.unlinkpath() with calls to wctx[f].remove()...
r33082 wctx[f0].remove()
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 updated += 1
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # local directory rename, get
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_LOCAL_DIR_RENAME_GET]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> dg\n" % (f, msg))
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f)
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 f0, flags = args
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b"getting %s to %s\n") % (f0, f))
Phil Cohen
merge: convert repo.wwrite() calls to wctx[f].write()...
r33083 wctx[f].write(mctx.filectx(f0).data(), flags)
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 updated += 1
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # exec
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions[ACTION_EXEC]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> e\n" % (f, msg))
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f)
Augie Fackler
formatting: blacken the codebase...
r43346 (flags,) = args
Phil Cohen
workingfilectx: add audit() as a wrapper for wvfs.audit()
r33086 wctx[f].audit()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 wctx[f].setflags(b'l' in flags, b'x' in flags)
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 updated += 1
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Siddharth Agarwal
merge.applyupdates: call driverpreprocess before starting merge actions...
r26786 # 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:
Phil Cohen
merge: raise before running mergedriver if using IMM...
r35516 if wctx.isinmemory():
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.InMemoryMergeConflictsError(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b"in-memory merge does not support mergedriver"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Siddharth Agarwal
merge.applyupdates: call driverpreprocess before starting merge actions...
r26786 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
Augie Fackler
formatting: blacken the codebase...
r43346 return updateresult(
updated, merged, removed, max(len(unresolvedf), 1)
)
Siddharth Agarwal
merge.applyupdates: call driverpreprocess before starting merge actions...
r26786 newactions = []
for f, args, msg in mergeactions:
if f in unresolvedf:
newactions.append((f, args, msg))
mergeactions = newactions
Ryan McElroy
merge: ensure that we always commit the mergestate...
r34681 try:
# premerge
tocomplete = []
for f, args, msg in mergeactions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> m (premerge)\n" % (f, msg))
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if f == b'.hgsubstate': # subrepo states need updating
Augie Fackler
formatting: blacken the codebase...
r43346 subrepoutil.submerge(
repo, wctx, mctx, wctx.ancestor(mctx), overwrite, labels
)
Ryan McElroy
merge: ensure that we always commit the mergestate...
r34681 continue
wctx[f].audit()
complete, r = ms.preresolve(f, wctx)
if not complete:
numupdates += 1
tocomplete.append((f, args, msg))
Siddharth Agarwal
merge.mergestate: perform all premerges before any merges (BC)...
r26618
Ryan McElroy
merge: ensure that we always commit the mergestate...
r34681 # merge
for f, args, msg in tocomplete:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" %s: %s -> m (merge)\n" % (f, msg))
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 progress.increment(item=f, total=numupdates)
Ryan McElroy
merge: ensure that we always commit the mergestate...
r34681 ms.resolve(f, wctx)
Siddharth Agarwal
merge: move merge step to the end...
r26292
Ryan McElroy
merge: ensure that we always commit the mergestate...
r34681 finally:
ms.commit()
Siddharth Agarwal
merge.applyupdates: call driverconclude after performing merge actions...
r26787
Siddharth Agarwal
merge.applyupdates: use counters from mergestate...
r27078 unresolved = ms.unresolvedcount()
Augie Fackler
formatting: blacken the codebase...
r43346 if (
usemergedriver
and not unresolved
and ms.mdstate() != MERGE_DRIVER_STATE_SUCCESS
):
Siddharth Agarwal
merge.applyupdates: call driverconclude after performing merge actions...
r26787 if not driverconclude(repo, ms, wctx, labels=labels):
# XXX setting unresolved to at least 1 is a hack to make sure we
# error out
Siddharth Agarwal
merge.applyupdates: don't return early if merge driver's conclude failed...
r26975 unresolved = max(unresolved, 1)
Siddharth Agarwal
merge.applyupdates: call driverconclude after performing merge actions...
r26787
ms.commit()
Siddharth Agarwal
merge.applyupdates: use counters from mergestate...
r27078 msupdated, msmerged, msremoved = ms.counts()
updated += msupdated
merged += msmerged
removed += msremoved
Siddharth Agarwal
merge.applyupdates: extend action queues with ones returned from mergestate...
r27080
extraactions = ms.actions()
Siddharth Agarwal
merge: remove files with extra actions from merge action list...
r29831 if extraactions:
Augie Fackler
cleanup: run pyupgrade on our source tree to clean up varying things...
r44937 mfiles = {a[0] for a in actions[ACTION_MERGE]}
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for k, acts in pycompat.iteritems(extraactions):
Siddharth Agarwal
merge: remove files with extra actions from merge action list...
r29831 actions[k].extend(acts)
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 if k == ACTION_GET and wantfiledata:
# no filedata until mergestate is updated to provide it
Valentin Gatien-Baron
update: fix spurious unclean status bug shown by previous commit...
r42722 for a in acts:
getfiledata[a[0]] = None
Gregory Szorc
merge: use constants for actions...
r37130 # 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).
Siddharth Agarwal
merge: remove files with extra actions from merge action list...
r29831 #
# 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)
Augie Fackler
formatting: blacken the codebase...
r43346 actions[ACTION_MERGE] = [
a for a in actions[ACTION_MERGE] if a[0] in mfiles
]
Siddharth Agarwal
merge.applyupdates: extend action queues with ones returned from mergestate...
r27080
Martin von Zweigbergk
progress: hide update(None) in a new complete() method...
r38392 progress.complete()
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 assert len(getfiledata) == (len(actions[ACTION_GET]) if wantfiledata else 0)
return updateresult(updated, merged, removed, unresolved), getfiledata
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111
Augie Fackler
formatting: blacken the codebase...
r43346
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 def recordupdates(repo, actions, branchmerge, getfiledata):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """record merge actions to the dirstate"""
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # remove (must come first)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_REMOVE, []):
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 if branchmerge:
repo.dirstate.remove(f)
else:
Mads Kiilerich
merge: change priority / ordering of merge actions...
r21389 repo.dirstate.drop(f)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # forget (must come first)
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_FORGET, []):
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 repo.dirstate.drop(f)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mark Thomas
merge: add merge action 'pr' to rename files during update...
r34549 # resolve path conflicts
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_PATH_CONFLICT_RESOLVE, []):
Augie Fackler
formatting: blacken the codebase...
r43346 (f0,) = args
Mark Thomas
merge: add merge action 'pr' to rename files during update...
r34549 origf0 = repo.dirstate.copied(f0) or f0
repo.dirstate.add(f)
repo.dirstate.copy(origf0, f)
if f0 == origf0:
repo.dirstate.remove(f0)
else:
repo.dirstate.drop(f0)
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # re-add
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_ADD, []):
Siddharth Agarwal
merge.recordupdates: mark 'a' files as added unconditionally...
r27132 repo.dirstate.add(f)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Siddharth Agarwal
merge: add a new action type representing files to add/mark as modified...
r27131 # re-add/mark as modified
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_ADD_MODIFIED, []):
Siddharth Agarwal
merge: add a new action type representing files to add/mark as modified...
r27131 if branchmerge:
repo.dirstate.normallookup(f)
else:
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 repo.dirstate.add(f)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # exec change
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_EXEC, []):
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 repo.dirstate.normallookup(f)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # keep
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_KEEP, []):
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 pass
# get
Valentin Gatien-Baron
update: fix spurious unclean status bug shown by previous commit...
r42722 for f, args, msg in actions.get(ACTION_GET, []):
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 if branchmerge:
repo.dirstate.otherparent(f)
else:
Valentin Gatien-Baron
update: fix spurious unclean status bug shown by previous commit...
r42722 parentfiledata = getfiledata[f] if getfiledata else None
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 repo.dirstate.normal(f, parentfiledata=parentfiledata)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # merge
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_MERGE, []):
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 f1, f2, fa, move, anc = args
if branchmerge:
# We've done a branch merge, mark this file as merged
# so that we properly record the merger later
repo.dirstate.merge(f)
Augie Fackler
formatting: blacken the codebase...
r43346 if f1 != f2: # copy/rename
Matt Mackall
merge: unify merge and copy actions
r3308 if move:
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 repo.dirstate.remove(f1)
if f1 != f:
repo.dirstate.copy(f1, f)
else:
repo.dirstate.copy(f2, f)
else:
# We've update-merged a locally modified file, so
# we set the dirstate to emulate a normal checkout
# of that file some time in the past. Thus our
# merge will appear as a normal local file
# modification.
Augie Fackler
formatting: blacken the codebase...
r43346 if f2 == f: # file not locally copied/moved
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 repo.dirstate.normallookup(f)
if move:
repo.dirstate.drop(f1)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # directory rename, move local
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_DIR_RENAME_MOVE_LOCAL, []):
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 f0, flag = args
if branchmerge:
repo.dirstate.add(f)
repo.dirstate.remove(f0)
repo.dirstate.copy(f0, f)
else:
repo.dirstate.normal(f)
repo.dirstate.drop(f0)
Mads Kiilerich
merge: change debug logging - test output changes but no real changes...
r21391
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 # directory rename, get
Gregory Szorc
merge: use constants for actions...
r37130 for f, args, msg in actions.get(ACTION_LOCAL_DIR_RENAME_GET, []):
Mads Kiilerich
merge: fix stupid indentation left over from previous refactorings
r21551 f0, flag = args
if branchmerge:
repo.dirstate.add(f)
repo.dirstate.copy(f0, f)
else:
repo.dirstate.normal(f)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 UPDATECHECK_ABORT = b'abort' # handled at higher layers
UPDATECHECK_NONE = b'none'
UPDATECHECK_LINEAR = b'linear'
UPDATECHECK_NO_CONFLICT = b'noconflict'
Augie Fackler
merge: replace magic strings with NAMED_CONSTANTS (API)...
r43240
Augie Fackler
formatting: blacken the codebase...
r43346
def update(
repo,
node,
branchmerge,
force,
ancestor=None,
mergeancestor=False,
labels=None,
matcher=None,
mergeforce=False,
Martin von Zweigbergk
merge: introduce a revert_to() for that use-case...
r44744 updatedirstate=True,
Augie Fackler
formatting: blacken the codebase...
r43346 updatecheck=None,
wc=None,
):
Matt Mackall
merge: update some docstrings
r3315 """
Perform a merge between the working directory and the given node
Martin von Zweigbergk
merge: remove unused handling of default destination in merge.update()...
r30902 node = the node to update to
Matt Mackall
merge: update some docstrings
r3315 branchmerge = whether to merge between branches
force = whether to force branch merging or file overwriting
Augie Fackler
merge: have merge.update use a matcher instead of partial fn...
r27344 matcher = a matcher to filter file lists (dirstate not updated)
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 mergeancestor = whether it is merging with an ancestor. If true,
we should accept the incoming changes for any prompts that occur.
If false, merging with an ancestor (fast-forward) is only allowed
between different named branches. This flag is used by rebase extension
as a temporary fix and should be avoided in general.
Siddharth Agarwal
merge: add missing doc for 'labels' parameter
r28019 labels = labels to use for base, local and other
Siddharth Agarwal
merge: tell _checkunknownfiles about whether this was merge --force...
r28020 mergeforce = whether the merge was run with 'merge --force' (deprecated): if
this is True, then 'force' should be True as well.
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716
muxator
update: mention long options explicitly in description of merge.update()...
r34920 The table below shows all the behaviors of the update command given the
-c/--check and -C/--clean or no options, whether the working directory is
dirty, whether a revision is specified, and the relationship of the parent
rev to the target rev (linear or not). Match from top first. The -n
option doesn't exist on the command line, but represents the
Martin von Zweigbergk
update: allow setting default update check to "noconflict"...
r31168 experimental.updatecheck=noconflict option.
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716
Adrian Buehlmann
combine tests
r12279 This logic is tested by test-update-branches.t.
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716
Martin von Zweigbergk
update: allow setting default update check to "noconflict"...
r31168 -c -C -n -m dirty rev linear | result
y y * * * * * | (1)
y * y * * * * | (1)
y * * y * * * | (1)
* y y * * * * | (1)
* y * y * * * | (1)
* * y y * * * | (1)
* * * * * n n | x
* * * * n * * | ok
n n n n y * y | merge
n n n n y y n | (2)
n n n y y * * | merge
n n y n y * * | merge if no conflict
n y n n y * * | discard
y n n n y * * | (3)
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716
x = can't happen
* = don't-care
Martin von Zweigbergk
merge: move "incompatible options" case first in docstring table
r31161 1 = incompatible options (checked in commands.py)
2 = abort: uncommitted changes (commit or update --clean to discard changes)
3 = abort: uncommitted changes (checked in commands.py)
Greg Ward
merge: document some internal return values.
r13162
Phil Cohen
merge: allow a custom working context to be passed to update...
r34303 The merge is performed inside ``wc``, a workingctx-like objects. It defaults
to repo[None] if None is passed.
Greg Ward
merge: document some internal return values.
r13162 Return the same tuple as applyupdates().
Matt Mackall
merge: update some docstrings
r3315 """
Gregory Szorc
sparse: move pruning of temporary includes into core...
r33321 # Avoid cycle.
from . import sparse
Matt Mackall
Merge: combine force and forcemerge arguments
r2815
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166 # This function used to find the default destination if node was None, but
Martin von Zweigbergk
merge: remove unused handling of default destination in merge.update()...
r30902 # that's now in destutil.py.
assert node is not None
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166 if not branchmerge and not force:
# TODO: remove the default once all callers that pass branchmerge=False
# and force=False pass a value for updatecheck. We may want to allow
# updatecheck='abort' to better suppport some of these callers.
if updatecheck is None:
Augie Fackler
merge: replace magic strings with NAMED_CONSTANTS (API)...
r43240 updatecheck = UPDATECHECK_LINEAR
Augie Fackler
formatting: blacken the codebase...
r43346 if updatecheck not in (
UPDATECHECK_NONE,
UPDATECHECK_LINEAR,
UPDATECHECK_NO_CONFLICT,
Augie Fackler
merge: check argument value with if/raise instead of an assert...
r43242 ):
Augie Fackler
formatting: blacken the codebase...
r43346 raise ValueError(
r'Invalid updatecheck %r (can accept %r)'
% (
updatecheck,
(
UPDATECHECK_NONE,
UPDATECHECK_LINEAR,
UPDATECHECK_NO_CONFLICT,
),
)
)
Bryan O'Sullivan
with: use context manager in merge update
r27852 with repo.wlock():
Phil Cohen
merge: allow a custom working context to be passed to update...
r34303 if wc is None:
wc = repo[None]
Sean Farley
merge: refactor initialization of variables in update...
r20279 pl = wc.parents()
p1 = pl[0]
Martin von Zweigbergk
merge: reorder some initialization to make more sense...
r42601 p2 = repo[node]
Mads Kiilerich
merge: 0 is a valid ancestor different from None...
r23405 if ancestor is not None:
Mads Kiilerich
merge: pass merge ancestor to calculateupdates as a list...
r21081 pas = [repo[ancestor]]
Martin von Zweigbergk
merge: simplify initialization of "pas"...
r42602 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if repo.ui.configlist(b'merge', b'preferancestor') == [b'*']:
Mads Kiilerich
merge: with merge.preferancestor=*, run an auction with bids from ancestors...
r21128 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
else:
Mads Kiilerich
merge: show the scary multiple ancestor hint for merges only, not for updates...
r22179 pas = [p1.ancestor(p2, warn=branchmerge)]
Matt Mackall
merge: add ancestor to the update function...
r13874
Augie Fackler
merge: coerce nodes to bytes, not str...
r36195 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), bytes(p1), bytes(p2)
Matt Mackall
merge: various tidying...
r3314
Martin von Zweigbergk
merge: reorder some initialization to make more sense...
r42601 overwrite = force and not branchmerge
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 ### check phase
Martin von Zweigbergk
merge: refuse update/merge if there are unresolved conflicts (BC)...
r27316 if not overwrite:
if len(pl) > 1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"outstanding uncommitted merge"))
Martin von Zweigbergk
merge: refuse update/merge if there are unresolved conflicts (BC)...
r27316 ms = mergestate.read(repo)
if list(ms.unresolved()):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"outstanding merge conflicts"),
hint=_(b"use 'hg resolve' to resolve"),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
update: better logic and messages for updates...
r6375 if branchmerge:
Mads Kiilerich
merge: pass merge ancestor to calculateupdates as a list...
r21081 if pas == [p2]:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"merging with a working directory ancestor"
b" has no effect"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Mads Kiilerich
merge: pass merge ancestor to calculateupdates as a list...
r21081 elif pas == [p1]:
Mads Kiilerich
merge: check current wc branch for 'nothing to merge', not its p1...
r31379 if not mergeancestor and wc.branch() == p2.branch():
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"nothing to merge"),
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 hint=_(b"use 'hg update' or check 'hg heads'"),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
update: better logic and messages for updates...
r6375 if not force and (wc.files() or wc.deleted()):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"uncommitted changes"),
hint=_(b"use 'hg status' to list changes"),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Phil Cohen
merge: skip subrepo state, update hooks, and updating the dirstate in IMM...
r35285 if not wc.isinmemory():
for s in sorted(wc.substate):
wc.sub(s).bailifchanged()
Oleg Stepanov
Do not allow merging with uncommitted changes in a subrepo
r13437
Matt Mackall
update: better logic and messages for updates...
r6375 elif not overwrite:
Augie Fackler
formatting: blacken the codebase...
r43346 if p1 == p2: # no-op update
Siddharth Agarwal
merge: exit early during a no-op update (BC)...
r19929 # call the hooks and exit early
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.hook(b'preupdate', throw=True, parent1=xp2, parent2=b'')
repo.hook(b'update', parent1=xp2, parent2=b'', error=0)
Gregory Szorc
merge: return an attrs class from update() and applyupdates()...
r37125 return updateresult(0, 0, 0, 0)
Siddharth Agarwal
merge: exit early during a no-op update (BC)...
r19929
Augie Fackler
formatting: blacken the codebase...
r43346 if updatecheck == UPDATECHECK_LINEAR and pas not in (
[p1],
[p2],
): # nonlinear
Pierre-Yves David
update: allow dirty update to foreground (successors)...
r18985 dirty = wc.dirty(missing=True)
Martin von Zweigbergk
merge: remove unused handling of default destination in merge.update()...
r30902 if dirty:
Pierre-Yves David
update: allow dirty update to foreground (successors)...
r18985 # Branching is a bit strange to ensure we do the minimal
obsutil: move 'foreground' to the new modules...
r33147 # amount of call to obsutil.foreground.
foreground = obsutil.foreground(repo, [p1.node()])
Pierre-Yves David
update: allow dirty update to foreground (successors)...
r18985 # note: the <node> variable contains a random identifier
if repo[node].node() in foreground:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # allow updating to successors
Martin von Zweigbergk
merge: remove unused handling of default destination in merge.update()...
r30902 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b"uncommitted changes")
hint = _(b"commit or update --clean to discard changes")
Martin von Zweigbergk
destutil: remove duplicate check and leave it to merge.update()...
r30961 raise error.UpdateAbort(msg, hint=hint)
Pierre-Yves David
update: allow dirty update to foreground (successors)...
r18985 else:
# Allow jumping branches if clean and specific rev given
Martin von Zweigbergk
update: localize logic around which ancestor to use...
r30901 pass
if overwrite:
pas = [wc]
elif not branchmerge:
pas = [p1]
Matt Mackall
Merge: move most tests to the beginning
r2814
Matt Mackall
merge: mark ancient debugging option
r25843 # deprecated config: merge.followcopies
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 followcopies = repo.ui.configbool(b'merge', b'followcopies')
Mads Kiilerich
merge: move ancestor selection tweaking from manifestmerge to update function...
r21080 if overwrite:
Gábor Stefanik
update: enable copy tracing for backwards and non-linear updates...
r30200 followcopies = False
elif not pas[0]:
followcopies = False
if not branchmerge and not wc.dirty(missing=True):
followcopies = False
Mads Kiilerich
merge: move ancestor selection tweaking from manifestmerge to update function...
r21080
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 ### calculate phase
Martin von Zweigbergk
merge: make calculateupdates() return file->action dict...
r23641 actionbyfile, diverge, renamedelete = calculateupdates(
Augie Fackler
formatting: blacken the codebase...
r43346 repo,
wc,
p2,
pas,
branchmerge,
force,
mergeancestor,
followcopies,
matcher=matcher,
mergeforce=mergeforce,
)
Siddharth Agarwal
merge: don't try to merge subrepos twice (issue4988)...
r27951
Augie Fackler
merge: replace magic strings with NAMED_CONSTANTS (API)...
r43240 if updatecheck == UPDATECHECK_NO_CONFLICT:
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, (m, args, msg) in pycompat.iteritems(actionbyfile):
Augie Fackler
formatting: blacken the codebase...
r43346 if m not in (
ACTION_GET,
ACTION_KEEP,
ACTION_EXEC,
ACTION_REMOVE,
ACTION_PATH_CONFLICT_RESOLVE,
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b"conflicting changes")
hint = _(b"commit or update --clean to discard changes")
Martin von Zweigbergk
update: allow setting default update check to "noconflict"...
r31168 raise error.Abort(msg, hint=hint)
Siddharth Agarwal
merge: don't try to merge subrepos twice (issue4988)...
r27951 # Prompt and create actions. Most of this is in the resolve phase
# already, but we can't handle .hgsubstate in filemerge or
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 # subrepoutil.submerge yet so we have to keep prompting for it.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'.hgsubstate' in actionbyfile:
f = b'.hgsubstate'
Siddharth Agarwal
merge: don't try to merge subrepos twice (issue4988)...
r27951 m, args, msg = actionbyfile[f]
Simon Farnsworth
merge: use labels in prompts to the user...
r29774 prompts = filemerge.partextras(labels)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prompts[b'f'] = f
Gregory Szorc
merge: use constants for actions...
r37130 if m == ACTION_CHANGED_DELETED:
Siddharth Agarwal
merge: don't try to merge subrepos twice (issue4988)...
r27951 if repo.ui.promptchoice(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"local%(l)s changed %(f)s which other%(o)s deleted\n"
b"use (c)hanged version or (d)elete?"
b"$$ &Changed $$ &Delete"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% prompts,
0,
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actionbyfile[f] = (ACTION_REMOVE, None, b'prompt delete')
Siddharth Agarwal
merge: don't try to merge subrepos twice (issue4988)...
r27951 elif f in p1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actionbyfile[f] = (
ACTION_ADD_MODIFIED,
None,
b'prompt keep',
)
Siddharth Agarwal
merge: don't try to merge subrepos twice (issue4988)...
r27951 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 actionbyfile[f] = (ACTION_ADD, None, b'prompt keep')
Gregory Szorc
merge: use constants for actions...
r37130 elif m == ACTION_DELETED_CHANGED:
Siddharth Agarwal
merge: don't try to merge subrepos twice (issue4988)...
r27951 f1, f2, fa, move, anc = args
flags = p2[f2].flags()
Augie Fackler
formatting: blacken the codebase...
r43346 if (
repo.ui.promptchoice(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"other%(o)s changed %(f)s which local%(l)s deleted\n"
b"use (c)hanged version or leave (d)eleted?"
b"$$ &Changed $$ &Deleted"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% prompts,
0,
)
== 0
):
actionbyfile[f] = (
ACTION_GET,
(flags, False),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'prompt recreating',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Siddharth Agarwal
merge: don't try to merge subrepos twice (issue4988)...
r27951 else:
del actionbyfile[f]
Martin von Zweigbergk
merge: make calculateupdates() return file->action dict...
r23641 # Convert to dictionary-of-lists format
Martin von Zweigbergk
merge: extract helper for creating empty "actions" dict...
r41068 actions = emptyactions()
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, (m, args, msg) in pycompat.iteritems(actionbyfile):
Martin von Zweigbergk
merge: make calculateupdates() return file->action dict...
r23641 if m not in actions:
actions[m] = []
actions[m].append((f, args, msg))
Matt Mackall
Move merge code to its own module...
r2775
Martin von Zweigbergk
util: rename checkcase() to fscasesensitive() (API)...
r29889 if not util.fscasesensitive(repo.path):
Martin von Zweigbergk
merge: perform case-collision checking on final set of actions...
r23544 # check collision between files only in p2 for clean update
Augie Fackler
formatting: blacken the codebase...
r43346 if not branchmerge and (
force or not wc.dirty(missing=True, branch=False)
):
Martin von Zweigbergk
merge: perform case-collision checking on final set of actions...
r23544 _checkcollision(repo, p2.manifest(), None)
else:
_checkcollision(repo, wc.manifest(), actions)
Martin von Zweigbergk
merge: move dr/rd warning messages out of applyupdates()...
r23525 # divergent renames
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, fl in sorted(pycompat.iteritems(diverge)):
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"note: possible conflict - %s was renamed "
b"multiple times to:\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% f
)
Martin von Zweigbergk
copies: print list of divergent renames in sorted order...
r42279 for nf in sorted(fl):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(b" %s\n" % nf)
Martin von Zweigbergk
merge: move dr/rd warning messages out of applyupdates()...
r23525
# rename and delete
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, fl in sorted(pycompat.iteritems(renamedelete)):
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"note: possible conflict - %s was deleted "
b"and renamed to:\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% f
)
Martin von Zweigbergk
copies: print list of divergent renames in sorted order...
r42279 for nf in sorted(fl):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(b" %s\n" % nf)
Martin von Zweigbergk
merge: move dr/rd warning messages out of applyupdates()...
r23525
Martin von Zweigbergk
merge: move messages about possible conflicts a litte earlier...
r26957 ### apply phase
Augie Fackler
formatting: blacken the codebase...
r43346 if not branchmerge: # just jump to the new rev
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, b''
Martin von Zweigbergk
merge: move definition of `partial` closer to where it's used...
r44625 # If we're doing a partial update, we need to skip updating
Martin von Zweigbergk
merge: avoid a negation in the definition of updatedirstate...
r44626 # the dirstate.
always = matcher is None or matcher.always()
Martin von Zweigbergk
merge: introduce a revert_to() for that use-case...
r44744 updatedirstate = updatedirstate and always and not wc.isinmemory()
Martin von Zweigbergk
merge: define updatedirstate a little earlier and reuse it...
r44612 if updatedirstate:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.hook(b'preupdate', throw=True, parent1=xp1, parent2=xp2)
Martin von Zweigbergk
merge: move messages about possible conflicts a litte earlier...
r26957 # note that we're in the middle of an update
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.vfs.write(b'updatestate', p2.hex())
Martin von Zweigbergk
merge: move messages about possible conflicts a litte earlier...
r26957
Gregory Szorc
fsmonitor: warn when fsmonitor could be used...
r34886 # Advertise fsmonitor when its presence could be useful.
#
# We only advertise when performing an update from an empty working
# directory. This typically only occurs during initial clone.
#
# We give users a mechanism to disable the warning in case it is
# annoying.
#
# We only allow on Linux and MacOS because that's where fsmonitor is
# considered stable.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fsmonitorwarning = repo.ui.configbool(b'fsmonitor', b'warn_when_unused')
Augie Fackler
formatting: blacken the codebase...
r43346 fsmonitorthreshold = repo.ui.configint(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor', b'warn_update_file_count'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
fsmonitor: warn when fsmonitor could be used...
r34886 try:
Yuya Nishihara
merge: cut import cycle at merge -> extensions...
r36027 # avoid cycle: extensions -> cmdutil -> merge
from . import extensions
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extensions.find(b'fsmonitor')
fsmonitorenabled = repo.ui.config(b'fsmonitor', b'mode') != b'off'
Gregory Szorc
fsmonitor: warn when fsmonitor could be used...
r34886 # We intentionally don't look at whether fsmonitor has disabled
# itself because a) fsmonitor may have already printed a warning
# b) we only care about the config state here.
except KeyError:
fsmonitorenabled = False
Augie Fackler
formatting: blacken the codebase...
r43346 if (
fsmonitorwarning
and not fsmonitorenabled
and p1.node() == nullid
and len(actions[ACTION_GET]) >= fsmonitorthreshold
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 and pycompat.sysplatform.startswith((b'linux', b'darwin'))
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Gregory Szorc
fsmonitor: warn when fsmonitor could be used...
r34886 repo.ui.warn(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'(warning: large working directory being used without '
b'fsmonitor enabled; enable fsmonitor to improve performance; '
b'see "hg help -e fsmonitor")\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Gregory Szorc
fsmonitor: warn when fsmonitor could be used...
r34886
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 wantfiledata = updatedirstate and not branchmerge
Augie Fackler
formatting: blacken the codebase...
r43346 stats, getfiledata = applyupdates(
repo, actions, wc, p2, overwrite, wantfiledata, labels=labels
)
Martin von Zweigbergk
merge: move messages about possible conflicts a litte earlier...
r26957
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 if updatedirstate:
Augie Fackler
merge: migrate to context manager for changing dirstate parents
r32351 with repo.dirstate.parentchange():
repo.setparents(fp1, fp2)
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 recordupdates(repo, actions, branchmerge, getfiledata)
Augie Fackler
merge: migrate to context manager for changing dirstate parents
r32351 # update completed, clear state
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 util.unlink(repo.vfs.join(b'updatestate'))
Matt Mackall
update: add tracking of interrupted updates (issue3113)...
r19482
Augie Fackler
merge: migrate to context manager for changing dirstate parents
r32351 if not branchmerge:
repo.dirstate.setbranch(p2.branch())
Sune Foldager
run commit and update hooks after command completion (issue1827)...
r10492
Gregory Szorc
sparse: move pruning of temporary includes into core...
r33321 # If we're updating to a location, clean up any stale temporary includes
# (ex: this happens during hg rebase --abort).
if not branchmerge:
sparse.prunetemporaryincludes(repo)
Martin von Zweigbergk
merge: don't call update hook when using in-memory context...
r44611 if updatedirstate:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.hook(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'update', parent1=xp1, parent2=xp2, error=stats.unresolvedcount
Augie Fackler
formatting: blacken the codebase...
r43346 )
Sune Foldager
run commit and update hooks after command completion (issue1827)...
r10492 return stats
Matt Mackall
merge: add merge.graft helper...
r22902
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
merge: introduce a merge() for that use-case...
r44883 def merge(ctx, labels=None, force=False, wc=None):
"""Merge another topological branch into the working copy.
force = whether the merge was run with 'merge --force' (deprecated)
"""
return update(
ctx.repo(),
ctx.rev(),
labels=labels,
branchmerge=True,
force=force,
mergeforce=force,
wc=wc,
)
Martin von Zweigbergk
merge: introduce a clean_update() for that use-case...
r44743 def clean_update(ctx, wc=None):
"""Do a clean update to the given commit.
This involves updating to the commit and discarding any changes in the
working copy.
"""
return update(ctx.repo(), ctx.rev(), branchmerge=False, force=True, wc=wc)
Martin von Zweigbergk
merge: introduce a revert_to() for that use-case...
r44744 def revert_to(ctx, matcher=None, wc=None):
"""Revert the working copy to the given commit.
The working copy will keep its current parent(s) but its content will
be the same as in the given commit.
"""
return update(
ctx.repo(),
ctx.rev(),
branchmerge=False,
force=True,
updatedirstate=False,
matcher=matcher,
wc=wc,
)
Augie Fackler
formatting: blacken the codebase...
r43346 def graft(
Martin von Zweigbergk
graft: let caller pass in overlayworkingctx to merge.graft()...
r44692 repo,
ctx,
Martin von Zweigbergk
graft: default `base` argument to common case of `ctx.p1()`...
r44693 base=None,
Martin von Zweigbergk
graft: let caller pass in overlayworkingctx to merge.graft()...
r44692 labels=None,
keepparent=False,
keepconflictparent=False,
wctx=None,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Matt Mackall
merge: add merge.graft helper...
r22902 """Do a graft-like merge.
This is a merge where the merge ancestor is chosen such that one
or more changesets are grafted onto the current changeset. In
addition to the merge, this fixes up the dirstate to include only
Andrew Halberstadt
merge.graft: add option to keep second parent...
r27267 a single parent (if keepparent is False) and tries to duplicate any
renames/copies appropriately.
Matt Mackall
merge: add merge.graft helper...
r22902
ctx - changeset to rebase
Martin von Zweigbergk
graft: default `base` argument to common case of `ctx.p1()`...
r44693 base - merge base, or ctx.p1() if not specified
Matt Mackall
merge: add merge.graft helper...
r22902 labels - merge labels eg ['local', 'graft']
Andrew Halberstadt
merge.graft: add option to keep second parent...
r27267 keepparent - keep second parent if any
av6
merge: correct argument name in docstring...
r42604 keepconflictparent - if unresolved, keep parent used for the merge
Matt Mackall
merge: add merge.graft helper...
r22902
"""
Durham Goode
graft: allow creating sibling grafts...
r24643 # If we're grafting a descendant onto an ancestor, be sure to pass
# mergeancestor=True to update. This does two things: 1) allows the merge if
# the destination is the same as the parent of the ctx (so we can use graft
# to copy commits), and 2) informs update that the incoming changes are
# newer than the destination so it doesn't prompt about "remote changed foo
# which local deleted".
Valentin Gatien-Baron
graft: always allow hg graft --base . (issue6248)...
r44867 # We also pass mergeancestor=True when base is the same revision as p1. 2)
# doesn't matter as there can't possibly be conflicts, but 1) is necessary.
Martin von Zweigbergk
graft: let caller pass in overlayworkingctx to merge.graft()...
r44692 wctx = wctx or repo[None]
Martin von Zweigbergk
graft: extract repo[None] to a variable...
r44548 pctx = wctx.p1()
Martin von Zweigbergk
graft: default `base` argument to common case of `ctx.p1()`...
r44693 base = base or ctx.p1()
Valentin Gatien-Baron
graft: always allow hg graft --base . (issue6248)...
r44867 mergeancestor = (
repo.changelog.isancestor(pctx.node(), ctx.node())
or pctx.rev() == base.rev()
)
Matt Mackall
merge: add merge.graft helper...
r22902
Augie Fackler
formatting: blacken the codebase...
r43346 stats = update(
repo,
ctx.node(),
True,
True,
Martin von Zweigbergk
graft: rename `pctx` argument to `base` since that's what it is...
r44235 base.node(),
Augie Fackler
formatting: blacken the codebase...
r43346 mergeancestor=mergeancestor,
labels=labels,
Martin von Zweigbergk
graft: let caller pass in overlayworkingctx to merge.graft()...
r44692 wc=wctx,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Boris Feld
merge: add a 'keepconflictparent' argument to graft...
r38513
if keepconflictparent and stats.unresolvedcount:
pother = ctx.node()
else:
pother = nullid
parents = ctx.parents()
Martin von Zweigbergk
graft: rename `pctx` argument to `base` since that's what it is...
r44235 if keepparent and len(parents) == 2 and base in parents:
parents.remove(base)
Boris Feld
merge: add a 'keepconflictparent' argument to graft...
r38513 pother = parents[0].node()
Martin von Zweigbergk
graft: never set both parents equal in the dirstate (issue6098)...
r44237 # Never set both parents equal to each other
if pother == pctx.node():
pother = nullid
Andrew Halberstadt
merge.graft: add option to keep second parent...
r27267
Martin von Zweigbergk
graft: let caller pass in overlayworkingctx to merge.graft()...
r44692 if wctx.isinmemory():
wctx.setparents(pctx.node(), pother)
Augie Fackler
merge: migrate to context manager for changing dirstate parents
r32351 # fix up dirstate for copies and renames
Martin von Zweigbergk
graftcopies: remove `skip` and `repo` arguments...
r44551 copies.graftcopies(wctx, ctx, base)
Martin von Zweigbergk
graft: let caller pass in overlayworkingctx to merge.graft()...
r44692 else:
with repo.dirstate.parentchange():
repo.setparents(pctx.node(), pother)
repo.dirstate.write(repo.currenttransaction())
# fix up dirstate for copies and renames
copies.graftcopies(wctx, ctx, base)
Matt Mackall
merge: add merge.graft helper...
r22902 return stats
Gregory Szorc
merge: move purge logic from extension...
r39499
Augie Fackler
formatting: blacken the codebase...
r43346
def purge(
repo,
matcher,
Valentin Gatien-Baron
purge: add -i flag to delete ignored files instead of untracked files...
r44771 unknown=True,
Augie Fackler
formatting: blacken the codebase...
r43346 ignored=False,
removeemptydirs=True,
removefiles=True,
abortonerror=False,
noop=False,
):
Gregory Szorc
merge: move purge logic from extension...
r39499 """Purge the working directory of untracked files.
``matcher`` is a matcher configured to scan the working directory -
potentially a subset.
Valentin Gatien-Baron
purge: add -i flag to delete ignored files instead of untracked files...
r44771 ``unknown`` controls whether unknown files should be purged.
``ignored`` controls whether ignored files should be purged.
Gregory Szorc
merge: move purge logic from extension...
r39499
``removeemptydirs`` controls whether empty directories should be removed.
``removefiles`` controls whether files are removed.
``abortonerror`` causes an exception to be raised if an error occurs
deleting a file or directory.
``noop`` controls whether to actually remove files. If not defined, actions
will be taken.
Returns an iterable of relative paths in the working directory that were
or would be removed.
"""
def remove(removefn, path):
try:
Gregory Szorc
merge: use vfs methods for I/O...
r39500 removefn(path)
Gregory Szorc
merge: move purge logic from extension...
r39499 except OSError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 m = _(b'%s cannot be removed') % path
Gregory Szorc
merge: move purge logic from extension...
r39499 if abortonerror:
raise error.Abort(m)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(_(b'warning: %s\n') % m)
Gregory Szorc
merge: move purge logic from extension...
r39499
# There's no API to copy a matcher. So mutate the passed matcher and
# restore it when we're done.
oldtraversedir = matcher.traversedir
res = []
try:
if removeemptydirs:
directories = []
Martin von Zweigbergk
dirstate: include explicit matches in match.traversedir calls...
r44112 matcher.traversedir = directories.append
Gregory Szorc
merge: move purge logic from extension...
r39499
Valentin Gatien-Baron
purge: add -i flag to delete ignored files instead of untracked files...
r44771 status = repo.status(match=matcher, ignored=ignored, unknown=unknown)
Gregory Szorc
merge: move purge logic from extension...
r39499
if removefiles:
for f in sorted(status.unknown + status.ignored):
if not noop:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b'removing file %s\n') % f)
Gregory Szorc
merge: use vfs methods for I/O...
r39500 remove(repo.wvfs.unlink, f)
Gregory Szorc
merge: move purge logic from extension...
r39499 res.append(f)
if removeemptydirs:
for f in sorted(directories, reverse=True):
Gregory Szorc
merge: use vfs methods for I/O...
r39500 if matcher(f) and not repo.wvfs.listdir(f):
Gregory Szorc
merge: move purge logic from extension...
r39499 if not noop:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b'removing directory %s\n') % f)
Gregory Szorc
merge: use vfs methods for I/O...
r39500 remove(repo.wvfs.rmdir, f)
Gregory Szorc
merge: move purge logic from extension...
r39499 res.append(f)
return res
finally:
matcher.traversedir = oldtraversedir