Patchwork [v2] update: teach hg to override untracked dir with a tracked file on update

login
register
mail settings
Submitter Kostia Balytskyi
Date June 30, 2016, 9:51 p.m.
Message ID <51c1f0ae6dc4855e213b.1467323467@dev1902.lla1.facebook.com>
Download mbox | patch
Permalink /patch/15667/
State Changes Requested
Headers show

Comments

Kostia Balytskyi - June 30, 2016, 9:51 p.m.
# HG changeset patch
# User Kostia Balytskyi <ikostia@fb.com>
# Date 1467323089 25200
#      Thu Jun 30 14:44:49 2016 -0700
# Node ID 51c1f0ae6dc4855e213b7ce49acc8010d5505a3f
# Parent  33a6b750b5b9e0cc193ae0103420dc80af074352
update: teach hg to override untracked dir with a tracked file on update

This is a fix to an old problem when Mercurial got confused by an
untracked folder with the same name as one of the files in a commit
hg was trying to update to. It is pretty safe to remove this folder if
it is empty. Backing up an empty folder seems to go agains Mercurial's
"don't track dirs" philosophy.

Let me know if I am wrong about the above assumption please.
Kostia Balytskyi - July 1, 2016, 12:06 p.m.
Sorry for two emails, I wasn’t sure whether I had a problem with patchbomp configuration. Aslo, I did not notice the “agains”-related comment by timeless at first, so if you’re going to accept this, please fix in-flight agains->against.

On 6/30/16, 11:51 PM, "Mercurial-devel on behalf of Kostia Balytskyi" <mercurial-devel-bounces@mercurial-scm.org on behalf of ikostia@fb.com> wrote:

># HG changeset patch

># User Kostia Balytskyi <ikostia@fb.com>

># Date 1467323089 25200

>#      Thu Jun 30 14:44:49 2016 -0700

># Node ID 51c1f0ae6dc4855e213b7ce49acc8010d5505a3f

># Parent  33a6b750b5b9e0cc193ae0103420dc80af074352

>update: teach hg to override untracked dir with a tracked file on update

>

>This is a fix to an old problem when Mercurial got confused by an

>untracked folder with the same name as one of the files in a commit

>hg was trying to update to. It is pretty safe to remove this folder if

>it is empty. Backing up an empty folder seems to go agains Mercurial's

>"don't track dirs" philosophy.

>

>Let me know if I am wrong about the above assumption please.

>

>diff --git a/mercurial/merge.py b/mercurial/merge.py

>--- a/mercurial/merge.py

>+++ b/mercurial/merge.py

>@@ -1076,15 +1076,14 @@ def batchget(repo, mctx, actions):

>                 absf = repo.wjoin(f)

>                 orig = scmutil.origpath(ui, repo, absf)

>                 try:

>-                    # TODO Mercurial has always aborted if an untracked

>-                    # directory is replaced by a tracked file, or generally

>-                    # with file/directory merges. This needs to be sorted out.

>                     if repo.wvfs.isfileorlink(f):

>                         util.rename(absf, orig)

>                 except OSError as e:

>                     if e.errno != errno.ENOENT:

>                         raise

> 

>+            if repo.wvfs.isdir(f):

>+                repo.wvfs.removedirs(f)

>             wwrite(f, fctx(f).data(), flags, backgroundclose=True)

>             if i == 100:

>                 yield i, f

>diff --git a/tests/test-merge1.t b/tests/test-merge1.t

>--- a/tests/test-merge1.t

>+++ b/tests/test-merge1.t

>@@ -26,10 +26,7 @@

> 

> Test interrupted updates by exploiting our non-handling of directory collisions

> 

>-  $ mkdir b

>-  $ hg up

>-  abort: *: '$TESTTMP/t/b' (glob)

>-  [255]

>+  $ echo somethingsomething > .hg/updatestate

>   $ hg ci

>   abort: last update was interrupted

>   (use 'hg update' to get a consistent checkout)

>@@ -41,7 +38,7 @@ Test interrupted updates by exploiting o

>   commit: (interrupted update)

>   update: 1 new changesets (update)

>   phases: 2 draft

>-  $ rmdir b

>+  $ rm .hg/updatestate

>   $ hg up

>   1 files updated, 0 files merged, 0 files removed, 0 files unresolved

>   $ hg sum

>diff --git a/tests/test-update-renames.t b/tests/test-update-names.t

>rename from tests/test-update-renames.t

>rename to tests/test-update-names.t

>--- a/tests/test-update-renames.t

>+++ b/tests/test-update-names.t

>@@ -1,8 +1,9 @@

>-Test update logic when there are renames

>+Test update logic when there are renames or weird same-name cases between dirs

>+and files

> 

> Update with local changes across a file rename

> 

>-  $ hg init

>+  $ hg init r1 && cd r1

> 

>   $ echo a > a

>   $ hg add a

>@@ -24,3 +25,31 @@ Update with local changes across a file 

>   0 files updated, 0 files merged, 0 files removed, 1 files unresolved

>   use 'hg resolve' to retry unresolved file merges

>   [1]

>+

>+Test update when local untracked directory exists with the same name as a

>+tracked file in a commit we are updating to

>+  $ hg init r2 && cd r2

>+  $ echo root > root && hg ci -Am root  # rev 0

>+  adding root

>+  $ echo text > name && hg ci -Am "name is a file"  # rev 1

>+  adding name

>+  $ hg up 0

>+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved

>+  $ mkdir name

>+  $ hg up 1

>+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved

>+

>+Test update when local untracked directory exists with some files in it and has

>+the same name a tracked file in a commit we are updating to. In future this

>+should be updated to give an friendlier error message, but now we should just

>+make sure that this does not erase untracked data

>+  $ hg up 0

>+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved

>+  $ mkdir name

>+  $ echo text > name/file

>+  $ hg st

>+  ? name/file

>+  $ hg up 1

>+  abort: Directory not empty: '$TESTTMP/r1/r2/name'

>+  [255]

>+  $ cd ..

>_______________________________________________

>Mercurial-devel mailing list

>Mercurial-devel@mercurial-scm.org

>https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=CwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Pp-gQYFgs4tKlSFPF5kfCw&m=cW-pM3joq-4g86Su1YmqxcYHAszk9Nh9fZfsg-FK7ws&s=Sv90sHaM4l2hPlDp7HF88vWlBC04XHRb0bb7msj21B4&e=
Yuya Nishihara - July 1, 2016, 2:19 p.m.
On Thu, 30 Jun 2016 14:51:07 -0700, Kostia Balytskyi wrote:
> # HG changeset patch
> # User Kostia Balytskyi <ikostia@fb.com>
> # Date 1467323089 25200
> #      Thu Jun 30 14:44:49 2016 -0700
> # Node ID 51c1f0ae6dc4855e213b7ce49acc8010d5505a3f
> # Parent  33a6b750b5b9e0cc193ae0103420dc80af074352
> update: teach hg to override untracked dir with a tracked file on update

> +++ b/tests/test-merge1.t
> @@ -26,10 +26,7 @@
>  
>  Test interrupted updates by exploiting our non-handling of directory collisions
>  
> -  $ mkdir b
> -  $ hg up
> -  abort: *: '$TESTTMP/t/b' (glob)
> -  [255]
> +  $ echo somethingsomething > .hg/updatestate

It doesn't agree with the comment above, and I slightly prefer making a real
interrupted update instead of mocking the .hg directory. It could be

  $ touch b/nonempty
timeless - July 6, 2016, 11:07 p.m.
Kostia Balytskyi wrote:
> update: teach hg to override untracked dir with a tracked file on update

Not sure what the status of this is, but do you mean `overwrite`?

Patch

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -1076,15 +1076,14 @@  def batchget(repo, mctx, actions):
                 absf = repo.wjoin(f)
                 orig = scmutil.origpath(ui, repo, absf)
                 try:
-                    # TODO Mercurial has always aborted if an untracked
-                    # directory is replaced by a tracked file, or generally
-                    # with file/directory merges. This needs to be sorted out.
                     if repo.wvfs.isfileorlink(f):
                         util.rename(absf, orig)
                 except OSError as e:
                     if e.errno != errno.ENOENT:
                         raise
 
+            if repo.wvfs.isdir(f):
+                repo.wvfs.removedirs(f)
             wwrite(f, fctx(f).data(), flags, backgroundclose=True)
             if i == 100:
                 yield i, f
diff --git a/tests/test-merge1.t b/tests/test-merge1.t
--- a/tests/test-merge1.t
+++ b/tests/test-merge1.t
@@ -26,10 +26,7 @@ 
 
 Test interrupted updates by exploiting our non-handling of directory collisions
 
-  $ mkdir b
-  $ hg up
-  abort: *: '$TESTTMP/t/b' (glob)
-  [255]
+  $ echo somethingsomething > .hg/updatestate
   $ hg ci
   abort: last update was interrupted
   (use 'hg update' to get a consistent checkout)
@@ -41,7 +38,7 @@  Test interrupted updates by exploiting o
   commit: (interrupted update)
   update: 1 new changesets (update)
   phases: 2 draft
-  $ rmdir b
+  $ rm .hg/updatestate
   $ hg up
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg sum
diff --git a/tests/test-update-renames.t b/tests/test-update-names.t
rename from tests/test-update-renames.t
rename to tests/test-update-names.t
--- a/tests/test-update-renames.t
+++ b/tests/test-update-names.t
@@ -1,8 +1,9 @@ 
-Test update logic when there are renames
+Test update logic when there are renames or weird same-name cases between dirs
+and files
 
 Update with local changes across a file rename
 
-  $ hg init
+  $ hg init r1 && cd r1
 
   $ echo a > a
   $ hg add a
@@ -24,3 +25,31 @@  Update with local changes across a file 
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
   use 'hg resolve' to retry unresolved file merges
   [1]
+
+Test update when local untracked directory exists with the same name as a
+tracked file in a commit we are updating to
+  $ hg init r2 && cd r2
+  $ echo root > root && hg ci -Am root  # rev 0
+  adding root
+  $ echo text > name && hg ci -Am "name is a file"  # rev 1
+  adding name
+  $ hg up 0
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkdir name
+  $ hg up 1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Test update when local untracked directory exists with some files in it and has
+the same name a tracked file in a commit we are updating to. In future this
+should be updated to give an friendlier error message, but now we should just
+make sure that this does not erase untracked data
+  $ hg up 0
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkdir name
+  $ echo text > name/file
+  $ hg st
+  ? name/file
+  $ hg up 1
+  abort: Directory not empty: '$TESTTMP/r1/r2/name'
+  [255]
+  $ cd ..