/[drupal]/contributions/tricks/cvs_rename/cvs_rename.pl
ViewVC logotype

Contents of /contributions/tricks/cvs_rename/cvs_rename.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (show annotations) (download) (as text)
Tue Apr 22 16:05:49 2008 UTC (19 months ago) by dww
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +28 -2 lines
File MIME type: text/x-perl
Changes to use 'cvs admin -s' to mark every revision of the new name
of the file dead, except for a new revision where the file is "added"
back to HEAD. This way, date-based checkouts always work correctly.
1 #!/usr/bin/env perl -w
2 use strict 'subs';
3 use Getopt::Std;
4
5 ($prog = $0) =~ s|.*/||;
6 $usage = <<END;
7 usage:
8 $prog [-vn][-r repository] oldname newname [oldname newname ...]
9 or
10 $prog [-vn] -x.old.new [except ...]
11 END
12
13 # $Header: /u/s/o/solomon/util/RCS/cvs_rename.pl,v 1.9 1997/11/29 12:27:52 solomon Exp solomon $
14
15 =head1 NAME
16
17 cvs_rename - program to rename files that are under control of CVS
18
19 =head1 SYNOPSIS
20
21 cvs_rename I<[-n][-v][-r repository]> old-name new-name [old-name new-name ...]
22 cvs_rename I<[-vn] -x.old.new> [except ...]
23
24 =head1 DESCRIPTION
25
26 Renaming a file that is under the control of CVS is not so simple as
27
28 mv old-name new-name
29
30 CVS should have a command to do that, but it doesn't (at least as of release
31 1.9). Instead, it suggests no fewer than three different ways of accomplishing
32 the task in the online documenation (topic "Moving files" in the info doc).
33 The first and simplest is to I<cvs remove> the old version and I<cvs add> the
34 second. Unfortunately, it leaves no record of the connection between the two,
35 and I<cvs log> doesn't do the right thing. The second way is simply to rename
36 the history file ($CVSROOT/whatever/old-name,v), but that has problems as well
37 (see the CVS info for details). The third is a variant of that that leaves
38 old-name,v intact. That's what this program does.
39
40 The first version of the call simply renames I<old-name> in the current
41 directory to I<new-name>.
42 The second version renames I<foo.old> to I<foo.new> for each file I<foo.old>
43 in the current directory.
44 Any remaining arguments are names of files that should I<not> be renamed.
45 It either case, it is a fatal error if a desination file
46 exists either in the current directory or in the repository.
47
48 =head1 OPTIONS
49
50 =over 4
51
52 =item [-n]
53
54 Don't actually do it, just indicate what would happen if you did.
55 (Like I<make -n>).
56
57 =item [-v]
58
59 Verbose output about what's happening.
60
61 =item [-m]
62
63 Additional text to prepend for the rename commit message.
64
65 =back
66
67 =head1 AUTHOR
68
69 Marvin Solomon (solomn@cs.wisc.edu), June 1997
70
71 =cut
72
73
74 # Argv processing
75
76 die $usage unless
77 getopts("vnx:r:m:");
78
79 # -v: verbose
80 $opt_v = 0 unless defined $opt_v;
81 # -n: don't do it (like make -n)
82 $opt_n = 0 unless defined $opt_n;
83 # -m: additional commit message to prepend
84 $opt_m = "" unless defined $opt_m;
85 # -r: directory containing the repository
86 chomp($opt_r = `cat CVS/Repository`) unless $opt_r;
87
88 # Find out where we are
89 die "cannot find repository; giving up"
90 unless $opt_r;
91
92 # Actually do the renames
93
94 if ($opt_x) {
95 die "bad -x option\n"
96 unless ($oldext,$newext) = $opt_x =~ /^\.([^.]+)\.([^.]+)$/;
97 foreach $file (@ARGV) { $except{$file} = 1; }
98 die "opendir" unless opendir(DIR,'.');
99 @files = grep { /\.$oldext$/ && !$except{$_} } readdir(DIR);
100 closedir DIR;
101 unless(@files) {
102 print STDERR "nothing to be renamed\n";
103 exit 0;
104 }
105
106 # Make sure everything will go without a hitch before doing anything
107 foreach $old (@files) {
108 $new = $old;
109 $new =~ s/$oldext$/$newext/;
110 die "$new already exists\n" if -e "$new";
111 die "$opt_r/$old,v: $!\n" unless -e "$opt_r/$old,v";
112 die "$opt_r/$new,v already exists\n" if -e "$opt_r/$new,v";
113 $tags{$old} = check_status($old);
114 }
115
116 # Ok, let 'er rip
117 $commit = '';
118 foreach $old (@files) {
119 $new = $old;
120 $new =~ s/$oldext$/$newext/;
121 do_rename($old,$new,$tags{$old});
122 $commit .= " $old $new";
123 }
124 $msg = "$opt_m";
125 $msg .= "Renamed from *.$oldext to *.$newext";
126 do_sys("cvs commit -f -m \"$msg\" $commit");
127 }
128 else { # not opt_x
129 die "wrong number of arguments\n$usage"
130 unless (@ARGV > 0) && ((@ARGV % 2) == 0);
131
132 # Make sure everything will go without a hitch before doing anything
133 @args = @ARGV;
134 while ($old = shift()) {
135 $new = shift();
136 die "$new already exists\n" if -e "$new";
137 die "$opt_r/$old,v: $!\n" unless -e "$opt_r/$old,v";
138 die "$opt_r/$new,v already exists\n" if -e "$opt_r/$new,v";
139 $tags{$old} = check_status($old);
140 }
141 @ARGV = @args;
142
143 # Ok, let 'er rip
144 $commit = '';
145 $msg = '';
146 while ($old = shift()) {
147 $new = shift();
148 do_rename($old,$new,$tags{$old});
149 if ($msg) {
150 $msg .= " and from $old to $new";
151 }
152 else {
153 $msg = "$opt_m";
154 $msg .= "Renamed from $old to $new";
155 }
156 $commit .= " $old $new";
157 }
158 do_sys("cvs commit -f -m \"$msg\" $commit");
159 }
160 exit;
161
162 # Make sure file to be renamed is up-to-date with respect to the repository
163 # Return list of tags from the cvs status command.
164 sub check_status {
165 local($old) = @_;
166 local($status, $info);
167
168 die "cvs status: $!\n"
169 unless $info = `cvs status -v $old`;
170 die "cannot parse cvs status"
171 unless $info =~ /^\=+\nFile.*Status: (.*)/;
172 $status = $1;
173 die "cannot rename; file $old is $status, not Up-to-date\n"
174 unless $status eq 'Up-to-date';
175
176 # Generate a list of tags in the old version
177 die "cannot parse cvs status"
178 unless $info =~ s/.*Existing Tags:\n//s;
179 return $info;
180 }
181
182 sub do_rename {
183 local ($old, $new, $info) = @_;
184 local (@revisions);
185
186 # 1. Copy the file in the repository
187 do_sys("cp $opt_r/$old,v $opt_r/$new,v");
188 do_sys("rm $old");
189
190 # 2. Make the version under the old name obsolete.
191 do_sys("cvs remove $old");
192
193 # 3. Get the latest version under the new name.
194 do_sys("cvs update $new");
195
196 # 4. Remove all tags from the new version
197 unless ($info =~ /No Tags/) {
198 while ($info =~ s/\s*(\S+)\s*\((\w+):.*\n//) {
199 $tag = $1;
200 $branch = $2;
201 $arg = '-d';
202 if( $branch =~ /branch/ ) {
203 $arg .= 'B';
204 }
205 do_sys("cvs tag $arg $tag $new");
206 }
207 }
208
209 # 5. Find all the revisions of the new file.
210 die "cvs log: $!\n"
211 unless @logs = `cvs log -N $new`;
212 foreach $line (@logs) {
213 if ($line =~ /^revision\s+(\S+)/) {
214 push(@revisions, $1);
215 }
216 }
217
218 # 6. Save a copy of the latest file so we can add it again.
219 do_sys("cp $new $new.cvstmp");
220
221 # 7. Mark all those revisions of the new file dead status.
222 foreach $rev (@revisions) {
223 do_sys("cvs admin -s dead:$rev $new");
224 }
225
226 # 8. Make CVS unconfused about the local copy again.
227 do_sys("cvs update $new");
228 do_sys("mv $new.cvstmp $new");
229
230 # 9. Officially add the new file so it's marked live.
231 do_sys("cvs add $new");
232
233 } # do_rename
234
235 sub do_sys {
236 local ($cmd) = @_;
237 print STDERR "+ $cmd\n" if $opt_v;
238 return if $opt_n;
239 system($cmd);
240 die "$cmd: $!" if $?;
241 }

  ViewVC Help
Powered by ViewVC 1.1.2