Re: cvs2svn, vendor branches, and missing default branch

Michael Haggerty <[email protected]> Sat, 03 Jan 2015 22:32:49 +0100
Newsgroups gmane.comp.version-control.subversion.cvs2svn.user
Message-ID <[email protected]>
On 01/03/2015 04:14 AM, John Hood wrote:
> I've got a problem with some old repos where cvs2svn is choosing=20
> revisions differently than CVS for vendor imports.  I"m not sure it's=20
> actually a CVS2SVN *bug*, because the files involved have unusual=20
> history, and are possibly corrupt in a sense.  But CVS2SVN is creating=20
> output that's different from what CVS saw.
>=20
> The files in question are files that have seen two vendor imports, and=20
> no revisions any place else.  They appear to be constructed as one would=
=20
> expect, except that they lack a 'branch' header to set the default=20
> branch.  That header seems to have disappeared around the time of the=20
> second vendor import, because new tags on trunk start showing up as=20
> revision 1.1 at that time, instead of 1.1.1.1 or 1.1.1.2.  The second=20
> vendor import seems to have been incorrectly/incompletely done, since=20
> the 1.1.1.2 revisions aren't used anywhere in the history.  The files=20
> appear to be syntactically valid, and semantically valid apart from the=
=20
> missing 'branch' header.  That may or may not be valid, but its absence=
=20
> does mean that a little bit of explicit revision history on these files=
=20
> at certain points in time is lost.
>=20
> With these files, CVS chooses revision 1.1.1.1 for checkouts on trunk,=20
> but cvs2svn chooses the second vendor import, formerly known as 1.1.1.2=
=20
> in CVS, after the time of the second import.  This only happens with=20
> these files.  Files that were created by the first vendor import and=20
> unchanged by the second don't have this problem, of course, since they=20
> don't have a 1.1.1.2.  Files that have been imported twice, and updated=
=20
> on HEAD, are OK (though there are the usual footprints of messy CVS=20
> merges).  I think cvs2svn is making a more logical choice about which=20
> revision to use, but unfortunately, it's different from what CVS=20
> chooses, and we need to preserve the CVS history.  It looks like=20
> cvs2svn's behavior is a logical result of how it grafts vendor branches=
=20
> into trunk-- resulting in something slightly different from CVS' heuristi=
c.
>=20
> I see this problem in two CVS repositories so far-- the one I'm working=
=20
> on converting and discussing here, and another which I've not looked=20
> closely at yet.  Both have long history, dating back to 1996-1999.  Both=
=20
> were hosted on FreeBSD machines, but by completely different=20
> organizations.  I doubt it's significant, but in the first repository,=20
> the two vendor imports were done in two different CVS modules, which are=
=20
> submodules of another which is almost always what people use-- it's=20
> generally rare for the submodules to be checked=20
> out/edited/tagged/branched independently. It looks like the first vendor=
=20
> import was done by a single person, but the second imports were done by=
=20
> different people a couple of weeks apart.
>=20
> I've attached a destroyed CVS repository with two of these files from=20
> the two submodules. It's also got a few other files with plenty of=20
> revisions to give cvs2svn something to use for dates and correlation. =20
> There's also a copy of that repo that's been reduced nicely to the=20
> minimum history needed to show this problem.
>=20
> I took a stab at fixing the problem in cvs2svn, but the code and=20
> internal state dealing with vendor branches is complicated enough that I=
=20
> didn't find the right one- or two-line fix.  I have an external=20
> workaround which involves making a force commit and then editing=20
> revision numbers to point at the force commit, before the cvs2svn=20
> conversion.  It gets me a reasonable SVN history.  But I'd like to fix=20
> it more cleanly; there's perhaps 10 more repos behind this one that will=
=20
> be converted.

Thanks for the very thorough error report!

The handling of vendor branches in CVS is quite confusing, and CVS
discards critical information such as when the default branch was
switched back from the vendor branch to HEAD.  So the code makes some
guesses here and I suppose that one of them is wrong.

The two methods most closely related to your problem are

* collect_data.py:_FileDataCollector._process_ntdbrs()

* cvs_file_items.py:CVSFileItems.process_historical_ntdb()

My guess is that the second of these functions is being too aggressive.
Could you try the following change and see if it helps:

diff --git a/cvs2svn_lib/cvs_file_items.py b/cvs2svn_lib/cvs_file_items.py
index d339047..b8f395d 100644
--- a/cvs2svn_lib/cvs_file_items.py
+++ b/cvs2svn_lib/cvs_file_items.py
@@ -533,7 +533,7 @@ class CVSFileItems(object):
     rev_1_2_id =3D rev_1_1.next_id

     if rev_1_2_id is None:
-      rev_1_2_timestamp =3D None
+      return False
     else:
       rev_1_2_timestamp =3D self[rev_1_2_id].timestamp

Given your description of the problem and of CVS's behavior, I don't see
how we can justify treating vendor branch revisions as HEAD branch
revisions if there is no 1.2 revision to tell when to switch back to
HEAD (i.e., I think this change would be justified in general, not just
in your special case).

Please let us know if that does what you expect.

Michael

--=20
Michael Haggerty
[email protected]

------------------------------------------------------
http://cvs2svn.tigris.org/ds/viewMessage.do?dsForumId=3D1670&dsMessageId=3D=
3093683

To unsubscribe from this discussion, e-mail: [[email protected]=
ris.org].