/[svn2cvs]/trunk/svn2cvs.pl
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/svn2cvs.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (show annotations)
Sat Mar 13 15:44:04 2004 UTC (20 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 5879 byte(s)
quite commit messages in single quotes

1 #!/usr/bin/perl -w
2
3 # This script will transfer changes from Subversion repository
4 # to CVS repository (e.g. SourceForge) while preserving commit
5 # logs.
6 #
7 # Based on original shell version by Tollef Fog Heen available at
8 # http://raw.no/personal/blog
9 #
10 # 2004-03-09 Dobrica Pavlinusic <dpavlin@rot13.org>
11
12 use strict;
13 use File::Temp qw/ tempdir /;
14 use Data::Dumper;
15 use XML::Simple;
16
17 if (@ARGV < 2) {
18 print "usage: $0 SVN_URL CVSROOT CVSREPOSITORY\n";
19 exit 1;
20 }
21
22 my ($SVNROOT,$CVSROOT, $CVSREP) = @ARGV;
23
24 if ($SVNROOT !~ m,^[\w+]+:///*\w+,) {
25 print "ERROR: invalid svn root $SVNROOT\n";
26 exit 1;
27 }
28
29 my $TMPDIR=tempdir( "/tmp/checkoutXXXXX", CLEANUP => 1 );
30
31 chdir($TMPDIR) || die "can't cd to $TMPDIR: $!";
32
33 # cvs command with root
34 my $cvs="cvs -d $CVSROOT";
35
36 #
37 # sub to do logging and system calls
38 #
39 sub log_system($$) {
40 my ($cmd,$errmsg) = @_;
41 print STDERR "## $cmd\n";
42 system($cmd) == 0 || die "$errmsg: $!";
43 }
44
45 #
46 # sub to commit .svn rev file later
47 #
48 sub commit_svnrev {
49 my $rev = shift @_;
50 my $add_new = shift @_;
51
52 die "commit_svnrev needs revision" if (! defined($rev));
53
54 open(SVNREV,"> .svnrev") || die "can't open $TMPDIR/$CVSREP/.svnrev: $!";
55 print SVNREV $rev;
56 close(SVNREV);
57
58 my $path=".svnrev";
59
60 if ($add_new) {
61 system "$cvs add $path" || die "cvs add of $path failed: $!";
62 } else {
63 my $msg="subversion revision $rev commited to CVS";
64 print "$msg\n";
65 system "$cvs commit -m '$msg' $path" || die "cvs commit of $path failed: $!";
66 }
67 }
68
69 # ok, now do the checkout
70
71 log_system("$cvs -q checkout $CVSREP", "cvs checkout failed");
72
73 chdir($CVSREP) || die "can't cd to $TMPDIR/$CVSREP: $!";
74
75
76 my $rev;
77
78 # check if svnrev exists
79 if (! -e ".svnrev") {
80 print <<_USAGE_;
81
82 Your CVS repository doesn't have .svnrev file!
83
84 This file is used to keep CVS repository and SubVersion in sync, so
85 that only newer changes will be commited.
86
87 It's quote possible that this is first svn2cvs run for this repository.
88 If so, you will have to identify correct svn revision which
89 corresponds to current version of CVS repository that has just
90 been checkouted.
91
92 If you migrated your cvs repository to svn using cvs2svn, this will be
93 last SubVersion revision. If this is initial run of conversion of
94 SubVersion repository to CVS, correct revision is 0.
95
96 _USAGE_
97
98 print "svn revision corresponding to CVS [abort]: ";
99 my $in = <STDIN>;
100 chomp($in);
101 if ($in !~ /^\d+$/) {
102 print "Aborting: revision not a number\n";
103 exit 1;
104 } else {
105 $rev = $in;
106 commit_svnrev($rev,1); # create new
107 }
108 } else {
109 open(SVNREV,".svnrev") || die "can't open $TMPDIR/$CVSREP/.svnrev: $!";
110 $rev = <SVNREV>;
111 chomp($rev);
112 close(SVNREV);
113 }
114
115 print "Starting after revision $rev\n";
116 $rev++;
117
118
119 #
120 # FIXME!! HEAD should really be next verison and loop because this way we
121 # loose multiple edits of same file and corresponding messages. On the
122 # other hand, if you want to compress your traffic to CVS server and don't
123 # case much about accuracy and completnes of logs there, this might
124 # be good. YMMV
125 #
126 open(LOG, "svn log -r $rev:HEAD -v --xml $SVNROOT |") || die "svn log for repository $SVNROOT failed: $!";
127 my $log;
128 while(<LOG>) {
129 $log .= $_;
130 }
131 close(LOG);
132
133 my $xml = XMLin($log, ForceArray => [ 'logentry', 'path' ]);
134
135
136 =begin log_example
137
138 ------------------------------------------------------------------------
139 r256 | dpavlin | 2004-03-09 13:18:17 +0100 (Tue, 09 Mar 2004) | 2 lines
140
141 ported r254 from hidra branch
142
143 =cut
144
145 my $fmt = "\n" . "-" x 79 . "\nr%5s| %8s | %s\n\n%s\n";
146
147 if (! $xml->{'logentry'}) {
148 print "no newer log entries in SubVersion repostory. CVS is current\n";
149 exit 0;
150 }
151
152 foreach my $e (@{$xml->{'logentry'}}) {
153 die "BUG: revision from .svnrev ($rev) greater than from subversion (".$e->{'revision'}.")" if ($rev > $e->{'revision'});
154 $rev = $e->{'revision'};
155 log_system("svn export --force -q -r $rev $SVNROOT $TMPDIR/$CVSREP", "svn export of revision $rev failed");
156
157 # deduce name of svn directory
158 my $SVNREP = "";
159 my $tmpsvn = $SVNROOT || die "BUG: SVNROOT empty!";
160 my $tmppath = $e->{'paths'}->{'path'}->[0]->{'content'} || die "BUG: tmppath empty!";
161 do {
162 print "## tmppath: $tmppath tmpsvn: $tmpsvn SVNREP: $SVNREP\n";
163 if ($tmpsvn =~ s,(/\w+/*)$,,) {
164 $SVNREP .= $1;
165 } else {
166 die "ERROR: can't deduce svn dir from $SVNROOT.\nUsing root of snv repository for current version instead of /trunk/ is not supported.\n";
167 }
168 } until ($tmppath =~ m/^$SVNREP/);
169
170 print "NOTICE: using $SVNREP as directory for svn\n";
171
172 printf($fmt, $e->{'revision'}, $e->{'author'}, $e->{'date'}, $e->{'msg'});
173 foreach my $p (@{$e->{'paths'}->{'path'}}) {
174 my ($action,$path) = ($p->{'action'},$p->{'content'});
175
176 print "svn2cvs: $action $path\n";
177
178 # prepare path and message
179 my $file = $path;
180 $path =~ s,^$SVNREP/*,, || die "BUG: can't strip SVNREP from path";
181
182 if (! $path) {
183 print "NOTICE: skipped this operation. Probably trunk creation\n";
184 next;
185 }
186
187 my $msg = $e->{'msg'};
188 $msg =~ s/'/\\'/g; # quote "
189
190 if ($action =~ /M/) {
191 print "svn2cvs: modify $path -- nop\n";
192 } elsif ($action =~ /A/) {
193 if (-d $path) {
194 chdir($path) || die "can't cd into dir $path for import: $!";
195 log_system("$cvs import -d -m '$msg' $CVSREP/$path svn r$rev", "cvs import of $path failed");
196 chdir("$TMPDIR") || die "can't cd to $TMPDIR/$CVSREP: $!";
197 log_system("$cvs checkout $CVSREP/$path", "cvs checkout of imported dir $path failed");
198 chdir("$TMPDIR/$CVSREP") || die "can't cd back to $TMPDIR/$CVSREP: $!";
199 } else {
200 log_system("$cvs add -m '$msg' $path", "cvs add of $path failed");
201 }
202 } elsif ($action =~ /D/) {
203 log_system("$cvs delete -m '$msg' $path", "cvs delete of $path failed");
204 } else {
205 print "WARNING: action $action not implemented on $path. Bug or missing feature of $0\n";
206 }
207
208 # now commit changes
209 log_system("$cvs commit -m '$msg' $path", "cvs commit of $path failed");
210
211 }
212
213 commit_svnrev($rev);
214 }

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26