/[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 6 - (show annotations)
Tue Mar 9 22:16:19 2004 UTC (20 years ago) by dpavlin
File MIME type: text/plain
File size: 5433 byte(s)
make incremental run work again (brown-bag-kind-of-bug)

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

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26