* [PATCH] git-mv: fix moves into a subdir from outside
From: Josef Weidendorfer @ 2006-03-03 16:23 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
git-mv needs to be run from the base directory so that
the check if a file is under revision also covers files
outside of a subdirectory. Previously, e.g. in the git repo,
cd Documentation; git-mv ../README .
produced the error
Error: '../README' not under version control
The test is extended for this case; it previously only tested
one direction.
Signed-off-by: Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
---
git-mv.perl | 8 ++++++++
t/t7001-mv.sh | 18 ++++++++++++++++--
2 files changed, 24 insertions(+), 2 deletions(-)
08d21abe95064934ea559b88801415e09b19f628
diff --git a/git-mv.perl b/git-mv.perl
index f3e859a..0a63860 100755
--- a/git-mv.perl
+++ b/git-mv.perl
@@ -62,9 +62,17 @@ else {
$dstDir = "";
}
+my $subdir_prefix = `git rev-parse --show-prefix`;
+chomp($subdir_prefix);
+
+# run in git base directory, so that git-ls-files lists all revisioned files
+chdir "$GIT_DIR/..";
+
# normalize paths, needed to compare against versioned files and update-index
# also, this is nicer to end-users by doing ".//a/./b/.//./c" ==> "a/b/c"
for (@srcArgs, @dstArgs) {
+ # prepend git prefix as we run from base directory
+ $_ = $subdir_prefix.$_;
s|^\./||;
s|/\./|/| while (m|/\./|);
s|//+|/|g;
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 43d74c5..811a479 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -11,17 +11,31 @@ test_expect_success \
git-commit -m add -a'
test_expect_success \
- 'moving the file' \
+ 'moving the file out of subdirectory' \
'cd path0 && git-mv COPYING ../path1/COPYING'
# in path0 currently
test_expect_success \
'commiting the change' \
- 'cd .. && git-commit -m move -a'
+ 'cd .. && git-commit -m move-out -a'
test_expect_success \
'checking the commit' \
'git-diff-tree -r -M --name-status HEAD^ HEAD | \
grep -E "^R100.+path0/COPYING.+path1/COPYING"'
+test_expect_success \
+ 'moving the file back into subdirectory' \
+ 'cd path0 && git-mv ../path1/COPYING COPYING'
+
+# in path0 currently
+test_expect_success \
+ 'commiting the change' \
+ 'cd .. && git-commit -m move-in -a'
+
+test_expect_success \
+ 'checking the commit' \
+ 'git-diff-tree -r -M --name-status HEAD^ HEAD | \
+ grep -E "^R100.+path1/COPYING.+path0/COPYING"'
+
test_done
--
1.2.0.g719b
^ permalink raw reply related
* Re: [PATCH] Add --temp and --stage=all options to checkout-index.
From: Shawn Pearce @ 2006-03-03 15:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmzg83xro.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote:
> Shawn Pearce <spearce@spearce.org> writes:
>
> > Unfortunately this change lead me down a path which changed the core
> > checkout code also used by apply and read-tree.
>
> ... which makes it much harder to swallow without careful
> inspection X-<.
>
> I think the patch only appears much bigger than it actually is,
> because of reindentation effect coming from "if (to-temp-file)".
> However, I am too tired to carefully examine them tonight, so I
> hope you do not mind my postponing this for now.
Not at all. I read over the diff before sending it and thought it
made the patch look much worse than it really is, simply because
of the reindentation. :-|
Sometimes good 'ole diff ain't that great for conveying a change.
--
Shawn.
^ permalink raw reply
* Re: bug?: stgit creates (unneccessary?) conflicts when pulling
From: Karl Hasselström @ 2006-03-03 14:24 UTC (permalink / raw)
To: git
In-Reply-To: <b0943d9e0602281445w7160d915y@mail.gmail.com>
On 2006-02-28 22:45:56 +0000, Catalin Marinas wrote:
> On 27/02/06, Catalin Marinas <catalin.marinas@gmail.com> wrote:
>
> > An idea (untested, I don't even know whether it's feasible) would
> > be to check which patches were merged by reverse-applying them
> > starting with the last. In this situation, all the merged patches
> > should just revert their changes. You only need to do a git-diff
> > between the bottom and the top of the patch and git-apply the
> > output (maybe without even modifying the tree). If this operation
> > succeeds, the patch was integrated and you don't even need to push
> > it.
>
> I attached another patch that should work properly. It also pushes
> empty patches on the stack if they were merged upstream (a 'stg
> clean' is required to remove them). This is useful for the push
> --undo command if you are not happy with the result.
>
> I'll try this patch for a bit more before pushing into the
> repository.
It appears to work for me. I still had to fix things up manually when
pulling the uncommit patch though, since you had made a minor change
in "uncommit.py":
Pushing patch "uncommit"...Error: File "stgit/commands/uncommit.py" added in branches but different
Is there a way to make stgit not fall on its face when faced with this
situation? Surely it ought to be possible to create a merged file with
conflict markers? (I realize this is harder when there is no common
ancestor, but these files are 95% identical!)
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
^ permalink raw reply
* Re: bug?: stgit creates (unneccessary?) conflicts when pulling
From: Karl Hasselström @ 2006-03-03 14:13 UTC (permalink / raw)
To: git
In-Reply-To: <b0943d9e0603010953iccf64a4v@mail.gmail.com>
On 2006-03-01 17:53:53 +0000, Catalin Marinas wrote:
> This won't solve the problem since testing whether patch "a" was
> merged upstream will fail because its reverse won't apply cleanly
> onto the upstream HEAD. Of course, you can try combination of
> upstream commits and local patches but it's not really feasible.
>
> As I said, this method doesn't solve all the upstream merge
> situations but it is OK for most of them.
We could perhaps do a little better. Instead of just noting whether
the patch vanishes when reverse-applied, save the top and bottom of
the patch as reverse-applied, and then replace the patch with the
reverse of that. If the patch vanishes, this does what your patch does
right now. If the patch does not vanish, all that remains is the parts
that upstream didn't accept. (And as before, if the patch didn't
reverse-apply cleanly, assume upstream hasn't accepted it at all yet.)
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
^ permalink raw reply
* Re: [PATCH 1/3] cg-mv doesn't work with bash 3.1.7 due to excessive quotes
From: Pavel Roskin @ 2006-03-03 14:11 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vbqwo3xo4.fsf@assigned-by-dhcp.cox.net>
On Thu, 2006-03-02 at 21:27 -0800, Junio C Hamano wrote:
> Pavel Roskin <proski@gnu.org> writes:
>
> > - ARGS2["${#ARGS2[@]}"]="$_git_relpath${arg%/}"
> > + ARGS2[${#ARGS2[@]}]="$_git_relpath${arg%/}"
>
> Is this an application bug? It looks like a workaround for a
> bug in the shell...
Indeed, bash 3.00.16 (FC4) is fine with the original cg-mv. On the
other hand, bash 3.1.7 (FC development) doesn't even like this:
$ arg["0"]=0
bash: "0": syntax error: operand expected (error token is ""0"")
I don't see any relevant information in the NEWS file, so even if it's
no a bug, it's an undocumented feature :-)
Anyway, the quotes are excessive, bash is (sort of) correct to complain
about it, and I don't see any other instances of quoting array arguments
in cogito.
The quotes in question have always existed in cg-mv, they were not added
to work around anything.
--
Regards,
Pavel Roskin
^ permalink raw reply
* workaround fat/ntfs deficiencies for t3600-rm.sh (git-rm)
From: Alex Riesen @ 2006-03-03 10:20 UTC (permalink / raw)
To: Git Mailing List; +Cc: Junio C Hamano, Carl Worth
[-- Attachment #1: Type: text/plain, Size: 243 bytes --]
Signed-off-by: Alex Riesen <ariesen@harmanbecker.com>
---
chmod u-w and even chmod a-w dont work on fat and ntfs.
The actually do something, but rm a file from that directory
will succeed anyway. That's windows permission model to you...
[-- Attachment #2: 0001-workaround-fat-ntfs-deficiencies-for-t3600-rm.sh-git-rm.txt --]
[-- Type: text/plain, Size: 1900 bytes --]
>From nobody Mon Sep 17 00:00:00 2001
From: Alex Riesen <raa.lkml@gmail.com>
Date: Fri Mar 3 11:15:05 2006 +0100
Subject: workaround fat/ntfs deficiencies for t3600-rm.sh (git-rm)
---
t/t3600-rm.sh | 23 +++++++++++++++++------
1 files changed, 17 insertions(+), 6 deletions(-)
583a9faeab3a200fc970577458b7827d86aa7df1
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index cabfadd..d1947e1 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -8,11 +8,20 @@ test_description='Test of the various op
. ./test-lib.sh
# Setup some files to be removed, some with funny characters
-touch -- foo bar baz 'space embedded' 'tab embedded' 'newline
-embedded' -q
-git-add -- foo bar baz 'space embedded' 'tab embedded' 'newline
-embedded' -q
-git-commit -m "add files"
+touch -- foo bar baz 'space embedded' -q
+git-add -- foo bar baz 'space embedded' -q
+git-commit -m "add normal files"
+test_tabs=y
+if touch -- 'tab embedded' 'newline
+embedded'
+then
+git-add -- 'tab embedded' 'newline
+embedded'
+git-commit -m "add files with tabs and newlines"
+else
+ say 'Your filesystem does not allow tabs in filenames.'
+ test_tabs=n
+fi
test_expect_success \
'Pre-check that foo exists and is in index before git-rm foo' \
@@ -42,16 +51,18 @@ test_expect_success \
'Test that "git-rm -- -q" succeeds (remove a file that looks like an option)' \
'git-rm -- -q'
-test_expect_success \
+test "$test_tabs" = y && test_expect_success \
"Test that \"git-rm -f\" succeeds with embedded space, tab, or newline characters." \
"git-rm -f 'space embedded' 'tab embedded' 'newline
embedded'"
+if test "$test_tabs" = y; then
chmod u-w .
test_expect_failure \
'Test that "git-rm -f" fails if its rm fails' \
'git-rm -f baz'
chmod u+w .
+fi
test_expect_success \
'When the rm in "git-rm -f" fails, it should not remove the file from the index' \
--
1.2.4.ga091
^ permalink raw reply related
* [PATCH] send-email: accept --no-signed-off-by-cc as the documentation states
From: Eric Wong @ 2006-03-03 9:28 UTC (permalink / raw)
To: junkio, ryan; +Cc: git, Eric Wong
--no-signed-off-cc is still supported, for backwards compatibility
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
git-send-email.perl | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
374f3e5c7fd49c4949df9b29ed03287e6ceb2e2c
diff --git a/git-send-email.perl b/git-send-email.perl
index b0d095b..7c8d512 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -54,7 +54,7 @@ my $rc = GetOptions("from=s" => \$from,
"compose" => \$compose,
"quiet" => \$quiet,
"suppress-from" => \$suppress_from,
- "no-signed-off-cc" => \$no_signed_off_cc,
+ "no-signed-off-cc|no-signed-off-by-cc" => \$no_signed_off_cc,
);
# Now, let's fill any that aren't set in with defaults:
--
1.2.3.g4676
^ permalink raw reply related
* [PATCH 8/9] contrib/git-svn: add --id/-i=$GIT_SVN_ID command-line switch
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <11413776092493-git-send-email-normalperson@yhbt.net>
I ended up using GIT_SVN_ID far more than I ever thought I
would. Typing less is good.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 19 +++++++++++--------
1 files changed, 11 insertions(+), 8 deletions(-)
1d3dc63f7ed276863c71f9a212471658f359ef75
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index 041791b..db199a3 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -10,13 +10,6 @@ use vars qw/ $AUTHOR $VERSION
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
$VERSION = '0.10.0';
$GIT_DIR = $ENV{GIT_DIR} || "$ENV{PWD}/.git";
-$GIT_SVN = $ENV{GIT_SVN_ID} || 'git-svn';
-$GIT_SVN_INDEX = "$GIT_DIR/$GIT_SVN/index";
-$ENV{GIT_DIR} ||= $GIT_DIR;
-$SVN_URL = undef;
-$REV_DIR = "$GIT_DIR/$GIT_SVN/revs";
-$SVN_WC = "$GIT_DIR/$GIT_SVN/tree";
-
# make sure the svn binary gives consistent output between locales and TZs:
$ENV{TZ} = 'UTC';
$ENV{LC_ALL} = 'C';
@@ -78,7 +71,17 @@ foreach (keys %cmd) {
my %opts;
%opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
-GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version ) or exit 1;
+GetOptions(%opts, 'help|H|h' => \$_help,
+ 'version|V' => \$_version,
+ 'id|i=s' => \$GIT_SVN) or exit 1;
+
+$GIT_SVN ||= $ENV{GIT_SVN_ID} || 'git-svn';
+$GIT_SVN_INDEX = "$GIT_DIR/$GIT_SVN/index";
+$ENV{GIT_DIR} ||= $GIT_DIR;
+$SVN_URL = undef;
+$REV_DIR = "$GIT_DIR/$GIT_SVN/revs";
+$SVN_WC = "$GIT_DIR/$GIT_SVN/tree";
+
usage(0) if $_help;
version() if $_version;
usage(1) unless defined $cmd;
--
1.2.3.g4676
^ permalink raw reply related
* [PATCH 2/9] contrib/git-svn: several small bug fixes and changes
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <11413776074148-git-send-email-normalperson@yhbt.net>
* Fixed manually-edited commit messages not going to
remotes/git-svn on sequential commits after the sequential
commit optimization.
* format help correctly after adding 'show-ignore'
* sha1_short regexp matches down to 4 hex characters
(from git-rev-parse --short documentation)
* Print the first line of the commit message when we commit to
SVN next to the sha1.
* Document 'T' (type change) in the comments
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 27 +++++++++++++++++----------
1 files changed, 17 insertions(+), 10 deletions(-)
43965ace71422148acb1bae488d78cbcfc5ca65e
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index 1f9a470..67368a5 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -32,7 +32,7 @@ use Getopt::Long qw/:config gnu_getopt n
use File::Spec qw//;
use POSIX qw/strftime/;
my $sha1 = qr/[a-f\d]{40}/;
-my $sha1_short = qr/[a-f\d]{6,40}/;
+my $sha1_short = qr/[a-f\d]{4,40}/;
my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
$_find_copies_harder, $_l, $_version, $_upgrade);
my (@_branch_from, %tree_map);
@@ -90,12 +90,12 @@ Usage: $0 <command> [options] [arguments
Available commands:
foreach (sort keys %cmd) {
- print $fd ' ',pack('A10',$_),$cmd{$_}->[1],"\n";
+ print $fd ' ',pack('A13',$_),$cmd{$_}->[1],"\n";
}
print $fd <<"";
\nGIT_SVN_ID may be set in the environment to an arbitrary identifier if
you're tracking multiple SVN branches/repositories in one git repository
-and want to keep them separate.
+and want to keep them separate. See git-svn(1) for more information.
exit $exit;
}
@@ -245,7 +245,7 @@ sub commit {
print "Reading from stdin...\n";
@commits = ();
while (<STDIN>) {
- if (/\b([a-f\d]{6,40})\b/) {
+ if (/\b($sha1_short)\b/) {
unshift @commits, $1;
}
}
@@ -267,7 +267,6 @@ sub commit {
chdir $SVN_WC or croak $!;
my $svn_current_rev = svn_info('.')->{'Last Changed Rev'};
foreach my $c (@revs) {
- print "Committing $c\n";
my $mods = svn_checkout_tree($svn_current_rev, $c);
if (scalar @$mods == 0) {
print "Skipping, no changes detected\n";
@@ -514,7 +513,7 @@ sub svn_checkout_tree {
my ($svn_rev, $treeish) = @_;
my $from = file_to_s("$REV_DIR/$svn_rev");
assert_svn_wc_clean($svn_rev,$from);
- print "diff-tree '$from' '$treeish'\n";
+ print "diff-tree $from $treeish\n";
my $pid = open my $diff_fh, '-|';
defined $pid or croak $!;
if ($pid == 0) {
@@ -525,7 +524,7 @@ sub svn_checkout_tree {
}
my $mods = parse_diff_tree($diff_fh);
unless (@$mods) {
- # git can do empty commits, SVN doesn't allow it...
+ # git can do empty commits, but SVN doesn't allow it...
return $mods;
}
my ($rm, $add) = precommit_check($mods);
@@ -612,7 +611,7 @@ sub svn_commit_tree {
my ($svn_rev, $commit) = @_;
my $commit_msg = "$GIT_DIR/$GIT_SVN/.svn-commit.tmp.$$";
my %log_msg = ( msg => '' );
- open my $msg, '>', $commit_msg or croak $!;
+ open my $msg, '>', $commit_msg or croak $!;
chomp(my $type = `git-cat-file -t $commit`);
if ($type eq 'commit') {
@@ -627,7 +626,6 @@ sub svn_commit_tree {
if (!$in_msg) {
$in_msg = 1 if (/^\s*$/);
} else {
- $log_msg{msg} .= $_;
print $msg $_ or croak $!;
}
}
@@ -639,6 +637,15 @@ sub svn_commit_tree {
my $editor = $ENV{VISUAL} || $ENV{EDITOR} || 'vi';
system($editor, $commit_msg);
}
+
+ # file_to_s removes all trailing newlines, so just use chomp() here:
+ open $msg, '<', $commit_msg or croak $!;
+ { local $/; chomp($log_msg{msg} = <$msg>); }
+ close $msg or croak $!;
+
+ my ($oneline) = ($log_msg{msg} =~ /([^\n\r]+)/);
+ print "Committing $commit: $oneline\n";
+
my @ci_output = safe_qx(qw(svn commit -F),$commit_msg);
my ($committed) = grep(/^Committed revision \d+\./,@ci_output);
unlink $commit_msg;
@@ -1037,7 +1044,7 @@ diff-index line ($m hash)
mode_a => first column of diff-index output, no leading ':',
mode_b => second column of diff-index output,
sha1_b => sha1sum of the final blob,
- chg => change type [MCRAD],
+ chg => change type [MCRADT],
file_a => original file name of a file (iff chg is 'C' or 'R')
file_b => new/current file name of a file (any chg)
}
--
1.2.3.g4676
^ permalink raw reply related
* [PATCH 9/9] contrib/git-svn: better documenting of CLI switches
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <11413776092524-git-send-email-normalperson@yhbt.net>
Also, fix a asciidoc formatting error
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 29 +++++++++++++++--------------
contrib/git-svn/git-svn.txt | 17 ++++++++++++++++-
2 files changed, 31 insertions(+), 15 deletions(-)
65d8e4920084c96f82b4604ded1bd4e4fa91d3d8
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index db199a3..808b933 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -60,16 +60,7 @@ for (my $i = 0; $i < @ARGV; $i++) {
}
};
-# we may be called as git-svn-(command), or git-svn(command).
-foreach (keys %cmd) {
- if (/git\-svn\-?($_)(?:\.\w+)?$/) {
- $cmd = $1;
- last;
- }
-}
-
-my %opts;
-%opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
+my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
GetOptions(%opts, 'help|H|h' => \$_help,
'version|V' => \$_version,
@@ -97,15 +88,25 @@ sub usage {
print $fd <<"";
git-svn - bidirectional operations between a single Subversion tree and git
Usage: $0 <command> [options] [arguments]\n
-Available commands:
+
+ print $fd "Available commands:\n" unless $cmd;
foreach (sort keys %cmd) {
+ next if $cmd && $cmd ne $_;
print $fd ' ',pack('A13',$_),$cmd{$_}->[1],"\n";
+ foreach (keys %{$cmd{$_}->[2]}) {
+ # prints out arguments as they should be passed:
+ my $x = s#=s$## ? '<arg>' : s#=i$## ? '<num>' : '';
+ print $fd ' ' x 17, join(', ', map { length $_ > 1 ?
+ "--$_" : "-$_" }
+ split /\|/,$_)," $x\n";
+ }
}
print $fd <<"";
-\nGIT_SVN_ID may be set in the environment to an arbitrary identifier if
-you're tracking multiple SVN branches/repositories in one git repository
-and want to keep them separate. See git-svn(1) for more information.
+\nGIT_SVN_ID may be set in the environment or via the --id/-i switch to an
+arbitrary identifier if you're tracking multiple SVN branches/repositories in
+one git repository and want to keep them separate. See git-svn(1) for more
+information.
exit $exit;
}
diff --git a/contrib/git-svn/git-svn.txt b/contrib/git-svn/git-svn.txt
index 7306048..8e9a971 100644
--- a/contrib/git-svn/git-svn.txt
+++ b/contrib/git-svn/git-svn.txt
@@ -116,6 +116,8 @@ OPTIONS
They are both passed directly to git-diff-tree see
git-diff-tree(1) for more information.
+ADVANCED OPTIONS
+----------------
-b<refname>::
--branch <refname>::
Used with 'fetch' or 'commit'.
@@ -131,8 +133,21 @@ OPTIONS
This option may be specified multiple times, once for each
branch.
+-i<GIT_SVN_ID>::
+--id <GIT_SVN_ID>::
+ This sets GIT_SVN_ID (instead of using the environment). See
+ the section on "Tracking Multiple Repositories or Branches" for
+ more information on using GIT_SVN_ID.
+
COMPATIBILITY OPTIONS
---------------------
+--upgrade::
+ Only used with the 'rebuild' command.
+
+ Run this if you used an old version of git-svn that used
+ 'git-svn-HEAD' instead of 'remotes/git-svn' as the branch
+ for tracking the remote.
+
--no-ignore-externals::
Only used with the 'fetch' and 'rebuild' command.
@@ -177,7 +192,7 @@ Tracking and contributing to an Subversi
git-svn commit remotes/git-svn..my-branch
# Something is committed to SVN, pull the latest into your branch::
git-svn fetch && git pull . remotes/git-svn
-# Append svn:ignore settings to the default git exclude file:
+# Append svn:ignore settings to the default git exclude file::
git-svn show-ignore >> .git/info/exclude
DESIGN PHILOSOPHY
--
1.2.3.g4676
^ permalink raw reply related
* [PATCH 4/9] contrib/git-svn: allow --authors-file to be specified
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <11413776082010-git-send-email-normalperson@yhbt.net>
Syntax is compatible with git-svnimport and git-cvsimport:
normalperson = Eric Wong <normalperson@yhbt.net>
If this option is specified and git-svn encounters an SVN
committer name that it cannot parse, it git-svn will abort.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 40 ++++++++++++++++++++++++++++++++--------
1 files changed, 32 insertions(+), 8 deletions(-)
c501f8378dfb5529993755caaf99ca632418e382
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index edae9d4..c2b4ee9 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -34,8 +34,8 @@ use POSIX qw/strftime/;
my $sha1 = qr/[a-f\d]{40}/;
my $sha1_short = qr/[a-f\d]{4,40}/;
my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
- $_find_copies_harder, $_l, $_version, $_upgrade);
-my (@_branch_from, %tree_map);
+ $_find_copies_harder, $_l, $_version, $_upgrade, $_authors);
+my (@_branch_from, %tree_map, %users);
GetOptions( 'revision|r=s' => \$_revision,
'no-ignore-externals' => \$_no_ignore_ext,
@@ -46,6 +46,7 @@ GetOptions( 'revision|r=s' => \$_revisio
'help|H|h' => \$_help,
'branch|b=s' => \@_branch_from,
'find-copies-harder' => \$_find_copies_harder,
+ 'authors-file|authors|A=s' => \$_authors,
'l=i' => \$_l,
'version|V' => \$_version,
'no-stop-on-copy' => \$_no_stop_copy );
@@ -73,6 +74,19 @@ foreach (keys %cmd) {
last;
}
}
+
+# '<svn username> = real-name <email address>' mapping based on git-svnimport:
+if ($_authors) {
+ open my $authors, '<', $_authors or die "Can't open $_authors $!\n";
+ while (<$authors>) {
+ chomp;
+ next unless /^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/;
+ my ($user, $name, $email) = ($1, $2, $3);
+ $users{$user} = [$name, $email];
+ }
+ close $authors or croak $!;
+}
+
usage(0) if $_help;
version() if $_version;
usage(1) unless (defined $cmd);
@@ -740,6 +754,10 @@ sub svn_log_raw {
author => $author,
lines => $lines,
msg => '' );
+ if (defined $_authors && ! defined $users{$author}) {
+ die "Author: $author not defined in ",
+ "$_authors file\n";
+ }
push @svn_log, \%log_msg;
$state = 'msg_start';
next;
@@ -884,12 +902,8 @@ sub git_commit {
$msg_fh->flush == 0 or croak $!;
seek $msg_fh, 0, 0 or croak $!;
- $ENV{GIT_AUTHOR_NAME} = $ENV{GIT_COMMITTER_NAME} =
- $log_msg->{author};
- $ENV{GIT_AUTHOR_EMAIL} = $ENV{GIT_COMMITTER_EMAIL} =
- $log_msg->{author}."\@$uuid";
- $ENV{GIT_AUTHOR_DATE} = $ENV{GIT_COMMITTER_DATE} =
- $log_msg->{date};
+ set_commit_env($log_msg, $uuid);
+
my @exec = ('git-commit-tree',$tree);
push @exec, '-p', $_ foreach @exec_parents;
open STDIN, '<&', $msg_fh or croak $!;
@@ -915,6 +929,16 @@ sub git_commit {
return $commit;
}
+sub set_commit_env {
+ my ($log_msg, $uuid) = @_;
+ my $author = $log_msg->{author};
+ my ($name,$email) = defined $users{$author} ? @{$users{$author}}
+ : ($author,"$author\@$uuid");
+ $ENV{GIT_AUTHOR_NAME} = $ENV{GIT_COMMITTER_NAME} = $name;
+ $ENV{GIT_AUTHOR_EMAIL} = $ENV{GIT_COMMITTER_EMAIL} = $email;
+ $ENV{GIT_AUTHOR_DATE} = $ENV{GIT_COMMITTER_DATE} = $log_msg->{date};
+}
+
sub apply_mod_line_blob {
my $m = shift;
if ($m->{mode_b} =~ /^120/) {
--
1.2.3.g4676
^ permalink raw reply related
* [PATCH 7/9] contrib/git-svn: avoid re-reading the repository uuid, it never changes
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <11413776092820-git-send-email-normalperson@yhbt.net>
If it does change, we're screwed anyways as SVN will refuse to
commit or update. We also never access more than one SVN
repository per-invocation, so we can store it as a global, too.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 27 ++++++++++++---------------
1 files changed, 12 insertions(+), 15 deletions(-)
3dc689059bd5cffa12bb2b8cdc0f1965d5f6cee2
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index 69b6be3..041791b 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -4,7 +4,7 @@
use warnings;
use strict;
use vars qw/ $AUTHOR $VERSION
- $SVN_URL $SVN_INFO $SVN_WC
+ $SVN_URL $SVN_INFO $SVN_WC $SVN_UUID
$GIT_SVN_INDEX $GIT_SVN
$GIT_DIR $REV_DIR/;
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
@@ -114,7 +114,6 @@ sub version {
sub rebuild {
$SVN_URL = shift or undef;
- my $repo_uuid;
my $newest_rev = 0;
if ($_upgrade) {
sys('git-update-ref',"refs/remotes/$GIT_SVN","$GIT_SVN-HEAD");
@@ -150,7 +149,7 @@ sub rebuild {
# if we merged or otherwise started elsewhere, this is
# how we break out of it
- next if (defined $repo_uuid && ($uuid ne $repo_uuid));
+ next if (defined $SVN_UUID && ($uuid ne $SVN_UUID));
next if (defined $SVN_URL && ($url ne $SVN_URL));
print "r$rev = $c\n";
@@ -159,7 +158,7 @@ sub rebuild {
croak "SVN repository location required: $url\n";
}
$SVN_URL ||= $url;
- $repo_uuid ||= setup_git_svn();
+ $SVN_UUID ||= setup_git_svn();
$latest = $rev;
}
assert_revision_eq_or_unknown($rev, $c);
@@ -252,7 +251,7 @@ sub commit {
print "Reading from stdin...\n";
@commits = ();
while (<STDIN>) {
- if (/\b($sha1_short)\b/) {
+ if (/\b($sha1_short)\b/o) {
unshift @commits, $1;
}
}
@@ -320,14 +319,14 @@ sub setup_git_svn {
mkpath(["$GIT_DIR/$GIT_SVN/info"]);
mkpath([$REV_DIR]);
s_to_file($SVN_URL,"$GIT_DIR/$GIT_SVN/info/url");
- my $uuid = svn_info($SVN_URL)->{'Repository UUID'} or
+ $SVN_UUID = svn_info($SVN_URL)->{'Repository UUID'} or
croak "Repository UUID unreadable\n";
- s_to_file($uuid,"$GIT_DIR/$GIT_SVN/info/uuid");
+ s_to_file($SVN_UUID,"$GIT_DIR/$GIT_SVN/info/uuid");
open my $fd, '>>', "$GIT_DIR/$GIT_SVN/info/exclude" or croak $!;
print $fd '.svn',"\n";
close $fd or croak $!;
- return $uuid;
+ return $SVN_UUID;
}
sub assert_svn_wc_clean {
@@ -850,9 +849,7 @@ sub git_commit {
my ($log_msg, @parents) = @_;
assert_revision_unknown($log_msg->{revision});
my $out_fh = IO::File->new_tmpfile or croak $!;
- my $info = svn_info('.');
- my $uuid = $info->{'Repository UUID'};
- defined $uuid or croak "Unable to get Repository UUID\n";
+ $SVN_UUID ||= svn_info('.')->{'Repository UUID'};
map_tree_joins() if (@_branch_from && !%tree_map);
@@ -891,11 +888,11 @@ sub git_commit {
my $msg_fh = IO::File->new_tmpfile or croak $!;
print $msg_fh $log_msg->{msg}, "\ngit-svn-id: ",
"$SVN_URL\@$log_msg->{revision}",
- " $uuid\n" or croak $!;
+ " $SVN_UUID\n" or croak $!;
$msg_fh->flush == 0 or croak $!;
seek $msg_fh, 0, 0 or croak $!;
- set_commit_env($log_msg, $uuid);
+ set_commit_env($log_msg);
my @exec = ('git-commit-tree',$tree);
push @exec, '-p', $_ foreach @exec_parents;
@@ -923,10 +920,10 @@ sub git_commit {
}
sub set_commit_env {
- my ($log_msg, $uuid) = @_;
+ my ($log_msg) = @_;
my $author = $log_msg->{author};
my ($name,$email) = defined $users{$author} ? @{$users{$author}}
- : ($author,"$author\@$uuid");
+ : ($author,"$author\@$SVN_UUID");
$ENV{GIT_AUTHOR_NAME} = $ENV{GIT_COMMITTER_NAME} = $name;
$ENV{GIT_AUTHOR_EMAIL} = $ENV{GIT_COMMITTER_EMAIL} = $email;
$ENV{GIT_AUTHOR_DATE} = $ENV{GIT_COMMITTER_DATE} = $log_msg->{date};
--
1.2.3.g4676
^ permalink raw reply related
* [PATCH 5/9] contrib/git-svn: cleanup option parsing
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <11413776082506-git-send-email-normalperson@yhbt.net>
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 65 +++++++++++++++++++++++-------------------
1 files changed, 35 insertions(+), 30 deletions(-)
a080e189728de9a7aa834b61205df9d8de1025ba
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index c2b4ee9..5d547e8 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -24,6 +24,7 @@ $ENV{LC_ALL} = 'C';
# If SVN:: library support is added, please make the dependencies
# optional and preserve the capability to use the command-line client.
# use eval { require SVN::... } to make it lazy load
+# We don't use any modules not in the standard Perl distribution:
use Carp qw/croak/;
use IO::File qw//;
use File::Basename qw/dirname basename/;
@@ -37,26 +38,25 @@ my ($_revision,$_stdin,$_no_ignore_ext,$
$_find_copies_harder, $_l, $_version, $_upgrade, $_authors);
my (@_branch_from, %tree_map, %users);
-GetOptions( 'revision|r=s' => \$_revision,
- 'no-ignore-externals' => \$_no_ignore_ext,
- 'stdin|' => \$_stdin,
- 'edit|e' => \$_edit,
- 'rmdir' => \$_rmdir,
- 'upgrade' => \$_upgrade,
- 'help|H|h' => \$_help,
+my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext,
'branch|b=s' => \@_branch_from,
- 'find-copies-harder' => \$_find_copies_harder,
- 'authors-file|authors|A=s' => \$_authors,
- 'l=i' => \$_l,
- 'version|V' => \$_version,
- 'no-stop-on-copy' => \$_no_stop_copy );
+ 'authors-file|A=s' => \$_authors );
my %cmd = (
- fetch => [ \&fetch, "Download new revisions from SVN" ],
- init => [ \&init, "Initialize and fetch (import)"],
- commit => [ \&commit, "Commit git revisions to SVN" ],
- 'show-ignore' => [ \&show_ignore, "Show svn:ignore listings" ],
- rebuild => [ \&rebuild, "Rebuild git-svn metadata (after git clone)" ],
- help => [ \&usage, "Show help" ],
+ fetch => [ \&fetch, "Download new revisions from SVN",
+ { 'revision|r=s' => \$_revision, %fc_opts } ],
+ init => [ \&init, "Initialize and fetch (import)", { } ],
+ commit => [ \&commit, "Commit git revisions to SVN",
+ { 'stdin|' => \$_stdin,
+ 'edit|e' => \$_edit,
+ 'rmdir' => \$_rmdir,
+ 'find-copies-harder' => \$_find_copies_harder,
+ 'l=i' => \$_l,
+ %fc_opts,
+ } ],
+ 'show-ignore' => [ \&show_ignore, "Show svn:ignore listings", { } ],
+ rebuild => [ \&rebuild, "Rebuild git-svn metadata (after git clone)",
+ { 'no-ignore-externals' => \$_no_ignore_ext,
+ 'upgrade' => \$_upgrade } ],
);
my $cmd;
for (my $i = 0; $i < @ARGV; $i++) {
@@ -75,21 +75,14 @@ foreach (keys %cmd) {
}
}
-# '<svn username> = real-name <email address>' mapping based on git-svnimport:
-if ($_authors) {
- open my $authors, '<', $_authors or die "Can't open $_authors $!\n";
- while (<$authors>) {
- chomp;
- next unless /^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/;
- my ($user, $name, $email) = ($1, $2, $3);
- $users{$user} = [$name, $email];
- }
- close $authors or croak $!;
-}
+my %opts;
+%opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
+GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version ) or exit 1;
usage(0) if $_help;
version() if $_version;
-usage(1) unless (defined $cmd);
+usage(1) unless defined $cmd;
+load_authors() if $_authors;
svn_check_ignore_externals();
$cmd{$cmd}->[0]->(@ARGV);
exit 0;
@@ -1047,6 +1040,18 @@ sub map_tree_joins {
}
}
+# '<svn username> = real-name <email address>' mapping based on git-svnimport:
+sub load_authors {
+ open my $authors, '<', $_authors or die "Can't open $_authors $!\n";
+ while (<$authors>) {
+ chomp;
+ next unless /^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/;
+ my ($user, $name, $email) = ($1, $2, $3);
+ $users{$user} = [$name, $email];
+ }
+ close $authors or croak $!;
+}
+
__END__
Data structures:
--
1.2.3.g4676
^ permalink raw reply related
* [PATCH 6/9] contrib/git-svn: create a more recent master if one does not exist
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <11413776081545-git-send-email-normalperson@yhbt.net>
In a new repository, the initial fetch creates a master branch
if one does not exist so HEAD has something to point to.
It now creates a master at the end of the initial fetch run,
pointing to the latest revision. Previously it pointed to the
first revision imported, which is generally less useful.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
7d3cf853ffbe0d1ce8a15fa5ac3dad793ddb5021
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index 5d547e8..69b6be3 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -224,9 +224,6 @@ sub fetch {
sys(@svn_co, $SVN_URL, $SVN_WC);
chdir $SVN_WC or croak $!;
$last_commit = git_commit($base, @parents);
- unless (-f "$GIT_DIR/refs/heads/master") {
- sys(qw(git-update-ref refs/heads/master),$last_commit);
- }
assert_svn_wc_clean($base->{revision}, $last_commit);
} else {
chdir $SVN_WC or croak $!;
@@ -242,6 +239,9 @@ sub fetch {
$last_commit = git_commit($log_msg, $last_commit, @parents);
}
assert_svn_wc_clean($last_rev, $last_commit);
+ unless (-e "$GIT_DIR/refs/heads/master") {
+ sys(qw(git-update-ref refs/heads/master),$last_commit);
+ }
return pop @$svn_log;
}
--
1.2.3.g4676
^ permalink raw reply related
* [PATCH 3/9] contrib/git-svn: strip 'git-svn-id:' when commiting to SVN
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <114137760733-git-send-email-normalperson@yhbt.net>
We regenerate and use git-svn-id: whenever we fetch or otherwise
commit to remotes/git-svn. We don't actually know what revision
number we'll commit to SVN at commit time, so this is useless.
It won't throw off things like 'rebuild', though, which knows to
only use the last instance of git-svn-id: in a log message
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
15b28ddfc496fa88cffdfddcc9262cae635a34d0
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index 67368a5..edae9d4 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -625,6 +625,9 @@ sub svn_commit_tree {
while (<$msg_fh>) {
if (!$in_msg) {
$in_msg = 1 if (/^\s*$/);
+ } elsif (/^git-svn-id: /) {
+ # skip this, we regenerate the correct one
+ # on re-fetch anyways
} else {
print $msg $_ or croak $!;
}
--
1.2.3.g4676
^ permalink raw reply related
* contrib/git-svn: polishing up
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
Mostly small things: documentation and code cleanups.
One bugfix of some significance:
Edited commit messages are parsed back to remotes/git-svn
correctly. The sequential commit optimization broke this :x
Significant new features:
--branch/-b is interesting and fun for those of you who miss 'real'
branch support in SVN.
--authors-file/-A support, because git-svnimport has it :)
None of the core commit/fetch tree-writing code was touched.
git-svn.perl | 210 ++++++++++++++++++++++++++++++++++++++++-------------------
git-svn.txt | 34 ++++++++-
2 files changed, 176 insertions(+), 68 deletions(-)
^ permalink raw reply
* [PATCH 1/9] contrib/git-svn: add -b/--branch switch for branch detection
From: Eric Wong @ 2006-03-03 9:20 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <11413776074123-git-send-email-normalperson@yhbt.net>
I've said I don't like branches in Subversion, and I still don't.
This is a bit more flexible, though, as the argument for -b is any
arbitrary git head/tag reference.
This makes some things easier:
* Importing git history into a brand new SVN branch.
* Tracking multiple SVN branches via GIT_SVN_ID, even from multiple
repositories.
* Adding tags from SVN (still need to use GIT_SVN_ID, though).
* Even merge tracking is supported, if and only the heads end up with
100% equivalent tree objects. This is more stricter but more robust
and foolproof than parsing commit messages, imho.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 38 ++++++++++++++++++++++++++++++++++++++
contrib/git-svn/git-svn.txt | 17 ++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletions(-)
536109ffa6682954d3b2bb6a184978fd185ecaa4
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index 0e092c5..1f9a470 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -35,6 +35,7 @@ my $sha1 = qr/[a-f\d]{40}/;
my $sha1_short = qr/[a-f\d]{6,40}/;
my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
$_find_copies_harder, $_l, $_version, $_upgrade);
+my (@_branch_from, %tree_map);
GetOptions( 'revision|r=s' => \$_revision,
'no-ignore-externals' => \$_no_ignore_ext,
@@ -43,6 +44,7 @@ GetOptions( 'revision|r=s' => \$_revisio
'rmdir' => \$_rmdir,
'upgrade' => \$_upgrade,
'help|H|h' => \$_help,
+ 'branch|b=s' => \@_branch_from,
'find-copies-harder' => \$_find_copies_harder,
'l=i' => \$_l,
'version|V' => \$_version,
@@ -831,6 +833,8 @@ sub git_commit {
my $uuid = $info->{'Repository UUID'};
defined $uuid or croak "Unable to get Repository UUID\n";
+ map_tree_joins() if (@_branch_from && !%tree_map);
+
# commit parents can be conditionally bound to a particular
# svn revision via: "svn_revno=commit_sha1", filter them out here:
my @exec_parents;
@@ -852,6 +856,17 @@ sub git_commit {
git_addremove();
chomp(my $tree = `git-write-tree`);
croak if $?;
+ if (exists $tree_map{$tree}) {
+ my %seen_parent = map { $_ => 1 } @exec_parents;
+ foreach (@{$tree_map{$tree}}) {
+ # MAXPARENT is defined to 16 in commit-tree.c:
+ if ($seen_parent{$_} || @exec_parents > 16) {
+ next;
+ }
+ push @exec_parents, $_;
+ $seen_parent{$_} = 1;
+ }
+ }
my $msg_fh = IO::File->new_tmpfile or croak $!;
print $msg_fh $log_msg->{msg}, "\ngit-svn-id: ",
"$SVN_URL\@$log_msg->{revision}",
@@ -975,6 +990,29 @@ sub check_upgrade_needed {
}
}
+# fills %tree_map with a reverse mapping of trees to commits. Useful
+# for finding parents to commit on.
+sub map_tree_joins {
+ foreach my $br (@_branch_from) {
+ my $pid = open my $pipe, '-|';
+ defined $pid or croak $!;
+ if ($pid == 0) {
+ exec(qw(git-rev-list --pretty=raw), $br) or croak $?;
+ }
+ while (<$pipe>) {
+ if (/^commit ($sha1)$/o) {
+ my $commit = $1;
+ my ($tree) = (<$pipe> =~ /^tree ($sha1)$/o);
+ unless (defined $tree) {
+ die "Failed to parse commit $commit\n";
+ }
+ push @{$tree_map{$tree}}, $commit;
+ }
+ }
+ close $pipe or croak $?;
+ }
+}
+
__END__
Data structures:
diff --git a/contrib/git-svn/git-svn.txt b/contrib/git-svn/git-svn.txt
index 4102deb..7306048 100644
--- a/contrib/git-svn/git-svn.txt
+++ b/contrib/git-svn/git-svn.txt
@@ -27,7 +27,7 @@ For importing svn, git-svnimport is pote
operating on repositories organized under the recommended
trunk/branch/tags structure, and should be faster, too.
-git-svn completely ignores the very limited view of branching that
+git-svn mostly ignores the very limited view of branching that
Subversion has. This allows git-svn to be much easier to use,
especially on repositories that are not organized in a manner that
git-svnimport is designed for.
@@ -116,6 +116,21 @@ OPTIONS
They are both passed directly to git-diff-tree see
git-diff-tree(1) for more information.
+-b<refname>::
+--branch <refname>::
+ Used with 'fetch' or 'commit'.
+
+ This can be used to join arbitrary git branches to remotes/git-svn
+ on new commits where the tree object is equivalent.
+
+ When used with different GIT_SVN_ID values, tags and branches in
+ SVN can be tracked this way, as can some merges where the heads
+ end up having completely equivalent content. This can even be
+ used to track branches across multiple SVN _repositories_.
+
+ This option may be specified multiple times, once for each
+ branch.
+
COMPATIBILITY OPTIONS
---------------------
--no-ignore-externals::
--
1.2.3.g4676
^ permalink raw reply related
* Re: cygwin: push/pull takes very long time
From: Alex Riesen @ 2006-03-03 9:10 UTC (permalink / raw)
To: Christopher Faylor; +Cc: Git Mailing List
In-Reply-To: <20060303002806.GB7497@trixie.casa.cgf.cx>
On 3/3/06, Christopher Faylor <me@cgf.cx> wrote:
> On Thu, Mar 02, 2006 at 10:54:08PM +0100, Alex Riesen wrote:
> >Alex Riesen, Thu, Mar 02, 2006 18:09:23 +0100:
> >>I'll cleanup the profiling code and send it as well soon (I had to
> >>instrument x*alloc).
> >
> >This is not exactly the same. It counts free as well, even if that is
> >not really interesting - there are places were there is more frees than
> >allocs. Probably something missed or a result coming from libc.
> >
> >Also it is _not_ the code I used for windows. I had to have a global
> >variable for argv[0], which needs modification of all main()s, which
> >gets too easily out of sync.
>
> I wasn't following this discussion closely so maybe this is useless
> information, but for Cygwin you can either use the undocumented global
> __argv or you can use /proc/cmdline. /proc/self/cmdline is going to be
> pretty slow, however.
Oh, thanks. The speed is of no problem here: it's in atexit callback.
> It looks like pure Windows console apps define _argv in stdlib.h also
> but I've never used this and don't know if it is what it looks like.
It works as usual argv. I used "char **__argv", got the message from linker:
Info: resolving ___argv by linking to __imp____argv (auto-import)
which I almost expected.
^ permalink raw reply
* Re: [PATCH] annotate should number lines starting with 1
From: Junio C Hamano @ 2006-03-03 7:09 UTC (permalink / raw)
To: Luck, Tony; +Cc: git, Martin Langhoff
In-Reply-To: <200603022327.k22NRVek023304@agluck-lia64.sc.intel.com>
"Luck, Tony" <tony.luck@intel.com> writes:
> C programmers are well used to counting from zero, but every
> other text file tool starts counting from 1.
Thanks.
I agree with this patch 100%, so I am going to take this patch.
But git-cvsserver might need some adjustments.
Martin?
^ permalink raw reply
* Re: [PATCH] annotate should number lines starting with 1
From: Junio C Hamano @ 2006-03-03 7:09 UTC (permalink / raw)
To: Luck, Tony; +Cc: git, Martin Langhoff
In-Reply-To: <200603022327.k22NRVek023304@agluck-lia64.sc.intel.com>
"Luck, Tony" <tony.luck@intel.com> writes:
> C programmers are well used to counting from zero, but every
> other text file tool starts counting from 1.
Thanks.
I agree with this patch 100%, so I am going to take this patch.
But git-cvsserver might need some adjustments.
Martin?
^ permalink raw reply
* Re: [PATCH 1/3] cg-mv doesn't work with bash 3.1.7 due to excessive quotes
From: Junio C Hamano @ 2006-03-03 5:27 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <20060303011154.14619.71590.stgit@dv.roinet.com>
Pavel Roskin <proski@gnu.org> writes:
> - ARGS2["${#ARGS2[@]}"]="$_git_relpath${arg%/}"
> + ARGS2[${#ARGS2[@]}]="$_git_relpath${arg%/}"
Is this an application bug? It looks like a workaround for a
bug in the shell...
Not that I care too much either way -- I do not use shell arrays
myself ;-).
^ permalink raw reply
* Re: [PATCH] Add --temp and --stage=all options to checkout-index.
From: Junio C Hamano @ 2006-03-03 5:25 UTC (permalink / raw)
To: Shawn Pearce; +Cc: git
In-Reply-To: <20060303012032.GC6321@spearce.org>
Shawn Pearce <spearce@spearce.org> writes:
> Unfortunately this change lead me down a path which changed the core
> checkout code also used by apply and read-tree.
... which makes it much harder to swallow without careful
inspection X-<.
I think the patch only appears much bigger than it actually is,
because of reindentation effect coming from "if (to-temp-file)".
However, I am too tired to carefully examine them tonight, so I
hope you do not mind my postponing this for now.
^ permalink raw reply
* Re: [PATCH] fmt-merge-msg: avoid open "-|" list form for Perl 5.6
From: Linus Torvalds @ 2006-03-03 1:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vveuw48uw.fsf@assigned-by-dhcp.cox.net>
On Thu, 2 Mar 2006, Junio C Hamano wrote:
>
> Linus Torvalds <torvalds@osdl.org> writes:
>
> > Yeah, I actually looked at a few examples, so I knew what it was basically
> > trying to do, and then I ignored it as not interesting to the exercise,
> > which was to abuse the new revision listing library in interesting ways by
> > calling it multiple times.
>
> Abuse is exactly the word. The reason it is an abuse is exactly
> why you said "... but to fix it you'd have to actualyl walk the
> parent list yourself, rather than letting get_revision do it all
> for you." Which relates to the fact that object.c layer is not
> designed to be used multiple times...
>
> Maybe we want to make object.c layer reusable first?
No, the "abuse" is actually very much done that way on purpose. It's a bit
strange to do "incremental" prepare_revision_walk() calls, but it all
comes from the fact that the object structures are "persistent" across the
calls, even if we remove them from the list when we walk them.
So it's strange, but that was kind of part of the reason for doing it.
It's a _good_ strangeness.
The thing about handling commits that were already in another branch but
weren't shown is different: the way to handle that is to generate the
_whole_ revision list in one go - instead of incrementally - and then for
each branch you merge you show the top 10 "not yet shown" commits.
IOW, that thing would never use "get_revision()" at all, but would instead
depend on "prepare_revision_walk()" generating the whole tree, and then
you just walk the parent pointers from the branch heads by hand, marking
then "seen" as you print them.
So the object layer and the revision parsing actually does exactly the
right thing, you just have to decide on how to use them..
Linus
^ permalink raw reply
* Re: [PATCH] fmt-merge-msg: avoid open "-|" list form for Perl 5.6
From: Junio C Hamano @ 2006-03-03 1:25 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0603021643560.22647@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> Yeah, I actually looked at a few examples, so I knew what it was basically
> trying to do, and then I ignored it as not interesting to the exercise,
> which was to abuse the new revision listing library in interesting ways by
> calling it multiple times.
Abuse is exactly the word. The reason it is an abuse is exactly
why you said "... but to fix it you'd have to actualyl walk the
parent list yourself, rather than letting get_revision do it all
for you." Which relates to the fact that object.c layer is not
designed to be used multiple times...
Maybe we want to make object.c layer reusable first?
^ permalink raw reply
* [PATCH] Add --temp and --stage=all options to checkout-index.
From: Shawn Pearce @ 2006-03-03 1:20 UTC (permalink / raw)
To: git
Sometimes it is convient for a Porcelain to be able to checkout all
unmerged files in all stages so that an external merge tool can be
executed by the Porcelain or the end-user. Using git-unpack-file
on each stage individually incurs a rather high penalty due to the
need to fork for each file version obtained. git-checkout-index -a
--stage=all will now do the same thing, but faster.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
This spawned out of the discussion of my prior --suffix patch
and replaces it entirely.
The output format is Junio's idea, which I happened to like a lot.
I think I have faithfully implemented it here, but added a case
where you can obtain temporary files for only a specific stage
without needing to read the 'wider' 3-stage format.
Unfortunately this change lead me down a path which changed the core
checkout code also used by apply and read-tree. So those commands
could now checkout to temporary files if they wanted to. :-)
It currently passes all test cases, including the new one provided
by this patch.
Documentation/git-checkout-index.txt | 51 ++++++++
apply.c | 3
cache.h | 5 -
checkout-index.c | 84 ++++++++++++-
entry.c | 92 +++++++++------
read-tree.c | 3
t/t2004-checkout-cache-temp.sh | 212 ++++++++++++++++++++++++++++++++++
7 files changed, 396 insertions(+), 54 deletions(-)
create mode 100755 t/t2004-checkout-cache-temp.sh
base c6b84bc40310f8e0cf2fe290b5f291e31cf688ef
last 022659f9b239fd5513a883e09ac0e0688b69dbe1
diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt
index b0b6588..09bd6a5 100644
--- a/Documentation/git-checkout-index.txt
+++ b/Documentation/git-checkout-index.txt
@@ -10,7 +10,8 @@ SYNOPSIS
--------
[verse]
'git-checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
- [--stage=<number>]
+ [--stage=<number>|all]
+ [--temp]
[-z] [--stdin]
[--] [<file>]\*
@@ -43,9 +44,15 @@ OPTIONS
When creating files, prepend <string> (usually a directory
including a trailing /)
---stage=<number>::
+--stage=<number>|all::
Instead of checking out unmerged entries, copy out the
files from named stage. <number> must be between 1 and 3.
+ Note: --stage=all automatically implies --temp.
+
+--temp::
+ Instead of copying the files to the working directory
+ write the content to temporary files. The temporary name
+ associations will be written to stdout.
--stdin::
Instead of taking list of paths from the command line,
@@ -87,6 +94,46 @@ it will prevent problems with a filename
Using `--` is probably a good policy in scripts.
+Using --temp or --stage=all
+---------------------------
+When `--temp` is used (or implied by `--stage=all`)
+`git-checkout-index` will create a temporary file for each index
+entry being checked out. The index will not be updated with stat
+information. These options can be useful if the caller needs all
+stages of all unmerged entries so that the unmerged files can be
+processed by an external merge tool.
+
+A listing will be written to stdout providing the association of
+temporary file names to tracked path names. The listing format
+has two variations:
+
+ . tempname TAB path RS
++
+The first format is what gets used when `--stage` is omitted or
+is not `--stage=all`. The field tempname is the temporary file
+name holding the file content and path is the tracked path name in
+the index. Only the requested entries are output.
+
+ . stage1temp SP stage2temp SP stage3tmp TAB path RS
++
+The second format is what gets used when `--stage=all`. The three
+stage temporary fields (stage1temp, stage2temp, stage3temp) list the
+name of the temporary file if there is a stage entry in the index
+or `.` if there is no stage entry. Paths which only have a stage 0
+entry will always be omitted from the output.
+
+In both formats RS (the record separator) is newline by default
+but will be the null byte if -z was passed on the command line.
+The temporary file names are always safe strings; they will never
+contain directory separators or whitespace characters. The path
+field is always relative to the current directory and the temporary
+file names are always relative to the top level directory.
+
+If the object being copied out to a temporary file is a symbolic
+link the content of the link will be written to a normal file. It is
+up to the end-user or the Porcelain to make use of this information.
+
+
EXAMPLES
--------
To update and refresh only the files already checked out::
diff --git a/apply.c b/apply.c
index c369966..5583a80 100644
--- a/apply.c
+++ b/apply.c
@@ -1376,6 +1376,7 @@ static int apply_data(struct patch *patc
static int check_patch(struct patch *patch)
{
struct stat st;
+ static char topath[MAXPATHLEN+1];
const char *old_name = patch->old_name;
const char *new_name = patch->new_name;
const char *name = old_name ? old_name : new_name;
@@ -1402,7 +1403,7 @@ static int check_patch(struct patch *pat
costate.not_new = 0;
costate.refresh_cache = 1;
if (checkout_entry(active_cache[pos],
- &costate) ||
+ &costate, topath) ||
lstat(old_name, &st))
return -1;
}
diff --git a/cache.h b/cache.h
index 0d3b244..f87744c 100644
--- a/cache.h
+++ b/cache.h
@@ -259,10 +259,11 @@ struct checkout {
unsigned force:1,
quiet:1,
not_new:1,
- refresh_cache:1;
+ refresh_cache:1,
+ to_tempfile:1;
};
-extern int checkout_entry(struct cache_entry *ce, struct checkout *state);
+extern int checkout_entry(struct cache_entry *ce, struct checkout *state, char *topath);
extern struct alternate_object_database {
struct alternate_object_database *next;
diff --git a/checkout-index.c b/checkout-index.c
index f54c606..24845c3 100644
--- a/checkout-index.c
+++ b/checkout-index.c
@@ -40,9 +40,12 @@
#include "strbuf.h"
#include "quote.h"
+#define CHECKOUT_ALL 4
static const char *prefix;
static int prefix_length;
+static int line_termination = '\n';
static int checkout_stage; /* default to checkout stage0 */
+static char topath[4][MAXPATHLEN+1];
static struct checkout state = {
.base_dir = "",
@@ -51,13 +54,42 @@ static struct checkout state = {
.quiet = 0,
.not_new = 0,
.refresh_cache = 0,
+ .to_tempfile = 0,
};
+static void write_tempfile_record (const char *name)
+{
+ int i;
+
+ if (CHECKOUT_ALL == checkout_stage) {
+ for (i = 1; i < 4; i++) {
+ if (i > 1)
+ putchar(' ');
+ if (topath[i][0])
+ fputs(topath[i], stdout);
+ else
+ putchar('.');
+ }
+ } else
+ fputs(topath[checkout_stage], stdout);
+
+ putchar('\t');
+ write_name_quoted("", 0, name + prefix_length,
+ line_termination, stdout);
+ putchar(line_termination);
+
+ for (i = 0; i < 4; i++) {
+ topath[i][0] = 0;
+ }
+}
+
static int checkout_file(const char *name)
{
int namelen = strlen(name);
int pos = cache_name_pos(name, namelen);
int has_same_name = 0;
+ int did_checkout = 0;
+ int errs = 0;
if (pos < 0)
pos = -pos - 1;
@@ -68,9 +100,19 @@ static int checkout_file(const char *nam
memcmp(ce->name, name, namelen))
break;
has_same_name = 1;
- if (checkout_stage == ce_stage(ce))
- return checkout_entry(ce, &state);
pos++;
+ if (ce_stage(ce) != checkout_stage
+ && (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
+ continue;
+ did_checkout = 1;
+ if (checkout_entry(ce, &state, topath[ce_stage(ce)]) < 0)
+ errs++;
+ }
+
+ if (did_checkout) {
+ if (state.to_tempfile)
+ write_tempfile_record(name);
+ return errs > 0 ? -1 : 0;
}
if (!state.quiet) {
@@ -90,18 +132,28 @@ static int checkout_file(const char *nam
static int checkout_all(void)
{
int i, errs = 0;
+ struct cache_entry* last_ce = 0;
for (i = 0; i < active_nr ; i++) {
struct cache_entry *ce = active_cache[i];
- if (ce_stage(ce) != checkout_stage)
+ if (ce_stage(ce) != checkout_stage
+ && (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
continue;
if (prefix && *prefix &&
(ce_namelen(ce) <= prefix_length ||
memcmp(prefix, ce->name, prefix_length)))
continue;
- if (checkout_entry(ce, &state) < 0)
+ if (last_ce && state.to_tempfile) {
+ if (ce_namelen(last_ce) != ce_namelen(ce)
+ || memcmp(last_ce->name, ce->name, ce_namelen(ce)))
+ write_tempfile_record(last_ce->name);
+ }
+ if (checkout_entry(ce, &state, topath[ce_stage(ce)]) < 0)
errs++;
+ last_ce = ce;
}
+ if (last_ce && state.to_tempfile)
+ write_tempfile_record(last_ce->name);
if (errs)
/* we have already done our error reporting.
* exit with the same code as die().
@@ -111,7 +163,7 @@ static int checkout_all(void)
}
static const char checkout_cache_usage[] =
-"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]] [--prefix=<string>] [--] <file>...";
+"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
static struct cache_file cache_file;
@@ -121,7 +173,6 @@ int main(int argc, char **argv)
int newfd = -1;
int all = 0;
int read_from_stdin = 0;
- int line_termination = '\n';
prefix = setup_git_directory();
git_config(git_default_config);
@@ -175,17 +226,26 @@ int main(int argc, char **argv)
i++; /* do not consider arg as a file name */
break;
}
+ if (!strcmp(arg, "--temp")) {
+ state.to_tempfile = 1;
+ continue;
+ }
if (!strncmp(arg, "--prefix=", 9)) {
state.base_dir = arg+9;
state.base_dir_len = strlen(state.base_dir);
continue;
}
if (!strncmp(arg, "--stage=", 8)) {
- int ch = arg[8];
- if ('1' <= ch && ch <= '3')
- checkout_stage = arg[8] - '0';
- else
- die("stage should be between 1 and 3");
+ if (!strcmp(arg + 8, "all")) {
+ state.to_tempfile = 1;
+ checkout_stage = CHECKOUT_ALL;
+ } else {
+ int ch = arg[8];
+ if ('1' <= ch && ch <= '3')
+ checkout_stage = arg[8] - '0';
+ else
+ die("stage should be between 1 and 3 or all");
+ }
continue;
}
if (arg[0] == '-')
@@ -193,7 +253,7 @@ int main(int argc, char **argv)
break;
}
- if (state.base_dir_len) {
+ if (state.base_dir_len || state.to_tempfile) {
/* when --prefix is specified we do not
* want to update cache.
*/
diff --git a/entry.c b/entry.c
index 8fb99bc..c33a35d 100644
--- a/entry.c
+++ b/entry.c
@@ -63,7 +63,7 @@ static int create_file(const char *path,
return open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
}
-static int write_entry(struct cache_entry *ce, const char *path, struct checkout *state)
+static int write_entry(struct cache_entry *ce, char *path, struct checkout *state)
{
int fd;
void *new;
@@ -80,7 +80,11 @@ static int write_entry(struct cache_entr
}
switch (ntohl(ce->ce_mode) & S_IFMT) {
case S_IFREG:
- fd = create_file(path, ntohl(ce->ce_mode));
+ if (state->to_tempfile) {
+ strcpy(path, ".merge_file_XXXXXX");
+ fd = mkstemp(path);
+ } else
+ fd = create_file(path, ntohl(ce->ce_mode));
if (fd < 0) {
free(new);
return error("git-checkout-index: unable to create file %s (%s)",
@@ -93,12 +97,27 @@ static int write_entry(struct cache_entr
return error("git-checkout-index: unable to write file %s", path);
break;
case S_IFLNK:
- if (symlink(new, path)) {
+ if (state->to_tempfile) {
+ strcpy(path, ".merge_link_XXXXXX");
+ fd = mkstemp(path);
+ if (fd < 0) {
+ free(new);
+ return error("git-checkout-index: unable to create "
+ "file %s (%s)", path, strerror(errno));
+ }
+ wrote = write(fd, new, size);
+ close(fd);
free(new);
- return error("git-checkout-index: unable to create "
- "symlink %s (%s)", path, strerror(errno));
+ if (wrote != size)
+ return error("git-checkout-index: unable to write file %s",
+ path);
+ } else {
+ wrote = symlink(new, path);
+ free(new);
+ if (wrote)
+ return error("git-checkout-index: unable to create "
+ "symlink %s (%s)", path, strerror(errno));
}
- free(new);
break;
default:
free(new);
@@ -113,41 +132,42 @@ static int write_entry(struct cache_entr
return 0;
}
-int checkout_entry(struct cache_entry *ce, struct checkout *state)
+int checkout_entry(struct cache_entry *ce, struct checkout *state, char *topath)
{
struct stat st;
- static char path[MAXPATHLEN+1];
int len = state->base_dir_len;
- memcpy(path, state->base_dir, len);
- strcpy(path + len, ce->name);
-
- if (!lstat(path, &st)) {
- unsigned changed = ce_match_stat(ce, &st, 1);
- if (!changed)
+ if (!state->to_tempfile) {
+ memcpy(topath, state->base_dir, len);
+ strcpy(topath + len, ce->name);
+
+ if (!lstat(topath, &st)) {
+ unsigned changed = ce_match_stat(ce, &st, 1);
+ if (!changed)
+ return 0;
+ if (!state->force) {
+ if (!state->quiet)
+ fprintf(stderr, "git-checkout-index: %s already exists\n", topath);
+ return -1;
+ }
+
+ /*
+ * We unlink the old file, to get the new one with the
+ * right permissions (including umask, which is nasty
+ * to emulate by hand - much easier to let the system
+ * just do the right thing)
+ */
+ unlink(topath);
+ if (S_ISDIR(st.st_mode)) {
+ if (!state->force)
+ return error("%s is a directory", topath);
+ remove_subtree(topath);
+ }
+ } else if (state->not_new)
return 0;
- if (!state->force) {
- if (!state->quiet)
- fprintf(stderr, "git-checkout-index: %s already exists\n", path);
- return -1;
- }
-
- /*
- * We unlink the old file, to get the new one with the
- * right permissions (including umask, which is nasty
- * to emulate by hand - much easier to let the system
- * just do the right thing)
- */
- unlink(path);
- if (S_ISDIR(st.st_mode)) {
- if (!state->force)
- return error("%s is a directory", path);
- remove_subtree(path);
- }
- } else if (state->not_new)
- return 0;
- create_directories(path, state);
- return write_entry(ce, path, state);
+ create_directories(topath, state);
+ }
+ return write_entry(ce, topath, state);
}
diff --git a/read-tree.c b/read-tree.c
index be29b3f..e88d69e 100644
--- a/read-tree.c
+++ b/read-tree.c
@@ -279,6 +279,7 @@ static void progress_interval(int signum
static void check_updates(struct cache_entry **src, int nr)
{
+ static char topath[MAXPATHLEN+1];
static struct checkout state = {
.base_dir = "",
.force = 1,
@@ -337,7 +338,7 @@ static void check_updates(struct cache_e
if (ce->ce_flags & mask) {
ce->ce_flags &= ~mask;
if (update)
- checkout_entry(ce, &state);
+ checkout_entry(ce, &state, topath);
}
}
if (total) {
diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh
new file mode 100755
index 0000000..c100959
--- /dev/null
+++ b/t/t2004-checkout-cache-temp.sh
@@ -0,0 +1,212 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Shawn Pearce
+#
+
+test_description='git-checkout-index --temp test.
+
+With --temp flag, git-checkout-index writes to temporary merge files
+rather than the tracked path.'
+
+. ./test-lib.sh
+
+test_expect_success \
+'preparation' '
+mkdir asubdir &&
+echo tree1path0 >path0 &&
+echo tree1path1 >path1 &&
+echo tree1path3 >path3 &&
+echo tree1path4 >path4 &&
+echo tree1asubdir/path5 >asubdir/path5 &&
+git-update-index --add path0 path1 path3 path4 asubdir/path5 &&
+t1=$(git-write-tree) &&
+rm -f path* .merge_* out .git/index &&
+echo tree2path0 >path0 &&
+echo tree2path1 >path1 &&
+echo tree2path2 >path2 &&
+echo tree2path4 >path4 &&
+git-update-index --add path0 path1 path2 path4 &&
+t2=$(git-write-tree) &&
+rm -f path* .merge_* out .git/index &&
+echo tree2path0 >path0 &&
+echo tree3path1 >path1 &&
+echo tree3path2 >path2 &&
+echo tree3path3 >path3 &&
+git-update-index --add path0 path1 path2 path3 &&
+t3=$(git-write-tree)'
+
+test_expect_success \
+'checkout one stage 0 to temporary file' '
+rm -f path* .merge_* out .git/index &&
+git-read-tree $t1 &&
+git-checkout-index --temp -- path1 >out &&
+test $(wc -l <out) = 1 &&
+test $(cut "-d " -f2 out) = path1 &&
+p=$(cut "-d " -f1 out) &&
+test -f $p &&
+test $(cat $p) = tree1path1'
+
+test_expect_success \
+'checkout all stage 0 to temporary files' '
+rm -f path* .merge_* out .git/index &&
+git-read-tree $t1 &&
+git-checkout-index -a --temp >out &&
+test $(wc -l <out) = 5 &&
+for f in path0 path1 path3 path4 asubdir/path5
+do
+ test $(grep $f out | cut "-d " -f2) = $f &&
+ p=$(grep $f out | cut "-d " -f1) &&
+ test -f $p &&
+ test $(cat $p) = tree1$f
+done'
+
+test_expect_success \
+'prepare 3-way merge' '
+rm -f path* .merge_* out .git/index &&
+git-read-tree -m $t1 $t2 $t3'
+
+test_expect_success \
+'checkout one stage 2 to temporary file' '
+rm -f path* .merge_* out &&
+git-checkout-index --stage=2 --temp -- path1 >out &&
+test $(wc -l <out) = 1 &&
+test $(cut "-d " -f2 out) = path1 &&
+p=$(cut "-d " -f1 out) &&
+test -f $p &&
+test $(cat $p) = tree2path1'
+
+test_expect_success \
+'checkout all stage 2 to temporary files' '
+rm -f path* .merge_* out &&
+git-checkout-index --all --stage=2 --temp >out &&
+test $(wc -l <out) = 3 &&
+for f in path1 path2 path4
+do
+ test $(grep $f out | cut "-d " -f2) = $f &&
+ p=$(grep $f out | cut "-d " -f1) &&
+ test -f $p &&
+ test $(cat $p) = tree2$f
+done'
+
+test_expect_success \
+'checkout all stages/one file to nothing' '
+rm -f path* .merge_* out &&
+git-checkout-index --stage=all --temp -- path0 >out &&
+test $(wc -l <out) = 0'
+
+test_expect_success \
+'checkout all stages/one file to temporary files' '
+rm -f path* .merge_* out &&
+git-checkout-index --stage=all --temp -- path1 >out &&
+test $(wc -l <out) = 1 &&
+test $(cut "-d " -f2 out) = path1 &&
+cut "-d " -f1 out | (read s1 s2 s3 &&
+test -f $s1 &&
+test -f $s2 &&
+test -f $s3 &&
+test $(cat $s1) = tree1path1 &&
+test $(cat $s2) = tree2path1 &&
+test $(cat $s3) = tree3path1)'
+
+test_expect_success \
+'checkout some stages/one file to temporary files' '
+rm -f path* .merge_* out &&
+git-checkout-index --stage=all --temp -- path2 >out &&
+test $(wc -l <out) = 1 &&
+test $(cut "-d " -f2 out) = path2 &&
+cut "-d " -f1 out | (read s1 s2 s3 &&
+test $s1 = . &&
+test -f $s2 &&
+test -f $s3 &&
+test $(cat $s2) = tree2path2 &&
+test $(cat $s3) = tree3path2)'
+
+test_expect_success \
+'checkout all stages/all files to temporary files' '
+rm -f path* .merge_* out &&
+git-checkout-index -a --stage=all --temp >out &&
+test $(wc -l <out) = 5'
+
+test_expect_success \
+'-- path0: no entry' '
+test x$(grep path0 out | cut "-d " -f2) = x'
+
+test_expect_success \
+'-- path1: all 3 stages' '
+test $(grep path1 out | cut "-d " -f2) = path1 &&
+grep path1 out | cut "-d " -f1 | (read s1 s2 s3 &&
+test -f $s1 &&
+test -f $s2 &&
+test -f $s3 &&
+test $(cat $s1) = tree1path1 &&
+test $(cat $s2) = tree2path1 &&
+test $(cat $s3) = tree3path1)'
+
+test_expect_success \
+'-- path2: no stage 1, have stage 2 and 3' '
+test $(grep path2 out | cut "-d " -f2) = path2 &&
+grep path2 out | cut "-d " -f1 | (read s1 s2 s3 &&
+test $s1 = . &&
+test -f $s2 &&
+test -f $s3 &&
+test $(cat $s2) = tree2path2 &&
+test $(cat $s3) = tree3path2)'
+
+test_expect_success \
+'-- path3: no stage 2, have stage 1 and 3' '
+test $(grep path3 out | cut "-d " -f2) = path3 &&
+grep path3 out | cut "-d " -f1 | (read s1 s2 s3 &&
+test -f $s1 &&
+test $s2 = . &&
+test -f $s3 &&
+test $(cat $s1) = tree1path3 &&
+test $(cat $s3) = tree3path3)'
+
+test_expect_success \
+'-- path4: no stage 3, have stage 1 and 3' '
+test $(grep path4 out | cut "-d " -f2) = path4 &&
+grep path4 out | cut "-d " -f1 | (read s1 s2 s3 &&
+test -f $s1 &&
+test -f $s2 &&
+test $s3 = . &&
+test $(cat $s1) = tree1path4 &&
+test $(cat $s2) = tree2path4)'
+
+test_expect_success \
+'-- asubdir/path5: no stage 2 and 3 have stage 1' '
+test $(grep asubdir/path5 out | cut "-d " -f2) = asubdir/path5 &&
+grep asubdir/path5 out | cut "-d " -f1 | (read s1 s2 s3 &&
+test -f $s1 &&
+test $s2 = . &&
+test $s3 = . &&
+test $(cat $s1) = tree1asubdir/path5)'
+
+test_expect_success \
+'checkout --temp within subdir' '
+(cd asubdir &&
+ git-checkout-index -a --stage=all >out &&
+ test $(wc -l <out) = 1 &&
+ test $(grep path5 out | cut "-d " -f2) = path5 &&
+ grep path5 out | cut "-d " -f1 | (read s1 s2 s3 &&
+ test -f ../$s1 &&
+ test $s2 = . &&
+ test $s3 = . &&
+ test $(cat ../$s1) = tree1asubdir/path5)
+)'
+
+test_expect_success \
+'checkout --temp symlink' '
+rm -f path* .merge_* out .git/index &&
+ln -s b a &&
+git-update-index --add a &&
+t4=$(git-write-tree) &&
+rm -f .git/index &&
+git-read-tree $t4 &&
+git-checkout-index --temp -a >out &&
+test $(wc -l <out) = 1 &&
+test $(cut "-d " -f2 out) = a &&
+p=$(cut "-d " -f1 out) &&
+test -f $p &&
+test $(cat $p) = b'
+
+test_done
--
1.2.3.g5f0e
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox