git svn: attempt to create empty dirs on clone+rebase
We parse unhandled.log files for empty_dir statements and make a best effort attempt to recreate empty directories on fresh clones and rebase. This should cover the majority of cases where users work off a single branch or for projects where branches do not differ in empty directories. Since this cannot affect "normal" git commands like "checkout" or "reset", so users switching between branches in a single working directory should use the new "git svn mkdirs" command after switching branches. Signed-off-by: Eric Wong <normalperson@yhbt.net>
This commit is contained in:
parent
e2f8617b26
commit
6111b93499
@ -320,6 +320,13 @@ Any other arguments are passed directly to 'git log'
|
||||
directories. The output is suitable for appending to
|
||||
the $GIT_DIR/info/exclude file.
|
||||
|
||||
'mkdirs'::
|
||||
Attempts to recreate empty directories that core git cannot track
|
||||
based on information in $GIT_DIR/svn/<refname>/unhandled.log files.
|
||||
Empty directories are automatically recreated when using
|
||||
"git svn clone" and "git svn rebase", so "mkdirs" is intended
|
||||
for use after commands like "git checkout" or "git reset".
|
||||
|
||||
'commit-diff'::
|
||||
Commits the diff of two tree-ish arguments from the
|
||||
command-line. This command does not rely on being inside an `git svn
|
||||
|
45
git-svn.perl
45
git-svn.perl
@ -168,6 +168,9 @@ my %cmd = (
|
||||
'Create a .gitignore per svn:ignore',
|
||||
{ 'revision|r=i' => \$_revision
|
||||
} ],
|
||||
'mkdirs' => [ \&cmd_mkdirs ,
|
||||
"recreate empty directories after a checkout",
|
||||
{ 'revision|r=i' => \$_revision } ],
|
||||
'propget' => [ \&cmd_propget,
|
||||
'Print the value of a property on a file or directory',
|
||||
{ 'revision|r=i' => \$_revision } ],
|
||||
@ -769,6 +772,7 @@ sub cmd_rebase {
|
||||
$_fetch_all ? $gs->fetch_all : $gs->fetch;
|
||||
}
|
||||
command_noisy(rebase_cmd(), $gs->refname);
|
||||
$gs->mkemptydirs;
|
||||
}
|
||||
|
||||
sub cmd_show_ignore {
|
||||
@ -830,6 +834,12 @@ sub cmd_create_ignore {
|
||||
});
|
||||
}
|
||||
|
||||
sub cmd_mkdirs {
|
||||
my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
|
||||
$gs ||= Git::SVN->new;
|
||||
$gs->mkemptydirs($_revision);
|
||||
}
|
||||
|
||||
sub canonicalize_path {
|
||||
my ($path) = @_;
|
||||
my $dot_slash_added = 0;
|
||||
@ -1196,6 +1206,7 @@ sub post_fetch_checkout {
|
||||
command_noisy(qw/read-tree -m -u -v HEAD HEAD/);
|
||||
print STDERR "Checked out HEAD:\n ",
|
||||
$gs->full_url, " r", $gs->last_rev, "\n";
|
||||
$gs->mkemptydirs($gs->last_rev);
|
||||
}
|
||||
|
||||
sub complete_svn_url {
|
||||
@ -2724,6 +2735,34 @@ sub do_fetch {
|
||||
$self->make_log_entry($rev, \@parents, $ed);
|
||||
}
|
||||
|
||||
sub mkemptydirs {
|
||||
my ($self, $r) = @_;
|
||||
my %empty_dirs = ();
|
||||
|
||||
open my $fh, '<', "$self->{dir}/unhandled.log" or return;
|
||||
binmode $fh or croak "binmode: $!";
|
||||
while (<$fh>) {
|
||||
if (defined $r && /^r(\d+)$/) {
|
||||
last if $1 > $r;
|
||||
} elsif (/^ \+empty_dir: (.+)$/) {
|
||||
$empty_dirs{$1} = 1;
|
||||
} elsif (/^ \-empty_dir: (.+)$/) {
|
||||
delete $empty_dirs{$1};
|
||||
}
|
||||
}
|
||||
close $fh;
|
||||
foreach my $d (sort keys %empty_dirs) {
|
||||
$d = uri_decode($d);
|
||||
next if -d $d;
|
||||
if (-e _) {
|
||||
warn "$d exists but is not a directory\n";
|
||||
} else {
|
||||
print "creating empty directory: $d\n";
|
||||
mkpath([$d]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub get_untracked {
|
||||
my ($self, $ed) = @_;
|
||||
my @out;
|
||||
@ -3556,6 +3595,12 @@ sub uri_encode {
|
||||
$f
|
||||
}
|
||||
|
||||
sub uri_decode {
|
||||
my ($f) = @_;
|
||||
$f =~ s#%([0-9a-fA-F]{2})#chr(hex($1))#eg;
|
||||
$f
|
||||
}
|
||||
|
||||
sub remove_username {
|
||||
$_[0] =~ s{^([^:]*://)[^@]+@}{$1};
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ test_expect_success 'init and fetch repository' '
|
||||
'
|
||||
|
||||
test_expect_success 'create file in existing ugly and empty dir' '
|
||||
mkdir "#{bad_directory_name}" &&
|
||||
mkdir -p "#{bad_directory_name}" &&
|
||||
echo hi > "#{bad_directory_name}/ foo" &&
|
||||
git update-index --add "#{bad_directory_name}/ foo" &&
|
||||
git commit -m "new file in ugly parent" &&
|
||||
@ -37,7 +37,7 @@ test_expect_success 'rename pretty file' '
|
||||
git update-index --add pretty &&
|
||||
git commit -m "pretty :x" &&
|
||||
git svn dcommit &&
|
||||
mkdir regular_dir_name &&
|
||||
mkdir -p regular_dir_name &&
|
||||
git mv pretty regular_dir_name/pretty &&
|
||||
git commit -m "moved pretty file" &&
|
||||
git svn dcommit
|
||||
|
85
t/t9146-git-svn-empty-dirs.sh
Executable file
85
t/t9146-git-svn-empty-dirs.sh
Executable file
@ -0,0 +1,85 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2009 Eric Wong
|
||||
|
||||
test_description='git svn creates empty directories'
|
||||
. ./lib-git-svn.sh
|
||||
|
||||
test_expect_success 'initialize repo' '
|
||||
for i in a b c d d/e d/e/f "weird file name"
|
||||
do
|
||||
svn_cmd mkdir -m "mkdir $i" "$svnrepo"/"$i"
|
||||
done
|
||||
'
|
||||
|
||||
test_expect_success 'clone' 'git svn clone "$svnrepo" cloned'
|
||||
|
||||
test_expect_success 'empty directories exist' '
|
||||
(
|
||||
cd cloned &&
|
||||
for i in a b c d d/e d/e/f "weird file name"
|
||||
do
|
||||
if ! test -d "$i"
|
||||
then
|
||||
echo >&2 "$i does not exist"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'more emptiness' '
|
||||
svn_cmd mkdir -m "bang bang" "$svnrepo"/"! !"
|
||||
'
|
||||
|
||||
test_expect_success 'git svn rebase creates empty directory' '
|
||||
( cd cloned && git svn rebase )
|
||||
test -d cloned/"! !"
|
||||
'
|
||||
|
||||
test_expect_success 'git svn mkdirs recreates empty directories' '
|
||||
(
|
||||
cd cloned &&
|
||||
rm -r * &&
|
||||
git svn mkdirs &&
|
||||
for i in a b c d d/e d/e/f "weird file name" "! !"
|
||||
do
|
||||
if ! test -d "$i"
|
||||
then
|
||||
echo >&2 "$i does not exist"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'git svn mkdirs -r works' '
|
||||
(
|
||||
cd cloned &&
|
||||
rm -r * &&
|
||||
git svn mkdirs -r7 &&
|
||||
for i in a b c d d/e d/e/f "weird file name"
|
||||
do
|
||||
if ! test -d "$i"
|
||||
then
|
||||
echo >&2 "$i does not exist"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if test -d "! !"
|
||||
then
|
||||
echo >&2 "$i should not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git svn mkdirs -r8 &&
|
||||
if ! test -d "! !"
|
||||
then
|
||||
echo >&2 "$i not exist"
|
||||
exit 1
|
||||
fi
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
Loading…
Reference in New Issue
Block a user