/[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 11 by dpavlin, Sat Mar 13 15:44:04 2004 UTC revision 15 by dpavlin, Sun Mar 14 21:53:44 2004 UTC
# Line 8  Line 8 
8  # http://raw.no/personal/blog  # http://raw.no/personal/blog
9  #  #
10  # 2004-03-09 Dobrica Pavlinusic <dpavlin@rot13.org>  # 2004-03-09 Dobrica Pavlinusic <dpavlin@rot13.org>
11    #
12    # documentation is after __END__
13    
14  use strict;  use strict;
15  use File::Temp qw/ tempdir /;  use File::Temp qw/ tempdir /;
# Line 81  if (! -e ".svnrev") { Line 83  if (! -e ".svnrev") {
83    
84  Your CVS repository doesn't have .svnrev file!  Your CVS repository doesn't have .svnrev file!
85    
86  This file is used to keep CVS repository and SubVersion in sync, so  This file is used to keep CVS repository and Subversion in sync, so
87  that only newer changes will be commited.  that only newer changes will be commited.
88    
89  It's quote possible that this is first svn2cvs run for this repository.  It's quote possible that this is first svn2cvs run for this repository.
# Line 90  corresponds to current version of CVS re Line 92  corresponds to current version of CVS re
92  been checkouted.  been checkouted.
93    
94  If you migrated your cvs repository to svn using cvs2svn, this will be  If you migrated your cvs repository to svn using cvs2svn, this will be
95  last SubVersion revision. If this is initial run of conversion of  last Subversion revision. If this is initial run of conversion of
96  SubVersion repository to CVS, correct revision is 0.  Subversion repository to CVS, correct revision is 0.
97    
98  _USAGE_  _USAGE_
99    
# Line 133  close(LOG); Line 135  close(LOG);
135  my $xml = XMLin($log, ForceArray => [ 'logentry', 'path' ]);  my $xml = XMLin($log, ForceArray => [ 'logentry', 'path' ]);
136    
137    
138  =begin log_example  #=begin log_example
139    #
140  ------------------------------------------------------------------------  #------------------------------------------------------------------------
141  r256 | dpavlin | 2004-03-09 13:18:17 +0100 (Tue, 09 Mar 2004) | 2 lines  #r256 | dpavlin | 2004-03-09 13:18:17 +0100 (Tue, 09 Mar 2004) | 2 lines
142    #
143  ported r254 from hidra branch  #ported r254 from hidra branch
144    #
145  =cut  #=cut
146    
147  my $fmt = "\n" . "-" x 79 . "\nr%5s| %8s | %s\n\n%s\n";  my $fmt = "\n" . "-" x 79 . "\nr%5s| %8s | %s\n\n%s\n";
148    
149  if (! $xml->{'logentry'}) {  if (! $xml->{'logentry'}) {
150          print "no newer log entries in SubVersion repostory. CVS is current\n";          print "no newer log entries in Subversion repostory. CVS is current\n";
151          exit 0;          exit 0;
152  }  }
153    
154    # check if file exists in CVS/Entries
155    sub in_entries($) {
156            my $path = shift;
157            if ($path !~ m,^(.*?/*)([^/]+)$,) {
158                    die "can't split '$path' to dir and file!";
159            } else {
160                    my ($d,$f) = ($1,$2);
161                    if ($d !~ m,/$,) {
162                            $d .= "/";
163                    }
164                    open(E, $d."CVS/Entries") || die "can't open ${d}CVS/Entries: $!";
165                    while(<E>) {
166                            return(1) if (m,^/$f/,);
167                    }
168                    close(E);
169                    return 0;
170            }
171    }
172    
173  foreach my $e (@{$xml->{'logentry'}}) {  foreach my $e (@{$xml->{'logentry'}}) {
174          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'});
175          $rev = $e->{'revision'};          $rev = $e->{'revision'};
# Line 159  foreach my $e (@{$xml->{'logentry'}}) { Line 180  foreach my $e (@{$xml->{'logentry'}}) {
180          my $tmpsvn = $SVNROOT || die "BUG: SVNROOT empty!";          my $tmpsvn = $SVNROOT || die "BUG: SVNROOT empty!";
181          my $tmppath = $e->{'paths'}->{'path'}->[0]->{'content'} || die "BUG: tmppath empty!";          my $tmppath = $e->{'paths'}->{'path'}->[0]->{'content'} || die "BUG: tmppath empty!";
182          do {          do {
 print "## tmppath: $tmppath tmpsvn: $tmpsvn SVNREP: $SVNREP\n";  
183                  if ($tmpsvn =~ s,(/\w+/*)$,,) {                  if ($tmpsvn =~ s,(/\w+/*)$,,) {
184                          $SVNREP .= $1;                          $SVNREP .= $1;
185                  } else {                  } else {
186                          die "ERROR: can't deduce svn dir from $SVNROOT.\nUsing root of snv repository for current version instead of /trunk/ is not supported.\n";                          print "NOTICE: can't deduce svn dir from $SVNROOT - skipping\n";
187                            next;
188                  }                  }
189          } until ($tmppath =~ m/^$SVNREP/);          } until ($tmppath =~ m/^$SVNREP/);
190    
# Line 185  print "## tmppath: $tmppath tmpsvn: $tmp Line 206  print "## tmppath: $tmppath tmpsvn: $tmp
206                  }                  }
207    
208                  my $msg = $e->{'msg'};                  my $msg = $e->{'msg'};
209                  $msg =~ s/'/\\'/g;      # quote "                  $msg =~ s/'/'\\''/g;    # quote "
210    
211                  if ($action =~ /M/) {                  if ($action =~ /M/) {
212                          print "svn2cvs: modify $path -- nop\n";                          print "svn2cvs: modify $path -- nop\n";
# Line 196  print "## tmppath: $tmppath tmpsvn: $tmp Line 217  print "## tmppath: $tmppath tmpsvn: $tmp
217                                  chdir("$TMPDIR") || die "can't cd to $TMPDIR/$CVSREP: $!";                                  chdir("$TMPDIR") || die "can't cd to $TMPDIR/$CVSREP: $!";
218                                  log_system("$cvs checkout $CVSREP/$path", "cvs checkout of imported dir $path failed");                                  log_system("$cvs checkout $CVSREP/$path", "cvs checkout of imported dir $path failed");
219                                  chdir("$TMPDIR/$CVSREP") || die "can't cd back to $TMPDIR/$CVSREP: $!";                                  chdir("$TMPDIR/$CVSREP") || die "can't cd back to $TMPDIR/$CVSREP: $!";
220                            } elsif ($path =~ m,^(.+)/[^/]+$, && ! -e "$1/CVS/Root") {
221                                    my $dir = $1;
222                                    in_entries($dir) || log_system("$cvs add $dir", "cvs add of dir $dir failed");
223                                    in_entries($path) || log_system("$cvs add $path", "cvs add of $path failed");
224                          } else {                          } else {
225                                  log_system("$cvs add -m '$msg' $path", "cvs add of $path failed");                                  in_entries($path) || log_system("$cvs add $path", "cvs add of $path failed");
226                          }                          }
227                  } elsif ($action =~ /D/) {                  } elsif ($action =~ /D/) {
228                          log_system("$cvs delete -m '$msg' $path", "cvs delete of $path failed");                          unlink $path || die "can't delete $path: $!";
229                            log_system("$cvs delete $path", "cvs delete of $path failed");
230                  } else {                  } else {
231                          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";
232                  }                  }
# Line 212  print "## tmppath: $tmppath tmpsvn: $tmp Line 238  print "## tmppath: $tmppath tmpsvn: $tmp
238    
239          commit_svnrev($rev);          commit_svnrev($rev);
240  }  }
241    
242    __END__
243    
244    =pod
245    
246    =head1 NAME
247    
248    svn2cvs - save subversion commits to (read-only) cvs repository
249    
250    =head1 SYNOPSIS
251    
252      ./svn2cvs.pl SVN_URL CVSROOT CVSREPOSITORY
253    
254    Usage example (used to self-host this script):
255    
256      ./svn2cvs.pl file:///home/dpavlin/private/svn/svn2cvs/trunk/ \
257                   :pserver:dpavlin@cvs.tigris.org:/cvs svn2cvs/src
258    
259    =head1 DESCRIPTION
260    
261    This script will allow you to commit changes made to Subversion repository also to (read-only) CVS repository manually or from Subversion's C<post-commit> hook.
262    
263    It's using F<.svnrev> file (which will be created on first run) in
264    B<CVSROOT/CVSREPOSITORY> to store last Subversion revision which was
265    committed into CVS.
266    
267    One run will do following things:
268    
269    =over 4
270    
271    =item *
272    checkout B<CVSREPOSITORY> from B<CVSROOT> to temporary directory
273    
274    =item *
275    check if F<.svnrev> file exists and create it if it doesn't
276    
277    =item *
278    loop through all revisions from current in B<CVSROOT/CVSREPOSITORY> (using
279    F<.svnrev>) up to B<HEAD> (current one)
280    
281    =over 5
282    
283    =item *
284    checkout next Subversion revision from B<SVN_URL> over CVS checkout
285    temporary directory
286    
287    =item *
288    make modification (add and/or delete) done in that revision
289    
290    =item *
291    commit modification (added, deleted or modified files/dirs) while
292    preserving original message from CVS
293    
294    =item *
295    update F<.svnrev> to match current revision
296    
297    =back
298    
299    =item *
300    cleanup temporary directory
301    
302    =back
303    
304    If checkout fails for some reason (e.g. flaky ssh connection), you will
305    still have valid CVS repository, so all you have to do is run B<svn2cvs.pl>
306    again.
307    
308    =head1 WARNINGS
309    
310    "Cheap" copy operations in Subversion are not at all cheap in CVS. They will
311    create multiple copies of files in CVS repository!
312    
313    =head1 RELATED PROJECTS
314    
315    B<Subversion> L<http://subversion.tigris.org/> version control system that is a
316    compelling replacement for CVS in the open source community.
317    
318    B<cvs2svn> L<http://cvs2svn.tigris.org/> converts a CVS repository to a
319    Subversion repository. It is designed for one-time conversions, not for
320    repeated synchronizations between CVS and Subversion.
321    
322    =head1 AUTHOR
323    
324    Dobrica Pavlinusic <dpavlin@rot13.org>
325    
326    L<http://www.rot13.org/~dpavlin/>
327    
328    =head1 LICENSE
329    
330    This product is licensed under GNU Public License (GPL) v2 or later.
331    
332    =cut
333    

Legend:
Removed from v.11  
changed lines
  Added in v.15

  ViewVC Help
Powered by ViewVC 1.1.26