/[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

Diff of /trunk/svn2cvs.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2 by dpavlin, Tue Mar 9 21:02:42 2004 UTC revision 8 by dpavlin, Thu Mar 11 16:26:49 2004 UTC
# Line 14  use File::Temp qw/ tempdir /; Line 14  use File::Temp qw/ tempdir /;
14  use Data::Dumper;  use Data::Dumper;
15  use XML::Simple;  use XML::Simple;
16    
17  # get current user home directory  if (@ARGV < 2) {
18  my $HOME = $ENV{'HOME'} || die "can't get home directory!";          print "usage: $0 SVN_URL CVSROOT CVSREPOSITORY\n";
19            exit 1;
20    }
21    
22    my ($SVNROOT,$CVSROOT, $CVSREP) = @ARGV;
23    
24  # cvsroot directory  if ($SVNROOT !~ m,^\w+:///*\w+,) {
25  my $CVSROOT="$HOME/x/cvsroot";          print "ERROR: invalid svn root $SVNROOT\n";
26  # name of cvs repository to commit to          exit 1;
27  my $CVSREP="webpac";  }
   
 # svnroot directory  
 my $SVNROOT="file://$HOME/private/svn/webpac/";  
 # name of respository  
 my $SVNREP="trunk";  
28    
29  my $TMPDIR=tempdir( "/tmp/checkoutXXXXX", CLEANUP => 1 );  my $TMPDIR=tempdir( "/tmp/checkoutXXXXX", CLEANUP => 1 );
30    
# Line 40  my $cvs="cvs -d $CVSROOT"; Line 39  my $cvs="cvs -d $CVSROOT";
39  sub log_system($$) {  sub log_system($$) {
40          my ($cmd,$errmsg) = @_;          my ($cmd,$errmsg) = @_;
41          print STDERR "## $cmd\n";          print STDERR "## $cmd\n";
42          system $cmd || die "$errmsg: $!";          system($cmd) == 0 || die "$errmsg: $!";
43  }  }
44    
45    #
46    # sub to commit .svn rev file later
47    #
48    sub commit_svnrev {
49            my $rev = shift @_;
50            my $add_new = shift @_;
51    
52  # ok, now do the checkout          die "commit_svnrev needs revision" if (! defined($rev));
53    
54  log_system("$cvs checkout $CVSREP","cvs checkout failed");          open(SVNREV,"> .svnrev") || die "can't open $TMPDIR/$CVSREP/.svnrev: $!";
55            print SVNREV $rev;
56            close(SVNREV);
57    
58  # check if svnrev exists          my $path=".svnrev";
59    
60  if (! -e "$CVSREP/.svnrev") {          if ($add_new) {
61          print <<_USAGE_;                  system "$cvs add $path" || die "cvs add of $path failed: $!";
62            } else {
63                    my $msg="subversion revision $rev commited to CVS";
64                    print "$msg\n";
65                    system "$cvs commit -m \"$msg\" $path" || die "cvs commit of $path failed: $!";
66            }
67    }
68    
69          Your CVS repository doesn't have $TMPDIR/$CVSREP/.svnrev file!  # ok, now do the checkout
70    
71          This file is used to commit changes to CVS repository with correct  log_system("$cvs -q checkout $CVSREP", "cvs checkout failed");
         logs from Subversion.  
72    
73          Please create .svnrec file with currect svn revision which  chdir($CVSREP) || die "can't cd to $TMPDIR/$CVSREP: $!";
         corresponds to version of checkouted tree and commit that file  
         to CVS repository, e.g.  
   
         echo 233 > .svnrev  
         cvs add .svnrev  
         cvs commit -m "subversion repository revision sync file" .svnrev  
74    
 _USAGE_  
         print "CVS Repository left in $TMPDIR/$CVSREP\n";  
         exit 1;  
 }  
75    
76    my $rev;
77    
78  open(SVNREV,"$CVSREP/.svnrev") || die "can't open $TMPDIR/$CVSREP/.svnrev: $!";  # check if svnrev exists
79  my $rev = <SVNREV>;  if (! -e ".svnrev") {
80  chomp($rev);          print <<_USAGE_;
 close(SVNREV);  
81    
82  print "Starting after revision $rev\n";  Your CVS repository doesn't have .svnrev file!
 $rev++;  
83    
84    This file is used to keep CVS repository and SubVersion in sync, so
85    that only newer changes will be commited.
86    
87  #  It's quote possible that this is first svn2cvs run for this repository.
88  # sub to commit .svn rev file later  If so, you will have to identify correct svn revision which
89  #  corresponds to current version of CVS repository that has just
90    been checkouted.
91    
92    If you migrated your cvs repository to svn using cvs2svn, this will be
93    last SubVersion revision. If this is initial run of conversion of
94    SubVersion repository to CVS, correct revision is 0.
95    
96  sub commit_svnrev($) {  _USAGE_
         my $rev = shift @_ || die "commit_svnrev needs revision";  
97    
98          open(SVNREV,"> $CVSREP/.svnrev") || die "can't open $TMPDIR/$CVSREP/.svnrev: $!";          print "svn revision corresponding to CVS [abort]: ";
99          print SVNREV $rev;          my $in = <STDIN>;
100            chomp($in);
101            if ($in !~ /^\d+$/) {
102                    print "Aborting: revision not a number\n";
103                    exit 1;
104            } else {
105                    $rev = $in;
106                    commit_svnrev($rev,1);  # create new
107            }
108    } else {
109            open(SVNREV,".svnrev") || die "can't open $TMPDIR/$CVSREP/.svnrev: $!";
110            $rev = <SVNREV>;
111            chomp($rev);
112          close(SVNREV);          close(SVNREV);
   
         my $msg="subversion revision $rev commited to CVS";  
         my $path=".svnrev";  
         print "$msg\n";  
         system "$cvs commit -m \"$msg\" $CVSREP/$path" || die "cvs commit of $path failed: $!";  
113  }  }
114    
115    print "Starting after revision $rev\n";
116    $rev++;
117    
118    
119  #  #
120  # FIXME!! HEAD should really be next verison and loop because this way we  # FIXME!! HEAD should really be next verison and loop because this way we
121  # loose multiple edits of same file and corresponding messages. On the  # loose multiple edits of same file and corresponding messages. On the
# Line 105  sub commit_svnrev($) { Line 123  sub commit_svnrev($) {
123  # case much about accuracy and completnes of logs there, this might  # case much about accuracy and completnes of logs there, this might
124  # be good. YMMV  # be good. YMMV
125  #  #
126  open(LOG, "svn log -r $rev:HEAD -v --xml $SVNROOT/$SVNREP |") || die "svn log for repository $SVNROOT/$SVNREP failed: $!";  open(LOG, "svn log -r $rev:HEAD -v --xml $SVNROOT |") || die "svn log for repository $SVNROOT failed: $!";
127  my $log;  my $log;
128  while(<LOG>) {  while(<LOG>) {
129          $log .= $_;          $log .= $_;
# Line 131  if (! $xml->{'logentry'}) { Line 149  if (! $xml->{'logentry'}) {
149          exit 0;          exit 0;
150  }  }
151    
 print Dumper($xml);  
   
152  foreach my $e (@{$xml->{'logentry'}}) {  foreach my $e (@{$xml->{'logentry'}}) {
153          die "BUG: revision from .svnrev ($rev) greater than from subversion (".$e->{'revision'}.")" if ($rev > $e->{'revision'});          die "BUG: revision from .svnrev ($rev) greater than from subversion (".$e->{'revision'}.")" if ($rev > $e->{'revision'});
154          $rev = $e->{'revision'};          $rev = $e->{'revision'};
155          log_system("svn export --force -q -r $rev $SVNROOT/$SVNREP $CVSREP", "svn export of revision $rev failed");          log_system("svn export --force -q -r $rev $SVNROOT $TMPDIR/$CVSREP", "svn export of revision $rev failed");
156    
157            # deduce name of svn directory
158            my $SVNREP = "";
159            my $tmpsvn = $SVNROOT || die "BUG: SVNROOT empty!";
160            my $tmppath = $e->{'paths'}->{'path'}->[0]->{'content'} || die "BUG: tmppath empty!";
161            do {
162    print "## tmppath: $tmppath tmpsvn: $tmpsvn SVNREP: $SVNREP\n";
163                    if ($tmpsvn =~ s,(/\w+/*)$,,) {
164                            $SVNREP .= $1;
165                    } else {
166                            die "ERROR: can't deduce svn dir from $SVNROOT.\nUsing root of snv repository for current version instead of /trunk/ is not supported.\n";
167                    }
168            } until ($tmppath =~ m/^$SVNREP/);
169    
170            print "NOTICE: using $SVNREP as directory for svn\n";
171    
172          printf($fmt, $e->{'revision'}, $e->{'author'}, $e->{'date'}, $e->{'msg'});          printf($fmt, $e->{'revision'}, $e->{'author'}, $e->{'date'}, $e->{'msg'});
173          foreach my $p (@{$e->{'paths'}->{'path'}}) {          foreach my $p (@{$e->{'paths'}->{'path'}}) {
# Line 146  foreach my $e (@{$xml->{'logentry'}}) { Line 177  foreach my $e (@{$xml->{'logentry'}}) {
177    
178                  # prepare path and message                  # prepare path and message
179                  my $file = $path;                  my $file = $path;
180                  $path =~ s,^/$SVNREP/*,, || die "BUG: can't strip SVNREP from path";                  $path =~ s,^$SVNREP/*,, || die "BUG: can't strip SVNREP from path";
181    
182                    if (! $path) {
183                            print "NOTICE: skipped this operation. Probably trunk creation\n";
184                            next;
185                    }
186    
187                  my $msg = $e->{'msg'};                  my $msg = $e->{'msg'};
188                  $msg =~ s/"/\\"/g;      # quote "                  $msg =~ s/"/\\"/g;      # quote "
189    
190                  if ($action =~ /M/) {                  if ($action =~ /M/) {
191                          print "svn2cvs: modify $path -- nop\n";                          print "svn2cvs: modify $path -- nop\n";
192                  } elsif ($action =~ /A/) {                  } elsif ($action =~ /A/) {
193                          log_system("$cvs add -m \"$msg\" $CVSREP/$path", "cvs add of $path failed");                          if (-d $path) {
194                                    chdir($path) || die "can't cd into dir $path for import: $!";
195                                    log_system("$cvs import -d -m \"$msg\" $CVSREP/$path svn r$rev", "cvs import of $path failed");
196                                    chdir("$TMPDIR") || die "can't cd to $TMPDIR/$CVSREP: $!";
197                                    log_system("$cvs checkout $CVSREP/$path", "cvs checkout of imported dir $path failed");
198                                    chdir("$TMPDIR/$CVSREP") || die "can't cd back to $TMPDIR/$CVSREP: $!";
199                            } else {
200                                    log_system("$cvs add -m \"$msg\" $path", "cvs add of $path failed");
201                            }
202                  } elsif ($action =~ /D/) {                  } elsif ($action =~ /D/) {
203                          log_system("$cvs delete -m \"$msg\" $CVSREP/$path", "cvs delete of $path failed");                          log_system("$cvs delete -m \"$msg\" $path", "cvs delete of $path failed");
204                  } else {                  } else {
205                          print "WARNING: action $action not implemented on $path. Bug or missing feature of $0\n";                          print "WARNING: action $action not implemented on $path. Bug or missing feature of $0\n";
206                  }                  }
207    
208                  # now commit changes                  # now commit changes
209                  log_system("$cvs commit -m \"$msg\" $CVSREP/$path", "cvs commit of $path failed");                  log_system("$cvs commit -m \"$msg\" $path", "cvs commit of $path failed");
210    
211          }          }
212    
213          commit_svnrev($rev);          commit_svnrev($rev);
214  }  }
   
 __END__  
   
 svn export --force "$SVNROOT/$SVNREP" "$CVSREP"  
   
 cd dotfiles  
   
 for file in $(find -type f -not -path \*CVS\*); do  
         FILE=$(basename $file)  
         DIR=$(dirname $file)  
         if ! grep -q "^/$FILE/" $DIR/CVS/Entries ; then  
                 cvs add $file  
         fi  
 done  
   
 #cvs commit -m "Automatic commit from SVN"  
   
 #rm -rf $TMPDIR  
   
 echo "cvs left in $TMPDIR"  

Legend:
Removed from v.2  
changed lines
  Added in v.8

  ViewVC Help
Powered by ViewVC 1.1.26