/[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 2 - (show annotations)
Tue Mar 9 21:02:42 2004 UTC (20 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 4775 byte(s)
start after current revision

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

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26