* Re: [PATCH 3/3] gitweb: use new Git::Repo API, and add optional caching
From: Jakub Narebski @ 2008-07-14 21:23 UTC (permalink / raw)
To: Lea Wiemann; +Cc: git, John Hawley, Petr Baudis
In-Reply-To: <1215738708-5212-1-git-send-email-LeWiemann@gmail.com>
On Fri, 11 July 2008, Lea Wiemann wrote:
> Gitweb now uses the Git::Repo API; this change is behavior-preserving,
> except for slightly more aggressive error handling; see below.
Good.
It was suggested to split this into separate commit from the following
change, for making it easier to test (you can check that behavior is
the same, with the exception of error handling) and review (smaller
patch to read and review).
> This patch also adds an optional caching layer for caching repository
> data in memory and (for larger cacheable items, like blobs, snapshots,
> or diffs) on disk.
As it was said, if feasible it would be good idea to put this change
into separate commit.
> Other minor changes:
>
> - Gitweb would previously accept invalid input and either (a) display
> nothing, (b) display an obscure error message, or (c) proceed as
> normal since the parameter happens to be unused in the particular
> code path used. This has changed in that gitweb will check for
> parameter correctness more aggressively, and display meaningful
> error messages. This change is only relevant if you manually edit
> gitweb's CGI parameters, since gitweb only generates valid links.
I understand that this change deals with treating invalid specifiers,
which point to either object that do not exists, are ambiguous, or point
to object of invalid type. Gitweb does check "syntactic" validity of
input (of CGI parameters) already, even those that are not used for
selected action.
BTW. such check was not feasible before implementing --batch and/or
--batch-check options to git-cat-file; I think that possibly one more
fork is not much price to pay for better error checking.
> - Empty projects:
>
> - Only display summary link for empty projects in project list to
> avoid broken links (yielding 404).
>
> - Slim down summary page for empty projects to avoid some broken
> links and unnecessary vertical space.
>
> - Sort empty projects at the bottom of the project list when sorting
> by last change.
>
> - Add test for empty projects to t9503 (the Mechanize test), now
> that there no broken links anymore.
Good. The only thing that *might* be controversial is putting empty
projects at the bottom of sorted by age (by last change) projects list,
instead of at top.
> - For HTML pages, remove the "Expires" HTTP response header, and add
> "Cache-Control: no-cache" instead. This is because pages can
> contain dynamic content (like the subject of the latest commit), so
> the Expires headers would be wrong.
>
> This makes gitweb's responsiveness slightly worse, but it will get
> much better once If-Last-Modified is implemented. It's better to be
> correct than to be convenient here, since having to press the reload
> button makes for lousy user experience (IOW, users should be able to
> always trust gitweb's output).
>
> Raw diffs and blobs still get the Expires header, where appropriate.
I don't think it is a good change.
Gitweb generates two types of views (pages): transient and immutable.
An example of transient view (transient page/action) is for example RSS
feed, or summary page. When project (repository) is updated, they can
change.
The opposite are immutable pages. They are pages/actions/views where
all specifiers are given by full SHA-1; to be more exact all specifiers
that are needed to reconstruct object are given by SHA-1. (It is
enough to have sufficient check for immutability, i.e. such that if
check succeeds, then page is immutable, but it doesn't need to be true
in reverse.)
Gitweb sets expires to '+1d' which is one day to pages it considers
immutable, while not defining expires for other pages (which results,
I think, in lack of expires header). We could have set it to "forever",
which in terms of Expires: HTTP header is half a year (from what
I remember).
Now I don't see *any* reason to not set long expires for immutable
pages; I don't know if forbidding to cache transient pages even if in
fact they are generated dynamically is a good idea... Note that if
caching is enabled, you can set expires to either time-to-expire of
cache entries (simpler), or time left to live to invalidation of item
in cache (better, but more complicated) perhaps also setting Age:
header to appropriate value.
Sidenote: we would probably want to use Expires: for HTTP/1.0 requests,
and Cache-Control: max-age=<seconds> for HTTP/1.1 requests. But that
might be left as improvement for later...
> - Add a $page_info option to display cache stats at the bottom of each
> page; the option is named generically to allow for adding non-cache
> page info there at some point (timings perhaps?).
Great idea!
> ---
> It's all documented of course :-), but for the impatient here's a
> snippet for gitweb_config.perl to activate caching:
Nice.
> use Cache::Memcached;
> $cache = Cache::Memcached->new( { servers => ['localhost:11211'],
> compress_threshold => 1000 } );
IIRC you can use any Cache::Cache compatibile (is it explained later
what it means?) cache here; IMVHO it would be nice if this info would
be also in commit message.
> $large_cache_root = '/home/lewiemann/gitweb-cache';
> $large_cache_case_sensitive = 1;
Errr... I understand that it is your _private_ configuration, just
copied here verbatim, but I don't think '/home/lewiemann/gitweb-cache'
is a good example: '/tmp/gitweb-cache' perhaps, that I can understand.
> # Invalidate cache on changes to gitweb without version number bump;
> # useful for development.
> $cache_key = (stat '/home/lewiemann/gitweb')[9] .
> (stat '/home/lewiemann/gitweb/gitweb.cgi')[9];
What should be used in production? "$cache_key = $version;"?
Besides hardcoding those paths is not a good idea. You can always
use $ENV{'SCRIPT_FILENAME'}, or dirname of it.
> # Display detailed cache info at the bottom of each page.
> $page_info = 2;
Errr... what does "$page_info = <n>;" mean?
> A live demo is here: http://odin3.kernel.org/git-lewiemann/
Nice. Thanks.
[...]
> gitweb/README | 14 +
Very good.
[Comments on patch itself in separate email, later]
--
Jakub Narebski
Poland
^ permalink raw reply
* [BUG] commit walk machinery is dangerous !
From: Nicolas Pitre @ 2008-07-14 20:54 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Good! I have all your attention now.
Yes, I'm kinda fscking upset about my hardware at this moment. I
apparently have git packs corrupting themselves from time to time which
prompted me to make git more robust against some kind of corruptions
recently.
However this time a corruption turned up and exposed what I think is a
major flaw in git's error checking. To demonstrate it, I created the
following test case. Turning the error() into a die() on line 772 of
commit.c makes this test pass but I don't know if this is the
appropriate fix (e.g. some attempt to parse non existing commits could
be valid usage, etc.). Note this is critical only for git versions
later than commit 8eca0b47ff15.
So here's the test. The catastrophic consequences that this can have on
one's repository is left as an exercise to the reader.
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
new file mode 100755
index 0000000..a5fe190
--- /dev/null
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='git rev-list should notice bad commits'
+
+. ./test-lib.sh
+
+# Note:
+# - compression level is set to zero to make "corruptions" easier to perform
+# - reflog is disabled to avoid extra references which would twart the test
+
+test_expect_success 'setup' \
+ '
+ git init &&
+ git config core.compression 0 &&
+ git config core.logallrefupdates false &&
+ echo "foo" > foo &&
+ git add foo &&
+ git commit -m "first commit" &&
+ echo "bar" > bar &&
+ git add bar &&
+ git commit -m "second commit" &&
+ echo "baz" > baz &&
+ git add baz &&
+ git commit -m "third commit" &&
+ echo "foo again" >> foo &&
+ git add foo &&
+ git commit -m "fourth commit" &&
+ git repack -a -f -d
+ '
+
+test_expect_success 'verify number of revisions' \
+ '
+ revs=$(git rev-list --all | wc -l) &&
+ test $revs -eq 4 &&
+ first_commit=$(git rev-parse HEAD~3)
+ '
+
+test_expect_success 'corrupt second commit object' \
+ '
+ perl -i.bak -pe "s/second commit/socond commit/" .git/objects/pack/*.pack &&
+ test_must_fail git fsck --all
+ '
+
+test_expect_success 'rev-list should fail' \
+ '
+ test_must_fail git rev-list --all > /dev/null
+ '
+
+test_expect_success 'git repack _MUST_ fail' \
+ '
+ test_must_fail git repack -a -f -d
+ '
+
+test_expect_success 'first commit is still available' \
+ '
+ git log $first_commit
+ '
+
+test_done
+
^ permalink raw reply related
* Re: [PATCH] git-rebase.sh: Display error output from git-checkout when detaching HEAD fails.
From: Rob Shearman @ 2008-07-14 19:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vr6a0hvvu.fsf@gitster.siamese.dyndns.org>
[-- Attachment #1: Type: text/plain, Size: 1723 bytes --]
2008/7/11 Junio C Hamano <gitster@pobox.com>:
> Robert Shearman <robertshearman@gmail.com> writes:
>> diff --git a/git-rebase.sh b/git-rebase.sh
>> index e2d85ee..0da2210 100755
>> --- a/git-rebase.sh
>> +++ b/git-rebase.sh
>> @@ -376,7 +376,7 @@ fi
>>
>> # Detach HEAD and reset the tree
>> echo "First, rewinding head to replay your work on top of it..."
>> -git checkout "$onto^0" >/dev/null 2>&1 ||
>
> I think this very much is done deliberately by somebody who knows the
> shell to discard everything.
Why wasn't "git checkout "$onto^0" &> /dev/null" used then? Then only
reason I can come up with would be portability, but it seems
surprising to me.
>> +git checkout "$onto^0" 2>&1 >/dev/null ||
>
> And if it is beneficial to show the error, you just do not touch fd #2,
> like this:
>
> git checkout "$onto^0" >/dev/null
Absolutely. I was just trying to fix the statement to what I thought
was the original intent.
> As I do not see any reason to send the error message to stdout like you
> did.
>
> I also suspect that this part of the script predates 6124aee (add a quiet
> option to git-checkout, 2007-02-01) where the command learned to be more
> quiet during the normal operation. Perhaps you can replace the line with
>
> git checkout -q "$onto^0"
>
> and be done with it. I haven't tested it, though.
I just tested it and it solves the original issue whilst not
displaying unnecessary messages during a rebase. For reference, the
attached script reproduces the issue that I was trying to solve.
Should I resend the patch (like the following) now that it is
effectively completely your work?
-git checkout "$onto^0" >/dev/null 2>&1 ||
+git checkout -q "$onto^0" ||
--
Rob Shearman
[-- Attachment #2: rebase_clash.sh --]
[-- Type: application/x-sh, Size: 356 bytes --]
^ permalink raw reply
* Re: Syncing up to a tree with a numeric EXTRAVERSION
From: vb @ 2008-07-14 19:41 UTC (permalink / raw)
To: Miklos Vajna; +Cc: git
In-Reply-To: <20080714192947.GS10347@genesis.frugalware.org>
On Mon, Jul 14, 2008 at 12:29 PM, Miklos Vajna <vmiklos@frugalware.org> wrote:
> On Mon, Jul 14, 2008 at 12:24:33PM -0700, vb <vb@vsbe.com> wrote:
>> VERSION = 2
>> PATCHLEVEL = 6
>> SUBLEVEL = 19
>> EXTRAVERSION = .2
>> NAME=Avast! A bilge rat!
>>
>> (...)
>>
>> so, the question is where do I find the tree with the Makefile
>> EXTRAVERSION set to .2?
>
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.19.y.git ?
>
> Hope this helps.
>
It certainly does, and it was quick too! Thanks a lot!
/vb
^ permalink raw reply
* [PATCH 4/6] archive: centralize archive entry writing
From: René Scharfe @ 2008-07-14 19:22 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <487B92FC.5030103@lsrfire.ath.cx>
Add the exported function write_archive_entries() to archive.c, which uses
the new ability of read_tree_recursive() to pass a context pointer to its
callback in order to centralize previously duplicated code.
The new callback function write_archive_entry() does the work that every
archiver backend needs to do: loading file contents, entering subdirectories,
handling file attributes, constructing the full path of the entry. All that
done, it calls the backend specific write_archive_entry_fn_t function.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
archive.c | 77 ++++++++++++++++++++++++++++++++++++++
archive.h | 4 ++
archive-tar.c | 116 ++++++++++++++++++--------------------------------------
archive-zip.c | 90 +++++++-------------------------------------
4 files changed, 133 insertions(+), 154 deletions(-)
diff --git a/archive.c b/archive.c
index 6502b76..58de55e 100644
--- a/archive.c
+++ b/archive.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "commit.h"
#include "attr.h"
+#include "archive.h"
static void format_subst(const struct commit *commit,
const char *src, size_t len,
@@ -95,3 +96,79 @@ int is_archive_path_ignored(const char *path)
return 0;
return ATTR_TRUE(check[0].value);
}
+
+struct archiver_context {
+ struct archiver_args *args;
+ write_archive_entry_fn_t write_entry;
+};
+
+static int write_archive_entry(const unsigned char *sha1, const char *base,
+ int baselen, const char *filename, unsigned mode, int stage,
+ void *context)
+{
+ static struct strbuf path = STRBUF_INIT;
+ struct archiver_context *c = context;
+ struct archiver_args *args = c->args;
+ write_archive_entry_fn_t write_entry = c->write_entry;
+ int err;
+ enum object_type type;
+ unsigned long size;
+ void *buffer;
+
+ strbuf_reset(&path);
+ strbuf_grow(&path, PATH_MAX);
+ strbuf_add(&path, base, baselen);
+ strbuf_addstr(&path, filename);
+
+ if (is_archive_path_ignored(path.buf + args->baselen))
+ return 0;
+
+ if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
+ strbuf_addch(&path, '/');
+ if (args->verbose)
+ fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
+ err = write_entry(args, sha1, path.buf, path.len, mode, NULL, 0);
+ if (err)
+ return err;
+ return READ_TREE_RECURSIVE;
+ }
+
+ buffer = sha1_file_to_archive(path.buf + args->baselen, sha1, mode,
+ &type, &size, args->commit);
+ if (!buffer)
+ return error("cannot read %s", sha1_to_hex(sha1));
+ if (args->verbose)
+ fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
+ err = write_entry(args, sha1, path.buf, path.len, mode, buffer, size);
+ free(buffer);
+ return err;
+}
+
+int write_archive_entries(struct archiver_args *args,
+ write_archive_entry_fn_t write_entry)
+{
+ struct archiver_context context;
+ int err;
+
+ if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
+ size_t len = args->baselen;
+
+ while (len > 1 && args->base[len - 2] == '/')
+ len--;
+ if (args->verbose)
+ fprintf(stderr, "%.*s\n", (int)len, args->base);
+ err = write_entry(args, args->tree->object.sha1, args->base,
+ len, 040777, NULL, 0);
+ if (err)
+ return err;
+ }
+
+ context.args = args;
+ context.write_entry = write_entry;
+
+ err = read_tree_recursive(args->tree, args->base, args->baselen, 0,
+ args->pathspec, write_archive_entry, &context);
+ if (err == READ_TREE_RECURSIVE)
+ err = 0;
+ return err;
+}
diff --git a/archive.h b/archive.h
index 34151f4..4e44549 100644
--- a/archive.h
+++ b/archive.h
@@ -20,6 +20,8 @@ typedef int (*write_archive_fn_t)(struct archiver_args *);
typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv);
+typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, void *buffer, unsigned long size);
+
struct archiver {
const char *name;
write_archive_fn_t write_archive;
@@ -44,4 +46,6 @@ extern void *parse_extra_zip_args(int argc, const char **argv);
extern void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size, const struct commit *commit);
extern int is_archive_path_ignored(const char *path);
+extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
+
#endif /* ARCHIVE_H */
diff --git a/archive-tar.c b/archive-tar.c
index 63cc2ec..f9eb726 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -13,11 +13,7 @@
static char block[BLOCKSIZE];
static unsigned long offset;
-static time_t archive_time;
static int tar_umask = 002;
-static int verbose;
-static const struct commit *commit;
-static size_t base_len;
/* writes out the whole block, but only if it is full */
static void write_if_needed(void)
@@ -114,22 +110,24 @@ static unsigned int ustar_header_chksum(const struct ustar_header *header)
return chksum;
}
-static int get_path_prefix(const struct strbuf *path, int maxlen)
+static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen)
{
- int i = path->len;
+ size_t i = pathlen;
if (i > maxlen)
i = maxlen;
do {
i--;
- } while (i > 0 && path->buf[i] != '/');
+ } while (i > 0 && path[i] != '/');
return i;
}
-static void write_entry(const unsigned char *sha1, struct strbuf *path,
- unsigned int mode, void *buffer, unsigned long size)
+static int write_tar_entry(struct archiver_args *args,
+ const unsigned char *sha1, const char *path, size_t pathlen,
+ unsigned int mode, void *buffer, unsigned long size)
{
struct ustar_header header;
struct strbuf ext_header;
+ int err = 0;
memset(&header, 0, sizeof(header));
strbuf_init(&ext_header, 0);
@@ -143,8 +141,6 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
mode = 0100666;
sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1));
} else {
- if (verbose)
- fprintf(stderr, "%.*s\n", (int)path->len, path->buf);
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
*header.typeflag = TYPEFLAG_DIR;
mode = (mode | 0777) & ~tar_umask;
@@ -155,24 +151,24 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
*header.typeflag = TYPEFLAG_REG;
mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask;
} else {
- error("unsupported file mode: 0%o (SHA1: %s)",
- mode, sha1_to_hex(sha1));
- return;
+ return error("unsupported file mode: 0%o (SHA1: %s)",
+ mode, sha1_to_hex(sha1));
}
- if (path->len > sizeof(header.name)) {
- int plen = get_path_prefix(path, sizeof(header.prefix));
- int rest = path->len - plen - 1;
+ if (pathlen > sizeof(header.name)) {
+ size_t plen = get_path_prefix(path, pathlen,
+ sizeof(header.prefix));
+ size_t rest = pathlen - plen - 1;
if (plen > 0 && rest <= sizeof(header.name)) {
- memcpy(header.prefix, path->buf, plen);
- memcpy(header.name, path->buf + plen + 1, rest);
+ memcpy(header.prefix, path, plen);
+ memcpy(header.name, path + plen + 1, rest);
} else {
sprintf(header.name, "%s.data",
sha1_to_hex(sha1));
strbuf_append_ext_header(&ext_header, "path",
- path->buf, path->len);
+ path, pathlen);
}
} else
- memcpy(header.name, path->buf, path->len);
+ memcpy(header.name, path, pathlen);
}
if (S_ISLNK(mode) && buffer) {
@@ -187,7 +183,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
sprintf(header.mode, "%07o", mode & 07777);
sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0);
- sprintf(header.mtime, "%011lo", archive_time);
+ sprintf(header.mtime, "%011lo", args->time);
sprintf(header.uid, "%07o", 0);
sprintf(header.gid, "%07o", 0);
@@ -202,22 +198,30 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
sprintf(header.chksum, "%07o", ustar_header_chksum(&header));
if (ext_header.len > 0) {
- write_entry(sha1, NULL, 0, ext_header.buf, ext_header.len);
+ err = write_tar_entry(args, sha1, NULL, 0, 0, ext_header.buf,
+ ext_header.len);
+ if (err)
+ return err;
}
strbuf_release(&ext_header);
write_blocked(&header, sizeof(header));
if (S_ISREG(mode) && buffer && size > 0)
write_blocked(buffer, size);
+ return err;
}
-static void write_global_extended_header(const unsigned char *sha1)
+static int write_global_extended_header(struct archiver_args *args)
{
+ const unsigned char *sha1 = args->commit_sha1;
struct strbuf ext_header;
+ int err;
strbuf_init(&ext_header, 0);
strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40);
- write_entry(NULL, NULL, 0, ext_header.buf, ext_header.len);
+ err = write_tar_entry(args, NULL, NULL, 0, 0, ext_header.buf,
+ ext_header.len);
strbuf_release(&ext_header);
+ return err;
}
static int git_tar_config(const char *var, const char *value, void *cb)
@@ -234,63 +238,17 @@ static int git_tar_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
-static int write_tar_entry(const unsigned char *sha1, const char *base,
- int baselen, const char *filename, unsigned mode, int stage,
- void *context)
-{
- static struct strbuf path = STRBUF_INIT;
- void *buffer;
- enum object_type type;
- unsigned long size;
-
- strbuf_reset(&path);
- strbuf_grow(&path, PATH_MAX);
- strbuf_add(&path, base, baselen);
- strbuf_addstr(&path, filename);
- if (is_archive_path_ignored(path.buf + base_len))
- return 0;
- if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
- strbuf_addch(&path, '/');
- buffer = NULL;
- size = 0;
- } else {
- buffer = sha1_file_to_archive(path.buf + base_len, sha1, mode,
- &type, &size, commit);
- if (!buffer)
- die("cannot read %s", sha1_to_hex(sha1));
- }
-
- write_entry(sha1, &path, mode, buffer, size);
- free(buffer);
-
- return READ_TREE_RECURSIVE;
-}
-
int write_tar_archive(struct archiver_args *args)
{
- git_config(git_tar_config, NULL);
+ int err = 0;
- archive_time = args->time;
- verbose = args->verbose;
- commit = args->commit;
- base_len = args->baselen;
+ git_config(git_tar_config, NULL);
if (args->commit_sha1)
- write_global_extended_header(args->commit_sha1);
-
- if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
- char *base = xstrdup(args->base);
- int baselen = strlen(base);
-
- while (baselen > 0 && base[baselen - 1] == '/')
- base[--baselen] = '\0';
- write_tar_entry(args->tree->object.sha1, "", 0, base, 040777,
- 0, NULL);
- free(base);
- }
- read_tree_recursive(args->tree, args->base, args->baselen, 0,
- args->pathspec, write_tar_entry, NULL);
- write_trailer();
-
- return 0;
+ err = write_global_extended_header(args);
+ if (!err)
+ err = write_archive_entries(args, write_tar_entry);
+ if (!err)
+ write_trailer();
+ return err;
}
diff --git a/archive-zip.c b/archive-zip.c
index d18254c..8131289 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -9,11 +9,8 @@
#include "builtin.h"
#include "archive.h"
-static int verbose;
static int zip_date;
static int zip_time;
-static const struct commit *commit;
-static size_t base_len;
static unsigned char *zip_dir;
static unsigned int zip_dir_size;
@@ -128,33 +125,9 @@ static void *zlib_deflate(void *data, unsigned long size,
return buffer;
}
-static char *construct_path(const char *base, int baselen,
- const char *filename, int isdir, int *pathlen)
-{
- int filenamelen = strlen(filename);
- int len = baselen + filenamelen;
- char *path, *p;
-
- if (isdir)
- len++;
- p = path = xmalloc(len + 1);
-
- memcpy(p, base, baselen);
- p += baselen;
- memcpy(p, filename, filenamelen);
- p += filenamelen;
- if (isdir)
- *p++ = '/';
- *p = '\0';
-
- *pathlen = len;
-
- return path;
-}
-
-static int write_zip_entry(const unsigned char *sha1, const char *base,
- int baselen, const char *filename, unsigned mode, int stage,
- void *context)
+static int write_zip_entry(struct archiver_args *args,
+ const unsigned char *sha1, const char *path, size_t pathlen,
+ unsigned int mode, void *buffer, unsigned long size)
{
struct zip_local_header header;
struct zip_dir_header dirent;
@@ -163,33 +136,20 @@ static int write_zip_entry(const unsigned char *sha1, const char *base,
unsigned long uncompressed_size;
unsigned long crc;
unsigned long direntsize;
- unsigned long size;
int method;
- int result = -1;
- int pathlen;
unsigned char *out;
- char *path;
- enum object_type type;
- void *buffer = NULL;
void *deflated = NULL;
crc = crc32(0, NULL, 0);
- path = construct_path(base, baselen, filename, S_ISDIR(mode), &pathlen);
- if (is_archive_path_ignored(path + base_len))
- return 0;
- if (verbose)
- fprintf(stderr, "%s\n", path);
if (pathlen > 0xffff) {
- error("path too long (%d chars, SHA1: %s): %s", pathlen,
- sha1_to_hex(sha1), path);
- goto out;
+ return error("path too long (%d chars, SHA1: %s): %s",
+ (int)pathlen, sha1_to_hex(sha1), path);
}
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
method = 0;
attr2 = 16;
- result = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
out = NULL;
uncompressed_size = 0;
compressed_size = 0;
@@ -199,19 +159,13 @@ static int write_zip_entry(const unsigned char *sha1, const char *base,
(mode & 0111) ? ((mode) << 16) : 0;
if (S_ISREG(mode) && zlib_compression_level != 0)
method = 8;
- result = 0;
- buffer = sha1_file_to_archive(path + base_len, sha1, mode,
- &type, &size, commit);
- if (!buffer)
- die("cannot read %s", sha1_to_hex(sha1));
crc = crc32(crc, buffer, size);
out = buffer;
uncompressed_size = size;
compressed_size = size;
} else {
- error("unsupported file mode: 0%o (SHA1: %s)", mode,
- sha1_to_hex(sha1));
- goto out;
+ return error("unsupported file mode: 0%o (SHA1: %s)", mode,
+ sha1_to_hex(sha1));
}
if (method == 8) {
@@ -278,12 +232,9 @@ static int write_zip_entry(const unsigned char *sha1, const char *base,
zip_offset += compressed_size;
}
-out:
- free(buffer);
free(deflated);
- free(path);
- return result;
+ return 0;
}
static void write_zip_trailer(const unsigned char *sha1)
@@ -316,31 +267,20 @@ static void dos_time(time_t *time, int *dos_date, int *dos_time)
int write_zip_archive(struct archiver_args *args)
{
+ int err;
+
dos_time(&args->time, &zip_date, &zip_time);
zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
- verbose = args->verbose;
- commit = args->commit;
- base_len = args->baselen;
-
- if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
- char *base = xstrdup(args->base);
- int baselen = strlen(base);
-
- while (baselen > 0 && base[baselen - 1] == '/')
- base[--baselen] = '\0';
- write_zip_entry(args->tree->object.sha1, "", 0, base, 040777,
- 0, NULL);
- free(base);
- }
- read_tree_recursive(args->tree, args->base, args->baselen, 0,
- args->pathspec, write_zip_entry, NULL);
- write_zip_trailer(args->commit_sha1);
+
+ err = write_archive_entries(args, write_zip_entry);
+ if (!err)
+ write_zip_trailer(args->commit_sha1);
free(zip_dir);
- return 0;
+ return err;
}
void *parse_extra_zip_args(int argc, const char **argv)
--
1.5.6.2.212.g08b51
^ permalink raw reply related
* [PATCH 2/6] add context pointer to read_tree_recursive()
From: René Scharfe @ 2008-07-14 19:22 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <487B92FC.5030103@lsrfire.ath.cx>
Add a pointer parameter to read_tree_recursive(), which is passed to the
callback function. This allows callers of read_tree_recursive() to
share data with the callback without resorting to global variables. All
current callers pass NULL.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
archive-tar.c | 11 ++++++-----
archive-zip.c | 11 ++++++-----
builtin-checkout.c | 4 ++--
builtin-log.c | 4 ++--
builtin-ls-tree.c | 4 ++--
builtin-merge-recursive.c | 4 ++--
tree.c | 12 ++++++------
tree.h | 4 ++--
8 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/archive-tar.c b/archive-tar.c
index 99db58f..6eaf59e 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -234,9 +234,9 @@ static int git_tar_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
-static int write_tar_entry(const unsigned char *sha1,
- const char *base, int baselen,
- const char *filename, unsigned mode, int stage)
+static int write_tar_entry(const unsigned char *sha1, const char *base,
+ int baselen, const char *filename, unsigned mode, int stage,
+ void *context)
{
static struct strbuf path = STRBUF_INIT;
void *buffer;
@@ -286,11 +286,12 @@ int write_tar_archive(struct archiver_args *args)
while (baselen > 0 && base[baselen - 1] == '/')
base[--baselen] = '\0';
- write_tar_entry(args->tree->object.sha1, "", 0, base, 040777, 0);
+ write_tar_entry(args->tree->object.sha1, "", 0, base, 040777,
+ 0, NULL);
free(base);
}
read_tree_recursive(args->tree, args->base, plen, 0,
- args->pathspec, write_tar_entry);
+ args->pathspec, write_tar_entry, NULL);
write_trailer();
return 0;
diff --git a/archive-zip.c b/archive-zip.c
index 5742762..0d24f3f 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -152,9 +152,9 @@ static char *construct_path(const char *base, int baselen,
return path;
}
-static int write_zip_entry(const unsigned char *sha1,
- const char *base, int baselen,
- const char *filename, unsigned mode, int stage)
+static int write_zip_entry(const unsigned char *sha1, const char *base,
+ int baselen, const char *filename, unsigned mode, int stage,
+ void *context)
{
struct zip_local_header header;
struct zip_dir_header dirent;
@@ -332,11 +332,12 @@ int write_zip_archive(struct archiver_args *args)
while (baselen > 0 && base[baselen - 1] == '/')
base[--baselen] = '\0';
- write_zip_entry(args->tree->object.sha1, "", 0, base, 040777, 0);
+ write_zip_entry(args->tree->object.sha1, "", 0, base, 040777,
+ 0, NULL);
free(base);
}
read_tree_recursive(args->tree, args->base, plen, 0,
- args->pathspec, write_zip_entry);
+ args->pathspec, write_zip_entry, NULL);
write_zip_trailer(args->commit_sha1);
free(zip_dir);
diff --git a/builtin-checkout.c b/builtin-checkout.c
index d6641c2..a542033 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -43,7 +43,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
}
static int update_some(const unsigned char *sha1, const char *base, int baselen,
- const char *pathname, unsigned mode, int stage)
+ const char *pathname, unsigned mode, int stage, void * context)
{
int len;
struct cache_entry *ce;
@@ -67,7 +67,7 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
static int read_tree_some(struct tree *tree, const char **pathspec)
{
- read_tree_recursive(tree, "", 0, 0, pathspec, update_some);
+ read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL);
/* update the index with the given tree's info
* for all args, expanding wildcards, and exit
diff --git a/builtin-log.c b/builtin-log.c
index 430d876..617aa67 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -313,7 +313,7 @@ static int show_object(const unsigned char *sha1, int show_tag_object,
static int show_tree_object(const unsigned char *sha1,
const char *base, int baselen,
- const char *pathname, unsigned mode, int stage)
+ const char *pathname, unsigned mode, int stage, void *context)
{
printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
return 0;
@@ -366,7 +366,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
name,
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
- show_tree_object);
+ show_tree_object, NULL);
break;
case OBJ_COMMIT:
rev.pending.nr = rev.pending.alloc = 0;
diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c
index f4a75dd..0da047c 100644
--- a/builtin-ls-tree.c
+++ b/builtin-ls-tree.c
@@ -56,7 +56,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
}
static int show_tree(const unsigned char *sha1, const char *base, int baselen,
- const char *pathname, unsigned mode, int stage)
+ const char *pathname, unsigned mode, int stage, void *context)
{
int retval = 0;
const char *type = blob_type;
@@ -189,7 +189,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
tree = parse_tree_indirect(sha1);
if (!tree)
die("not a tree object");
- read_tree_recursive(tree, "", 0, 0, pathspec, show_tree);
+ read_tree_recursive(tree, "", 0, 0, pathspec, show_tree, NULL);
return 0;
}
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
index 43bf6aa..385e742 100644
--- a/builtin-merge-recursive.c
+++ b/builtin-merge-recursive.c
@@ -256,7 +256,7 @@ struct tree *write_tree_from_memory(void)
static int save_files_dirs(const unsigned char *sha1,
const char *base, int baselen, const char *path,
- unsigned int mode, int stage)
+ unsigned int mode, int stage, void *context)
{
int len = strlen(path);
char *newpath = xmalloc(baselen + len + 1);
@@ -276,7 +276,7 @@ static int save_files_dirs(const unsigned char *sha1,
static int get_files_dirs(struct tree *tree)
{
int n;
- if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs) != 0)
+ if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, NULL))
return 0;
n = current_file_set.nr + current_directory_set.nr;
return n;
diff --git a/tree.c b/tree.c
index 4b1825c..03e782a 100644
--- a/tree.c
+++ b/tree.c
@@ -29,7 +29,7 @@ static int read_one_entry_opt(const unsigned char *sha1, const char *base, int b
return add_cache_entry(ce, opt);
}
-static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
+static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)
{
return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,
ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
@@ -39,7 +39,7 @@ static int read_one_entry(const unsigned char *sha1, const char *base, int basel
* This is used when the caller knows there is no existing entries at
* the stage that will conflict with the entry being added.
*/
-static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
+static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)
{
return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,
ADD_CACHE_JUST_APPEND);
@@ -92,7 +92,7 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns
int read_tree_recursive(struct tree *tree,
const char *base, int baselen,
int stage, const char **match,
- read_tree_fn_t fn)
+ read_tree_fn_t fn, void *context)
{
struct tree_desc desc;
struct name_entry entry;
@@ -106,7 +106,7 @@ int read_tree_recursive(struct tree *tree,
if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
continue;
- switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage)) {
+ switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) {
case 0:
continue;
case READ_TREE_RECURSIVE:
@@ -126,7 +126,7 @@ int read_tree_recursive(struct tree *tree,
retval = read_tree_recursive(lookup_tree(entry.sha1),
newbase,
baselen + pathlen + 1,
- stage, match, fn);
+ stage, match, fn, context);
free(newbase);
if (retval)
return -1;
@@ -174,7 +174,7 @@ int read_tree(struct tree *tree, int stage, const char **match)
if (!fn)
fn = read_one_entry_quick;
- err = read_tree_recursive(tree, "", 0, stage, match, fn);
+ err = read_tree_recursive(tree, "", 0, stage, match, fn, NULL);
if (fn == read_one_entry || err)
return err;
diff --git a/tree.h b/tree.h
index dd25c53..2ff01a4 100644
--- a/tree.h
+++ b/tree.h
@@ -21,12 +21,12 @@ int parse_tree(struct tree *tree);
struct tree *parse_tree_indirect(const unsigned char *sha1);
#define READ_TREE_RECURSIVE 1
-typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int);
+typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int, void *);
extern int read_tree_recursive(struct tree *tree,
const char *base, int baselen,
int stage, const char **match,
- read_tree_fn_t fn);
+ read_tree_fn_t fn, void *context);
extern int read_tree(struct tree *tree, int stage, const char **paths);
--
1.5.6.2.212.g08b51
^ permalink raw reply related
* [PATCH 1/6] archive: remove args member from struct archiver
From: René Scharfe @ 2008-07-14 19:23 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <487B8E81.5030402@lsrfire.ath.cx>
Pass struct archiver and struct archiver_args explicitly to
parse_archive_args
and remove the latter from the former. This allows us to get rid of struct
archiver_desc and simplifies the code a bit.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
archive.h | 5 +---
builtin-archive.c | 51
+++++++++++++++++++---------------------------
builtin-upload-archive.c | 11 +++++----
3 files changed, 28 insertions(+), 39 deletions(-)
diff --git a/archive.h b/archive.h
index ddf004a..1b24ae3 100644
--- a/archive.h
+++ b/archive.h
@@ -21,14 +21,11 @@ typedef void *(*parse_extra_args_fn_t)(int argc,
const char **argv);
struct archiver {
const char *name;
- struct archiver_args args;
write_archive_fn_t write_archive;
parse_extra_args_fn_t parse_extra;
};
-extern int parse_archive_args(int argc,
- const char **argv,
- struct archiver *ar);
+extern int parse_archive_args(int argc, const char **argv, const struct
archiver **ar, struct archiver_args *args);
extern void parse_treeish_arg(const char **treeish,
struct archiver_args *ar_args,
diff --git a/builtin-archive.c b/builtin-archive.c
index c2e0c1e..6ee3677 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -15,12 +15,7 @@
static const char archive_usage[] = \
"git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>]
<tree-ish> [path...]";
-static struct archiver_desc
-{
- const char *name;
- write_archive_fn_t write_archive;
- parse_extra_args_fn_t parse_extra;
-} archivers[] = {
+const struct archiver archivers[] = {
{ "tar", write_tar_archive, NULL },
{ "zip", write_zip_archive, parse_extra_zip_args },
};
@@ -79,21 +74,15 @@ static int run_remote_archiver(const char *remote,
int argc,
return !!rv;
}
-static int init_archiver(const char *name, struct archiver *ar)
+static const struct archiver *lookup_archiver(const char *name)
{
- int rv = -1, i;
+ int i;
for (i = 0; i < ARRAY_SIZE(archivers); i++) {
- if (!strcmp(name, archivers[i].name)) {
- memset(ar, 0, sizeof(*ar));
- ar->name = archivers[i].name;
- ar->write_archive = archivers[i].write_archive;
- ar->parse_extra = archivers[i].parse_extra;
- rv = 0;
- break;
- }
+ if (!strcmp(name, archivers[i].name))
+ return &archivers[i];
}
- return rv;
+ return NULL;
}
void parse_pathspec_arg(const char **pathspec, struct archiver_args
*ar_args)
@@ -145,7 +134,8 @@ void parse_treeish_arg(const char **argv, struct
archiver_args *ar_args,
ar_args->time = archive_time;
}
-int parse_archive_args(int argc, const char **argv, struct archiver *ar)
+int parse_archive_args(int argc, const char **argv, const struct
archiver **ar,
+ struct archiver_args *args)
{
const char *extra_argv[MAX_EXTRA_ARGS];
int extra_argc = 0;
@@ -190,17 +180,18 @@ int parse_archive_args(int argc, const char
**argv, struct archiver *ar)
/* We need at least one parameter -- tree-ish */
if (argc - 1 < i)
usage(archive_usage);
- if (init_archiver(format, ar) < 0)
+ *ar = lookup_archiver(format);
+ if (!*ar)
die("Unknown archive format '%s'", format);
if (extra_argc) {
- if (!ar->parse_extra)
+ if (!(*ar)->parse_extra)
die("'%s' format does not handle %s",
- ar->name, extra_argv[0]);
- ar->args.extra = ar->parse_extra(extra_argc, extra_argv);
+ (*ar)->name, extra_argv[0]);
+ args->extra = (*ar)->parse_extra(extra_argc, extra_argv);
}
- ar->args.verbose = verbose;
- ar->args.base = base;
+ args->verbose = verbose;
+ args->base = base;
return i;
}
@@ -238,7 +229,8 @@ static const char *extract_remote_arg(int *ac, const
char **av)
int cmd_archive(int argc, const char **argv, const char *prefix)
{
- struct archiver ar;
+ const struct archiver *ar = NULL;
+ struct archiver_args args;
int tree_idx;
const char *remote = NULL;
@@ -248,14 +240,13 @@ int cmd_archive(int argc, const char **argv, const
char *prefix)
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
- memset(&ar, 0, sizeof(ar));
- tree_idx = parse_archive_args(argc, argv, &ar);
+ tree_idx = parse_archive_args(argc, argv, &ar, &args);
if (prefix == NULL)
prefix = setup_git_directory();
argv += tree_idx;
- parse_treeish_arg(argv, &ar.args, prefix);
- parse_pathspec_arg(argv + 1, &ar.args);
+ parse_treeish_arg(argv, &args, prefix);
+ parse_pathspec_arg(argv + 1, &args);
- return ar.write_archive(&ar.args);
+ return ar->write_archive(&args);
}
diff --git a/builtin-upload-archive.c b/builtin-upload-archive.c
index 371400d..295e24c 100644
--- a/builtin-upload-archive.c
+++ b/builtin-upload-archive.c
@@ -19,7 +19,8 @@ static const char lostchild[] =
static int run_upload_archive(int argc, const char **argv, const char
*prefix)
{
- struct archiver ar;
+ const struct archiver *ar;
+ struct archiver_args args;
const char *sent_argv[MAX_ARGS];
const char *arg_cmd = "argument ";
char *p, buf[4096];
@@ -65,12 +66,12 @@ static int run_upload_archive(int argc, const char
**argv, const char *prefix)
sent_argv[sent_argc] = NULL;
/* parse all options sent by the client */
- treeish_idx = parse_archive_args(sent_argc, sent_argv, &ar);
+ treeish_idx = parse_archive_args(sent_argc, sent_argv, &ar, &args);
- parse_treeish_arg(sent_argv + treeish_idx, &ar.args, prefix);
- parse_pathspec_arg(sent_argv + treeish_idx + 1, &ar.args);
+ parse_treeish_arg(sent_argv + treeish_idx, &args, prefix);
+ parse_pathspec_arg(sent_argv + treeish_idx + 1, &args);
- return ar.write_archive(&ar.args);
+ return ar->write_archive(&args);
}
static void error_clnt(const char *fmt, ...)
--
1.5.6.2.212.g08b51
^ permalink raw reply related
* [PATCH 3/6] archive: add baselen member to struct archiver_args
From: René Scharfe @ 2008-07-14 19:23 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <487B92FC.5030103@lsrfire.ath.cx>
Calculate the length of base and save it in a new member of struct
archiver_args. This way we don't have to compute it in each of the
format backends.
Note: parse_archive_args() guarantees that ->base won't ever be NULL.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
archive-tar.c | 8 +++-----
archive-zip.c | 8 +++-----
archive.h | 1 +
builtin-archive.c | 1 +
4 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/archive-tar.c b/archive-tar.c
index 6eaf59e..63cc2ec 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -268,19 +268,17 @@ static int write_tar_entry(const unsigned char
*sha1, const char *base,
int write_tar_archive(struct archiver_args *args)
{
- int plen = args->base ? strlen(args->base) : 0;
-
git_config(git_tar_config, NULL);
archive_time = args->time;
verbose = args->verbose;
commit = args->commit;
- base_len = args->base ? strlen(args->base) : 0;
+ base_len = args->baselen;
if (args->commit_sha1)
write_global_extended_header(args->commit_sha1);
- if (args->base && plen > 0 && args->base[plen - 1] == '/') {
+ if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
char *base = xstrdup(args->base);
int baselen = strlen(base);
@@ -290,7 +288,7 @@ int write_tar_archive(struct archiver_args *args)
0, NULL);
free(base);
}
- read_tree_recursive(args->tree, args->base, plen, 0,
+ read_tree_recursive(args->tree, args->base, args->baselen, 0,
args->pathspec, write_tar_entry, NULL);
write_trailer();
diff --git a/archive-zip.c b/archive-zip.c
index 0d24f3f..d18254c 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -316,17 +316,15 @@ static void dos_time(time_t *time, int *dos_date,
int *dos_time)
int write_zip_archive(struct archiver_args *args)
{
- int plen = strlen(args->base);
-
dos_time(&args->time, &zip_date, &zip_time);
zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
verbose = args->verbose;
commit = args->commit;
- base_len = args->base ? strlen(args->base) : 0;
+ base_len = args->baselen;
- if (args->base && plen > 0 && args->base[plen - 1] == '/') {
+ if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
char *base = xstrdup(args->base);
int baselen = strlen(base);
@@ -336,7 +334,7 @@ int write_zip_archive(struct archiver_args *args)
0, NULL);
free(base);
}
- read_tree_recursive(args->tree, args->base, plen, 0,
+ read_tree_recursive(args->tree, args->base, args->baselen, 0,
args->pathspec, write_zip_entry, NULL);
write_zip_trailer(args->commit_sha1);
diff --git a/archive.h b/archive.h
index 1b24ae3..34151f4 100644
--- a/archive.h
+++ b/archive.h
@@ -6,6 +6,7 @@
struct archiver_args {
const char *base;
+ size_t baselen;
struct tree *tree;
const unsigned char *commit_sha1;
const struct commit *commit;
diff --git a/builtin-archive.c b/builtin-archive.c
index 6ee3677..e7f4ec6 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -192,6 +192,7 @@ int parse_archive_args(int argc, const char **argv,
const struct archiver **ar,
}
args->verbose = verbose;
args->base = base;
+ args->baselen = strlen(base);
return i;
}
--
1.5.6.2.212.g08b51
^ permalink raw reply related
* [PATCH 0/6] archive: refactor and cleanup
From: René Scharfe @ 2008-07-14 19:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
This series is a collection of cleanups for git archive that I finally need
to get out, reviewed and (hopefully!) integrated. It should make adding
more format backends easier.
Patch 2 adds a context parameter to read_tree_recursive(), thus affecting
all its callers. The rest of the patches change *archive*.[ch], only.
René
archive-tar.c | 115 ++++++++++++---------------------------
archive-zip.c | 102 +++++------------------------------
archive.c | 132 ++++++++++++++++++++++++++++++++------------
archive.h | 15 ++----
builtin-archive.c | 75 ++++++++++++--------------
builtin-checkout.c | 4 +-
builtin-log.c | 4 +-
builtin-ls-tree.c | 4 +-
builtin-merge-recursive.c | 4 +-
builtin-upload-archive.c | 11 ++--
tree.c | 12 ++--
tree.h | 4 +-
12 files changed, 208 insertions(+), 274 deletions(-)
^ permalink raw reply
* [PATCH 6/6] archive: remove extra arguments parsing code
From: René Scharfe @ 2008-07-14 19:22 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <487B92FC.5030103@lsrfire.ath.cx>
Replace the code that calls backend specific argument parsers by a
simple flag mechanism. This reduces code size and complexity.
We can add back such a mechanism (based on incremental parse_opt(),
perhaps) when we need it. The compression level parameter, though,
is going to be shared by future compressing backends like tgz.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
archive-zip.c | 13 -------------
archive.h | 6 +-----
builtin-archive.c | 29 ++++++++++++++++-------------
3 files changed, 17 insertions(+), 31 deletions(-)
diff --git a/archive-zip.c b/archive-zip.c
index 8131289..d56e5cf 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -282,16 +282,3 @@ int write_zip_archive(struct archiver_args *args)
return err;
}
-
-void *parse_extra_zip_args(int argc, const char **argv)
-{
- for (; argc > 0; argc--, argv++) {
- const char *arg = argv[0];
-
- if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0')
- zlib_compression_level = arg[1] - '0';
- else
- die("Unknown argument for zip format: %s", arg);
- }
- return NULL;
-}
diff --git a/archive.h b/archive.h
index 88ee3be..96bb1cd 100644
--- a/archive.h
+++ b/archive.h
@@ -13,19 +13,16 @@ struct archiver_args {
time_t time;
const char **pathspec;
unsigned int verbose : 1;
- void *extra;
};
typedef int (*write_archive_fn_t)(struct archiver_args *);
-typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv);
-
typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, void *buffer, unsigned long size);
struct archiver {
const char *name;
write_archive_fn_t write_archive;
- parse_extra_args_fn_t parse_extra;
+ unsigned int flags;
};
extern int parse_archive_args(int argc, const char **argv, const struct archiver **ar, struct archiver_args *args);
@@ -41,7 +38,6 @@ extern void parse_pathspec_arg(const char **pathspec,
*/
extern int write_tar_archive(struct archiver_args *);
extern int write_zip_archive(struct archiver_args *);
-extern void *parse_extra_zip_args(int argc, const char **argv);
extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
diff --git a/builtin-archive.c b/builtin-archive.c
index e7f4ec6..88204bf 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -15,9 +15,11 @@
static const char archive_usage[] = \
"git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
+#define USES_ZLIB_COMPRESSION 1
+
const struct archiver archivers[] = {
- { "tar", write_tar_archive, NULL },
- { "zip", write_zip_archive, parse_extra_zip_args },
+ { "tar", write_tar_archive },
+ { "zip", write_zip_archive, USES_ZLIB_COMPRESSION },
};
static int run_remote_archiver(const char *remote, int argc,
@@ -137,10 +139,9 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
int parse_archive_args(int argc, const char **argv, const struct archiver **ar,
struct archiver_args *args)
{
- const char *extra_argv[MAX_EXTRA_ARGS];
- int extra_argc = 0;
const char *format = "tar";
const char *base = "";
+ int compression_level = -1;
int verbose = 0;
int i;
@@ -168,12 +169,12 @@ int parse_archive_args(int argc, const char **argv, const struct archiver **ar,
i++;
break;
}
- if (arg[0] == '-') {
- if (extra_argc > MAX_EXTRA_ARGS - 1)
- die("Too many extra options");
- extra_argv[extra_argc++] = arg;
+ if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0') {
+ compression_level = arg[1] - '0';
continue;
}
+ if (arg[0] == '-')
+ die("Unknown argument: %s", arg);
break;
}
@@ -184,11 +185,13 @@ int parse_archive_args(int argc, const char **argv, const struct archiver **ar,
if (!*ar)
die("Unknown archive format '%s'", format);
- if (extra_argc) {
- if (!(*ar)->parse_extra)
- die("'%s' format does not handle %s",
- (*ar)->name, extra_argv[0]);
- args->extra = (*ar)->parse_extra(extra_argc, extra_argv);
+ if (compression_level != -1) {
+ if ((*ar)->flags & USES_ZLIB_COMPRESSION)
+ zlib_compression_level = compression_level;
+ else {
+ die("Argument not supported for format '%s': -%d",
+ format, compression_level);
+ }
}
args->verbose = verbose;
args->base = base;
--
1.5.6.2.212.g08b51
^ permalink raw reply related
* [PATCH 5/6] archive: unify file attribute handling
From: René Scharfe @ 2008-07-14 19:22 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <487B92FC.5030103@lsrfire.ath.cx>
Now that all file attribute handling for git archive has moved to archive.c,
we can unexport sha1_file_to_archive() and is_archive_path_ignored() even
disappears.
Add setup_archive_check(), modelled after similar functions used in the code
of other commands that support multiple file attributes.
Also remove convert_to_archive(), as it's only remaining function with
attribute handling gone was to call format_subst() if commit was not NULL,
which is now checked in sha1_file_to_archive().
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
archive.c | 63 ++++++++++++++++++++++--------------------------------------
archive.h | 3 --
2 files changed, 23 insertions(+), 43 deletions(-)
diff --git a/archive.c b/archive.c
index 58de55e..b8b45ba 100644
--- a/archive.c
+++ b/archive.c
@@ -36,34 +36,9 @@ static void format_subst(const struct commit *commit,
free(to_free);
}
-static int convert_to_archive(const char *path,
- const void *src, size_t len,
- struct strbuf *buf,
- const struct commit *commit)
-{
- static struct git_attr *attr_export_subst;
- struct git_attr_check check[1];
-
- if (!commit)
- return 0;
-
- if (!attr_export_subst)
- attr_export_subst = git_attr("export-subst", 12);
-
- check[0].attr = attr_export_subst;
- if (git_checkattr(path, ARRAY_SIZE(check), check))
- return 0;
- if (!ATTR_TRUE(check[0].value))
- return 0;
-
- format_subst(commit, src, len, buf);
- return 1;
-}
-
-void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
- unsigned int mode, enum object_type *type,
- unsigned long *sizep,
- const struct commit *commit)
+static void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
+ unsigned int mode, enum object_type *type,
+ unsigned long *sizep, const struct commit *commit)
{
void *buffer;
@@ -75,7 +50,8 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
strbuf_init(&buf, 0);
strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
convert_to_working_tree(path, buf.buf, buf.len, &buf);
- convert_to_archive(path, buf.buf, buf.len, &buf, commit);
+ if (commit)
+ format_subst(commit, buf.buf, buf.len, &buf);
buffer = strbuf_detach(&buf, &size);
*sizep = size;
}
@@ -83,18 +59,17 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
return buffer;
}
-int is_archive_path_ignored(const char *path)
+static void setup_archive_check(struct git_attr_check *check)
{
static struct git_attr *attr_export_ignore;
- struct git_attr_check check[1];
+ static struct git_attr *attr_export_subst;
- if (!attr_export_ignore)
+ if (!attr_export_ignore) {
attr_export_ignore = git_attr("export-ignore", 13);
-
+ attr_export_subst = git_attr("export-subst", 12);
+ }
check[0].attr = attr_export_ignore;
- if (git_checkattr(path, ARRAY_SIZE(check), check))
- return 0;
- return ATTR_TRUE(check[0].value);
+ check[1].attr = attr_export_subst;
}
struct archiver_context {
@@ -110,6 +85,9 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
struct archiver_context *c = context;
struct archiver_args *args = c->args;
write_archive_entry_fn_t write_entry = c->write_entry;
+ struct git_attr_check check[2];
+ const char *path_without_prefix;
+ int convert = 0;
int err;
enum object_type type;
unsigned long size;
@@ -119,9 +97,14 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
strbuf_grow(&path, PATH_MAX);
strbuf_add(&path, base, baselen);
strbuf_addstr(&path, filename);
+ path_without_prefix = path.buf + args->baselen;
- if (is_archive_path_ignored(path.buf + args->baselen))
- return 0;
+ setup_archive_check(check);
+ if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) {
+ if (ATTR_TRUE(check[0].value))
+ return 0;
+ convert = ATTR_TRUE(check[1].value);
+ }
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
strbuf_addch(&path, '/');
@@ -133,8 +116,8 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
return READ_TREE_RECURSIVE;
}
- buffer = sha1_file_to_archive(path.buf + args->baselen, sha1, mode,
- &type, &size, args->commit);
+ buffer = sha1_file_to_archive(path_without_prefix, sha1, mode,
+ &type, &size, convert ? args->commit : NULL);
if (!buffer)
return error("cannot read %s", sha1_to_hex(sha1));
if (args->verbose)
diff --git a/archive.h b/archive.h
index 4e44549..88ee3be 100644
--- a/archive.h
+++ b/archive.h
@@ -43,9 +43,6 @@ extern int write_tar_archive(struct archiver_args *);
extern int write_zip_archive(struct archiver_args *);
extern void *parse_extra_zip_args(int argc, const char **argv);
-extern void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size, const struct commit *commit);
-extern int is_archive_path_ignored(const char *path);
-
extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
#endif /* ARCHIVE_H */
--
1.5.6.2.212.g08b51
^ permalink raw reply related
* Re: Syncing up to a tree with a numeric EXTRAVERSION
From: Miklos Vajna @ 2008-07-14 19:29 UTC (permalink / raw)
To: vb; +Cc: git
In-Reply-To: <f608b67d0807141224v258172a7pfe655a0ceb0f8efd@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 373 bytes --]
On Mon, Jul 14, 2008 at 12:24:33PM -0700, vb <vb@vsbe.com> wrote:
> VERSION = 2
> PATCHLEVEL = 6
> SUBLEVEL = 19
> EXTRAVERSION = .2
> NAME=Avast! A bilge rat!
>
> (...)
>
> so, the question is where do I find the tree with the Makefile
> EXTRAVERSION set to .2?
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.19.y.git ?
Hope this helps.
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Syncing up to a tree with a numeric EXTRAVERSION
From: vb @ 2008-07-14 19:24 UTC (permalink / raw)
To: git
I have vendor provided linux tree which includes some vendor specific
code. The tree's top level Makefile has this header:
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 19
EXTRAVERSION = .2
NAME=Avast! A bilge rat!
so, this is what I want to pull from the repository to see what's
different. The thing is that when I go to the Makefile history in the
master git repository
(http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=history;f=Makefile;h=e3c5eb66ec52dee13127e3b2b83f84c3184bd8be;hb=bce7f793daec3e65ec5c5705d2457b81fe7b5725;pg=1)
I don't see a tag for this version, all which is there between 19-rc6
and 20-rc1 are
2006-12-14 Linus Torvalds Linux v2.6.20-rc1 v2.6.20-rc1
2006-12-13 Jeff Dike [PATCH] Fix crossbuilding checkstack
2006-12-12 Samuel Tardieu Use consistent casing in help message
2006-12-10 Oleg Verych [PATCH] kbuild: fix-rR-is-now-default
2006-11-29 Linus Torvalds Linux 2.6.19 v2.6.19
2006-11-16 Linus Torvalds Linux 2.6.19-rc6 v2.6.19-rc6
so, the question is where do I find the tree with the Makefile
EXTRAVERSION set to .2?
TIA,
vadim
^ permalink raw reply
* Re: Closing the merge window for 1.6.0
From: Teemu Likonen @ 2008-07-14 19:19 UTC (permalink / raw)
To: Junio C Hamano
Cc: Nicolas Pitre, Gerrit Pape, Johannes Schindelin, Petr Baudis, git
In-Reply-To: <7v3amcgujd.fsf@gitster.siamese.dyndns.org>
Junio C Hamano wrote (2008-07-14 12:00 -0700):
> Nicolas Pitre <nico@cam.org> writes:
>
> > On Mon, 14 Jul 2008, Gerrit Pape wrote:
> >> > On Mon, 14 Jul 2008, Petr Baudis wrote:
> >> > > I'm saying this because I believe the best conservative upper
> >> > > bound for backwards compatibility is Git version in Debian
> >> > > stable. It gets
> > Please consider it as a critical usability problem.
> >
> > Maybe we can release 1.4.5 with the ability to read index v2? That
> > wouldn't be hard to backport the reading part of it.
> I am of two minds here.
>
> On one hand, I am sympathetic to distros that want to give long time
> support for ancient versions to keep working in an ever-changing new
> world. It is a wonderful thing that there are distros that aim for
> ultra conservative stability, and I applaud them.
>
> But as the upstream, we have our own deprecation schedule.
As Debian stable (4.0 "Etch") and its git 1.4.4.4 was mentioned I'd like
to point out that git 1.5.6 is available for Etch users from
kind-of-semi-official <www.backports.org>. So I guess Debian stable
users aren't left completely behind. Git's web page already advertises
backports.org version for Etch.
^ permalink raw reply
* Re: Closing the merge window for 1.6.0
From: Junio C Hamano @ 2008-07-14 19:16 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
In-Reply-To: <20080714085555.GJ32184@machine.or.cz>
Petr Baudis <pasky@suse.cz> writes:
> Getting alternates list for http://repo.or.cz/r/repo.git/
> Getting pack list for http://repo.or.cz/r/repo.git/
> Getting index for pack 5111285cac0f895cd9367c9939ced68e2c43dcc0
> error: non-monotonic index
> /usr/bin/git-fetch: line 297: 30402 Segmentation fault git-http-fetch -v -a "$head" "$remote/"
Yeah, I think git-repack, git-gc, git-pack-objects and git-index-pack on
the server side need a knob to tell it to stay conservative because the
repository may be served over dumb protocols to avoid this problem.
That knob could even be called
[repack]
usedeltabaseoffset = false
[pack]
indexversion = 1
^ permalink raw reply
* Re: [PATCH] Fix relative built-in paths to be relative to the command invocation
From: Junio C Hamano @ 2008-07-14 19:03 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Johannes Schindelin, git, Steffen Prohaska
In-Reply-To: <200807142054.35027.johannes.sixt@telecom.at>
Johannes Sixt <johannes.sixt@telecom.at> writes:
> On Montag, 14. Juli 2008, Johannes Schindelin wrote:
>> Hi,
>>
>> On Mon, 14 Jul 2008, Johannes Sixt wrote:
>> > Zitat von Johannes Schindelin <Johannes.Schindelin@gmx.de>:
>> > > On Sun, 13 Jul 2008, Johannes Sixt wrote:
>> > > > @@ -84,7 +90,7 @@ static void add_path(struct strbuf *out, const char
>> > > > *path)
>> > > > }
>> > > > }
>> > > >
>> > > > -void setup_path(const char *cmd_path)
>> > > > +void setup_path(void)
>> > >
>> > > It seems to me that this patch would not do anything different, but
>> > > with less code change, if setup_path() would set argv0_path, and not a
>> > > new function was introduced.
>> >
>> > This is just to play a safe game. I had it that way, but I decided to
>> > have the call to the new git_set_argv0_path() early in git.c because the
>> > call to setup_path() in git.c is very late, and it could happen that we
>> > call system_path() (which needs argv0_path) before that. Although I
>> > didn't audit the code whether this really happens.
>>
>> Well, okay... I would have rather seen it not change (since there was no
>> bug to fix), or as a separate patch, but it's Junio's call.
>
> I investigated this, and, yes, there indeed are calls to system_path() before
> setup_path(), for example:
>
> commit_pager_choice
> setup_pager
> git_config
> git_etc_gitconfig
> system_path(ETC_GITCONFIG)
>
> Junio, do you want git_set_argv0_path() in a separate patch?
I think that would be easier to explain in the commit log what is going
on, if it is a separate patch.
^ permalink raw reply
* Re: Closing the merge window for 1.6.0
From: Junio C Hamano @ 2008-07-14 19:00 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Gerrit Pape, Johannes Schindelin, Petr Baudis, git
In-Reply-To: <alpine.LFD.1.10.0807141351540.12484@xanadu.home>
Nicolas Pitre <nico@cam.org> writes:
> On Mon, 14 Jul 2008, Gerrit Pape wrote:
>
>> On Mon, Jul 14, 2008 at 12:57:56PM +0100, Johannes Schindelin wrote:
>> > On Mon, 14 Jul 2008, Petr Baudis wrote:
>> > > I'm saying this because I believe the best conservative upper bound for
>> > > backwards compatibility is Git version in Debian stable. It gets
>> > > probably the most stale from all the widely used software distributions
>> > > using Git, and it *is* quite widely used. Etch carries v1.4.4.4, which
>> > > fails miserably on the new packs.
>> >
>> > Can't we just hit Debian's Git maintainer with a clue bat or a bus,
>>
>> Please don't. It wouldn't help, rather the opposite I think, espacially
>> the bus. We don't introduce new upstream versions into a Debian stable
>> release, there's a great effort done for each stable release to reach
>> high quality integration of all the software packages available in
>> Debian. Once that status is reached, only security fixes and criticial
>> usability fixes are added.
>
> Please consider it as a critical usability problem.
>
> Maybe we can release 1.4.5 with the ability to read index v2? That
> wouldn't be hard to backport the reading part of it.
I am of two minds here.
On one hand, I am sympathetic to distros that want to give long time
support for ancient versions to keep working in an ever-changing new
world. It is a wonderful thing that there are distros that aim for ultra
conservative stability, and I applaud them.
But as the upstream, we have our own deprecation schedule. We should of
course plan carefully not to harm existing users of our releases, but
frankly speaking, 18 months since 1.4.4.4 was tagged (early January 2007)
is an eternity in git timescale. Maybe we will slow down someday, and
this 18-month is not a set-in-stone rule in any way, but at this point
even without the packfile format issues, I personally think anything
before 1.5.0 is irrelevant --- maybe they are interesting as historical
curiosities, but not more than that.
We could:
$ git checkout -b maint-1.4 v1.4.4.4
$ git merge maint
$ git tag v1.4.4.5
and push the result out. While I would imagine that the end-user
experience after such a maintenance release would be very positive, that
is not something distros who really want to stay with a stale version for
a good reason would want to swallow ;-).
If we _were_ to keep v1.4.4.X series alive, serious backporting efforts
will be necessary. For example, recent 'git-shell' futureproofing was
made not just to 1.5.6.X series but was backported to 1.5.4.X and 1.5.5.X,
and we would probably need to give it to 1.4.4.X as well. What other
things are there that are missing in 1.4.4.X? It would take nontrivial
engineering resource to even list them, let alone assessing how much
effort is required for such backporting and actually doing it.
The remotes/ layout, use of "git-add" for new contents (instead of only
new files), reflogs, detached HEAD, --pretty=format:%<blah>, bundles,
mergetool,... all the things that a modern git workflow revolves around
and are described in the user manuals the users find on the net are not
found in 1.4.4.X series. If a user of such a conservative distro needs to
work with a repository prepared on another platform with newer git,
perhaps crossmounted, should we backport "git branch -r" so that the user
can confortably work with remote tracking branches? Should we backport
reflogs?
If a distro chooses to support its users whom they force to pin at 1.4.4.X
series, it's primarily _their_ choice. I do not mind helping them in such
a backport, but the request has to come from the distro first with a
specific list of items that need to be supported.
^ permalink raw reply
* Re: [PATCH] Fix relative built-in paths to be relative to the command invocation
From: Johannes Sixt @ 2008-07-14 18:54 UTC (permalink / raw)
To: Johannes Schindelin, Junio C Hamano; +Cc: git, Steffen Prohaska
In-Reply-To: <alpine.DEB.1.00.0807141319420.8950@racer>
On Montag, 14. Juli 2008, Johannes Schindelin wrote:
> Hi,
>
> On Mon, 14 Jul 2008, Johannes Sixt wrote:
> > Zitat von Johannes Schindelin <Johannes.Schindelin@gmx.de>:
> > > On Sun, 13 Jul 2008, Johannes Sixt wrote:
> > > > @@ -84,7 +90,7 @@ static void add_path(struct strbuf *out, const char
> > > > *path)
> > > > }
> > > > }
> > > >
> > > > -void setup_path(const char *cmd_path)
> > > > +void setup_path(void)
> > >
> > > It seems to me that this patch would not do anything different, but
> > > with less code change, if setup_path() would set argv0_path, and not a
> > > new function was introduced.
> >
> > This is just to play a safe game. I had it that way, but I decided to
> > have the call to the new git_set_argv0_path() early in git.c because the
> > call to setup_path() in git.c is very late, and it could happen that we
> > call system_path() (which needs argv0_path) before that. Although I
> > didn't audit the code whether this really happens.
>
> Well, okay... I would have rather seen it not change (since there was no
> bug to fix), or as a separate patch, but it's Junio's call.
I investigated this, and, yes, there indeed are calls to system_path() before
setup_path(), for example:
commit_pager_choice
setup_pager
git_config
git_etc_gitconfig
system_path(ETC_GITCONFIG)
Junio, do you want git_set_argv0_path() in a separate patch?
-- Hannes
^ permalink raw reply
* Re: RA layer request failed
From: Carlos Oliveira @ 2008-07-14 18:47 UTC (permalink / raw)
To: git
In-Reply-To: <3cfdbff10807141141h2a182dd5vc79a6b41bdbea748@mail.gmail.com>
Just some additional information:
- it is not a connectivity problem: I can commit from a conventional svn client
- git version is 1.5.6 on cygwin
-Carlos
On Mon, Jul 14, 2008 at 2:41 PM, Carlos Oliveira <coliveira@gmail.com> wrote:
> Hi Everyone,
>
> I am using git svn dcommit, and I am receiving the following message:
>
> RA layer request failed: COPY of <file>: 40 Not Found ... at
> /usr/bin/git-svn line 461
>
> This is the first time I see this message after I started using git
> svn (I use it a lot).
> This all started when I had a interrupted dcommit, which I managed to
> rebase to a safe
> state.
>
> Does anyone know what this error means, and how I can fix it?
>
> Thanks,
> -Carlos
>
^ permalink raw reply
* RA layer request failed
From: Carlos Oliveira @ 2008-07-14 18:41 UTC (permalink / raw)
To: git
Hi Everyone,
I am using git svn dcommit, and I am receiving the following message:
RA layer request failed: COPY of <file>: 40 Not Found ... at
/usr/bin/git-svn line 461
This is the first time I see this message after I started using git
svn (I use it a lot).
This all started when I had a interrupted dcommit, which I managed to
rebase to a safe
state.
Does anyone know what this error means, and how I can fix it?
Thanks,
-Carlos
^ permalink raw reply
* [PATCH,v2] Make git-add -i accept ranges like 7-
From: Ciaran McCreesh @ 2008-07-14 18:29 UTC (permalink / raw)
To: gitster; +Cc: git, Ciaran McCreesh
In-Reply-To: <7vfxqcgwni.fsf@gitster.siamese.dyndns.org>
git-add -i ranges expect number-number. But for the supremely lazy, typing in
that second number when selecting "from patch 7 to the end" is wasted effort.
So treat an empty second number in a range as "until the last item".
Signed-off-by: Ciaran McCreesh <ciaran.mccreesh@googlemail.com>
---
Oops, my bad.
Attempt 2 changes the regex to require a number in the first half of the range.
I was planning to allow for -7, meaning 'up to 7', but this collides with - at
the start being used to unchoose things. There's not much point adding a
special thing for 'from the start' though, since '1' is only one character to
type.
Documentation/git-add.txt | 5 +++--
git-add--interactive.perl | 6 +++---
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 46dd56c..3558905 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -187,8 +187,9 @@ update::
"Update>>". When the prompt ends with double '>>', you can
make more than one selection, concatenated with whitespace or
comma. Also you can say ranges. E.g. "2-5 7,9" to choose
- 2,3,4,5,7,9 from the list. You can say '*' to choose
- everything.
+ 2,3,4,5,7,9 from the list. If the second number in a range is
+ omitted, all remaining patches are taken. E.g. "7-" to choose
+ 7,8,9 from the list. You can say '*' to choose everything.
+
What you chose are then highlighted with '*',
like this:
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 801d7c0..a6a5c52 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -406,9 +406,9 @@ sub list_and_choose {
if ($choice =~ s/^-//) {
$choose = 0;
}
- # A range can be specified like 5-7
- if ($choice =~ /^(\d+)-(\d+)$/) {
- ($bottom, $top) = ($1, $2);
+ # A range can be specified like 5-7 or 5-.
+ if ($choice =~ /^(\d+)-(\d*)$/) {
+ ($bottom, $top) = ($1, length($2) ? $2 : 1 + @stuff);
}
elsif ($choice =~ /^\d+$/) {
$bottom = $top = $choice;
--
1.5.6.2
^ permalink raw reply related
* Re: [PATCH] Make git-add -i accept ranges like 7-
From: Junio C Hamano @ 2008-07-14 18:15 UTC (permalink / raw)
To: Ciaran McCreesh; +Cc: git
In-Reply-To: <1216058784-32584-1-git-send-email-ciaran.mccreesh@googlemail.com>
Ciaran McCreesh <ciaran.mccreesh@googlemail.com> writes:
> git-add -i ranges expect number-number. But for the supremely lazy, typing in
> that second number when selecting "from patch 7 to the end" is wasted effort.
> So treat an empty second number in a range as "until the last item".
You didn't describe why you changed the first regexp from \d+ to \d*,
which would allow "-9" as a valid input as well.
But in that case $bottom will become an empty string. Don't you need to
adjust the users of this data in the codepaths that follow this part? I
didn't check.
> diff --git a/git-add--interactive.perl b/git-add--interactive.perl
> index 801d7c0..72a8858 100755
> --- a/git-add--interactive.perl
> +++ b/git-add--interactive.perl
> @@ -406,9 +406,9 @@ sub list_and_choose {
> if ($choice =~ s/^-//) {
> $choose = 0;
> }
> - # A range can be specified like 5-7
> - if ($choice =~ /^(\d+)-(\d+)$/) {
> - ($bottom, $top) = ($1, $2);
> + # A range can be specified like 5-7 or 5-.
> + if ($choice =~ /^(\d*)-(\d*)$/) {
> + ($bottom, $top) = ($1, length($2) ? $2 : 1 + @stuff);
> }
> elsif ($choice =~ /^\d+$/) {
> $bottom = $top = $choice;
> --
> 1.5.6.2
^ permalink raw reply
* [PATCH] shortlog: support --pretty=format: option
From: Johannes Schindelin @ 2008-07-14 18:08 UTC (permalink / raw)
To: Linus Torvalds
Cc: Andrew Morton, Junio C Hamano, Ingo Molnar, Git Mailing List,
Thomas Gleixner
In-Reply-To: <alpine.DEB.1.00.0807141844160.8950@racer>
With this patch, the user can override the default setting, to print
the commit messages using a user format instead of the onelines of the
commits. Example:
$ git shortlog --pretty='format:%s (%h)' <commit>..
Note that shortlog will only respect a user format setting, as the other
formats do not make much sense.
Wished for by Andrew Morton.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
On Mon, 14 Jul 2008, Johannes Schindelin wrote:
> Note that I do not think it would be all that hard to teach
> shortlog the --pretty option.
Well...
builtin-shortlog.c | 11 +++++++++++
shortlog.h | 1 +
2 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/builtin-shortlog.c b/builtin-shortlog.c
index 0136202..f8bcbfc 100644
--- a/builtin-shortlog.c
+++ b/builtin-shortlog.c
@@ -154,6 +154,15 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
if (!author)
die("Missing author: %s",
sha1_to_hex(commit->object.sha1));
+ if (log->user_format) {
+ struct strbuf buf = STRBUF_INIT;
+
+ pretty_print_commit(CMIT_FMT_USERFORMAT, commit, &buf,
+ DEFAULT_ABBREV, "", "", DATE_NORMAL, 0);
+ insert_one_record(log, author, buf.buf);
+ strbuf_release(&buf);
+ return;
+ }
if (*buffer)
buffer++;
insert_one_record(log, author, !*buffer ? "<none>" : buffer);
@@ -271,6 +280,8 @@ parse_done:
usage_with_options(shortlog_usage, options);
}
+ log.user_format = rev.commit_format == CMIT_FMT_USERFORMAT;
+
/* assume HEAD if from a tty */
if (!nongit && !rev.pending.nr && isatty(0))
add_head_to_pending(&rev);
diff --git a/shortlog.h b/shortlog.h
index 31ff491..6608ee8 100644
--- a/shortlog.h
+++ b/shortlog.h
@@ -11,6 +11,7 @@ struct shortlog {
int wrap;
int in1;
int in2;
+ int user_format;
char *common_repo_prefix;
int email;
--
1.5.6.2.511.ge432a
^ permalink raw reply related
* [PATCH] Make git-add -i accept ranges like 7-
From: Ciaran McCreesh @ 2008-07-14 18:06 UTC (permalink / raw)
To: git; +Cc: Ciaran McCreesh
git-add -i ranges expect number-number. But for the supremely lazy, typing in
that second number when selecting "from patch 7 to the end" is wasted effort.
So treat an empty second number in a range as "until the last item".
Signed-off-by: Ciaran McCreesh <ciaran.mccreesh@googlemail.com>
---
Documentation/git-add.txt | 5 +++--
git-add--interactive.perl | 6 +++---
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 46dd56c..3558905 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -187,8 +187,9 @@ update::
"Update>>". When the prompt ends with double '>>', you can
make more than one selection, concatenated with whitespace or
comma. Also you can say ranges. E.g. "2-5 7,9" to choose
- 2,3,4,5,7,9 from the list. You can say '*' to choose
- everything.
+ 2,3,4,5,7,9 from the list. If the second number in a range is
+ omitted, all remaining patches are taken. E.g. "7-" to choose
+ 7,8,9 from the list. You can say '*' to choose everything.
+
What you chose are then highlighted with '*',
like this:
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 801d7c0..72a8858 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -406,9 +406,9 @@ sub list_and_choose {
if ($choice =~ s/^-//) {
$choose = 0;
}
- # A range can be specified like 5-7
- if ($choice =~ /^(\d+)-(\d+)$/) {
- ($bottom, $top) = ($1, $2);
+ # A range can be specified like 5-7 or 5-.
+ if ($choice =~ /^(\d*)-(\d*)$/) {
+ ($bottom, $top) = ($1, length($2) ? $2 : 1 + @stuff);
}
elsif ($choice =~ /^\d+$/) {
$bottom = $top = $choice;
--
1.5.6.2
^ permalink raw reply related
* Re: Closing the merge window for 1.6.0
From: Nicolas Pitre @ 2008-07-14 17:54 UTC (permalink / raw)
To: Gerrit Pape; +Cc: Johannes Schindelin, Petr Baudis, Junio C Hamano, git
In-Reply-To: <20080714124109.25414.qmail@06d015ec9c6744.315fe32.mid.smarden.org>
On Mon, 14 Jul 2008, Gerrit Pape wrote:
> On Mon, Jul 14, 2008 at 12:57:56PM +0100, Johannes Schindelin wrote:
> > On Mon, 14 Jul 2008, Petr Baudis wrote:
> > > I'm saying this because I believe the best conservative upper bound for
> > > backwards compatibility is Git version in Debian stable. It gets
> > > probably the most stale from all the widely used software distributions
> > > using Git, and it *is* quite widely used. Etch carries v1.4.4.4, which
> > > fails miserably on the new packs.
> >
> > Can't we just hit Debian's Git maintainer with a clue bat or a bus,
>
> Please don't. It wouldn't help, rather the opposite I think, espacially
> the bus. We don't introduce new upstream versions into a Debian stable
> release, there's a great effort done for each stable release to reach
> high quality integration of all the software packages available in
> Debian. Once that status is reached, only security fixes and criticial
> usability fixes are added.
Please consider it as a critical usability problem.
Maybe we can release 1.4.5 with the ability to read index v2? That
wouldn't be hard to backport the reading part of it.
Nicolas
^ 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