(+mercurial-devel) On Tue, Feb 14, 2017 at 10:48 AM, Gábor STEFANIK <gabor.stefa...@nng.com> wrote: >> > > > -------------------------------------------------------------------------- > This message, including its attachments, is confidential. For more > information please read NNG's email policy here: > http://www.nng.com/emailpolicy/ > By responding to this email you accept the email policy. > > > -----Original Message----- >> From: Mercurial-devel [mailto:mercurial-devel-boun...@mercurial-scm.org] >> On Behalf Of Martin von Zweigbergk via Mercurial-devel >> Sent: Tuesday, February 14, 2017 2:07 AM >> To: mercurial-devel@mercurial-scm.org >> Subject: [PATCH 5 of 6] update: learn --merge to allow merging across >> topological branches (issue5125) >> >> # HG changeset patch >> # User Martin von Zweigbergk <martinv...@google.com> >> # Date 1487019517 28800 >> # Mon Feb 13 12:58:37 2017 -0800 >> # Node ID 75e5a492d7f69420a554fe498ae24060c755b09f >> # Parent 59e2d3da607cc09ebe133ab199fc4f343d74e1e6 >> update: learn --merge to allow merging across topological branches >> (issue5125) >> >> diff -r 59e2d3da607c -r 75e5a492d7f6 mercurial/commands.py >> --- a/mercurial/commands.py Mon Feb 13 15:04:46 2017 -0800 >> +++ b/mercurial/commands.py Mon Feb 13 12:58:37 2017 -0800 >> @@ -6471,12 +6471,13 @@ >> @command('^update|up|checkout|co', >> [('C', 'clean', None, _('discard uncommitted changes (no backup)')), >> ('c', 'check', None, _('require clean working directory')), >> + ('m', 'merge', None, _('merge local changes')), >> ('d', 'date', '', _('tipmost revision matching date'), _('DATE')), >> ('r', 'rev', '', _('revision'), _('REV')) >> ] + mergetoolopts, >> - _('[-C|-c] [-d DATE] [[-r] REV]')) >> + _('[-C|-c|-m] [-d DATE] [[-r] REV]')) >> def update(ui, repo, node=None, rev=None, clean=False, date=None, >> check=False, >> - tool=None): >> + merge=None, tool=None): >> """update working directory (or switch revisions) >> >> Update the repository's working directory to the specified >> @@ -6498,7 +6499,7 @@ >> The following rules apply when the working directory contains >> uncommitted changes: >> >> - 1. If neither -c/--check nor -C/--clean is specified, and if >> + 1. If none of -c/--check, -C/--clean, or -m/--merge is specified, and >> if >> the requested changeset is an ancestor or descendant of >> the working directory's parent, the uncommitted changes >> are merged into the requested changeset and the merged >> @@ -6507,10 +6508,14 @@ >> branch), the update is aborted and the uncommitted changes >> are preserved. >> >> - 2. With the -c/--check option, the update is aborted and the >> + 2. With the -m/--merge option, the update is allowed even if the >> + requested changeset is not an ancestor or descendant of >> + the working directory's parent. >> + >> + 3. With the -c/--check option, the update is aborted and the >> uncommitted changes are preserved. >> >> - 3. With the -C/--clean option, uncommitted changes are discarded and >> + 4. With the -C/--clean option, uncommitted changes are discarded and >> the working directory is updated to the requested changeset. >> >> To cancel an uncommitted merge (and lose your changes), use >> @@ -6535,8 +6540,15 @@ >> if date and rev is not None: >> raise error.Abort(_("you can't specify a revision and a date")) >> >> - if check and clean: >> - raise error.Abort(_("cannot specify both -c/--check and >> -C/--clean")) >> + if len([x for x in (check, clean , merge) if x]) > 1: >> + raise error.Abort(_("can only specify one of -c/--check, >> -C/--clean, " >> + "and -m/merge")) >> + >> + updatecheck = 'linear' >> + if check: >> + updatecheck = 'abort' >> + elif merge: >> + updatecheck = None > > I don't really like the use of None to indicate "always merge". > I would strongly prefer updatecheck = 'merge', with None instead > representing a default or "unset" case.
Makes sense. Since the check that's done is not about merging, I'll call it 'none' instead, if you don't mind. > > This makes setting the default via a config option (as in your 6th patch) > a lot safer and easier - see below. > >> >> with repo.wlock(): >> cmdutil.clearunfinished(repo) >> @@ -6550,7 +6562,8 @@ >> >> repo.ui.setconfig('ui', 'forcemerge', tool, 'update') >> >> - return hg.updatetotally(ui, repo, rev, brev, clean=clean, >> check=check) >> + return hg.updatetotally(ui, repo, rev, brev, clean=clean, >> + updatecheck=updatecheck) >> >> @command('verify', []) >> def verify(ui, repo): >> diff -r 59e2d3da607c -r 75e5a492d7f6 mercurial/hg.py >> --- a/mercurial/hg.py Mon Feb 13 15:04:46 2017 -0800 >> +++ b/mercurial/hg.py Mon Feb 13 12:58:37 2017 -0800 >> @@ -681,18 +681,19 @@ >> repo.ui.status(_("%d files updated, %d files merged, " >> "%d files removed, %d files unresolved\n") % stats) >> >> -def updaterepo(repo, node, overwrite): >> +def updaterepo(repo, node, overwrite, updatecheck=None): >> """Update the working directory to node. >> >> When overwrite is set, changes are clobbered, merged else >> >> returns stats (see pydoc mercurial.merge.applyupdates)""" >> return mergemod.update(repo, node, False, overwrite, >> - labels=['working copy', 'destination']) >> + labels=['working copy', 'destination'], >> + updatecheck=updatecheck) >> >> -def update(repo, node, quietempty=False): >> - """update the working directory to node, merging linear changes""" >> - stats = updaterepo(repo, node, False) >> +def update(repo, node, quietempty=False, updatecheck=None): >> + """update the working directory to node""" >> + stats = updaterepo(repo, node, False, updatecheck=updatecheck) >> _showstats(repo, stats, quietempty) >> if stats[3]: >> repo.ui.status(_("use 'hg resolve' to retry unresolved file >> merges\n")) >> @@ -712,7 +713,8 @@ >> # naming conflict in updatetotally() >> _clean = clean >> >> -def updatetotally(ui, repo, checkout, brev, clean=False, check=False): >> +def updatetotally(ui, repo, checkout, brev, clean=False, >> + updatecheck='linear'): > > Please make this updatecheck=None, and set it to 'linear' inside > merge.update() > explicitly if None was passed to that function. Will do. > > This way, in patch 6, you can red the config option inside merge.update(), > and let > other callers (primarily extensions) also automatically follow the config > option. I don't think it's a good idea for the low-level merge.update() to read the config. That function is called e.g. by rebase and graft and they should not have their behavior changed by this config. > >> """Update the working directory with extra care for non-file components >> >> This takes care of non-file components below: >> @@ -724,7 +726,14 @@ >> :checkout: to which revision the working directory is updated >> :brev: a name, which might be a bookmark to be activated after updating >> :clean: whether changes in the working directory can be discarded >> - :check: whether changes in the working directory should be checked >> + :updatecheck: how to deal with a dirty working directory >> + >> + Valid values for updatecheck are: >> + >> + * abort: abort if the working directory is dirty >> + * None: don't check (merge working directory changes into destination) >> + * linear: check that update is linear before merging working directory >> + changes into destination >> >> This returns whether conflict is detected at updating or not. >> """ >> @@ -739,9 +748,10 @@ >> if clean: >> ret = _clean(repo, checkout) >> else: >> - if check: >> + if updatecheck == 'abort': >> cmdutil.bailifchanged(repo, merge=False) >> - ret = _update(repo, checkout) >> + updatecheck = None >> + ret = _update(repo, checkout, updatecheck=updatecheck) >> >> if not ret and movemarkfrom: >> if movemarkfrom == repo['.'].node(): >> diff -r 59e2d3da607c -r 75e5a492d7f6 mercurial/merge.py >> --- a/mercurial/merge.py Mon Feb 13 15:04:46 2017 -0800 >> +++ b/mercurial/merge.py Mon Feb 13 12:58:37 2017 -0800 >> @@ -1444,7 +1444,8 @@ >> repo.dirstate.normal(f) >> >> def update(repo, node, branchmerge, force, ancestor=None, >> - mergeancestor=False, labels=None, matcher=None, >> mergeforce=False): >> + mergeancestor=False, labels=None, matcher=None, >> mergeforce=False, >> + updatecheck='linear'): > > Again, default to None here, and explicitly set to 'linear' > (and later set it based on config) if it's None. Will do. > >> """ >> Perform a merge between the working directory and the given node >> >> @@ -1494,6 +1495,7 @@ >> # This functon used to find the default destination if node was None, >> but >> # that's now in destutil.py. >> assert node is not None >> + assert updatecheck in (None, 'linear') >> # If we're doing a partial update, we need to skip updating >> # the dirstate, so make a note of any partial-ness to the >> # update here. >> @@ -1550,7 +1552,8 @@ >> repo.hook('update', parent1=xp2, parent2='', error=0) >> return 0, 0, 0, 0 >> >> - if pas not in ([p1], [p2]): # nonlinear >> + if (updatecheck == 'linear' and >> + pas not in ([p1], [p2])): # nonlinear >> dirty = wc.dirty(missing=True) >> if dirty: >> # Branching is a bit strange to ensure we do the minimal >> diff -r 59e2d3da607c -r 75e5a492d7f6 tests/test-completion.t >> --- a/tests/test-completion.t Mon Feb 13 15:04:46 2017 -0800 >> +++ b/tests/test-completion.t Mon Feb 13 12:58:37 2017 -0800 >> @@ -223,7 +223,7 @@ >> serve: accesslog, daemon, daemon-postexec, errorlog, port, address, >> prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, >> style, ipv6, certificate >> status: all, modified, added, removed, deleted, clean, unknown, ignored, >> no-status, copies, print0, rev, change, include, exclude, subrepos, template >> summary: remote >> - update: clean, check, date, rev, tool >> + update: clean, check, merge, date, rev, tool >> addremove: similarity, subrepos, include, exclude, dry-run >> archive: no-decode, prefix, rev, type, subrepos, include, exclude >> backout: merge, commit, no-commit, parent, rev, edit, tool, include, >> exclude, message, logfile, date, user >> diff -r 59e2d3da607c -r 75e5a492d7f6 tests/test-update-branches.t >> --- a/tests/test-update-branches.t Mon Feb 13 15:04:46 2017 -0800 >> +++ b/tests/test-update-branches.t Mon Feb 13 12:58:37 2017 -0800 >> @@ -160,6 +160,16 @@ >> parent=1 >> M foo >> >> + $ revtest '-m dirty linear' dirty 1 2 -m >> + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved >> + parent=2 >> + M foo >> + >> + $ revtest '-m dirty cross' dirty 3 4 -m >> + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved >> + parent=4 >> + M foo >> + >> $ revtest '-c dirtysub linear' dirtysub 1 2 -c >> abort: uncommitted changes in subrepository 'sub' >> parent=1 >> @@ -171,7 +181,17 @@ >> parent=2 >> >> $ revtest '-cC dirty linear' dirty 1 2 -cC >> - abort: cannot specify both -c/--check and -C/--clean >> + abort: can only specify one of -c/--check, -C/--clean, and -m/merge >> + parent=1 >> + M foo >> + >> + $ revtest '-mc dirty linear' dirty 1 2 -mc >> + abort: can only specify one of -c/--check, -C/--clean, and -m/merge >> + parent=1 >> + M foo >> + >> + $ revtest '-mC dirty linear' dirty 1 2 -mC >> + abort: can only specify one of -c/--check, -C/--clean, and -m/merge >> parent=1 >> M foo >> >> _______________________________________________ >> Mercurial-devel mailing list >> Mercurial-devel@mercurial-scm.org >> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel