Patchwork [3,of,3] revset: two new revsets, copies and renames

login
register
mail settings
Submitter Jordi Gutiérrez Hermoso
Date April 5, 2019, 6:42 p.m.
Message ID <cf6a3da4082569df7b5d.1554489759@chloe>
Download mbox | patch
Permalink /patch/39514/
State Accepted
Headers show

Comments

Jordi Gutiérrez Hermoso - April 5, 2019, 6:42 p.m.
# HG changeset patch
# User Jordi Gutiérrez Hermoso <jordigh@octave.org>
# Date 1554489566 14400
#      Fri Apr 05 14:39:26 2019 -0400
# Node ID cf6a3da4082569df7b5dd83ab61fcbedc70839f1
# Parent  4baa10f1f44a8e427f49fa4f4d8d29552c2a1a65
revset: two new revsets, copies and renames
Yuya Nishihara - April 7, 2019, 12:48 a.m.
On Fri, 05 Apr 2019 14:42:39 -0400, Jordi Gutiérrez Hermoso wrote:
> # HG changeset patch
> # User Jordi Gutiérrez Hermoso <jordigh@octave.org>
> # Date 1554489566 14400
> #      Fri Apr 05 14:39:26 2019 -0400
> # Node ID cf6a3da4082569df7b5dd83ab61fcbedc70839f1
> # Parent  4baa10f1f44a8e427f49fa4f4d8d29552c2a1a65
> revset: two new revsets, copies and renames
> 
> diff --git a/mercurial/revset.py b/mercurial/revset.py
> --- a/mercurial/revset.py
> +++ b/mercurial/revset.py
> @@ -757,6 +757,21 @@ def converted(repo, subset, x):
>      return subset.filter(lambda r: _matchvalue(r),
>                           condrepr=('<converted %r>', rev))
>  
> +@predicate('copies(pattern)', safe=True, weight=30)
> +def copies(repo, subset, x):
> +    """Changesets which added files matching pattern via copying. This
> +    excludes renames, which are copies where the original file was
> +    removed.
> +
> +    The pattern without explicit kind like ``glob:`` is expected to be
> +    relative to the current directory and match against a file or a
> +    directory.
> +
> +    """
> +    # i18n: "removes" is a keyword
> +    pat = getstring(x, _("copies requires a pattern"))
> +    return checkstatus(repo, subset, pat, 3)
> +
>  @predicate('date(interval)', safe=True, weight=10)
>  def date(repo, subset, x):
>      """Changesets within the interval, see :hg:`help dates`.
> @@ -1802,6 +1817,18 @@ def public(repo, subset, x):
>      getargs(x, 0, 0, _("public takes no arguments"))
>      return _phase(repo, subset, phases.public)
>  
> +@predicate('renames(pattern)', safe=True, weight=30)
> +def renames(repo, subset, x):
> +    """Changesets which added files matching pattern via a rename.
> +
> +    The pattern without explicit kind like ``glob:`` is expected to be
> +    relative to the current directory and match against a file or a
> +    directory.
> +    """
> +    # i18n: "removes" is a keyword
> +    pat = getstring(x, _("renames requires a pattern"))
> +    return checkstatus(repo, subset, pat, 4)

So they are quite similar to -r 'file("set:copied()")', and we do include
renames in copies in general.

I think these predicates are useful, but it's confusing to handle copies
and renames separately only in revset.
Jordi Gutiérrez Hermoso - April 8, 2019, 12:39 a.m.
On Sun, 2019-04-07 at 09:48 +0900, Yuya Nishihara wrote:
> So they are quite similar to -r 'file("set:copied()")', and we do include
> renames in copies in general.

Hm, but we don't have a renamed() fileset, do we? How do you find renames?

> I think these predicates are useful, but it's confusing to handle copies
> and renames separately only in revset.

I agree, consistency is important, but I don't know how to implement a
fileset or revset for finding renames.
via Mercurial-devel - April 8, 2019, 5:10 p.m.
On Sun, Apr 7, 2019 at 5:50 PM Jordi Gutiérrez Hermoso <jordigh@octave.org>
wrote:

> On Sun, 2019-04-07 at 09:48 +0900, Yuya Nishihara wrote:
> > So they are quite similar to -r 'file("set:copied()")', and we do include
> > renames in copies in general.
>
> Hm, but we don't have a renamed() fileset, do we? How do you find renames?
>

Yes, I don't think there is one.


>
> > I think these predicates are useful, but it's confusing to handle copies
> > and renames separately only in revset.
>
> I agree, consistency is important, but I don't know how to implement a
> fileset or revset for finding renames.
>

Hmm, this patch has a revset for finding renames... :)

Anyway, I agree with Yuya that it will be confusing if the copied() fileset
includes copies and the copies() revset doesn't. Perhaps we can add
arguments to both of them? Something like
copied(renames=True,purecopies=True)? I don't think you need to implement
such support for the copied() fileset, but I'd like to have a plan for how
to eventually make them consistent.

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -757,6 +757,21 @@  def converted(repo, subset, x):
     return subset.filter(lambda r: _matchvalue(r),
                          condrepr=('<converted %r>', rev))
 
+@predicate('copies(pattern)', safe=True, weight=30)
+def copies(repo, subset, x):
+    """Changesets which added files matching pattern via copying. This
+    excludes renames, which are copies where the original file was
+    removed.
+
+    The pattern without explicit kind like ``glob:`` is expected to be
+    relative to the current directory and match against a file or a
+    directory.
+
+    """
+    # i18n: "removes" is a keyword
+    pat = getstring(x, _("copies requires a pattern"))
+    return checkstatus(repo, subset, pat, 3)
+
 @predicate('date(interval)', safe=True, weight=10)
 def date(repo, subset, x):
     """Changesets within the interval, see :hg:`help dates`.
@@ -1802,6 +1817,18 @@  def public(repo, subset, x):
     getargs(x, 0, 0, _("public takes no arguments"))
     return _phase(repo, subset, phases.public)
 
+@predicate('renames(pattern)', safe=True, weight=30)
+def renames(repo, subset, x):
+    """Changesets which added files matching pattern via a rename.
+
+    The pattern without explicit kind like ``glob:`` is expected to be
+    relative to the current directory and match against a file or a
+    directory.
+    """
+    # i18n: "removes" is a keyword
+    pat = getstring(x, _("renames requires a pattern"))
+    return checkstatus(repo, subset, pat, 4)
+
 @predicate('remote([id [,path]])', safe=False)
 def remote(repo, subset, x):
     """Local revision that corresponds to the given identifier in a
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -3038,3 +3038,15 @@  abort if the revset doesn't expect given
   $ log 'expectsize(0:2, :2)'
   abort: revset size mismatch. expected between 0 and 2, got 3!
   [255]
+
+test copies and renames
+
+  $ hg cp b c
+  $ hg ci -m copy
+  $ hg mv c d
+  $ hg ci -m rename
+  $ hg log -r 'copies("**")' -T '{rev}:{desc}\n'
+  10:copy
+  $ hg log -r 'renames("**")' -T '{rev}:{desc}\n'
+  11:rename
+