Re: [PATCH] destroy_repository.py and empty/non-empty revisions

Michael Haggerty <[email protected]> Fri, 05 Mar 2010 12:16:14 +0100
Newsgroups gmane.comp.version-control.subversion.cvs2svn.devel
Message-ID <[email protected]>
Jon Foster wrote:
> With CVS, you can use "cvs commit -f" to commit a file that hasn't
> actually changed.  This generates a new revision in the repository,
> with an empty diff.  I'm working on a patch for cvs2svn to allow these
> no-op CVS commits to be ignored.

This is a nice idea.

> I want to use contrib/destroy_repository.py to make test cases, but
> it replaces every diff with an empty one.  This means that every
> revision (except adds and deletes) looks like a no-op CVS commit.
> 
> The attached patch to contrib/destroy_repository.py makes it preserve
> the empty/non-empty state, while still destroying the actual data.
> The patch is against cvs2svn trunk.

Also a good idea.  Thanks for the patch!

I went a step further and set the revision texts to say something about
the revision number of the corresponding revision.  I think this text
might sometimes be helpful for debugging.  The main functional
difference to your patch is that your patch leaves an empty HEAD
revision empty, whereas my patch changes it unconditionally to "This
text was last seen in HEAD (revision REV)".  Would that be a problem for
your purposes?

If not, maybe you could give my patch a look and tell me if you like it.
 It applies to trunk.

Michael

------------------------------------------------------
http://cvs2svn.tigris.org/ds/viewMessage.do?dsForumId=1667&dsMessageId=2455395

To unsubscribe from this discussion, e-mail: [[email protected]].
preserve-empty2.diff (text/x-diff, 2.5 KB)
diff --git a/contrib/destroy_repository.py b/contrib/destroy_repository.py
index 461a189..73c141c 100755
--- a/contrib/destroy_repository.py
+++ b/contrib/destroy_repository.py
@@ -276,6 +276,10 @@ class DestroyerFilterSink(FilterSink):
         self.author_substituter = author_substituter
         self.log_substituter = log_substituter
 
+    def set_head_revision(self, revision):
+        self.head_revision = revision
+        self.sink.set_head_revision(revision)
+
     def define_tag(self, name, revision):
         if destroy['symbols']:
             name = rewrite_symbol(name)
@@ -297,7 +301,38 @@ class DestroyerFilterSink(FilterSink):
 
     def set_revision_info(self, revision, log, text):
         if destroy['data']:
-            text = ''
+            if revision == self.head_revision:
+                # Set the HEAD text unconditionally.  (It could be
+                # that revision HEAD-1 has an empty deltatext, in
+                # which case the HEAD text was actually committed in
+                # an earlier commit.)
+                text = (
+                    'This text was last seen in HEAD (revision %s)\n'
+                    ) % (revision,)
+            elif text == '':
+                # This is a no-op revision; preserve that fact.  (It
+                # might be relied on by cvs2svn).
+                pass
+            else:
+                # Otherwise, replace the data.
+                if revision.count('.') == 1:
+                    # On trunk, it could be that revision N-1 has an
+                    # empty deltatext, in which case text for revision
+                    # N was actually committed in an earlier commit.
+                    text = (
+                        'd1 1\n'
+                        'a1 1\n'
+                        'This text was last seen in revision %s\n'
+                        ) % (revision,)
+                else:
+                    # On a branch, we know that the text was changed
+                    # in revision N (even though the same text might
+                    # also be kept across later revisions N+1 etc.)
+                    text = (
+                        'd1 1\n'
+                        'a1 1\n'
+                        'This text was committed in revision %s\n'
+                        ) % (revision,)
         if destroy['metadata'] or destroy['symbols'] or destroy['filenames']:
             log = self.log_substituter.get_substitution(log)
         FilterSink.set_revision_info(self, revision, log, text)