Patchwork [5,of,5,STABLE] largefiles: synchronize lfdirstate with dirstate after automated committing

login
register
mail settings
Submitter Katsunori FUJIWARA
Date Aug. 11, 2014, 1:39 p.m.
Message ID <fc6348572bf34b53f72d.1407764383@feefifofum>
Download mbox | patch
Permalink /patch/5341/
State Accepted
Headers show

Comments

Katsunori FUJIWARA - Aug. 11, 2014, 1:39 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1407763783 -32400
#      Mon Aug 11 22:29:43 2014 +0900
# Branch stable
# Node ID fc6348572bf34b53f72d70a14c394cb77624641e
# Parent  84bf4aa8363406dc5da25d9a7819a66acb1e259c
largefiles: synchronize lfdirstate with dirstate after automated committing

Before this patch, after successful "hg rebase" of the revision
removing largefiles, "hg status" may still show ""R" for such
largefiles unexpectedly.

"lfilesrepo.commit" executes the special code path for automated
committing while rebase/transplant, and lfdirstate entries for removed
files aren't updated in this code path, even after successful
committing.

Then, "R" entries still existing in lfdirstate cause unexpected "hg
status" output.

This patch synchronizes lfdirstate with dirstate after automated
committing.

This patch passes False as "normallookup" to "synclfdirstate", because
modified files in "files()" of the recent (= just committed) context
should be "normal"-ed.

This is a temporary way to fix with less changes. For fundamental
resolution of this kind of problems in the future, lfdirstate should
be updated with dirstate simultaneously. Hooking "markcommitted" of
ctx in "localrepository.commitctx" may achieve this.

This problem occurs, only when (1) the parent of the working directory
is rebased and (2) it removes largefiles, because:

  - if the parent of the working directory isn't rebased, returning to
    the initial revision (= update) after rebase hides this problem

  - files added on "other" branch (= rebase target) are treated not as
    "added" but as "modified" (= "normal" status and "unset"
    timestamp) at merging

This patch tests also the status of added largefile, but it is only
for avoiding regression.

In addition to conditions above, "hg status" must not take existing
files to reproduce this problem, because existing files make
"match._files" not empty in "lfilesrepo.status" code path below:

    def sfindirstate(f):
        sf = lfutil.standin(f)
        dirstate = self.dirstate
        return sf in dirstate or sf in dirstate.dirs()

    match._files = [f for f in match._files
                    if sfindirstate(f)]

Not empty "match._files" prevents "status" on lfdirstate from
returning the result containing problematic "R" files.

This is reason why "large1" (removed) and "largeX" (added) are checked
separately in this patch.

Problematic code path in "lfilesrepo.commit" is used also by "hg
transplant", but this problem doesn't occur at "hg transplant",
because invocation of "updatelfiles" after transplant-ing in
"overridetransplant" causes cleaning lfdirstate up.

This patch tests also "hg transplant" as same as "hg rebase", but it
is only for avoiding regression.
Matt Mackall - Aug. 11, 2014, 2:57 p.m.
On Mon, 2014-08-11 at 22:39 +0900, FUJIWARA Katsunori wrote:
> # HG changeset patch
> # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> # Date 1407763783 -32400
> #      Mon Aug 11 22:29:43 2014 +0900
> # Branch stable
> # Node ID fc6348572bf34b53f72d70a14c394cb77624641e
> # Parent  84bf4aa8363406dc5da25d9a7819a66acb1e259c
> largefiles: synchronize lfdirstate with dirstate after automated committing

These are queued for default, thanks. contrib/check-commit says hi.
Katsunori FUJIWARA - Aug. 12, 2014, 3:16 p.m.
At Mon, 11 Aug 2014 09:57:19 -0500,
Matt Mackall wrote:
> 
> On Mon, 2014-08-11 at 22:39 +0900, FUJIWARA Katsunori wrote:
> > # HG changeset patch
> > # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> > # Date 1407763783 -32400
> > #      Mon Aug 11 22:29:43 2014 +0900
> > # Branch stable
> > # Node ID fc6348572bf34b53f72d70a14c394cb77624641e
> > # Parent  84bf4aa8363406dc5da25d9a7819a66acb1e259c
> > largefiles: synchronize lfdirstate with dirstate after automated committing
> 
> These are queued for default, thanks. contrib/check-commit says hi.

Oops ! sorry for forgetting verification by contrib/check-commit.

Now, I set it up as "pre-email" hook, and it will say nothing on
posted my patches :-)

----------------------------------------------------------------------
[FUJIWARA Katsunori]                             foozy@lares.dti.ne.jp

Patch

diff --git a/hgext/largefiles/reposetup.py b/hgext/largefiles/reposetup.py
--- a/hgext/largefiles/reposetup.py
+++ b/hgext/largefiles/reposetup.py
@@ -285,6 +285,16 @@ 
                                             printmessage=False)
                     result = orig(text=text, user=user, date=date, match=match,
                                     force=force, editor=editor, extra=extra)
+
+                    if result:
+                        lfdirstate = lfutil.openlfdirstate(ui, self)
+                        for f in self[result].files():
+                            if lfutil.isstandin(f):
+                                lfile = lfutil.splitstandin(f)
+                                lfutil.synclfdirstate(self, lfdirstate, lfile,
+                                                      False)
+                        lfdirstate.write()
+
                     return result
                 # Case 1: user calls commit with no specific files or
                 # include/exclude patterns: refresh and commit all files that
diff --git a/tests/test-largefiles-update.t b/tests/test-largefiles-update.t
--- a/tests/test-largefiles-update.t
+++ b/tests/test-largefiles-update.t
@@ -129,4 +129,42 @@ 
   $ hg status -A largeY
   ? largeY
 
+Test that "hg status" shows status of largefiles correctly just after
+automated commit like rebase/transplant
+
+  $ cat >> .hg/hgrc <<EOF
+  > [extensions]
+  > rebase =
+  > strip =
+  > transplant =
+  > EOF
+  $ hg update -q -C 1
+  $ hg remove large1
+  $ echo largeX > largeX
+  $ hg add --large largeX
+  $ hg commit -m '#4'
+
+  $ hg rebase -s 1 -d 2 --keep
+  $ hg status -A large1
+  large1: No such file or directory
+  $ hg status -A largeX
+  C largeX
+  $ hg strip -q 5
+
+  $ hg update -q -C 2
+  $ hg transplant -q 1 4
+  $ hg status -A large1
+  large1: No such file or directory
+  $ hg status -A largeX
+  C largeX
+  $ hg strip -q 5
+
+  $ hg update -q -C 2
+  $ hg transplant -q --merge 1 --merge 4
+  $ hg status -A large1
+  large1: No such file or directory
+  $ hg status -A largeX
+  C largeX
+  $ hg strip -q 5
+
   $ cd ..