/[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 3 - (show annotations)
Tue Mar 9 21:45:32 2004 UTC (20 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 5388 byte(s)
better instructions, auto-creation of .svnrev, quiet checkout

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

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26