# HG changeset patch # User Matt Mackall # Date 1240336386 18000 # Node ID 0019be957555b5b7de2a12316fc805169ffade1f # Parent fd7cc930ab8f03b37ac464616e471f4c89f5aa08# Parent d8229670710fa17ed594b036f815318968fd5e8b Merge with crew-stable diff -r fd7cc930ab8f -r 0019be957555 hgext/convert/monotone.py --- a/hgext/convert/monotone.py Fri Apr 17 11:16:50 2009 -0500 +++ b/hgext/convert/monotone.py Tue Apr 21 12:53:06 2009 -0500 @@ -106,15 +106,10 @@ value = value.replace(r'\"', '"') value = value.replace(r'\\', '\\') certs[name] = value + # Monotone may have subsecond dates: 2005-02-05T09:39:12.364306 + certs["date"] = certs["date"].split('.')[0] return certs - def mtnrenamefiles(self, files, fromdir, todir): - renamed = {} - for tofile in files: - if tofile.startswith(todir + '/'): - renamed[tofile] = fromdir + tofile[len(todir):] - return renamed - # implement the converter_source interface: def getheads(self): @@ -127,15 +122,17 @@ #revision = self.mtncmd("get_revision %s" % rev).split("\n\n") revision = self.mtnrun("get_revision", rev).split("\n\n") files = {} + addedfiles = {} + renameddirs = [] copies = {} for e in revision: m = self.add_file_re.match(e) if m: files[m.group(1)] = rev + addedfiles[m.group(1)] = rev m = self.patch_re.match(e) if m: files[m.group(1)] = rev - # Delete/rename is handled later when the convert engine # discovers an IOError exception from getfile, # but only if we add the "from" file to the list of changes. @@ -150,14 +147,26 @@ copies[toname] = fromname files[toname] = rev files[fromname] = rev - if self.mtnisdir(toname, rev): - renamed = self.mtnrenamefiles(self.files, fromname, toname) - for tofile, fromfile in renamed.items(): - self.ui.debug (_("copying file in renamed dir from '%s' to '%s'") % (fromfile, tofile), '\n') - files[tofile] = rev - copies[tofile] = fromfile - for fromfile in renamed.values(): - files[fromfile] = rev + elif self.mtnisdir(toname, rev): + renameddirs.append((fromname, toname)) + + # Directory renames can be handled only once we have recorded + # all new files + for fromdir, todir in renameddirs: + renamed = {} + for tofile in self.files: + if tofile in addedfiles: + continue + if tofile.startswith(todir + '/'): + renamed[tofile] = fromdir + tofile[len(todir):] + for tofile, fromfile in renamed.items(): + self.ui.debug (_("copying file in renamed dir from '%s' to '%s'") + % (fromfile, tofile), '\n') + files[tofile] = rev + copies[tofile] = fromfile + for fromfile in renamed.values(): + files[fromfile] = rev + return (files.items(), copies) def getmode(self, name, rev): diff -r fd7cc930ab8f -r 0019be957555 tests/test-convert-cvs-synthetic --- a/tests/test-convert-cvs-synthetic Fri Apr 17 11:16:50 2009 -0500 +++ b/tests/test-convert-cvs-synthetic Tue Apr 21 12:53:06 2009 -0500 @@ -3,8 +3,6 @@ # This feature requires use of builtin cvsps! "$TESTDIR/hghave" cvs || exit 80 -# XXX lots of duplication with other test-convert-cvs* scripts - set -e echo "[extensions]" >> $HGRCPATH @@ -19,47 +17,62 @@ export CVS_OPTIONS=-f cd .. -filter='sed "s:$CVSROOT:*REPO*:g"' +filterpath() +{ + eval "$@" | sed "s:$CVSROOT:*REPO*:g" +} + cvscall() { - cvs -f "$@" | eval $filter + echo cvs -f "$@" + cvs -f "$@" 2>&1 } -cvscall -q -d "$CVSROOT" init +# output of 'cvs ci' varies unpredictably, so just discard it +cvsci() +{ + echo cvs -f ci "$@" + cvs -f ci "$@" >/dev/null 2>&1 +} + +filterpath cvscall -d "$CVSROOT" init mkdir cvsrepo/proj -cvscall co proj +cvscall -q co proj echo % create file1 on the trunk cd proj touch file1 -cvscall add file1 -cvscall ci -m"add file1 on trunk" file1 +cvscall -Q add file1 +cvsci -m"add file1 on trunk" file1 echo % create two branches -cvscall tag -b v1_0 -cvscall tag -b v1_1 +cvscall -q tag -b v1_0 +cvscall -q tag -b v1_1 echo % create file2 on branch v1_0 -cvs up -rv1_0 +cvscall -q up -rv1_0 touch file2 -cvscall add file2 -cvscall ci -m"add file2 on branch v1_0" file2 +cvscall -Q add file2 +cvsci -m"add file2 on branch v1_0" file2 echo % create file3, file4 on branch v1_1 -cvs up -rv1_1 +cvscall -Q up -rv1_1 touch file3 touch file4 -cvscall add file3 file4 -cvscall ci -m"add file3, file4 on branch v1_1" file3 file4 +cvscall -Q add file3 file4 +cvsci -m"add file3, file4 on branch v1_1" file3 file4 echo % merge file2 from v1_0 to v1_1 -cvscall up -jv1_0 -cvscall ci -m"merge file2 from v1_0 to v1_1" +cvscall -q up -jv1_0 +cvsci -m"merge file2 from v1_0 to v1_1" + +echo % cvs rlog output +filterpath cvscall -q rlog proj | egrep '^(RCS file|revision)' echo % convert to hg cd .. -hg convert proj proj.hg | eval $filter +filterpath hg convert proj proj.hg echo % hg log output hg -R proj.hg log --template "{rev} {desc}\n" diff -r fd7cc930ab8f -r 0019be957555 tests/test-convert-cvs-synthetic.out --- a/tests/test-convert-cvs-synthetic.out Fri Apr 17 11:16:50 2009 -0500 +++ b/tests/test-convert-cvs-synthetic.out Tue Apr 21 12:53:06 2009 -0500 @@ -1,37 +1,40 @@ % create cvs repository with one project -cvs checkout: Updating proj +cvs -f -d *REPO* init +cvs -f -q co proj % create file1 on the trunk -cvs add: scheduling file `file1' for addition -cvs add: use `cvs commit' to add this file permanently -*REPO*/proj/file1,v <-- file1 -initial revision: 1.1 +cvs -f -Q add file1 +cvs -f ci -madd file1 on trunk file1 % create two branches -cvs tag: Tagging . +cvs -f -q tag -b v1_0 T file1 -cvs tag: Tagging . +cvs -f -q tag -b v1_1 T file1 % create file2 on branch v1_0 -cvs update: Updating . -cvs add: scheduling file `file2' for addition on branch `v1_0' -cvs add: use `cvs commit' to add this file permanently -*REPO*/proj/Attic/file2,v <-- file2 -new revision: 1.1.2.1; previous revision: 1.1 +cvs -f -q up -rv1_0 +cvs -f -Q add file2 +cvs -f ci -madd file2 on branch v1_0 file2 % create file3, file4 on branch v1_1 -cvs update: Updating . -cvs update: `file2' is no longer in the repository -cvs add: scheduling file `file3' for addition on branch `v1_1' -cvs add: scheduling file `file4' for addition on branch `v1_1' -cvs add: use `cvs commit' to add these files permanently -*REPO*/proj/Attic/file3,v <-- file3 -new revision: 1.1.2.1; previous revision: 1.1 -*REPO*/proj/Attic/file4,v <-- file4 -new revision: 1.1.2.1; previous revision: 1.1 +cvs -f -Q up -rv1_1 +cvs -f -Q add file3 file4 +cvs -f ci -madd file3, file4 on branch v1_1 file3 file4 % merge file2 from v1_0 to v1_1 -cvs update: Updating . +cvs -f -q up -jv1_0 U file2 -cvs commit: Examining . -*REPO*/proj/Attic/file2,v <-- file2 -new revision: 1.1.4.2; previous revision: 1.1.4.1 +cvs -f ci -mmerge file2 from v1_0 to v1_1 +% cvs rlog output +RCS file: *REPO*/proj/file1,v +revision 1.1 +RCS file: *REPO*/proj/Attic/file2,v +revision 1.1 +revision 1.1.4.2 +revision 1.1.4.1 +revision 1.1.2.1 +RCS file: *REPO*/proj/Attic/file3,v +revision 1.1 +revision 1.1.2.1 +RCS file: *REPO*/proj/Attic/file4,v +revision 1.1 +revision 1.1.2.1 % convert to hg initializing destination proj.hg repository using builtin cvsps diff -r fd7cc930ab8f -r 0019be957555 tests/test-convert-mtn --- a/tests/test-convert-mtn Fri Apr 17 11:16:50 2009 -0500 +++ b/tests/test-convert-mtn Tue Apr 21 12:53:06 2009 -0500 @@ -33,9 +33,10 @@ echo a > a mkdir dir echo b > dir/b +echo d > dir/d python -c 'file("bin", "wb").write("a\\x00b")' echo c > c -mtn add a dir/b c bin +mtn add a dir/b dir/d c bin mtn ci -m initialize echo % update monotone working directory mtn mv a dir/a @@ -66,6 +67,9 @@ mtn ci -m movedir1 echo '% test subdirectory move' mtn mv dir dir2 +echo newfile > dir2/newfile +mtn drop dir2/d +mtn add dir2/newfile mtn ci -m movedir # Test directory removal with empty directory mkdir dir2/dir @@ -102,5 +106,7 @@ test -d dir1/subdir2 || echo 'new dir1/subdir2 does not exist!' test -d dir1/subdir1 && echo 'renamed dir1/subdir1 is still there!' hg log -v -C -r 4 | grep copies +echo % check file remove with directory move +hg manifest -r 5 exit 0 diff -r fd7cc930ab8f -r 0019be957555 tests/test-convert-mtn.out --- a/tests/test-convert-mtn.out Fri Apr 17 11:16:50 2009 -0500 +++ b/tests/test-convert-mtn.out Tue Apr 21 12:53:06 2009 -0500 @@ -5,14 +5,15 @@ mtn: adding c to workspace manifest mtn: adding dir to workspace manifest mtn: adding dir/b to workspace manifest +mtn: adding dir/d to workspace manifest mtn: beginning commit on branch 'com.selenic.test' -mtn: committed revision 803ef0bf815e35b951dbd4310acd1e45e675016e +mtn: committed revision 0f6e5e4f2e7d2a8ef312408f57618abf026afd90 % update monotone working directory mtn: skipping dir, already accounted for in workspace mtn: renaming a to dir/a in workspace manifest mtn: dropping c from workspace manifest mtn: beginning commit on branch 'com.selenic.test' -mtn: committed revision 4daf60753d6fe21a06ce5f716303fe55fd6d3a56 +mtn: committed revision 51d0a982464573a2a2cf5ee2c9219c652aaebeff % convert once assuming destination repo.mtn-hg initializing destination repo.mtn-hg repository @@ -25,7 +26,7 @@ mtn: dropping dir/b from workspace manifest mtn: renaming bin to bin2 in workspace manifest mtn: beginning commit on branch 'com.selenic.test' -mtn: committed revision 6c6977a6ef609ec80e40779f89dbd2772c96de62 +mtn: committed revision ebe58335d85d8cb176b6d0a12be04f5314b998da % test directory move mtn: adding dir1 to workspace manifest mtn: adding dir1/subdir1 to workspace manifest @@ -33,23 +34,25 @@ mtn: adding dir1/subdir2_other to workspace manifest mtn: adding dir1/subdir2_other/file1 to workspace manifest mtn: beginning commit on branch 'com.selenic.test' -mtn: committed revision e066b1feb2b7a7110450c2c18b5b4462011427d1 +mtn: committed revision a8d62bc04fee4d2936d28e98bbcc81686dd74306 mtn: skipping dir1, already accounted for in workspace mtn: renaming dir1/subdir1 to dir1/subdir2 in workspace manifest mtn: beginning commit on branch 'com.selenic.test' -mtn: committed revision 2ad2409d25bb8d2583b57a3d4c0fa1df62aa1f79 +mtn: committed revision 2c3d241bbbfe538b1b51d910f5676407e3f4d3a6 % test subdirectory move mtn: renaming dir to dir2 in workspace manifest +mtn: dropping dir2/d from workspace manifest +mtn: adding dir2/newfile to workspace manifest mtn: beginning commit on branch 'com.selenic.test' -mtn: committed revision a85290b81fc4a8fbce4dc4d956404109842b406e +mtn: committed revision fdb5a02dae8bfce3a79b3393680af471016e1b4c mtn: beginning commit on branch 'com.selenic.test' -mtn: committed revision 7e3c8746060117104f16ff2d9212cf0f810cbff0 +mtn: committed revision 8bbf76d717001d24964e4604739fdcd0f539fc88 mtn: dropping dir2/dir/subdir/f from workspace manifest mtn: dropping dir2/dir/subdir from workspace manifest mtn: dropping dir2/dir/emptydir from workspace manifest mtn: dropping dir2/dir from workspace manifest mtn: beginning commit on branch 'com.selenic.test' -mtn: committed revision a97e0433d041a6d253c5dc27e080d544e55d9c19 +mtn: committed revision 2323d4bc324e6c82628dc04d47a9fd32ad24e322 % convert incrementally assuming destination repo.mtn-hg scanning source... @@ -61,12 +64,12 @@ 2 movedir 1 emptydir 0 dropdirectory -5 files updated, 0 files merged, 0 files removed, 0 files unresolved +6 files updated, 0 files merged, 0 files removed, 0 files unresolved @ 7 "dropdirectory" files: dir2/dir/subdir/f | o 6 "emptydir" files: dir2/dir/subdir/f | -o 5 "movedir" files: dir/a dir2/a +o 5 "movedir" files: dir/a dir/d dir2/a dir2/newfile | o 4 "movedir1" files: dir1/subdir1/file1 dir1/subdir2/file1 | @@ -76,13 +79,14 @@ | o 1 "update1" files: a bin c dir/a dir/b | -o 0 "initialize" files: a bin c dir/b +o 0 "initialize" files: a bin c dir/b dir/d % manifest bin2 dir1/subdir2/file1 dir1/subdir2_other/file1 dir2/a +dir2/newfile e % contents a @@ -92,7 +96,15 @@ % check directory move bin2 dir/a +dir/d dir1/subdir2/file1 dir1/subdir2_other/file1 e copies: dir1/subdir2/file1 (dir1/subdir1/file1) +% check file remove with directory move +bin2 +dir1/subdir2/file1 +dir1/subdir2_other/file1 +dir2/a +dir2/newfile +e