16 print 'USAGE: %s cvs-repos-path svn-repos-path' \
17 % os
.path
.basename(sys
.argv
[0])
18 print ' --help, -h print this usage message and exit with success'
22 sys
.stderr
.write('Error: ' + str(msg
) + '\n')
26 def __init__(self
, path
):
27 path
= os
.path
.abspath(path
)
28 if not os
.path
.isdir(path
):
29 raise RuntimeError('CVS path is not a directory')
30 if os
.path
.exists(os
.path
.join(path
, 'CVSROOT')):
31 # A whole CVS repository was selected
34 for entry
in os
.listdir(path
):
35 if entry
!= 'CVSROOT' and os
.path
.isdir(os
.path
.join(path
, entry
)):
36 self
.modules
.append(( entry
, os
.path
.basename(entry
) ))
38 # A sub-directory of a CVS repository was selected
39 self
.cvsroot
= os
.path
.dirname(path
)
40 module
= os
.path
.basename(path
)
41 while not os
.path
.exists(os
.path
.join(self
.cvsroot
, 'CVSROOT')):
42 parent
= os
.path
.dirname(self
.cvsroot
)
44 raise RuntimeError('Cannot find the CVSROOT directory')
45 module
= os
.path
.join(os
.path
.basename(self
.cvsroot
), module
)
47 self
.modules
= [ ( module
, None ) ]
49 def _export_single(self
, base_cmd
, module
, dest_path
):
50 cmd
= base_cmd
+ [ '-d', dest_path
, module
]
51 pipe
= popen2
.Popen4(cmd
)
52 output
= pipe
.fromchild
.read()
55 print 'CMD FAILED:', string
.join(cmd
, ' ')
57 sys
.stdout
.write(output
)
58 raise RuntimeError('CVS command failed!')
60 def export(self
, dest_path
, rev
=None):
62 base_cmd
= [ CVS_CMD
, '-Q', '-d', self
.cvsroot
, 'export' ]
64 base_cmd
.extend([ '-r', rev
])
66 base_cmd
.extend([ '-D', 'now' ])
67 for module
, subdir
in self
.modules
:
69 this_dest_path
= os
.path
.join(dest_path
, subdir
)
71 this_dest_path
= dest_path
72 self
._export
_single
(base_cmd
, module
, this_dest_path
)
76 def __init__(self
, url
):
79 def export(self
, url
, dest_path
):
80 cmd
= [ SVN_CMD
, 'export', '-q', url
, dest_path
]
81 pipe
= popen2
.Popen4(cmd
)
82 output
= pipe
.fromchild
.read()
85 print 'CMD FAILED:', string
.join(cmd
, ' ')
87 sys
.stdout
.write(output
)
88 raise RuntimeError('SVN command failed!')
90 def export_trunk(self
, rel_url
):
91 self
.export(self
.url
+ '/trunk', rel_url
)
93 def export_tag(self
, rel_url
, tag
):
94 self
.export(self
.url
+ '/tags/' + tag
, rel_url
)
96 def export_branch(self
, rel_url
, branch
):
97 self
.export(self
.url
+ '/branches/' + branch
, rel_url
)
99 def list(self
, rel_url
):
100 cmd
= [ SVN_CMD
, 'ls', self
.url
+ '/' + rel_url
]
101 pipe
= popen2
.Popen4(cmd
)
102 lines
= pipe
.fromchild
.readlines()
105 print 'CMD FAILED:', string
.join(cmd
, ' ')
107 sys
.stdout
.writelines(lines
)
108 raise RuntimeError('SVN command failed!')
111 entries
.append(line
[:-2])
115 return self
.list('tags')
118 return self
.list('branches')
121 def file_compare(base1
, base2
, rel_path
):
122 path1
= os
.path
.join(base1
, rel_path
)
123 path2
= os
.path
.join(base2
, rel_path
)
124 if open(path1
, 'rb').read() != open(path2
, 'rb').read():
125 print ' ANOMALY: File contents differ for %s' % rel_path
130 def tree_compare(base1
, base2
, rel_path
=''):
135 path1
= os
.path
.join(base1
, rel_path
)
136 path2
= os
.path
.join(base2
, rel_path
)
137 if os
.path
.isfile(path1
) and os
.path
.isfile(path2
):
138 return file_compare(base1
, base2
, rel_path
)
139 if not os
.path
.isdir(path1
) or not os
.path
.isdir(path2
):
140 print ' ANOMALY: Path type differ for %s' % rel_path
142 entries1
= os
.listdir(path1
)
144 entries2
= os
.listdir(path2
)
146 if entries1
!= entries2
:
147 print ' ANOMALY: Directory contents differ for %s' % rel_path
150 for entry
in entries1
:
151 new_rel_path
= os
.path
.join(rel_path
, entry
)
152 if not tree_compare(base1
, base2
, new_rel_path
):
157 def verify_contents(cvsroot
, svn_url
, tmpdir
=''):
158 cvs_export_dir
= os
.path
.join(tmpdir
, 'cvs-export')
159 svn_export_dir
= os
.path
.join(tmpdir
, 'svn-export')
161 cr
= CvsRepos(cvsroot
)
162 sr
= SvnRepos(svn_url
)
166 print 'Verifying trunk'
167 cr
.export(cvs_export_dir
)
168 sr
.export_trunk(svn_export_dir
)
169 if not tree_compare(cvs_export_dir
, svn_export_dir
):
170 anomalies
.append('trunk')
171 shutil
.rmtree(cvs_export_dir
)
172 shutil
.rmtree(svn_export_dir
)
174 for tag
in sr
.tags():
175 print 'Verifying tag', tag
176 cr
.export(cvs_export_dir
, tag
)
177 sr
.export_tag(svn_export_dir
, tag
)
178 if not tree_compare(cvs_export_dir
, svn_export_dir
):
179 anomalies
.append('tag:' + tag
)
180 shutil
.rmtree(cvs_export_dir
)
181 shutil
.rmtree(svn_export_dir
)
183 for branch
in sr
.branches():
184 print 'Verifying branch', branch
185 cr
.export(cvs_export_dir
, branch
)
186 sr
.export_branch(svn_export_dir
, branch
)
187 if not tree_compare(cvs_export_dir
, svn_export_dir
):
188 anomalies
.append('branch:' + branch
)
189 shutil
.rmtree(cvs_export_dir
)
190 shutil
.rmtree(svn_export_dir
)
194 print len(anomalies
), 'content anomalies detected:', anomalies
196 print 'No content anomalies detected'
199 def verify(cvsroot
, svn_url
, tmpdir
=''):
200 return verify_contents(cvsroot
, svn_url
, tmpdir
)
205 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'h',
207 except getopt
.GetoptError
, e
:
212 for opt
, value
in opts
:
213 if (opt
== '--help') or (opt
== '-h'):
217 # Consistency check for options and arguments.
223 svn_url
= 'file://' + string
.join([os
.getcwd(), args
[1]], '/')
225 verify(cvsroot
, svn_url
)
228 if __name__
== '__main__':