* Re: [PATCH] Make git-fmt-merge-msg a builtin
From: Johannes Schindelin @ 2006-07-03 15:45 UTC (permalink / raw)
To: Timo Hirvonen; +Cc: git, junkio
In-Reply-To: <20060703182621.dbed5b5f.tihirvon@gmail.com>
Hi,
On Mon, 3 Jul 2006, Timo Hirvonen wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
>
> > I had in mind that I want to use path-list instead (which is cooking in
> > the merge-recursive efforts ATM). And there, I would add a flag
> > needs_payload. Opinions?
>
> This code is so simple that making the path_list more complex
> (needs_payload special case?) is not worth it. I have not looked at the
> code very closely though and have no idea what I'm talking about :)
Okay. But I'd rather go back to work on merge-recursive, and just reuse
the path_list struct.
> > > free(NULL) is safe.
> >
> > Is it? I vaguely remember that I had problems with this on some obscure
> > platform.
>
> I don't think so.
Well, after a little Googling, I am more convinced than ever that it is a
BAD thing to rely on free(NULL) being a NOP.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH 1/4] merge-recursive in C
From: Timo Hirvonen @ 2006-07-03 15:46 UTC (permalink / raw)
To: fork0; +Cc: git, Johannes.Schindelin, junkio
In-Reply-To: <20060630002721.GA22618@steel.home>
fork0@t-online.de (Alex Riesen) wrote:
> +/* in place */
> +void path_list_union_update(struct path_list *dst, const struct path_list *src)
> +{
> + char **new_paths;
> + int i = 0, j = 0, nr = 0, alloc = dst->nr + dst->nr;
It should be alloc = dst->nr + src->nr.
--
http://onion.dynserv.net/~timo/
^ permalink raw reply
* Re: [PATCH 1/4] merge-recursive in C
From: Johannes Schindelin @ 2006-07-03 15:54 UTC (permalink / raw)
To: Timo Hirvonen; +Cc: git
In-Reply-To: <20060703184604.59801e4e.tihirvon@gmail.com>
Hi,
On Mon, 3 Jul 2006, Timo Hirvonen wrote:
> fork0@t-online.de (Alex Riesen) wrote:
>
> > +/* in place */
> > +void path_list_union_update(struct path_list *dst, const struct path_list *src)
> > +{
> > + char **new_paths;
> > + int i = 0, j = 0, nr = 0, alloc = dst->nr + dst->nr;
>
> It should be alloc = dst->nr + src->nr.
Good catch. Merci.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] Make git-fmt-merge-msg a builtin
From: Timo Hirvonen @ 2006-07-03 16:16 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, junkio
In-Reply-To: <Pine.LNX.4.63.0607031731550.29667@wbgn013.biozentrum.uni-wuerzburg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > > > free(NULL) is safe.
> > >
> > > Is it? I vaguely remember that I had problems with this on some obscure
> > > platform.
> >
> > I don't think so.
>
> Well, after a little Googling, I am more convinced than ever that it is a
> BAD thing to rely on free(NULL) being a NOP.
I did some research too. Seems that C89 requires free(NULL) to be a
no-op but on some old systems (SunOS) it may crash. IMNSHO these
systems were designed to crash valid programs and torture developers.
There are probably many free(NULL) and realloc(NULL, ...) uses in the
git source code and are not worth fixing.
--
http://onion.dynserv.net/~timo/
^ permalink raw reply
* Re: Compression speed for large files
From: Linus Torvalds @ 2006-07-03 16:31 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Joachim Berdal Haga, Alex Riesen, git
In-Reply-To: <Pine.LNX.4.64.0607031030150.1213@localhost.localdomain>
On Mon, 3 Jul 2006, Nicolas Pitre wrote:
> On Mon, 3 Jul 2006, Joachim Berdal Haga wrote:
> >
> > I can send a patch later. If it's to be a per-repo option, it's probably too
> > confusing with several values. Is it ok with
> >
> > core.compression = [-1..9]
> >
> > where the numbers are the zlib/gzip constants,
> > -1 = zlib default (currently 6)
> > 0 = no compression
> > 1..9 = various speed/size tradeoffs (9 is git default)
>
> I think this makes a lot of sense, although IMHO I'd simply use
> Z_DEFAULT_COMPRESSION everywhere and be done with it without extra
> complexity which aren't worth the size difference.
I think Z_DEFAULT_COMPRESSION is fine too - we've long since started
relying on pack-files and the delta compression for the _real_ size
improvements, and as such, the zlib compression is less important.
That said, the "core.compression" thing sounds good to me, and gives
people the ability to tune things for their loads.
Linus
^ permalink raw reply
* Re: [PATCH 3/3] Make clear_commit_marks() clean harder
From: Linus Torvalds @ 2006-07-03 17:05 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Junio C Hamano, Rene Scharfe, git
In-Reply-To: <Pine.LNX.4.63.0607031553570.29667@wbgn013.biozentrum.uni-wuerzburg.de>
On Mon, 3 Jul 2006, Johannes Schindelin wrote:
>
> On Mon, 3 Jul 2006, Junio C Hamano wrote:
>
> > Rene Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
> >
> > > Don't care if objects have been parsed or not and don't stop when we
> > > reach a commit that is already clean -- its parents could be dirty.
> >
> > There is something quite wrong with this patch.
>
> I always had the feeling that it was wrong to traverse not-yet-parsed
> parents: How could a revision walk possibly come to a certain commit
> without at least one continuous history of now-parsed objects?
No, that's not the problem.
The problem is that if we unconditionally traverse parents - whether
parsed or not - any merge will basically result in a 2* expansion of the
working set: we'll traverse all children twice (whether they meet again or
not).
So the cost of doign unconditional traversals of parents basically
approaches 2^n, where 'n' is the number of merges.
Now, the fact that we only traverse parents without adding new ones (and
the decision on whether it is parsed or not is irrelevant - the only
relevant part being that we don't parse any _new_ ones) means that each
commit itself is very cheap to traverse, but O(2^n) ends up meaning that
even a small constant will eventually be pretty big.
The proper fix is _not_ to add the "object->parsed" check (which is silly,
wrong, and doesn't fix anything at all), but to add a check for whether
the object has been seen or not.
In the case of clearing flags, you have two choices:
- _set_ a new flag ("already cleared"). This would work - once - but is
obviously pretty bad.
This is what we do in all the other cases. We usually call the flag
SEEN or similar.
- depend on the flags being "dense", and saying that we depend on the
fact that in order for any of the flags to have been set in the first
place, at least _one_ of them needs to be set in the path leading up to
that commit.
Now, for the specific case of get_merge_bases(), the flags _are_ dense.
Individual flags may not be (eg the "UNINTERESTING" flag, whatever it's
called, will not be dense), but the question of "is _any_ of the flags we
care about set" _will_ be dense.
As such, adding a
/* Have we already cleared this? */
if (!(mask & object->flags))
return;
object->flags &= ~mask;
to the traversal function will fix the O(m+2^n) behaviour, and turn the
traversal into O(m+n) (where "n" is the number of merges, and "m" is the
total number of commits).
Linus
^ permalink raw reply
* [PATCH] Make zlib compression level configurable, and change default.
From: Joachim B Haga @ 2006-07-03 18:59 UTC (permalink / raw)
To: git; +Cc: Nicolas Pitre, Linus Torvalds, Alex Riesen, Junio C Hamano
In-Reply-To: <Pine.LNX.4.64.0607030929490.12404@g5.osdl.org>
Make zlib compression level configurable, and change the default.
With the change in default, "git add ." on kernel dir is about
twice as fast as before, with only minimal (0.5%) change in
object size. The speed difference is even more noticeable
when committing large files, which is now up to 8 times faster.
The configurability is through setting core.compression = [-1..9]
which maps to the zlib constants; -1 is the default, 0 is no
compression, and 1..9 are various speed/size tradeoffs, 9
being slowest.
Signed-off-by: Joachim B Haga (cjhaga@fys.uio.no)
---
Documentation/config.txt | 6 ++++++
cache.h | 1 +
config.c | 5 +++++
environment.c | 1 +
sha1_file.c | 4 ++--
5 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index a04c5ad..ac89be7 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -91,6 +91,12 @@ core.warnAmbiguousRefs::
If true, git will warn you if the ref name you passed it is ambiguous
and might match multiple refs in the .git/refs/ tree. True by default.
+core.compression:
+ An integer -1..9, indicating the compression level for objects that
+ are not in a pack file. -1 is the zlib and git default. 0 means no
+ compression, and 1..9 are various speed/size tradeoffs, 9 being
+ slowest.
+
alias.*::
Command aliases for the gitlink:git[1] command wrapper - e.g.
after defining "alias.last = cat-file commit HEAD", the invocation
diff --git a/cache.h b/cache.h
index 8719939..84770bf 100644
--- a/cache.h
+++ b/cache.h
@@ -183,6 +183,7 @@ extern int log_all_ref_updates;
extern int warn_ambiguous_refs;
extern int shared_repository;
extern const char *apply_default_whitespace;
+extern int zlib_compression_level;
#define GIT_REPO_VERSION 0
extern int repository_format_version;
diff --git a/config.c b/config.c
index ec44827..61563be 100644
--- a/config.c
+++ b/config.c
@@ -279,6 +279,11 @@ int git_default_config(const char *var,
return 0;
}
+ if (!strcmp(var, "core.compression")) {
+ zlib_compression_level = git_config_int(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "user.name")) {
strlcpy(git_default_name, value, sizeof(git_default_name));
return 0;
diff --git a/environment.c b/environment.c
index 3de8eb3..1d8ceef 100644
--- a/environment.c
+++ b/environment.c
@@ -20,6 +20,7 @@ int repository_format_version = 0;
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
int shared_repository = PERM_UMASK;
const char *apply_default_whitespace = NULL;
+int zlib_compression_level = -1;
static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
*git_graft_file;
diff --git a/sha1_file.c b/sha1_file.c
index 8179630..bc35808 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1458,7 +1458,7 @@ int write_sha1_file(void *buf, unsigned
/* Set it up */
memset(&stream, 0, sizeof(stream));
- deflateInit(&stream, Z_BEST_COMPRESSION);
+ deflateInit(&stream, zlib_compression_level);
size = deflateBound(&stream, len+hdrlen);
compressed = xmalloc(size);
@@ -1511,7 +1511,7 @@ static void *repack_object(const unsigne
/* Set it up */
memset(&stream, 0, sizeof(stream));
- deflateInit(&stream, Z_BEST_COMPRESSION);
+ deflateInit(&stream, zlib_compression_level);
size = deflateBound(&stream, len + hdrlen);
buf = xmalloc(size);
--
1.4.1.g8fced-dirty
^ permalink raw reply related
* [PATCH] Use configurable zlib compression level everywhere.
From: Joachim B Haga @ 2006-07-03 19:02 UTC (permalink / raw)
To: git; +Cc: Nicolas Pitre, Linus Torvalds, Alex Riesen, Junio C Hamano
In-Reply-To: <Pine.LNX.4.64.0607030929490.12404@g5.osdl.org>
This one I'm not so sure about, it's for completeness. But I don't actually use
git and haven't tested beyond the git add / git commit stage. Still...
Signed-off-by: Joachim B Haga (cjhaga@fys.uio.no)
---
csum-file.c | 2 +-
diff.c | 2 +-
http-push.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/csum-file.c b/csum-file.c
index ebaad03..6a7b40f 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -122,7 +122,7 @@ int sha1write_compressed(struct sha1file
void *out;
memset(&stream, 0, sizeof(stream));
- deflateInit(&stream, Z_DEFAULT_COMPRESSION);
+ deflateInit(&stream, zlib_compression_level);
maxsize = deflateBound(&stream, size);
out = xmalloc(maxsize);
diff --git a/diff.c b/diff.c
index 5a71489..428ff78 100644
--- a/diff.c
+++ b/diff.c
@@ -583,7 +583,7 @@ static unsigned char *deflate_it(char *d
z_stream stream;
memset(&stream, 0, sizeof(stream));
- deflateInit(&stream, Z_BEST_COMPRESSION);
+ deflateInit(&stream, zlib_compression_level);
bound = deflateBound(&stream, size);
deflated = xmalloc(bound);
stream.next_out = deflated;
diff --git a/http-push.c b/http-push.c
index e281f70..f761584 100644
--- a/http-push.c
+++ b/http-push.c
@@ -492,7 +492,7 @@ static void start_put(struct transfer_re
/* Set it up */
memset(&stream, 0, sizeof(stream));
- deflateInit(&stream, Z_BEST_COMPRESSION);
+ deflateInit(&stream, zlib_compression_level);
size = deflateBound(&stream, len + hdrlen);
request->buffer.buffer = xmalloc(size);
--
1.4.1.g8fced-dirty
^ permalink raw reply related
* Re: [PATCH] Make zlib compression level configurable, and change default.
From: Linus Torvalds @ 2006-07-03 19:33 UTC (permalink / raw)
To: Joachim B Haga
Cc: Nicolas Pitre, Alex Riesen, Junio C Hamano, Git Mailing List
In-Reply-To: <85d5cm8qfn.fsf_-_@lupus.ig3.net>
On Mon, 3 Jul 2006, Joachim B Haga wrote:
>
> The configurability is through setting core.compression = [-1..9]
> which maps to the zlib constants; -1 is the default, 0 is no
> compression, and 1..9 are various speed/size tradeoffs, 9
> being slowest.
My only worry is that this encodes "Z_DEFAULT_COMPRESSION" as being -1,
which happens to be /true/, but I don't think that's a documented
interface (you're supposed to use the Z_DEFAULT_COMPRESSION macro, which
could have any value, and just _happens_ to be -1).
Is it likely to ever change from that -1? Probably not. So I think your
patch is technically correct, but it might just be nicer if it did
something like
..
if (!strcmp(var, "core.compression")) {
int level = git_config_int(var, value);
if (level == -1)
level = Z_DEFAULT_COMPRESSION;
else if (level < 0 || level > Z_BEST_COMPRESSION)
die("bad zlib compression level %d", level);
zlib_compression_level = level;
return 0;
}
..
which would be safer, and a smart compiler might notice that the -1 case
ends up being a no-op, and then just generate code AS IF we just had a
if (level < -1 || level > Z_BEST_COMPRESSION)
die(...
there.
Oh, and for all the same reasons, we should use
int zlib_compression_level = Z_BEST_COMPRESSION;
for the default initializer.
Hmm?
Linus
^ permalink raw reply
* Re: [PATCH] Use configurable zlib compression level everywhere.
From: Junio C Hamano @ 2006-07-03 19:43 UTC (permalink / raw)
To: Joachim B Haga; +Cc: git
In-Reply-To: <8564ie8qbe.fsf_-_@lupus.ig3.net>
Joachim B Haga <cjhaga@fys.uio.no> writes:
> This one I'm not so sure about, it's for completeness. But I don't actually use
> git and haven't tested beyond the git add / git commit stage. Still...
>
> Signed-off-by: Joachim B Haga (cjhaga@fys.uio.no)
You made a good judgement to notice that these three are
different.
* sha1write_compressed() in csum-file.c is for producing packs
and most of the things we compress there are deltas and less
compressible, so even when core.compression is set to high we
might be better off using faster compression.
* diff's deflate_it() is about producing binary diffs (later
encoded in base85) for textual transfer. Again it is almost
always used to compress deltas so the same comment as above
apply to this.
* http-push uses it to send compressed whole object, and this
is only used over the network, so it is plausible that the
user would want to use different compression level than the
usual core.compression.
It is fine by me to use the same core.compression to these
three. If somebody comes up with a workload that benefits from
having different settings for them, we can add separate
variables, falling back on the default core.compression if there
isn't one, as needed.
Thanks for the patches.
^ permalink raw reply
* Re: [PATCH 3/3] Make clear_commit_marks() clean harder
From: Junio C Hamano @ 2006-07-03 19:47 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0607031553570.29667@wbgn013.biozentrum.uni-wuerzburg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>> > Don't care if objects have been parsed or not and don't stop when we
>> > reach a commit that is already clean -- its parents could be dirty.
>>
>> There is something quite wrong with this patch.
>
> I always had the feeling that it was wrong to traverse not-yet-parsed
> parents: How could a revision walk possibly come to a certain commit
> without at least one continuous history of now-parsed objects?
>
> Also, AFAIK the revision walk sets flags for each commit it touched, and
> we should not try to be smart-asses about the flags, but just unset these
> flags.
The main points were made by Linus already.
Traversing is not needed -- not clearing not-yet-parsed is
obviously wrong.
> BTW some very quick tests showed that the clear_commit_marks() thing that
> I sent to the list was much faster than traversing all objects (which was
> in my original version).
I have a crude workaround pushed out last night but will be
replacing it with something less drastic. I think the final
version should be what you had, perhaps minus not looking at the
parsed flag for unmarking purposes.
^ permalink raw reply
* Re: [PATCH] Make zlib compression level configurable, and change default.
From: Linus Torvalds @ 2006-07-03 19:50 UTC (permalink / raw)
To: Joachim B Haga
Cc: Nicolas Pitre, Alex Riesen, Junio C Hamano, Git Mailing List
In-Reply-To: <Pine.LNX.4.64.0607031226370.12404@g5.osdl.org>
On Mon, 3 Jul 2006, Linus Torvalds wrote:
>
> Oh, and for all the same reasons, we should use
>
> int zlib_compression_level = Z_BEST_COMPRESSION;
That should be Z_DEFAULT_COMPRESSION, of course.
Anyway, I think the patches are ok as-is, and my suggestion to avoid the
"-1" and use Z_DEFAULT_COMPRESSION is really just an additional comment,
not anything fundamental.
So Junio, feel free to add an
Acked-by: Linus Torvalds <torvalds@osdl.org>
regardless of whether also doing that.
Linus
^ permalink raw reply
* Re: qgit idea: interface for cherry-picking
From: Junio C Hamano @ 2006-07-03 20:03 UTC (permalink / raw)
To: Marco Costalba; +Cc: git
In-Reply-To: <e5bfff550607030418n6a46c0cdh1a95155e1feb4356@mail.gmail.com>
"Marco Costalba" <mcostalba@gmail.com> writes:
> I cannot test your patch now, so I'm just guessing, what if we have a
> series of patches?
The patch stops at each patch. I am primarily interested in
keeping "git-am" usable from command line while making it easy
to use from other tools.
The expected use for the patch you are responding to is that
after the first application with --fail the user has an
opportunity to fix the result up but needs to create a commit by
rerunning "git-am" (or just drop that by resetting the index and
saying "git-am --skip").
> Is it possible that for two patches A and B happens that
>
> git-am A
> git-am B
> git-reset --soft HEAD^^
>
> gives a different result then
>
> git-am --fail A
> git-am --fail B
If you had a series of patches chosen inside your GUI and
squash-apply them all, two full am with soft reset to the
original state would be the easiest, if and only if both patch
applications do not fail. If patch A does not apply for
whatever reason, you have to guide your user through the patch
adjustment process before applying B, regardless of the reason
why the patch application failed (either A did not apply
cleanly, or you gave --fail to the command).
The main question is what you would let your users do and how
you would guide them through the process, when the application
of an earlier patch in the series fails. I think it is a
secondary implementation detail which of "git-am", "git-am
--fail" or "git-apply" to implement that process.
^ permalink raw reply
* Re: [PATCH 2] autoconf: Use ./configure script in git *.spec file
From: Junio C Hamano @ 2006-07-03 20:08 UTC (permalink / raw)
To: jnareb; +Cc: git
In-Reply-To: <e8atkm$ipg$1@sea.gmane.org>
Jakub Narebski <jnareb@gmail.com> writes:
> As I see it, we have the following options with respect to autoconf related
> files and use of ./configure script
>
>
> 1. Use autoconf and ./configure script generated by it as optional way to
> configure installation process. Have configure.ac and config.mak.in in main
> directory of git.git repository. Do not use ./configure script in
> git.spec.in, i.e. do not apply this patch... perhaps put _patch_ in the
> contrib/. Leave changes to *.spec file to distributions, documenting it
> somewhere.
> ..
> I am partially to [*1*], if just because I wouldn't need to take care
> autoconf in git.
I do not understand this "I wouldn't need to take care autoconf
in git" part. Sorry.
^ permalink raw reply
* Re: [PATCH] Make zlib compression level configurable, and change default.
From: Joachim B Haga @ 2006-07-03 20:11 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds, Junio C Hamano
In-Reply-To: <Pine.LNX.4.64.0607031226370.12404@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> [snip suggested improvements]
Yes, that would be more... thorough. And, especially for the
int zlib_compression_level = Z_DEFAULT_COMPRESSION;
line, more self-explanatory, too. So here's an updated patch
(replacing the previous) including your suggestions.
-j.
-
Make zlib compression level configurable, and change default.
With the change in default, "git add ." on kernel dir is about
twice as fast as before, with only minimal (0.5%) change in
object size. The speed difference is even more noticeable
when committing large files, which is now up to 8 times faster.
The configurability is through setting core.compression = [-1..9]
which maps to the zlib constants; -1 is the default, 0 is no
compression, and 1..9 are various speed/size tradeoffs, 9
being slowest.
Signed-off-by: Joachim B Haga (cjhaga@fys.uio.no)
---
Documentation/config.txt | 6 ++++++
cache.h | 1 +
config.c | 10 ++++++++++
environment.c | 1 +
sha1_file.c | 4 ++--
5 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index a04c5ad..ac89be7 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -91,6 +91,12 @@ core.warnAmbiguousRefs::
If true, git will warn you if the ref name you passed it is ambiguous
and might match multiple refs in the .git/refs/ tree. True by default.
+core.compression:
+ An integer -1..9, indicating the compression level for objects that
+ are not in a pack file. -1 is the zlib and git default. 0 means no
+ compression, and 1..9 are various speed/size tradeoffs, 9 being
+ slowest.
+
alias.*::
Command aliases for the gitlink:git[1] command wrapper - e.g.
after defining "alias.last = cat-file commit HEAD", the invocation
diff --git a/cache.h b/cache.h
index 8719939..84770bf 100644
--- a/cache.h
+++ b/cache.h
@@ -183,6 +183,7 @@ extern int log_all_ref_updates;
extern int warn_ambiguous_refs;
extern int shared_repository;
extern const char *apply_default_whitespace;
+extern int zlib_compression_level;
#define GIT_REPO_VERSION 0
extern int repository_format_version;
diff --git a/config.c b/config.c
index ec44827..b23f4bf 100644
--- a/config.c
+++ b/config.c
@@ -279,6 +279,16 @@ int git_default_config(const char *var,
return 0;
}
+ if (!strcmp(var, "core.compression")) {
+ int level = git_config_int(var, value);
+ if (level == -1)
+ level = Z_DEFAULT_COMPRESSION;
+ else if (level < 0 || level > Z_BEST_COMPRESSION)
+ die("bad zlib compression level %d", level);
+ zlib_compression_level = level;
+ return 0;
+ }
+
if (!strcmp(var, "user.name")) {
strlcpy(git_default_name, value, sizeof(git_default_name));
return 0;
diff --git a/environment.c b/environment.c
index 3de8eb3..43823ff 100644
--- a/environment.c
+++ b/environment.c
@@ -20,6 +20,7 @@ int repository_format_version = 0;
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
int shared_repository = PERM_UMASK;
const char *apply_default_whitespace = NULL;
+int zlib_compression_level = Z_DEFAULT_COMPRESSION;
static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
*git_graft_file;
diff --git a/sha1_file.c b/sha1_file.c
index 8179630..bc35808 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1458,7 +1458,7 @@ int write_sha1_file(void *buf, unsigned
/* Set it up */
memset(&stream, 0, sizeof(stream));
- deflateInit(&stream, Z_BEST_COMPRESSION);
+ deflateInit(&stream, zlib_compression_level);
size = deflateBound(&stream, len+hdrlen);
compressed = xmalloc(size);
@@ -1511,7 +1511,7 @@ static void *repack_object(const unsigne
/* Set it up */
memset(&stream, 0, sizeof(stream));
- deflateInit(&stream, Z_BEST_COMPRESSION);
+ deflateInit(&stream, zlib_compression_level);
size = deflateBound(&stream, len + hdrlen);
buf = xmalloc(size);
--
1.4.1.g8fced-dirty
^ permalink raw reply related
* Re: Quick merge status updates.
From: Petr Baudis @ 2006-07-03 20:29 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vejx31sav.fsf@assigned-by-dhcp.cox.net>
Dear diary, on Mon, Jul 03, 2006 at 02:02:30AM CEST, I got a letter
where Junio C Hamano <junkio@cox.net> said that...
> Petr Baudis <pasky@suse.cz> writes:
>
> > so this is my attempt to summarize it:
>
> Ah, our message crossed -- thanks for summarizing it. I do not
> particularly like any of the solution so far, but maybe the
> patch I just sent out to "do the normal thing unless we are
> running tests" might be the right thing to do.
Yes, I roughly agree. I have some gripes, patches will follow.
> > (ii) My proposed second solution was to add an autogenerated line to
> > the Git's perl scripts saying something like:
> >
> > use lib ('instlibdir', 'srclibdir');
> >
> > This fulfills all (D1), (D2) and (D3)
>
> If you have srclibdir after instlibdir, aren't you breaking D2?
*Sigh*
Why can't I get it right for once? ;-)
> And I do not think swapping them is right either. It would
> fullfil D1/D2/D3 but I think it has one bad side effect.
Yes, I agree with your reservations.
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Snow falling on Perl. White noise covering line noise.
Hides all the bugs too. -- J. Putnam
^ permalink raw reply
* Re: [PATCH 2] autoconf: Use ./configure script in git *.spec file
From: Jakub Narebski @ 2006-07-03 20:43 UTC (permalink / raw)
To: git
In-Reply-To: <7v4pxyqwn6.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano wrote:
> Jakub Narebski <jnareb@gmail.com> writes:
>
>> As I see it, we have the following options with respect to autoconf
related
>> files and use of ./configure script
>>
>>
>> 1. Use autoconf and ./configure script generated by it as optional way to
>> configure installation process. Have configure.ac and config.mak.in in
main
>> directory of git.git repository. Do not use ./configure script in
>> git.spec.in, i.e. do not apply this patch... perhaps put _patch_ in the
>> contrib/. Leave changes to *.spec file to distributions, documenting it
>> somewhere.
>> ..
>> I am partially to [*1*], if just because I wouldn't need to take care
>> autoconf in git.
>
> I do not understand this "I wouldn't need to take care autoconf
> in git" part. Sorry.
Gah. It should be: "if just because there would be no need to have someone
to take care that ./configure is up-to-date with respect to changes in
autoconf files". Sorry for the noise.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* [PATCH 3/6] Git.pm: Introduce ident() and ident_person() methods
From: Petr Baudis @ 2006-07-03 20:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <20060703204415.28541.47920.stgit@machine.or.cz>
These methods can retrieve/parse the author/committer ident.
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
git-send-email.perl | 11 ++---------
perl/Git.pm | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/git-send-email.perl b/git-send-email.perl
index e794e44..79e82f5 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -84,15 +84,8 @@ foreach my $entry (@bcclist) {
# Now, let's fill any that aren't set in with defaults:
-sub gitvar_ident {
- my ($name) = @_;
- my $val = $repo->command('var', $name);
- my @field = split(/\s+/, $val);
- return join(' ', @field[0...(@field-3)]);
-}
-
-my ($author) = gitvar_ident('GIT_AUTHOR_IDENT');
-my ($committer) = gitvar_ident('GIT_COMMITTER_IDENT');
+my ($author) = $repo->ident_person('author');
+my ($committer) = $repo->ident_person('committer');
my %aliases;
my @alias_files = $repo->config('sendemail.aliasesfile');
diff --git a/perl/Git.pm b/perl/Git.pm
index 24fd7ce..9ce9fcd 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -521,6 +521,55 @@ sub config {
}
+=item ident ( TYPE | IDENTSTR )
+
+=item ident_person ( TYPE | IDENTSTR | IDENTARRAY )
+
+This suite of functions retrieves and parses ident information, as stored
+in the commit and tag objects or produced by C<var GIT_type_IDENT> (thus
+C<TYPE> can be either I<author> or I<committer>; case is insignificant).
+
+The C<ident> method retrieves the ident information from C<git-var>
+and either returns it as a scalar string or as an array with the fields parsed.
+Alternatively, it can take a prepared ident string (e.g. from the commit
+object) and just parse it.
+
+C<ident_person> returns the person part of the ident - name and email;
+it can take the same arguments as C<ident> or the array returned by C<ident>.
+
+The synopsis is like:
+
+ my ($name, $email, $time_tz) = ident('author');
+ "$name <$email>" eq ident_person('author');
+ "$name <$email>" eq ident_person($name);
+ $time_tz =~ /^\d+ [+-]\d{4}$/;
+
+Both methods must be called on a repository instance.
+
+=cut
+
+sub ident {
+ my ($self, $type) = @_;
+ my $identstr;
+ if (lc $type eq lc 'committer' or lc $type eq lc 'author') {
+ $identstr = $self->command_oneline('var', 'GIT_'.uc($type).'_IDENT');
+ } else {
+ $identstr = $type;
+ }
+ if (wantarray) {
+ return $identstr =~ /^(.*) <(.*)> (\d+ [+-]\d{4})$/;
+ } else {
+ return $identstr;
+ }
+}
+
+sub ident_person {
+ my ($self, @ident) = @_;
+ $#ident == 0 and @ident = $self->ident($ident[0]);
+ return "$ident[0] <$ident[1]>";
+}
+
+
=item hash_object ( TYPE, FILENAME )
=item hash_object ( TYPE, FILEHANDLE )
^ permalink raw reply related
* [PATCH 0/6] The residual Git.pm patches
From: Petr Baudis @ 2006-07-03 20:44 UTC (permalink / raw)
To: junkio; +Cc: git
Hi,
this series is not so much meant for immediate application but
rather so that you can leave it lingering on top of pu, if you wish,
and especially of fear of it being lost in all the turmoil around
Git.pm - this is what was left in my StGIT series after weeding out
what ended up in next, neatly stacked in a single mail thread.
Petr Baudis
--
And on the eigth day, God started debugging.
^ permalink raw reply
* [PATCH 1/6] Git.pm: Add config() method
From: Petr Baudis @ 2006-07-03 20:47 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <20060703204415.28541.47920.stgit@machine.or.cz>
This accessor will retrieve value(s) of the given configuration variable.
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
Documentation/git-repo-config.txt | 3 ++-
perl/Git.pm | 37 ++++++++++++++++++++++++++++++++++++-
repo-config.c | 2 +-
3 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-repo-config.txt b/Documentation/git-repo-config.txt
index 803c0d5..cc72fa9 100644
--- a/Documentation/git-repo-config.txt
+++ b/Documentation/git-repo-config.txt
@@ -54,7 +54,8 @@ OPTIONS
--get::
Get the value for a given key (optionally filtered by a regex
- matching the value).
+ matching the value). Returns error code 1 if the key was not
+ found and error code 2 if multiple key values were found.
--get-all::
Like get, but does not fail if the number of values for the key
diff --git a/perl/Git.pm b/perl/Git.pm
index b4ee88b..24fd7ce 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -473,7 +473,6 @@ and the directory must exist.
sub wc_chdir {
my ($self, $subdir) = @_;
-
$self->wc_path()
or throw Error::Simple("bare repository");
@@ -486,6 +485,42 @@ sub wc_chdir {
}
+=item config ( VARIABLE )
+
+Retrieve the configuration C<VARIABLE> in the same manner as C<repo-config>
+does. In scalar context requires the variable to be set only one time
+(exception is thrown otherwise), in array context returns allows the
+variable to be set multiple times and returns all the values.
+
+Must be called on a repository instance.
+
+This currently wraps command('repo-config') so it is not so fast.
+
+=cut
+
+sub config {
+ my ($self, $var) = @_;
+ $self->repo_path()
+ or throw Error::Simple("not a repository");
+
+ try {
+ if (wantarray) {
+ return $self->command('repo-config', '--get-all', $var);
+ } else {
+ return $self->command_oneline('repo-config', '--get', $var);
+ }
+ } catch Git::Error::Command with {
+ my $E = shift;
+ if ($E->value() == 1) {
+ # Key not found.
+ return undef;
+ } else {
+ throw $E;
+ }
+ };
+}
+
+
=item hash_object ( TYPE, FILENAME )
=item hash_object ( TYPE, FILEHANDLE )
diff --git a/repo-config.c b/repo-config.c
index 743f02b..c7ed0ac 100644
--- a/repo-config.c
+++ b/repo-config.c
@@ -118,7 +118,7 @@ static int get_value(const char* key_, c
if (do_all)
ret = !seen;
else
- ret = (seen == 1) ? 0 : 1;
+ ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1;
free_strings:
if (repo_config)
^ permalink raw reply related
* [PATCH 6/6] Convert git-annotate to use Git.pm
From: Petr Baudis @ 2006-07-03 20:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <20060703204415.28541.47920.stgit@machine.or.cz>
Together with the other converted scripts, this is probably still pu
material; it appears to work fine for me, though. The speed gain from
get_object() is about 10% (I expected more...).
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
git-annotate.perl | 167 ++++++++++-------------------------------------------
1 files changed, 31 insertions(+), 136 deletions(-)
diff --git a/git-annotate.perl b/git-annotate.perl
index a6a7a48..d924e87 100755
--- a/git-annotate.perl
+++ b/git-annotate.perl
@@ -11,6 +11,7 @@ use strict;
use Getopt::Long;
use POSIX qw(strftime gmtime);
use File::Basename qw(basename dirname);
+use Git;
sub usage() {
print STDERR "Usage: ${\basename $0} [-s] [-S revs-file] file [ revision ]
@@ -29,7 +30,7 @@ sub usage() {
exit(1);
}
-our ($help, $longrev, $rename, $rawtime, $starting_rev, $rev_file) = (0, 0, 1);
+our ($help, $longrev, $rename, $rawtime, $starting_rev, $rev_file, $repo) = (0, 0, 1);
my $rc = GetOptions( "long|l" => \$longrev,
"time|t" => \$rawtime,
@@ -52,6 +53,8 @@ my @stack = (
},
);
+$repo = Git->repository();
+
our @filelines = ();
if (defined $starting_rev) {
@@ -102,15 +105,11 @@ while (my $bound = pop @stack) {
push @revqueue, $head;
init_claim( defined $starting_rev ? $head : 'dirty');
unless (defined $starting_rev) {
- my $diff = open_pipe("git","diff","-R", "HEAD", "--",$filename)
- or die "Failed to call git diff to check for dirty state: $!";
-
- _git_diff_parse($diff, $head, "dirty", (
- 'author' => gitvar_name("GIT_AUTHOR_IDENT"),
- 'author_date' => sprintf("%s +0000",time()),
- )
- );
- close($diff);
+ my %ident;
+ @ident{'author', 'author_email', 'author_date'} = $repo->ident('author');
+ my $diff = $repo->command_output_pipe('diff', '-R', 'HEAD', '--', $filename);
+ _git_diff_parse($diff, $head, "dirty", %ident);
+ $repo->command_close_pipe($diff);
}
handle_rev();
@@ -181,8 +180,7 @@ sub git_rev_list {
open($revlist, '<' . $rev_file)
or die "Failed to open $rev_file : $!";
} else {
- $revlist = open_pipe("git-rev-list","--parents","--remove-empty",$rev,"--",$file)
- or die "Failed to exec git-rev-list: $!";
+ $revlist = $repo->command_output_pipe('rev-list', '--parents', '--remove-empty', $rev, '--', $file);
}
my @revs;
@@ -191,7 +189,7 @@ sub git_rev_list {
my ($rev, @parents) = split /\s+/, $line;
push @revs, [ $rev, @parents ];
}
- close($revlist);
+ $repo->command_close_pipe($revlist);
printf("0 revs found for rev %s (%s)\n", $rev, $file) if (@revs == 0);
return @revs;
@@ -200,8 +198,7 @@ sub git_rev_list {
sub find_parent_renames {
my ($rev, $file) = @_;
- my $patch = open_pipe("git-diff-tree", "-M50", "-r","--name-status", "-z","$rev")
- or die "Failed to exec git-diff: $!";
+ my $patch = $repo->command_output_pipe('diff-tree', '-M50', '-r', '--name-status', '-z', $rev);
local $/ = "\0";
my %bound;
@@ -227,7 +224,7 @@ sub find_parent_renames {
}
}
}
- close($patch);
+ $repo->command_close_pipe($patch);
return \%bound;
}
@@ -236,14 +233,9 @@ sub find_parent_renames {
sub git_find_parent {
my ($rev, $filename) = @_;
- my $revparent = open_pipe("git-rev-list","--remove-empty", "--parents","--max-count=1","$rev","--",$filename)
- or die "Failed to open git-rev-list to find a single parent: $!";
-
- my $parentline = <$revparent>;
- chomp $parentline;
- my ($revfound,$parent) = split m/\s+/, $parentline;
-
- close($revparent);
+ my $parentline = $repo->command_oneline('rev-list', '--remove-empty',
+ '--parents', '--max-count=1', $rev, '--', $filename);
+ my ($revfound, $parent) = split m/\s+/, $parentline;
return $parent;
}
@@ -254,13 +246,13 @@ # Record the commit information that res
sub git_diff_parse {
my ($parent, $rev, %revinfo) = @_;
- my $diff = open_pipe("git-diff-tree","-M","-p",$rev,$parent,"--",
- $revs{$rev}{'filename'}, $revs{$parent}{'filename'})
- or die "Failed to call git-diff for annotation: $!";
+ my $diff = $repo->command_output_pipe('diff-tree', '-M', '-p',
+ $rev, $parent, '--',
+ $revs{$rev}{'filename'}, $revs{$parent}{'filename'});
_git_diff_parse($diff, $parent, $rev, %revinfo);
- close($diff);
+ $repo->command_close_pipe($diff);
}
sub _git_diff_parse {
@@ -351,36 +343,25 @@ sub git_cat_file {
my $blob = git_ls_tree($rev, $filename);
die "Failed to find a blob for $filename in rev $rev\n" if !defined $blob;
- my $catfile = open_pipe("git","cat-file", "blob", $blob)
- or die "Failed to git-cat-file blob $blob (rev $rev, file $filename): " . $!;
-
- my @lines;
- while(<$catfile>) {
- chomp;
- push @lines, $_;
- }
- close($catfile);
-
+ my @lines = split(/\n/, $repo->get_object('blob', $blob));
+ pop @lines unless $lines[$#lines]; # Trailing newline
return @lines;
}
sub git_ls_tree {
my ($rev, $filename) = @_;
- my $lstree = open_pipe("git","ls-tree",$rev,$filename)
- or die "Failed to call git ls-tree: $!";
-
+ my $lstree = $repo->command_output_pipe('ls-tree', $rev, $filename);
my ($mode, $type, $blob, $tfilename);
while(<$lstree>) {
chomp;
($mode, $type, $blob, $tfilename) = split(/\s+/, $_, 4);
last if ($tfilename eq $filename);
}
- close($lstree);
+ $repo->command_close_pipe($lstree);
return $blob if ($tfilename eq $filename);
die "git-ls-tree failed to find blob for $filename";
-
}
@@ -396,25 +377,17 @@ sub claim_line {
sub git_commit_info {
my ($rev) = @_;
- my $commit = open_pipe("git-cat-file", "commit", $rev)
- or die "Failed to call git-cat-file: $!";
+ my $commit = $repo->get_object('commit', $rev);
my %info;
- while(<$commit>) {
- chomp;
- last if (length $_ == 0);
-
- if (m/^author (.*) <(.*)> (.*)$/) {
- $info{'author'} = $1;
- $info{'author_email'} = $2;
- $info{'author_date'} = $3;
- } elsif (m/^committer (.*) <(.*)> (.*)$/) {
- $info{'committer'} = $1;
- $info{'committer_email'} = $2;
- $info{'committer_date'} = $3;
+ while ($commit =~ /(.*?)\n/g) {
+ my $line = $1;
+ if ($line =~ s/^author //) {
+ @info{'author', 'author_email', 'author_date'} = $repo->ident($line);
+ } elsif ($line =~ s/^committer//) {
+ @info{'committer', 'committer_email', 'committer_date'} = $repo->ident($line);
}
}
- close($commit);
return %info;
}
@@ -432,81 +405,3 @@ sub format_date {
my $t = $timestamp + $minutes * 60;
return strftime("%Y-%m-%d %H:%M:%S " . $timezone, gmtime($t));
}
-
-# Copied from git-send-email.perl - We need a Git.pm module..
-sub gitvar {
- my ($var) = @_;
- my $fh;
- my $pid = open($fh, '-|');
- die "$!" unless defined $pid;
- if (!$pid) {
- exec('git-var', $var) or die "$!";
- }
- my ($val) = <$fh>;
- close $fh or die "$!";
- chomp($val);
- return $val;
-}
-
-sub gitvar_name {
- my ($name) = @_;
- my $val = gitvar($name);
- my @field = split(/\s+/, $val);
- return join(' ', @field[0...(@field-4)]);
-}
-
-sub open_pipe {
- if ($^O eq '##INSERT_ACTIVESTATE_STRING_HERE##') {
- return open_pipe_activestate(@_);
- } else {
- return open_pipe_normal(@_);
- }
-}
-
-sub open_pipe_activestate {
- tie *fh, "Git::ActiveStatePipe", @_;
- return *fh;
-}
-
-sub open_pipe_normal {
- my (@execlist) = @_;
-
- my $pid = open my $kid, "-|";
- defined $pid or die "Cannot fork: $!";
-
- unless ($pid) {
- exec @execlist;
- die "Cannot exec @execlist: $!";
- }
-
- return $kid;
-}
-
-package Git::ActiveStatePipe;
-use strict;
-
-sub TIEHANDLE {
- my ($class, @params) = @_;
- my $cmdline = join " ", @params;
- my @data = qx{$cmdline};
- bless { i => 0, data => \@data }, $class;
-}
-
-sub READLINE {
- my $self = shift;
- if ($self->{i} >= scalar @{$self->{data}}) {
- return undef;
- }
- return $self->{'data'}->[ $self->{i}++ ];
-}
-
-sub CLOSE {
- my $self = shift;
- delete $self->{data};
- delete $self->{i};
-}
-
-sub EOF {
- my $self = shift;
- return ($self->{i} >= scalar @{$self->{data}});
-}
^ permalink raw reply related
* [PATCH 5/6] Git.pm: Introduce fast get_object() method
From: Petr Baudis @ 2006-07-03 20:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <20060703204415.28541.47920.stgit@machine.or.cz>
Direct .xs routine. Note that it does not work 100% correctly when
you juggle multiple repository objects, but it is not that bad either.
The trouble is that we might reuse packs information for another
Git project; that is not an issue since Git depends on uniqueness
of SHA1 ids so if we have found the object somewhere else, it is
nevertheless going to be the same object. It merely makes object
existence detection through this method unreliable; it is duly noted
in the documentation.
At least that's how I see it, I hope I didn't overlook any other
potential problem. I tested it for memory leaks and it appears to be
doing ok.
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
perl/Git.pm | 18 ++++++++++++++++++
perl/Git.xs | 24 ++++++++++++++++++++++++
2 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/perl/Git.pm b/perl/Git.pm
index 895a939..65acaa7 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -571,6 +571,24 @@ sub ident_person {
}
+=item get_object ( TYPE, SHA1 )
+
+Return contents of the given object in a scalar string. If the object has
+not been found, undef is returned; however, do not rely on this! Currently,
+if you use multiple repositories at once, get_object() on one repository
+_might_ return the object even though it exists only in another repository.
+(But do not rely on this behaviour either.)
+
+The method must be called on a repository instance.
+
+Implementation of this method is very fast; no external command calls
+are involved. That's why it is broken, too. ;-)
+
+=cut
+
+# Implemented in Git.xs.
+
+
=item hash_object ( TYPE, FILENAME )
=item hash_object ( TYPE, FILEHANDLE )
diff --git a/perl/Git.xs b/perl/Git.xs
index 6ed26a2..226dd4f 100644
--- a/perl/Git.xs
+++ b/perl/Git.xs
@@ -111,6 +111,30 @@ CODE:
free((char **) argv);
}
+
+SV *
+xs_get_object(type, id)
+ char *type;
+ char *id;
+CODE:
+{
+ unsigned char sha1[20];
+ unsigned long size;
+ void *buf;
+
+ if (strlen(id) != 40 || get_sha1_hex(id, sha1) < 0)
+ XSRETURN_UNDEF;
+
+ buf = read_sha1_file(sha1, type, &size);
+ if (!buf)
+ XSRETURN_UNDEF;
+ RETVAL = newSVpvn(buf, size);
+ free(buf);
+}
+OUTPUT:
+ RETVAL
+
+
char *
xs_hash_object_pipe(type, fd)
char *type;
^ permalink raw reply related
* [PATCH 4/6] Make it possible to set up libgit directly (instead of from the environment)
From: Petr Baudis @ 2006-07-03 20:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <20060703204415.28541.47920.stgit@machine.or.cz>
This introduces a setup_git() function which is essentialy a (public)
backend for setup_git_env() which lets anyone specify custom sources
for the various paths instead of environment variables. Since the repositories
may get switched on the fly, this also updates code that caches paths to
invalidate them properly; I hope neither of those is a sweet spot.
It is used by Git.xs' xs__call_gate() to set up per-repository data
for libgit's consumption. No code actually takes advantage of it yet
but get_object() will in the next patches.
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
cache.h | 3 +++
commit.c | 23 +++++++++++++++++++----
environment.c | 45 +++++++++++++++++++++++++++++++++++++++------
perl/Git.pm | 8 ++++----
perl/Git.xs | 16 +++++++++++++++-
sha1_file.c | 30 ++++++++++++++++++++++++------
sha1_name.c | 10 ++++++++--
7 files changed, 112 insertions(+), 23 deletions(-)
diff --git a/cache.h b/cache.h
index 8719939..962f2fc 100644
--- a/cache.h
+++ b/cache.h
@@ -116,6 +116,9 @@ extern struct cache_entry **active_cache
extern unsigned int active_nr, active_alloc, active_cache_changed;
extern struct cache_tree *active_cache_tree;
+extern void setup_git(char *new_git_dir, char *new_git_object_dir,
+ char *new_git_index_file, char *new_git_graft_file);
+
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
diff --git a/commit.c b/commit.c
index a608faf..91f97c1 100644
--- a/commit.c
+++ b/commit.c
@@ -163,6 +163,14 @@ int register_commit_graft(struct commit_
return 0;
}
+void free_commit_grafts(void)
+{
+ int pos = commit_graft_nr;
+ while (pos >= 0)
+ free(commit_graft[pos--]);
+ commit_graft_nr = 0;
+}
+
struct commit_graft *read_graft_line(char *buf, int len)
{
/* The format is just "Commit Parent1 Parent2 ...\n" */
@@ -215,11 +223,18 @@ int read_graft_file(const char *graft_fi
static void prepare_commit_graft(void)
{
static int commit_graft_prepared;
- char *graft_file;
+ static char *last_graft_file;
+ char *graft_file = get_graft_file();
+
+ if (last_graft_file) {
+ if (!strcmp(graft_file, last_graft_file))
+ return;
+ free_commit_grafts();
+ }
+ if (last_graft_file)
+ free(last_graft_file);
+ last_graft_file = strdup(graft_file);
- if (commit_graft_prepared)
- return;
- graft_file = get_graft_file();
read_graft_file(graft_file);
commit_graft_prepared = 1;
}
diff --git a/environment.c b/environment.c
index 3de8eb3..6b64d11 100644
--- a/environment.c
+++ b/environment.c
@@ -21,28 +21,61 @@ char git_commit_encoding[MAX_ENCODING_LE
int shared_repository = PERM_UMASK;
const char *apply_default_whitespace = NULL;
+static int dyn_git_object_dir, dyn_git_index_file, dyn_git_graft_file;
static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
*git_graft_file;
-static void setup_git_env(void)
+
+void setup_git(char *new_git_dir, char *new_git_object_dir,
+ char *new_git_index_file, char *new_git_graft_file)
{
- git_dir = getenv(GIT_DIR_ENVIRONMENT);
+ git_dir = new_git_dir;
if (!git_dir)
git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
- git_object_dir = getenv(DB_ENVIRONMENT);
+
+ if (dyn_git_object_dir)
+ free(git_object_dir);
+ git_object_dir = new_git_object_dir;
if (!git_object_dir) {
git_object_dir = xmalloc(strlen(git_dir) + 9);
sprintf(git_object_dir, "%s/objects", git_dir);
+ dyn_git_object_dir = 1;
+ } else {
+ dyn_git_object_dir = 0;
}
+
+ if (git_refs_dir)
+ free(git_refs_dir);
git_refs_dir = xmalloc(strlen(git_dir) + 6);
sprintf(git_refs_dir, "%s/refs", git_dir);
- git_index_file = getenv(INDEX_ENVIRONMENT);
+
+ if (dyn_git_index_file)
+ free(git_index_file);
+ git_index_file = new_git_index_file;
if (!git_index_file) {
git_index_file = xmalloc(strlen(git_dir) + 7);
sprintf(git_index_file, "%s/index", git_dir);
+ dyn_git_index_file = 1;
+ } else {
+ dyn_git_index_file = 0;
}
- git_graft_file = getenv(GRAFT_ENVIRONMENT);
- if (!git_graft_file)
+
+ if (dyn_git_graft_file)
+ free(git_graft_file);
+ git_graft_file = new_git_graft_file;
+ if (!git_graft_file) {
git_graft_file = strdup(git_path("info/grafts"));
+ dyn_git_graft_file = 1;
+ } else {
+ dyn_git_graft_file = 0;
+ }
+}
+
+static void setup_git_env(void)
+{
+ setup_git(getenv(GIT_DIR_ENVIRONMENT),
+ getenv(DB_ENVIRONMENT),
+ getenv(INDEX_ENVIRONMENT),
+ getenv(GRAFT_ENVIRONMENT));
}
char *get_git_dir(void)
diff --git a/perl/Git.pm b/perl/Git.pm
index 9ce9fcd..895a939 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -92,6 +92,7 @@ increate nonwithstanding).
use Carp qw(carp croak); # but croak is bad - throw instead
use Error qw(:try);
use Cwd qw(abs_path);
+use Scalar::Util;
require XSLoader;
XSLoader::load('Git', $VERSION);
@@ -833,11 +834,10 @@ sub _call_gate {
if (defined $self) {
# XXX: We ignore the WorkingCopy! To properly support
# that will require heavy changes in libgit.
+ # For now, when we will need to do it we could temporarily
+ # chdir() there and then chdir() back after the call is done.
- # XXX: And we ignore everything else as well. libgit
- # at least needs to be extended to let us specify
- # the $GIT_DIR instead of looking it up in environment.
- #xs_call_gate($self->{opts}->{Repository});
+ xs__call_gate(Scalar::Util::refaddr($self), $self->repo_path());
}
# Having to call throw from the C code is a sure path to insanity.
diff --git a/perl/Git.xs b/perl/Git.xs
index 2bbec43..6ed26a2 100644
--- a/perl/Git.xs
+++ b/perl/Git.xs
@@ -52,7 +52,21 @@ BOOT:
}
-# /* TODO: xs_call_gate(). See Git.pm. */
+void
+xs__call_gate(repoid, git_dir)
+ long repoid;
+ char *git_dir;
+CODE:
+{
+ static long last_repoid;
+ if (repoid != last_repoid) {
+ setup_git(git_dir,
+ getenv(DB_ENVIRONMENT),
+ getenv(INDEX_ENVIRONMENT),
+ getenv(GRAFT_ENVIRONMENT));
+ last_repoid = repoid;
+ }
+}
char *
diff --git a/sha1_file.c b/sha1_file.c
index 8179630..ab64543 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -126,16 +126,22 @@ static void fill_sha1_path(char *pathbuf
char *sha1_file_name(const unsigned char *sha1)
{
static char *name, *base;
+ static const char *last_objdir;
+ const char *sha1_file_directory = get_object_directory();
- if (!base) {
- const char *sha1_file_directory = get_object_directory();
+ if (!last_objdir || strcmp(last_objdir, sha1_file_directory)) {
int len = strlen(sha1_file_directory);
+ if (base)
+ free(base);
base = xmalloc(len + 60);
memcpy(base, sha1_file_directory, len);
memset(base+len, 0, 60);
base[len] = '/';
base[len+3] = '/';
name = base + len + 1;
+ if (last_objdir)
+ free((char *) last_objdir);
+ last_objdir = strdup(sha1_file_directory);
}
fill_sha1_path(name, sha1);
return base;
@@ -145,14 +151,20 @@ char *sha1_pack_name(const unsigned char
{
static const char hex[] = "0123456789abcdef";
static char *name, *base, *buf;
+ static const char *last_objdir;
+ const char *sha1_file_directory = get_object_directory();
int i;
- if (!base) {
- const char *sha1_file_directory = get_object_directory();
+ if (!last_objdir || strcmp(last_objdir, sha1_file_directory)) {
int len = strlen(sha1_file_directory);
+ if (base)
+ free(base);
base = xmalloc(len + 60);
sprintf(base, "%s/pack/pack-1234567890123456789012345678901234567890.pack", sha1_file_directory);
name = base + len + 11;
+ if (last_objdir)
+ free((char *) last_objdir);
+ last_objdir = strdup(sha1_file_directory);
}
buf = name;
@@ -170,14 +182,20 @@ char *sha1_pack_index_name(const unsigne
{
static const char hex[] = "0123456789abcdef";
static char *name, *base, *buf;
+ static const char *last_objdir;
+ const char *sha1_file_directory = get_object_directory();
int i;
- if (!base) {
- const char *sha1_file_directory = get_object_directory();
+ if (!last_objdir || strcmp(last_objdir, sha1_file_directory)) {
int len = strlen(sha1_file_directory);
+ if (base)
+ free(base);
base = xmalloc(len + 60);
sprintf(base, "%s/pack/pack-1234567890123456789012345678901234567890.idx", sha1_file_directory);
name = base + len + 11;
+ if (last_objdir)
+ free((char *) last_objdir);
+ last_objdir = strdup(sha1_file_directory);
}
buf = name;
diff --git a/sha1_name.c b/sha1_name.c
index f2cbafa..c698c1b 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -12,15 +12,21 @@ static int find_short_object_filename(in
char hex[40];
int found = 0;
static struct alternate_object_database *fakeent;
+ static const char *last_objdir;
+ const char *objdir = get_object_directory();
- if (!fakeent) {
- const char *objdir = get_object_directory();
+ if (!last_objdir || strcmp(last_objdir, objdir)) {
int objdir_len = strlen(objdir);
int entlen = objdir_len + 43;
+ if (fakeent)
+ free(fakeent);
fakeent = xmalloc(sizeof(*fakeent) + entlen);
memcpy(fakeent->base, objdir, objdir_len);
fakeent->name = fakeent->base + objdir_len + 1;
fakeent->name[-1] = '/';
+ if (last_objdir)
+ free((char *) last_objdir);
+ last_objdir = strdup(objdir);
}
fakeent->next = alt_odb_list;
^ permalink raw reply related
* [PATCH 2/6] Convert git-send-email to use Git.pm
From: Petr Baudis @ 2006-07-03 20:47 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <20060703204415.28541.47920.stgit@machine.or.cz>
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
git-send-email.perl | 30 ++++++++----------------------
1 files changed, 8 insertions(+), 22 deletions(-)
diff --git a/git-send-email.perl b/git-send-email.perl
index c5d9e73..e794e44 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -21,6 +21,7 @@ use warnings;
use Term::ReadLine;
use Getopt::Long;
use Data::Dumper;
+use Git;
# most mail servers generate the Date: header, but not all...
$ENV{LC_ALL} = 'C';
@@ -46,6 +47,8 @@ my $smtp_server;
# Example reply to:
#$initial_reply_to = ''; #<20050203173208.GA23964@foobar.com>';
+my $repo = Git->repository();
+
my $term = new Term::ReadLine 'git-send-email';
# Begin by accumulating all the variables (defined above), that we will end up
@@ -81,23 +84,9 @@ foreach my $entry (@bcclist) {
# Now, let's fill any that aren't set in with defaults:
-sub gitvar {
- my ($var) = @_;
- my $fh;
- my $pid = open($fh, '-|');
- die "$!" unless defined $pid;
- if (!$pid) {
- exec('git-var', $var) or die "$!";
- }
- my ($val) = <$fh>;
- close $fh or die "$!";
- chomp($val);
- return $val;
-}
-
sub gitvar_ident {
my ($name) = @_;
- my $val = gitvar($name);
+ my $val = $repo->command('var', $name);
my @field = split(/\s+/, $val);
return join(' ', @field[0...(@field-3)]);
}
@@ -106,8 +95,8 @@ my ($author) = gitvar_ident('GIT_AUTHOR_
my ($committer) = gitvar_ident('GIT_COMMITTER_IDENT');
my %aliases;
-chomp(my @alias_files = `git-repo-config --get-all sendemail.aliasesfile`);
-chomp(my $aliasfiletype = `git-repo-config sendemail.aliasfiletype`);
+my @alias_files = $repo->config('sendemail.aliasesfile');
+my $aliasfiletype = $repo->config('sendemail.aliasfiletype');
my %parse_alias = (
# multiline formats can be supported in the future
mutt => sub { my $fh = shift; while (<$fh>) {
@@ -132,7 +121,7 @@ my %parse_alias = (
}}}
);
-if (@alias_files && defined $parse_alias{$aliasfiletype}) {
+if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {
foreach my $file (@alias_files) {
open my $fh, '<', $file or die "opening $file: $!\n";
$parse_alias{$aliasfiletype}->($fh);
@@ -374,10 +363,7 @@ sub send_message
my $date = strftime('%a, %d %b %Y %H:%M:%S %z', localtime($time++));
my $gitversion = '@@GIT_VERSION@@';
if ($gitversion =~ m/..GIT_VERSION../) {
- $gitversion = `git --version`;
- chomp $gitversion;
- # keep only what's after the last space
- $gitversion =~ s/^.* //;
+ $gitversion = Git::version();
}
my $header = "From: $from
^ permalink raw reply related
* Re: [PATCH 1/3] Add read_cache_from() and discard_cache()
From: Junio C Hamano @ 2006-07-03 21:04 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0607021043550.29667@wbgn013.biozentrum.uni-wuerzburg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Okay. After reading the comment, I am quite certain we can just set the
> index_file_timestamp to 0.
Thanks.
> So, I still think that these two lines should be in the cleanup part of
> get_merge_bases().
I think that is sane -- please make it so.
> BTW personally, I prefer the one-function approach, i.e. a flag which says
> if it is okay not to clean up.
Yup. Agreed.
^ 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