]> git.ipfire.org Git - thirdparty/git.git/blame - git-mv.perl
config.c: constness tightening to avoid compilation warning.
[thirdparty/git.git] / git-mv.perl
CommitLineData
1114b26e
JW
1#!/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;
3ae64dff
JW
16$0 [-f] [-n] <source> <destination>
17$0 [-f] [-n] [-k] <source> ... <destination directory>
1114b26e
JW
18EOT
19 exit(1);
20}
21
22# Sanity checks:
23my $GIT_DIR = $ENV{'GIT_DIR'} || ".git";
24
25unless ( -d $GIT_DIR && -d $GIT_DIR . "/objects" &&
26 -d $GIT_DIR . "/objects/" && -d $GIT_DIR . "/refs") {
3ae64dff
JW
27 print "Error: git repository not found.";
28 exit(1);
1114b26e
JW
29}
30
31
32our ($opt_n, $opt_f, $opt_h, $opt_k, $opt_v);
33getopts("hnfkv") || usage;
34usage() if $opt_h;
35@ARGV >= 1 or usage;
36
37my (@srcArgs, @dstArgs, @srcs, @dsts);
38my ($src, $dst, $base, $dstDir);
39
40my $argCount = scalar @ARGV;
41if (-d $ARGV[$argCount-1]) {
42 $dstDir = $ARGV[$argCount-1];
f676fa76
JW
43 # remove any trailing slash
44 $dstDir =~ s/\/$//;
1114b26e
JW
45 @srcArgs = @ARGV[0..$argCount-2];
46
47 foreach $src (@srcArgs) {
48 $base = $src;
49 $base =~ s/^.*\///;
50 $dst = "$dstDir/". $base;
51 push @dstArgs, $dst;
52 }
53}
54else {
55 if ($argCount != 2) {
56 print "Error: moving to directory '"
57 . $ARGV[$argCount-1]
58 . "' not possible; not exisiting\n";
3ae64dff 59 exit(1);
1114b26e
JW
60 }
61 @srcArgs = ($ARGV[0]);
62 @dstArgs = ($ARGV[1]);
63 $dstDir = "";
64}
65
66my (@allfiles,@srcfiles,@dstfiles);
67my $safesrc;
05ff5649 68my (%overwritten, %srcForDst);
1114b26e
JW
69
70$/ = "\0";
71open(F,"-|","git-ls-files","-z")
72 or die "Failed to open pipe from git-ls-files: " . $!;
73
74@allfiles = map { chomp; $_; } <F>;
75close(F);
76
77
78my ($i, $bad);
79while(scalar @srcArgs > 0) {
80 $src = shift @srcArgs;
81 $dst = shift @dstArgs;
82 $bad = "";
83
84 if ($opt_v) {
85 print "Checking rename of '$src' to '$dst'\n";
86 }
87
88 unless (-f $src || -l $src || -d $src) {
89 $bad = "bad source '$src'";
90 }
91
073dab13
JW
92 $safesrc = quotemeta($src);
93 @srcfiles = grep /^$safesrc(\/|$)/, @allfiles;
94
1114b26e
JW
95 $overwritten{$dst} = 0;
96 if (($bad eq "") && -e $dst) {
97 $bad = "destination '$dst' already exists";
073dab13
JW
98 if ($opt_f) {
99 # only files can overwrite each other: check both source and destination
100 if (-f $dst && (scalar @srcfiles == 1)) {
101 print "Warning: $bad; will overwrite!\n";
102 $bad = "";
103 $overwritten{$dst} = 1;
104 }
105 else {
106 $bad = "Can not overwrite '$src' with '$dst'";
107 }
1114b26e
JW
108 }
109 }
110
ca203ee7 111 if (($bad eq "") && ($dst =~ /^$src\//)) {
1114b26e
JW
112 $bad = "can not move directory '$src' into itself";
113 }
114
115 if ($bad eq "") {
1114b26e
JW
116 if (scalar @srcfiles == 0) {
117 $bad = "'$src' not under version control";
118 }
119 }
120
05ff5649
JW
121 if ($bad eq "") {
122 if (defined $srcForDst{$dst}) {
123 $bad = "can not move '$src' to '$dst'; already target of ";
124 $bad .= "'".$srcForDst{$dst}."'";
125 }
126 else {
127 $srcForDst{$dst} = $src;
128 }
129 }
130
1114b26e
JW
131 if ($bad ne "") {
132 if ($opt_k) {
133 print "Warning: $bad; skipping\n";
134 next;
135 }
136 print "Error: $bad\n";
3ae64dff 137 exit(1);
1114b26e
JW
138 }
139 push @srcs, $src;
140 push @dsts, $dst;
141}
142
143# Final pass: rename/move
144my (@deletedfiles,@addedfiles,@changedfiles);
f6bc189a 145$bad = "";
1114b26e
JW
146while(scalar @srcs > 0) {
147 $src = shift @srcs;
148 $dst = shift @dsts;
149
150 if ($opt_n || $opt_v) { print "Renaming $src to $dst\n"; }
151 if (!$opt_n) {
f6bc189a
JW
152 if (!rename($src,$dst)) {
153 $bad = "renaming '$src' failed: $!";
26169747
JW
154 if ($opt_k) {
155 print "Warning: skipped: $bad\n";
156 $bad = "";
157 next;
158 }
f6bc189a
JW
159 last;
160 }
1114b26e
JW
161 }
162
163 $safesrc = quotemeta($src);
164 @srcfiles = grep /^$safesrc(\/|$)/, @allfiles;
165 @dstfiles = @srcfiles;
166 s/^$safesrc(\/|$)/$dst$1/ for @dstfiles;
167
168 push @deletedfiles, @srcfiles;
169 if (scalar @srcfiles == 1) {
073dab13 170 # $dst can be a directory with 1 file inside
1114b26e 171 if ($overwritten{$dst} ==1) {
073dab13
JW
172 push @changedfiles, $dstfiles[0];
173
1114b26e 174 } else {
073dab13 175 push @addedfiles, $dstfiles[0];
1114b26e
JW
176 }
177 }
178 else {
179 push @addedfiles, @dstfiles;
180 }
181}
182
183if ($opt_n) {
3ae64dff 184 if (@changedfiles) {
1114b26e 185 print "Changed : ". join(", ", @changedfiles) ."\n";
3ae64dff
JW
186 }
187 if (@addedfiles) {
1114b26e 188 print "Adding : ". join(", ", @addedfiles) ."\n";
3ae64dff
JW
189 }
190 if (@deletedfiles) {
1114b26e 191 print "Deleting : ". join(", ", @deletedfiles) ."\n";
3ae64dff 192 }
1114b26e 193}
3ae64dff
JW
194else {
195 if (@changedfiles) {
f359ae42
AL
196 open(H, "| git-update-index -z --stdin")
197 or die "git-update-index failed to update changed files with code $!\n";
198 foreach my $fileName (@changedfiles) {
199 print H "$fileName\0";
200 }
201 close(H);
3ae64dff
JW
202 }
203 if (@addedfiles) {
f359ae42
AL
204 open(H, "| git-update-index --add -z --stdin")
205 or die "git-update-index failed to add new names with code $!\n";
206 foreach my $fileName (@addedfiles) {
207 print H "$fileName\0";
208 }
209 close(H);
3ae64dff
JW
210 }
211 if (@deletedfiles) {
f359ae42
AL
212 open(H, "| git-update-index --remove -z --stdin")
213 or die "git-update-index failed to remove old names with code $!\n";
214 foreach my $fileName (@deletedfiles) {
215 print H "$fileName\0";
216 }
217 close(H);
3ae64dff 218 }
1114b26e 219}
f6bc189a
JW
220
221if ($bad ne "") {
222 print "Error: $bad\n";
223 exit(1);
224}