diff --git a/hgext3rd/p4fastimport/importer.py b/hgext3rd/p4fastimport/importer.py --- a/hgext3rd/p4fastimport/importer.py +++ b/hgext3rd/p4fastimport/importer.py @@ -125,6 +125,34 @@ continue info = fileinfo[depotname] localname, baserev = info['localname'], info['baserev'] + + # Under rare situations, when a symlink points to a directory, + # the P4 server can report a file "under" it (as if it really + # were a directory). 'p4 sync' reports this as an error and + # continues, but 'hg update' will abort if it encounters this. + # We need to keep such damage out of the hg repository. + depotparentname = os.path.dirname(depotname) + localparentname = os.path.dirname(localname) + + # The manifest's flags for the parent haven't been updated to + # reflect this changelist yet. If the parent's flags are + # changing right now, use them. Otherwise, use the manifest's + # flags. + parentflags = None + parentinfo = fileinfo.get(depotparentname, None) + if parentinfo: + parentflags = parentinfo['flags'].get(change.cl, None) + if parentflags == None: + parentflags = mf.flags(localparentname) + + if 'l' in parentflags: + # We already wrote the filelog. Oh well. Just don't + # reference it in the manifest. + # TODO: hgfilelog.strip()? + self._ui.warn("warning: ignoring {} because it's under a " + "symlink\n".format(localname)) + continue + hgfilelog = self._repo.file(localname) try: mf[localname] = hgfilelog.node(baserev) diff --git a/tests/test-p4fastimport-import-badsymlink.t b/tests/test-p4fastimport-import-badsymlink.t new file mode 100644 --- /dev/null +++ b/tests/test-p4fastimport-import-badsymlink.t @@ -0,0 +1,55 @@ +#require p4 + + $ . $TESTDIR/p4setup.sh + +populate the depot + + $ mkdir Main + $ mkdir Main/b + $ echo a > Main/a + $ echo c > Main/b/c + $ ln -s b Main/d + $ p4 add Main/a Main/b/c Main/d + //depot/Main/a#1 - opened for add + //depot/Main/b/c#1 - opened for add + //depot/Main/d#1 - opened for add + $ p4 submit -d initial + Submitting change 1. + Locking 3 files ... + add //depot/Main/a#1 + add //depot/Main/b/c#1 + add //depot/Main/d#1 + Change 1 submitted. + $ rm Main/d + $ mkdir Main/d + $ echo d > Main/d/d + $ p4 add Main/d/d + //depot/Main/d/d#1 - opened for add + $ p4 submit -d initial + Submitting change 2. + Locking 1 files ... + add //depot/Main/d/d#1 + Change 2 submitted. + $ p4 files ... + //depot/Main/a#1 - add change 1 (text) + //depot/Main/b/c#1 - add change 1 (text) + //depot/Main/d#1 - add change 1 (symlink) + //depot/Main/d/d#1 - add change 2 (text) + +According to P4, Main/d/d is a file inside Main/d, which is a symlink(!) + + $ cd $hgwd + $ hg init --config 'format.usefncache=False' + $ hg p4fastimport --bookmark master -P $P4ROOT hg-p4-import + warning: ignoring Main/d/d because it's under a symlink + $ hg update + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ ls -l Main + total 8 + -rw-r--r-- 1 .* a (re) + drwxr-xr-x 2 .* b (re) + lrwxrwxrwx 1 .* d -> b (re) + +End Test + + stopping the p4 server