Patchwork [stable] add: add back forgotten files even when not matching exactly

login
register
mail settings
Submitter Martin von Zweigbergk
Date Nov. 10, 2014, 11:18 p.m.
Message ID <eaf1154e17256fb20ce3.1415661512@martinvonz.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/6672/
State Superseded
Headers show

Comments

Martin von Zweigbergk - Nov. 10, 2014, 11:18 p.m.
# HG changeset patch
# User Martin von Zweigbergk <martinvonz@google.com>
# Date 1415659878 28800
#      Mon Nov 10 14:51:18 2014 -0800
# Node ID eaf1154e17256fb20ce3ef7989ea849904e4c8b2
# Parent  2d54aa5397cdb1c697673ba10b7618d5ac25c69e
add: add back forgotten files even when not matching exactly

The output from the following two invocations should be the same, but
it's not.

  $ hg forget README && hg add README && hg status -A README
  C README
  $ hg forget README && hg add . && hg status -A README
  R README

The problem lies in cmdutil.add(). That method checks that the file
isn't already tracked before adding it, but it does so by checking the
dirstate, which does have an entry for forgotten files (state 'r'). We
should instead be checking whether the file exists in the
workingctx. The workingctx is also what we later call add() on, and
that method takes care of transforming the add() into a normallookup()
on the dirstate.

Since we're changing repo.dirstate into wctx, let's also change
repo.walk into wctx.walk for consistency (repo.walk calls wctx.walk,
so we're simply inlining the call).
Augie Fackler - Nov. 11, 2014, 2:17 p.m.
On Mon, Nov 10, 2014 at 03:18:32PM -0800, Martin von Zweigbergk wrote:
> # HG changeset patch
> # User Martin von Zweigbergk <martinvonz@google.com>
> # Date 1415659878 28800
> #      Mon Nov 10 14:51:18 2014 -0800
> # Node ID eaf1154e17256fb20ce3ef7989ea849904e4c8b2
> # Parent  2d54aa5397cdb1c697673ba10b7618d5ac25c69e
> add: add back forgotten files even when not matching exactly

This looks reasonable to me.

>
> The output from the following two invocations should be the same, but
> it's not.
>
>   $ hg forget README && hg add README && hg status -A README
>   C README
>   $ hg forget README && hg add . && hg status -A README
>   R README

I assume the intent is that the latter case will look like the former
after this change?

>
> The problem lies in cmdutil.add(). That method checks that the file
> isn't already tracked before adding it, but it does so by checking the
> dirstate, which does have an entry for forgotten files (state 'r'). We
> should instead be checking whether the file exists in the
> workingctx. The workingctx is also what we later call add() on, and
> that method takes care of transforming the add() into a normallookup()
> on the dirstate.
>
> Since we're changing repo.dirstate into wctx, let's also change
> repo.walk into wctx.walk for consistency (repo.walk calls wctx.walk,
> so we're simply inlining the call).
>
> diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
> --- a/mercurial/cmdutil.py
> +++ b/mercurial/cmdutil.py
> @@ -1982,9 +1982,9 @@
>      abort, warn = scmutil.checkportabilityalert(ui)
>      if abort or warn:
>          cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
> -    for f in repo.walk(match):
> +    for f in wctx.walk(match):
>          exact = match.exact(f)
> -        if exact or not explicitonly and f not in repo.dirstate:
> +        if exact or not explicitonly and f not in wctx:
>              if cca:
>                  cca(f)
>              names.append(f)
> diff --git a/tests/test-add.t b/tests/test-add.t
> --- a/tests/test-add.t
> +++ b/tests/test-add.t
> @@ -126,6 +126,19 @@
>    M a
>    ? a.orig
>
> +Forgotten file can be added back (as either clean or modified)
> +
> +  $ hg forget b
> +  $ hg add b
> +  $ hg st -A b
> +  C b
> +  $ hg forget b
> +  $ echo modified > b
> +  $ hg add b
> +  $ hg st -A b
> +  M b
> +  $ hg revert -qC b
> +
>    $ hg add c && echo "unexpected addition of missing file"
>    c: * (glob)
>    [1]
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Martin von Zweigbergk - Nov. 11, 2014, 3:42 p.m.
On Tue, Nov 11, 2014, 06:17 Augie Fackler <raf@durin42.com> wrote:

On Mon, Nov 10, 2014 at 03:18:32PM -0800, Martin von Zweigbergk wrote:
> # HG changeset patch
> # User Martin von Zweigbergk <martinvonz@google.com>
> # Date 1415659878 28800
> #      Mon Nov 10 14:51:18 2014 -0800
> # Node ID eaf1154e17256fb20ce3ef7989ea849904e4c8b2
> # Parent  2d54aa5397cdb1c697673ba10b7618d5ac25c69e
> add: add back forgotten files even when not matching exactly

This looks reasonable to me.

>
> The output from the following two invocations should be the same, but
> it's not.
>
>   $ hg forget README && hg add README && hg status -A README
>   C README
>   $ hg forget README && hg add . && hg status -A README
>   R README

I assume the intent is that the latter case will look like the former
after this change?



 Right. It should be clear with the subject line fresh in mind, but I
should have said it explicitly. I'll make it clearer and resend. I might
also include the use case that made me find this bug (accidental use of "hg
forget .").

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1982,9 +1982,9 @@ 
     abort, warn = scmutil.checkportabilityalert(ui)
     if abort or warn:
         cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
-    for f in repo.walk(match):
+    for f in wctx.walk(match):
         exact = match.exact(f)
-        if exact or not explicitonly and f not in repo.dirstate:
+        if exact or not explicitonly and f not in wctx:
             if cca:
                 cca(f)
             names.append(f)
diff --git a/tests/test-add.t b/tests/test-add.t
--- a/tests/test-add.t
+++ b/tests/test-add.t
@@ -126,6 +126,19 @@ 
   M a
   ? a.orig
 
+Forgotten file can be added back (as either clean or modified)
+
+  $ hg forget b
+  $ hg add b
+  $ hg st -A b
+  C b
+  $ hg forget b
+  $ echo modified > b
+  $ hg add b
+  $ hg st -A b
+  M b
+  $ hg revert -qC b
+
   $ hg add c && echo "unexpected addition of missing file"
   c: * (glob)
   [1]