Bug 3511 - hg merge aborts with bogus 'path contains illegal component: /foo'
Summary: hg merge aborts with bogus 'path contains illegal component: /foo'
Status: RESOLVED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: Mercurial (show other bugs)
Version: earlier
Hardware: PC Other
: normal bug
Assignee: Bugzilla
URL:
Keywords:
: 3523 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-06-22 16:56 UTC by Jonathan Adams
Modified: 2017-11-01 18:12 UTC (History)
9 users (show)

See Also:
Python Version: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Adams 2012-06-22 16:56 UTC
After upgrading from 1.8.4 to 2.2.1, I started seeing:

% hg merge
 local changed usr/src/uts/sun4/os/memnode.c which remote deleted
use (c)hanged version or (d)elete? c
abort: path contains illegal component: /foo.c
% echo $?
255

where "foo.c" was a file that had been added in one of the two heads.  The
merge is quite complicated, because it has both the entire history of
a multi-year project, as well as the re-based "final push" version on one side,
and then a month or two of continued development on the other.

1.8.4 was able to do the merge with no complaints.

I was able to write a 'hg bisect' script, which:

        blows away the "prefix" dir
        builds and installs hg into 'prefix',
        runs the merge using the built hg on my workspace, records $?,
        does a 'make clean', and
        exiting 1 IFF the merge exited w/ 255

Bisecting from 2.0 (good) to the tip (bad) led to:

--- cut here ---
% hg bisect -b tip
% hg update 2.0
455 files updated, 0 files merged, 29 files removed, 0 files unresolved
% ./run_test.sh; echo $?
0
% hg bisect -g
Testing changeset 16030:308406677e9d (1262 changesets remaining, ~10 tests)
358 files updated, 0 files merged, 2 files removed, 0 files unresolved
% hg bisect -c ./run_test.sh
Changeset 16030:308406677e9d: good
Changeset 16364:48692b416fbc: bad
Changeset 16187:b9bd95e61b49: good
Changeset 16290:6863caf01daa: bad
Changeset 16251:6f236c8bdc01: good
Changeset 16270:e04cc21b01b2: good
Changeset 16280:db75321c7a0e: good
Changeset 16285:828fe2ca7cbb: bad
Changeset 16282:0a73c4bd9f47: good
Changeset 16283:0bb0b9f22cd7: good
Changeset 16284:b8c1a8a57540: good
The first bad revision is:
changeset:   16285:828fe2ca7cbb
user:        Matt Mackall <mpm@selenic.com>
date:        Sun Feb 26 16:45:59 2012 -0600
summary:     copies: use ctx.dirs() for directory rename detection

%
--- cut here ---

Given that, I tried doing:

--- cut here ---
% hg update -C tip
251 files updated, 0 files merged, 3 files removed, 0 files unresolved
% hg backout -r 16285
reverting mercurial/copies.py
251 files updated, 0 files merged, 3 files removed, 0 files unresolved
% ./run_test.sh; echo $?
0
%
--- cut here ---

so backing out that changeset allowed the merge to proceed without aborting.
Comment 1 Jonathan Adams 2012-06-22 16:58 UTC
(this was all run on a development version of Solaris)
Comment 2 Jonathan Adams 2012-06-22 17:00 UTC
To be clear, /foo.c doesn't exist in the workspace, but one of the heads
introduced a file:

usr/src/uts/common/vm/foo.c

and "foo.c" doesn't exist anywhere else in the source base.
Comment 3 kiilerix 2012-06-23 11:21 UTC
Is the repository public? Can you describe how to reproduce the problem?
Comment 4 Jonathan Adams 2012-06-25 13:45 UTC
Unfortunately, the repository is private. 

I'm trying to create a reproducible test case I can hand over, but I may not have the time to do so until next week; the simple cases I put together failed to tickle the bug. 

I'm going to try generating the sequence of renames, updates, and deletions in the existing repository with all of the content removed, and see if that works.
Comment 5 Jonathan Adams 2012-06-25 18:08 UTC
Alternatively, if there is some debugging mode I could turn on, I'd be happy to provide the output from it.
Comment 6 Matt Mackall 2012-06-25 19:13 UTC
Well, there's always --debug.
Comment 7 Jonathan Adams 2012-06-27 14:14 UTC
Looking at the --debug output, the problem appears to be here:

  searching for copies back to rev 17621
  unmatched files in local:
   README.decage-gate
   TODO
   usr/src/uts/common/vm/kmw.h
   usr/src/uts/common/vm/kmw_api.c
   usr/src/uts/common/vm/kmw_impl.c
...
  unmatched files in other:
...
   usr/src/uts/common/vm/mempm_active.c
   usr/src/uts/common/vm/mempm_active.h
   usr/src/uts/common/vm/page_lock_impl.h
...
  all copies found (* = to merge, ! = divergent):
...
   TODO -> usr/src/uts/common/vm/TODO 
...
  checking for directory renames
  dir usr/src/cmd/sgs/tools/common/ -> usr/src/cmd/sgs/common/
  dir usr/src/cmd/sgs/tools/i386/ -> usr/src/cmd/sgs/tools/sgsmsg/i386/
  dir usr/src/cmd/sgs/tools/sparc/ -> usr/src/cmd/sgs/tools/sgsmsg/sparc/
  dir usr/src/uts/common/vm/ -> /
  file usr/src/uts/common/vm/kmw.h -> /kmw.h
  file usr/src/uts/common/vm/kmw_api.c -> /kmw_api.c
  file usr/src/uts/common/vm/kmw_impl.c -> /kmw_impl.c
  file usr/src/uts/common/vm/mempm_active.c -> /mempm_active.c
  file usr/src/uts/common/vm/mempm_active.h -> /mempm_active.h
  file usr/src/uts/common/vm/page_lock_impl.h -> /page_lock_impl.h
...
removing usr/src/uts/intel/ecc/Makefile.32
updating:None 370/3720 files (9.95%)
getting usr/src/uts/common/vm/mempm_active.c to /mempm_active.c
abort: path contains illegal component: /mempm_active.c

I'm guessing that the TODO -> usr/src/uts/common/vm/TODO re-name was 
somehow interpreted wrongly as a directory rename, which is causing this issue.  I'll continue to try to get a simple example of this.
Comment 8 Matt Mackall 2012-06-27 14:43 UTC
Looks like the issue here is that the new code doesn't consider '' (ie the repository root) to be a directory, and thus gets confused. Try this patch:

diff -r 1cf8fe170085 mercurial/context.py
--- a/mercurial/context.py	Mon Jun 25 15:14:05 2012 -0700
+++ b/mercurial/context.py	Wed Jun 27 13:39:44 2012 -0500
@@ -1054,7 +1054,7 @@
                 wlock.release()
 
     def dirs(self):
-        return self._repo.dirstate.dirs()
+        return set(self._repo.dirstate.dirs())
 
 class workingfilectx(filectx):
     """A workingfilectx object makes access to data related to a particular
diff -r 1cf8fe170085 mercurial/copies.py
--- a/mercurial/copies.py	Mon Jun 25 15:14:05 2012 -0700
+++ b/mercurial/copies.py	Wed Jun 27 13:39:44 2012 -0500
@@ -321,7 +321,9 @@
 
     # generate a directory move map
     d1, d2 = c1.dirs(), c2.dirs()
-    invalid = set([""])
+    d1.add('')
+    d2.add('')
+    invalid = set()
     dirmove = {}
 
     # examine each file copy for a potential directory move, which is


Still need a test case though.
Comment 9 Jonathan Adams 2012-06-27 14:52 UTC
I'm still working on an example, but I can verify that this patch allows me to successfully merge.  Post-patch, the renames list is:

  checking for directory renames
  dir usr/src/cmd/sgs/tools/common/ -> usr/src/cmd/sgs/common/
  dir usr/src/cmd/sgs/tools/i386/ -> usr/src/cmd/sgs/tools/sgsmsg/i386/
  dir usr/src/cmd/sgs/tools/sparc/ -> usr/src/cmd/sgs/tools/sgsmsg/sparc/

Which looks right.

I'm still trying to get a test case together.
Comment 10 Matt Mackall 2012-07-02 15:12 UTC
*** Bug 3523 has been marked as a duplicate of this bug. ***
Comment 11 Jonathan Adams 2012-07-02 15:29 UTC
from Bug 3523, a reproducible example:

--- cut here ---
Description Aaron Jensen 2012-07-02 14:47:02 EDT

When you move a file from a sub-directory into the Mercurial root directory in the same commit that you add a file into renamed file's source sub-directory, when you update to the branch where those changes are made, or merge that branch into another, Mercurial gives the following error:

    abort: path contains illegal component: \new_file.txt 

You can workaround this by using the `-C` parameter to update.  There is no workaround for merging.  This isn't a problem in Mercurial 2.1.2.

## Steps to Reproduce

> hg init illegal_path_component         
> cd .\illegal_path_component            
> '' > root.txt
> mkdir sub                              
> '' > sub/sub.txt 
> hg add sub/sub.txt root.txt                               
> hg commit -m "Initial commit."         
> '' > sub\new.txt
> hg add sub\new.txt
> hg rename sub\sub.txt sub.txt      
> hg commit -m "Moving/adding."          
> hg up 0
> hg up 1
abort: path contains illegal component: \new.txt
> hg branch feature
> 'a' > root.txt
> hg commit -m "Feature update."
> hg up default
abort: path contains illegal component: \new.txt
> hg up default -C
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
> hg merge feature
abort: path contains illegal component: \new.txt

[This test repository on BitBucket shows the issue.](https://bitbucket.org/johnweldon/hg_bug)
--- cut here ---
Comment 12 Jonathan Adams 2012-07-02 15:55 UTC
Running my script against the new test case, it finds the same culprit:

Changeset 16667:86a3bb9c5f5c: bad
Changeset 16030:308406677e9d: good                                              
Changeset 16366:f350021ee32e: bad                                               
Changeset 16189:0d8df15b59d6: good                                              
Changeset 16291:352053e6cd8e: bad                                               
Changeset 16251:6f236c8bdc01: good                                              
Changeset 16271:ec33539b61f6: good                                              
Changeset 16281:9178d284b880: good                                              
Changeset 16286:46a96cc830c2: bad                                               
Changeset 16283:0bb0b9f22cd7: good                                              
Changeset 16284:b8c1a8a57540: good                                              
Changeset 16285:828fe2ca7cbb: bad                                               
The first bad revision is:
changeset:   16285:828fe2ca7cbb
user:        Matt Mackall <mpm@selenic.com>
date:        Sun Feb 26 16:45:59 2012 -0600
summary:     copies: use ctx.dirs() for directory rename detection

and applying Matt's patch to the tip allows the test to succeed.
Comment 13 Vladislav Poluhin 2012-07-17 03:16 UTC
Have same issue with 2.2.3, but `update` and `merge` works fine with same repo at 2.1.2 O_o
Comment 14 Even 2012-07-23 08:39 UTC
I had the same issue on 2.2.1, when merging one branch into another:
"hg abort path contains illegal component"

I installed hg from tip (17228:d1b49b02bc16) and the bug went away.
Comment 15 Matt Mackall 2012-07-29 15:05 UTC
Fixed in stable by:

8b7cd9a998f0 copies: re-include root directory in directory rename detection
Comment 16 Matt Mackall 2012-09-30 16:19 UTC
Mass close old bugs in testing.