🌐 AI搜索 & 代理 主页
blob: 75aa8feeb6201c54e55bfaca0cc178c53891e776 [file] [log] [blame]
Josef Weidendorfer1114b262005-10-23 16:15:341#!/usr/bin/perl
2#
3# Copyright 2005, Ryan Anderson <ryan@michonline.com>
4# Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
5#
6# This file is licensed under the GPL v2, or a later version
7# at the discretion of Linus Torvalds.
8
9
10use warnings;
11use strict;
12use Getopt::Std;
13
14sub usage() {
15 print <<EOT;
Josef Weidendorfer3ae64df2005-11-27 20:58:5216$0 [-f] [-n] <source> <destination>
17$0 [-f] [-n] [-k] <source> ... <destination directory>
Josef Weidendorfer1114b262005-10-23 16:15:3418EOT
19 exit(1);
20}
21
Josef Weidendorfer1114b262005-10-23 16:15:3422our ($opt_n, $opt_f, $opt_h, $opt_k, $opt_v);
23getopts("hnfkv") || usage;
24usage() if $opt_h;
25@ARGV >= 1 or usage;
26
Josef Weidendorfer5e6f85f2006-03-01 17:16:3627my $GIT_DIR = `git rev-parse --git-dir`;
28exit 1 if $?; # rev-parse would have given "not a git dir" message.
29chomp($GIT_DIR);
30
Josef Weidendorfer1114b262005-10-23 16:15:3431my (@srcArgs, @dstArgs, @srcs, @dsts);
32my ($src, $dst, $base, $dstDir);
33
Josef Weidendorfer9e7c73d2006-03-01 18:09:2334# remove any trailing slash in arguments
35for (@ARGV) { s/\/*$//; }
36
Josef Weidendorfer1114b262005-10-23 16:15:3437my $argCount = scalar @ARGV;
38if (-d $ARGV[$argCount-1]) {
39 $dstDir = $ARGV[$argCount-1];
Josef Weidendorfer1114b262005-10-23 16:15:3440 @srcArgs = @ARGV[0..$argCount-2];
Josef Weidendorfer9e7c73d2006-03-01 18:09:2341
Josef Weidendorfer1114b262005-10-23 16:15:3442 foreach $src (@srcArgs) {
43 $base = $src;
44 $base =~ s/^.*\///;
45 $dst = "$dstDir/". $base;
46 push @dstArgs, $dst;
47 }
48}
49else {
Josef Weidendorfer5e6f85f2006-03-01 17:16:3650 if ($argCount < 2) {
51 print "Error: need at least two arguments\n";
52 exit(1);
53 }
54 if ($argCount > 2) {
Josef Weidendorfer1114b262005-10-23 16:15:3455 print "Error: moving to directory '"
56 . $ARGV[$argCount-1]
Josef Weidendorfer5e6f85f2006-03-01 17:16:3657 . "' not possible; not existing\n";
Josef Weidendorfer3ae64df2005-11-27 20:58:5258 exit(1);
Josef Weidendorfer1114b262005-10-23 16:15:3459 }
60 @srcArgs = ($ARGV[0]);
61 @dstArgs = ($ARGV[1]);
62 $dstDir = "";
63}
64
Josef Weidendorfer90924d52006-03-03 16:23:3265my $subdir_prefix = `git rev-parse --show-prefix`;
66chomp($subdir_prefix);
67
68# run in git base directory, so that git-ls-files lists all revisioned files
69chdir "$GIT_DIR/..";
70
Josef Weidendorfer9e7c73d2006-03-01 18:09:2371# normalize paths, needed to compare against versioned files and update-index
72# also, this is nicer to end-users by doing ".//a/./b/.//./c" ==> "a/b/c"
73for (@srcArgs, @dstArgs) {
Josef Weidendorfer90924d52006-03-03 16:23:3274 # prepend git prefix as we run from base directory
75 $_ = $subdir_prefix.$_;
Josef Weidendorfer9e7c73d2006-03-01 18:09:2376 s|^\./||;
77 s|/\./|/| while (m|/\./|);
78 s|//+|/|g;
79 # Also "a/b/../c" ==> "a/c"
80 1 while (s,(^|/)[^/]+/\.\./,$1,);
81}
82
Josef Weidendorfer1114b262005-10-23 16:15:3483my (@allfiles,@srcfiles,@dstfiles);
84my $safesrc;
Josef Weidendorfer05ff5642005-10-25 12:20:4585my (%overwritten, %srcForDst);
Josef Weidendorfer1114b262005-10-23 16:15:3486
87$/ = "\0";
Junio C Hamano23c99d82005-12-06 02:14:3488open(F, 'git-ls-files -z |')
Josef Weidendorfer1114b262005-10-23 16:15:3489 or die "Failed to open pipe from git-ls-files: " . $!;
90
91@allfiles = map { chomp; $_; } <F>;
92close(F);
93
94
95my ($i, $bad);
96while(scalar @srcArgs > 0) {
97 $src = shift @srcArgs;
98 $dst = shift @dstArgs;
99 $bad = "";
100
Junio C Hamano9a0e6732006-02-19 07:42:03101 for ($src, $dst) {
102 # Be nicer to end-users by doing ".//a/./b/.//./c" ==> "a/b/c"
103 s|^\./||;
104 s|/\./|/| while (m|/\./|);
105 s|//+|/|g;
106 # Also "a/b/../c" ==> "a/c"
107 1 while (s,(^|/)[^/]+/\.\./,$1,);
108 }
109
Josef Weidendorfer1114b262005-10-23 16:15:34110 if ($opt_v) {
111 print "Checking rename of '$src' to '$dst'\n";
112 }
113
114 unless (-f $src || -l $src || -d $src) {
115 $bad = "bad source '$src'";
116 }
117
Josef Weidendorfer073dab12005-11-23 11:04:23118 $safesrc = quotemeta($src);
119 @srcfiles = grep /^$safesrc(\/|$)/, @allfiles;
120
Josef Weidendorfer1114b262005-10-23 16:15:34121 $overwritten{$dst} = 0;
122 if (($bad eq "") && -e $dst) {
123 $bad = "destination '$dst' already exists";
Josef Weidendorfer073dab12005-11-23 11:04:23124 if ($opt_f) {
125 # only files can overwrite each other: check both source and destination
126 if (-f $dst && (scalar @srcfiles == 1)) {
127 print "Warning: $bad; will overwrite!\n";
128 $bad = "";
129 $overwritten{$dst} = 1;
130 }
131 else {
132 $bad = "Can not overwrite '$src' with '$dst'";
133 }
Josef Weidendorfer1114b262005-10-23 16:15:34134 }
135 }
136
Junio C Hamano90109b32005-11-28 10:54:05137 if (($bad eq "") && ($dst =~ /^$safesrc\//)) {
Josef Weidendorfer1114b262005-10-23 16:15:34138 $bad = "can not move directory '$src' into itself";
139 }
140
141 if ($bad eq "") {
Josef Weidendorfer1114b262005-10-23 16:15:34142 if (scalar @srcfiles == 0) {
143 $bad = "'$src' not under version control";
144 }
145 }
146
Josef Weidendorfer05ff5642005-10-25 12:20:45147 if ($bad eq "") {
148 if (defined $srcForDst{$dst}) {
149 $bad = "can not move '$src' to '$dst'; already target of ";
150 $bad .= "'".$srcForDst{$dst}."'";
151 }
152 else {
153 $srcForDst{$dst} = $src;
154 }
155 }
156
Josef Weidendorfer1114b262005-10-23 16:15:34157 if ($bad ne "") {
158 if ($opt_k) {
159 print "Warning: $bad; skipping\n";
160 next;
161 }
162 print "Error: $bad\n";
Josef Weidendorfer3ae64df2005-11-27 20:58:52163 exit(1);
Josef Weidendorfer1114b262005-10-23 16:15:34164 }
165 push @srcs, $src;
166 push @dsts, $dst;
167}
168
169# Final pass: rename/move
170my (@deletedfiles,@addedfiles,@changedfiles);
Josef Weidendorferf6bc1892005-11-27 21:04:14171$bad = "";
Josef Weidendorfer1114b262005-10-23 16:15:34172while(scalar @srcs > 0) {
173 $src = shift @srcs;
174 $dst = shift @dsts;
175
176 if ($opt_n || $opt_v) { print "Renaming $src to $dst\n"; }
177 if (!$opt_n) {
Josef Weidendorferf6bc1892005-11-27 21:04:14178 if (!rename($src,$dst)) {
179 $bad = "renaming '$src' failed: $!";
Josef Weidendorfer26169742005-11-27 21:11:33180 if ($opt_k) {
181 print "Warning: skipped: $bad\n";
182 $bad = "";
183 next;
184 }
Josef Weidendorferf6bc1892005-11-27 21:04:14185 last;
186 }
Josef Weidendorfer1114b262005-10-23 16:15:34187 }
188
189 $safesrc = quotemeta($src);
190 @srcfiles = grep /^$safesrc(\/|$)/, @allfiles;
191 @dstfiles = @srcfiles;
192 s/^$safesrc(\/|$)/$dst$1/ for @dstfiles;
193
194 push @deletedfiles, @srcfiles;
195 if (scalar @srcfiles == 1) {
Josef Weidendorfer073dab12005-11-23 11:04:23196 # $dst can be a directory with 1 file inside
Josef Weidendorfer1114b262005-10-23 16:15:34197 if ($overwritten{$dst} ==1) {
Josef Weidendorfer073dab12005-11-23 11:04:23198 push @changedfiles, $dstfiles[0];
199
Josef Weidendorfer1114b262005-10-23 16:15:34200 } else {
Josef Weidendorfer073dab12005-11-23 11:04:23201 push @addedfiles, $dstfiles[0];
Josef Weidendorfer1114b262005-10-23 16:15:34202 }
203 }
204 else {
205 push @addedfiles, @dstfiles;
206 }
207}
208
209if ($opt_n) {
Josef Weidendorfer3ae64df2005-11-27 20:58:52210 if (@changedfiles) {
Josef Weidendorfer1114b262005-10-23 16:15:34211 print "Changed : ". join(", ", @changedfiles) ."\n";
Josef Weidendorfer3ae64df2005-11-27 20:58:52212 }
213 if (@addedfiles) {
Josef Weidendorfer1114b262005-10-23 16:15:34214 print "Adding : ". join(", ", @addedfiles) ."\n";
Josef Weidendorfer3ae64df2005-11-27 20:58:52215 }
216 if (@deletedfiles) {
Josef Weidendorfer1114b262005-10-23 16:15:34217 print "Deleting : ". join(", ", @deletedfiles) ."\n";
Josef Weidendorfer3ae64df2005-11-27 20:58:52218 }
Josef Weidendorfer1114b262005-10-23 16:15:34219}
Josef Weidendorfer3ae64df2005-11-27 20:58:52220else {
221 if (@changedfiles) {
Alexander Litvinovf359ae42005-11-23 10:19:41222 open(H, "| git-update-index -z --stdin")
223 or die "git-update-index failed to update changed files with code $!\n";
224 foreach my $fileName (@changedfiles) {
225 print H "$fileName\0";
226 }
227 close(H);
Josef Weidendorfer3ae64df2005-11-27 20:58:52228 }
229 if (@addedfiles) {
Alexander Litvinovf359ae42005-11-23 10:19:41230 open(H, "| git-update-index --add -z --stdin")
231 or die "git-update-index failed to add new names with code $!\n";
232 foreach my $fileName (@addedfiles) {
233 print H "$fileName\0";
234 }
235 close(H);
Josef Weidendorfer3ae64df2005-11-27 20:58:52236 }
237 if (@deletedfiles) {
Alexander Litvinovf359ae42005-11-23 10:19:41238 open(H, "| git-update-index --remove -z --stdin")
239 or die "git-update-index failed to remove old names with code $!\n";
240 foreach my $fileName (@deletedfiles) {
241 print H "$fileName\0";
242 }
243 close(H);
Josef Weidendorfer3ae64df2005-11-27 20:58:52244 }
Alexander Litvinovf359ae42005-11-23 10:19:41245}
Josef Weidendorferf6bc1892005-11-27 21:04:14246
247if ($bad ne "") {
248 print "Error: $bad\n";
249 exit(1);
250}