# HG changeset patch # User Matt Mackall # Date 2011-11-17 22:53:17 # Node ID 646759147717243ca967fe99c627373c5a72e804 # Parent 5414b56cfad648a0e06ca5f6252f43f69cad264a # Parent 8b011ededfb2abe73f99996bd4ef4bc0b74dd78b merge with stable diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2570,15 +2570,32 @@ def graft(ui, repo, *revs, **opts): if not revs: return -1 + # analyze revs for earlier grafts + ids = {} + for ctx in repo.set("%ld", revs): + ids[ctx.hex()] = ctx.rev() + n = ctx.extra().get('source') + if n: + ids[n] = ctx.rev() + # check ancestors for earlier grafts ui.debug('scanning for duplicate grafts\n') for ctx in repo.set("::. - ::%ld", revs): n = ctx.extra().get('source') - if n and n in repo: + if n in ids: r = repo[n].rev() if r in revs: ui.warn(_('skipping already grafted revision %s\n') % r) revs.remove(r) + elif ids[n] in revs: + ui.warn(_('skipping already grafted revision %s ' + '(same origin %d)\n') % (ids[n], r)) + revs.remove(ids[n]) + elif ctx.hex() in ids: + r = ids[ctx.hex()] + ui.warn(_('skipping already grafted revision %s ' + '(was grafted from %d)\n') % (r, ctx.rev())) + revs.remove(r) if not revs: return -1 @@ -2613,7 +2630,10 @@ def graft(ui, repo, *revs, **opts): cont = False # commit - extra = {'source': ctx.hex()} + source = ctx.extra().get('source') + if not source: + source = ctx.hex() + extra = {'source': source} user = ctx.user() if opts.get('user'): user = opts['user'] @@ -3513,6 +3533,12 @@ def import_(ui, repo, patch1=None, *patc try: p1 = repo[p1] p2 = repo[p2] + # Without any options, consider p2 only if the + # patch is being applied on top of the recorded + # first parent. + if p1 != parents[0]: + p1 = parents[0] + p2 = repo[nullid] except error.RepoError: p1, p2 = parents else: @@ -3520,9 +3546,9 @@ def import_(ui, repo, patch1=None, *patc n = None if update: - if opts.get('exact') and p1 != parents[0]: + if p1 != parents[0]: hg.clean(repo, p1.node()) - if p1 != parents[0] and p2 != parents[1]: + if p2 != parents[1]: repo.dirstate.setparents(p1.node(), p2.node()) if opts.get('exact') or opts.get('import_branch'): @@ -3536,7 +3562,10 @@ def import_(ui, repo, patch1=None, *patc if message: msgs.append(message) else: - if opts.get('exact'): + if opts.get('exact') or p2: + # If you got here, you either use --force and know what + # you are doing or used --exact or a merge patch while + # being updated to its first parent. m = None else: m = scmutil.matchfiles(repo, files or []) diff --git a/mercurial/discovery.py b/mercurial/discovery.py --- a/mercurial/discovery.py +++ b/mercurial/discovery.py @@ -178,9 +178,9 @@ def prepush(repo, remote, force, revs, n hint = _("did you forget to merge? " "use push -f to force") if branch is not None: - repo.ui.note("new remote heads on branch '%s'\n" % branch) + repo.ui.note(_("new remote heads on branch '%s'\n") % branch) for h in dhs: - repo.ui.note("new remote head %s\n" % short(h)) + repo.ui.note(_("new remote head %s\n") % short(h)) if error: raise util.Abort(error, hint=hint) diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -124,7 +124,7 @@ def _runcatch(req): ui.warn(_("hg: %s\n") % inst.args[1]) commands.help_(ui, 'shortlist') except error.OutOfBandError, inst: - ui.warn("abort: remote error:\n") + ui.warn(_("abort: remote error:\n")) ui.warn(''.join(inst.args)) except error.RepoError, inst: ui.warn(_("abort: %s!\n") % inst) diff --git a/mercurial/help/urls.txt b/mercurial/help/urls.txt --- a/mercurial/help/urls.txt +++ b/mercurial/help/urls.txt @@ -1,7 +1,7 @@ Valid URLs are of the form:: local/filesystem/path[#revision] - file://local/filesystem/path[#revision] + file://localhost/filesystem/path[#revision] http://[user[:pass]@]host[:port]/[path][#revision] https://[user[:pass]@]host[:port]/[path][#revision] ssh://[user@]host[:port]/[path][#revision] diff --git a/mercurial/hook.py b/mercurial/hook.py --- a/mercurial/hook.py +++ b/mercurial/hook.py @@ -139,6 +139,7 @@ def hook(ui, repo, name, throw=False, ** stderrno = sys.__stderr__.fileno() # temporarily redirect stdout to stderr, if possible if stdoutno >= 0 and stderrno >= 0: + sys.__stdout__.flush() oldstdout = os.dup(stdoutno) os.dup2(stderrno, stdoutno) except AttributeError: diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py --- a/mercurial/mdiff.py +++ b/mercurial/mdiff.py @@ -72,7 +72,7 @@ def wsclean(opts, text, blank=True): text = re.sub('[ \t\r]+', ' ', text) text = text.replace(' \n', '\n') if blank and opts.ignoreblanklines: - text = re.sub('\n+', '', text) + text = re.sub('\n+', '\n', text).strip('\n') return text def diffline(revs, a, b, opts): diff --git a/mercurial/setdiscovery.py b/mercurial/setdiscovery.py --- a/mercurial/setdiscovery.py +++ b/mercurial/setdiscovery.py @@ -128,7 +128,7 @@ def findcommonheads(ui, local, remote, return (srvheadhashes, False, srvheadhashes,) if sample and util.all(yesno): - ui.note("all local heads known remotely\n") + ui.note(_("all local heads known remotely\n")) ownheadhashes = dag.externalizeall(ownheads) return (ownheadhashes, True, srvheadhashes,) @@ -158,7 +158,7 @@ def findcommonheads(ui, local, remote, break if full: - ui.note("sampling from both directions\n") + ui.note(_("sampling from both directions\n")) sample = _takefullsample(dag, undecided, size=fullsamplesize) elif common: # use cheapish initial sample diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -223,7 +223,7 @@ def _abssource(repo, push=False, abort=T source.path = posixpath.normpath(source.path) parent = _abssource(repo._subparent, push, abort=False) if parent: - parent = util.url(parent) + parent = util.url(util.pconvert(parent)) parent.path = posixpath.join(parent.path or '', source.path) parent.path = posixpath.normpath(parent.path) return str(parent) diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -16,7 +16,7 @@ hide platform-specific details from the from i18n import _ import error, osutil, encoding import errno, re, shutil, sys, tempfile, traceback -import os, time, calendar, textwrap, signal +import os, time, datetime, calendar, textwrap, signal import imp, socket, urllib if os.name == 'nt': @@ -900,16 +900,14 @@ def filechunkiter(f, size=65536, limit=N yield s def makedate(): - lt = time.localtime() - if lt[8] == 1 and time.daylight: - tz = time.altzone - else: - tz = time.timezone - t = time.mktime(lt) - if t < 0: + ct = time.time() + if ct < 0: hint = _("check your clock") - raise Abort(_("negative timestamp: %d") % t, hint=hint) - return t, tz + raise Abort(_("negative timestamp: %d") % ct, hint=hint) + delta = (datetime.datetime.utcfromtimestamp(ct) - + datetime.datetime.fromtimestamp(ct)) + tz = delta.days * 86400 + delta.seconds + return ct, tz def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'): """represent a (unixtime, offset) tuple as a localized time. @@ -1708,7 +1706,8 @@ class url(object): # letters to paths with drive letters. if hasdriveletter(self._hostport): path = self._hostport + '/' + self.path - elif self.host is not None and self.path: + elif (self.host is not None and self.path + and not hasdriveletter(path)): path = '/' + path return path return self._origpath diff --git a/tests/test-diff-ignore-whitespace.t b/tests/test-diff-ignore-whitespace.t --- a/tests/test-diff-ignore-whitespace.t +++ b/tests/test-diff-ignore-whitespace.t @@ -442,3 +442,16 @@ Only new line noticed: New line not noticed when space change ignored: $ hg ndiff --ignore-blank-lines --ignore-all-space + +Do not ignore all newlines, only blank lines + + $ printf 'hello \nworld\ngoodbye world\n' > foo + $ hg ndiff --ignore-blank-lines + diff -r 540c40a65b78 foo + --- a/foo + +++ b/foo + @@ -1,2 +1,3 @@ + -hello world + +hello + +world + goodbye world diff --git a/tests/test-graft.t b/tests/test-graft.t --- a/tests/test-graft.t +++ b/tests/test-graft.t @@ -200,28 +200,80 @@ Compare with original: View graph: - $ hg --config extensions.graphlog= log -G --template '{author}@rev: {desc}\n' - @ test@rev: 3 + $ hg --config extensions.graphlog= log -G --template '{author}@{rev}: {desc}\n' + @ test@11: 3 | - o test@rev: 4 + o test@10: 4 | - o test@rev: 5 + o test@9: 5 | - o bar@rev: 1 + o bar@8: 1 | - o foo@rev: 2 + o foo@7: 2 | - | o test@rev: 6 + | o test@6: 6 | |\ - | | o test@rev: 5 + | | o test@5: 5 | | | - | o | test@rev: 4 + | o | test@4: 4 | |/ - | o baz@rev: 3 + | o baz@3: 3 + | | + | o test@2: 2 | | - | o test@rev: 2 - | | - | o bar@rev: 1 + | o bar@1: 1 |/ - o test@rev: 0 + o test@0: 0 +Graft again onto another branch should preserve the original source + $ hg up -q 0 + $ echo 'g'>g + $ hg add g + $ hg ci -m 7 + created new head + $ hg graft 7 + grafting revision 7 + + $ hg log -r 7 --template '{rev}:{node}\n' + 7:d2e44c99fd3f31c176ea4efb9eca9f6306c81756 + $ hg log -r 2 --template '{rev}:{node}\n' + 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4 + + $ hg log --debug -r tip + changeset: 13:39bb1d13572759bd1e6fc874fed1b12ece047a18 + tag: tip + parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f + parent: -1:0000000000000000000000000000000000000000 + manifest: 13:0780e055d8f4cd12eadd5a2719481648f336f7a9 + user: foo + date: Thu Jan 01 00:00:00 1970 +0000 + files+: b + files-: a + extra: branch=default + extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4 + description: + 2 + + +Disallow grafting an already grafted cset onto its original branch + $ hg up -q 6 + $ hg graft 7 + skipping already grafted revision 7 (was grafted from 2) + [255] + +Disallow grafting already grafted csets with the same origin onto each other + $ hg up -q 13 + $ hg graft 2 + skipping already grafted revision 2 + [255] + $ hg graft 7 + skipping already grafted revision 7 (same origin 2) + [255] + + $ hg up -q 7 + $ hg graft 2 + skipping already grafted revision 2 + [255] + $ hg graft tip + skipping already grafted revision 13 (same origin 2) + [255] diff --git a/tests/test-import-merge.t b/tests/test-import-merge.t new file mode 100644 --- /dev/null +++ b/tests/test-import-merge.t @@ -0,0 +1,114 @@ + $ echo "[extensions]" >> $HGRCPATH + $ echo "mq=" >> $HGRCPATH + + $ tipparents() { + > hg parents --template "{rev}:{node|short} {desc|firstline}\n" -r tip + > } + +Test import and merge diffs + + $ hg init repo + $ cd repo + $ echo a > a + $ hg ci -Am adda + adding a + $ echo a >> a + $ hg ci -m changea + $ echo c > c + $ hg ci -Am addc + adding c + $ hg up 0 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo b > b + $ hg ci -Am addb + adding b + created new head + $ hg up 1 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg merge 3 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m merge + $ hg export . > ../merge.diff + $ cd .. + $ hg clone -r2 repo repo2 + adding changesets + adding manifests + adding file changes + added 3 changesets with 3 changes to 2 files + updating to branch default + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd repo2 + $ hg pull -r3 ../repo + pulling from ../repo + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files (+1 heads) + (run 'hg heads' to see heads, 'hg merge' to merge) + +Test without --exact and diff.p1 == workingdir.p1 + + $ hg up 1 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg import ../merge.diff + applying ../merge.diff + $ tipparents + 1:540395c44225 changea + 3:102a90ea7b4a addb + $ hg strip --no-backup tip + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + +Test without --exact and diff.p1 != workingdir.p1 + + $ hg up 2 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg import ../merge.diff + applying ../merge.diff + $ tipparents + 2:890ecaa90481 addc + $ hg strip --no-backup tip + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + +Test with --exact + + $ hg import --exact ../merge.diff + applying ../merge.diff + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ tipparents + 1:540395c44225 changea + 3:102a90ea7b4a addb + $ hg strip --no-backup tip + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + +Test with --bypass and diff.p1 == workingdir.p1 + + $ hg up 1 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg import --bypass ../merge.diff + applying ../merge.diff + $ tipparents + 1:540395c44225 changea + 3:102a90ea7b4a addb + $ hg strip --no-backup tip + +Test with --bypass and diff.p1 != workingdir.p1 + + $ hg up 2 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg import --bypass ../merge.diff + applying ../merge.diff + $ tipparents + 2:890ecaa90481 addc + $ hg strip --no-backup tip + +Test with --bypass and --exact + + $ hg import --bypass --exact ../merge.diff + applying ../merge.diff + $ tipparents + 1:540395c44225 changea + 3:102a90ea7b4a addb + $ hg strip --no-backup tip + diff --git a/tests/test-url.py b/tests/test-url.py --- a/tests/test-url.py +++ b/tests/test-url.py @@ -223,6 +223,14 @@ def test_url(): >>> u.localpath() 'f:oo/bar/baz' + >>> u = url('file://localhost/f:oo/bar/baz') + >>> u + + >>> str(u) + 'file://localhost/f:oo/bar/baz' + >>> u.localpath() + 'f:oo/bar/baz' + >>> u = url('file:foo/bar/baz') >>> u