diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -1050,7 +1050,7 @@ def bundle(ui, repo, fname, dest=None, * portable=True) cg = repo.getlocalbundle('bundle', outgoing) if not cg: - scmutil.nochangesfound(ui, outgoing and outgoing.excluded) + scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded) return 1 changegroup.writebundle(cg, fname, bundletype) diff --git a/mercurial/discovery.py b/mercurial/discovery.py --- a/mercurial/discovery.py +++ b/mercurial/discovery.py @@ -116,7 +116,7 @@ def findcommonoutgoing(repo, other, only # use visible heads as it should be cached og.missingheads = visibleheads(repo) # extinct changesets are silently ignored - og.excluded = [ctx.node() for ctx in repo.set('secret()')] + og.excluded = [ctx.node() for ctx in repo.set('secret() or extinct()')] else: # compute common, missing and exclude secret stuff sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads) @@ -125,12 +125,10 @@ def findcommonoutgoing(repo, other, only og.excluded = excluded = [] for node in allmissing: ctx = repo[node] - if not ctx.extinct(): - # extinct changesets are silently ignored - if ctx.phase() >= phases.secret: - excluded.append(node) - else: - missing.append(node) + if ctx.phase() >= phases.secret or ctx.extinct(): + excluded.append(node) + else: + missing.append(node) if len(missing) == len(allmissing): missingheads = onlyheads else: # update missing heads diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -525,7 +525,7 @@ def _outgoing(ui, repo, dest, opts): force=opts.get('force')) o = outgoing.missing if not o: - scmutil.nochangesfound(repo.ui, outgoing.excluded) + scmutil.nochangesfound(repo.ui, repo, outgoing.excluded) return None return o diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1844,7 +1844,7 @@ class localrepository(object): if not outgoing.missing: # nothing to push - scmutil.nochangesfound(self.ui, outgoing.excluded) + scmutil.nochangesfound(self.ui, self, outgoing.excluded) ret = None else: # something to push diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py --- a/mercurial/scmutil.py +++ b/mercurial/scmutil.py @@ -6,12 +6,21 @@ # GNU General Public License version 2 or any later version. from i18n import _ -import util, error, osutil, revset, similar, encoding +import util, error, osutil, revset, similar, encoding, phases import match as matchmod import os, errno, re, stat, sys, glob -def nochangesfound(ui, secretlist=None): - '''report no changes for push/pull''' +def nochangesfound(ui, repo, excluded=None): + '''Report no changes for push/pull, excluded is None or a list of + nodes excluded from the push/pull. + ''' + secretlist = [] + if excluded: + for n in excluded: + ctx = repo[n] + if ctx.phase() >= phases.secret and not ctx.extinct(): + secretlist.append(n) + if secretlist: ui.status(_("no changes found (ignored %d secret changesets)\n") % len(secretlist)) diff --git a/tests/test-obsolete-changeset-exchange.t b/tests/test-obsolete-changeset-exchange.t new file mode 100644 --- /dev/null +++ b/tests/test-obsolete-changeset-exchange.t @@ -0,0 +1,48 @@ +Test changesets filtering during exchanges (some tests are still in +test-obsolete.t) + +Push does corrupt remote +------------------------ + +Create a DAG where a changeset reuses a revision from a file first used in an +extinct changeset. + + $ hg init local + $ cd local + $ echo 'base' > base + $ hg commit -Am base + adding base + $ echo 'A' > A + $ hg commit -Am A + adding A + $ hg up 0 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg revert -ar 1 + adding A + $ hg commit -Am "A'" + created new head + $ hg log -G --template='{desc} {node}' + @ A' f89bcc95eba5174b1ccc3e33a82e84c96e8338ee + | + | o A 9d73aac1b2ed7d53835eaeec212ed41ea47da53a + |/ + o base d20a80d4def38df63a4b330b7fb688f3d4cae1e3 + + $ hg debugobsolete 9d73aac1b2ed7d53835eaeec212ed41ea47da53a f89bcc95eba5174b1ccc3e33a82e84c96e8338ee + +Push it. The bundle should not refer to the extinct changeset. + + $ hg init ../other + $ hg push ../other + pushing to ../other + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + $ hg -R ../other verify + checking changesets + checking manifests + crosschecking files in changesets and manifests + checking files + 2 files, 2 changesets, 2 total revisions