/[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 7 - (show annotations)
Tue Mar 9 22:35:55 2004 UTC (20 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 5556 byte(s)
work in relative directory to checkouted CVS repository, skip trunk
creation (which resulted in additional commit on .svnrev file, making
revision of .svnrev and svn repository out of sync)

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

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26