* Re: obnoxious CLI complaints
From: René Scharfe @ 2009-09-10 22:19 UTC (permalink / raw)
To: Jakub Narebski; +Cc: Brendan Miller, git
In-Reply-To: <200909101116.55098.jnareb@gmail.com>
Jakub Narebski schrieb:
> [...] Second, compression is better left to separate program, but
> I guess we can follow GNU tar example and add equivalents of -Z/-z/-j
> and --use-compress-program options when using --output=<file>. [...]
Compression only makes sense for the tar format, so I think it's better
exposed by new formats and not by generic options.
For compress and bzip2 we'd need to call the external archiver, similar
to a pager. Interesting idea.
For gzip, we can use the zlib helper functions, since we're linking
against it anyway. I mention this because the following patch has been
laying around here for a while, collecting dust because it was a feature
waiting for a requester.
Using zlib directly avoids the overhead of a pipe and of buffering the
output for blocked writes; surprisingly (to me), it isn't any faster.
I didn't make any tuning efforts, yet, though. Anyway, here it is:
---
Documentation/git-archive.txt | 2 +-
archive-tar.c | 76 ++++++++++++++++++++++++++++++++++++----
archive.c | 43 ++++++++++++++++++++++-
archive.h | 1 +
t/t5000-tar-tree.sh | 30 ++++++++++++++++
5 files changed, 141 insertions(+), 11 deletions(-)
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index 92444dd..2935246 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -34,7 +34,7 @@ OPTIONS
-------
--format=<fmt>::
- Format of the resulting archive: 'tar' or 'zip'. The default
+ Format of the resulting archive: 'tar', 'tar.gz' or 'zip'. The default
is 'tar'.
-l::
diff --git a/archive-tar.c b/archive-tar.c
index cee06ce..f22304d 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -58,18 +58,78 @@ static void write_blocked(const void *data, unsigned long size)
write_if_needed();
}
+static void gzwrite_or_die(gzFile *gzfile, const void *buf, size_t count)
+{
+ const int chunk = 1 << 30; /* Big arbitrary value that fits into int. */
+ const char *p = buf;
+
+ while (count > 0) {
+ unsigned int to_write = (count < chunk) ? count : chunk;
+ int written = gzwrite(gzfile, p, to_write);
+ if (written <= 0) {
+ int err;
+ const char *msg = gzerror(gzfile, &err);
+ if (err != Z_ERRNO)
+ die("zlib error: %s", msg);
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ if (errno == EPIPE)
+ exit(0);
+ die_errno("write error");
+ }
+ count -= written;
+ p += written;
+ }
+}
+
+/*
+ * Writes directly through zlib and pads with NUL bytes to multiples of
+ * RECORDSIZE. Updates offset because the length of the trailer depends
+ * on it.
+ */
+static void write_to_tgz(struct archiver_args *args, const void *data,
+ unsigned long size)
+{
+ unsigned long tail = size % RECORDSIZE;
+ gzwrite_or_die(args->gzfile, data, size);
+ if (tail) {
+ tail = RECORDSIZE - tail;
+ if (gzseek(args->gzfile, tail, SEEK_CUR) == -1)
+ die("zlib error while seeking.");
+ }
+ offset = (offset + size + tail) % BLOCKSIZE;
+}
+
+static void write_to_archive(struct archiver_args *args, const void *data,
+ unsigned long size)
+{
+ if (args->gzfile)
+ write_to_tgz(args, data, size);
+ else
+ write_blocked(data, size);
+}
+
/*
* The end of tar archives is marked by 2*512 nul bytes and after that
* follows the rest of the block (if any).
*/
-static void write_trailer(void)
+static void write_trailer(struct archiver_args *args)
{
int tail = BLOCKSIZE - offset;
- memset(block + offset, 0, tail);
- write_or_die(1, block, BLOCKSIZE);
- if (tail < 2 * RECORDSIZE) {
- memset(block, 0, offset);
+ if (args->gzfile) {
+ if (tail < 2 * RECORDSIZE)
+ tail += BLOCKSIZE;
+ if (gzseek(args->gzfile, tail - 1, SEEK_CUR) == -1)
+ die("zlib error while seeking.");
+ if (gzputc(args->gzfile, '\0') == -1)
+ die("zlib error while writing a NUL byte.");
+ } else {
+ memset(block + offset, 0, tail);
write_or_die(1, block, BLOCKSIZE);
+ if (tail < 2 * RECORDSIZE) {
+ memset(block, 0, offset);
+ write_or_die(1, block, BLOCKSIZE);
+ }
}
}
@@ -201,9 +261,9 @@ static int write_tar_entry(struct archiver_args *args,
return err;
}
strbuf_release(&ext_header);
- write_blocked(&header, sizeof(header));
+ write_to_archive(args, &header, sizeof(header));
if (S_ISREG(mode) && buffer && size > 0)
- write_blocked(buffer, size);
+ write_to_archive(args, buffer, size);
return err;
}
@@ -245,6 +305,6 @@ int write_tar_archive(struct archiver_args *args)
if (!err)
err = write_archive_entries(args, write_tar_entry);
if (!err)
- write_trailer();
+ write_trailer(args);
return err;
}
diff --git a/archive.c b/archive.c
index 0bca9ca..8809f51 100644
--- a/archive.c
+++ b/archive.c
@@ -15,6 +15,8 @@ static char const * const archive_usage[] = {
};
#define USES_ZLIB_COMPRESSION 1
+#define USES_GZIP_COMPRESSION 2
+#define USES_COMPRESSION (USES_ZLIB_COMPRESSION | USES_GZIP_COMPRESSION)
static const struct archiver {
const char *name;
@@ -22,6 +24,7 @@ static const struct archiver {
unsigned int flags;
} archivers[] = {
{ "tar", write_tar_archive },
+ { "tar.gz", write_tar_archive, USES_GZIP_COMPRESSION },
{ "zip", write_zip_archive, USES_ZLIB_COMPRESSION },
};
@@ -336,7 +339,7 @@ static int parse_archive_args(int argc, const char **argv,
args->compression_level = Z_DEFAULT_COMPRESSION;
if (compression_level != -1) {
- if ((*ar)->flags & USES_ZLIB_COMPRESSION)
+ if ((*ar)->flags & USES_COMPRESSION)
args->compression_level = compression_level;
else {
die("Argument not supported for format '%s': -%d",
@@ -351,11 +354,38 @@ static int parse_archive_args(int argc, const char **argv,
return argc;
}
+static void archive_gzfile_open(struct archiver_args *args)
+{
+ char mode[] = "wbX";
+ if (args->compression_level == Z_DEFAULT_COMPRESSION)
+ mode[2] = '\0';
+ else
+ mode[2] = '0' + args->compression_level;
+ args->gzfile = gzdopen(xdup(1), mode);
+ if (!args->gzfile)
+ die("zlib error: out of memory.");
+}
+
+static void archive_gzfile_close(struct archiver_args *args)
+{
+ int err = gzclose(args->gzfile);
+ switch (err) {
+ case Z_OK:
+ break;
+ case Z_ERRNO:
+ die_errno("zlib error");
+ default:
+ die("zlib error %d while closing.", err);
+ }
+ args->gzfile = NULL;
+}
+
int write_archive(int argc, const char **argv, const char *prefix,
int setup_prefix)
{
const struct archiver *ar = NULL;
struct archiver_args args;
+ int err;
argc = parse_archive_args(argc, argv, &ar, &args);
if (setup_prefix && prefix == NULL)
@@ -366,5 +396,14 @@ int write_archive(int argc, const char **argv, const char *prefix,
git_config(git_default_config, NULL);
- return ar->write_archive(&args);
+ args.gzfile = NULL;
+ if (ar->flags & USES_GZIP_COMPRESSION)
+ archive_gzfile_open(&args);
+
+ err = ar->write_archive(&args);
+
+ if (!err && (ar->flags & USES_GZIP_COMPRESSION))
+ archive_gzfile_close(&args);
+
+ return err;
}
diff --git a/archive.h b/archive.h
index 038ac35..638a7ba 100644
--- a/archive.h
+++ b/archive.h
@@ -12,6 +12,7 @@ struct archiver_args {
unsigned int verbose : 1;
unsigned int worktree_attributes : 1;
int compression_level;
+ gzFile gzfile;
};
typedef int (*write_archive_fn_t)(struct archiver_args *);
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 5f84b18..4094c18 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -26,6 +26,8 @@ commit id embedding:
. ./test-lib.sh
UNZIP=${UNZIP:-unzip}
+GZIP=${GZIP:-gzip}
+GUNZIP=${GUNZIP:-$GZIP -d}
SUBSTFORMAT=%H%n
@@ -79,6 +81,15 @@ test_expect_success \
'git tar-tree HEAD >b2.tar'
test_expect_success \
+ 'git archive --format=tar.gz' \
+ 'git archive --format=tar.gz HEAD >bz.tar.gz'
+
+test_expect_success \
+ 'git archive --format=tar.gz with --output' \
+ 'git archive --format=tar.gz --output=bz1.tar.gz HEAD &&
+ test_cmp bz.tar.gz bz1.tar.gz'
+
+test_expect_success \
'git archive vs. git tar-tree' \
'test_cmp b.tar b2.tar'
@@ -146,7 +157,9 @@ test_expect_success \
'cp .git/info/attributes .git/info/attributes.before &&
echo "substfile?" export-subst >>.git/info/attributes &&
git archive HEAD >f.tar &&
+ git archive --format=tar.gz HEAD >fz.tar.gz &&
git archive --prefix=prefix/ HEAD >g.tar &&
+ git archive --format=tar.gz --prefix=prefix/ HEAD >gz.tar.gz &&
mv .git/info/attributes.before .git/info/attributes'
test_expect_success \
@@ -173,6 +186,23 @@ test_expect_success \
test_cmp a/substfile2 g/prefix/a/substfile2
'
+$GUNZIP -h >/dev/null 2>&1
+if [ $? -eq 127 ]; then
+ echo "Skipping tar.gz expansion tests, because gunzip was not found"
+else
+ test_expect_success \
+ 'expand *.tar.gz' \
+ '$GUNZIP bz.tar.gz &&
+ $GUNZIP fz.tar.gz &&
+ $GUNZIP gz.tar.gz'
+
+ test_expect_success \
+ 'compare files created by formats tar and tar.gz' \
+ 'test_cmp b.tar bz.tar &&
+ test_cmp f.tar fz.tar &&
+ test_cmp g.tar gz.tar'
+fi
+
test_expect_success \
'git archive --format=zip' \
'git archive --format=zip HEAD >d.zip'
--
1.6.5.rc0
^ permalink raw reply related
* Re: obnoxious CLI complaints
From: René Scharfe @ 2009-09-10 22:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jakub Narebski, Wincent Colaiuta, Brendan Miller, git
In-Reply-To: <7vbpliaaxo.fsf@alter.siamese.dyndns.org>
Junio C Hamano schrieb:
> Jakub Narebski <jnareb@gmail.com> writes:
>
>> First, it would be consistent with how ordinary archivers such as tar
>> or zip are used, where you have to specify list of files to archive
>> (in our case this list is HEAD). Second, I'd rather not accidentally
>> dump binary to terminal: "git archive [HEAD]" dumps archive to standard
>> output.
>
> So does "cat". I do not agree with your second point.
>
> While I somewhat see the similarity argument, your first point, I am not
> sure if it is relevant. It is not like "tar or zip allows us to say what
> files to archive, but git-archive doesn't and it always archives HEAD";
> you are saying "they require us to specify, so should we".
>
> But I do not see a strong reason not to default to HEAD. The case that
> would make difference would be to differentiate among
>
> $ git archive HEAD TAIL
> $ git archive HEAD -- TAIL
> $ git archive -- HEAD TAIL
>
> i.e. what if you happen to have a tracked content called HEAD. I didn't
> check the current command line parser in git-archive understands the "--"
> convention for that, but it is not a rocket science to add it if it
> doesn't.
Currently it doesn't. An attempt to implement it is below (tests and
documentation update missing).
I wonder if we want to make treeless calls to archive the worktree (or the
index) instead of HEAD, similar to git grep, though. Not that I remember
someone requesting such a thing, but I'm already slightly surprised about
archive being used to tar up HEAD in any case -- I imagined it would mostly
be used to make releases of tagged versions.
---
archive.c | 34 ++++++++++++++++++++++++----------
1 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/archive.c b/archive.c
index 0bca9ca..04fa6a5 100644
--- a/archive.c
+++ b/archive.c
@@ -214,18 +214,32 @@ static void parse_pathspec_arg(const char **pathspec,
ar_args->pathspec = get_pathspec(ar_args->base, pathspec);
}
-static void parse_treeish_arg(const char **argv,
- struct archiver_args *ar_args, const char *prefix)
+static int parse_treeish_arg(int argc, const char **argv,
+ struct archiver_args *ar_args, const char *prefix)
{
- const char *name = argv[0];
+ const char *name = "HEAD";
const unsigned char *commit_sha1;
time_t archive_time;
struct tree *tree;
const struct commit *commit;
unsigned char sha1[20];
+ if (argc > 0) {
+ int consume = 1;
+
+ if (strcmp(argv[0], "--")) {
+ name = argv[0];
+ if (argc > 1 && !strcmp(argv[1], "--"))
+ consume++;
+ }
+
+ argc -= consume;
+ memmove(argv, argv + consume, argc * sizeof(*argv));
+ argv[argc] = NULL;
+ }
+
if (get_sha1(name, sha1))
- die("Not a valid object name");
+ die("Not a valid object name: %s", name);
commit = lookup_commit_reference_gently(sha1, 1);
if (commit) {
@@ -256,6 +270,8 @@ static void parse_treeish_arg(const char **argv,
ar_args->commit_sha1 = commit_sha1;
ar_args->commit = commit;
ar_args->time = archive_time;
+
+ return argc;
}
#define OPT__COMPR(s, v, h, p) \
@@ -309,7 +325,8 @@ static int parse_archive_args(int argc, const char **argv,
OPT_END()
};
- argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
+ argc = parse_options(argc, argv, NULL, opts, archive_usage,
+ PARSE_OPT_KEEP_DASHDASH);
if (remote)
die("Unexpected option --remote");
@@ -327,9 +344,6 @@ static int parse_archive_args(int argc, const char **argv,
exit(0);
}
- /* We need at least one parameter -- tree-ish */
- if (argc < 1)
- usage_with_options(archive_usage, opts);
*ar = lookup_archiver(format);
if (!*ar)
die("Unknown archive format '%s'", format);
@@ -361,8 +375,8 @@ int write_archive(int argc, const char **argv, const char *prefix,
if (setup_prefix && prefix == NULL)
prefix = setup_git_directory();
- parse_treeish_arg(argv, &args, prefix);
- parse_pathspec_arg(argv + 1, &args);
+ argc = parse_treeish_arg(argc, argv, &args, prefix);
+ parse_pathspec_arg(argv, &args);
git_config(git_default_config, NULL);
--
1.6.5.rc0
^ permalink raw reply related
* Re: [PATCH 4/4] reset: add test cases for "--merge-dirty" option
From: Daniel Barkalow @ 2009-09-10 22:14 UTC (permalink / raw)
To: Christian Couder
Cc: Junio C Hamano, git, Johannes Schindelin, Stephan Beyer,
Jakub Narebski, Linus Torvalds
In-Reply-To: <20090910202333.3722.13214.chriscool@tuxfamily.org>
On Thu, 10 Sep 2009, Christian Couder wrote:
This shows that with the "--merge-dirty" option,
changes that are both in the work tree and the index are kept
in the work tree after the reset (but discarded in the index). As with
the "--merge" option,
changes that are in both the work tree and the index are discarded
after the reset.
I'm lost here.
If you have:
working index HEAD target
version B B A A
You get:
working index HEAD target
--m-d B A A A
--merge A A A A
?
> ---
> t/t7110-reset-merge.sh | 54 +++++++++++++++++++++++++++++++++++++++++++----
> 1 files changed, 49 insertions(+), 5 deletions(-)
>
> diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh
> index 45714ae..1e6d634 100755
> --- a/t/t7110-reset-merge.sh
> +++ b/t/t7110-reset-merge.sh
> @@ -19,7 +19,7 @@ test_expect_success 'creating initial files' '
> git commit -m "Initial commit"
> '
>
> -test_expect_success 'ok with changes in file not changed by reset' '
> +test_expect_success '--merge: ok if changes in file not touched by reset' '
Should probably have the "--merge: " from the beginning, since you're
adding the test in this series anyway. That would make the diff come out
clearer.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: obnoxious CLI complaints
From: John Tapsell @ 2009-09-10 22:04 UTC (permalink / raw)
To: Jakub Narebski; +Cc: Wincent Colaiuta, Brendan Miller, git
In-Reply-To: <200909102223.31602.jnareb@gmail.com>
2009/9/10 Jakub Narebski <jnareb@gmail.com>:
> Dnia czwartek 10. września 2009 21:46, John Tapsell napisał:
>> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:
>
>> > First, it would be consistent with how ordinary archivers such as tar
>> > or zip are used, where you have to specify list of files to archive
>> > (in our case this list is HEAD). Second, I'd rather not accidentally
>> > dump binary to terminal: "git archive [HEAD]" dumps archive to standard
>> > output.
>>
>> That could be fixed by outputting to a file. git format-patch outputs
>> to a file, so why wouldn't git achieve?
>
> "git format-patch" outputs to files because it generates _multiple_
> files; generating single patch is special case. Also git-format-patch
> can generate file names from patch (commit) subject; it is not the case
> for "git archive" (what name should it use?).
What if it used the current (or topleve) directory name? Wouldn't
that work in most cases? For cases it doesn't work, the user can just
rename or specify the output name, so it would be no worse than the
current case.
John
^ permalink raw reply
* Re: [RFC/PATCH 1/2] gitweb: extend &git_get_head_hash to be &git_get_hash
From: Jakub Narebski @ 2009-09-10 21:49 UTC (permalink / raw)
To: Mark Rada; +Cc: git, Junio C Hamano
In-Reply-To: <4AA96D9B.6090003@mailservices.uwaterloo.ca>
On Thu, 10 Sep 2009, Mark Rada wrote:
> gitweb: extend &git_get_head_hash to be &git_get_hash
Should be "extend git_get_head_hash to be git_get_hash", see below.
>
> This adds an optional second argument to the routine which lets the
> caller specify a treeish that can be translated to a hash id by
> rev-parse.
Minor nit: we use "tree-ish" not "treeish" in documentation.
>
> To maintain some backwards compatability, the second argument is
> optional and it will default to `HEAD' if not specified.
Why 'some'? It does maintain backward compatibility.
Also i am not sure about git_get_hash defaulting to "HEAD". Perhaps
it would be better to keep git_get_head_hash as warpper around
git_get_hash? Or perhaps it would be better to explicitly pass
"HEAD" as second parameter?
>
> Signed-off-by: Mark Rada <marada@uwaterloo.ca>
It looks like a good idea, even if it doesn't make much sense as
a standalone patch.
> ---
> gitweb/gitweb.perl | 31 ++++++++++++++++---------------
> 1 files changed, 16 insertions(+), 15 deletions(-)
>
> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
> index 24b2193..d650188 100755
> --- a/gitweb/gitweb.perl
> +++ b/gitweb/gitweb.perl
> @@ -1981,13 +1981,14 @@ sub quote_command {
> map { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ );
> }
>
> -# get HEAD ref of given project as hash
> -sub git_get_head_hash {
> +# get object id of given project as full hash, defaults to HEAD
> +sub git_get_hash {
I'm not sure about naming (not that git_get_head_hash was best), as
you don't see from git_get_hash subroutine name that the first parameter
is the name of repository (the git_get_head_hash at least hinted, if
very weekly, at it).
> my $project = shift;
> + my $hash = shift || 'HEAD';
> my $o_git_dir = $git_dir;
> my $retval = undef;
> $git_dir = "$projectroot/$project";
> - if (open my $fd, "-|", git_cmd(), "rev-parse", "--verify", "HEAD") {
> + if (open my $fd, '-|', git_cmd(), 'rev-parse', '--verify', "$hash") {
Minor nit: we don't need to quote (stringify) single variable here;
using
..., '--verify', $hash)
would work as well.
> my $head = <$fd>;
> close $fd;
> if (defined $head && $head =~ /^([0-9a-fA-F]{40})$/) {
> @@ -4737,7 +4738,7 @@ sub git_summary {
> }
>
> sub git_tag {
> - my $head = git_get_head_hash($project);
> + my $head = &git_get_hash($project);
One very rarely needs to use explicit "&" subroutine calling syntax;
I think only when you want to circumvent subroutine prototype (which
is different from function/procedure prototypes in other languages).
Current practice is to not use it.
Besides it it not used anywhere else in gitweb (consistency).
> git_header_html();
> git_print_page_nav('','', $head,undef,$head);
> my %tag = parse_tag($hash);
> @@ -4778,7 +4779,7 @@ sub git_blame {
>
> # error checking
> die_error(400, "No file name given") unless $file_name;
> - $hash_base ||= git_get_head_hash($project);
> + $hash_base ||= &git_get_hash($project);
Same as above: use "git_get_hash($project)" or "git_get_hash($project, 'HEAD');"
> die_error(404, "Couldn't find base commit") unless $hash_base;
> my %co = parse_commit($hash_base)
> or die_error(404, "Commit not found");
> @@ -4911,7 +4912,7 @@ HTML
> }
>
> sub git_tags {
> - my $head = git_get_head_hash($project);
> + my $head = &git_get_hash($project);
Same as above: use "git_get_hash($project)"
> git_header_html();
> git_print_page_nav('','', $head,undef,$head);
> git_print_header_div('summary', $project);
> @@ -4924,7 +4925,7 @@ sub git_tags {
> }
>
> sub git_heads {
> - my $head = git_get_head_hash($project);
> + my $head = &git_get_hash($project);
Same as above: use "git_get_hash($project)"
> git_header_html();
> git_print_page_nav('','', $head,undef,$head);
> git_print_header_div('summary', $project);
> @@ -4942,7 +4943,7 @@ sub git_blob_plain {
>
> if (!defined $hash) {
> if (defined $file_name) {
> - my $base = $hash_base || git_get_head_hash($project);
> + my $base = $hash_base || &git_get_hash($project);
Same as above: use "git_get_hash($project)"
[...]
--
Jakub Narebski
Poland
^ permalink raw reply
* [RFC/PATCH 2/2] gitweb: check given hash before trying to create snapshot
From: Mark Rada @ 2009-09-10 21:20 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski, Junio C Hamano
This patch is dual purposed.
First, it makes things nicer in cases when you hand craft the snapshot
URL but make a typo (e.g. netx instead of next); you will now get an
error message instead of a broken tarball.
Second, any given treeish will always be translated to the full length,
unambiguous, hash id; this will be useful for things like creating
unique names for snapshot caches.
This patch includes test for t9501 to demonstrate the changed
functionality.
Signed-off-by: Mark Rada <marada@uwaterloo.ca>
---
gitweb/gitweb.perl | 5 +++--
t/t9501-gitweb-standalone-http-status.sh | 26 ++++++++++++++++++++++++++
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index d650188..4ae960c 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -5197,8 +5197,9 @@ sub git_snapshot {
die_error(403, "Unsupported snapshot format");
}
- if (!defined $hash) {
- $hash = &git_get_hash($project);
+ my $snapshot = &git_get_hash($project, $hash);
+ if (!$snapshot) {
+ die_error(400, "Not a valid hash id: $hash");
}
my $name = $project;
diff --git a/t/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh
index d0ff21d..4f8f147 100644
--- a/t/t9501-gitweb-standalone-http-status.sh
+++ b/t/t9501-gitweb-standalone-http-status.sh
@@ -75,4 +75,30 @@ test_expect_success \
test_debug 'cat gitweb.output'
+test_expect_success \
+ 'snapshots: bad treeish id' \
+ 'gitweb_run "p=.git;a=snapshot;h=frizzumFrazzum;sf=tgz" &&
+ grep "400 - Not a valid hash id:" gitweb.output'
+test_debug 'cat gitweb.output'
+
+test_expect_success \
+ 'snapshots: good treeish id' \
+ 'gitweb_run "p=.git;a=snapshot;h=master;sf=tgz" &&
+ grep "Status: 200 OK" gitweb.output'
+test_debug 'cat gitweb.output'
+
+test_expect_success \
+ 'snapshots: good object id' \
+ 'ID=`git rev-parse --verify HEAD` &&
+ gitweb_run "p=.git;a=snapshot;h=$ID;sf=tgz" &&
+ grep "Status: 200 OK" gitweb.output'
+test_debug 'cat gitweb.output'
+
+test_expect_success \
+ 'snapshots: bad object id' \
+ 'gitweb_run "p=.git;a=snapshot;h=abcdef01234;sf=tgz" &&
+ grep "400 - Not a valid hash id:" gitweb.output'
+test_debug 'cat gitweb.output'
+
+
test_done
--
1.6.4.2
^ permalink raw reply related
* [RFC/PATCH 1/2] gitweb: extend &git_get_head_hash to be &git_get_hash
From: Mark Rada @ 2009-09-10 21:20 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski, Junio C Hamano
This adds an optional second argument to the routine which lets the
caller specify a treeish that can be translated to a hash id by
rev-parse.
To maintain some backwards compatability, the second argument is
optional and it will default to `HEAD' if not specified.
Signed-off-by: Mark Rada <marada@uwaterloo.ca>
---
gitweb/gitweb.perl | 31 ++++++++++++++++---------------
1 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 24b2193..d650188 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1981,13 +1981,14 @@ sub quote_command {
map { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ );
}
-# get HEAD ref of given project as hash
-sub git_get_head_hash {
+# get object id of given project as full hash, defaults to HEAD
+sub git_get_hash {
my $project = shift;
+ my $hash = shift || 'HEAD';
my $o_git_dir = $git_dir;
my $retval = undef;
$git_dir = "$projectroot/$project";
- if (open my $fd, "-|", git_cmd(), "rev-parse", "--verify", "HEAD") {
+ if (open my $fd, '-|', git_cmd(), 'rev-parse', '--verify', "$hash") {
my $head = <$fd>;
close $fd;
if (defined $head && $head =~ /^([0-9a-fA-F]{40})$/) {
@@ -4737,7 +4738,7 @@ sub git_summary {
}
sub git_tag {
- my $head = git_get_head_hash($project);
+ my $head = &git_get_hash($project);
git_header_html();
git_print_page_nav('','', $head,undef,$head);
my %tag = parse_tag($hash);
@@ -4778,7 +4779,7 @@ sub git_blame {
# error checking
die_error(400, "No file name given") unless $file_name;
- $hash_base ||= git_get_head_hash($project);
+ $hash_base ||= &git_get_hash($project);
die_error(404, "Couldn't find base commit") unless $hash_base;
my %co = parse_commit($hash_base)
or die_error(404, "Commit not found");
@@ -4911,7 +4912,7 @@ HTML
}
sub git_tags {
- my $head = git_get_head_hash($project);
+ my $head = &git_get_hash($project);
git_header_html();
git_print_page_nav('','', $head,undef,$head);
git_print_header_div('summary', $project);
@@ -4924,7 +4925,7 @@ sub git_tags {
}
sub git_heads {
- my $head = git_get_head_hash($project);
+ my $head = &git_get_hash($project);
git_header_html();
git_print_page_nav('','', $head,undef,$head);
git_print_header_div('summary', $project);
@@ -4942,7 +4943,7 @@ sub git_blob_plain {
if (!defined $hash) {
if (defined $file_name) {
- my $base = $hash_base || git_get_head_hash($project);
+ my $base = $hash_base || &git_get_hash($project);
$hash = git_get_hash_by_path($base, $file_name, "blob")
or die_error(404, "Cannot find file");
} else {
@@ -4994,7 +4995,7 @@ sub git_blob {
if (!defined $hash) {
if (defined $file_name) {
- my $base = $hash_base || git_get_head_hash($project);
+ my $base = $hash_base || &git_get_hash($project);
$hash = git_get_hash_by_path($base, $file_name, "blob")
or die_error(404, "Cannot find file");
} else {
@@ -5197,7 +5198,7 @@ sub git_snapshot {
}
if (!defined $hash) {
- $hash = git_get_head_hash($project);
+ $hash = &git_get_hash($project);
}
my $name = $project;
@@ -5229,7 +5230,7 @@ sub git_snapshot {
}
sub git_log {
- my $head = git_get_head_hash($project);
+ my $head = &git_get_hash($project);
if (!defined $hash) {
$hash = $head;
}
@@ -5833,7 +5834,7 @@ sub git_patches {
sub git_history {
if (!defined $hash_base) {
- $hash_base = git_get_head_hash($project);
+ $hash_base = &git_get_hash($project);
}
if (!defined $page) {
$page = 0;
@@ -5904,7 +5905,7 @@ sub git_search {
die_error(400, "Text field is empty");
}
if (!defined $hash) {
- $hash = git_get_head_hash($project);
+ $hash = &git_get_hash($project);
}
my %co = parse_commit($hash);
if (!%co) {
@@ -6159,7 +6160,7 @@ EOT
}
sub git_shortlog {
- my $head = git_get_head_hash($project);
+ my $head = &git_get_hash($project);
if (!defined $hash) {
$hash = $head;
}
@@ -6486,7 +6487,7 @@ XML
foreach my $pr (@list) {
my %proj = %$pr;
- my $head = git_get_head_hash($proj{'path'});
+ my $head = &git_get_hash($proj{'path'});
if (!defined $head) {
next;
}
--
1.6.4.2
^ permalink raw reply related
* Re: [PATCH 1/4] reset: add a few tests for "git reset --merge"
From: Jakub Narebski @ 2009-09-10 20:59 UTC (permalink / raw)
To: Christian Couder; +Cc: git, Stephan Beyer, Daniel Barkalow
In-Reply-To: <20090910202333.3722.45063.chriscool@tuxfamily.org>
Christian Couder wrote:
> diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh
> new file mode 100755
> index 0000000..45714ae
> --- /dev/null
> +++ b/t/t7110-reset-merge.sh
> @@ -0,0 +1,70 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2009 Christian Couder
> +#
> +
> +test_description='Tests for "git reset --merge"'
> +
> +exec </dev/null
What does this do?
--
Jakub Narebski
Poland
^ permalink raw reply
* Re: [BUG] 'add -u' doesn't work from untracked subdir
From: Clemens Buchacher @ 2009-09-10 20:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nanako Shiraishi, Jeff King, SZEDER Gbor, git
In-Reply-To: <7vmy527f0b.fsf@alter.siamese.dyndns.org>
On Thu, Sep 10, 2009 at 12:53:40PM -0700, Junio C Hamano wrote:
> If this were going to happen as a list concensus, I am very tempted to
> suggest that we at least _consider_ applying the same rule even to
> ls-files and ls-tree. That would impact scripts, so we need to be extra
> careful, though.
I originally thought those commands should be consistent with plain "ls",
simply because of their name. However, ls-files is already inconsistent
because "ls-files <subdir>" lists files relative to the current directory,
as opposed to "ls <subdir>", which does so relative to <subdir>. And ls-tree
is even more different from "ls".
So I don't think users are tempted to associate those commands with the
behavior they are used from "ls". From that perspective it would therefore
be ok to traverse the entire tree by default. To me that seems perfectly
natural, especially for ls-tree.
In case of ls-files, I don't know. Its current behavior certainly did not
bother me so far. But the same arguments as for "add -u" apply if you think
of doing something like "git ls-files -u | cut -f2 | xargs git add", for
example.
I can't really speak for the impact on scripts. But that is certainly an
issue, more so than with "add -u" or "grep", which are more typically used
interactively.
> If we try to give a sensible default to make it easier for the user,
> perhaps we should also default to HEAD when the user did not specify which
> tree-ish to archive from. This is a topic in a separate thread.
I don't see why not.
> *3* Command line pathspec of course should honor cwd as before.
No argument there.
Clemens
^ permalink raw reply
* [PATCH v3 3/3] INSTALL: Describe dependency knobs from Makefile
From: Brian Gernhardt @ 2009-09-10 20:28 UTC (permalink / raw)
To: Git List; +Cc: Junio C Hamano
In-Reply-To: <7v7hw6aas8.fsf@alter.siamese.dyndns.org>
We said that some of our dependencies were optional, but didn't say
how to turn them off. Add information for that and mention where to
save the options close to the top of the file.
Also, standardize on both using quotes for the names of the dependencies
and tabs for indentation of the list.
Signed-off-by: Brian Gernhardt <brian@gernhardtsoftware.com>
---
INSTALL | 38 ++++++++++++++++++++++++--------------
1 files changed, 24 insertions(+), 14 deletions(-)
Junio C Hamano <gitster@pobox.com> wrote:
> Sorry, but the description still speaks of options and does not say what
> good they are. Sent a wrong patch?
Wrong patch? Never. A good git developer always makes sure he re-generated
patch files before making a fool of himself on a public list.
Ahem.
diff --git a/INSTALL b/INSTALL
index 7ab2580..be504c9 100644
--- a/INSTALL
+++ b/INSTALL
@@ -13,6 +13,10 @@ that uses $prefix, the built results have some paths encoded,
which are derived from $prefix, so "make all; make prefix=/usr
install" would not work.
+The beginning of the Makefile documents many variables that affect the way
+git is built. You can override them either from the command line, or in a
+config.mak file.
+
Alternatively you can use autoconf generated ./configure script to
set up install paths (via config.mak.autogen), so you can write instead
@@ -48,7 +52,9 @@ Issues of note:
export GIT_EXEC_PATH PATH GITPERLLIB
- Git is reasonably self-sufficient, but does depend on a few external
- programs and libraries:
+ programs and libraries. Git can be used without most of them by adding
+ the approriate "NO_<LIBRARY>=YesPlease" to the make command line or
+ config.mak file.
- "zlib", the compression library. Git won't build without it.
@@ -59,25 +65,29 @@ Issues of note:
- "Perl" is needed to use some of the features (e.g. preparing a
partial commit using "git add -i/-p", interacting with svn
- repositories with "git svn").
+ repositories with "git svn"). If you can live without these, use
+ NO_PERL.
- - "openssl". Unless you specify otherwise, you'll get the SHA1
- library from here.
+ - "openssl" library is used by git-imap-send to use IMAP over SSL.
+ If you don't need it, use NO_OPENSSL.
- If you don't have openssl, you can use one of the SHA1 libraries
- that come with git (git includes one inspired by Mozilla's and a
- PowerPC optimized one too - see the Makefile).
+ By default, git uses OpenSSL for SHA1 but it will use it's own
+ library (inspired by Mozilla's) with either NO_OPENSSL or
+ BLK_SHA1. Also included is a version optimized for PowerPC
+ (PPC_SHA1).
- - libcurl library; git-http-fetch and git-fetch use them. You
+ - "libcurl" library is used by git-http-fetch and git-fetch. You
might also want the "curl" executable for debugging purposes.
- If you do not use http transfer, you are probably OK if you
- do not have them.
+ If you do not use http:// or https:// repositories, you do not
+ have to have them (use NO_CURL).
- - expat library; git-http-push uses it for remote lock
- management over DAV. Similar to "curl" above, this is optional.
+ - "expat" library; git-http-push uses it for remote lock
+ management over DAV. Similar to "curl" above, this is optional
+ (with NO_EXPAT).
- - "wish", the Tcl/Tk windowing shell is used in gitk to show the
- history graphically, and in git-gui.
+ - "wish", the Tcl/Tk windowing shell is used in gitk to show the
+ history graphically, and in git-gui. If you don't want gitk or
+ git-gui, you can use NO_TCLTK.
- Some platform specific issues are dealt with Makefile rules,
but depending on your specific installation, you may not
--
1.6.4.2.420.g30ecf
^ permalink raw reply related
* [PATCH 4/4] reset: add test cases for "--merge-dirty" option
From: Christian Couder @ 2009-09-10 20:23 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski, Linus Torvalds
In-Reply-To: <20090910200334.3722.20140.chriscool@tuxfamily.org>
This shows that with the "--merge-dirty" option, changes that are
both in the work tree and the index are kept in the work tree after
the reset (but discarded in the index). As with the "--merge" option,
changes that are in both the work tree and the index are discarded
after the reset.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
t/t7110-reset-merge.sh | 54 +++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh
index 45714ae..1e6d634 100755
--- a/t/t7110-reset-merge.sh
+++ b/t/t7110-reset-merge.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2009 Christian Couder
#
-test_description='Tests for "git reset --merge"'
+test_description='Tests for "git reset" with --merge and --merge-dirty'
exec </dev/null
@@ -19,7 +19,7 @@ test_expect_success 'creating initial files' '
git commit -m "Initial commit"
'
-test_expect_success 'ok with changes in file not changed by reset' '
+test_expect_success '--merge: ok if changes in file not touched by reset' '
echo "line 4" >> file1 &&
echo "line 4" >> file2 &&
test_tick &&
@@ -32,7 +32,21 @@ test_expect_success 'ok with changes in file not changed by reset' '
grep 4 file2
'
-test_expect_success 'discard changes added to index 1' '
+test_expect_success '--merge-dirty: ok if changes in file untouched by reset' '
+ git reset --hard HEAD^ &&
+ echo "line 4" >> file1 &&
+ echo "line 4" >> file2 &&
+ test_tick &&
+ git commit -m "add line 4" file1 &&
+ git reset --merge-dirty HEAD^ &&
+ ! grep 4 file1 &&
+ grep 4 file2 &&
+ git reset --merge-dirty HEAD@{1} &&
+ grep 4 file1 &&
+ grep 4 file2
+'
+
+test_expect_success '--merge: discard changes added to index 1' '
echo "line 5" >> file1 &&
git add file1 &&
git reset --merge HEAD^ &&
@@ -47,7 +61,7 @@ test_expect_success 'discard changes added to index 1' '
grep 4 file1
'
-test_expect_success 'discard changes added to index 2' '
+test_expect_success '--merge: discard changes added to index 2' '
echo "line 4" >> file2 &&
git add file2 &&
git reset --merge HEAD^ &&
@@ -57,7 +71,37 @@ test_expect_success 'discard changes added to index 2' '
grep 4 file1
'
-test_expect_success 'not ok with changes in file changed by reset' '
+test_expect_success '--merge-dirty: not ok with touched changes in index' '
+ echo "line 4" >> file2 &&
+ echo "line 5" >> file1 &&
+ git add file1 &&
+ test_must_fail git reset --merge-dirty HEAD^ &&
+ git reset --hard HEAD
+'
+
+test_expect_success '--merge-dirty: keep untouched changes' '
+ echo "line 4" >> file2 &&
+ git add file2 &&
+ git reset --merge-dirty HEAD^ &&
+ grep 4 file2 &&
+ git reset --merge HEAD@{1} &&
+ grep 4 file2 &&
+ grep 4 file1 &&
+ git reset --hard HEAD
+'
+
+test_expect_success '--merge: not ok with changes in file changed by reset' '
+ echo "line 6" >> file1 &&
+ test_tick &&
+ git commit -m "add line 6" file1 &&
+ sed -e "s/line 1/changed line 1/" <file1 >file3 &&
+ mv file3 file1 &&
+ test_must_fail git reset --merge HEAD^ 2>err.log &&
+ grep file1 err.log | grep "not uptodate"
+'
+
+test_expect_success '--merge-dirty: not ok with changes in file changed by reset' '
+ git reset --hard HEAD^ &&
echo "line 6" >> file1 &&
test_tick &&
git commit -m "add line 6" file1 &&
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 0/4] "git reset --merge" related improvements
From: Christian Couder @ 2009-09-10 20:23 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski, Linus Torvalds
As agreed during private discussions, I am trying to refactor and
merge some interesting bits of code from the GSoC sequencer project.
So here is a first round about "git reset".
Patches 1/4 and 2/4 are using sequencer code to speed up "git reset" and
add some test cases for "git reset --merge".
Patches 3/4 and 4/4 are implementing "git reset --merge-dirty" and
showing the differences with "--merge". "--merge-dirty" is a really bad
name for the index reset option that is available using the "allow_dirty"
global variable in the sequencer. These 2 patches are for discussing
this feature.
Christian Couder (2):
reset: add a few tests for "git reset --merge"
reset: add test cases for "--merge-dirty" option
Stephan Beyer (2):
reset: use "unpack_trees()" directly instead of "git read-tree"
reset: add option "--merge-dirty" to "git reset"
builtin-reset.c | 81 +++++++++++++++++++++++++++-------
t/t7110-reset-merge.sh | 114 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 179 insertions(+), 16 deletions(-)
create mode 100755 t/t7110-reset-merge.sh
^ permalink raw reply
* [PATCH 1/4] reset: add a few tests for "git reset --merge"
From: Christian Couder @ 2009-09-10 20:23 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski, Linus Torvalds
In-Reply-To: <20090910200334.3722.20140.chriscool@tuxfamily.org>
Commit 9e8eceab ("Add 'merge' mode to 'git reset'", 2008-12-01),
added the --merge option to git reset, but there were no test cases
for it.
This was not a big problem because "git reset" was just forking and
execing "git read-tree", but this will change in a following patch.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
t/t7110-reset-merge.sh | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 70 insertions(+), 0 deletions(-)
create mode 100755 t/t7110-reset-merge.sh
diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh
new file mode 100755
index 0000000..45714ae
--- /dev/null
+++ b/t/t7110-reset-merge.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Christian Couder
+#
+
+test_description='Tests for "git reset --merge"'
+
+exec </dev/null
+
+. ./test-lib.sh
+
+test_expect_success 'creating initial files' '
+ echo "line 1" >> file1 &&
+ echo "line 2" >> file1 &&
+ echo "line 3" >> file1 &&
+ cp file1 file2 &&
+ git add file1 file2 &&
+ test_tick &&
+ git commit -m "Initial commit"
+'
+
+test_expect_success 'ok with changes in file not changed by reset' '
+ echo "line 4" >> file1 &&
+ echo "line 4" >> file2 &&
+ test_tick &&
+ git commit -m "add line 4" file1 &&
+ git reset --merge HEAD^ &&
+ ! grep 4 file1 &&
+ grep 4 file2 &&
+ git reset --merge HEAD@{1} &&
+ grep 4 file1 &&
+ grep 4 file2
+'
+
+test_expect_success 'discard changes added to index 1' '
+ echo "line 5" >> file1 &&
+ git add file1 &&
+ git reset --merge HEAD^ &&
+ ! grep 4 file1 &&
+ ! grep 5 file1 &&
+ grep 4 file2 &&
+ echo "line 5" >> file2 &&
+ git add file2 &&
+ git reset --merge HEAD@{1} &&
+ ! grep 4 file2 &&
+ ! grep 5 file1 &&
+ grep 4 file1
+'
+
+test_expect_success 'discard changes added to index 2' '
+ echo "line 4" >> file2 &&
+ git add file2 &&
+ git reset --merge HEAD^ &&
+ ! grep 4 file2 &&
+ git reset --merge HEAD@{1} &&
+ ! grep 4 file2 &&
+ grep 4 file1
+'
+
+test_expect_success 'not ok with changes in file changed by reset' '
+ echo "line 6" >> file1 &&
+ test_tick &&
+ git commit -m "add line 6" file1 &&
+ sed -e "s/line 1/changed line 1/" <file1 >file3 &&
+ mv file3 file1 &&
+ test_must_fail git reset --merge HEAD^ 2>err.log &&
+ grep file1 err.log | grep "not uptodate"
+'
+
+test_done
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 2/4] reset: use "unpack_trees()" directly instead of "git read-tree"
From: Christian Couder @ 2009-09-10 20:23 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski, Linus Torvalds
In-Reply-To: <20090910200334.3722.20140.chriscool@tuxfamily.org>
From: Stephan Beyer <s-beyer@gmx.net>
This patch makes "reset_index_file()" call "unpack_trees()" directly
instead of forking and execing "git read-tree".
The code comes from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(at commit 5a78908b70ceb5a4ea9fd4b82f07ceba1f019079)
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-reset.c | 51 ++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/builtin-reset.c b/builtin-reset.c
index 73e6022..ddb81f3 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -18,6 +18,8 @@
#include "tree.h"
#include "branch.h"
#include "parse-options.h"
+#include "unpack-trees.h"
+#include "cache-tree.h"
static const char * const git_reset_usage[] = {
"git reset [--mixed | --soft | --hard | --merge] [-q] [<commit>]",
@@ -52,29 +54,56 @@ static inline int is_merge(void)
return !access(git_path("MERGE_HEAD"), F_OK);
}
+static int parse_and_init_tree_desc(const unsigned char *sha1,
+ struct tree_desc *desc)
+{
+ struct tree *tree = parse_tree_indirect(sha1);
+ if (!tree)
+ return 1;
+ init_tree_desc(desc, tree->buffer, tree->size);
+ return 0;
+}
+
static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet)
{
- int i = 0;
- const char *args[6];
+ int nr = 1;
+ int newfd;
+ struct tree_desc desc[2];
+ struct unpack_trees_options opts;
+ struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
- args[i++] = "read-tree";
+ memset(&opts, 0, sizeof(opts));
+ opts.head_idx = 1;
+ opts.src_index = &the_index;
+ opts.dst_index = &the_index;
+ opts.fn = oneway_merge;
+ opts.merge = 1;
if (!quiet)
- args[i++] = "-v";
+ opts.verbose_update = 1;
switch (reset_type) {
case MERGE:
- args[i++] = "-u";
- args[i++] = "-m";
+ opts.update = 1;
break;
case HARD:
- args[i++] = "-u";
+ opts.update = 1;
/* fallthrough */
default:
- args[i++] = "--reset";
+ opts.reset = 1;
}
- args[i++] = sha1_to_hex(sha1);
- args[i] = NULL;
- return run_command_v_opt(args, RUN_GIT_CMD);
+ newfd = hold_locked_index(lock, 1);
+
+ read_cache_unmerged();
+
+ if (parse_and_init_tree_desc(sha1, desc + nr - 1))
+ return error("Failed to find tree of %s.", sha1_to_hex(sha1));
+ if (unpack_trees(nr, desc, &opts))
+ return -1;
+ if (write_cache(newfd, active_cache, active_nr) ||
+ commit_locked_index(lock))
+ return error("Could not write new index file.");
+
+ return 0;
}
static void print_new_head_line(struct commit *commit)
--
1.6.4.271.ge010d
^ permalink raw reply related
* [PATCH 3/4] reset: add option "--merge-dirty" to "git reset"
From: Christian Couder @ 2009-09-10 20:23 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski, Linus Torvalds
In-Reply-To: <20090910200334.3722.20140.chriscool@tuxfamily.org>
From: Stephan Beyer <s-beyer@gmx.net>
This option is nearly like "--merge" except that it is
a little bit safer as it seems that it tries to keep
changes in the index. On the contrary "--merge", only
keep changes in the work tree.
This will be shown in the next patch that adds some
test cases for "--merge-dirty".
In fact with "--merge-dirty", changes that are both in
the work tree and the index are kept in the work tree
after the reset (but discarded in the index). As with
"--merge", changes that are in both the work tree and
the index are discarded after the reset.
So "--merge-dirty" is probably a very bad name for
this new option. Perhaps "--merge-safe" is better?
The code comes from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(at commit 5a78908b70ceb5a4ea9fd4b82f07ceba1f019079)
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-reset.c | 30 +++++++++++++++++++++++++-----
1 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/builtin-reset.c b/builtin-reset.c
index ddb81f3..be7aa8d 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -22,13 +22,15 @@
#include "cache-tree.h"
static const char * const git_reset_usage[] = {
- "git reset [--mixed | --soft | --hard | --merge] [-q] [<commit>]",
+ "git reset [--mixed | --soft | --hard | --merge | --merge-dirty] [-q] [<commit>]",
"git reset [--mixed] <commit> [--] <paths>...",
NULL
};
-enum reset_type { MIXED, SOFT, HARD, MERGE, NONE };
-static const char *reset_type_names[] = { "mixed", "soft", "hard", "merge", NULL };
+enum reset_type { MIXED, SOFT, HARD, MERGE, MERGE_DIRTY, NONE };
+static const char *reset_type_names[] = {
+ "mixed", "soft", "hard", "merge", "merge_dirty", NULL
+};
static char *args_to_str(const char **argv)
{
@@ -84,6 +86,7 @@ static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet
case MERGE:
opts.update = 1;
break;
+ case MERGE_DIRTY:
case HARD:
opts.update = 1;
/* fallthrough */
@@ -95,6 +98,16 @@ static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet
read_cache_unmerged();
+ if (reset_type == MERGE_DIRTY) {
+ unsigned char *head_sha1;
+ if (get_sha1("HEAD", head_sha1))
+ return error("You do not have a valid HEAD.");
+ if (parse_and_init_tree_desc(head_sha1, desc))
+ return error("Failed to find tree of HEAD.");
+ nr++;
+ opts.fn = twoway_merge;
+ }
+
if (parse_and_init_tree_desc(sha1, desc + nr - 1))
return error("Failed to find tree of %s.", sha1_to_hex(sha1));
if (unpack_trees(nr, desc, &opts))
@@ -238,6 +251,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
"reset HEAD, index and working tree", HARD),
OPT_SET_INT(0, "merge", &reset_type,
"reset HEAD, index and working tree", MERGE),
+ OPT_SET_INT(0, "merge-dirty", &reset_type,
+ "reset HEAD, index and working tree",
+ MERGE_DIRTY),
OPT_BOOLEAN('q', NULL, &quiet,
"disable showing new HEAD in hard reset and progress message"),
OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
@@ -324,9 +340,13 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (reset_type == SOFT) {
if (is_merge() || read_cache() < 0 || unmerged_cache())
die("Cannot do a soft reset in the middle of a merge.");
+ } else {
+ int err = reset_index_file(sha1, reset_type, quiet);
+ if (reset_type == MERGE_DIRTY)
+ err = err || reset_index_file(sha1, MIXED, quiet);
+ if (err)
+ die("Could not reset index file to revision '%s'.", rev);
}
- else if (reset_index_file(sha1, reset_type, quiet))
- die("Could not reset index file to revision '%s'.", rev);
/* Any resets update HEAD to the head being switched to,
* saving the previous head in ORIG_HEAD before. */
--
1.6.4.271.ge010d
^ permalink raw reply related
* Re: obnoxious CLI complaints
From: Jakub Narebski @ 2009-09-10 20:23 UTC (permalink / raw)
To: John Tapsell; +Cc: Wincent Colaiuta, Brendan Miller, git
In-Reply-To: <43d8ce650909101246l50189c97r4f3fc4a8d7a0bd4@mail.gmail.com>
Dnia czwartek 10. września 2009 21:46, John Tapsell napisał:
> 2009/9/10 Jakub Narebski <jnareb@gmail.com>:
> > First, it would be consistent with how ordinary archivers such as tar
> > or zip are used, where you have to specify list of files to archive
> > (in our case this list is HEAD). Second, I'd rather not accidentally
> > dump binary to terminal: "git archive [HEAD]" dumps archive to standard
> > output.
>
> That could be fixed by outputting to a file. git format-patch outputs
> to a file, so why wouldn't git achieve?
"git format-patch" outputs to files because it generates _multiple_
files; generating single patch is special case. Also git-format-patch
can generate file names from patch (commit) subject; it is not the case
for "git archive" (what name should it use?).
--
Jakub Narebski
Poland
^ permalink raw reply
* Re: obnoxious CLI complaints
From: Sverre Rabbelier @ 2009-09-10 20:17 UTC (permalink / raw)
To: John Tapsell; +Cc: Jakub Narebski, Wincent Colaiuta, Brendan Miller, git
In-Reply-To: <43d8ce650909101246l50189c97r4f3fc4a8d7a0bd4@mail.gmail.com>
Heya,
On Thu, Sep 10, 2009 at 21:46, John Tapsell <johnflux@gmail.com> wrote:
> That could be fixed by outputting to a file. git format-patch outputs
> to a file, so why wouldn't git achieve?
Because git format-patch works on a per-patch basis, and patches
inherently have a 'name' (the first line of the commit message), an
entire repository does not, so one would have to resort to arbitrary
names such as 'archive.tar.gz' or such.
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: [BUG] 'add -u' doesn't work from untracked subdir
From: Junio C Hamano @ 2009-09-10 19:53 UTC (permalink / raw)
To: Nanako Shiraishi; +Cc: Jeff King, Clemens Buchacher, SZEDER Gbor, git
In-Reply-To: <20090910084653.6117@nanako3.lavabit.com>
Nanako Shiraishi <nanako3@lavabit.com> writes:
> Quoting Junio C Hamano <gitster@pobox.com>
>
>> We could probably declare "In 1.X.0 everything will be relative to the
>> root and you have to give an explicit '.' if you mean the cwd".
>>
>> Three questions:
>>
>> #1 What are the commands that will be affected, other than "add -u" and
>> "grep"? Are there others?
>>
>> #2 Do all the commands in the answer to #1 currently behave exactly the
>> same when run without any path parameter and when run with a single
>> '.'?
>
> 'git-archive' behaves relative to your current directory.
>
> http://thread.gmane.org/gmane.comp.version-control.git/41300/focus=44125
>
> You can limit it to the current directory with a dot.
Thanks.
If you want to make a tarball of the Documentation directory from your
work tree, you do this:
$ cd Documentation
$ tar cf - . >/tmp/docs.tar
If you want to do the same but from your committed content, you do this:
$ cd Documentation
$ git archive HEAD >/tmp/docs.tar
and you do not have to say:
$ cd Documentation
$ git archive HEAD . >/tmp/docs.tar
So in that sense it does make sense to archive the current directory. It
matches what the users expect from their archivers.
The traditional archivers may not default to "." but we do. That is about
giving a sensible default [*1*]. Perhaps defaulting to the cwd behaviour
for one command may seem a sensible thing when looking at that particular
command alone; archive and grep fall into that category.
But as this "add -u" discussion showed us [*2*], people may expect
different "sensible default", and as a suite of commands as the whole, it
becomes messy. People have to remember which ones obey cwd, and to some
people the choice is not intuitive.
To avoid confusion, I am beginning to agree with people who said in the
thread that it is a good idea to consistently default to the root of the
contents. When we use "everything" as the default due to lack of command
line pathspec, we would use "everything from root" no matter where you
are, regardless of what command we are talking about. That would make the
rule easier to remember [*3*].
This changes the way how "git (add -u|grep|clean|archive)" without
pathspec and "git (add -u|grep|clean|archive) ." with an explicit dot
work. The former (adds all changed files in, finds hits in, removes
untracked paths in, creates a tarball for) the whole tree, while the
latter limits the operation explicitly to the current directory.
If this were going to happen as a list concensus, I am very tempted to
suggest that we at least _consider_ applying the same rule even to
ls-files and ls-tree. That would impact scripts, so we need to be extra
careful, though.
Also this takes us to a tangent.
If we try to give a sensible default to make it easier for the user,
perhaps we should also default to HEAD when the user did not specify which
tree-ish to archive from. This is a topic in a separate thread.
[Footnote]
*1* Actually we don't allow "git archive HEAD ..", which I think is a
bug. Also we do not have --full-tree workaround, which makes it slightly
cumbersome to use.
*2* And the thread you quoted shows us that the argument applies equally
to "git archive" as well; you see me complaining that it is unintuitive
for me to care about "archive", and the counterargument was that ls-tree
does so. I however think it is more important for archive to behave in a
way that is easier for the users to understand, than mimick the historical
mistake in a plumbing command.
*3* Command line pathspec of course should honor cwd as before. When you
say "git distim Makefile" inside t/ directory, we distim t/Makefile, not
the toplevel Makefile. This discussion is only about the case where the
user didn't give us any pathspec.
^ permalink raw reply
* Re: obnoxious CLI complaints
From: John Tapsell @ 2009-09-10 19:46 UTC (permalink / raw)
To: Jakub Narebski; +Cc: Wincent Colaiuta, Brendan Miller, git
In-Reply-To: <200909101850.26109.jnareb@gmail.com>
2009/9/10 Jakub Narebski <jnareb@gmail.com>:
> Dnia czwartek 10. września 2009 00:06, Wincent Colaiuta napisał:
>> El 09/09/2009, a las 23:54, Jakub Narebski escribió:
>>> Brendan Miller <catphive@catphive.net> writes:
>>>
>>>> 5. Most commands require lots of flags, and don't have reasonable
>>>> defaults. e.g. archive.
>>>>
>>>> $ git archive --format=tar --prefix=myproject/ HEAD |
>>>> > gzip myproject.tar.gz
>>>>
>>>> Should just be:
>>>> git archive
>>>> run from the root of the repo.
>>>
>>> I'd rather not have "git archive" work without specifying tree-ish.
>>
>> Why, out of interest? I would've thought that HEAD would be a pretty
>> good default, although I confess that I have never used "git archive"
>> without specifying a particular signed tag.
>
> First, it would be consistent with how ordinary archivers such as tar
> or zip are used, where you have to specify list of files to archive
> (in our case this list is HEAD). Second, I'd rather not accidentally
> dump binary to terminal: "git archive [HEAD]" dumps archive to standard
> output.
That could be fixed by outputting to a file. git format-patch outputs
to a file, so why wouldn't git achieve?
John
^ permalink raw reply
* Re: [PATCH v3 3/3] INSTALL: Describe dependency knobs from Makefile
From: Junio C Hamano @ 2009-09-10 18:56 UTC (permalink / raw)
To: Brian Gernhardt; +Cc: Git List
In-Reply-To: <1252591928-2278-1-git-send-email-brian@gernhardtsoftware.com>
Brian Gernhardt <brian@gernhardtsoftware.com> writes:
> We said that some of our dependencies were optional, but didn't say
> how to turn them off. Add information for that and mention where to
> save the options close to the top of the file.
>
> Also, standardize on both using quotes for the names of the dependencies
> and tabs for indentation of the list.
>
> Signed-off-by: Brian Gernhardt <brian@gernhardtsoftware.com>
> ---
>
> Junio C Hamano <gitster@pobox.com> wrote:
> > I did not like calling "make variables" "options", and also it was unclear
> > what good these "options" are for. How about...
>
> Sounds good. Would have sent this out yesterday, but I ran out of tuits.
>
> INSTALL | 38 ++++++++++++++++++++++++--------------
> 1 files changed, 24 insertions(+), 14 deletions(-)
>
> diff --git a/INSTALL b/INSTALL
> index 7ab2580..69c97b2 100644
> --- a/INSTALL
> +++ b/INSTALL
> @@ -13,6 +13,10 @@ that uses $prefix, the built results have some paths encoded,
> which are derived from $prefix, so "make all; make prefix=/usr
> install" would not work.
>
> +There are many options that can be configured in the makefile using either
> +command line defines or a config.mak file. These options are documented at
> +the beginning of the Makefile.
Sorry, but the description still speaks of options and does not say what
good they are. Sent a wrong patch?
^ permalink raw reply
* Re: obnoxious CLI complaints
From: Matthieu Moy @ 2009-09-10 18:54 UTC (permalink / raw)
To: Björn Steinbrink; +Cc: Brendan Miller, git
In-Reply-To: <20090910013235.GA9980@atjola.homenet>
Björn Steinbrink <B.Steinbrink@gmx.de> writes:
> On 2009.09.09 14:27:56 -0700, Brendan Miller wrote:
>> 8. There's no obvious way to make a remote your default push pull
>> location without editing the git config file. Why not just something
>> like
>>
>> git remote setdefault origin
>
> Because "git remote" is the wrong tool. The default remote for
> fetch/push is configured per branch head, not globally.
(the --track option of git branch and git checkout can help).
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: obnoxious CLI complaints
From: Junio C Hamano @ 2009-09-10 18:53 UTC (permalink / raw)
To: Jakub Narebski; +Cc: Wincent Colaiuta, Brendan Miller, git
In-Reply-To: <200909101850.26109.jnareb@gmail.com>
Jakub Narebski <jnareb@gmail.com> writes:
> First, it would be consistent with how ordinary archivers such as tar
> or zip are used, where you have to specify list of files to archive
> (in our case this list is HEAD). Second, I'd rather not accidentally
> dump binary to terminal: "git archive [HEAD]" dumps archive to standard
> output.
So does "cat". I do not agree with your second point.
While I somewhat see the similarity argument, your first point, I am not
sure if it is relevant. It is not like "tar or zip allows us to say what
files to archive, but git-archive doesn't and it always archives HEAD";
you are saying "they require us to specify, so should we".
But I do not see a strong reason not to default to HEAD. The case that
would make difference would be to differentiate among
$ git archive HEAD TAIL
$ git archive HEAD -- TAIL
$ git archive -- HEAD TAIL
i.e. what if you happen to have a tracked content called HEAD. I didn't
check the current command line parser in git-archive understands the "--"
convention for that, but it is not a rocket science to add it if it
doesn't.
^ permalink raw reply
* Re: obnoxious CLI complaints
From: Sverre Rabbelier @ 2009-09-10 18:52 UTC (permalink / raw)
To: Eric Schaefer; +Cc: git
In-Reply-To: <34f8975d0909101118x7c95be1ehda085bea1611b70c@mail.gmail.com>
Heya,
On Thu, Sep 10, 2009 at 20:18, Eric Schaefer
<eric.schaefer@ericschaefer.org> wrote:
> "Unimportant bug reports"? Interesting concept... ;-)
Sure, if there's a bug in feature foo, but it only happens when
invoking it with some rarely used argument, and only on Solaris
platforms, it is probably not worth spending time on it if the
original reporter does not even have the time to stick around and aid
in resolving the issue. It's probably better to spend that precious
time on other bug fixes, or features instead.
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: What's cooking in git.git (Sep 2009, #02; Mon, 07)
From: Junio C Hamano @ 2009-09-10 18:41 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Daniel Barkalow, Junio C Hamano, git
In-Reply-To: <alpine.DEB.1.00.0909101852080.8306@pacific.mpi-cbg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> There is a reason why you call the series "foreign" vcs helpers. And
> that's because it would be very wrong to pretend that they are the rule,
> and the current URL schemes the exception. Very wrong, indeed.
I do not know what you mean by "very wrong".
If the name bothers you, you can think of the earlier part of the series
cleaning up the transport code so that it makes easier to choose which
transport, either internal or external, and ports the native transport
support to use the mechanism. Then the rest of the series builds on it to
add further support for "foreign" vcs helpers.
^ permalink raw reply
* Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch
From: Junio C Hamano @ 2009-09-10 18:29 UTC (permalink / raw)
To: Jeff King
Cc: Johan Herland, git, Michael J Gruber, Johannes Schindelin,
Junio C Hamano, Björn Steinbrink, Pete Wyckoff
In-Reply-To: <20090910111156.GA2910@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
> On Thu, Sep 10, 2009 at 12:18:06PM +0200, Johan Herland wrote:
>
>> > > A special shortcut '@{tracked}' refers to the branch tracked by the
>> > > current branch.
>> >
>> > Sorry, I didn't know the name of the long form was up for discussion.
>> > But it should certainly coincide with the key which for-each-ref
>> > uses, shouldn't it? I don't care whether tracked or upstream, but
>> > for-each-ref's "upstream" has set the precedent.
>>
>> ...and 'git branch --track' set an even earlier precedent...
>
> FWIW, that came about from this discussion:
>
> http://article.gmane.org/gmane.comp.version-control.git/115765
After re-reading the discussion in the thread that contains the quoted
article, it sounds like we may want to fix "branch --track X Y". X does
not "track" Y in the same sense as origin/master "tracks" master at
origin. Rather, X builds on Y.
^ 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