/[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 1 - (show annotations)
Tue Mar 9 20:58:34 2004 UTC (20 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 4621 byte(s)
initial import

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
82
83 #
84 # sub to commit .svn rev file later
85 #
86
87 sub commit_svnrev($) {
88 my $rev = shift @_ || die "commit_svnrev needs revision";
89
90 open(SVNREV,"> $CVSREP/.svnrev") || die "can't open $TMPDIR/$CVSREP/.svnrev: $!";
91 print SVNREV $rev;
92 close(SVNREV);
93
94 my $msg="subversion revision $rev commited to CVS";
95 my $path=".svnrev";
96 print "$msg\n";
97 system "$cvs commit -m \"$msg\" $CVSREP/$path" || die "cvs commit of $path failed: $!";
98 }
99
100 #
101 # FIXME!! HEAD should really be next verison and loop because this way we
102 # loose multiple edits of same file and corresponding messages. On the
103 # other hand, if you want to compress your traffic to CVS server and don't
104 # case much about accuracy and completnes of logs there, this might
105 # be good. YMMV
106 #
107 open(LOG, "svn log -r $rev:HEAD -v --xml $SVNROOT/$SVNREP |") || die "svn log for repository $SVNROOT/$SVNREP failed: $!";
108 my $log;
109 while(<LOG>) {
110 $log .= $_;
111 }
112 close(LOG);
113
114 my $xml = XMLin($log, ForceArray => [ 'path' ]);
115
116
117 =begin log_example
118
119 ------------------------------------------------------------------------
120 r256 | dpavlin | 2004-03-09 13:18:17 +0100 (Tue, 09 Mar 2004) | 2 lines
121
122 ported r254 from hidra branch
123
124 =cut
125
126 my $fmt = "\n" . "-" x 79 . "\nr%5s| %8s | %s\n\n%s\n";
127
128 foreach my $e (@{$xml->{'logentry'}}) {
129 die "BUG: revision from .svnrev ($rev) greater than from subversion (".$e->{'revision'}.")" if ($rev > $e->{'revision'});
130 $rev = $e->{'revision'};
131 log_system("svn export --force -q -r $rev $SVNROOT/$SVNREP $CVSREP", "svn export of revision $rev failed");
132
133 printf($fmt, $e->{'revision'}, $e->{'author'}, $e->{'date'}, $e->{'msg'});
134 foreach my $p (@{$e->{'paths'}->{'path'}}) {
135 my ($action,$path) = ($p->{'action'},$p->{'content'});
136
137 print "svn2cvs: $action $path\n";
138
139 # prepare path and message
140 my $file = $path;
141 $path =~ s,^/$SVNREP/*,, || die "BUG: can't strip SVNREP from path";
142 my $msg = $e->{'msg'};
143 $msg =~ s/"/\\"/g; # quote "
144
145 if ($action =~ /M/) {
146 print "svn2cvs: modify $path -- nop\n";
147 } elsif ($action =~ /A/) {
148 log_system("$cvs add -m \"$msg\" $CVSREP/$path", "cvs add of $path failed");
149 } elsif ($action =~ /D/) {
150 log_system("$cvs delete -m \"$msg\" $CVSREP/$path", "cvs delete of $path failed");
151 } else {
152 print "WARNING: action $action not implemented on $path. Bug or missing feature of $0\n";
153 }
154
155 # now commit changes
156 log_system("$cvs commit -m \"$msg\" $CVSREP/$path", "cvs commit of $path failed");
157
158 }
159
160 commit_svnrev($rev);
161 }
162
163 __END__
164
165 svn export --force "$SVNROOT/$SVNREP" "$CVSREP"
166
167 cd dotfiles
168
169 for file in $(find -type f -not -path \*CVS\*); do
170 FILE=$(basename $file)
171 DIR=$(dirname $file)
172 if ! grep -q "^/$FILE/" $DIR/CVS/Entries ; then
173 cvs add $file
174 fi
175 done
176
177 #cvs commit -m "Automatic commit from SVN"
178
179 #rm -rf $TMPDIR
180
181 echo "cvs left in $TMPDIR"

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26