mercurial/merge.py
changeset 45366 e5b4061f32be
parent 45365 4c6004afd836
child 45367 3c783ff08d40
equal deleted inserted replaced
45365:4c6004afd836 45366:e5b4061f32be
   149                 abortconflicts.update(conflicts)
   149                 abortconflicts.update(conflicts)
   150             elif config == b'warn':
   150             elif config == b'warn':
   151                 warnconflicts.update(conflicts)
   151                 warnconflicts.update(conflicts)
   152 
   152 
   153         checkunknowndirs = _unknowndirschecker()
   153         checkunknowndirs = _unknowndirschecker()
   154         for f, args, msg in mresult.getactions(
   154         for f in mresult.files(
   155             [
   155             (
   156                 mergestatemod.ACTION_CREATED,
   156                 mergestatemod.ACTION_CREATED,
   157                 mergestatemod.ACTION_DELETED_CHANGED,
   157                 mergestatemod.ACTION_DELETED_CHANGED,
   158             ]
   158             )
   159         ):
   159         ):
   160             if _checkunknownfile(repo, wctx, mctx, f):
   160             if _checkunknownfile(repo, wctx, mctx, f):
   161                 fileconflicts.add(f)
   161                 fileconflicts.add(f)
   162             elif pathconfig and f not in wctx:
   162             elif pathconfig and f not in wctx:
   163                 path = checkunknowndirs(repo, wctx, f)
   163                 path = checkunknowndirs(repo, wctx, f)
   297     # If the repo is narrowed, filter out files outside the narrowspec.
   297     # If the repo is narrowed, filter out files outside the narrowspec.
   298     narrowmatch = repo.narrowmatch()
   298     narrowmatch = repo.narrowmatch()
   299     if not narrowmatch.always():
   299     if not narrowmatch.always():
   300         pmmf = set(wmf.walk(narrowmatch))
   300         pmmf = set(wmf.walk(narrowmatch))
   301         if mresult:
   301         if mresult:
   302             for f, actionsfortype in pycompat.iteritems(mresult.actions):
   302             for f in list(mresult.files()):
   303                 if not narrowmatch(f):
   303                 if not narrowmatch(f):
   304                     mresult.removefile(f)
   304                     mresult.removefile(f)
   305     else:
   305     else:
   306         # build provisional merged manifest up
   306         # build provisional merged manifest up
   307         pmmf = set(wmf)
   307         pmmf = set(wmf)
   308 
   308 
   309     if mresult:
   309     if mresult:
   310         # KEEP and EXEC are no-op
   310         # KEEP and EXEC are no-op
   311         for f, args, msg in mresult.getactions(
   311         for f in mresult.files(
   312             (
   312             (
   313                 mergestatemod.ACTION_ADD,
   313                 mergestatemod.ACTION_ADD,
   314                 mergestatemod.ACTION_ADD_MODIFIED,
   314                 mergestatemod.ACTION_ADD_MODIFIED,
   315                 mergestatemod.ACTION_FORGET,
   315                 mergestatemod.ACTION_FORGET,
   316                 mergestatemod.ACTION_GET,
   316                 mergestatemod.ACTION_GET,
   317                 mergestatemod.ACTION_CHANGED_DELETED,
   317                 mergestatemod.ACTION_CHANGED_DELETED,
   318                 mergestatemod.ACTION_DELETED_CHANGED,
   318                 mergestatemod.ACTION_DELETED_CHANGED,
   319             )
   319             )
   320         ):
   320         ):
   321             pmmf.add(f)
   321             pmmf.add(f)
   322         for f, args, msg in mresult.getactions([mergestatemod.ACTION_REMOVE]):
   322         for f in mresult.files((mergestatemod.ACTION_REMOVE,)):
   323             pmmf.discard(f)
   323             pmmf.discard(f)
   324         for f, args, msg in mresult.getactions(
   324         for f, args, msg in mresult.getactions(
   325             [mergestatemod.ACTION_DIR_RENAME_MOVE_LOCAL]
   325             [mergestatemod.ACTION_DIR_RENAME_MOVE_LOCAL]
   326         ):
   326         ):
   327             f2, flags = args
   327             f2, flags = args
   328             pmmf.discard(f2)
   328             pmmf.discard(f2)
   329             pmmf.add(f)
   329             pmmf.add(f)
   330         for f, args, msg in mresult.getactions(
   330         for f in mresult.files((mergestatemod.ACTION_LOCAL_DIR_RENAME_GET,)):
   331             [mergestatemod.ACTION_LOCAL_DIR_RENAME_GET]
       
   332         ):
       
   333             pmmf.add(f)
   331             pmmf.add(f)
   334         for f, args, msg in mresult.getactions([mergestatemod.ACTION_MERGE]):
   332         for f, args, msg in mresult.getactions([mergestatemod.ACTION_MERGE]):
   335             f1, f2, fa, move, anc = args
   333             f1, f2, fa, move, anc = args
   336             if move:
   334             if move:
   337                 pmmf.discard(f1)
   335                 pmmf.discard(f1)
   412     createdfiledirs = set()
   410     createdfiledirs = set()
   413 
   411 
   414     # The set of files deleted by all the actions.
   412     # The set of files deleted by all the actions.
   415     deletedfiles = set()
   413     deletedfiles = set()
   416 
   414 
   417     for (f, args, msg) in mresult.getactions(
   415     for f in mresult.files(
   418         (
   416         (
   419             mergestatemod.ACTION_CREATED,
   417             mergestatemod.ACTION_CREATED,
   420             mergestatemod.ACTION_DELETED_CHANGED,
   418             mergestatemod.ACTION_DELETED_CHANGED,
   421             mergestatemod.ACTION_MERGE,
   419             mergestatemod.ACTION_MERGE,
   422             mergestatemod.ACTION_CREATED_MERGE,
   420             mergestatemod.ACTION_CREATED_MERGE,
   428             # The file aliases a local directory.  This might be ok if all
   426             # The file aliases a local directory.  This might be ok if all
   429             # the files in the local directory are being deleted.  This
   427             # the files in the local directory are being deleted.  This
   430             # will be checked once we know what all the deleted files are.
   428             # will be checked once we know what all the deleted files are.
   431             remoteconflicts.add(f)
   429             remoteconflicts.add(f)
   432     # Track the names of all deleted files.
   430     # Track the names of all deleted files.
   433     for (f, args, msg) in mresult.getactions((mergestatemod.ACTION_REMOVE,)):
   431     for f in mresult.files((mergestatemod.ACTION_REMOVE,)):
   434         deletedfiles.add(f)
   432         deletedfiles.add(f)
   435     for (f, args, msg) in mresult.getactions((mergestatemod.ACTION_MERGE,)):
   433     for (f, args, msg) in mresult.getactions((mergestatemod.ACTION_MERGE,)):
   436         f1, f2, fa, move, anc = args
   434         f1, f2, fa, move, anc = args
   437         if move:
   435         if move:
   438             deletedfiles.add(f1)
   436             deletedfiles.add(f1)
   468 
   466 
   469     # Rename all local conflicting files that have not been deleted.
   467     # Rename all local conflicting files that have not been deleted.
   470     for p in localconflicts:
   468     for p in localconflicts:
   471         if p not in deletedfiles:
   469         if p not in deletedfiles:
   472             ctxname = bytes(wctx).rstrip(b'+')
   470             ctxname = bytes(wctx).rstrip(b'+')
   473             pnew = util.safename(p, ctxname, wctx, set(mresult.actions.keys()))
   471             pnew = util.safename(p, ctxname, wctx, set(mresult.files()))
   474             porig = wctx[p].copysource() or p
   472             porig = wctx[p].copysource() or p
   475             mresult.addfile(
   473             mresult.addfile(
   476                 pnew,
   474                 pnew,
   477                 mergestatemod.ACTION_PATH_CONFLICT_RESOLVE,
   475                 mergestatemod.ACTION_PATH_CONFLICT_RESOLVE,
   478                 (p, porig),
   476                 (p, porig),
   489         # Check if all files in the conflicting directories have been removed.
   487         # Check if all files in the conflicting directories have been removed.
   490         ctxname = bytes(mctx).rstrip(b'+')
   488         ctxname = bytes(mctx).rstrip(b'+')
   491         for f, p in _filesindirs(repo, mf, remoteconflicts):
   489         for f, p in _filesindirs(repo, mf, remoteconflicts):
   492             if f not in deletedfiles:
   490             if f not in deletedfiles:
   493                 m, args, msg = mresult.getfile(p)
   491                 m, args, msg = mresult.getfile(p)
   494                 pnew = util.safename(
   492                 pnew = util.safename(p, ctxname, wctx, set(mresult.files()))
   495                     p, ctxname, wctx, set(mresult.actions.keys())
       
   496                 )
       
   497                 if m in (
   493                 if m in (
   498                     mergestatemod.ACTION_DELETED_CHANGED,
   494                     mergestatemod.ACTION_DELETED_CHANGED,
   499                     mergestatemod.ACTION_MERGE,
   495                     mergestatemod.ACTION_MERGE,
   500                 ):
   496                 ):
   501                     # Action was merge, just update target.
   497                     # Action was merge, just update target.
   619         returns default_return if the file is not present """
   615         returns default_return if the file is not present """
   620         if filename in self._filemapping:
   616         if filename in self._filemapping:
   621             return self._filemapping[filename]
   617             return self._filemapping[filename]
   622         return default_return
   618         return default_return
   623 
   619 
       
   620     def files(self, actions=None):
       
   621         """ returns files on which provided action needs to perfromed
       
   622 
       
   623         If actions is None, all files are returned
       
   624         """
       
   625         # TODO: think whether we should return renamedelete and
       
   626         # diverge filenames also
       
   627         if actions is None:
       
   628             for f in self._filemapping:
       
   629                 yield f
       
   630 
       
   631         else:
       
   632             for a in actions:
       
   633                 for f in self._actionmapping[a]:
       
   634                     yield f
       
   635 
   624     def removefile(self, filename):
   636     def removefile(self, filename):
   625         """ removes a file from the mergeresult object as the file might
   637         """ removes a file from the mergeresult object as the file might
   626         not merging anymore """
   638         not merging anymore """
   627         action, data, message = self._filemapping[filename]
   639         action, data, message = self._filemapping[filename]
   628         del self._filemapping[filename]
   640         del self._filemapping[filename]
  1027 def _resolvetrivial(repo, wctx, mctx, ancestor, mresult):
  1039 def _resolvetrivial(repo, wctx, mctx, ancestor, mresult):
  1028     """Resolves false conflicts where the nodeid changed but the content
  1040     """Resolves false conflicts where the nodeid changed but the content
  1029        remained the same."""
  1041        remained the same."""
  1030     # We force a copy of actions.items() because we're going to mutate
  1042     # We force a copy of actions.items() because we're going to mutate
  1031     # actions as we resolve trivial conflicts.
  1043     # actions as we resolve trivial conflicts.
  1032     for f, args, msg in list(
  1044     for f in list(mresult.files((mergestatemod.ACTION_CHANGED_DELETED,))):
  1033         mresult.getactions([mergestatemod.ACTION_CHANGED_DELETED])
       
  1034     ):
       
  1035         if f in ancestor and not wctx[f].cmp(ancestor[f]):
  1045         if f in ancestor and not wctx[f].cmp(ancestor[f]):
  1036             # local did change but ended up with same content
  1046             # local did change but ended up with same content
  1037             mresult.addfile(
  1047             mresult.addfile(
  1038                 f, mergestatemod.ACTION_REMOVE, None, b'prompt same'
  1048                 f, mergestatemod.ACTION_REMOVE, None, b'prompt same'
  1039             )
  1049             )
  1040 
  1050 
  1041     for f, args, msg in list(
  1051     for f in list(mresult.files((mergestatemod.ACTION_DELETED_CHANGED,))):
  1042         mresult.getactions([mergestatemod.ACTION_DELETED_CHANGED])
       
  1043     ):
       
  1044         if f in ancestor and not mctx[f].cmp(ancestor[f]):
  1052         if f in ancestor and not mctx[f].cmp(ancestor[f]):
  1045             # remote did change but ended up with same content
  1053             # remote did change but ended up with same content
  1046             mresult.removefile(f)  # don't get = keep local deleted
  1054             mresult.removefile(f)  # don't get = keep local deleted
  1047 
  1055 
  1048 
  1056 
  1302     of merge actions.  ``ctx`` is the context being merged in."""
  1310     of merge actions.  ``ctx`` is the context being merged in."""
  1303 
  1311 
  1304     # Skipping 'a', 'am', 'f', 'r', 'dm', 'e', 'k', 'p' and 'pr', because they
  1312     # Skipping 'a', 'am', 'f', 'r', 'dm', 'e', 'k', 'p' and 'pr', because they
  1305     # don't touch the context to be merged in.  'cd' is skipped, because
  1313     # don't touch the context to be merged in.  'cd' is skipped, because
  1306     # changed/deleted never resolves to something from the remote side.
  1314     # changed/deleted never resolves to something from the remote side.
  1307     files = []
  1315     files = mresult.files(
  1308     for f, args, msg in mresult.getactions(
       
  1309         [
  1316         [
  1310             mergestatemod.ACTION_GET,
  1317             mergestatemod.ACTION_GET,
  1311             mergestatemod.ACTION_DELETED_CHANGED,
  1318             mergestatemod.ACTION_DELETED_CHANGED,
  1312             mergestatemod.ACTION_LOCAL_DIR_RENAME_GET,
  1319             mergestatemod.ACTION_LOCAL_DIR_RENAME_GET,
  1313             mergestatemod.ACTION_MERGE,
  1320             mergestatemod.ACTION_MERGE,
  1314         ]
  1321         ]
  1315     ):
  1322     )
  1316         files.append(f)
       
  1317 
  1323 
  1318     prefetch = scmutil.prefetchfiles
  1324     prefetch = scmutil.prefetchfiles
  1319     matchfiles = scmutil.matchfiles
  1325     matchfiles = scmutil.matchfiles
  1320     prefetch(
  1326     prefetch(
  1321         repo, [(ctx.rev(), matchfiles(repo, files),)],
  1327         repo, [(ctx.rev(), matchfiles(repo, files),)],