-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
It supersedes git-rename by adding functionality to move multiple files, directories or symlinks into another directory. It also provides according documentation. The implementation renames multiple files, using the arguments from the command line to produce an array of sources and destinations. In a first pass, all requested renames are checked for errors, and overwriting of existing files is only allowed with '-f'. The actual renaming is done in a second pass. This ensures that any error condition is checked before anything is changed. Signed-off-by: Josef Weidendorfer <Josef.Weidendorfer@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>
- Loading branch information
Josef Weidendorfer
authored and
Junio C Hamano
committed
Oct 24, 2005
1 parent
e2029eb
commit 1114b26
Showing
3 changed files
with
237 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
git-mv(1) | ||
========= | ||
|
||
NAME | ||
---- | ||
git-mv - Script used to move or rename a file, directory or symlink. | ||
|
||
|
||
SYNOPSIS | ||
-------- | ||
'git-mv' [-f] [-n] <source> <destination> | ||
'git-mv' [-f] [-k] [-n] <source> ... <destination directory> | ||
|
||
DESCRIPTION | ||
----------- | ||
This script is used to move or rename a file, directory or symlink. | ||
In the first form, it renames <source>, which must exist and be either | ||
a file, symlink or directory, to <destination>, which must not exist. | ||
In the second form, the last argument has to be an existing | ||
directory; the given sources will be moved into this directory. | ||
|
||
The index is updated after successful completion, but the change must still be | ||
committed. | ||
|
||
OPTIONS | ||
------- | ||
-f:: | ||
Force renaming or moving even targets exist | ||
-k:: | ||
Skip move or rename actions which would lead to an error | ||
condition. An error happens when a source is neither existing nor | ||
controlled by GIT, or when it would overwrite an existing | ||
file unless '-f' is given. | ||
-n:: | ||
Do nothing; only show what would happen | ||
|
||
|
||
Author | ||
------ | ||
Written by Linus Torvalds <torvalds@osdl.org> | ||
Rewritten by Ryan Anderson <ryan@michonline.com> | ||
Move functionality added by Josef Weidendorfer <Josef.Weidendorfer@gmx.de> | ||
|
||
Documentation | ||
-------------- | ||
Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>. | ||
|
||
GIT | ||
--- | ||
Part of the gitlink:git[7] suite | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
#!/usr/bin/perl | ||
# | ||
# Copyright 2005, Ryan Anderson <ryan@michonline.com> | ||
# Josef Weidendorfer <Josef.Weidendorfer@gmx.de> | ||
# | ||
# This file is licensed under the GPL v2, or a later version | ||
# at the discretion of Linus Torvalds. | ||
|
||
|
||
use warnings; | ||
use strict; | ||
use Getopt::Std; | ||
|
||
sub usage() { | ||
print <<EOT; | ||
$0 [-f] [-n] <source> <dest> | ||
$0 [-f] [-k] [-n] <source> ... <dest directory> | ||
In the first form, source must exist and be either a file, | ||
symlink or directory, dest must not exist. It renames source to dest. | ||
In the second form, the last argument has to be an existing | ||
directory; the given sources will be moved into this directory. | ||
Updates the git cache to reflect the change. | ||
Use "git commit" to make the change permanently. | ||
Options: | ||
-f Force renaming/moving, even if target exists | ||
-k Continue on error by skipping | ||
not-existing or not revision-controlled source | ||
-n Do nothing; show what would happen | ||
EOT | ||
exit(1); | ||
} | ||
|
||
# Sanity checks: | ||
my $GIT_DIR = $ENV{'GIT_DIR'} || ".git"; | ||
|
||
unless ( -d $GIT_DIR && -d $GIT_DIR . "/objects" && | ||
-d $GIT_DIR . "/objects/" && -d $GIT_DIR . "/refs") { | ||
print "Git repository not found."; | ||
usage(); | ||
} | ||
|
||
|
||
our ($opt_n, $opt_f, $opt_h, $opt_k, $opt_v); | ||
getopts("hnfkv") || usage; | ||
usage() if $opt_h; | ||
@ARGV >= 1 or usage; | ||
|
||
my (@srcArgs, @dstArgs, @srcs, @dsts); | ||
my ($src, $dst, $base, $dstDir); | ||
|
||
my $argCount = scalar @ARGV; | ||
if (-d $ARGV[$argCount-1]) { | ||
$dstDir = $ARGV[$argCount-1]; | ||
@srcArgs = @ARGV[0..$argCount-2]; | ||
|
||
foreach $src (@srcArgs) { | ||
$base = $src; | ||
$base =~ s/^.*\///; | ||
$dst = "$dstDir/". $base; | ||
push @dstArgs, $dst; | ||
} | ||
} | ||
else { | ||
if ($argCount != 2) { | ||
print "Error: moving to directory '" | ||
. $ARGV[$argCount-1] | ||
. "' not possible; not exisiting\n"; | ||
usage; | ||
} | ||
@srcArgs = ($ARGV[0]); | ||
@dstArgs = ($ARGV[1]); | ||
$dstDir = ""; | ||
} | ||
|
||
my (@allfiles,@srcfiles,@dstfiles); | ||
my $safesrc; | ||
my %overwritten; | ||
|
||
$/ = "\0"; | ||
open(F,"-|","git-ls-files","-z") | ||
or die "Failed to open pipe from git-ls-files: " . $!; | ||
|
||
@allfiles = map { chomp; $_; } <F>; | ||
close(F); | ||
|
||
|
||
my ($i, $bad); | ||
while(scalar @srcArgs > 0) { | ||
$src = shift @srcArgs; | ||
$dst = shift @dstArgs; | ||
$bad = ""; | ||
|
||
if ($opt_v) { | ||
print "Checking rename of '$src' to '$dst'\n"; | ||
} | ||
|
||
unless (-f $src || -l $src || -d $src) { | ||
$bad = "bad source '$src'"; | ||
} | ||
|
||
$overwritten{$dst} = 0; | ||
if (($bad eq "") && -e $dst) { | ||
$bad = "destination '$dst' already exists"; | ||
if (-f $dst && $opt_f) { | ||
print "Warning: $bad; will overwrite!\n"; | ||
$bad = ""; | ||
$overwritten{$dst} = 1; | ||
} | ||
} | ||
|
||
if (($bad eq "") && ($src eq $dstDir)) { | ||
$bad = "can not move directory '$src' into itself"; | ||
} | ||
|
||
if ($bad eq "") { | ||
$safesrc = quotemeta($src); | ||
@srcfiles = grep /^$safesrc(\/|$)/, @allfiles; | ||
if (scalar @srcfiles == 0) { | ||
$bad = "'$src' not under version control"; | ||
} | ||
} | ||
|
||
if ($bad ne "") { | ||
if ($opt_k) { | ||
print "Warning: $bad; skipping\n"; | ||
next; | ||
} | ||
print "Error: $bad\n"; | ||
usage(); | ||
} | ||
push @srcs, $src; | ||
push @dsts, $dst; | ||
} | ||
|
||
# Final pass: rename/move | ||
my (@deletedfiles,@addedfiles,@changedfiles); | ||
while(scalar @srcs > 0) { | ||
$src = shift @srcs; | ||
$dst = shift @dsts; | ||
|
||
if ($opt_n || $opt_v) { print "Renaming $src to $dst\n"; } | ||
if (!$opt_n) { | ||
rename($src,$dst) | ||
or die "rename failed: $!"; | ||
} | ||
|
||
$safesrc = quotemeta($src); | ||
@srcfiles = grep /^$safesrc(\/|$)/, @allfiles; | ||
@dstfiles = @srcfiles; | ||
s/^$safesrc(\/|$)/$dst$1/ for @dstfiles; | ||
|
||
push @deletedfiles, @srcfiles; | ||
if (scalar @srcfiles == 1) { | ||
if ($overwritten{$dst} ==1) { | ||
push @changedfiles, $dst; | ||
} else { | ||
push @addedfiles, $dst; | ||
} | ||
} | ||
else { | ||
push @addedfiles, @dstfiles; | ||
} | ||
} | ||
|
||
if ($opt_n) { | ||
print "Changed : ". join(", ", @changedfiles) ."\n"; | ||
print "Adding : ". join(", ", @addedfiles) ."\n"; | ||
print "Deleting : ". join(", ", @deletedfiles) ."\n"; | ||
exit(1); | ||
} | ||
|
||
my $rc; | ||
if (scalar @changedfiles >0) { | ||
$rc = system("git-update-index","--",@changedfiles); | ||
die "git-update-index failed to update changed files with code $?\n" if $rc; | ||
} | ||
if (scalar @addedfiles >0) { | ||
$rc = system("git-update-index","--add","--",@addedfiles); | ||
die "git-update-index failed to add new names with code $?\n" if $rc; | ||
} | ||
$rc = system("git-update-index","--remove","--",@deletedfiles); | ||
die "git-update-index failed to remove old names with code $?\n" if $rc; |