mercurial/merge.py
changeset 3106 7c7469d41ade
parent 3105 ef4e5d05bac4
child 3107 4ec28446fca8
equal deleted inserted replaced
3105:ef4e5d05bac4 3106:7c7469d41ade
    50 
    50 
    51     os.unlink(b)
    51     os.unlink(b)
    52     os.unlink(c)
    52     os.unlink(c)
    53     return r
    53     return r
    54 
    54 
       
    55 def manifestmerge(ui, m1, m2, ma, overwrite, backwards):
       
    56     """
       
    57     Merge manifest m1 with m2 using ancestor ma and generate merge action list
       
    58     """
       
    59 
       
    60     action = []
       
    61 
       
    62     # Compare manifests
       
    63     for f, n in m1.iteritems():
       
    64         if f in m2:
       
    65             queued = 0
       
    66 
       
    67             # are files different?
       
    68             if n != m2[f]:
       
    69                 a = ma.get(f, nullid)
       
    70                 # are both different from the ancestor?
       
    71                 if not overwrite and n != a and m2[f] != a:
       
    72                     ui.debug(_(" %s versions differ, resolve\n") % f)
       
    73                     action.append((f, "m", fmerge(f, m1, m2, ma), n[:20], m2[f]))
       
    74                     queued = 1
       
    75                 # are we clobbering?
       
    76                 # is remote's version newer?
       
    77                 # or are we going back in time and clean?
       
    78                 elif overwrite or m2[f] != a or (backwards and not n[20:]):
       
    79                     ui.debug(_(" remote %s is newer, get\n") % f)
       
    80                     action.append((f, "g", m2.execf(f), m2[f]))
       
    81                     queued = 1
       
    82             elif n[20:] in ("u","a"):
       
    83                 # this unknown file is the same as the checkout
       
    84                 # we need to reset the dirstate if the file was added
       
    85                 action.append((f, "g", m2.execf(f), m2[f]))
       
    86 
       
    87             # do we still need to look at mode bits?
       
    88             if not queued and m1.execf(f) != m2.execf(f):
       
    89                 if overwrite:
       
    90                     ui.debug(_(" updating permissions for %s\n") % f)
       
    91                     action.append((f, "e", m2.execf(f)))
       
    92                 else:
       
    93                     mode = fmerge(f, m1, m2, ma)
       
    94                     if mode != m1.execf(f):
       
    95                         ui.debug(_(" updating permissions for %s\n")
       
    96                                       % f)
       
    97                         action.append((f, "e", m2.execf(f)))
       
    98             del m2[f]
       
    99         elif f in ma:
       
   100             if n != ma[f]:
       
   101                 r = _("d")
       
   102                 if not overwrite:
       
   103                     r = ui.prompt(
       
   104                         (_(" local changed %s which remote deleted\n") % f) +
       
   105                          _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
       
   106                 if r == _("d"):
       
   107                     action.append((f, "r"))
       
   108             else:
       
   109                 ui.debug(_("other deleted %s\n") % f)
       
   110                 action.append((f, "r"))
       
   111         else:
       
   112             # file is created on branch or in working directory
       
   113             if overwrite and n[20:] != "u":
       
   114                 ui.debug(_("remote deleted %s, clobbering\n") % f)
       
   115                 action.append((f, "r"))
       
   116             elif not n[20:]: # same as parent
       
   117                 if backwards:
       
   118                     ui.debug(_("remote deleted %s\n") % f)
       
   119                     action.append((f, "r"))
       
   120                 else:
       
   121                     ui.debug(_("local modified %s, keeping\n") % f)
       
   122             else:
       
   123                 ui.debug(_("working dir created %s, keeping\n") % f)
       
   124 
       
   125     for f, n in m2.iteritems():
       
   126         if f[0] == "/":
       
   127             continue
       
   128         if f in ma and n != ma[f]:
       
   129             r = _("k")
       
   130             if not overwrite:
       
   131                 r = ui.prompt(
       
   132                     (_("remote changed %s which local deleted\n") % f) +
       
   133                      _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
       
   134             if r == _("k"):
       
   135                 action.append((f, "g", m2.execf(f), n))
       
   136         elif f not in ma:
       
   137             ui.debug(_("remote created %s\n") % f)
       
   138             action.append((f, "g", m2.execf(f), n))
       
   139         else:
       
   140             if overwrite or backwards:
       
   141                 ui.debug(_("local deleted %s, recreating\n") % f)
       
   142                 action.append((f, "g", m2.execf(f), n))
       
   143             else:
       
   144                 ui.debug(_("local deleted %s\n") % f)
       
   145 
       
   146     return action
       
   147 
    55 def update(repo, node, branchmerge=False, force=False, partial=None,
   148 def update(repo, node, branchmerge=False, force=False, partial=None,
    56            wlock=None, show_stats=True, remind=True):
   149            wlock=None, show_stats=True, remind=True):
    57 
   150 
    58     overwrite = force and not branchmerge
   151     overwrite = force and not branchmerge
    59     forcemerge = force and branchmerge
   152     forcemerge = force and branchmerge
   132         for f in m1.keys():
   225         for f in m1.keys():
   133             if not partial(f): del m1[f]
   226             if not partial(f): del m1[f]
   134         for f in m2.keys():
   227         for f in m2.keys():
   135             if not partial(f): del m2[f]
   228             if not partial(f): del m2[f]
   136 
   229 
   137     # Compare manifests
   230     action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards)
   138     for f, n in m1.iteritems():
       
   139         if f in m2:
       
   140             queued = 0
       
   141 
       
   142             # are files different?
       
   143             if n != m2[f]:
       
   144                 a = ma.get(f, nullid)
       
   145                 # are both different from the ancestor?
       
   146                 if not overwrite and n != a and m2[f] != a:
       
   147                     repo.ui.debug(_(" %s versions differ, resolve\n") % f)
       
   148                     action.append((f, "m", fmerge(f, m1, m2, ma), n[:20], m2[f]))
       
   149                     queued = 1
       
   150                 # are we clobbering?
       
   151                 # is remote's version newer?
       
   152                 # or are we going back in time and clean?
       
   153                 elif overwrite or m2[f] != a or (backwards and not n[20:]):
       
   154                     repo.ui.debug(_(" remote %s is newer, get\n") % f)
       
   155                     action.append((f, "g", m2.execf(f), m2[f]))
       
   156                     queued = 1
       
   157             elif n[20:] in ("u","a"):
       
   158                 # this unknown file is the same as the checkout
       
   159                 # we need to reset the dirstate if the file was added
       
   160                 action.append((f, "g", m2.execf(f), m2[f]))
       
   161 
       
   162             # do we still need to look at mode bits?
       
   163             if not queued and m1.execf(f) != m2.execf(f):
       
   164                 if overwrite:
       
   165                     repo.ui.debug(_(" updating permissions for %s\n") % f)
       
   166                     action.append((f, "e", m2.execf(f)))
       
   167                 else:
       
   168                     mode = fmerge(f, m1, m2, ma)
       
   169                     if mode != m1.execf(f):
       
   170                         repo.ui.debug(_(" updating permissions for %s\n")
       
   171                                       % f)
       
   172                         action.append((f, "e", m2.execf(f)))
       
   173             del m2[f]
       
   174         elif f in ma:
       
   175             if n != ma[f]:
       
   176                 r = _("d")
       
   177                 if not overwrite:
       
   178                     r = repo.ui.prompt(
       
   179                         (_(" local changed %s which remote deleted\n") % f) +
       
   180                          _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
       
   181                 if r == _("d"):
       
   182                     action.append((f, "r"))
       
   183             else:
       
   184                 repo.ui.debug(_("other deleted %s\n") % f)
       
   185                 action.append((f, "r"))
       
   186         else:
       
   187             # file is created on branch or in working directory
       
   188             if overwrite and n[20:] != "u":
       
   189                 repo.ui.debug(_("remote deleted %s, clobbering\n") % f)
       
   190                 action.append((f, "r"))
       
   191             elif not n[20:]: # same as parent
       
   192                 if backwards:
       
   193                     repo.ui.debug(_("remote deleted %s\n") % f)
       
   194                     action.append((f, "r"))
       
   195                 else:
       
   196                     repo.ui.debug(_("local modified %s, keeping\n") % f)
       
   197             else:
       
   198                 repo.ui.debug(_("working dir created %s, keeping\n") % f)
       
   199 
       
   200     for f, n in m2.iteritems():
       
   201         if f[0] == "/":
       
   202             continue
       
   203         if f in ma and n != ma[f]:
       
   204             r = _("k")
       
   205             if not overwrite:
       
   206                 r = repo.ui.prompt(
       
   207                     (_("remote changed %s which local deleted\n") % f) +
       
   208                      _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
       
   209             if r == _("k"):
       
   210                 action.append((f, "g", m2.execf(f), n))
       
   211         elif f not in ma:
       
   212             repo.ui.debug(_("remote created %s\n") % f)
       
   213             action.append((f, "g", m2.execf(f), n))
       
   214         else:
       
   215             if overwrite or backwards:
       
   216                 repo.ui.debug(_("local deleted %s, recreating\n") % f)
       
   217                 action.append((f, "g", m2.execf(f), n))
       
   218             else:
       
   219                 repo.ui.debug(_("local deleted %s\n") % f)
       
   220 
       
   221     del m1, m2, ma
   231     del m1, m2, ma
   222 
   232 
   223     ### apply phase
   233     ### apply phase
   224 
   234 
   225     if linear_path or overwrite:
   235     if linear_path or overwrite: