Patchwork [1,of,1] fix sparse:subprepo.subrepo - now provide DummySubrepo for subs out of sparse

login
register
mail settings
Submitter alexrayne
Date May 13, 2021, 5:35 p.m.
Message ID <57d1837724ebe88c2760.1620927320@black2>
Download mbox | patch
Permalink /patch/49028/
State New
Headers show

Comments

alexrayne - May 13, 2021, 5:35 p.m.
# HG changeset patch
# User alexrayne <alexraynepe196@gmail.com>
# Date 1619989845 -10800
#      Mon May 03 00:10:45 2021 +0300
# Branch stable
# Node ID 57d1837724ebe88c276013a621a3de9163bd51f7
# Parent  b7e623ac98b6f0d3b4e2f394637ae3f1a2a59711
fix sparse:subprepo.subrepo - now provide DummySubrepo for subs out of sparse.
        This dummy sub is empty node, always clean and ready to get/remove
fix subrepoutil.submerge - now ignores changes for items out of sparce
Raphaël Gomès - May 19, 2021, 8:29 a.m.
Hi,

This patch breaks a few tests in the Heptapod CI [1]. I have removed it 
from the queue, please feel free to send a second version.

[1] https://foss.heptapod.net/octobus/mercurial-devel/-/pipelines/22116

On 5/13/21 7:35 PM, alexrayne wrote:
> # HG changeset patch
> # User alexrayne <alexraynepe196@gmail.com>
> # Date 1619989845 -10800
> #      Mon May 03 00:10:45 2021 +0300
> # Branch stable
> # Node ID 57d1837724ebe88c276013a621a3de9163bd51f7
> # Parent  b7e623ac98b6f0d3b4e2f394637ae3f1a2a59711
> fix sparse:subprepo.subrepo - now provide DummySubrepo for subs out of sparse.
>          This dummy sub is empty node, always clean and ready to get/remove
> fix subrepoutil.submerge - now ignores changes for items out of sparce
>
> diff --git a/hgext/sparse.py b/hgext/sparse.py
> --- a/hgext/sparse.py
> +++ b/hgext/sparse.py
> @@ -78,6 +78,8 @@
>   from mercurial import (
>       commands,
>       dirstate,
> +    subrepoutil,
> +    subrepo,
>       error,
>       extensions,
>       logcmdutil,
> @@ -106,6 +108,7 @@
>       _setuplog(ui)
>       _setupadd(ui)
>       _setupdirstate(ui)
> +    _setupsubrepo(ui)
>   
>   
>   def replacefilecache(cls, propname, replacement):
> @@ -285,6 +288,52 @@
>   
>           extensions.wrapfunction(dirstate.dirstate, func, _wrapper)
>   
> +class DummySubrepo(subrepo.abstractsubrepo):
> +    """ Dumy subrepo is replacement of subrepo, that should be filterout from sparce.
> +        this subrepo acts as always clean and always get/remove well.
> +    """
> +
> +    def dirty(self, ignoreupdate=False, missing=False):
> +        return False
> +
> +    def get(self, state, overwrite=False):
> +        return
> +
> +    def remove(self):
> +        return
> +
> +
> +
> +def _setupsubrepo(ui):
> +    """Modify the dirstate to prevent stat'ing excluded files,
> +    and to prevent modifications to files outside the checkout.
> +    """
> +
> +    def _state(orig, ctx, ui):
> +        sparsematch = sparse.matcher(ctx.repo(), revs=[ ctx.rev() ])
> +        if not sparsematch.always():
> +            # filter allstate, leave only sparce pathes
> +            allstate = orig(ctx, ui)
> +            sparcestate = dict()
> +            for (idx, item) in allstate.items():
> +                if sparsematch(idx):
> +                    sparcestate[idx] = item
> +            return sparcestate
> +        else:
> +            return orig(ctx, ui)
> +
> +    #extensions.wrapfunction(subrepoutil, b'state', _state)
> +
> +    """ provide DummySubrepo for pathes out of sparse
> +    """
> +    def _subrepo(orig, ctx, path, allowwdir=False, allowcreate=True):
> +        sparsematch = sparse.matcher(ctx.repo(), revs=[ ctx.rev() ])
> +        if not sparsematch.always():
> +            if not sparsematch(path):
> +                return DummySubrepo(ctx, path)
> +        return orig(ctx, path, allowwdir, allowcreate)
> +
> +    extensions.wrapfunction(subrepo, b'subrepo', _subrepo)
>   
>   @command(
>       b'debugsparse',
> diff --git a/mercurial/subrepoutil.py b/mercurial/subrepoutil.py
> --- a/mercurial/subrepoutil.py
> +++ b/mercurial/subrepoutil.py
> @@ -21,6 +21,7 @@
>       pathutil,
>       phases,
>       pycompat,
> +    sparse,
>       util,
>   )
>   from .utils import (
> @@ -183,6 +184,9 @@
>       sa = actx.substate
>       sm = {}
>   
> +    s1match = sparse.matcher(repo, revs=[ wctx.rev() ])
> +    s2match = sparse.matcher(repo, revs=[ mctx.rev() ])
> +
>       repo.ui.debug(b"subrepo merge %s %s %s\n" % (wctx, mctx, actx))
>   
>       def debug(s, msg, r=b""):
> @@ -192,6 +196,9 @@
>   
>       promptssrc = filemerge.partextras(labels)
>       for s, l in sorted(pycompat.iteritems(s1)):
> +        if not s1match(s):
> +            sm[s] = l       # ignore changes out of sparse
> +            continue
>           a = sa.get(s, nullstate)
>           ld = l  # local state with possible dirty flag for compares
>           if wctx.sub(s).dirty():
> @@ -202,6 +209,9 @@
>           prompts = promptssrc.copy()
>           prompts[b's'] = s
>           if s in s2:
> +            if not s2match(s):
> +                sm[s] = l       # ignore changes out of sparse
> +                continue
>               r = s2[s]
>               if ld == r or r == a:  # no change or local is newer
>                   sm[s] = l
> @@ -288,6 +298,14 @@
>               mctx.sub(s).get(r)
>               sm[s] = r
>           elif r != sa[s]:
> +            if not s2match(s):
> +                # ignore changes out of sparse,
> +                continue
> +            elif not s1match(s):
> +                # recreate changes out of sparse,
> +                # sm[s] = r
> +                continue
> +
>               prompts = promptssrc.copy()
>               prompts[b's'] = s
>               if (
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Augie Fackler - May 19, 2021, 2:58 p.m.
Elaborating more: this appears to introduce import cycles caught by running the tests under Python 2.7. I’m not sure why that test is broken on Python 3, but I’ll try to make a note to explore that.

> On May 19, 2021, at 4:29 AM, Raphaël Gomès <raphael.gomes@octobus.net> wrote:
> 
> Hi,
> 
> This patch breaks a few tests in the Heptapod CI [1]. I have removed it from the queue, please feel free to send a second version.
> 
> [1] https://foss.heptapod.net/octobus/mercurial-devel/-/pipelines/22116 <https://foss.heptapod.net/octobus/mercurial-devel/-/pipelines/22116>
> On 5/13/21 7:35 PM, alexrayne wrote:
>> # HG changeset patch
>> # User alexrayne <alexraynepe196@gmail.com> <mailto:alexraynepe196@gmail.com>
>> # Date 1619989845 -10800
>> #      Mon May 03 00:10:45 2021 +0300
>> # Branch stable
>> # Node ID 57d1837724ebe88c276013a621a3de9163bd51f7
>> # Parent  b7e623ac98b6f0d3b4e2f394637ae3f1a2a59711
>> fix sparse:subprepo.subrepo - now provide DummySubrepo for subs out of sparse.
>>         This dummy sub is empty node, always clean and ready to get/remove
>> fix subrepoutil.submerge - now ignores changes for items out of sparce
>> 
>> diff --git a/hgext/sparse.py b/hgext/sparse.py
>> --- a/hgext/sparse.py
>> +++ b/hgext/sparse.py
>> @@ -78,6 +78,8 @@
>>  from mercurial import (
>>      commands,
>>      dirstate,
>> +    subrepoutil,
>> +    subrepo,
>>      error,
>>      extensions,
>>      logcmdutil,
>> @@ -106,6 +108,7 @@
>>      _setuplog(ui)
>>      _setupadd(ui)
>>      _setupdirstate(ui)
>> +    _setupsubrepo(ui)
>>  
>>  
>>  def replacefilecache(cls, propname, replacement):
>> @@ -285,6 +288,52 @@
>>  
>>          extensions.wrapfunction(dirstate.dirstate, func, _wrapper)
>>  
>> +class DummySubrepo(subrepo.abstractsubrepo):
>> +    """ Dumy subrepo is replacement of subrepo, that should be filterout from sparce.
>> +        this subrepo acts as always clean and always get/remove well.
>> +    """
>> +
>> +    def dirty(self, ignoreupdate=False, missing=False):
>> +        return False
>> +    
>> +    def get(self, state, overwrite=False):
>> +        return
>> +
>> +    def remove(self):
>> +        return
>> +    
>> +    
>> +
>> +def _setupsubrepo(ui):
>> +    """Modify the dirstate to prevent stat'ing excluded files,
>> +    and to prevent modifications to files outside the checkout.
>> +    """
>> +    
>> +    def _state(orig, ctx, ui):
>> +        sparsematch = sparse.matcher(ctx.repo(), revs=[ ctx.rev() ])
>> +        if not sparsematch.always():
>> +            # filter allstate, leave only sparce pathes
>> +            allstate = orig(ctx, ui)
>> +            sparcestate = dict()
>> +            for (idx, item) in allstate.items():
>> +                if sparsematch(idx):
>> +                    sparcestate[idx] = item
>> +            return sparcestate
>> +        else:
>> +            return orig(ctx, ui)
>> +    
>> +    #extensions.wrapfunction(subrepoutil, b'state', _state)
>> +    
>> +    """ provide DummySubrepo for pathes out of sparse
>> +    """
>> +    def _subrepo(orig, ctx, path, allowwdir=False, allowcreate=True):
>> +        sparsematch = sparse.matcher(ctx.repo(), revs=[ ctx.rev() ])
>> +        if not sparsematch.always():
>> +            if not sparsematch(path):
>> +                return DummySubrepo(ctx, path)
>> +        return orig(ctx, path, allowwdir, allowcreate)
>> +    
>> +    extensions.wrapfunction(subrepo, b'subrepo', _subrepo)
>>  
>>  @command(
>>      b'debugsparse',
>> diff --git a/mercurial/subrepoutil.py b/mercurial/subrepoutil.py
>> --- a/mercurial/subrepoutil.py
>> +++ b/mercurial/subrepoutil.py
>> @@ -21,6 +21,7 @@
>>      pathutil,
>>      phases,
>>      pycompat,
>> +    sparse,
>>      util,
>>  )
>>  from .utils import (
>> @@ -183,6 +184,9 @@
>>      sa = actx.substate
>>      sm = {}
>>  
>> +    s1match = sparse.matcher(repo, revs=[ wctx.rev() ])
>> +    s2match = sparse.matcher(repo, revs=[ mctx.rev() ])
>> +
>>      repo.ui.debug(b"subrepo merge %s %s %s\n" % (wctx, mctx, actx))
>>  
>>      def debug(s, msg, r=b""):
>> @@ -192,6 +196,9 @@
>>  
>>      promptssrc = filemerge.partextras(labels)
>>      for s, l in sorted(pycompat.iteritems(s1)):
>> +        if not s1match(s):
>> +            sm[s] = l       # ignore changes out of sparse
>> +            continue
>>          a = sa.get(s, nullstate)
>>          ld = l  # local state with possible dirty flag for compares
>>          if wctx.sub(s).dirty():
>> @@ -202,6 +209,9 @@
>>          prompts = promptssrc.copy()
>>          prompts[b's'] = s
>>          if s in s2:
>> +            if not s2match(s):
>> +                sm[s] = l       # ignore changes out of sparse
>> +                continue
>>              r = s2[s]
>>              if ld == r or r == a:  # no change or local is newer
>>                  sm[s] = l
>> @@ -288,6 +298,14 @@
>>              mctx.sub(s).get(r)
>>              sm[s] = r
>>          elif r != sa[s]:
>> +            if not s2match(s):
>> +                # ignore changes out of sparse, 
>> +                continue
>> +            elif not s1match(s):
>> +                # recreate changes out of sparse, 
>> +                # sm[s] = r
>> +                continue
>> +            
>>              prompts = promptssrc.copy()
>>              prompts[b's'] = s
>>              if (
>> 
>> 
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel@mercurial-scm.org <mailto:Mercurial-devel@mercurial-scm.org>
>> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel <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

Patch

# HG changeset patch
# User alexrayne <alexraynepe196@gmail.com>
# Date 1619989845 -10800
#      Mon May 03 00:10:45 2021 +0300
# Branch stable
# Node ID 57d1837724ebe88c276013a621a3de9163bd51f7
# Parent  b7e623ac98b6f0d3b4e2f394637ae3f1a2a59711
fix sparse:subprepo.subrepo - now provide DummySubrepo for subs out of sparse.
        This dummy sub is empty node, always clean and ready to get/remove
fix subrepoutil.submerge - now ignores changes for items out of sparce

diff --git a/hgext/sparse.py b/hgext/sparse.py
--- a/hgext/sparse.py
+++ b/hgext/sparse.py
@@ -78,6 +78,8 @@ 
 from mercurial import (
     commands,
     dirstate,
+    subrepoutil,
+    subrepo,
     error,
     extensions,
     logcmdutil,
@@ -106,6 +108,7 @@ 
     _setuplog(ui)
     _setupadd(ui)
     _setupdirstate(ui)
+    _setupsubrepo(ui)
 
 
 def replacefilecache(cls, propname, replacement):
@@ -285,6 +288,52 @@ 
 
         extensions.wrapfunction(dirstate.dirstate, func, _wrapper)
 
+class DummySubrepo(subrepo.abstractsubrepo):
+    """ Dumy subrepo is replacement of subrepo, that should be filterout from sparce.
+        this subrepo acts as always clean and always get/remove well.
+    """
+
+    def dirty(self, ignoreupdate=False, missing=False):
+        return False
+    
+    def get(self, state, overwrite=False):
+        return
+
+    def remove(self):
+        return
+    
+    
+
+def _setupsubrepo(ui):
+    """Modify the dirstate to prevent stat'ing excluded files,
+    and to prevent modifications to files outside the checkout.
+    """
+    
+    def _state(orig, ctx, ui):
+        sparsematch = sparse.matcher(ctx.repo(), revs=[ ctx.rev() ])
+        if not sparsematch.always():
+            # filter allstate, leave only sparce pathes
+            allstate = orig(ctx, ui)
+            sparcestate = dict()
+            for (idx, item) in allstate.items():
+                if sparsematch(idx):
+                    sparcestate[idx] = item
+            return sparcestate
+        else:
+            return orig(ctx, ui)
+    
+    #extensions.wrapfunction(subrepoutil, b'state', _state)
+    
+    """ provide DummySubrepo for pathes out of sparse
+    """
+    def _subrepo(orig, ctx, path, allowwdir=False, allowcreate=True):
+        sparsematch = sparse.matcher(ctx.repo(), revs=[ ctx.rev() ])
+        if not sparsematch.always():
+            if not sparsematch(path):
+                return DummySubrepo(ctx, path)
+        return orig(ctx, path, allowwdir, allowcreate)
+    
+    extensions.wrapfunction(subrepo, b'subrepo', _subrepo)
 
 @command(
     b'debugsparse',
diff --git a/mercurial/subrepoutil.py b/mercurial/subrepoutil.py
--- a/mercurial/subrepoutil.py
+++ b/mercurial/subrepoutil.py
@@ -21,6 +21,7 @@ 
     pathutil,
     phases,
     pycompat,
+    sparse,
     util,
 )
 from .utils import (
@@ -183,6 +184,9 @@ 
     sa = actx.substate
     sm = {}
 
+    s1match = sparse.matcher(repo, revs=[ wctx.rev() ])
+    s2match = sparse.matcher(repo, revs=[ mctx.rev() ])
+
     repo.ui.debug(b"subrepo merge %s %s %s\n" % (wctx, mctx, actx))
 
     def debug(s, msg, r=b""):
@@ -192,6 +196,9 @@ 
 
     promptssrc = filemerge.partextras(labels)
     for s, l in sorted(pycompat.iteritems(s1)):
+        if not s1match(s):
+            sm[s] = l       # ignore changes out of sparse
+            continue
         a = sa.get(s, nullstate)
         ld = l  # local state with possible dirty flag for compares
         if wctx.sub(s).dirty():
@@ -202,6 +209,9 @@ 
         prompts = promptssrc.copy()
         prompts[b's'] = s
         if s in s2:
+            if not s2match(s):
+                sm[s] = l       # ignore changes out of sparse
+                continue
             r = s2[s]
             if ld == r or r == a:  # no change or local is newer
                 sm[s] = l
@@ -288,6 +298,14 @@ 
             mctx.sub(s).get(r)
             sm[s] = r
         elif r != sa[s]:
+            if not s2match(s):
+                # ignore changes out of sparse, 
+                continue
+            elif not s1match(s):
+                # recreate changes out of sparse, 
+                # sm[s] = r
+                continue
+            
             prompts = promptssrc.copy()
             prompts[b's'] = s
             if (