mercurial/merge.py
changeset 2824 ca06d35af65e
parent 2803 987c31e2a08c
child 2825 1ea086bc2086
equal deleted inserted replaced
2823:1c6beafbae97 2824:ca06d35af65e
    45 
    45 
    46     os.unlink(b)
    46     os.unlink(b)
    47     os.unlink(c)
    47     os.unlink(c)
    48     return r
    48     return r
    49 
    49 
    50 def update(repo, node, allow=False, force=False, choose=None,
    50 def update(repo, node, branchmerge=False, force=False, choose=None,
    51            moddirstate=True, forcemerge=False, wlock=None, show_stats=True,
    51            moddirstate=True, forcemerge=False, wlock=None, show_stats=True,
    52            remind=True):
    52            remind=True):
    53     pl = repo.dirstate.parents()
    53     pl = repo.dirstate.parents()
    54     if not force and pl[1] != nullid:
    54     if not force and pl[1] != nullid:
    55         raise util.Abort(_("outstanding uncommitted merges"))
    55         raise util.Abort(_("outstanding uncommitted merges"))
    72 
    72 
    73     # is this a jump, or a merge?  i.e. is there a linear path
    73     # is this a jump, or a merge?  i.e. is there a linear path
    74     # from p1 to p2?
    74     # from p1 to p2?
    75     linear_path = (pa == p1 or pa == p2)
    75     linear_path = (pa == p1 or pa == p2)
    76 
    76 
    77     if allow and linear_path:
    77     if branchmerge and linear_path:
    78         raise util.Abort(_("there is nothing to merge, just use "
    78         raise util.Abort(_("there is nothing to merge, just use "
    79                            "'hg update' or look at 'hg heads'"))
    79                            "'hg update' or look at 'hg heads'"))
    80     if allow and not forcemerge:
    80     if branchmerge and not forcemerge:
    81         if modified or added or removed:
    81         if modified or added or removed:
    82             raise util.Abort(_("outstanding uncommitted changes"))
    82             raise util.Abort(_("outstanding uncommitted changes"))
    83 
    83 
    84     if not forcemerge and not force:
    84     if not forcemerge and not force:
    85         for f in unknown:
    85         for f in unknown:
    91                                        " dir and differs from remote") % f)
    91                                        " dir and differs from remote") % f)
    92 
    92 
    93     # resolve the manifest to determine which files
    93     # resolve the manifest to determine which files
    94     # we care about merging
    94     # we care about merging
    95     repo.ui.note(_("resolving manifests\n"))
    95     repo.ui.note(_("resolving manifests\n"))
    96     repo.ui.debug(_(" force %s allow %s moddirstate %s linear %s\n") %
    96     repo.ui.debug(_(" force %s branchmerge %s moddirstate %s linear %s\n") %
    97                   (force, allow, moddirstate, linear_path))
    97                   (force, branchmerge, moddirstate, linear_path))
    98     repo.ui.debug(_(" ancestor %s local %s remote %s\n") %
    98     repo.ui.debug(_(" ancestor %s local %s remote %s\n") %
    99                   (short(man), short(m1n), short(m2n)))
    99                   (short(man), short(m1n), short(m2n)))
   100 
   100 
   101     merge = {}
   101     merge = {}
   102     get = {}
   102     get = {}
   178                         util.set_exec(repo.wjoin(f), mode)
   178                         util.set_exec(repo.wjoin(f), mode)
   179             del m2[f]
   179             del m2[f]
   180         elif f in ma:
   180         elif f in ma:
   181             if n != ma[f]:
   181             if n != ma[f]:
   182                 r = _("d")
   182                 r = _("d")
   183                 if not force and (linear_path or allow):
   183                 if not force and (linear_path or branchmerge):
   184                     r = repo.ui.prompt(
   184                     r = repo.ui.prompt(
   185                         (_(" local changed %s which remote deleted\n") % f) +
   185                         (_(" local changed %s which remote deleted\n") % f) +
   186                          _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
   186                          _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
   187                 if r == _("d"):
   187                 if r == _("d"):
   188                     remove.append(f)
   188                     remove.append(f)
   208             continue
   208             continue
   209         if f[0] == "/":
   209         if f[0] == "/":
   210             continue
   210             continue
   211         if f in ma and n != ma[f]:
   211         if f in ma and n != ma[f]:
   212             r = _("k")
   212             r = _("k")
   213             if not force and (linear_path or allow):
   213             if not force and (linear_path or branchmerge):
   214                 r = repo.ui.prompt(
   214                 r = repo.ui.prompt(
   215                     (_("remote changed %s which local deleted\n") % f) +
   215                     (_("remote changed %s which local deleted\n") % f) +
   216                      _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
   216                      _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
   217             if r == _("k"):
   217             if r == _("k"):
   218                 get[f] = n
   218                 get[f] = n
   233             get[f] = merge[f][1]
   233             get[f] = merge[f][1]
   234         merge = {}
   234         merge = {}
   235 
   235 
   236     if linear_path or force:
   236     if linear_path or force:
   237         # we don't need to do any magic, just jump to the new rev
   237         # we don't need to do any magic, just jump to the new rev
   238         branch_merge = False
       
   239         p1, p2 = p2, nullid
   238         p1, p2 = p2, nullid
   240     else:
   239     else:
   241         if not allow:
   240         if not branchmerge:
   242             repo.ui.status(_("this update spans a branch"
   241             repo.ui.status(_("this update spans a branch"
   243                              " affecting the following files:\n"))
   242                              " affecting the following files:\n"))
   244             fl = merge.keys() + get.keys()
   243             fl = merge.keys() + get.keys()
   245             fl.sort()
   244             fl.sort()
   246             for f in fl:
   245             for f in fl:
   250                 repo.ui.status(" %s%s\n" % (f, cf))
   249                 repo.ui.status(" %s%s\n" % (f, cf))
   251             repo.ui.warn(_("aborting update spanning branches!\n"))
   250             repo.ui.warn(_("aborting update spanning branches!\n"))
   252             repo.ui.status(_("(use 'hg merge' to merge across branches"
   251             repo.ui.status(_("(use 'hg merge' to merge across branches"
   253                              " or 'hg update -C' to lose changes)\n"))
   252                              " or 'hg update -C' to lose changes)\n"))
   254             return 1
   253             return 1
   255         branch_merge = True
       
   256 
   254 
   257     xp1 = hex(p1)
   255     xp1 = hex(p1)
   258     xp2 = hex(p2)
   256     xp2 = hex(p2)
   259     if p2 == nullid: xxp2 = ''
   257     if p2 == nullid: xxp2 = ''
   260     else: xxp2 = xp2
   258     else: xxp2 = xp2
   270         repo.ui.note(_("getting %s\n") % f)
   268         repo.ui.note(_("getting %s\n") % f)
   271         t = repo.file(f).read(get[f])
   269         t = repo.file(f).read(get[f])
   272         repo.wwrite(f, t)
   270         repo.wwrite(f, t)
   273         util.set_exec(repo.wjoin(f), mf2[f])
   271         util.set_exec(repo.wjoin(f), mf2[f])
   274         if moddirstate:
   272         if moddirstate:
   275             if branch_merge:
   273             if branchmerge:
   276                 repo.dirstate.update([f], 'n', st_mtime=-1)
   274                 repo.dirstate.update([f], 'n', st_mtime=-1)
   277             else:
   275             else:
   278                 repo.dirstate.update([f], 'n')
   276                 repo.dirstate.update([f], 'n')
   279 
   277 
   280     # merge the tricky bits
   278     # merge the tricky bits
   288         if ret:
   286         if ret:
   289             err = True
   287             err = True
   290             failedmerge.append(f)
   288             failedmerge.append(f)
   291         util.set_exec(repo.wjoin(f), flag)
   289         util.set_exec(repo.wjoin(f), flag)
   292         if moddirstate:
   290         if moddirstate:
   293             if branch_merge:
   291             if branchmerge:
   294                 # We've done a branch merge, mark this file as merged
   292                 # We've done a branch merge, mark this file as merged
   295                 # so that we properly record the merger later
   293                 # so that we properly record the merger later
   296                 repo.dirstate.update([f], 'm')
   294                 repo.dirstate.update([f], 'm')
   297             else:
   295             else:
   298                 # We've update-merged a locally modified file, so
   296                 # We've update-merged a locally modified file, so
   312         except OSError, inst:
   310         except OSError, inst:
   313             if inst.errno != errno.ENOENT:
   311             if inst.errno != errno.ENOENT:
   314                 repo.ui.warn(_("update failed to remove %s: %s!\n") %
   312                 repo.ui.warn(_("update failed to remove %s: %s!\n") %
   315                              (f, inst.strerror))
   313                              (f, inst.strerror))
   316     if moddirstate:
   314     if moddirstate:
   317         if branch_merge:
   315         if branchmerge:
   318             repo.dirstate.update(remove, 'r')
   316             repo.dirstate.update(remove, 'r')
   319         else:
   317         else:
   320             repo.dirstate.forget(remove)
   318             repo.dirstate.forget(remove)
   321 
   319 
   322     if moddirstate:
   320     if moddirstate:
   328                  (len(remove), _("removed")),
   326                  (len(remove), _("removed")),
   329                  (len(failedmerge), _("unresolved")))
   327                  (len(failedmerge), _("unresolved")))
   330         note = ", ".join([_("%d files %s") % s for s in stats])
   328         note = ", ".join([_("%d files %s") % s for s in stats])
   331         repo.ui.status("%s\n" % note)
   329         repo.ui.status("%s\n" % note)
   332     if moddirstate:
   330     if moddirstate:
   333         if branch_merge:
   331         if branchmerge:
   334             if failedmerge:
   332             if failedmerge:
   335                 repo.ui.status(_("There are unresolved merges,"
   333                 repo.ui.status(_("There are unresolved merges,"
   336                                 " you can redo the full merge using:\n"
   334                                 " you can redo the full merge using:\n"
   337                                 "  hg update -C %s\n"
   335                                 "  hg update -C %s\n"
   338                                 "  hg merge %s\n"
   336                                 "  hg merge %s\n"