diff options
author | Eric Wong <normalperson@yhbt.net> | 2009-11-15 18:57:16 -0800 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2009-11-15 19:30:06 -0800 |
commit | 6111b934991f3ea670ac2442806c976defc7b61c (patch) | |
tree | cb892f1efc6601e63f640d6a51f222e89c60a08c | |
parent | e2f8617b266e320fd58ab584cae2ebe9906daaac (diff) | |
download | git-6111b934991f3ea670ac2442806c976defc7b61c.tar.gz git-6111b934991f3ea670ac2442806c976defc7b61c.tar.xz |
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>
-rw-r--r-- | Documentation/git-svn.txt | 7 | ||||
-rwxr-xr-x | git-svn.perl | 45 | ||||
-rwxr-xr-x | t/t9115-git-svn-dcommit-funky-renames.sh | 4 | ||||
-rwxr-xr-x | t/t9146-git-svn-empty-dirs.sh | 85 |
4 files changed, 139 insertions, 2 deletions
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 1812890a7..db00ed43b 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -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 diff --git a/git-svn.perl b/git-svn.perl index ea922ace1..ab0a8dd09 100755 --- a/git-svn.perl +++ b/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}; } diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh index 9be7aefae..767799e7a 100755 --- a/t/t9115-git-svn-dcommit-funky-renames.sh +++ b/t/t9115-git-svn-dcommit-funky-renames.sh @@ -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 diff --git a/t/t9146-git-svn-empty-dirs.sh b/t/t9146-git-svn-empty-dirs.sh new file mode 100755 index 000000000..5948544ec --- /dev/null +++ b/t/t9146-git-svn-empty-dirs.sh @@ -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 |