Patchwork [4,of,5,filtering,part,2,V2] clfilter: use filtering in `visibleheads` and `visiblebranchmap`

login
register
mail settings
Submitter Pierre-Yves David
Date Dec. 10, 2012, 5:30 p.m.
Message ID <0ffb3f54b38648807bb2.1355160624@crater1.logilab.fr>
Download mbox | patch
Permalink /patch/43/
State Superseded, archived
Commit a2cebd3e4daaa0565733b75fa1275c497746e115
Headers show

Comments

Pierre-Yves David - Dec. 10, 2012, 5:30 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at ens-lyon.org>
# Date 1354463434 -3600
# Node ID 0ffb3f54b38648807bb24f020db9fbde84615c52
# Parent  37c514a7a7d59b318ca066e0c797cfedbfd3dccd
clfilter: use filtering in `visibleheads` and `visiblebranchmap`

This is the first real use of changelog filtering. The change is very small to
allow testing the new filter with a setup close to the original one.

We replace custom post processing on `heads` and `branchmap` function by call to
the standard code pass on a filtering repo.

In later coming will have wider usage of filtering that will make the dedicated
function useless.
Idan Kamara - Dec. 14, 2012, 6:34 p.m.
On Mon, Dec 10, 2012 at 7:30 PM,  <pierre-yves.david at logilab.fr> wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david at ens-lyon.org>
> # Date 1354463434 -3600
> # Node ID 0ffb3f54b38648807bb24f020db9fbde84615c52
> # Parent  37c514a7a7d59b318ca066e0c797cfedbfd3dccd
> clfilter: use filtering in `visibleheads` and `visiblebranchmap`

I think this patch can be split to 3:

1) introduce 'unserved' filter
2) use it in visibleheads
3) use it in visiblebranchmap

>
> This is the first real use of changelog filtering. The change is very small to
> allow testing the new filter with a setup close to the original one.
>
> We replace custom post processing on `heads` and `branchmap` function by call to
> the standard code pass on a filtering repo.
>
> In later coming will have wider usage of filtering that will make the dedicated
> function useless.
>
> diff --git a/mercurial/discovery.py b/mercurial/discovery.py
> --- a/mercurial/discovery.py
> +++ b/mercurial/discovery.py
> @@ -336,42 +336,11 @@ def checkheads(repo, remote, outgoing, r
>      if unsynced:
>          repo.ui.warn(_("note: unsynced remote changes!\n"))
>
>  def visibleheads(repo):
>      """return the set of visible head of this repo"""
> -    # XXX we want a cache on this
> -    sroots = repo._phasecache.phaseroots[phases.secret]
> -    if sroots or repo.obsstore:
> -        # XXX very slow revset. storing heads or secret "boundary"
> -        # would help.
> -        revset = repo.set('heads(not (%ln:: + extinct()))', sroots)
> -
> -        vheads = [ctx.node() for ctx in revset]
> -        if not vheads:
> -            vheads.append(nullid)
> -    else:
> -        vheads = repo.heads()
> -    return vheads
> +    return repo.filtered('unserved').heads()
>
>
>  def visiblebranchmap(repo):
>      """return a branchmap for the visible set"""
> -    # XXX Recomputing this data on the fly is very slow.  We should build a
> -    # XXX cached version while computing the standard branchmap version.
> -    sroots = repo._phasecache.phaseroots[phases.secret]
> -    if sroots or repo.obsstore:
> -        vbranchmap = {}
> -        for branch, nodes in  repo.branchmap().iteritems():
> -            # search for secret heads.
> -            for n in nodes:
> -                if repo[n].phase() >= phases.secret:
> -                    nodes = None
> -                    break
> -            # if secret heads were found we must compute them again
> -            if nodes is None:
> -                s = repo.set('heads(branch(%s) - secret() - extinct())',
> -                             branch)
> -                nodes = [c.node() for c in s]
> -            vbranchmap[branch] = nodes
> -    else:
> -        vbranchmap = repo.branchmap()
> -    return vbranchmap
> +    return repo.filtered('unserved').branchmap()
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -57,11 +57,21 @@ def unfilteredmethod(orig):
>      def wrapper(repo, *args, **kwargs):
>          return orig(repo.unfiltered(), *args, **kwargs)
>      return wrapper
>
>  # function to compute filtered set
> -computefiltered = {}
> +def computeunserved(repo):
> +    """compute the set of revision that should be filtered when used a server
> +
> +    Secret and hidden changeset should not pretend to be here."""
> +    assert not repo.changelog.filteredrevs
> +    # fast path in simple case to avoid impact of non optimised code
> +    if phases.hassecret(repo) or repo.obsstore:
> +        return frozenset(repo.revs('hidden() + secret()'))
> +    return ()
> +
> +computefiltered = {'unserved': computeunserved}
>
>  def _filteredrevs(repo, filtername):
>      """returns set of filtered revision for this filter name"""
>      if filtername not in repo.revsfiltercache:
>          func = computefiltered[filtername]
> diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
> --- a/tests/test-obsolete.t
> +++ b/tests/test-obsolete.t
> @@ -174,10 +174,11 @@ the public changeset
>  And that we can't push bumped changeset
>
>    $ hg push ../tmpa -r 0 --force #(make repo)
>    pushing to ../tmpa
>    searching for changes
> +  warning: repository is unrelated

What's this?
Pierre-Yves David - Dec. 16, 2012, 12:22 a.m.
On 14 d?c. 2012, at 19:34, Idan Kamara wrote:

> On Mon, Dec 10, 2012 at 7:30 PM,  <pierre-yves.david at logilab.fr> wrote:
>> # HG changeset patch
>> # User Pierre-Yves David <pierre-yves.david at ens-lyon.org>
>> # Date 1354463434 -3600
>> # Node ID 0ffb3f54b38648807bb24f020db9fbde84615c52
>> # Parent  37c514a7a7d59b318ca066e0c797cfedbfd3dccd
>> clfilter: use filtering in `visibleheads` and `visiblebranchmap`
> 
> I think this patch can be split to 3:
> 
> 1) introduce 'unserved' filter
> 2) use it in visibleheads
> 3) use it in visiblebranchmap

Right, good catch.

>> --- a/tests/test-obsolete.t
>> +++ b/tests/test-obsolete.t
>> @@ -174,10 +174,11 @@ the public changeset
>> And that we can't push bumped changeset
>> 
>>   $ hg push ../tmpa -r 0 --force #(make repo)
>>   pushing to ../tmpa
>>   searching for changes
>> +  warning: repository is unrelated
> 
> What's this?

Expected warning now we have a more correct filtering. See preliminary changeset on the topic.

http://www.selenic.com/hg/rev/42f56a0418b3

Patch

diff --git a/mercurial/discovery.py b/mercurial/discovery.py
--- a/mercurial/discovery.py
+++ b/mercurial/discovery.py
@@ -336,42 +336,11 @@  def checkheads(repo, remote, outgoing, r
     if unsynced:
         repo.ui.warn(_("note: unsynced remote changes!\n"))
 
 def visibleheads(repo):
     """return the set of visible head of this repo"""
-    # XXX we want a cache on this
-    sroots = repo._phasecache.phaseroots[phases.secret]
-    if sroots or repo.obsstore:
-        # XXX very slow revset. storing heads or secret "boundary"
-        # would help.
-        revset = repo.set('heads(not (%ln:: + extinct()))', sroots)
-
-        vheads = [ctx.node() for ctx in revset]
-        if not vheads:
-            vheads.append(nullid)
-    else:
-        vheads = repo.heads()
-    return vheads
+    return repo.filtered('unserved').heads()
 
 
 def visiblebranchmap(repo):
     """return a branchmap for the visible set"""
-    # XXX Recomputing this data on the fly is very slow.  We should build a
-    # XXX cached version while computing the standard branchmap version.
-    sroots = repo._phasecache.phaseroots[phases.secret]
-    if sroots or repo.obsstore:
-        vbranchmap = {}
-        for branch, nodes in  repo.branchmap().iteritems():
-            # search for secret heads.
-            for n in nodes:
-                if repo[n].phase() >= phases.secret:
-                    nodes = None
-                    break
-            # if secret heads were found we must compute them again
-            if nodes is None:
-                s = repo.set('heads(branch(%s) - secret() - extinct())',
-                             branch)
-                nodes = [c.node() for c in s]
-            vbranchmap[branch] = nodes
-    else:
-        vbranchmap = repo.branchmap()
-    return vbranchmap
+    return repo.filtered('unserved').branchmap()
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -57,11 +57,21 @@  def unfilteredmethod(orig):
     def wrapper(repo, *args, **kwargs):
         return orig(repo.unfiltered(), *args, **kwargs)
     return wrapper
 
 # function to compute filtered set
-computefiltered = {}
+def computeunserved(repo):
+    """compute the set of revision that should be filtered when used a server
+
+    Secret and hidden changeset should not pretend to be here."""
+    assert not repo.changelog.filteredrevs
+    # fast path in simple case to avoid impact of non optimised code
+    if phases.hassecret(repo) or repo.obsstore:
+        return frozenset(repo.revs('hidden() + secret()'))
+    return ()
+
+computefiltered = {'unserved': computeunserved}
 
 def _filteredrevs(repo, filtername):
     """returns set of filtered revision for this filter name"""
     if filtername not in repo.revsfiltercache:
         func = computefiltered[filtername]
diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
--- a/tests/test-obsolete.t
+++ b/tests/test-obsolete.t
@@ -174,10 +174,11 @@  the public changeset
 And that we can't push bumped changeset
 
   $ hg push ../tmpa -r 0 --force #(make repo)
   pushing to ../tmpa
   searching for changes
+  warning: repository is unrelated
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
   $ hg push ../tmpa