* Re: [PATCH] svn: Add && to t9107-git-svn-migrarte.sh
From: Adam Brewster @ 2009-08-12 3:14 UTC (permalink / raw)
To: git; +Cc: Eric Wong
In-Reply-To: <20090810083234.GA8698@dcvr.yhbt.net>
Eric,
Any thoughts on the other patch?
Am I close or is there a better way to go about this?
I didn't really know what to do with .git/svn/*. The easy answer is
mkdir -p $GIT_DIR/svn/refs/remotes &&
mv $GIT_DIR/svn/* $GIT_DIR/svn/refs/remotes
>From the comments in the Migration module, it seems like that's frowned
upon, so I came up with looking for .rev_map (or .rev_db) in both
locations (.git/svn/git-svn and .git/svn/refs/remotes/svn) and letting
it stay in whichever location it already exists. (The next email has a
slightly improved version of the patch.)
This solution is particularly inelegant in it's handling of
unhandled.log, but as far as I know that file is unused.
There's also the problem of what to do if someone has a ref called
ref/remotes/refs/remotes/..., but that seems unlikely enough to not
cause concern.
Adam
^ permalink raw reply
* [PATCH] svn: allow branches outside of refs/remotes
From: Adam Brewster @ 2009-08-12 3:14 UTC (permalink / raw)
To: git; +Cc: Eric Wong, Adam Brewster
In-Reply-To: <1250046867-13655-1-git-send-email-adambrewster@gmail.com>
It may be convenient for some users to store svn remote tracking
branches outside of the refs/remotes/ heirarchy.
To accomplish this feat, this patch includes the entire path to
the ref in $r->{'refname'} in &read_all_remotes and tries to change
references to this entry so the new value makes sense.
Signed-off-by: Adam Brewster <adambrewster@gmail.com>
---
git-svn.perl | 82 +++++++++++++++++++++----------------
t/lib-git-svn.sh | 2 +-
t/t9104-git-svn-follow-parent.sh | 10 ++--
t/t9107-git-svn-migrate.sh | 14 +++----
t/t9143-git-svn-gc.sh | 10 ++--
5 files changed, 63 insertions(+), 55 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index b0bfb74..cafd7fe 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -909,7 +909,7 @@ sub cmd_multi_init {
}
do_git_init_db();
if (defined $_trunk) {
- my $trunk_ref = $_prefix . 'trunk';
+ my $trunk_ref = 'refs/remotes/' . $_prefix . 'trunk';
# try both old-style and new-style lookups:
my $gs_trunk = eval { Git::SVN->new($trunk_ref) };
unless ($gs_trunk) {
@@ -1643,23 +1643,23 @@ sub resolve_local_globs {
return unless defined $glob_spec;
my $ref = $glob_spec->{ref};
my $path = $glob_spec->{path};
- foreach (command(qw#for-each-ref --format=%(refname) refs/remotes#)) {
- next unless m#^refs/remotes/$ref->{regex}$#;
+ foreach (command(qw#for-each-ref --format=%(refname) refs/#)) {
+ next unless m#^$ref->{regex}$#;
my $p = $1;
my $pathname = desanitize_refname($path->full_path($p));
my $refname = desanitize_refname($ref->full_path($p));
if (my $existing = $fetch->{$pathname}) {
if ($existing ne $refname) {
die "Refspec conflict:\n",
- "existing: refs/remotes/$existing\n",
- " globbed: refs/remotes/$refname\n";
+ "existing: $existing\n",
+ " globbed: $refname\n";
}
- my $u = (::cmt_metadata("refs/remotes/$refname"))[0];
+ my $u = (::cmt_metadata("$refname"))[0];
$u =~ s!^\Q$url\E(/|$)!! or die
- "refs/remotes/$refname: '$url' not found in '$u'\n";
+ "$refname: '$url' not found in '$u'\n";
if ($pathname ne $u) {
warn "W: Refspec glob conflict ",
- "(ref: refs/remotes/$refname):\n",
+ "(ref: $refname):\n",
"expected path: $pathname\n",
" real path: $u\n",
"Continuing ahead with $u\n";
@@ -1737,33 +1737,34 @@ sub read_all_remotes {
my $use_svm_props = eval { command_oneline(qw/config --bool
svn.useSvmProps/) };
$use_svm_props = $use_svm_props eq 'true' if $use_svm_props;
+ my $svn_refspec = qr{\s*/?(.*?)\s*:\s*(.+?)\s*};
foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
- if (m!^(.+)\.fetch=\s*(.*)\s*:\s*(.+)\s*$!) {
- my ($remote, $local_ref, $_remote_ref) = ($1, $2, $3);
- die("svn-remote.$remote: remote ref '$_remote_ref' "
- . "must start with 'refs/remotes/'\n")
- unless $_remote_ref =~ m{^refs/remotes/(.+)};
- my $remote_ref = $1;
- $local_ref =~ s{^/}{};
+ if (m!^(.+)\.fetch=$svn_refspec$!) {
+ my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
+ die("svn-remote.$remote: remote ref '$remote_ref' "
+ . "must start with 'refs/'\n")
+ unless $remote_ref =~ m{^refs/};
$r->{$remote}->{fetch}->{$local_ref} = $remote_ref;
$r->{$remote}->{svm} = {} if $use_svm_props;
} elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
$r->{$1}->{svm} = {};
} elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
$r->{$1}->{url} = $2;
- } elsif (m!^(.+)\.(branches|tags)=
- (.*):refs/remotes/(.+)\s*$/!x) {
- my ($p, $g) = ($3, $4);
+ } elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) {
+ my ($remote, $t, $local_ref, $remote_ref) = ($1, $2, $3, $4);
+ die("svn-remote.$remote: remote ref '$remote_ref' ($t) "
+ . "must start with 'refs/'\n")
+ unless $remote_ref =~ m{^refs/};
my $rs = {
- t => $2,
- remote => $1,
- path => Git::SVN::GlobSpec->new($p),
- ref => Git::SVN::GlobSpec->new($g) };
+ t => $t,
+ remote => $remote,
+ path => Git::SVN::GlobSpec->new($local_ref),
+ ref => Git::SVN::GlobSpec->new($remote_ref) };
if (length($rs->{ref}->{right}) != 0) {
die "The '*' glob character must be the last ",
- "character of '$g'\n";
+ "character of '$remote_ref'\n";
}
- push @{ $r->{$1}->{$2} }, $rs;
+ push @{ $r->{$remote}->{$t} }, $rs;
}
}
@@ -1871,9 +1872,9 @@ sub init_remote_config {
}
}
my ($xrepo_id, $xpath) = find_ref($self->refname);
- if (defined $xpath) {
+ if (!$no_write && defined $xpath) {
die "svn-remote.$xrepo_id.fetch already set to track ",
- "$xpath:refs/remotes/", $self->refname, "\n";
+ "$xpath:", $self->refname, "\n";
}
unless ($no_write) {
command_noisy('config',
@@ -1948,7 +1949,7 @@ sub find_ref {
my ($ref_id) = @_;
foreach (command(qw/config -l/)) {
next unless m!^svn-remote\.(.+)\.fetch=
- \s*(.*)\s*:\s*refs/remotes/(.+)\s*$!x;
+ \s*/?(.*?)\s*:\s*(.+?)\s*$!x;
my ($repo_id, $path, $ref) = ($1, $2, $3);
if ($ref eq $ref_id) {
$path = '' if ($path =~ m#^\./?#);
@@ -1965,16 +1966,16 @@ sub new {
if (!defined $repo_id) {
die "Could not find a \"svn-remote.*.fetch\" key ",
"in the repository configuration matching: ",
- "refs/remotes/$ref_id\n";
+ "$ref_id\n";
}
}
my $self = _new($class, $repo_id, $ref_id, $path);
if (!defined $self->{path} || !length $self->{path}) {
my $fetch = command_oneline('config', '--get',
"svn-remote.$repo_id.fetch",
- ":refs/remotes/$ref_id\$") or
+ ":$ref_id\$") or
die "Failed to read \"svn-remote.$repo_id.fetch\" ",
- "\":refs/remotes/$ref_id\$\" in config\n";
+ "\":$ref_id\$\" in config\n";
($self->{path}, undef) = split(/\s*:\s*/, $fetch);
}
$self->{url} = command_oneline('config', '--get',
@@ -1985,7 +1986,7 @@ sub new {
}
sub refname {
- my ($refname) = "refs/remotes/$_[0]->{ref_id}" ;
+ my ($refname) = $_[0]->{ref_id} ;
# It cannot end with a slash /, we'll throw up on this because
# SVN can't have directories with a slash in their name, either:
@@ -3320,12 +3321,12 @@ sub _new {
}
unless (defined $ref_id && length $ref_id) {
$_prefix = '' unless defined($_prefix);
- $_[2] = $ref_id = $_prefix . $Git::SVN::default_ref_id;
+ $_[2] = $ref_id = 'refs/remotes/' . $_prefix . $Git::SVN::default_ref_id;
}
$_[1] = $repo_id;
my $dir = "$ENV{GIT_DIR}/svn/$ref_id";
$_[3] = $path = '' unless (defined $path);
- mkpath(["$ENV{GIT_DIR}/svn"]);
+ mkpath(["$ENV{GIT_DIR}/svn/$ref_id"]);
bless {
ref_id => $ref_id, dir => $dir, index => "$dir/index",
path => $path, config => "$ENV{GIT_DIR}/svn/config",
@@ -3354,7 +3355,16 @@ sub rev_db_path {
sub map_path {
my ($self, $uuid) = @_;
$uuid ||= $self->ra_uuid;
- "$self->{map_root}.$uuid";
+ my $map_path = "$self->{map_root}.$uuid";
+ return $map_path if ( -f $map_path );
+
+ my $db_path = $map_path;
+ $db_path =~ s/\.rev_map/.rev_db/;
+ return $map_path if ( -f $db_path );
+
+ return $1 if ($map_path =~ m(refs/remotes/(.*)) && -f $1);
+ return $1 if ($db_path =~ m(refs/remotes/(.*)) && -f $1);
+ return $map_path;
}
sub uri_encode {
@@ -5498,7 +5508,7 @@ sub minimize_connections {
my $pfx = "svn-remote.$x->{old_repo_id}";
my $old_fetch = quotemeta("$x->{old_path}:".
- "refs/remotes/$x->{ref_id}");
+ "$x->{ref_id}");
command_noisy(qw/config --unset/,
"$pfx.fetch", '^'. $old_fetch . '$');
delete $r->{$x->{old_repo_id}}->
@@ -5567,7 +5577,7 @@ sub new {
my ($class, $glob) = @_;
my $re = $glob;
$re =~ s!/+$!!g; # no need for trailing slashes
- $re =~ m!^([^*]*)(\*(?:/\*)*)([^*]*)$!;
+ $re =~ m!^([^*]*)(\*(?:/\*)*)(.*)$!;
my $temp = $re;
my ($left, $right) = ($1, $3);
$re = $2;
diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh
index 5654962..fd8631f 100644
--- a/t/lib-git-svn.sh
+++ b/t/lib-git-svn.sh
@@ -14,7 +14,7 @@ if ! test_have_prereq PERL; then
fi
GIT_DIR=$PWD/.git
-GIT_SVN_DIR=$GIT_DIR/svn/git-svn
+GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn
SVN_TREE=$GIT_SVN_DIR/svn-tree
svn >/dev/null 2>&1
diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh
index 78610b6..bbfd7f4 100755
--- a/t/t9104-git-svn-follow-parent.sh
+++ b/t/t9104-git-svn-follow-parent.sh
@@ -172,11 +172,11 @@ test_expect_success "follow-parent is atomic" '
git update-ref refs/remotes/flunk@18 refs/remotes/stunk~2 &&
git update-ref -d refs/remotes/stunk &&
git config --unset svn-remote.svn.fetch stunk &&
- mkdir -p "$GIT_DIR"/svn/flunk@18 &&
- rev_map=$(cd "$GIT_DIR"/svn/stunk && ls .rev_map*) &&
- dd if="$GIT_DIR"/svn/stunk/$rev_map \
- of="$GIT_DIR"/svn/flunk@18/$rev_map bs=24 count=1 &&
- rm -rf "$GIT_DIR"/svn/stunk &&
+ mkdir -p "$GIT_DIR"/svn/refs/remotes/flunk@18 &&
+ rev_map=$(cd "$GIT_DIR"/svn/refs/remotes/stunk && ls .rev_map*) &&
+ dd if="$GIT_DIR"/svn/refs/remotes/stunk/$rev_map \
+ of="$GIT_DIR"/svn/refs/remotes/flunk@18/$rev_map bs=24 count=1 &&
+ rm -rf "$GIT_DIR"/svn/refs/remotes/stunk &&
git svn init --minimize-url -i flunk "$svnrepo"/flunk &&
git svn fetch -i flunk &&
git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh
index c0098d9..901b8e0 100755
--- a/t/t9107-git-svn-migrate.sh
+++ b/t/t9107-git-svn-migrate.sh
@@ -16,9 +16,7 @@ test_expect_success 'setup old-looking metadata' '
cd .. &&
git svn init "$svnrepo" &&
git svn fetch &&
- mv "$GIT_DIR"/svn/* "$GIT_DIR"/ &&
- mv "$GIT_DIR"/svn/.metadata "$GIT_DIR"/ &&
- rmdir "$GIT_DIR"/svn &&
+ rm -rf "$GIT_DIR"/svn &&
git update-ref refs/heads/git-svn-HEAD refs/${remotes_git_svn} &&
git update-ref refs/heads/svn-HEAD refs/${remotes_git_svn} &&
git update-ref -d refs/${remotes_git_svn} refs/${remotes_git_svn}
@@ -87,7 +85,7 @@ test_expect_success 'migrate --minimize on old inited layout' '
rm -rf "$GIT_DIR"/svn &&
for i in `cat fetch.out`; do
path=`expr $i : "\([^:]*\):.*$"`
- ref=`expr $i : "[^:]*:refs/remotes/\(.*\)$"`
+ ref=`expr $i : "[^:]*:\(refs/remotes/.*\)$"`
if test -z "$ref"; then continue; fi
if test -n "$path"; then path="/$path"; fi
( mkdir -p "$GIT_DIR"/svn/$ref/info/ &&
@@ -107,16 +105,16 @@ test_expect_success 'migrate --minimize on old inited layout' '
test_expect_success ".rev_db auto-converted to .rev_map.UUID" '
git svn fetch -i trunk &&
- test -z "$(ls "$GIT_DIR"/svn/trunk/.rev_db.* 2>/dev/null)" &&
- expect="$(ls "$GIT_DIR"/svn/trunk/.rev_map.*)" &&
+ test -z "$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db.* 2>/dev/null)" &&
+ expect="$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_map.*)" &&
test -n "$expect" &&
rev_db="$(echo $expect | sed -e "s,_map,_db,")" &&
convert_to_rev_db "$expect" "$rev_db" &&
rm -f "$expect" &&
test -f "$rev_db" &&
git svn fetch -i trunk &&
- test -z "$(ls "$GIT_DIR"/svn/trunk/.rev_db.* 2>/dev/null)" &&
- test ! -e "$GIT_DIR"/svn/trunk/.rev_db &&
+ test -z "$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db.* 2>/dev/null)" &&
+ test ! -e "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db &&
test -f "$expect"
'
diff --git a/t/t9143-git-svn-gc.sh b/t/t9143-git-svn-gc.sh
index f2ba2d1..99f69c6 100755
--- a/t/t9143-git-svn-gc.sh
+++ b/t/t9143-git-svn-gc.sh
@@ -28,26 +28,26 @@ test_expect_success 'Setup repo' 'git svn init "$svnrepo"'
test_expect_success 'Fetch repo' 'git svn fetch'
test_expect_success 'make backup copy of unhandled.log' '
- cp .git/svn/git-svn/unhandled.log tmp
+ cp .git/svn/refs/remotes/git-svn/unhandled.log tmp
'
-test_expect_success 'create leftover index' '> .git/svn/git-svn/index'
+test_expect_success 'create leftover index' '> .git/svn/refs/remotes/git-svn/index'
test_expect_success 'git svn gc runs' 'git svn gc'
-test_expect_success 'git svn index removed' '! test -f .git/svn/git-svn/index'
+test_expect_success 'git svn index removed' '! test -f .git/svn/refs/remotes/git-svn/index'
if perl -MCompress::Zlib -e 0 2>/dev/null
then
test_expect_success 'git svn gc produces a valid gzip file' '
- gunzip .git/svn/git-svn/unhandled.log.gz
+ gunzip .git/svn/refs/remotes/git-svn/unhandled.log.gz
'
else
say "Perl Compress::Zlib unavailable, skipping gunzip test"
fi
test_expect_success 'git svn gc does not change unhandled.log files' '
- test_cmp .git/svn/git-svn/unhandled.log tmp/unhandled.log
+ test_cmp .git/svn/refs/remotes/git-svn/unhandled.log tmp/unhandled.log
'
test_done
--
1.6.0.6
^ permalink raw reply related
* Re: [PATCH 5/8] Add a config option for remotes to specify a foreign vcs
From: Junio C Hamano @ 2009-08-12 3:26 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Jeff King, Nanako Shiraishi, Bert Wesarg, Junio C Hamano,
Daniel Barkalow, git, Brian Gernhardt
In-Reply-To: <alpine.DEB.1.00.0908120212500.8306@pacific.mpi-cbg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>> I have no problem with that, and I think it makes it even more visually
>> obvious what is going. For example:
>>
>> svn::http://server/path/to/repo
>>
>> makes the "svn" prefix jump out a bit more.
>
> ... and http:://repo.or.cz/r/git.git ? Thanks. But no, thanks.
Huh?
If you meant a "canonical format that always spells out the name of the
helper, and then whatever string the chosen helper uses to identify the
repository", that would be spelled as:
libcurl::http://repo.or.cz/r/git.git/
and will be handled by a single helper, git-remote-libcurl, that is
essentially what Linus and Daniel ejected from the builtin.
And in fact, that would be vastly more sensible than "we have one helper
that uses libcurl, but we hide the implementation detail and call the
helper with three names git-remote-{http,https,ftp}, so you would spell
the repository http://repo.or.cz/r/git.git/", which is what we have queued
in 'next/pu'.
And of course the use of "canonical format" for transports that git
traditionally has known about is only for consistency; we would want to
give shortcut for them. Obviously we would want "http://<anything>" to be
a short-hand for "curl::http://<anything>".
^ permalink raw reply
* Re: fatal: bad revision 'HEAD'
From: Jeff King @ 2009-08-12 3:27 UTC (permalink / raw)
To: Joel Mahoney; +Cc: Junio C Hamano, Johannes Schindelin, git
In-Reply-To: <C44788EB-02BA-4D69-8091-9E97827223A0@gmail.com>
[re-adding git@vger, since this discussion really belongs on the list]
On Tue, Aug 11, 2009 at 10:30:49AM -0600, Joel Mahoney wrote:
> here's what I get now:
>
> trace: built-in: git 'init'
> Initialized empty Git repository in /path/to/project/vendor/plugins/
> paperclip/.git/
> trace: exec: 'git-pull' '--depth' '1' 'git://github.com/thoughtbot/
> paperclip.git'
> trace: built-in: git 'rev-parse' '--git-dir'
> trace: built-in: git 'rev-parse' '--is-inside-work-tree'
> trace: built-in: git 'rev-parse' '--show-cdup'
> trace: built-in: git 'ls-files' '-u'
> trace: built-in: git 'symbolic-ref' '-q' 'HEAD'
> trace: built-in: git 'config' '--bool' 'branch.master.rebase'
> trace: built-in: git 'update-index' '--ignore-submodules' '--refresh'
> trace: built-in: git 'diff-files' '--ignore-submodules' '--quiet'
> trace: built-in: git 'diff-index' '--ignore-submodules' '--cached'
> '--quiet' 'HEAD' '--'
> fatal: bad revision 'HEAD'
> refusing to pull with rebase: your working tree is not up-to-date
I was able to replicate your problem, but only if I set
branch.master.rebase to "true" in my user-wide git config (i.e.,
~/.gitconfig). It looks like "git pull" is not capable of handling a
rebase when you have no commits yet.
I'm slightly dubious that such a configuration is sane, but probably
"git pull" should handle this case anyway, as you can easily replicate
it without config by doing:
git init && git pull --rebase /any/git/repo
Patch is below.
-- >8 --
Subject: [PATCH] allow pull --rebase on branch yet to be born
When doing a "pull --rebase", we check to make sure that the
index and working tree are clean. The index-clean check
compares the index against HEAD. The test erroneously
reports dirtiness if we don't have a HEAD yet.
In the case that we don't have a HEAD, we should just check
if the index has anything in it, which we can do by
comparing to the empty tree.
Signed-off-by: Jeff King <peff@peff.net>
---
Actually, this test is slightly more strict than the "index dirty" check
in git-rebase.sh itself. That test does "git diff-index HEAD", but
doesn't check the return code. It actually looks at whether it generates
output. So it would consider an index with something in it on a branch
yet-to-be-born to be clean, which is perhaps wrong.
Such a thing seems pretty unlikely in practice, though. I don't know if
it is worth making the two tests the same (maybe it is worth refactoring
into an index_is_clean function in git-sh-setup).
git-pull.sh | 8 +++++++-
t/t5520-pull.sh | 11 +++++++++++
2 files changed, 18 insertions(+), 1 deletions(-)
diff --git a/git-pull.sh b/git-pull.sh
index 0f24182..427b5c6 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -119,9 +119,15 @@ error_on_no_merge_candidates () {
}
test true = "$rebase" && {
+ if git rev-parse -q --verify HEAD >/dev/null; then
+ parent_tree=HEAD
+ else # empty tree
+ parent_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+ fi
+
git update-index --ignore-submodules --refresh &&
git diff-files --ignore-submodules --quiet &&
- git diff-index --ignore-submodules --cached --quiet HEAD -- ||
+ git diff-index --ignore-submodules --cached --quiet $parent_tree -- ||
die "refusing to pull with rebase: your working tree is not up-to-date"
oldremoteref= &&
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index e78d402..dd2ee84 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -149,4 +149,15 @@ test_expect_success 'pull --rebase dies early with dirty working directory' '
'
+test_expect_success 'pull --rebase works on branch yet to be born' '
+ git rev-parse master >expect &&
+ mkdir empty_repo &&
+ (cd empty_repo &&
+ git init &&
+ git pull --rebase .. master &&
+ git rev-parse HEAD >../actual
+ ) &&
+ test_cmp expect actual
+'
+
test_done
--
1.6.4.228.g9ab2.dirty
^ permalink raw reply related
* Git<->Accurev Bridge
From: Joshua Jensen @ 2009-08-12 4:02 UTC (permalink / raw)
To: git
Early last year, there was mention of a bridge between Git and Accurev.
Does anyone know what became of this project?
Thanks.
Josh
^ permalink raw reply
* Re: [RFC PATCH v3 7/8] Support sparse checkout in unpack_trees() and read-tree
From: skillzero @ 2009-08-12 4:59 UTC (permalink / raw)
To: Nguyen Thai Ngoc Duy
Cc: Jakub Narebski, git, Johannes Schindelin, Junio C Hamano
In-Reply-To: <fcaeb9bf0908111830n50bd4733h5033c6f13a45999@mail.gmail.com>
On Tue, Aug 11, 2009 at 6:30 PM, Nguyen Thai Ngoc Duy<pclouds@gmail.com> wrote:
> I think it's as easy as writing exclude patterns once you figure out '*'.
That solves it for me. Thanks.
^ permalink raw reply
* [PATCH 02/13] sequencer: add "--fast-forward" option to "git sequencer--helper"
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
This new option uses the "do_fast_forward()" function to perform
a fast forward.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 16 ++++++++++++----
1 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index 0cd7e98..bd72f65 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -19,6 +19,7 @@ static unsigned char head_sha1[20];
static const char * const git_sequencer_helper_usage[] = {
"git sequencer--helper --make-patch <commit>",
"git sequencer--helper --reset-hard <commit> <reflog-msg> <verbosity>",
+ "git sequencer--helper --fast-forward <commit> <reflog-msg> <verbosity>",
NULL
};
@@ -218,11 +219,14 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
{
char *patch_commit = NULL;
char *reset_commit = NULL;
+ char *ff_commit = NULL;
struct option options[] = {
OPT_STRING(0, "make-patch", &patch_commit, "commit",
"create a patch from commit"),
OPT_STRING(0, "reset-hard", &reset_commit, "commit",
"reset to commit"),
+ OPT_STRING(0, "fast-forward", &ff_commit, "commit",
+ "fast forward to commit"),
OPT_END()
};
@@ -239,15 +243,16 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
return 0;
}
- if (reset_commit) {
+ if (ff_commit || reset_commit) {
unsigned char sha1[20];
+ char *commit = ff_commit ? ff_commit : reset_commit;
if (argc != 2)
usage_with_options(git_sequencer_helper_usage,
options);
- if (get_sha1(reset_commit, sha1)) {
- error("Could not find '%s'", reset_commit);
+ if (get_sha1(commit, sha1)) {
+ error("Could not find '%s'", commit);
return 1;
}
@@ -258,7 +263,10 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
return 1;
}
- return reset_almost_hard(sha1);
+ if (ff_commit)
+ return do_fast_forward(sha1);
+ else
+ return reset_almost_hard(sha1);
}
usage_with_options(git_sequencer_helper_usage, options);
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 00/13] more changes to port rebase -i to C using sequencer code
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
These is just the current state of my work.
Some patches have already been sent but are not yet in pu.
Christian Couder (9):
sequencer: add "--fast-forward" option to "git sequencer--helper"
sequencer: let "git sequencer--helper" callers set "allow_dirty"
rebase -i: use "git sequencer--helper --fast-forward"
pick: simplify "error(...)" followed by "return -1"
pick: rename "pick()" to "pick_commit()"
pick: remove useless PICK_REVERSE => PICK_ADD_NOTE code
pick: simplify bogus comment about commiting immediately
pick: libify "pick_help_msg()"
rebase -i: use "git sequencer--helper --cherry-pick"
Stephan Beyer (4):
sequencer: add "do_fast_forward()" to perform a fast forward
revert: libify pick
sequencer: add "do_commit()" and related functions
sequencer: add "--cherry-pick" option to "git sequencer--helper"
Makefile | 2 +
builtin-revert.c | 293 +++++++------------------------------------
builtin-sequencer--helper.c | 298 ++++++++++++++++++++++++++++++++++++++++++-
git-rebase--interactive.sh | 19 +--
pick.c | 232 +++++++++++++++++++++++++++++++++
pick.h | 14 ++
6 files changed, 592 insertions(+), 266 deletions(-)
create mode 100644 pick.c
create mode 100644 pick.h
^ permalink raw reply
* [PATCH 01/13] sequencer: add "do_fast_forward()" to perform a fast forward
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
From: Stephan Beyer <s-beyer@gmx.net>
This code is taken from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(commit e7b8dab0c2a73ade92017a52bb1405ea1534ef20)
but the messages have been changed to be the same as those
displayed by git-rebase--interactive.sh.
Mentored-by: Daniel Barkalow <barkalow@iabervon.org>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index be030bc..0cd7e98 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -171,6 +171,15 @@ static struct commit *get_commit(const char *arg)
return lookup_commit_reference(sha1);
}
+static int do_fast_forward(const unsigned char *sha)
+{
+ if (reset_almost_hard(sha))
+ return error("Cannot fast forward to %s", sha1_to_hex(sha));
+ if (verbosity > 1)
+ printf("Fast forward to %s\n", sha1_to_hex(sha));
+ return 0;
+}
+
static int set_verbosity(int verbose)
{
char tmp[] = "0";
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 07/13] pick: rename "pick()" to "pick_commit()"
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-revert.c | 2 +-
pick.c | 8 ++++----
pick.h | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/builtin-revert.c b/builtin-revert.c
index 6dd29a3..4797ac5 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -206,7 +206,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
git_commit_encoding, encoding)))
commit->buffer = reencoded_message;
- failed = pick(commit, mainline, flags, &msgbuf);
+ failed = pick_commit(commit, mainline, flags, &msgbuf);
if (failed < 0) {
exit(1);
} else if (failed > 0) {
diff --git a/pick.c b/pick.c
index 6fea39c..13bf793 100644
--- a/pick.c
+++ b/pick.c
@@ -60,16 +60,16 @@ static struct tree *empty_tree(void)
}
/*
- * Pick changes introduced by pick_commit into current working tree
- * and index.
+ * Pick changes introduced by "commit" argument into current working
+ * tree and index.
*
* Return 0 on success.
* Return negative value on error before picking,
* and a positive value after picking,
* and return 1 if and only if a conflict occurs but no other error.
*/
-int pick(struct commit *pick_commit, int mainline, int flags,
- struct strbuf *msg)
+int pick_commit(struct commit *pick_commit, int mainline, int flags,
+ struct strbuf *msg)
{
unsigned char head[20];
struct commit *base, *next, *parent;
diff --git a/pick.h b/pick.h
index 7eb0d3a..7a74ad8 100644
--- a/pick.h
+++ b/pick.h
@@ -8,6 +8,6 @@
#define PICK_ADD_NOTE 2 /* add note about original commit (unless conflict) */
/* We don't need a PICK_QUIET. This is done by
* setenv("GIT_MERGE_VERBOSITY", "0", 1); */
-extern int pick(struct commit *pick_commit, int mainline, int flags, struct strbuf *msg);
+extern int pick_commit(struct commit *commit, int mainline, int flags, struct strbuf *msg);
#endif
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 08/13] pick: remove useless PICK_REVERSE => PICK_ADD_NOTE code
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
Useless of the removed code was found by Junio.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
pick.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/pick.c b/pick.c
index 13bf793..a6b1d6f 100644
--- a/pick.c
+++ b/pick.c
@@ -84,9 +84,6 @@ int pick_commit(struct commit *pick_commit, int mainline, int flags,
strbuf_init(msg, 0);
commit = pick_commit;
- if (flags & PICK_REVERSE) /* REVERSE implies ADD_NOTE */
- flags |= PICK_ADD_NOTE;
-
/*
* We do not intend to commit immediately. We just want to
* merge the differences in, so let's compute the tree
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 13/13] rebase -i: use "git sequencer--helper --cherry-pick"
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
instead of "git cherry-pick", as this will make it easier to
port "git-rebase--interactive.sh" to C.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
git-rebase--interactive.sh | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 7651fd6..30af512 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -147,7 +147,7 @@ pick_one () {
pick_one_preserving_merges "$@" && return
if test ! -z "$REBASE_ROOT"
then
- output git cherry-pick "$@"
+ git sequencer--helper --cherry-pick $sha1 $no_ff
return
fi
parent_sha1=$(git rev-parse --verify $sha1^) ||
@@ -157,7 +157,7 @@ pick_one () {
git sequencer--helper --fast-forward $sha1 \
"$GIT_REFLOG_ACTION" "$VERBOSE"
else
- output git cherry-pick "$@"
+ git sequencer--helper --cherry-pick $sha1 $no_ff
fi
}
@@ -269,7 +269,9 @@ pick_one_preserving_merges () {
fi
;;
*)
- output git cherry-pick "$@" ||
+ no_commit=
+ test "a$1" = "a-n" && no_commit=t
+ git sequencer--helper --cherry-pick $sha1 $no_commit ||
die_with_patch $sha1 "Could not pick $sha1"
;;
esac
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 10/13] pick: libify "pick_help_msg()"
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
This function gives an help message when pick or revert failed.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-revert.c | 23 +----------------------
pick.c | 22 ++++++++++++++++++++++
pick.h | 1 +
3 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/builtin-revert.c b/builtin-revert.c
index 4797ac5..e5250bd 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -142,27 +142,6 @@ static void set_author_ident_env(const char *message)
sha1_to_hex(commit->object.sha1));
}
-static char *help_msg(const unsigned char *sha1)
-{
- static char helpbuf[1024];
- char *msg = getenv("GIT_CHERRY_PICK_HELP");
-
- if (msg)
- return msg;
-
- strcpy(helpbuf, " After resolving the conflicts,\n"
- "mark the corrected paths with 'git add <paths>' "
- "or 'git rm <paths>' and commit the result.");
-
- if (!(flags & PICK_REVERSE)) {
- sprintf(helpbuf + strlen(helpbuf),
- "\nWhen commiting, use the option "
- "'-c %s' to retain authorship and message.",
- find_unique_abbrev(sha1, DEFAULT_ABBREV));
- }
- return helpbuf;
-}
-
static void write_message(struct strbuf *msgbuf, const char *filename)
{
struct lock_file msg_file;
@@ -211,7 +190,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
exit(1);
} else if (failed > 0) {
fprintf(stderr, "Automatic %s failed.%s\n",
- me, help_msg(commit->object.sha1));
+ me, pick_help_msg(commit->object.sha1, flags));
write_message(&msgbuf, git_path("MERGE_MSG"));
rerere();
exit(1);
diff --git a/pick.c b/pick.c
index 058b877..4f882bb 100644
--- a/pick.c
+++ b/pick.c
@@ -208,3 +208,25 @@ int pick_commit(struct commit *pick_commit, int mainline, int flags,
return ret;
}
+
+char *pick_help_msg(const unsigned char *sha1, int flags)
+{
+ static char helpbuf[1024];
+ char *msg = getenv("GIT_CHERRY_PICK_HELP");
+
+ if (msg)
+ return msg;
+
+ strcpy(helpbuf, " After resolving the conflicts,\n"
+ "mark the corrected paths with 'git add <paths>' "
+ "or 'git rm <paths>' and commit the result.");
+
+ if (!(flags & PICK_REVERSE)) {
+ sprintf(helpbuf + strlen(helpbuf),
+ "\nWhen commiting, use the option "
+ "'-c %s' to retain authorship and message.",
+ find_unique_abbrev(sha1, DEFAULT_ABBREV));
+ }
+ return helpbuf;
+}
+
diff --git a/pick.h b/pick.h
index 7a74ad8..115541a 100644
--- a/pick.h
+++ b/pick.h
@@ -9,5 +9,6 @@
/* We don't need a PICK_QUIET. This is done by
* setenv("GIT_MERGE_VERBOSITY", "0", 1); */
extern int pick_commit(struct commit *commit, int mainline, int flags, struct strbuf *msg);
+extern char *pick_help_msg(const unsigned char *sha1, int flags);
#endif
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 12/13] sequencer: add "--cherry-pick" option to "git sequencer--helper"
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
From: Stephan Beyer <s-beyer@gmx.net>
This patch adds some code that comes from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(commit e7b8dab0c2a73ade92017a52bb1405ea1534ef20)
Most of the code is taken from the insn_pick_act() function.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 52 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 51 insertions(+), 1 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index 61a8f2e..0f2255a 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -288,7 +288,7 @@ static int do_commit(unsigned char *parent_sha1)
if (update_ref(reflog, "HEAD", commit_sha1, NULL, 0, 0))
return error("Could not update HEAD to %s.",
- sha1_to_hex(commit_sha1));
+ sha1_to_hex(commit_sha1));
return 0;
}
@@ -436,6 +436,7 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
char *patch_commit = NULL;
char *reset_commit = NULL;
char *ff_commit = NULL;
+ char *cp_commit = NULL;
struct option options[] = {
OPT_STRING(0, "make-patch", &patch_commit, "commit",
"create a patch from commit"),
@@ -443,6 +444,8 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
"reset to commit"),
OPT_STRING(0, "fast-forward", &ff_commit, "commit",
"fast forward to commit"),
+ OPT_STRING(0, "cherry-pick", &cp_commit, "commit",
+ "cherry pick commit"),
OPT_END()
};
@@ -488,5 +491,52 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
return reset_almost_hard(sha1);
}
+ if (cp_commit) {
+ struct commit *commit;
+ int failed;
+ const char *author;
+ int no_commit = 0;
+
+ if (argc != 0 && argc != 1)
+ usage_with_options(git_sequencer_helper_usage,
+ options);
+
+ if (argc == 1 && *argv[0] && strcmp(argv[0], "0"))
+ no_commit = 1;
+
+ if (get_sha1("HEAD", head_sha1))
+ return error("You do not have a valid HEAD.");
+
+ commit = get_commit(cp_commit);
+ if (!commit)
+ return 1;
+
+ set_pick_subject(cp_commit, commit);
+
+ failed = pick_commit(commit, 0, 0, &next_commit.summary);
+
+ set_message_source(sha1_to_hex(commit->object.sha1));
+ author = strstr(commit->buffer, "\nauthor ");
+ if (author)
+ set_author_info(author + 8);
+
+ /* We do not want extra Conflicts: lines on cherry-pick,
+ so just take the old commit message. */
+ if (failed) {
+ strbuf_setlen(&next_commit.summary, 0);
+ strbuf_addstr(&next_commit.summary,
+ strstr(commit->buffer, "\n\n") + 2);
+ rerere();
+ make_patch(commit);
+ write_commit_summary_into(MERGE_MSG);
+ return error(pick_help_msg(commit->object.sha1, 0));
+ }
+
+ if (!no_commit && do_commit(head_sha1))
+ return error("Could not commit.");
+
+ return 0;
+ }
+
usage_with_options(git_sequencer_helper_usage, options);
}
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 04/13] rebase -i: use "git sequencer--helper --fast-forward"
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
when fast forwarding.
Note that in the first hunk of this patch, there was this line:
test "a$1" = a-n && output git reset --soft $current_sha1
but the test always failed.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
git-rebase--interactive.sh | 11 +++--------
1 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0041994..7651fd6 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -154,11 +154,8 @@ pick_one () {
die "Could not get the parent of $sha1"
current_sha1=$(git rev-parse --verify HEAD)
if test "$no_ff$current_sha1" = "$parent_sha1"; then
- git sequencer--helper --reset-hard $sha1 \
+ git sequencer--helper --fast-forward $sha1 \
"$GIT_REFLOG_ACTION" "$VERBOSE"
- test "a$1" = a-n && output git reset --soft $current_sha1
- sha1=$(git rev-parse --short $sha1)
- output warn Fast forward to $sha1
else
output git cherry-pick "$@"
fi
@@ -238,10 +235,8 @@ pick_one_preserving_merges () {
done
case $fast_forward in
t)
- output warn "Fast forward to $sha1"
- git sequencer--helper --reset-hard $sha1 \
- "$GIT_REFLOG_ACTION" "$VERBOSE" ||
- die "Cannot fast forward to $sha1"
+ git sequencer--helper --fast-forward $sha1 \
+ "$GIT_REFLOG_ACTION" "$VERBOSE" || exit
;;
f)
first_parent=$(expr "$new_parents" : ' \([^ ]*\)')
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 03/13] sequencer: let "git sequencer--helper" callers set "allow_dirty"
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
This flag can be set when using --reset-hard or --fast-forward, and
in this case changes in the work tree will be kept.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index bd72f65..71a7fef 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -18,8 +18,10 @@ static unsigned char head_sha1[20];
static const char * const git_sequencer_helper_usage[] = {
"git sequencer--helper --make-patch <commit>",
- "git sequencer--helper --reset-hard <commit> <reflog-msg> <verbosity>",
- "git sequencer--helper --fast-forward <commit> <reflog-msg> <verbosity>",
+ "git sequencer--helper --reset-hard <commit> <reflog-msg> "
+ "<verbosity> [<allow-dirty>]",
+ "git sequencer--helper --fast-forward <commit> <reflog-msg> "
+ "<verbosity> [<allow-dirty>]",
NULL
};
@@ -247,7 +249,7 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
unsigned char sha1[20];
char *commit = ff_commit ? ff_commit : reset_commit;
- if (argc != 2)
+ if (argc != 2 && argc != 3)
usage_with_options(git_sequencer_helper_usage,
options);
@@ -263,6 +265,9 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
return 1;
}
+ if (argc == 3 && *argv[2] && strcmp(argv[2], "0"))
+ allow_dirty = 1;
+
if (ff_commit)
return do_fast_forward(sha1);
else
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 09/13] pick: simplify bogus comment about commiting immediately
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
as suggested by Junio.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
pick.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/pick.c b/pick.c
index a6b1d6f..058b877 100644
--- a/pick.c
+++ b/pick.c
@@ -85,10 +85,8 @@ int pick_commit(struct commit *pick_commit, int mainline, int flags,
commit = pick_commit;
/*
- * We do not intend to commit immediately. We just want to
- * merge the differences in, so let's compute the tree
- * that represents the "current" state for merge-recursive
- * to work on.
+ * Let's compute the tree that represents the "current" state
+ * for merge-recursive to work on.
*/
if (write_cache_as_tree(head, 0, NULL))
return error("Your index file is unmerged.");
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 05/13] revert: libify pick
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
From: Stephan Beyer <s-beyer@gmx.net>
This commit is made of code from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(commit e7b8dab0c2a73ade92017a52bb1405ea1534ef20)
The goal of this commit is to abstract out pick functionnality
into a new pick() function made of code from "builtin-revert.c".
The new pick() function is in a new "pick.c" file with an
associated "pick.h".
"pick.h" and "pick.c" are strictly the same as on the sequencer repo,
but a few changes were needed on "builtin-revert.c" to keep it up to
date with changes on git.git.
Mentored-by: Daniel Barkalow <barkalow@iabervon.org>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Makefile | 2 +
builtin-revert.c | 272 +++++++++---------------------------------------------
pick.c | 229 +++++++++++++++++++++++++++++++++++++++++++++
pick.h | 13 +++
4 files changed, 288 insertions(+), 228 deletions(-)
create mode 100644 pick.c
create mode 100644 pick.h
diff --git a/Makefile b/Makefile
index 189aee5..03ddc59 100644
--- a/Makefile
+++ b/Makefile
@@ -444,6 +444,7 @@ LIB_H += pack-refs.h
LIB_H += pack-revindex.h
LIB_H += parse-options.h
LIB_H += patch-ids.h
+LIB_H += pick.h
LIB_H += pkt-line.h
LIB_H += progress.h
LIB_H += quote.h
@@ -532,6 +533,7 @@ LIB_OBJS += parse-options.o
LIB_OBJS += patch-delta.o
LIB_OBJS += patch-ids.o
LIB_OBJS += path.o
+LIB_OBJS += pick.o
LIB_OBJS += pkt-line.o
LIB_OBJS += preload-index.o
LIB_OBJS += pretty.o
diff --git a/builtin-revert.c b/builtin-revert.c
index 151aa6a..6dd29a3 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -1,18 +1,14 @@
#include "cache.h"
#include "builtin.h"
-#include "object.h"
#include "commit.h"
#include "tag.h"
-#include "wt-status.h"
-#include "run-command.h"
#include "exec_cmd.h"
#include "utf8.h"
#include "parse-options.h"
-#include "cache-tree.h"
#include "diff.h"
#include "revision.h"
#include "rerere.h"
-#include "merge-recursive.h"
+#include "pick.h"
/*
* This implements the builtins revert and cherry-pick.
@@ -35,25 +31,23 @@ static const char * const cherry_pick_usage[] = {
NULL
};
-static int edit, no_replay, no_commit, mainline, signoff;
-static enum { REVERT, CHERRY_PICK } action;
+static int edit, no_commit, mainline, signoff;
+static int flags;
static struct commit *commit;
-static const char *me;
-
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
static void parse_args(int argc, const char **argv)
{
const char * const * usage_str =
- action == REVERT ? revert_usage : cherry_pick_usage;
+ flags & PICK_REVERSE ? revert_usage : cherry_pick_usage;
unsigned char sha1[20];
const char *arg;
int noop;
struct option options[] = {
OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"),
- OPT_BOOLEAN('x', NULL, &no_replay, "append commit name when cherry-picking"),
+ OPT_BIT('x', NULL, &flags, "append commit name when cherry-picking", PICK_ADD_NOTE),
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
@@ -77,42 +71,12 @@ static void parse_args(int argc, const char **argv)
die ("'%s' does not point to a commit", arg);
}
-static char *get_oneline(const char *message)
-{
- char *result;
- const char *p = message, *abbrev, *eol;
- int abbrev_len, oneline_len;
-
- if (!p)
- die ("Could not read commit message of %s",
- sha1_to_hex(commit->object.sha1));
- while (*p && (*p != '\n' || p[1] != '\n'))
- p++;
-
- if (*p) {
- p += 2;
- for (eol = p + 1; *eol && *eol != '\n'; eol++)
- ; /* do nothing */
- } else
- eol = p;
- abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
- abbrev_len = strlen(abbrev);
- oneline_len = eol - p;
- result = xmalloc(abbrev_len + 5 + oneline_len);
- memcpy(result, abbrev, abbrev_len);
- memcpy(result + abbrev_len, "... ", 4);
- memcpy(result + abbrev_len + 4, p, oneline_len);
- result[abbrev_len + 4 + oneline_len] = '\0';
- return result;
-}
-
static char *get_encoding(const char *message)
{
const char *p = message, *eol;
if (!p)
- die ("Could not read commit message of %s",
- sha1_to_hex(commit->object.sha1));
+ return NULL;
while (*p && *p != '\n') {
for (eol = p + 1; *eol && *eol != '\n'; eol++)
; /* do nothing */
@@ -128,30 +92,6 @@ static char *get_encoding(const char *message)
return NULL;
}
-static struct lock_file msg_file;
-static int msg_fd;
-
-static void add_to_msg(const char *string)
-{
- int len = strlen(string);
- if (write_in_full(msg_fd, string, len) < 0)
- die_errno ("Could not write to MERGE_MSG");
-}
-
-static void add_message_to_msg(const char *message)
-{
- const char *p = message;
- while (*p && (*p != '\n' || p[1] != '\n'))
- p++;
-
- if (!*p)
- add_to_msg(sha1_to_hex(commit->object.sha1));
-
- p += 2;
- add_to_msg(p);
- return;
-}
-
static void set_author_ident_env(const char *message)
{
const char *p = message;
@@ -214,7 +154,7 @@ static char *help_msg(const unsigned char *sha1)
"mark the corrected paths with 'git add <paths>' "
"or 'git rm <paths>' and commit the result.");
- if (action == CHERRY_PICK) {
+ if (!(flags & PICK_REVERSE)) {
sprintf(helpbuf + strlen(helpbuf),
"\nWhen commiting, use the option "
"'-c %s' to retain authorship and message.",
@@ -223,187 +163,68 @@ static char *help_msg(const unsigned char *sha1)
return helpbuf;
}
-static struct tree *empty_tree(void)
+static void write_message(struct strbuf *msgbuf, const char *filename)
{
- struct tree *tree = xcalloc(1, sizeof(struct tree));
-
- tree->object.parsed = 1;
- tree->object.type = OBJ_TREE;
- pretend_sha1_file(NULL, 0, OBJ_TREE, tree->object.sha1);
- return tree;
+ struct lock_file msg_file;
+ int msg_fd;
+ msg_fd = hold_lock_file_for_update(&msg_file, filename,
+ LOCK_DIE_ON_ERROR);
+ if (write_in_full(msg_fd, msgbuf->buf, msgbuf->len) < 0)
+ die_errno("Could not write to %s.", filename);
+ strbuf_release(msgbuf);
+ if (commit_lock_file(&msg_file) < 0)
+ die("Error wrapping up %s", filename);
}
static int revert_or_cherry_pick(int argc, const char **argv)
{
- unsigned char head[20];
- struct commit *base, *next, *parent;
- int i, index_fd, clean;
- char *oneline, *reencoded_message = NULL;
- const char *message, *encoding;
- char *defmsg = git_pathdup("MERGE_MSG");
- struct merge_options o;
- struct tree *result, *next_tree, *base_tree, *head_tree;
- static struct lock_file index_lock;
+ const char *me;
+ struct strbuf msgbuf;
+ char *reencoded_message = NULL;
+ const char *encoding;
+ int failed;
git_config(git_default_config, NULL);
- me = action == REVERT ? "revert" : "cherry-pick";
+ me = flags & PICK_REVERSE ? "revert" : "cherry-pick";
setenv(GIT_REFLOG_ACTION, me, 0);
parse_args(argc, argv);
- /* this is copied from the shell script, but it's never triggered... */
- if (action == REVERT && !no_replay)
- die("revert is incompatible with replay");
-
if (read_cache() < 0)
die("git %s: failed to read the index", me);
- if (no_commit) {
- /*
- * We do not intend to commit immediately. We just want to
- * merge the differences in, so let's compute the tree
- * that represents the "current" state for merge-recursive
- * to work on.
- */
- if (write_cache_as_tree(head, 0, NULL))
- die ("Your index file is unmerged.");
- } else {
- if (get_sha1("HEAD", head))
- die ("You do not have a valid HEAD");
- if (index_differs_from("HEAD", 0))
- die ("Dirty index: cannot %s", me);
- }
- discard_cache();
-
- index_fd = hold_locked_index(&index_lock, 1);
+ if (!no_commit && index_differs_from("HEAD", 0))
+ die ("Dirty index: cannot %s", me);
- if (!commit->parents) {
- if (action == REVERT)
- die ("Cannot revert a root commit");
- parent = NULL;
- }
- else if (commit->parents->next) {
- /* Reverting or cherry-picking a merge commit */
- int cnt;
- struct commit_list *p;
-
- if (!mainline)
- die("Commit %s is a merge but no -m option was given.",
- sha1_to_hex(commit->object.sha1));
-
- for (cnt = 1, p = commit->parents;
- cnt != mainline && p;
- cnt++)
- p = p->next;
- if (cnt != mainline || !p)
- die("Commit %s does not have parent %d",
- sha1_to_hex(commit->object.sha1), mainline);
- parent = p->item;
- } else if (0 < mainline)
- die("Mainline was specified but commit %s is not a merge.",
- sha1_to_hex(commit->object.sha1));
- else
- parent = commit->parents->item;
-
- if (!(message = commit->buffer))
- die ("Cannot get commit message for %s",
+ if (!commit->buffer)
+ return error("Cannot get commit message for %s",
sha1_to_hex(commit->object.sha1));
-
- if (parent && parse_commit(parent) < 0)
- die("%s: cannot parse parent commit %s",
- me, sha1_to_hex(parent->object.sha1));
-
- /*
- * "commit" is an existing commit. We would want to apply
- * the difference it introduces since its first parent "prev"
- * on top of the current HEAD if we are cherry-pick. Or the
- * reverse of it if we are revert.
- */
-
- msg_fd = hold_lock_file_for_update(&msg_file, defmsg,
- LOCK_DIE_ON_ERROR);
-
- encoding = get_encoding(message);
+ encoding = get_encoding(commit->buffer);
if (!encoding)
encoding = "UTF-8";
if (!git_commit_encoding)
git_commit_encoding = "UTF-8";
- if ((reencoded_message = reencode_string(message,
+ if ((reencoded_message = reencode_string(commit->buffer,
git_commit_encoding, encoding)))
- message = reencoded_message;
-
- oneline = get_oneline(message);
-
- if (action == REVERT) {
- char *oneline_body = strchr(oneline, ' ');
+ commit->buffer = reencoded_message;
- base = commit;
- next = parent;
- add_to_msg("Revert \"");
- add_to_msg(oneline_body + 1);
- add_to_msg("\"\n\nThis reverts commit ");
- add_to_msg(sha1_to_hex(commit->object.sha1));
-
- if (commit->parents->next) {
- add_to_msg(", reversing\nchanges made to ");
- add_to_msg(sha1_to_hex(parent->object.sha1));
- }
- add_to_msg(".\n");
- } else {
- base = parent;
- next = commit;
- set_author_ident_env(message);
- add_message_to_msg(message);
- if (no_replay) {
- add_to_msg("(cherry picked from commit ");
- add_to_msg(sha1_to_hex(commit->object.sha1));
- add_to_msg(")\n");
- }
- }
-
- read_cache();
- init_merge_options(&o);
- o.branch1 = "HEAD";
- o.branch2 = oneline;
-
- head_tree = parse_tree_indirect(head);
- next_tree = next ? next->tree : empty_tree();
- base_tree = base ? base->tree : empty_tree();
-
- clean = merge_trees(&o,
- head_tree,
- next_tree, base_tree, &result);
-
- if (active_cache_changed &&
- (write_cache(index_fd, active_cache, active_nr) ||
- commit_locked_index(&index_lock)))
- die("%s: Unable to write new index file", me);
- rollback_lock_file(&index_lock);
-
- if (!clean) {
- add_to_msg("\nConflicts:\n\n");
- for (i = 0; i < active_nr;) {
- struct cache_entry *ce = active_cache[i++];
- if (ce_stage(ce)) {
- add_to_msg("\t");
- add_to_msg(ce->name);
- add_to_msg("\n");
- while (i < active_nr && !strcmp(ce->name,
- active_cache[i]->name))
- i++;
- }
- }
- if (commit_lock_file(&msg_file) < 0)
- die ("Error wrapping up %s", defmsg);
+ failed = pick(commit, mainline, flags, &msgbuf);
+ if (failed < 0) {
+ exit(1);
+ } else if (failed > 0) {
fprintf(stderr, "Automatic %s failed.%s\n",
me, help_msg(commit->object.sha1));
+ write_message(&msgbuf, git_path("MERGE_MSG"));
rerere();
exit(1);
}
- if (commit_lock_file(&msg_file) < 0)
- die ("Error wrapping up %s", defmsg);
+ if (!(flags & PICK_REVERSE))
+ set_author_ident_env(commit->buffer);
+ free(reencoded_message);
+
fprintf(stderr, "Finished one %s.\n", me);
+ write_message(&msgbuf, git_path("MERGE_MSG"));
+
/*
- *
* If we are cherry-pick, and if the merge did not result in
* hand-editing, we will hit this commit and inherit the original
* author date and name.
@@ -421,14 +242,11 @@ static int revert_or_cherry_pick(int argc, const char **argv)
args[i++] = "-s";
if (!edit) {
args[i++] = "-F";
- args[i++] = defmsg;
+ args[i++] = git_path("MERGE_MSG");
}
args[i] = NULL;
return execv_git_cmd(args);
}
- free(reencoded_message);
- free(defmsg);
-
return 0;
}
@@ -436,14 +254,12 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
{
if (isatty(0))
edit = 1;
- no_replay = 1;
- action = REVERT;
+ flags = PICK_REVERSE | PICK_ADD_NOTE;
return revert_or_cherry_pick(argc, argv);
}
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
{
- no_replay = 0;
- action = CHERRY_PICK;
+ flags = 0;
return revert_or_cherry_pick(argc, argv);
}
diff --git a/pick.c b/pick.c
new file mode 100644
index 0000000..77c7169
--- /dev/null
+++ b/pick.c
@@ -0,0 +1,229 @@
+#include "cache.h"
+#include "commit.h"
+#include "run-command.h"
+#include "cache-tree.h"
+#include "pick.h"
+#include "merge-recursive.h"
+
+static struct commit *commit;
+
+static char *get_oneline(const char *message)
+{
+ char *result;
+ const char *p = message, *abbrev, *eol;
+ int abbrev_len, oneline_len;
+
+ if (!p)
+ return NULL;
+ while (*p && (*p != '\n' || p[1] != '\n'))
+ p++;
+
+ if (*p) {
+ p += 2;
+ for (eol = p + 1; *eol && *eol != '\n'; eol++)
+ ; /* do nothing */
+ } else
+ eol = p;
+ abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
+ abbrev_len = strlen(abbrev);
+ oneline_len = eol - p;
+ result = xmalloc(abbrev_len + 5 + oneline_len);
+ memcpy(result, abbrev, abbrev_len);
+ memcpy(result + abbrev_len, "... ", 4);
+ memcpy(result + abbrev_len + 4, p, oneline_len);
+ result[abbrev_len + 4 + oneline_len] = '\0';
+ return result;
+}
+
+static void add_message_to_msg(struct strbuf *msg, const char *message)
+{
+ const char *p = message;
+ while (*p && (*p != '\n' || p[1] != '\n'))
+ p++;
+
+ if (!*p)
+ strbuf_addstr(msg, sha1_to_hex(commit->object.sha1));
+
+ p += 2;
+ strbuf_addstr(msg, p);
+ return;
+}
+
+static struct tree *empty_tree(void)
+{
+ struct tree *tree = xcalloc(1, sizeof(struct tree));
+
+ tree->object.parsed = 1;
+ tree->object.type = OBJ_TREE;
+ pretend_sha1_file(NULL, 0, OBJ_TREE, tree->object.sha1);
+ return tree;
+}
+
+/*
+ * Pick changes introduced by pick_commit into current working tree
+ * and index.
+ *
+ * Return 0 on success.
+ * Return negative value on error before picking,
+ * and a positive value after picking,
+ * and return 1 if and only if a conflict occurs but no other error.
+ */
+int pick(struct commit *pick_commit, int mainline, int flags,
+ struct strbuf *msg)
+{
+ unsigned char head[20];
+ struct commit *base, *next, *parent;
+ int i, index_fd, clean;
+ int ret = 0;
+ char *oneline;
+ const char *message;
+ struct merge_options o;
+ struct tree *result, *next_tree, *base_tree, *head_tree;
+ static struct lock_file index_lock;
+
+ strbuf_init(msg, 0);
+ commit = pick_commit;
+
+ if (flags & PICK_REVERSE) /* REVERSE implies ADD_NOTE */
+ flags |= PICK_ADD_NOTE;
+
+ /*
+ * We do not intend to commit immediately. We just want to
+ * merge the differences in, so let's compute the tree
+ * that represents the "current" state for merge-recursive
+ * to work on.
+ */
+ if (write_cache_as_tree(head, 0, NULL)) {
+ error("Your index file is unmerged.");
+ return -1;
+ }
+ discard_cache();
+
+ index_fd = hold_locked_index(&index_lock, 0);
+ if (index_fd < 0) {
+ error("Unable to create locked index: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ if (!commit->parents) {
+ if (flags & PICK_REVERSE) {
+ error("Cannot revert a root commit");
+ return -1;
+ }
+ parent = NULL;
+ }
+ else if (commit->parents->next) {
+ /* Reverting or cherry-picking a merge commit */
+ int cnt;
+ struct commit_list *p;
+
+ if (!mainline) {
+ error("Commit %s is a merge but no mainline was given.",
+ sha1_to_hex(commit->object.sha1));
+ return -1;
+ }
+
+ for (cnt = 1, p = commit->parents;
+ cnt != mainline && p;
+ cnt++)
+ p = p->next;
+ if (cnt != mainline || !p) {
+ error("Commit %s does not have parent %d",
+ sha1_to_hex(commit->object.sha1), mainline);
+ return -1;
+ }
+ parent = p->item;
+ } else if (0 < mainline) {
+ error("Mainline was specified but commit %s is not a merge.",
+ sha1_to_hex(commit->object.sha1));
+ return -1;
+ } else
+ parent = commit->parents->item;
+
+ if (!(message = commit->buffer)) {
+ error("Cannot get commit message for %s",
+ sha1_to_hex(commit->object.sha1));
+ return -1;
+ }
+
+ if (parent && parse_commit(parent) < 0) {
+ error("Cannot parse parent commit %s",
+ sha1_to_hex(parent->object.sha1));
+ return -1;
+ }
+
+ oneline = get_oneline(message);
+
+ if (flags & PICK_REVERSE) {
+ char *oneline_body = strchr(oneline, ' ');
+
+ base = commit;
+ next = parent;
+ strbuf_addstr(msg, "Revert \"");
+ strbuf_addstr(msg, oneline_body + 1);
+ strbuf_addstr(msg, "\"\n\nThis reverts commit ");
+ strbuf_addstr(msg, sha1_to_hex(commit->object.sha1));
+
+ if (commit->parents->next) {
+ strbuf_addstr(msg, ", reversing\nchanges made to ");
+ strbuf_addstr(msg, sha1_to_hex(parent->object.sha1));
+ }
+ strbuf_addstr(msg, ".\n");
+ } else {
+ base = parent;
+ next = commit;
+ add_message_to_msg(msg, message);
+ if (flags & PICK_ADD_NOTE) {
+ strbuf_addstr(msg, "(cherry picked from commit ");
+ strbuf_addstr(msg, sha1_to_hex(commit->object.sha1));
+ strbuf_addstr(msg, ")\n");
+ }
+ }
+
+ read_cache();
+ init_merge_options(&o);
+ o.branch1 = "HEAD";
+ o.branch2 = oneline;
+
+ head_tree = parse_tree_indirect(head);
+ next_tree = next ? next->tree : empty_tree();
+ base_tree = base ? base->tree : empty_tree();
+
+ clean = merge_trees(&o,
+ head_tree,
+ next_tree, base_tree, &result);
+
+ if (active_cache_changed &&
+ (write_cache(index_fd, active_cache, active_nr) ||
+ commit_locked_index(&index_lock))) {
+ error("Unable to write new index file");
+ return 2;
+ }
+ rollback_lock_file(&index_lock);
+
+ if (!clean) {
+ strbuf_addstr(msg, "\nConflicts:\n\n");
+ for (i = 0; i < active_nr;) {
+ struct cache_entry *ce = active_cache[i++];
+ if (ce_stage(ce)) {
+ strbuf_addstr(msg, "\t");
+ strbuf_addstr(msg, ce->name);
+ strbuf_addstr(msg, "\n");
+ while (i < active_nr && !strcmp(ce->name,
+ active_cache[i]->name))
+ i++;
+ }
+ }
+ ret = 1;
+ }
+ free(oneline);
+
+ discard_cache();
+ if (read_cache() < 0) {
+ error("Cannot read the index");
+ return 2;
+ }
+
+ return ret;
+}
diff --git a/pick.h b/pick.h
new file mode 100644
index 0000000..7eb0d3a
--- /dev/null
+++ b/pick.h
@@ -0,0 +1,13 @@
+#ifndef PICK_H
+#define PICK_H
+
+#include "commit.h"
+
+/* Pick flags: */
+#define PICK_REVERSE 1 /* pick the reverse changes ("revert") */
+#define PICK_ADD_NOTE 2 /* add note about original commit (unless conflict) */
+/* We don't need a PICK_QUIET. This is done by
+ * setenv("GIT_MERGE_VERBOSITY", "0", 1); */
+extern int pick(struct commit *pick_commit, int mainline, int flags, struct strbuf *msg);
+
+#endif
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 06/13] pick: simplify "error(...)" followed by "return -1"
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
into "return error(...)", as suggested by Junio.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
pick.c | 62 ++++++++++++++++++++++++--------------------------------------
1 files changed, 24 insertions(+), 38 deletions(-)
diff --git a/pick.c b/pick.c
index 77c7169..6fea39c 100644
--- a/pick.c
+++ b/pick.c
@@ -93,24 +93,18 @@ int pick(struct commit *pick_commit, int mainline, int flags,
* that represents the "current" state for merge-recursive
* to work on.
*/
- if (write_cache_as_tree(head, 0, NULL)) {
- error("Your index file is unmerged.");
- return -1;
- }
+ if (write_cache_as_tree(head, 0, NULL))
+ return error("Your index file is unmerged.");
discard_cache();
index_fd = hold_locked_index(&index_lock, 0);
- if (index_fd < 0) {
- error("Unable to create locked index: %s",
- strerror(errno));
- return -1;
- }
+ if (index_fd < 0)
+ return error("Unable to create locked index: %s",
+ strerror(errno));
if (!commit->parents) {
- if (flags & PICK_REVERSE) {
- error("Cannot revert a root commit");
- return -1;
- }
+ if (flags & PICK_REVERSE)
+ return error("Cannot revert a root commit");
parent = NULL;
}
else if (commit->parents->next) {
@@ -118,40 +112,32 @@ int pick(struct commit *pick_commit, int mainline, int flags,
int cnt;
struct commit_list *p;
- if (!mainline) {
- error("Commit %s is a merge but no mainline was given.",
- sha1_to_hex(commit->object.sha1));
- return -1;
- }
+ if (!mainline)
+ return error("Commit %s is a merge but no mainline was given.",
+ sha1_to_hex(commit->object.sha1));
for (cnt = 1, p = commit->parents;
cnt != mainline && p;
cnt++)
p = p->next;
- if (cnt != mainline || !p) {
- error("Commit %s does not have parent %d",
- sha1_to_hex(commit->object.sha1), mainline);
- return -1;
- }
+ if (cnt != mainline || !p)
+ return error("Commit %s does not have parent %d",
+ sha1_to_hex(commit->object.sha1),
+ mainline);
parent = p->item;
- } else if (0 < mainline) {
- error("Mainline was specified but commit %s is not a merge.",
- sha1_to_hex(commit->object.sha1));
- return -1;
- } else
+ } else if (0 < mainline)
+ return error("Mainline was specified but commit %s is not a merge.",
+ sha1_to_hex(commit->object.sha1));
+ else
parent = commit->parents->item;
- if (!(message = commit->buffer)) {
- error("Cannot get commit message for %s",
- sha1_to_hex(commit->object.sha1));
- return -1;
- }
+ if (!(message = commit->buffer))
+ return error("Cannot get commit message for %s",
+ sha1_to_hex(commit->object.sha1));
- if (parent && parse_commit(parent) < 0) {
- error("Cannot parse parent commit %s",
- sha1_to_hex(parent->object.sha1));
- return -1;
- }
+ if (parent && parse_commit(parent) < 0)
+ return error("Cannot parse parent commit %s",
+ sha1_to_hex(parent->object.sha1));
oneline = get_oneline(message);
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 11/13] sequencer: add "do_commit()" and related functions
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
In-Reply-To: <20090812051116.18155.70541.chriscool@tuxfamily.org>
From: Stephan Beyer <s-beyer@gmx.net>
This patch adds some code that comes from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(commit e7b8dab0c2a73ade92017a52bb1405ea1534ef20)
It adds "struct commit_info", the "next_commit" static variable and
the following functions:
- do_commit()
- set_author_info()
- set_message_source()
- set_pick_subject()
- write_commit_summary_into()
This makes it possible to prepare and perform a commit.
Compared to the sequencer project, the only change is that "mark"
related (3 lines long) code has been removed from do_commit().
Mentored-by: Daniel Barkalow <barkalow@iabervon.org>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 214 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 214 insertions(+), 0 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index 71a7fef..61a8f2e 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -5,26 +5,69 @@
#include "refs.h"
#include "diff.h"
#include "unpack-trees.h"
+#include "string-list.h"
+#include "pick.h"
+#include "rerere.h"
+#include "dir.h"
+#include "cache-tree.h"
+#include "utf8.h"
#define SEQ_DIR "rebase-merge"
#define PATCH_FILE git_path(SEQ_DIR "/patch")
+#define MERGE_MSG git_path("MERGE_MSG")
+#define SQUASH_MSG git_path("SQUASH_MSG")
+
+/**********************************************************************
+ * Data structures
+ */
+
+struct user_info {
+ const char *name;
+ const char *mail;
+ const char *time; /* "<timestamp> <timezone>" */
+};
+
+struct commit_info {
+ struct user_info author; /* author info */
+ struct user_info committer; /* not used, but for easy extendability */
+ const char *encoding; /* encoding */
+ char *subject; /* basically the first line of the summary */
+ struct strbuf summary; /* the commit message */
+ char *source; /* source of the commit message, either
+ * "message", "merge", "squash" or a commit SHA1 */
+ char *patch; /* a patch */
+ struct string_list parents; /* list of parents' hex'ed sha1 ids */
+};
+
+/**********************************************************************
+ * Global variables
+ */
static char *reflog;
+static int squash_count = 0;
+
static int allow_dirty = 0, verbosity = 1, advice = 1;
static unsigned char head_sha1[20];
+static struct commit_info next_commit;
+
static const char * const git_sequencer_helper_usage[] = {
"git sequencer--helper --make-patch <commit>",
"git sequencer--helper --reset-hard <commit> <reflog-msg> "
"<verbosity> [<allow-dirty>]",
"git sequencer--helper --fast-forward <commit> <reflog-msg> "
"<verbosity> [<allow-dirty>]",
+ "git sequencer--helper --cherry-pick <commit> [<do-not-commit>]",
NULL
};
+/**********************************************************************
+ * Sequencer functions
+ */
+
static int parse_and_init_tree_desc(const unsigned char *sha1,
struct tree_desc *desc)
{
@@ -162,6 +205,157 @@ static void make_patch(struct commit *commit)
free(args);
}
+/* Commit current index with information next_commit onto parent_sha1. */
+static int do_commit(unsigned char *parent_sha1)
+{
+ int failed;
+ unsigned char tree_sha1[20];
+ unsigned char commit_sha1[20];
+ struct strbuf sbuf;
+ const char *reencoded = NULL;
+
+ if (squash_count) {
+ squash_count = 0;
+ if (file_exists(SQUASH_MSG))
+ unlink(SQUASH_MSG);
+ }
+
+ if (!index_differs_from("HEAD", 0) &&
+ !next_commit.parents.nr)
+ return error("No changes! Do you really want an empty commit?");
+
+ if (!next_commit.author.name || !next_commit.author.mail)
+ return error("Internal error: Author information not set properly.");
+
+ if (write_cache_as_tree(tree_sha1, 0, NULL))
+ return 1;
+
+ if (!next_commit.encoding)
+ next_commit.encoding = xstrdup("utf-8");
+ if (!git_commit_encoding)
+ git_commit_encoding = "utf-8";
+
+ strbuf_init(&sbuf, 8192); /* should avoid reallocs for the headers */
+ strbuf_addf(&sbuf, "tree %s\n", sha1_to_hex(tree_sha1));
+ if (parent_sha1)
+ strbuf_addf(&sbuf, "parent %s\n", sha1_to_hex(parent_sha1));
+ if (next_commit.parents.nr) {
+ int i;
+ for (i = 0; i < next_commit.parents.nr; ++i)
+ strbuf_addf(&sbuf, "parent %s\n",
+ next_commit.parents.items[i].string);
+ }
+ if (!next_commit.author.time) {
+ char time[50];
+ datestamp(time, sizeof(time));
+ next_commit.author.time = xstrdup(time);
+ }
+
+ stripspace(&next_commit.summary, 1);
+
+ /* if encodings differ, reencode whole buffer */
+ if (strcasecmp(git_commit_encoding, next_commit.encoding)) {
+ if ((reencoded = reencode_string(next_commit.author.name,
+ git_commit_encoding, next_commit.encoding))) {
+ free((void *)next_commit.author.name);
+ next_commit.author.name = reencoded;
+ }
+ if ((reencoded = reencode_string(next_commit.summary.buf,
+ git_commit_encoding, next_commit.encoding))) {
+ strbuf_reset(&next_commit.summary);
+ strbuf_addstr(&next_commit.summary, reencoded);
+ }
+ }
+ strbuf_addf(&sbuf, "author %s <%s> %s\n", next_commit.author.name,
+ next_commit.author.mail, next_commit.author.time);
+ strbuf_addf(&sbuf, "committer %s\n", git_committer_info(0));
+ if (!is_encoding_utf8(git_commit_encoding))
+ strbuf_addf(&sbuf, "encoding %s\n", git_commit_encoding);
+ strbuf_addch(&sbuf, '\n');
+ strbuf_addbuf(&sbuf, &next_commit.summary);
+ if (sbuf.buf[sbuf.len-1] != '\n')
+ strbuf_addch(&sbuf, '\n');
+
+ failed = write_sha1_file(sbuf.buf, sbuf.len, commit_type, commit_sha1);
+ strbuf_release(&sbuf);
+ if (failed)
+ return 1;
+
+ if (verbosity > 1)
+ printf("Created %scommit %s\n",
+ parent_sha1 || next_commit.parents.nr ? "" : "initial ",
+ sha1_to_hex(commit_sha1));
+
+ if (update_ref(reflog, "HEAD", commit_sha1, NULL, 0, 0))
+ return error("Could not update HEAD to %s.",
+ sha1_to_hex(commit_sha1));
+
+ return 0;
+}
+
+/*
+ * Fill next_commit.author according to ident.
+ * Ident may have one of the following forms:
+ * "name <e-mail> timestamp timezone\n..."
+ * "name <e-mail> timestamp timezone"
+ * "name <e-mail>"
+ */
+static void set_author_info(const char *ident)
+{
+ const char *tmp1 = strstr(ident, " <");
+ const char *tmp2;
+ char *data;
+ if (!tmp1)
+ return;
+ tmp2 = strstr(tmp1+2, ">");
+ if (!tmp2)
+ return;
+ if (tmp2[1] != 0 && tmp2[1] != ' ')
+ return;
+
+ data = xmalloc(strlen(ident)); /* a trivial upper bound */
+
+ snprintf(data, tmp1-ident+1, "%s", ident);
+ next_commit.author.name = xstrdup(data);
+ snprintf(data, tmp2-tmp1-1, "%s", tmp1+2);
+ next_commit.author.mail = xstrdup(data);
+
+ if (tmp2[1] == 0) {
+ free(data);
+ return;
+ }
+
+ tmp1 = strpbrk(tmp2+2, "\r\n");
+ if (!tmp1)
+ tmp1 = tmp2 + strlen(tmp2);
+
+ snprintf(data, tmp1-tmp2-1, "%s", tmp2+2);
+ next_commit.author.time = xstrdup(data);
+ free(data);
+}
+
+static void set_message_source(const char *source)
+{
+ if (next_commit.source)
+ free(next_commit.source);
+ next_commit.source = xstrdup(source);
+}
+
+/* Set subject, an information for the case of conflict */
+static void set_pick_subject(const char *hex, struct commit *commit)
+{
+ const char *tmp = strstr(commit->buffer, "\n\n");
+ if (tmp) {
+ const char *eol;
+ int len = strlen(hex);
+ tmp += 2;
+ eol = strchrnul(tmp, '\n');
+ next_commit.subject = xmalloc(eol - tmp + len + 5);
+ snprintf(next_commit.subject, eol - tmp + len + 5, "%s... %s",
+ hex, tmp);
+ }
+}
+
/* Return a commit object of "arg" */
static struct commit *get_commit(const char *arg)
{
@@ -198,6 +392,26 @@ static int set_verbosity(int verbose)
return 0;
}
+static int write_commit_summary_into(const char *filename)
+{
+ struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
+ int fd = hold_lock_file_for_update(lock, filename, 0);
+ if (fd < 0)
+ return error("Unable to create '%s.lock': %s", filename,
+ strerror(errno));
+ if (write_in_full(fd, next_commit.summary.buf,
+ next_commit.summary.len) < 0)
+ return error("Could not write to %s: %s",
+ filename, strerror(errno));
+ if (commit_lock_file(lock) < 0)
+ return error("Error wrapping up %s", filename);
+ return 0;
+}
+
+/**********************************************************************
+ * Builtin sequencer helper functions
+ */
+
/* v should be "" or "t" or "\d" */
static int parse_verbosity(const char *v)
{
--
1.6.4.271.ge010d
^ permalink raw reply related
* Re: unpack a single object
From: tarmigan @ 2009-08-12 5:34 UTC (permalink / raw)
To: Bryan Donlan; +Cc: Git Mailing List, Junio C Hamano
In-Reply-To: <3e8340490908111349j323812dbmf2211e4cf454b8f1@mail.gmail.com>
On Tue, Aug 11, 2009 at 1:49 PM, Bryan Donlan<bdonlan@gmail.com> wrote:
> On Tue, Aug 11, 2009 at 4:48 PM, Bryan Donlan<bdonlan@gmail.com> wrote:
>> On Tue, Aug 11, 2009 at 4:15 PM, tarmigan<tarmigan+lists@gmail.com> wrote:
>>> I would rather not copy the whole good repo back to the one that ran
>>> out of space because it's multiple gigs. My plan is to just explode
>>> the bad pack on of the corrupted repo, explode good pack and then,
>>> copy the corrupted object back. So my question is how do I tell which
>>> pack contains that object? (I would rather not explode all the packs
>>> because of the repo size.) Is there a way to extract a single object
>>> from a pack without exploding the whole pack?
>>
>> You should be able to just extract the single object in question:
>>
>> goodrepo$ git cat-file commit 3d4c2b0225e7605a7e2a38ffc44dcb888589f4ce
>> > ~/commit.dat
>> goodrepo$ cd ~/badrepo
>> badrepo$ git read-file -t commit ~/commit.dat
>> (should output 3d4c2b0225e7605a7e2a38ffc44dcb888589f4ce)
>>
>> At this point your repo should be repaired.
>>
>
> Err, that should read git hash-object, not git read-file.
>
Thanks, and thanks to Junio who also responded with something similar
off-list. I was vaguely familiar with cat-file and hash-object before
but didn't realize how they could be used to do what I wanted, so
thanks for the lesson.
As Junio suspected, I after the next fsck, I also had problems with
the tree associated with that commit and also the commits behind that
one. Each fsck takes around 12 minutes, so replacing one commit at a
time seemed not very productive. So now I am doing another svn clone
from scratch and letting it run for a few hours (it was a straight
mirror, so nothing is lost). It seems somewhat wasteful, but I guess
better a few hours of cpu time than a few hours of my time.
Thanks,
Tarmigan
^ permalink raw reply
* Re: [RFC PATCH v3 8/8] --sparse for porcelains
From: Junio C Hamano @ 2009-08-12 6:33 UTC (permalink / raw)
To: Nguyễn Thái Ngọc Duy; +Cc: git, Johannes Schindelin
In-Reply-To: <1250005446-12047-9-git-send-email-pclouds@gmail.com>
Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
> @@ -594,6 +596,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
> OPT_BOOLEAN('m', "merge", &opts.merge, "merge"),
> OPT_STRING(0, "conflict", &conflict_style, "style",
> "conflict style (merge or diff3)"),
> + OPT_SET_INT(0, "sparse", &opts.apply_sparse,
> + "apply sparse checkout filter", 1),
Shouldn't this be BOOLEAN not INT, i.e. "--[no-]sparse"? That way, you
could enable it by simply the presense of $GIT_DIR/info/sparse.
It could also require core.sparseworktree configuration set to true if we
are really paranoid, but without the actual sparse specification file
flipping that configuration to true would not be useful anyway, so in
practice, giving --sparse-work-tree option to these Porcelain commands
would be no-op, but --no-sparse-work-tree option would be useful to
ignore $GIT_DIR/info/sparse and populate the work tree fully.
Or am I missing something?
^ permalink raw reply
* Re: Implementing $Date$ substitution - problem with git status
From: Peter Krefting @ 2009-08-12 6:54 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Git List
In-Reply-To: <200908092252.58363.j6t@kdbg.org>
Johannes Sixt:
>> Doing "git reset --hard" or "git checkout master filename" does not
>> help, the file is still believed to be modified by git.
> Now, that's an entirely different problem, and I think that there is a
> bug. I have observed this as well with my own clean filter sometimes, but
> not always. I haven't found a recipe that reliably exhibits the problem.
After som examination, it seems to be caused by the way I imported the CVS
history: I kept all the $ keywords expanded in history (so that if I check
out an old version from Git, it looks like it did in CVS). This means that
still in the latest revision of several files, I have "$Id$" lines checked
in in CVS format.
However, as I have set the "ident" attribute, Git wants to expand it itself
and check in files with "$Id$". When I do a reset, it seems it records the
entry as clean against a version stored with just "$Id$", but the record in
history has an expanded "$Id$", and the entry is thus never deemed clean.
I can probably work around this by removing the "$Id$" attributes, or by
removing the "ident" rule.
--
\\// Peter - http://www.softwolves.pp.se/
^ permalink raw reply
* Meta data available to filters?
From: Peter Krefting @ 2009-08-12 6:59 UTC (permalink / raw)
To: Git List
Hi!
If I set up a filter, is there a way from my filter script to know the name
or identity of the file that I am processing?
I get the data on standard in and output the changed data on standard out,
but is there any way to get access to meta data?
I find the documentation on filters a bit terse. Once I figure out how they
actually work, I may be inclined to send a documentation patch. A minimum
would be to document their existence on the git-config manual page (with
reference to gitattributes), it took me some time to find it :-)
--
\\// Peter - http://www.softwolves.pp.se/
^ permalink raw reply
* Re: [msysGit] Re: Using VC build git
From: Marius Storm-Olsen @ 2009-08-12 7:13 UTC (permalink / raw)
To: Frank Li; +Cc: Johannes Schindelin, git, msysGit
In-Reply-To: <1976ea660908101826q26faa37ao7920d5cf9d4f53fd@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2288 bytes --]
[Please do *not* do top-posting! Both git and msysgit mailing lists
use bottom-posting]
Frank Li said the following on 11.08.2009 03:26:
> Thank you take care my patch.
> I can fix all problems.
Good! Many people want to see git build with MSVC, if only to use a
compiler better at optimizing code on Windows. (And the debugger, of
course)
> This patch is base on v1.6.4 release. My working branch is vc_build
> at git://repo.or.cz/tgit.git.
Ok. Dscho wondered why it wasn't a proper fork of the main git.git
repo, so it *should* really have been
git://repo.or.cz/git/tgit.git
^^^^ <-- Notice the fork relationship?
It would save some valuable space on the server, show relations, make
it easier to find, etc.
> That is actually prototype to approve VC can build git.
> The code style is not big problem. I will fix it.
You will experience that for the git community coding style is very
important (for good reason), so expect many rounds of rewriting your
patches, until they all shine like diamonds.
> VC build will reuse many msysgit works because msysgit really do many
> work at windows porting.
Sure, but I think it rarely will involve your patches changing the
code in MinGW at all. Try your outmost to keep your patches separated
from anything else. If in doubt, please ask us on the msysgit mailing
list, and we will guide you.
> I think the below is most important problem.
>
> 1. Where are vcbuild directory put, is it okay under contrib ?
> 2. How to handle external library, such as zlib? Can use submodule?
For point 2: If we cannot compile we don't accept it, is the basic
rule. This means that if you think the people building git with MSVC
cannot install some dependencies themselves, you need to provide the
full sources yourself, and make sure that the code compiles without
changes. So, in this case if would mean to include the sources for
zlib, and setup the vcproj to compile this code into the executable,
instead of linking with a precompiled lib.
In this case, however, I think you should rely on the developer
providing this library themselves, and not add it to the git project.
The zlib project is ~750KB of code itself..
--
.marius
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 187 bytes --]
^ permalink raw reply
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