[PATCH 1 of 4] verify-cvs2svn: add Failures class to report and count failures

Greg Ward <[email protected]>
Newsgroups gmane.comp.version-control.subversion.cvs2svn.devel
Message-ID <b7079a58632a3499400b.1250643307@davros>
- pass failures object around
- instead of "print '*** ANOMALY: ...'", call failures.report()
- change how file contents are compared: instead of spewing diff output
  to stdout, capture it with pipe() and pass to failures.report()

This reduces duplication a bit, but more importantly means we now exit
with meaningful exit status (1 on failures).

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

To unsubscribe from this discussion, e-mail: [[email protected]].
verify-refactor-failures.patch (text/x-patch, 7.8 KB)
# HG changeset patch
# User Greg Ward <[email protected]>
# Date 1249136682 14400
# Node ID b7079a58632a3499400b84c084de8e6c0b52f12c
# Parent  83f2e5a2d43d72b91474ce59d80114127b912f0c
verify-cvs2svn: add Failures class to report and count failures.
- pass failures object around
- instead of "print '*** ANOMALY: ...'", call failures.report()
- change how file contents are compared: instead of spewing diff output
  to stdout, capture it with pipe() and pass to failures.report()

This reduces duplication a bit, but more importantly means we now exit
with meaningful exit status (1 on failures).

diff --git a/contrib/verify-cvs2svn.py b/contrib/verify-cvs2svn.py
--- a/contrib/verify-cvs2svn.py
+++ b/contrib/verify-cvs2svn.py
@@ -251,7 +251,21 @@
   return name
 
 
-def file_compare(base1, base2, run_diff, rel_path):
+class Failures(object):
+  def __init__(self):
+    self.count = 0                      # number of failures seen
+
+  def report(self, summary, details=None):
+    self.count += 1
+    sys.stdout.write('*** ANOMALY: %s\n' % summary)
+    if details:
+      for line in details:
+        sys.stdout.write('***  %s\n' % line)
+
+  def __nonzero__(self):
+    return self.count > 0
+
+def file_compare(failures, base1, base2, run_diff, rel_path):
   """Compare the mode and contents of two files.  The paths are
   specified as two base paths BASE1 and BASE2, and a path REL_PATH that
   is relative to the two base paths.  Return 1 if the file mode and
@@ -261,9 +275,9 @@
   mode1 = os.stat(path1).st_mode & 0700   # only look at owner bits
   mode2 = os.stat(path2).st_mode & 0700
   if mode1 != mode2:
-    print '*** ANOMALY: File modes differ for %s' % rel_path
-    print '***   %s: %o' % (path1, mode1)
-    print '***   %s: %o' % (path2, mode2)
+    failures.report('File modes differ for %s' % rel_path,
+                    details=['%s: %o' % (path1, mode1),
+                             '%s: %o' % (path2, mode2)])
 
   file1 = open(path1, 'rb')
   file2 = open(path2, 'rb')
@@ -271,15 +285,20 @@
     data1 = file1.read(8192)
     data2 = file2.read(8192)
     if data1 != data2:
-      print '*** ANOMALY: File contents differ for %s' % rel_path
       if run_diff:
-        os.system('diff -u "' + path1 + '" "' + path2 + '"')
+        cmd = ['diff', '-u', path1, path2]
+        (output, status) = pipe(cmd)
+        diff = output.split('\n')
+      else:
+        diff = None
+      failures.report('File contents differ for %s' % rel_path,
+                      details=diff)
       return 0
     if len(data1) == 0:
       return 1
 
 
-def tree_compare(base1, base2, run_diff, rel_path=''):
+def tree_compare(failures, base1, base2, run_diff, rel_path=''):
   """Compare the contents of two directory trees, including the contents
   of all files.  The paths are specified as two base paths BASE1 and BASE2,
   and a path REL_PATH that is relative to the two base paths.  Return 1
@@ -291,15 +310,15 @@
     path1 = os.path.join(base1, rel_path)
     path2 = os.path.join(base2, rel_path)
   if not os.path.exists(path1):
-    print '*** ANOMALY: %s does not exist' % path1
+    failures.report('%s does not exist' % path1)
     return 0
   if not os.path.exists(path2):
-    print '*** ANOMALY: %s does not exist' % path2
+    failures.report('%s does not exist' % path2)
     return 0
   if os.path.isfile(path1) and os.path.isfile(path2):
-    return file_compare(base1, base2, run_diff, rel_path)
+    return file_compare(failures, base1, base2, run_diff, rel_path)
   if not (os.path.isdir(path1) and os.path.isdir(path2)):
-    print '*** ANOMALY: Path types differ for %r' % rel_path
+    failures.report('Path types differ for %r' % rel_path)
     return 0
   entries1 = os.listdir(path1)
   entries1.sort()
@@ -308,20 +327,20 @@
   missing = filter(lambda x: x not in entries2, entries1)
   extra = filter(lambda x: x not in entries1, entries2)
   if missing:
-    print '*** ANOMALY: Directory /%s is missing entries: %s' % (
-      rel_path, ', '.join(missing))
+    failures.report('Directory /%s is missing entries: %s' %
+                    (rel_path, ', '.join(missing)))
   if extra:
-    print '*** ANOMALY: Directory /%s has extra entries: %s' % (
-      rel_path, ', '.join(extra))
+    failures.report('Directory /%s has extra entries: %s' %
+                    (rel_path, ', '.join(extra)))
   ok = 1
   for entry in entries1:
     new_rel_path = os.path.join(rel_path, entry)
-    if not tree_compare(base1, base2, run_diff, new_rel_path):
+    if not tree_compare(failures, base1, base2, run_diff, new_rel_path):
       ok = 0
   return ok
 
 
-def verify_contents_single(cvsrepos, verifyrepos, kind, label, ctx):
+def verify_contents_single(failures, cvsrepos, verifyrepos, kind, label, ctx):
   """Verify that the contents of the HEAD revision of all directories
   and files in the conversion repository VERIFYREPOS matches the ones in
   the CVS repository CVSREPOS.  KIND can be either 'trunk', 'tag' or
@@ -351,7 +370,7 @@
     else:
       verifyrepos.export_branch(vrf_export_dir, label)
 
-    if not tree_compare(cvs_export_dir, vrf_export_dir, ctx.run_diff):
+    if not tree_compare(failures, cvs_export_dir, vrf_export_dir, ctx.run_diff):
       return 0
   finally:
     if not ctx.skip_cleanup:
@@ -362,7 +381,7 @@
   return 1
 
 
-def verify_contents(cvsrepos, verifyrepos, ctx):
+def verify_contents(failures, cvsrepos, verifyrepos, ctx):
   """Verify that the contents of the HEAD revision of all directories
   and files in the trunk, all tags and all branches in the conversion
   repository VERIFYREPOS matches the ones in the CVS repository CVSREPOS.
@@ -371,13 +390,13 @@
 
   # Verify contents of trunk
   print 'Verifying trunk'
-  if not verify_contents_single(cvsrepos, verifyrepos, 'trunk', None, ctx):
+  if not verify_contents_single(failures, cvsrepos, verifyrepos, 'trunk', None, ctx):
     anomalies.append('trunk')
 
   # Verify contents of all tags
   for tag in verifyrepos.tags():
     print 'Verifying tag', tag
-    if not verify_contents_single(cvsrepos, verifyrepos, 'tag', tag, ctx):
+    if not verify_contents_single(failures, cvsrepos, verifyrepos, 'tag', tag, ctx):
       anomalies.append('tag:' + tag)
 
   # Verify contents of all branches
@@ -386,11 +405,10 @@
       print 'Skipped branch', branch
     else:
       print 'Verifying branch', branch
-      if not verify_contents_single(cvsrepos, verifyrepos, 'branch', branch, ctx):
+      if not verify_contents_single(failures, cvsrepos, verifyrepos, 'branch', branch, ctx):
         anomalies.append('branch:' + branch)
 
   # Show the results
-  print
   if len(anomalies) == 0:
     print 'No content anomalies detected'
   else:
@@ -467,6 +485,7 @@
                   'hg':  HgRepos,
                   'git': GitRepos}[options.repos_type]
 
+  failures = Failures()
   try:
     # Open the repositories
     cvsrepos = CvsRepos(cvs_path)
@@ -475,21 +494,22 @@
     # Do our thing...
     if verify_branch:
       print 'Verifying branch', verify_branch
-      verify_contents_single(cvsrepos, verifyrepos, 'branch', verify_branch, options)
+      verify_contents_single(failures, cvsrepos, verifyrepos, 'branch', verify_branch, options)
     elif verify_tag:
       print 'Verifying tag', verify_tag
-      verify_contents_single(cvsrepos, verifyrepos, 'tag', verify_tag, options)
+      verify_contents_single(failures, cvsrepos, verifyrepos, 'tag', verify_tag, options)
     elif verify_trunk:
       print 'Verifying trunk'
-      verify_contents_single(cvsrepos, verifyrepos, 'trunk', None, options)
+      verify_contents_single(failures, cvsrepos, verifyrepos, 'trunk', None, options)
     else:
       # Verify trunk, tags and branches
-      verify_contents(cvsrepos, verifyrepos, options)
+      verify_contents(failures, cvsrepos, verifyrepos, options)
   except RuntimeError, e:
     error(str(e))
   except KeyboardInterrupt:
     pass
 
+  sys.exit(failures and 1 or 0)
 
 if __name__ == '__main__':
   main(sys.argv)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.