* Re: Roadmap for 1.7.9
From: Ævar Arnfjörð Bjarmason @ 2011-12-05 21:24 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7vd3c2lr36.fsf@alter.siamese.dyndns.org>
On Mon, Dec 5, 2011 at 21:07, Junio C Hamano <gitster@pobox.com> wrote:
> Now, here are the biggies that we would want to try to have in reasonable
> shape before the next release.
I'd like to get the i18n series into 1.7.9 as well. I think it's ready
as-is but some minor issues are sure to arise.
If time permits I'd also like to have a series of po/*.po files in as
well once it's in "master". Maybe as a submodule, which would be neat
in itself as we'd start dogfooding submodules.
^ permalink raw reply
* Re: hooks that do not consume stdin sometimes crash git with SIGPIPE
From: Jeff King @ 2011-12-05 21:43 UTC (permalink / raw)
To: Joey Hess; +Cc: git, Lars Wirzenius
In-Reply-To: <20111205192930.GA32463@gnu.kitenet.net>
On Mon, Dec 05, 2011 at 03:29:30PM -0400, Joey Hess wrote:
> We had a weird problem where, after moving to a new, faster server,
> "git push" would sometimes fail like this:
>
> Unpacking objects: 100% (3/3), done.
> fatal: The remote end hung up unexpectedly
> fatal: The remote end hung up unexpectedly
>
> Turns out that git-receive-pack was dying due to an uncaught SIGPIPE.
> The SIGPIPE occurred when it tried to write to the pre-receive hook's
> stdin. The pre-receive hook, in this case, was able to do all the checks
> it needed to do[1] without the input, and so did exit(0) without
> consuming it.
Ugh. Yeah, receive-pack should probably just be ignoring SIGPIPE
entirely. It checks the return from write() properly where it matters,
so SIGPIPE is just an annoyance.
I would go so far as to say that git should be ignoring SIGPIPE 99% of
the time. We have crap like this sprinkled throughout the code base:
$ git grep -C1 SIGPIPE
builtin/tag.c- /* When the username signingkey is bad, program could be terminated
builtin/tag.c: * because gpg exits without reading and then write gets SIGPIPE. */
builtin/tag.c: signal(SIGPIPE, SIG_IGN);
[...]
upload-pack.c- * If rev-list --stdin encounters an unknown commit, it
upload-pack.c: * terminates, which will cause SIGPIPE in the write loop
upload-pack.c- */
upload-pack.c: sigchain_push(SIGPIPE, SIG_IGN);
but I find it highly unlikely that they are covering all of the cases.
You found one already, and these things can quite often be
race-condition heisenbugs.
The one place where SIGPIPE _is_ useful is for things like "git log"
which are just dumping to a pager over stdout. When the pager dies, we
can stop bothering to produce output.
It would be really nice if we could write a sigpipe handler that knew
which fd caused the the signal, and then we could do something like:
void sigpipe_handler(int sig)
{
/* If we're writing to a pager over stdout, then there is
* little use in writing more; nobody is interested in our
* output. */
if (get_fd_that_caused_sigpipe() == 1 && pager_in_use)
exit(1);
/* Otherwise, ignore it, as it's a write to some auxiliary
* process and we will be careful about checking the return
* code from write(). */
}
But I don't think such a function exists. We could just check
pager_in_use, which would cover most cases (e.g., programs like
receive-pack don't use a pager). But it would fail in the case of
something like "git log" using an auxiliary process that closes the pipe
early. Maybe that would be good enough, though. I dunno.
Another option is to just ignore SIGPIPE entirely, and convince programs
like log to actually bother checking the result of write(). It would be
a slight pain to check every printf() call we make in log-tree.c, but we
could do one of:
1. Make a set of stdio wrapper scripts that exit gracefully on EPIPE.
Using the wrapper scripts everywhere is a slight pain, but would
work pretty well, and adapts easily to other places like printing
lists of refs, etc.
2. Don't check every printf. After printing each commit, check
ferror(stdout) and exit as appropriate. This is a very small amount
of code, but you'd need to do it in several places (i.e., anywhere
that produces a lot of output).
> I think git should ignore SIGPIPE when writing to hooks. Otherwise,
> hooks may have to go out of their way to consume all input, and as I've
> seen, the races when they fail to do this can lurk undiscovered.
Yeah, certainly. The question to me is whether we should just stick a
SIG_IGN in the beginning of receive-pack, or whether we should try to
deal with this problem everywhere.
For example, I suspect the same problem exists in the credential helpers
I wrote recently. Generally they will read all of their input, but you
could do something like:
[credential "https://github.com"]
username = peff
helper = "!
f() {
# if we call this helper, we know we want the
# github password, or else this helper config
# would never have been triggered. so we
# don't even have to bother reading our stdin.
# We only handle getting the password.
test "$1" = "get" || return
# Presumably gpg-agent will ask for and cache
# your gpg password.
p=`gpg -qd --no-tty <~/.github-password.gpg`
echo "password=$p"
}; f"
This can racily fail if our write happens after the helper has already
finished (unlikely, but possible).
-Peff
^ permalink raw reply
* Re: [PATCH, v4] git-tag: introduce --cleanup option
From: Jeff King @ 2011-12-05 21:51 UTC (permalink / raw)
To: Kirill A. Shutemov; +Cc: git, Junio C Hamano
In-Reply-To: <1322972426-7591-1-git-send-email-kirill@shutemov.name>
On Sun, Dec 04, 2011 at 06:20:26AM +0200, Kirill A. Shutemov wrote:
> From: "Kirill A. Shutemov" <kirill@shutemov.name>
>
> Normally git tag stripes tag message lines starting with '#', trailing
> spaces from every line and empty lines from the beginning and end.
s/stripes/strips
> --cleanup allows to select different cleanup modes for tag message.
> It provides the same interface as --cleanup option in git-commit.
Thanks, I think this is better, though it would be better still if they
could share the code. As a minor nit, I think the patch would be a
little easier to read and review if you split the actual changes from
the refactoring to use the "struct create_tag_options".
More importantly, though, this seems to break t6300 badly. I haven't
looked into why yet, though.
-Peff
^ permalink raw reply
* Re: [PATCH, v4] git-tag: introduce --cleanup option
From: Jeff King @ 2011-12-05 22:27 UTC (permalink / raw)
To: Kirill A. Shutemov; +Cc: git, Junio C Hamano
In-Reply-To: <1322972426-7591-1-git-send-email-kirill@shutemov.name>
On Sun, Dec 04, 2011 at 06:20:26AM +0200, Kirill A. Shutemov wrote:
> @@ -367,14 +390,15 @@ static void create_tag(const unsigned char *object, const char *tag,
> [...]
> - if (!message && !buf->len)
> + if (opt->message && !buf->len)
> die(_("no tag message?"));
Ah, this is the hunk that causes t6300 to fail. You accidentally removed
the negation when converting the "message" flag over.
This was much easier to find by splitting the refactoring (where the bug
is) away from the new feature (which is where I assumed the bug was).
Here's the first half of the "split". You can rebase your original patch
on top to get the second half.
I also looked at factoring out the "which cleanup mode to select" logic
from builtin/commit.c, but it turned out to just make things harder to
follow.
-- >8 --
From: "Kirill A. Shutemov" <kirill@shutemov.name>
Subject: [PATCH] tag: refactor passing tag creation options
Rather than continually adding parameters to the create_tag
function, we can put all of the flags in a struct.
Signed-off-by: Jeff King <peff@peff.net>
---
Actually, I'm not sure this really buys us much as a refactoring. It
saves a parameter in the function, but it's not like we end up passing
all those parameters to sub-functions, where something like this would
increase readability. I'm fine with this, but I'd also be fine with just
dropping this half and passing the cleanup_mode parameter directly.
builtin/tag.c | 32 ++++++++++++++++++++------------
1 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/builtin/tag.c b/builtin/tag.c
index 9b6fd95..e5bd708 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -319,8 +319,13 @@ static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
return 0;
}
+struct create_tag_options {
+ unsigned int message;
+ unsigned int sign;
+};
+
static void create_tag(const unsigned char *object, const char *tag,
- struct strbuf *buf, int message, int sign,
+ struct strbuf *buf, struct create_tag_options *opt,
unsigned char *prev, unsigned char *result)
{
enum object_type type;
@@ -345,7 +350,7 @@ static void create_tag(const unsigned char *object, const char *tag,
if (header_len > sizeof(header_buf) - 1)
die(_("tag header too big."));
- if (!message) {
+ if (!opt->message) {
int fd;
/* write the template message before editing: */
@@ -369,12 +374,12 @@ static void create_tag(const unsigned char *object, const char *tag,
stripspace(buf, 1);
- if (!message && !buf->len)
+ if (!opt->message && !buf->len)
die(_("no tag message?"));
strbuf_insert(buf, 0, header_buf, header_len);
- if (build_tag_object(buf, sign, result) < 0) {
+ if (build_tag_object(buf, opt->sign, result) < 0) {
if (path)
fprintf(stderr, _("The tag message has been left in %s\n"),
path);
@@ -422,9 +427,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
unsigned char object[20], prev[20];
const char *object_ref, *tag;
struct ref_lock *lock;
-
- int annotate = 0, sign = 0, force = 0, lines = -1,
- list = 0, delete = 0, verify = 0;
+ struct create_tag_options opt;
+ int annotate = 0, force = 0, lines = -1, list = 0,
+ delete = 0, verify = 0;
const char *msgfile = NULL, *keyid = NULL;
struct msg_arg msg = { 0, STRBUF_INIT };
struct commit_list *with_commit = NULL;
@@ -442,7 +447,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_CALLBACK('m', "message", &msg, "message",
"tag message", parse_msg_arg),
OPT_FILENAME('F', "file", &msgfile, "read message from file"),
- OPT_BOOLEAN('s', "sign", &sign, "annotated and GPG-signed tag"),
+ OPT_BOOLEAN('s', "sign", &opt.sign, "annotated and GPG-signed tag"),
OPT_STRING('u', "local-user", &keyid, "key-id",
"use another key to sign the tag"),
OPT__FORCE(&force, "replace the tag if exists"),
@@ -459,13 +464,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
git_config(git_tag_config, NULL);
+ opt.sign = 0;
+
argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
if (keyid) {
- sign = 1;
+ opt.sign = 1;
set_signingkey(keyid);
}
- if (sign)
+ if (opt.sign)
annotate = 1;
if (argc == 0 && !(delete || verify))
list = 1;
@@ -523,9 +530,10 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
else if (!force)
die(_("tag '%s' already exists"), tag);
+ opt.message = msg.given || msgfile;
+
if (annotate)
- create_tag(object, tag, &buf, msg.given || msgfile,
- sign, prev, object);
+ create_tag(object, tag, &buf, &opt, prev, object);
lock = lock_any_ref_for_update(ref.buf, prev, 0);
if (!lock)
--
1.7.8.rc4.4.g884ec
^ permalink raw reply related
* Re: [PATCH, v4] git-tag: introduce --cleanup option
From: Jeff King @ 2011-12-05 22:29 UTC (permalink / raw)
To: Kirill A. Shutemov; +Cc: git, Junio C Hamano
In-Reply-To: <20111205222724.GA7603@sigill.intra.peff.net>
On Mon, Dec 05, 2011 at 05:27:24PM -0500, Jeff King wrote:
> I also looked at factoring out the "which cleanup mode to select" logic
> from builtin/commit.c, but it turned out to just make things harder to
> follow.
While I was doing that, I also noticed this minor fix:
-- >8 --
Subject: [PATCH] stripspace: fix outdated comment
The comment on top of stripspace() claims that the buffer
will no longer be NUL-terminated. However, this has not been
the case at least since the move to using strbuf in 2007.
Signed-off-by: Jeff King <peff@peff.net>
---
builtin/stripspace.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/builtin/stripspace.c b/builtin/stripspace.c
index 4d3b93f..1288ffc 100644
--- a/builtin/stripspace.c
+++ b/builtin/stripspace.c
@@ -22,8 +22,6 @@ static size_t cleanup(char *line, size_t len)
* Remove empty lines from the beginning and end
* and also trailing spaces from every line.
*
- * Note that the buffer will not be NUL-terminated.
- *
* Turn multiple consecutive empty lines between paragraphs
* into just one empty line.
*
--
1.7.8.rc4.4.g884ec
^ permalink raw reply related
* Re: [PATCH, v4] git-tag: introduce --cleanup option
From: Junio C Hamano @ 2011-12-05 22:30 UTC (permalink / raw)
To: Jeff King; +Cc: Kirill A. Shutemov, git
In-Reply-To: <20111205215148.GA22663@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> More importantly, though, this seems to break t6300 badly. I haven't
> looked into why yet, though.
Also breaks 7004 which is _about_ tags.
Rolling a broken patch in quick succession to v4 without ever running
tests (and not adding new test pieces to protect new feature) is not a
very productive way to use the reviewer bandwidth on this list.
^ permalink raw reply
* Re: [PATCH 2/2] builtin/apply.c: report error on failure to recognize input
From: Brandon Casey @ 2011-12-05 22:38 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, artem.bityutskiy
In-Reply-To: <7vzkf6lsyx.fsf@alter.siamese.dyndns.org>
On Mon, Dec 5, 2011 at 1:27 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Brandon Casey <drafnel@gmail.com> writes:
>
>> When git apply is passed something that is not a patch, it does not produce
>> an error message or exit with a non-zero status if it was not actually
>> "applying" the patch i.e. --check or --numstat etc were supplied on the
>> command line.
>>
>> Fix this by producing an error when apply fails to find any hunks whatsoever
>> while parsing the patch.
>>
>> This will cause some of the output formats (--numstat, --diffstat, etc) to
>> produce an error when they formerly would have reported zero changes and
>> exited successfully. That seems like the correct behavior though. Failure
>> to recognize the input as a patch should be an error.
>>
>> Plus, add a test.
>>
>> Reported-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
>> Signed-off-by: Brandon Casey <drafnel@gmail.com>
>> ---
>>
>> Initially, I was reluctant to change the error message, thinking that
>> error messages for plumbing commands were not supposed to change. But I
>> think I was wrong in that thought, so I changed the error message so it
>> was a more descriptive "unrecognized input".
>
> I am still reluctant to see
>
> $ git apply </dev/null
> error: unrecognized input
>
> instead of "error: No changes", though.
I'm not partial to "unrecognized input", but I thought it was more
descriptive of what happened than "No changes". This error message is
only printed out when absolutely no hunks were found while parsing the
input.
> "git apply --check" is about asking "do you see anything offending in the
> diff?" and it is not "git apply --dry-run" that asks "do you promise if I
> feed this for real to you you will apply it without complaint?".
>
> I am slightly in favor of answering "well you do not have a diff to begin
> with, which in itself is suspicious" to "do you see anything offending?"
> question, but I have to admit that it is an equally valid answer to say
> "no, there is nothing offending in the diff.", which is what we do with
> the current code.
>
> So, I dunno.
I think the current code is a little inconsistent with respect to
empty or bogus non-diff input.
It seems more consistent that if it is an error to tell git apply to
apply zero hunks, then it is also an error to --check zero hunks, or
--stat etc. In all cases the cause is the same: failure to find any
hunks in the input because the input was not a diff.
Also, the man page description of --check says that it checks "if the
patch is applicable to the current working tree and/or the index".
The new behavior would answer that with "no, this patch is not
applicable ... since no hunks were found", rather than "yes, because
no hunks were found". But I'm really arguing on the side of
"unrecognized input should be an error", since the new behavior would
also be an error for --stat, --numstat, etc.
-Brandon
^ permalink raw reply
* Re: [PATCH, v4] git-tag: introduce --cleanup option
From: Junio C Hamano @ 2011-12-05 22:41 UTC (permalink / raw)
To: Jeff King; +Cc: Kirill A. Shutemov, git
In-Reply-To: <20111205215148.GA22663@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> More importantly, though, this seems to break t6300 badly. I haven't
> looked into why yet, though.
Probably two issues.
- opt.message (and the original 'message') was misnamed and confused the
patch author what "if (!message && !buf->len)" meant.
- "opt" is a structure meant to be extensible, but is not initialized as
a whole, inviting future errors.
It still seems to be broken with respect to the primary thing the patch
wanted to do (t7400 "git tag -F commentsfile comments-annotated-tag" does
not seem to produce an expected result), so I'll kick it back to the
Kirill to look at.
Thanks.
builtin/tag.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/builtin/tag.c b/builtin/tag.c
index 27a66a3..7883720 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -329,7 +329,7 @@ static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
}
struct create_tag_options {
- unsigned int message;
+ unsigned int message_given:1;
unsigned int sign;
enum {
CLEANUP_NONE,
@@ -364,7 +364,7 @@ static void create_tag(const unsigned char *object, const char *tag,
if (header_len > sizeof(header_buf) - 1)
die(_("tag header too big."));
- if (!opt->message) {
+ if (!opt->message_given) {
int fd;
/* write the template message before editing: */
@@ -393,7 +393,7 @@ static void create_tag(const unsigned char *object, const char *tag,
if (opt->cleanup_mode != CLEANUP_NONE)
stripspace(buf, opt->cleanup_mode == CLEANUP_ALL);
- if (opt->message && !buf->len)
+ if (!opt->message_given && !buf->len)
die(_("no tag message?"));
strbuf_insert(buf, 0, header_buf, header_len);
@@ -486,7 +486,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
git_config(git_tag_config, NULL);
- opt.sign = 0;
+ memset(&opt, 0, sizeof(opt));
argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
@@ -552,10 +552,10 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
else if (!force)
die(_("tag '%s' already exists"), tag);
- opt.message = msg.given || msgfile;
+ opt.message_given = msg.given || msgfile;
if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
- opt.cleanup_mode = !opt.message ? CLEANUP_ALL : CLEANUP_SPACE;
+ opt.cleanup_mode = !opt.message_given ? CLEANUP_ALL : CLEANUP_SPACE;
else if (!strcmp(cleanup_arg, "verbatim"))
opt.cleanup_mode = CLEANUP_NONE;
else if (!strcmp(cleanup_arg, "whitespace"))
^ permalink raw reply related
* Re: Roadmap for 1.7.9
From: Junio C Hamano @ 2011-12-05 22:47 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason; +Cc: Git Mailing List
In-Reply-To: <CACBZZX6aC-E4DxaZzzhfGnK8ovBGCq_gNG3hPU7QjfAiNb3WrA@mail.gmail.com>
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> On Mon, Dec 5, 2011 at 21:07, Junio C Hamano <gitster@pobox.com> wrote:
>
>> Now, here are the biggies that we would want to try to have in reasonable
>> shape before the next release.
>
> I'd like to get the i18n series into 1.7.9 as well. I think it's ready
> as-is but some minor issues are sure to arise.
Surely.
My impression was that the part that can have interactions with the
existing codebase is already in, and it is just the matter of updating
what _() ans Q_() actually do, which can be reverted out quickly if it
turns out to be necessary, and that was why I didn't count it as part of
the "biggies" that make us worry.
^ permalink raw reply
* Yo dawg, I heard you like trees...
From: Sebastian Morr @ 2011-12-05 23:57 UTC (permalink / raw)
To: git
Just out of curiosity: Do you know of any attempts to construct a tree
object that contains itself, that is, references it's own SHA-1?
Sebastian
^ permalink raw reply
* Re: Roadmap for 1.7.9
From: Ævar Arnfjörð Bjarmason @ 2011-12-06 0:02 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7vr50ik55n.fsf@alter.siamese.dyndns.org>
On Mon, Dec 5, 2011 at 23:47, Junio C Hamano <gitster@pobox.com> wrote:
> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> On Mon, Dec 5, 2011 at 21:07, Junio C Hamano <gitster@pobox.com> wrote:
>>
>>> Now, here are the biggies that we would want to try to have in reasonable
>>> shape before the next release.
>>
>> I'd like to get the i18n series into 1.7.9 as well. I think it's ready
>> as-is but some minor issues are sure to arise.
>
> Surely.
>
> My impression was that the part that can have interactions with the
> existing codebase is already in, and it is just the matter of updating
> what _() ans Q_() actually do, which can be reverted out quickly if it
> turns out to be necessary, and that was why I didn't count it as part of
> the "biggies" that make us worry.
That's the gist of it. But it's still a massive 1300 line patch,
which:
* Calls setlocale(LC_MESSAGES)
* Uses an evil trick to only call setlocale(LC_CTYPE) while loading
message catalogs
* Might have some portability problems on more obscure OS's.
* Has some tests I've only tested on Linux, FreeBSD and Solaris
So it might have some little surprises, and it would be nice to have
it in master early on so we'll give it plenty of time to cook and
discover any issues before 1.7.9.
^ permalink raw reply
* Re: Yo dawg, I heard you like trees...
From: Andrew Ardill @ 2011-12-06 0:04 UTC (permalink / raw)
To: Sebastian Morr; +Cc: git
In-Reply-To: <20111205235740.GB27318@thinkpad>
The difficulty in doing this is essentially the same as breaking
SHA-1, so I doubt anyone has seriously tried to do it.
Regards,
Andrew Ardill
On 6 December 2011 10:57, Sebastian Morr <sebastian@morr.cc> wrote:
> Just out of curiosity: Do you know of any attempts to construct a tree
> object that contains itself, that is, references it's own SHA-1?
>
> Sebastian
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH v2 0/3] grep multithreading and scaling
From: Jeff King @ 2011-12-06 0:40 UTC (permalink / raw)
To: Thomas Rast; +Cc: René Scharfe, Eric Herman, git, Junio C Hamano
In-Reply-To: <201112051038.16423.trast@student.ethz.ch>
On Mon, Dec 05, 2011 at 10:38:16AM +0100, Thomas Rast wrote:
> I just found out that on Linux, there's mincore() that can tell us
> (racily, but who cares) whether a given file mapping is in memory. If
> you would like to try it, see the source at the end, but I'm getting
> things such as
Neat, I didn't know about mincore.
> So that looks fairly promising, and the order would then be:
>
> - if stat-clean, and we have mincore(), and it tells us we can do it
> cheaply: grab file from tree
>
> - if it's a loose object: decompress it
>
> - if stat-clean: grab file from tree
>
> - access packs as usual
I don't think your third one makes sense. If the working tree file isn't
stat clean, then either:
1. the pack file is in cache, and it's way faster than faulting in the
working tree file from disk
2. the pack file is not in cache, and it's a toss-up whether it is
faster to fault in the smaller compressed pack-file version and
uncompress it, or to fault in the larger on-disk version. The
exact result will depend on the ratio of CPU to disk speed, the
quality of your filesystem, and the size and contents of your file.
And possibly on the exact delta chains you have. Though this
optimization only happens when the file is in the index, which
usually means it's recent, which means it will tend to be at the
head of the delta chain.
So it probably just makes sense to grab the working tree file only if
mincore() tells us we have all (or most) of it, and otherwise go to the
packfile.
> Ok, I see, I missed that part. Perhaps the heuristic should then be
> "if the regex boils down to memmem, disable threading", but let's see
> what loose object decompression in parallel can give us.
Yeah. I'd really rather have parallel object decompression than some
complex Linux-only mincore optimization (even though that optimization
_could_ yield extra savings on top of properly threading, if the blob
retrieval is threaded, I think I'll care less about how much CPU time it
takes).
-Peff
^ permalink raw reply
* Re: Auto update submodules after merge and reset
From: Max Krasnyansky @ 2011-12-06 1:06 UTC (permalink / raw)
To: Jens Lehmann; +Cc: git
In-Reply-To: <4ED5E9D2.4060503@web.de>
Hi Jens,
On 11/30/2011 12:31 AM, Jens Lehmann wrote:
> I'm working on a patch series to teach Git to optionally update the
> submodules work trees on checkout, reset merge and so on, but I'm not
> there yet.
> [SNIP]
Sorry for not replying right away.
Everything you suggested sounds great. We're on the same page (config
option, etc).
How far along are you? Do you have a tree I could pull from to play with
things?
I could help with testing, bug fixes and/or implementing parts of it.
Let me know.
For now I implemented automatic submodules update using 'post-merge'
hook. But obviously it does
not handle reset and things. I'm thinking of adding 'post-reset' and
'pre-merge' that would be useful
for this and maybe other things.
Thanx
Max
^ permalink raw reply
* Re: [RFD] Handling of non-UTF8 data in gitweb
From: Jeff King @ 2011-12-06 1:07 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git, Jürgen Kreileder, John Hawley
In-Reply-To: <201112041709.32212.jnareb@gmail.com>
On Sun, Dec 04, 2011 at 05:09:30PM +0100, Jakub Narebski wrote:
> The correct solution would be of course to respect `gui.encoding`
> per-repository config variable, and `encoding` gitattribute...
> though the latter is hampered by the fact that there is currently
> no way to read attribute with "git check-attr" from a given tree:
> think of a diff of change of encoding of a file!
We deal with the same problem at GitHub.
There really isn't a good way to specify per-file encodings. Something
like gui.encoding is too coarse. As you mentioned, we don't do per-tree
gitattribute lookups, so the encoding attribute has problems when the
encoding of a file changes. But even if we implemented them, you still
have the problem of getting a raw sha1 (e.g., git diff 9624865 e0a3260).
There's no way to look up attributes for that.
It would be nice if you could put an "encoding" header into the blob
object. You could use the .gitattributes in place at "git add" time to
set it. And then at lookup time, you either have the encoding, or you
assume it's in utf8 (if it isn't binary, of course).
But there's no room in the blob format for headers; the content starts
right after the size header.
You can get around this by searching the history for a tree that
contains the blob, and then checking the gitattributes. It's expensive,
but you could build a cache over time. However, it's not guaranteed to
provide a single answer; you could have multiple trees that mention the
blobs, each with different attributes.
And even if you implement all that, we have the problem that older blobs
won't have gotten an encoding header, even if they would have under the
new rules. So rather than assuming utf8, you have to make a guess
anyway.
At GitHub, we talked about a lot of these options and ended up just
using an encoding-detection library to make a best guess. It seems to
work well in practice, but it's only been deployed for a couple of
months.
-Peff
^ permalink raw reply
* Re: [PATCH] git-svn.perl: close the edit for propedits even with no mods
From: Eric Wong @ 2011-12-06 1:10 UTC (permalink / raw)
To: Steven Walter; +Cc: git
In-Reply-To: <1322707047-24227-1-git-send-email-stevenrwalter@gmail.com>
Steven Walter <stevenrwalter@gmail.com> wrote:
> It's legitimate to update the mergeinfo property without
> actually changing any files. This can happen when changes are
> backported to a branch, and then that branch is merged back
> into mainline. We still want to record the updated mergeinfo
> for book-keeping.
>
> Signed-off-by: Steven Walter <stevenrwalter@gmail.com>
Acked-by: Eric Wong <normalperson@yhbt.net>
Pushed to "master" of git://bogomips.org/git-svn.git
(Btw, you got my email address wrong in the Cc:)
^ permalink raw reply
* Re: hooks that do not consume stdin sometimes crash git with SIGPIPE
From: Junio C Hamano @ 2011-12-06 1:39 UTC (permalink / raw)
To: Joey Hess; +Cc: git, Lars Wirzenius
In-Reply-To: <20111205192930.GA32463@gnu.kitenet.net>
Joey Hess <joey@kitenet.net> writes:
> We had a weird problem where, after moving to a new, faster server,
> "git push" would sometimes fail like this:
>
> Unpacking objects: 100% (3/3), done.
> fatal: The remote end hung up unexpectedly
> fatal: The remote end hung up unexpectedly
>
> Turns out that git-receive-pack was dying due to an uncaught SIGPIPE.
Why do you have a hook that is expected to read from receive-pack that
does _not_ read anything from it in the first place? If you do not care
about the update status given to pre-receive, shouldn't you be using the
update hook and ignoring the command line parameters instead?
I am not saying this is a user configuration error and there is nothing to
fix---Git shouldn't get killed merely because of configuration error.
I am wondering if we would want to have a uniform way to tell run_*_hook()
functions that the hook writer explicitly declines to get any input. E.g.
"hooks/pre-receive-noinput" is called instead of "hooks/pre-receive" and
we do not send any input to it, or something like that.
^ permalink raw reply
* Re: Suggestion on hashing
From: Chris West (Faux) @ 2011-12-06 1:56 UTC (permalink / raw)
To: Nguyen Thai Ngoc Duy; +Cc: Bill Zaumen, Jeff King, Git Mailing List
In-Reply-To: <CACsJy8CO1GtpZVo-oA2eKbQadsXYBEKVLfUH0GONR5jovuvH+Q@mail.gmail.com>
Nguyen Thai Ngoc Duy wrote:
> SHA-1 charateristics (like 20 byte length) are hard coded everywhere
> in git, it'd be a big audit.
I was planning to look at this anyway. My branch[1] allows
init/add/commit with SHA-256, SHA-512 and all the SHA-3 candidates.
log/fsck/etc. are all broken. Don't even dare try packs. Fixing things
is painful but not impossible. I'm not convinced the task is even
remotely insurmountable.
(This is not a request-for-comments, just an informational notification.
It does not even attempt to address compatability or the like.)
$ make HASH=sha512 -j6
$ PATH=bin-wrappers:..
$ git init && echo hi > foo && git add foo && git commit -m "bang"
Initialized empty Git repository in /.../.git/
[master (root-commit)
8d3ae658dff0c6e398bb4a0d193974e49acfadedfcd61daca42c931ac18d5ac46f0a068e08d81c25d7b79b1c3f4951e4340eeb90f0ef39de355c9bab7e75faba]
bang
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 foo
1. (Please use the hash-v0.0.1 tag, I rebase.)
gitweb: http://preview.tinyurl.com/bsufh92
git://git.goeswhere.com/git/git.git
https://github.com/FauxFaux/git/tree/hash-v0.0.1
---
Chris West (Faux)
Freenode #git: FauxFaux
https://ssl.goeswhere.com/key-transition-2011-10-10.txt.asc
gpg: 408A E4F1 4EA7 33EF 1265 82C1 B195 E1C4 779B A9B2
^ permalink raw reply
* Re: hooks that do not consume stdin sometimes crash git with SIGPIPE
From: Joey Hess @ 2011-12-06 3:11 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Lars Wirzenius
In-Reply-To: <7vmxb6iim0.fsf@alter.siamese.dyndns.org>
[-- Attachment #1: Type: text/plain, Size: 737 bytes --]
Junio C Hamano wrote:
> Why do you have a hook that is expected to read from receive-pack that
> does _not_ read anything from it in the first place? If you do not care
> about the update status given to pre-receive, shouldn't you be using the
> update hook and ignoring the command line parameters instead?
My hook *does* consume the stdin in one case, but in another case it
does no checks and so can immediately exit.
Also, I didn't want it to be run once per updated ref as the update hook
is, since the tests it performs are rather expensive -- loading a perl
wiki engine in order to check that the changeset contains only changes to
wiki pages that are allowed based on the wiki's configuration.
--
see shy jo
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply
* Re: Suggestion on hashing
From: Bill Zaumen @ 2011-12-06 3:47 UTC (permalink / raw)
To: Chris West (Faux); +Cc: Nguyen Thai Ngoc Duy, Jeff King, Git Mailing List
In-Reply-To: <alpine.DEB.2.00.1112060146121.15104@hoki.goeswhere.com>
When I went through the code, I noted that SHA-1 hashes are
currently used for the following:
* object IDs
* authentication (something to sign using public-key encryption)
* data integrity (basically a really good checksum).
While there are lot of 20-byte arrays of unsigned char, many of those
are associated with lookups. You might want to look at the
number of places that git_SHA1_Init is called (there aren't all that
many of those, and that function indicates the points where SHA-1
hashes are being created).
While a few things I tried were complete false starts (kept those
out of the preliminary patches I sent), I managed to store
a CRC (which you can treat as a place-holder for a real message
digest) for each SHA-1 hash in a pack file, but I did it by
creating a separate file (extension ".mds") and that worked.
I looked into modifying pack files, and that was too messy given
that you'd want older version to still work with newer remote
repositories. The other factor is that the "mds" files are
computed locally, and at the same time that you create an "idx" file.
The formats of the "pack" and "idx" files don't change.
I've just started on replacing the CRC I used with real message
digests, making new digests easy to add. The plan is to initially
make it work with both a CRC and SHA-1 (the CRC so I can test it
easily by comparing new and old versions to show that nothing
changed when it shouldn't have), and because Git already implements
SHA-1.
I should complete my changes. If we are lucky, maybe the changes I'm
trying would solve some of the problems you mentioned with pack files.
At least I can store the digests in a way that doesn't break the log
and fsck operations (it went through all the test suites, with only
minor modifications for things like counting the number of files in
particular directories).
If you make changes to commit objects, fixing the test scripts is a
pain - there are a number of places where SHA-1 values are hard-
coded, and those have to be replaced.
Bill
On Tue, 2011-12-06 at 01:56 +0000, Chris West (Faux) wrote:
> Nguyen Thai Ngoc Duy wrote:
> > SHA-1 charateristics (like 20 byte length) are hard coded everywhere
> > in git, it'd be a big audit.
>
> I was planning to look at this anyway. My branch[1] allows
> init/add/commit with SHA-256, SHA-512 and all the SHA-3 candidates.
>
> log/fsck/etc. are all broken. Don't even dare try packs. Fixing things
> is painful but not impossible. I'm not convinced the task is even
> remotely insurmountable.
>
> (This is not a request-for-comments, just an informational notification.
> It does not even attempt to address compatability or the like.)
^ permalink raw reply
* [PATCH] enable SO_KEEPALIVE for connected TCP sockets
From: Eric Wong @ 2011-12-06 4:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Sockets may never receive notification of some link errors,
causing "git fetch" or similar processes to hang forever.
Enabling keepalive messages allows hung processes to error out
after a few minutes/hours depending on the keepalive settings of
the system.
This is a problem noticed when running non-interactive
cronjobs to mirror repositories using "git fetch".
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
connect.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/connect.c b/connect.c
index 51990fa..d0f59ef 100644
--- a/connect.c
+++ b/connect.c
@@ -175,6 +175,15 @@ static void get_host_and_port(char **host, const char **port)
}
}
+static void enable_keepalive(int sockfd)
+{
+ int ka = 1;
+
+ if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &ka, sizeof(ka)) < 0)
+ fprintf(stderr, "unable to set SO_KEEPALIVE on socket: %s\n",
+ strerror(errno));
+}
+
#ifndef NO_IPV6
static const char *ai_name(const struct addrinfo *ai)
@@ -239,6 +248,8 @@ static int git_tcp_connect_sock(char *host, int flags)
if (sockfd < 0)
die("unable to connect to %s:\n%s", host, error_message.buf);
+ enable_keepalive(sockfd);
+
if (flags & CONNECT_VERBOSE)
fprintf(stderr, "done.\n");
@@ -312,6 +323,8 @@ static int git_tcp_connect_sock(char *host, int flags)
if (sockfd < 0)
die("unable to connect to %s:\n%s", host, error_message.buf);
+ enable_keepalive(sockfd);
+
if (flags & CONNECT_VERBOSE)
fprintf(stderr, "done.\n");
--
Eric Wong
^ permalink raw reply related
* Re: Suggestion on hashing
From: Nguyen Thai Ngoc Duy @ 2011-12-06 4:46 UTC (permalink / raw)
To: Chris West (Faux); +Cc: Bill Zaumen, Jeff King, Git Mailing List
In-Reply-To: <alpine.DEB.2.00.1112060146121.15104@hoki.goeswhere.com>
On Tue, Dec 6, 2011 at 8:56 AM, Chris West (Faux) <faux@goeswhere.com> wrote:
>
> Nguyen Thai Ngoc Duy wrote:
>>
>> SHA-1 charateristics (like 20 byte length) are hard coded everywhere
>> in git, it'd be a big audit.
>
>
> I was planning to look at this anyway. My branch[1] allows
> init/add/commit with SHA-256, SHA-512 and all the SHA-3 candidates.
Great!
> log/fsck/etc. are all broken. Don't even dare try packs. Fixing things
> is painful but not impossible. I'm not convinced the task is even
> remotely insurmountable.
It would take more work, but after you're done with code changes, you
should have a look at updating the test suite. We have many SHA-1s
there. If the test suite passes, your job is (beautifully) done.
--
Duy
^ permalink raw reply
* request for re-review of i18n-enable patch
From: Junio C Hamano @ 2011-12-06 4:54 UTC (permalink / raw)
To: git; +Cc: Ævar Arnfjörð Bjarmason
I am resending this (after squashing a mini-fix from Ramsay) to solicit
another round of review, hoping that people can catch any potential glitch
before we merge this to 'next'.
Thanks.
-- >8 --
From: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Subject: [PATCH] i18n: add infrastructure for translating Git with gettext
Change the skeleton implementation of i18n in Git to one that can show
localized strings to users for our C, Shell and Perl programs using
either GNU libintl or the Solaris gettext implementation.
This new internationalization support is enabled by default. If
gettext isn't available, or if Git is compiled with
NO_GETTEXT=YesPlease, Git falls back on its current behavior of
showing interface messages in English. When using the autoconf script
we'll auto-detect if the gettext libraries are installed and act
appropriately.
This change is somewhat large because as well as adding a C, Shell and
Perl i18n interface we're adding a lot of tests for them, and for
those tests to work we need a skeleton PO file to actually test
translations. A minimal Icelandic translation is included for this
purpose. Icelandic includes multi-byte characters which makes it easy
to test various edge cases, and it's a language I happen to
understand.
The rest of the commit message goes into detail about various
sub-parts of this commit.
= Installation
Gettext .mo files will be installed and looked for in the standard
$(prefix)/share/locale path. GIT_TEXTDOMAINDIR can also be set to
override that, but that's only intended to be used to test Git itself.
= Perl
Perl code that's to be localized should use the new Git::I18n
module. It imports a __ function into the caller's package by default.
Instead of using the high level Locale::TextDomain interface I've
opted to use the low-level (equivalent to the C interface)
Locale::Messages module, which Locale::TextDomain itself uses.
Locale::TextDomain does a lot of redundant work we don't need, and
some of it would potentially introduce bugs. It tries to set the
$TEXTDOMAIN based on package of the caller, and has its own
hardcoded paths where it'll search for messages.
I found it easier just to completely avoid it rather than try to
circumvent its behavior. In any case, this is an issue wholly
internal Git::I18N. Its guts can be changed later if that's deemed
necessary.
See <AANLkTilYD_NyIZMyj9dHtVk-ylVBfvyxpCC7982LWnVd@mail.gmail.com> for
a further elaboration on this topic.
= Shell
Shell code that's to be localized should use the git-sh-i18n
library. It's basically just a wrapper for the system's gettext.sh.
If gettext.sh isn't available we'll fall back on gettext(1) if it's
available. The latter is available without the former on Solaris,
which has its own non-GNU gettext implementation. We also need to
emulate eval_gettext() there.
If neither are present we'll use a dumb printf(1) fall-through
wrapper.
= About libcharset.h and langinfo.h
We use libcharset to query the character set of the current locale if
it's available. I.e. we'll use it instead of nl_langinfo if
HAVE_LIBCHARSET_H is set.
The GNU gettext manual recommends using langinfo.h's
nl_langinfo(CODESET) to acquire the current character set, but on
systems that have libcharset.h's locale_charset() using the latter is
either saner, or the only option on those systems.
GNU and Solaris have a nl_langinfo(CODESET), FreeBSD can use either,
but MinGW and some others need to use libcharset.h's locale_charset()
instead.
=Credits
This patch is based on work by Jeff Epler <jepler@unpythonic.net> who
did the initial Makefile / C work, and a lot of comments from the Git
mailing list, including Jonathan Nieder, Jakub Narebski, Johannes
Sixt, Erik Faye-Lund, Peter Krefting, Junio C Hamano, Thomas Rast and
others.
[jc: squashed a small Makefile fix from Ramsay]
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Documentation/CodingGuidelines | 7 +
INSTALL | 12 ++
Makefile | 81 ++++++++++++-
config.mak.in | 3 +
configure.ac | 19 +++
daemon.c | 2 +
fast-import.c | 2 +
gettext.c | 117 ++++++++++++++++++
gettext.h | 25 ++++-
git-sh-i18n.sh | 100 +++++++++++-----
git.c | 2 +
http-backend.c | 2 +
http-fetch.c | 2 +
http-push.c | 2 +
imap-send.c | 2 +
perl/Git/I18N.pm | 89 ++++++++++++++
perl/Makefile | 3 +-
perl/Makefile.PL | 14 ++-
po/.gitignore | 1 +
po/README | 229 +++++++++++++++++++++++++++++++++++
po/is.po | 93 ++++++++++++++
shell.c | 2 +
show-index.c | 2 +
t/lib-gettext.sh | 55 +++++++++
t/t0200-gettext-basic.sh | 108 ++++++++++++++++
t/t0200/test.c | 23 ++++
t/t0200/test.perl | 14 ++
t/t0200/test.sh | 14 ++
t/t0201-gettext-fallbacks.sh | 20 +++-
t/t0202-gettext-perl.sh | 27 ++++
t/t0202/test.pl | 110 +++++++++++++++++
t/t0203-gettext-setlocale-sanity.sh | 26 ++++
t/t0204-gettext-reencode-sanity.sh | 78 ++++++++++++
t/t0205-gettext-poison.sh | 36 ++++++
t/test-lib.sh | 3 +
upload-pack.c | 2 +
wrap-for-bin.sh | 3 +-
37 files changed, 1291 insertions(+), 39 deletions(-)
create mode 100644 perl/Git/I18N.pm
create mode 100644 po/README
create mode 100644 po/is.po
create mode 100644 t/lib-gettext.sh
create mode 100755 t/t0200-gettext-basic.sh
create mode 100644 t/t0200/test.c
create mode 100644 t/t0200/test.perl
create mode 100644 t/t0200/test.sh
create mode 100755 t/t0202-gettext-perl.sh
create mode 100644 t/t0202/test.pl
create mode 100755 t/t0203-gettext-setlocale-sanity.sh
create mode 100755 t/t0204-gettext-reencode-sanity.sh
create mode 100755 t/t0205-gettext-poison.sh
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index fe1c1e5..4830086 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -81,6 +81,10 @@ For shell scripts specifically (not exhaustive):
are ERE elements not BRE (note that \? and \+ are not even part
of BRE -- making them accessible from BRE is a GNU extension).
+ - Use Git's gettext wrappers in git-sh-i18n to make the user
+ interface translatable. See "Marking strings for translation" in
+ po/README.
+
For C programs:
- We use tabs to indent, and interpret tabs as taking up to
@@ -144,6 +148,9 @@ For C programs:
- When we pass <string, length> pair to functions, we should try to
pass them in that order.
+ - Use Git's gettext wrappers to make the user interface
+ translatable. See "Marking strings for translation" in po/README.
+
Writing Documentation:
Every user-visible change should be reflected in the documentation.
diff --git a/INSTALL b/INSTALL
index bf0d97e..8120641 100644
--- a/INSTALL
+++ b/INSTALL
@@ -106,6 +106,18 @@ Issues of note:
history graphically, and in git-gui. If you don't want gitk or
git-gui, you can use NO_TCLTK.
+ - A gettext library is used by default for localizing Git. The
+ primary target is GNU libintl, but the Solaris gettext
+ implementation also works.
+
+ We need a gettext.h on the system for C code, gettext.sh (or
+ Solaris gettext(1)) for shell scripts, and libintl-perl for Perl
+ programs.
+
+ Set NO_GETTEXT to disable localization support and make Git only
+ use English. Under autoconf the configure script will do this
+ automatically if it can't find libintl on the system.
+
- Some platform specific issues are dealt with Makefile rules,
but depending on your specific installation, you may not
have all the libraries/tools needed, or you may have
diff --git a/Makefile b/Makefile
index ee34eab..08b9297 100644
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,22 @@ all::
# Define EXPATDIR=/foo/bar if your expat header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
#
+# Define NO_GETTEXT if you don't want Git output to be translated.
+# A translated Git requires GNU libintl or another gettext implementation,
+# plus libintl-perl at runtime.
+#
+# Define HAVE_LIBCHARSET_H if you haven't set NO_GETTEXT and you can't
+# trust the langinfo.h's nl_langinfo(CODESET) function to return the
+# current character set. GNU and Solaris have a nl_langinfo(CODESET),
+# FreeBSD can use either, but MinGW and some others need to use
+# libcharset.h's locale_charset() instead.
+#
+# Define LIBC_CONTAINS_LIBINTL if your gettext implementation doesn't
+# need -lintl when linking.
+#
+# Define NO_MSGFMT_EXTENDED_OPTIONS if your implementation of msgfmt
+# doesn't support GNU extensions like --check and --statistics
+#
# Define HAVE_PATHS_H if you have paths.h and want to use the default PATH
# it specifies.
#
@@ -301,6 +317,7 @@ gitexecdir = libexec/git-core
mergetoolsdir = $(gitexecdir)/mergetools
sharedir = $(prefix)/share
gitwebdir = $(sharedir)/gitweb
+localedir = $(sharedir)/locale
template_dir = share/git-core/templates
htmldir = share/doc/git-doc
ETC_GITCONFIG = $(sysconfdir)/gitconfig
@@ -309,7 +326,7 @@ lib = lib
# DESTDIR=
pathsep = :
-export prefix bindir sharedir sysconfdir gitwebdir
+export prefix bindir sharedir sysconfdir gitwebdir localedir
CC = gcc
AR = ar
@@ -322,6 +339,7 @@ RPMBUILD = rpmbuild
TCL_PATH = tclsh
TCLTK_PATH = wish
XGETTEXT = xgettext
+MSGFMT = msgfmt
PTHREAD_LIBS = -lpthread
PTHREAD_CFLAGS =
GCOV = gcov
@@ -621,6 +639,7 @@ LIB_OBJS += entry.o
LIB_OBJS += environment.o
LIB_OBJS += exec_cmd.o
LIB_OBJS += fsck.o
+LIB_OBJS += gettext.o
LIB_OBJS += graph.o
LIB_OBJS += grep.o
LIB_OBJS += hash.o
@@ -817,12 +836,14 @@ ifeq ($(uname_S),Linux)
NO_STRLCPY = YesPlease
NO_MKSTEMPS = YesPlease
HAVE_PATHS_H = YesPlease
+ LIBC_CONTAINS_LIBINTL = YesPlease
endif
ifeq ($(uname_S),GNU/kFreeBSD)
NO_STRLCPY = YesPlease
NO_MKSTEMPS = YesPlease
HAVE_PATHS_H = YesPlease
DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
+ LIBC_CONTAINS_LIBINTL = YesPlease
endif
ifeq ($(uname_S),UnixWare)
CC = cc
@@ -889,6 +910,7 @@ ifeq ($(uname_S),SunOS)
NO_MKSTEMPS = YesPlease
NO_REGEX = YesPlease
NO_FNMATCH_CASEFOLD = YesPlease
+ NO_MSGFMT_EXTENDED_OPTIONS = YesPlease
ifeq ($(uname_R),5.6)
SOCKLEN_T = int
NO_HSTRERROR = YesPlease
@@ -1012,6 +1034,7 @@ ifeq ($(uname_S),GNU)
NO_STRLCPY=YesPlease
NO_MKSTEMPS = YesPlease
HAVE_PATHS_H = YesPlease
+ LIBC_CONTAINS_LIBINTL = YesPlease
endif
ifeq ($(uname_S),IRIX)
NO_SETENV = YesPlease
@@ -1228,6 +1251,7 @@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
EXTLIBS += /mingw/lib/libz.a
NO_R_TO_GCC_LINKER = YesPlease
INTERNAL_QSORT = YesPlease
+ HAVE_LIBCHARSET_H = YesPlease
else
NO_CURL = YesPlease
endif
@@ -1405,6 +1429,11 @@ endif
ifdef NEEDS_LIBGEN
EXTLIBS += -lgen
endif
+ifndef NO_GETTEXT
+ifndef LIBC_CONTAINS_LIBINTL
+ EXTLIBS += -lintl
+endif
+endif
ifdef NEEDS_SOCKET
EXTLIBS += -lsocket
endif
@@ -1447,9 +1476,11 @@ ifdef NO_SYMLINK_HEAD
BASIC_CFLAGS += -DNO_SYMLINK_HEAD
endif
ifdef GETTEXT_POISON
- LIB_OBJS += gettext.o
BASIC_CFLAGS += -DGETTEXT_POISON
endif
+ifdef NO_GETTEXT
+ BASIC_CFLAGS += -DNO_GETTEXT
+endif
ifdef NO_STRCASESTR
COMPAT_CFLAGS += -DNO_STRCASESTR
COMPAT_OBJS += compat/strcasestr.o
@@ -1612,6 +1643,10 @@ ifdef HAVE_PATHS_H
BASIC_CFLAGS += -DHAVE_PATHS_H
endif
+ifdef HAVE_LIBCHARSET_H
+ BASIC_CFLAGS += -DHAVE_LIBCHARSET_H
+endif
+
ifdef DIR_HAS_BSD_GROUP_SEMANTICS
COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS
endif
@@ -1632,6 +1667,10 @@ ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
export GIT_TEST_CMP_USE_COPIED_CONTEXT
endif
+ifndef NO_MSGFMT_EXTENDED_OPTIONS
+ MSGFMT += --check --statistics
+endif
+
ifeq ($(TCLTK_PATH),)
NO_TCLTK=NoThanks
endif
@@ -1662,6 +1701,7 @@ ifndef V
QUIET_GEN = @echo ' ' GEN $@;
QUIET_LNCP = @echo ' ' LN/CP $@;
QUIET_XGETTEXT = @echo ' ' XGETTEXT $@;
+ QUIET_MSGFMT = @echo ' ' MSGFMT $@;
QUIET_GCOV = @echo ' ' GCOV $@;
QUIET_SP = @echo ' ' SP $<;
QUIET_SUBDIR0 = +@subdir=
@@ -1688,6 +1728,7 @@ bindir_SQ = $(subst ','\'',$(bindir))
bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
mandir_SQ = $(subst ','\'',$(mandir))
infodir_SQ = $(subst ','\'',$(infodir))
+localedir_SQ = $(subst ','\'',$(localedir))
gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
template_dir_SQ = $(subst ','\'',$(template_dir))
htmldir_SQ = $(subst ','\'',$(htmldir))
@@ -1743,7 +1784,7 @@ ifndef NO_TCLTK
$(QUIET_SUBDIR0)gitk-git $(QUIET_SUBDIR1) all
endif
ifndef NO_PERL
- $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
+ $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' localedir='$(localedir_SQ)' all
endif
ifndef NO_PYTHON
$(QUIET_SUBDIR0)git_remote_helpers $(QUIET_SUBDIR1) PYTHON_PATH='$(PYTHON_PATH_SQ)' prefix='$(prefix_SQ)' all
@@ -1793,6 +1834,7 @@ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
-e 's|@@DIFF@@|$(DIFF_SQ)|' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
+ -e 's|@@LOCALEDIR@@|$(localedir_SQ)|g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
-e $(BROKEN_PATH_FIX) \
$@.sh >$@+
@@ -2045,6 +2087,9 @@ config.sp config.s config.o: EXTRA_CPPFLAGS = \
attr.sp attr.s attr.o: EXTRA_CPPFLAGS = \
-DETC_GITATTRIBUTES='"$(ETC_GITATTRIBUTES_SQ)"'
+gettext.sp gettext.s gettext.o: EXTRA_CPPFLAGS = \
+ -DGIT_LOCALE_PATH='"$(localedir_SQ)"'
+
http.sp http.s http.o: EXTRA_CPPFLAGS = \
-DGIT_HTTP_USER_AGENT='"git/$(GIT_VERSION)"'
@@ -2118,17 +2163,37 @@ XGETTEXT_FLAGS = \
XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
--keyword=_ --keyword=N_ --keyword="Q_:1,2"
XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell
+XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
LOCALIZED_C := $(C_OBJ:o=c)
LOCALIZED_SH := $(SCRIPT_SH)
+LOCALIZED_PERL := $(SCRIPT_PERL)
+
+ifdef XGETTEXT_INCLUDE_TESTS
+LOCALIZED_C += t/t0200/test.c
+LOCALIZED_SH += t/t0200/test.sh
+LOCALIZED_PERL += t/t0200/test.perl
+endif
po/git.pot: $(LOCALIZED_C)
$(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ $(XGETTEXT_FLAGS_C) $(LOCALIZED_C)
$(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_SH) \
$(LOCALIZED_SH)
+ $(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_PERL) \
+ $(LOCALIZED_PERL)
mv $@+ $@
pot: po/git.pot
+POFILES := $(wildcard po/*.po)
+MOFILES := $(patsubst po/%.po,po/build/locale/%/LC_MESSAGES/git.mo,$(POFILES))
+
+ifndef NO_GETTEXT
+all:: $(MOFILES)
+endif
+
+po/build/locale/%/LC_MESSAGES/git.mo: po/%.po
+ $(QUIET_MSGFMT)mkdir -p $(dir $@) && $(MSGFMT) -o $@ $<
+
FIND_SOURCE_FILES = ( git ls-files '*.[hcS]' 2>/dev/null || \
$(FIND) . \( -name .git -type d -prune \) \
-o \( -name '*.[hcS]' -type f -print \) )
@@ -2147,7 +2212,8 @@ cscope:
### Detect prefix changes
TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS)):\
- $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
+ $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
+ $(localedir_SQ)
GIT-CFLAGS: FORCE
@FLAGS='$(TRACK_CFLAGS)'; \
@@ -2184,6 +2250,7 @@ endif
ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
@echo GIT_TEST_CMP_USE_COPIED_CONTEXT=YesPlease >>$@
endif
+ @echo NO_GETTEXT=\''$(subst ','\'',$(subst ','\'',$(NO_GETTEXT)))'\' >>$@
@echo GETTEXT_POISON=\''$(subst ','\'',$(subst ','\'',$(GETTEXT_POISON)))'\' >>$@
### Detect Tck/Tk interpreter path changes
@@ -2299,6 +2366,11 @@ install: all
$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(mergetools_instdir_SQ)'
$(INSTALL) -m 644 mergetools/* '$(DESTDIR_SQ)$(mergetools_instdir_SQ)'
+ifndef NO_GETTEXT
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(localedir_SQ)'
+ (cd po/build/locale && $(TAR) cf - .) | \
+ (cd '$(DESTDIR_SQ)$(localedir_SQ)' && umask 022 && $(TAR) xof -)
+endif
ifndef NO_PERL
$(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
$(MAKE) -C gitweb install
@@ -2435,6 +2507,7 @@ clean:
$(RM) $(TEST_PROGRAMS)
$(RM) -r bin-wrappers
$(RM) -r $(dep_dirs)
+ $(RM) -r po/build/
$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h $(ETAGS_TARGET) tags cscope*
$(RM) -r autom4te.cache
$(RM) config.log config.mak.autogen config.mak.append config.status config.cache
diff --git a/config.mak.in b/config.mak.in
index ab37101..10698c8 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -35,6 +35,9 @@ NO_CURL=@NO_CURL@
NO_EXPAT=@NO_EXPAT@
NO_LIBGEN_H=@NO_LIBGEN_H@
HAVE_PATHS_H=@HAVE_PATHS_H@
+HAVE_LIBCHARSET_H=@HAVE_LIBCHARSET_H@
+NO_GETTEXT=@NO_GETTEXT@
+LIBC_CONTAINS_LIBINTL=@LIBC_CONTAINS_LIBINTL@
NEEDS_LIBICONV=@NEEDS_LIBICONV@
NEEDS_SOCKET=@NEEDS_SOCKET@
NEEDS_RESOLV=@NEEDS_RESOLV@
diff --git a/configure.ac b/configure.ac
index 048a1d4..630dbdd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -636,6 +636,12 @@ AC_CHECK_LIB([c], [basename],
AC_SUBST(NEEDS_LIBGEN)
test -n "$NEEDS_LIBGEN" && LIBS="$LIBS -lgen"
+AC_CHECK_LIB([c], [gettext],
+[LIBC_CONTAINS_LIBINTL=YesPlease],
+[LIBC_CONTAINS_LIBINTL=])
+AC_SUBST(LIBC_CONTAINS_LIBINTL)
+test -n "$LIBC_CONTAINS_LIBINTL" || LIBS="$LIBS -lintl"
+
## Checks for header files.
AC_MSG_NOTICE([CHECKS for header files])
#
@@ -818,6 +824,19 @@ AC_CHECK_HEADER([paths.h],
[HAVE_PATHS_H=])
AC_SUBST(HAVE_PATHS_H)
#
+# Define NO_GETTEXT if you don't want Git output to be translated.
+# A translated Git requires GNU libintl or another gettext implementation
+AC_CHECK_HEADER([libintl.h],
+[NO_GETTEXT=],
+[NO_GETTEXT=YesPlease])
+AC_SUBST(NO_GETTEXT)
+#
+# Define HAVE_LIBCHARSET_H if have libcharset.h
+AC_CHECK_HEADER([libcharset.h],
+[HAVE_LIBCHARSET_H=YesPlease],
+[HAVE_LIBCHARSET_H=])
+AC_SUBST(HAVE_LIBCHARSET_H)
+#
# Define NO_STRCASESTR if you don't have strcasestr.
GIT_CHECK_FUNC(strcasestr,
[NO_STRCASESTR=],
diff --git a/daemon.c b/daemon.c
index fa28300..15ce918 100644
--- a/daemon.c
+++ b/daemon.c
@@ -1099,6 +1099,8 @@ int main(int argc, char **argv)
struct credentials *cred = NULL;
int i;
+ git_setup_gettext();
+
git_extract_argv0_path(argv[0]);
for (i = 1; i < argc; i++) {
diff --git a/fast-import.c b/fast-import.c
index 8d8ea3c..b59e7db 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -3292,6 +3292,8 @@ int main(int argc, const char **argv)
git_extract_argv0_path(argv[0]);
+ git_setup_gettext();
+
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(fast_import_usage);
diff --git a/gettext.c b/gettext.c
index ae5394a..f75bca7 100644
--- a/gettext.c
+++ b/gettext.c
@@ -5,6 +5,18 @@
#include "git-compat-util.h"
#include "gettext.h"
+#ifndef NO_GETTEXT
+# include <locale.h>
+# include <libintl.h>
+# ifdef HAVE_LIBCHARSET_H
+# include <libcharset.h>
+# else
+# include <langinfo.h>
+# define locale_charset() nl_langinfo(CODESET)
+# endif
+#endif
+
+#ifdef GETTEXT_POISON
int use_gettext_poison(void)
{
static int poison_requested = -1;
@@ -12,3 +24,108 @@ int use_gettext_poison(void)
poison_requested = getenv("GIT_GETTEXT_POISON") ? 1 : 0;
return poison_requested;
}
+#endif
+
+#ifndef NO_GETTEXT
+static void init_gettext_charset(const char *domain)
+{
+ const char *charset;
+
+ /*
+ This trick arranges for messages to be emitted in the user's
+ requested encoding, but avoids setting LC_CTYPE from the
+ environment for the whole program.
+
+ This primarily done to avoid a bug in vsnprintf in the GNU C
+ Library [1]. which triggered a "your vsnprintf is broken" error
+ on Git's own repository when inspecting v0.99.6~1 under a UTF-8
+ locale.
+
+ That commit contains a ISO-8859-1 encoded author name, which
+ the locale aware vsnprintf(3) won't interpolate in the format
+ argument, due to mismatch between the data encoding and the
+ locale.
+
+ Even if it wasn't for that bug we wouldn't want to use LC_CTYPE at
+ this point, because it'd require auditing all the code that uses C
+ functions whose semantics are modified by LC_CTYPE.
+
+ But only setting LC_MESSAGES as we do creates a problem, since
+ we declare the encoding of our PO files[2] the gettext
+ implementation will try to recode it to the user's locale, but
+ without LC_CTYPE it'll emit something like this on 'git init'
+ under the Icelandic locale:
+
+ Bj? til t?ma Git lind ? /hlagh/.git/
+
+ Gettext knows about the encoding of our PO file, but we haven't
+ told it about the user's encoding, so all the non-US-ASCII
+ characters get encoded to question marks.
+
+ But we're in luck! We can set LC_CTYPE from the environment
+ only while we call nl_langinfo and
+ bind_textdomain_codeset. That suffices to tell gettext what
+ encoding it should emit in, so it'll now say:
+
+ Bjó til tóma Git lind í /hlagh/.git/
+
+ And the equivalent ISO-8859-1 string will be emitted under a
+ ISO-8859-1 locale.
+
+ With this change way we get the advantages of setting LC_CTYPE
+ (talk to the user in his language/encoding), without the major
+ drawbacks (changed semantics for C functions we rely on).
+
+ However foreign functions using other message catalogs that
+ aren't using our neat trick will still have a problem, e.g. if
+ we have to call perror(3):
+
+ #include <stdio.h>
+ #include <locale.h>
+ #include <errno.h>
+
+ int main(void)
+ {
+ setlocale(LC_MESSAGES, "");
+ setlocale(LC_CTYPE, "C");
+ errno = ENODEV;
+ perror("test");
+ return 0;
+ }
+
+ Running that will give you a message with question marks:
+
+ $ LANGUAGE= LANG=de_DE.utf8 ./test
+ test: Kein passendes Ger?t gefunden
+
+ In the long term we should probably see about getting that
+ vsnprintf bug in glibc fixed, and audit our code so it won't
+ fall apart under a non-C locale.
+
+ Then we could simply set LC_CTYPE from the environment, which would
+ make things like the external perror(3) messages work.
+
+ See t/t0203-gettext-setlocale-sanity.sh's "gettext.c" tests for
+ regression tests.
+
+ 1. http://sourceware.org/bugzilla/show_bug.cgi?id=6530
+ 2. E.g. "Content-Type: text/plain; charset=UTF-8\n" in po/is.po
+ */
+ setlocale(LC_CTYPE, "");
+ charset = locale_charset();
+ bind_textdomain_codeset(domain, charset);
+ setlocale(LC_CTYPE, "C");
+}
+
+void git_setup_gettext(void)
+{
+ const char *podir = getenv("GIT_TEXTDOMAINDIR");
+
+ if (!podir)
+ podir = GIT_LOCALE_PATH;
+ bindtextdomain("git", podir);
+ setlocale(LC_MESSAGES, "");
+ init_gettext_charset("git");
+ textdomain("git");
+}
+#endif
diff --git a/gettext.h b/gettext.h
index 24d9182..57ba8bb 100644
--- a/gettext.h
+++ b/gettext.h
@@ -13,8 +13,29 @@
#error "namespace conflict: '_' or 'Q_' is pre-defined?"
#endif
+#ifndef NO_GETTEXT
+# include <libintl.h>
+#else
+# ifdef gettext
+# undef gettext
+# endif
+# define gettext(s) (s)
+# ifdef ngettext
+# undef ngettext
+# endif
+# define ngettext(s, p, n) ((n == 1) ? (s) : (p))
+#endif
+
#define FORMAT_PRESERVING(n) __attribute__((format_arg(n)))
+#ifndef NO_GETTEXT
+extern void git_setup_gettext(void);
+#else
+static inline void git_setup_gettext(void)
+{
+}
+#endif
+
#ifdef GETTEXT_POISON
extern int use_gettext_poison(void);
#else
@@ -23,7 +44,7 @@ extern int use_gettext_poison(void);
static inline FORMAT_PRESERVING(1) const char *_(const char *msgid)
{
- return use_gettext_poison() ? "# GETTEXT POISON #" : msgid;
+ return use_gettext_poison() ? "# GETTEXT POISON #" : gettext(msgid);
}
static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2)
@@ -31,7 +52,7 @@ const char *Q_(const char *msgid, const char *plu, unsigned long n)
{
if (use_gettext_poison())
return "# GETTEXT POISON #";
- return n == 1 ? msgid : plu;
+ return ngettext(msgid, plu, n);
}
/* Mark msgid for translation but do not translate it. */
diff --git a/git-sh-i18n.sh b/git-sh-i18n.sh
index e672366..b4575fb 100644
--- a/git-sh-i18n.sh
+++ b/git-sh-i18n.sh
@@ -2,47 +2,91 @@
#
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
#
-# This is a skeleton no-op implementation of gettext for Git. It'll be
-# replaced by something that uses gettext.sh in a future patch series.
+# This is Git's interface to gettext.sh. See po/README for usage
+# instructions.
+
+# Export the TEXTDOMAIN* data that we need for Git
+TEXTDOMAIN=git
+export TEXTDOMAIN
+if test -z "$GIT_TEXTDOMAINDIR"
+then
+ TEXTDOMAINDIR="@@LOCALEDIR@@"
+else
+ TEXTDOMAINDIR="$GIT_TEXTDOMAINDIR"
+fi
+export TEXTDOMAINDIR
if test -z "$GIT_GETTEXT_POISON"
then
- gettext () {
- printf "%s" "$1"
- }
+ if test -z "$GIT_INTERNAL_GETTEXT_TEST_FALLBACKS" && type gettext.sh >/dev/null 2>&1
+ then
+ # This is GNU libintl's gettext.sh, we don't need to do anything
+ # else than setting up the environment and loading gettext.sh
+ GIT_INTERNAL_GETTEXT_SH_SCHEME=gnu
+ export GIT_INTERNAL_GETTEXT_SH_SCHEME
- gettextln() {
- printf "%s\n" "$1"
- }
+ # Try to use libintl's gettext.sh, or fall back to English if we
+ # can't.
+ . gettext.sh
- eval_gettext () {
- printf "%s" "$1" | (
- export PATH $(git sh-i18n--envsubst --variables "$1");
- git sh-i18n--envsubst "$1"
- )
- }
+ elif test -z "$GIT_INTERNAL_GETTEXT_TEST_FALLBACKS" && test "$(gettext -h 2>&1)" = "-h"
+ then
+ # We don't have gettext.sh, but there's a gettext binary in our
+ # path. This is probably Solaris or something like it which has a
+ # gettext implementation that isn't GNU libintl.
+ GIT_INTERNAL_GETTEXT_SH_SCHEME=solaris
+ export GIT_INTERNAL_GETTEXT_SH_SCHEME
- eval_gettextln () {
- printf "%s\n" "$1" | (
- export PATH $(git sh-i18n--envsubst --variables "$1");
- git sh-i18n--envsubst "$1"
- )
- }
+ # Solaris has a gettext(1) but no eval_gettext(1)
+ eval_gettext () {
+ gettext "$1" | (
+ export PATH $(git sh-i18n--envsubst --variables "$1");
+ git sh-i18n--envsubst "$1"
+ )
+ }
+
+ else
+ # Since gettext.sh isn't available we'll have to define our own
+ # dummy pass-through functions.
+
+ # Tell our tests that we don't have the real gettext.sh
+ GIT_INTERNAL_GETTEXT_SH_SCHEME=fallthrough
+ export GIT_INTERNAL_GETTEXT_SH_SCHEME
+
+ gettext () {
+ printf "%s" "$1"
+ }
+
+ eval_gettext () {
+ printf "%s" "$1" | (
+ export PATH $(git sh-i18n--envsubst --variables "$1");
+ git sh-i18n--envsubst "$1"
+ )
+ }
+ fi
else
+ # Emit garbage under GETTEXT_POISON=YesPlease. Unlike the C tests
+ # this relies on an environment variable
+
+ GIT_INTERNAL_GETTEXT_SH_SCHEME=poison
+ export GIT_INTERNAL_GETTEXT_SH_SCHEME
+
gettext () {
printf "%s" "# GETTEXT POISON #"
}
- gettextln () {
- printf "%s\n" "# GETTEXT POISON #"
- }
-
eval_gettext () {
printf "%s" "# GETTEXT POISON #"
}
-
- eval_gettextln () {
- printf "%s\n" "# GETTEXT POISON #"
- }
fi
+# Git-specific wrapper functions
+gettextln () {
+ gettext "$1"
+ echo
+}
+
+eval_gettextln () {
+ eval_gettext "$1"
+ echo
+}
diff --git a/git.c b/git.c
index 8e34903..fa918b5 100644
--- a/git.c
+++ b/git.c
@@ -537,6 +537,8 @@ int main(int argc, const char **argv)
if (!cmd)
cmd = "git-help";
+ git_setup_gettext();
+
/*
* "git-xxxx" is the same as "git xxxx", but we obviously:
*
diff --git a/http-backend.c b/http-backend.c
index 59ad7da..869d515 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -545,6 +545,8 @@ int main(int argc, char **argv)
char *cmd_arg = NULL;
int i;
+ git_setup_gettext();
+
git_extract_argv0_path(argv[0]);
set_die_routine(die_webcgi);
diff --git a/http-fetch.c b/http-fetch.c
index 69299b7..9719d58 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -22,6 +22,8 @@ int main(int argc, const char **argv)
int get_verbosely = 0;
int get_recover = 0;
+ git_setup_gettext();
+
git_extract_argv0_path(argv[0]);
while (arg < argc && argv[arg][0] == '-') {
diff --git a/http-push.c b/http-push.c
index edd553b..f856299 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1748,6 +1748,8 @@ int main(int argc, char **argv)
int new_refs;
struct ref *ref, *local_refs;
+ git_setup_gettext();
+
git_extract_argv0_path(argv[0]);
repo = xcalloc(sizeof(*repo), 1);
diff --git a/imap-send.c b/imap-send.c
index e1ad1a4..9fba422 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -1539,6 +1539,8 @@ int main(int argc, char **argv)
git_extract_argv0_path(argv[0]);
+ git_setup_gettext();
+
if (argc != 1)
usage(imap_send_usage);
diff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm
new file mode 100644
index 0000000..07597dc
--- /dev/null
+++ b/perl/Git/I18N.pm
@@ -0,0 +1,89 @@
+package Git::I18N;
+use 5.008;
+use strict;
+use warnings;
+use Exporter 'import';
+
+our @EXPORT = qw(__);
+our @EXPORT_OK = @EXPORT;
+
+sub __bootstrap_locale_messages {
+ our $TEXTDOMAIN = 'git';
+ our $TEXTDOMAINDIR = $ENV{GIT_TEXTDOMAINDIR} || '++LOCALEDIR++';
+
+ require POSIX;
+ POSIX->import(qw(setlocale));
+ # Non-core prerequisite module
+ require Locale::Messages;
+ Locale::Messages->import(qw(:locale_h :libintl_h));
+
+ setlocale(LC_MESSAGES(), '');
+ setlocale(LC_CTYPE(), '');
+ textdomain($TEXTDOMAIN);
+ bindtextdomain($TEXTDOMAIN => $TEXTDOMAINDIR);
+
+ return;
+}
+
+BEGIN
+{
+ # Used by our test script to see if it should test fallbacks or
+ # not.
+ our $__HAS_LIBRARY = 1;
+
+ local $@;
+ eval {
+ __bootstrap_locale_messages();
+ *__ = \&Locale::Messages::gettext;
+ 1;
+ } or do {
+ # Tell test.pl that we couldn't load the gettext library.
+ $Git::I18N::__HAS_LIBRARY = 0;
+
+ # Just a fall-through no-op
+ *__ = sub ($) { $_[0] };
+ };
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Git::I18N - Perl interface to Git's Gettext localizations
+
+=head1 SYNOPSIS
+
+ use Git::I18N;
+
+ print __("Welcome to Git!\n");
+
+ printf __("The following error occured: %s\n"), $error;
+
+=head1 DESCRIPTION
+
+Git's internal Perl interface to gettext via L<Locale::Messages>. If
+L<Locale::Messages> can't be loaded (it's not a core module) we
+provide stub passthrough fallbacks.
+
+This is a distilled interface to gettext, see C<info '(gettext)Perl'>
+for the full interface. This module implements only a small part of
+it.
+
+=head1 FUNCTIONS
+
+=head2 __($)
+
+L<Locale::Messages>'s gettext function if all goes well, otherwise our
+passthrough fallback function.
+
+=head1 AUTHOR
+
+E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>
+
+=head1 COPYRIGHT
+
+Copyright 2010 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>
+
+=cut
diff --git a/perl/Makefile b/perl/Makefile
index a2ffb64..b2977cd 100644
--- a/perl/Makefile
+++ b/perl/Makefile
@@ -5,6 +5,7 @@ makfile:=perl.mak
PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
prefix_SQ = $(subst ','\'',$(prefix))
+localedir_SQ = $(subst ','\'',$(localedir))
ifndef V
QUIET = @
@@ -38,7 +39,7 @@ $(makfile): ../GIT-CFLAGS Makefile
echo ' echo $(instdir_SQ)' >> $@
else
$(makfile): Makefile.PL ../GIT-CFLAGS
- $(PERL_PATH) $< PREFIX='$(prefix_SQ)' INSTALL_BASE=''
+ $(PERL_PATH) $< PREFIX='$(prefix_SQ)' INSTALL_BASE='' --localedir='$(localedir_SQ)'
endif
# this is just added comfort for calling make directly in perl dir
diff --git a/perl/Makefile.PL b/perl/Makefile.PL
index 0b9deca..456d45b 100644
--- a/perl/Makefile.PL
+++ b/perl/Makefile.PL
@@ -1,4 +1,12 @@
+use strict;
+use warnings;
use ExtUtils::MakeMaker;
+use Getopt::Long;
+
+# Sanity: die at first unknown option
+Getopt::Long::Configure qw/ pass_through /;
+
+GetOptions("localedir=s" => \my $localedir);
sub MY::postamble {
return <<'MAKE_FRAG';
@@ -16,7 +24,10 @@ endif
MAKE_FRAG
}
-my %pm = ('Git.pm' => '$(INST_LIBDIR)/Git.pm');
+my %pm = (
+ 'Git.pm' => '$(INST_LIBDIR)/Git.pm',
+ 'Git/I18N.pm' => '$(INST_LIBDIR)/Git/I18N.pm',
+);
# We come with our own bundled Error.pm. It's not in the set of default
# Perl modules so install it if it's not available on the system yet.
@@ -33,6 +44,7 @@ WriteMakefile(
NAME => 'Git',
VERSION_FROM => 'Git.pm',
PM => \%pm,
+ PM_FILTER => qq[\$(PERL) -pe "s<\\Q++LOCALEDIR++\\E><$localedir>"],
MAKEFILE => 'perl.mak',
INSTALLSITEMAN3DIR => '$(SITEPREFIX)/share/man/man3'
);
diff --git a/po/.gitignore b/po/.gitignore
index a242a86..4caa631 100644
--- a/po/.gitignore
+++ b/po/.gitignore
@@ -1 +1,2 @@
/git.pot
+/build
diff --git a/po/README b/po/README
new file mode 100644
index 0000000..10b0ad2
--- /dev/null
+++ b/po/README
@@ -0,0 +1,229 @@
+Core GIT Translations
+=====================
+
+This directory holds the translations for the core of Git. This
+document describes how to add to and maintain these translations, and
+how to mark source strings for translation.
+
+
+Generating a .pot file
+----------------------
+
+The po/git.pot file contains a message catalog extracted from Git's
+sources. You need to generate it to add new translations with
+msginit(1), or update existing ones with msgmerge(1).
+
+Since the file can be automatically generated it's not checked into
+git.git. To generate it do, at the top-level:
+
+ make pot
+
+
+Initializing a .po file
+-----------------------
+
+To add a new translation first generate git.pot (see above) and then
+in the po/ directory do:
+
+ msginit --locale=XX
+
+Where XX is your locale, e.g. "is", "de" or "pt_BR".
+
+Then edit the automatically generated copyright info in your new XX.po
+to be correct, e.g. for Icelandic:
+
+ @@ -1,6 +1,6 @@
+ -# Icelandic translations for PACKAGE package.
+ -# Copyright (C) 2010 THE PACKAGE'S COPYRIGHT HOLDER
+ -# This file is distributed under the same license as the PACKAGE package.
+ +# Icelandic translations for Git.
+ +# Copyright (C) 2010 Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ +# This file is distributed under the same license as the Git package.
+ # Ævar Arnfjörð Bjarmason <avarab@gmail.com>, 2010.
+
+And change references to PACKAGE VERSION in the PO Header Entry to
+just "Git":
+
+ perl -pi -e 's/(?<="Project-Id-Version: )PACKAGE VERSION/Git/' XX.po
+
+
+Updating a .po file
+-------------------
+
+If there's an existing *.po file for your language but you need to
+update the translation you first need to generate git.pot (see above)
+and then in the po/ directory do:
+
+ msgmerge --add-location --backup=off -U XX.po git.pot
+
+Where XX.po is the file you want to update.
+
+Testing your changes
+--------------------
+
+Before you submit your changes go back to the top-level and do:
+
+ make
+
+On systems with GNU gettext (i.e. not Solaris) this will compile your
+changed PO file with `msgfmt --check`, the --check option flags many
+common errors, e.g. missing printf format strings, or translated
+messages that deviate from the originals in whether they begin/end
+with a newline or not.
+
+
+Marking strings for translation
+-------------------------------
+
+Before strings can be translated they first have to be marked for
+translation.
+
+Git uses an internationalization interface that wraps the system's
+gettext library, so most of the advice in your gettext documentation
+(on GNU systems `info gettext` in a terminal) applies.
+
+General advice:
+
+ - Don't mark everything for translation, only strings which will be
+ read by humans (the porcelain interface) should be translated.
+
+ The output from Git's plumbing utilities will primarily be read by
+ programs and would break scripts under non-C locales if it was
+ translated. Plumbing strings should not be translated, since
+ they're part of Git's API.
+
+ - Adjust the strings so that they're easy to translate. Most of the
+ advice in `info '(gettext)Preparing Strings'` applies here.
+
+ - If something is unclear or ambiguous you can use a "TRANSLATORS"
+ comment to tell the translators what to make of it. These will be
+ extracted by xgettext(1) and put in the po/*.po files, e.g. from
+ git-am.sh:
+
+ # TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
+ # in your translation. The program will only accept English
+ # input at this point.
+ gettext "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
+
+ Or in C, from builtin/revert.c:
+
+ /* TRANSLATORS: %s will be "revert" or "cherry-pick" */
+ die(_("%s: Unable to write new index file"), action_name(opts));
+
+We provide wrappers for C, Shell and Perl programs. Here's how they're
+used:
+
+C:
+
+ - Include builtin.h at the top, it'll pull in in gettext.h, which
+ defines the gettext interface. Consult with the list if you need to
+ use gettext.h directly.
+
+ - The C interface is a subset of the normal GNU gettext
+ interface. We currently export these functions:
+
+ - _()
+
+ Mark and translate a string. E.g.:
+
+ printf(_("HEAD is now at %s"), hex);
+
+ - Q_()
+
+ Mark and translate a plural string. E.g.:
+
+ printf(Q_("%d commit", "%d commits", number_of_commits));
+
+ This is just a wrapper for the ngettext() function.
+
+ - N_()
+
+ A no-op pass-through macro for marking strings inside static
+ initializations, e.g.:
+
+ static const char *reset_type_names[] = {
+ N_("mixed"), N_("soft"), N_("hard"), N_("merge"), N_("keep"), NULL
+ };
+
+ And then, later:
+
+ die(_("%s reset is not allowed in a bare repository"),
+ _(reset_type_names[reset_type]));
+
+ Here _() couldn't have statically determined what the translation
+ string will be, but since it was already marked for translation
+ with N_() the look-up in the message catalog will succeed.
+
+Shell:
+
+ - The Git gettext shell interface is just a wrapper for
+ gettext.sh. Import it right after git-sh-setup like this:
+
+ . git-sh-setup
+ . git-sh-i18n
+
+ And then use the gettext or eval_gettext functions:
+
+ # For constant interface messages:
+ gettext "A message for the user"; echo
+
+ # To interpolate variables:
+ details="oh noes"
+ eval_gettext "An error occured: \$details"; echo
+
+ In addition we have wrappers for messages that end with a trailing
+ newline. I.e. you could write the above as:
+
+ # For constant interface messages:
+ gettextln "A message for the user"
+
+ # To interpolate variables:
+ details="oh noes"
+ eval_gettextln "An error occured: \$details"
+
+ More documentation about the interface is available in the GNU info
+ page: `info '(gettext)sh'`. Looking at git-am.sh (the first shell
+ command to be translated) for examples is also useful:
+
+ git log --reverse -p --grep=i18n git-am.sh
+
+Perl:
+
+ - The Git::I18N module provides a limited subset of the
+ Locale::Messages functionality, e.g.:
+
+ use Git::I18N;
+ print __("Welcome to Git!\n");
+ printf __("The following error occured: %s\n"), $error;
+
+ Run `perldoc perl/Git/I18N.pm` for more info.
+
+
+Testing marked strings
+----------------------
+
+Even if you've correctly marked porcelain strings for translation
+something in the test suite might still depend on the US English
+version of the strings, e.g. to grep some error message or other
+output.
+
+To smoke out issues like these Git can be compiled with gettext poison
+support, at the top-level:
+
+ make GETTEXT_POISON=YesPlease
+
+That'll give you a git which emits gibberish on every call to
+gettext. It's obviously not meant to be installed, but you should run
+the test suite with it:
+
+ cd t && prove -j 9 ./t[0-9]*.sh
+
+If tests break with it you should inspect them manually and see if
+what you're translating is sane, i.e. that you're not translating
+plumbing output.
+
+If not you should replace calls to grep with test_i18ngrep, or
+test_cmp calls with test_i18ncmp. If that's not enough you can skip
+the whole test by making it depend on the C_LOCALE_OUTPUT
+prerequisite. See existing test files with this prerequisite for
+examples.
diff --git a/po/is.po b/po/is.po
new file mode 100644
index 0000000..8692a8b
--- /dev/null
+++ b/po/is.po
@@ -0,0 +1,93 @@
+# Icelandic translations for Git.
+# Copyright (C) 2010 Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+# This file is distributed under the same license as the Git package.
+# Ævar Arnfjörð Bjarmason <avarab@gmail.com>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Git\n"
+"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
+"POT-Creation-Date: 2010-09-20 14:44+0000\n"
+"PO-Revision-Date: 2010-06-05 19:06 +0000\n"
+"Last-Translator: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n"
+"Language-Team: Git Mailing List <git@vger.kernel.org>\n"
+"Language: is\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.c:5
+msgid "See 'git help COMMAND' for more information on a specific command."
+msgstr "Sjá 'git help SKIPUN' til að sjá hjálp fyrir tiltekna skipun."
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.c:10
+msgid "TEST: A C test string"
+msgstr "TILRAUN: C tilraunastrengur"
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.c:13
+#, c-format
+msgid "TEST: A C test string %s"
+msgstr "TILRAUN: C tilraunastrengur %s"
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.c:16
+#, c-format
+msgid "TEST: Hello World!"
+msgstr "TILRAUN: Halló Heimur!"
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.c:19
+#, c-format
+msgid "TEST: Old English Runes"
+msgstr "TILRAUN: ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ"
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.c:22
+#, c-format
+msgid "TEST: ‘single’ and “double” quotes"
+msgstr "TILRAUN: ‚einfaldar‘ og „tvöfaldar“ gæsalappir"
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.sh:8
+msgid "TEST: A Shell test string"
+msgstr "TILRAUN: Skeljartilraunastrengur"
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.sh:11
+#, sh-format
+msgid "TEST: A Shell test $variable"
+msgstr "TILRAUN: Skeljartilraunastrengur með breytunni $variable"
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.perl:8
+msgid "TEST: A Perl test string"
+msgstr "TILRAUN: Perl tilraunastrengur"
+
+#. TRANSLATORS: This is a test. You don't need to translate it.
+#: t/t0200/test.perl:11
+#, perl-format
+msgid "TEST: A Perl test variable %s"
+msgstr "TILRAUN: Perl tilraunastrengur með breytunni %s"
+
+#. TRANSLATORS: The first '%s' is either "Reinitialized
+#. existing" or "Initialized empty", the second " shared" or
+#. "", and the last '%s%s' is the verbatim directory name.
+#: builtin/init-db.c:355
+#, c-format
+msgid "%s%s Git repository in %s%s\n"
+msgstr "%s%s Git lind í %s%s\n"
+
+#: builtin/init-db.c:356
+msgid "Reinitialized existing"
+msgstr "Endurgerði"
+
+#: builtin/init-db.c:356
+msgid "Initialized empty"
+msgstr "Bjó til tóma"
+
+#: builtin/init-db.c:357
+msgid " shared"
+msgstr " sameiginlega"
diff --git a/shell.c b/shell.c
index abb8622..84b237f 100644
--- a/shell.c
+++ b/shell.c
@@ -137,6 +137,8 @@ int main(int argc, char **argv)
int devnull_fd;
int count;
+ git_setup_gettext();
+
git_extract_argv0_path(argv[0]);
/*
diff --git a/show-index.c b/show-index.c
index 63f9da5..5a9eed7 100644
--- a/show-index.c
+++ b/show-index.c
@@ -11,6 +11,8 @@ int main(int argc, char **argv)
unsigned int version;
static unsigned int top_index[256];
+ git_setup_gettext();
+
if (argc != 1)
usage(show_index_usage);
if (fread(top_index, 2 * 4, 1, stdin) != 1)
diff --git a/t/lib-gettext.sh b/t/lib-gettext.sh
new file mode 100644
index 0000000..0f76f6c
--- /dev/null
+++ b/t/lib-gettext.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
+#
+
+. ./test-lib.sh
+
+GIT_TEXTDOMAINDIR="$GIT_BUILD_DIR/po/build/locale"
+GIT_PO_PATH="$GIT_BUILD_DIR/po"
+export GIT_TEXTDOMAINDIR GIT_PO_PATH
+
+. "$GIT_BUILD_DIR"/git-sh-i18n
+
+if test_have_prereq GETTEXT && ! test_have_prereq GETTEXT_POISON
+then
+ # is_IS.UTF-8 on Solaris and FreeBSD, is_IS.utf8 on Debian
+ is_IS_locale=$(locale -a | sed -n '/^is_IS\.[uU][tT][fF]-*8$/{
+ p
+ q
+ }')
+ # is_IS.ISO8859-1 on Solaris and FreeBSD, is_IS.iso88591 on Debian
+ is_IS_iso_locale=$(locale -a | sed -n '/^is_IS\.[iI][sS][oO]8859-*1$/{
+ p
+ q
+ }')
+
+ # Export them as an environment variable so the t0202/test.pl Perl
+ # test can use it too
+ export is_IS_locale is_IS_iso_locale
+
+ if test -n "$is_IS_locale" &&
+ test $GIT_INTERNAL_GETTEXT_SH_SCHEME != "fallthrough"
+ then
+ # Some of the tests need the reference Icelandic locale
+ test_set_prereq GETTEXT_LOCALE
+
+ # Exporting for t0202/test.pl
+ GETTEXT_LOCALE=1
+ export GETTEXT_LOCALE
+ say "# lib-gettext: Found '$is_IS_locale' as an is_IS UTF-8 locale"
+ else
+ say "# lib-gettext: No is_IS UTF-8 locale available"
+ fi
+
+ if test -n "$is_IS_iso_locale" &&
+ test $GIT_INTERNAL_GETTEXT_SH_SCHEME != "fallthrough"
+ then
+ # Some of the tests need the reference Icelandic locale
+ test_set_prereq GETTEXT_ISO_LOCALE
+
+ say "# lib-gettext: Found '$is_IS_iso_locale' as an is_IS ISO-8859-1 locale"
+ else
+ say "# lib-gettext: No is_IS ISO-8859-1 locale available"
+ fi
+fi
diff --git a/t/t0200-gettext-basic.sh b/t/t0200-gettext-basic.sh
new file mode 100755
index 0000000..8853d8a
--- /dev/null
+++ b/t/t0200-gettext-basic.sh
@@ -0,0 +1,108 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
+#
+
+test_description='Gettext support for Git'
+
+. ./lib-gettext.sh
+
+test_expect_success "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" '
+ test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME"
+'
+
+test_expect_success 'sanity: $TEXTDOMAIN is git' '
+ test $TEXTDOMAIN = "git"
+'
+
+test_expect_success 'xgettext sanity: Perl _() strings are not extracted' '
+ ! grep "A Perl string xgettext will not get" "$GIT_PO_PATH"/is.po
+'
+
+test_expect_success 'xgettext sanity: Comment extraction with --add-comments' '
+ grep "TRANSLATORS: This is a test" "$TEST_DIRECTORY"/t0200/* | wc -l >expect &&
+ grep "TRANSLATORS: This is a test" "$GIT_PO_PATH"/is.po | wc -l >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'xgettext sanity: Comment extraction with --add-comments stops at statements' '
+ ! grep "This is a phony" "$GIT_PO_PATH"/is.po &&
+ ! grep "the above comment" "$GIT_PO_PATH"/is.po
+'
+
+test_expect_success GETTEXT 'sanity: $TEXTDOMAINDIR exists without NO_GETTEXT=YesPlease' '
+ test -d "$TEXTDOMAINDIR" &&
+ test "$TEXTDOMAINDIR" = "$GIT_TEXTDOMAINDIR"
+'
+
+test_expect_success GETTEXT 'sanity: Icelandic locale was compiled' '
+ test -f "$TEXTDOMAINDIR/is/LC_MESSAGES/git.mo"
+'
+
+# TODO: When we have more locales, generalize this to test them
+# all. Maybe we'll need a dir->locale map for that.
+test_expect_success GETTEXT_LOCALE 'sanity: gettext("") metadata is OK' '
+ # Return value may be non-zero
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "" >zero-expect &&
+ grep "Project-Id-Version: Git" zero-expect &&
+ grep "Git Mailing List <git@vger.kernel.org>" zero-expect &&
+ grep "Content-Type: text/plain; charset=UTF-8" zero-expect &&
+ grep "Content-Transfer-Encoding: 8bit" zero-expect
+'
+
+test_expect_success GETTEXT_LOCALE 'sanity: gettext(unknown) is passed through' '
+ printf "This is not a translation string" >expect &&
+ gettext "This is not a translation string" >actual &&
+ eval_gettext "This is not a translation string" >actual &&
+ test_cmp expect actual
+'
+
+# xgettext from C
+test_expect_success GETTEXT_LOCALE 'xgettext: C extraction of _() and N_() strings' '
+ printf "TILRAUN: C tilraunastrengur" >expect &&
+ printf "\n" >>expect &&
+ printf "Sjá '\''git help SKIPUN'\'' til að sjá hjálp fyrir tiltekna skipun." >>expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A C test string" >actual &&
+ printf "\n" >>actual &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "See '\''git help COMMAND'\'' for more information on a specific command." >>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GETTEXT_LOCALE 'xgettext: C extraction with %s' '
+ printf "TILRAUN: C tilraunastrengur %%s" >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A C test string %s" >actual &&
+ test_cmp expect actual
+'
+
+# xgettext from Shell
+test_expect_success GETTEXT_LOCALE 'xgettext: Shell extraction' '
+ printf "TILRAUN: Skeljartilraunastrengur" >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A Shell test string" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GETTEXT_LOCALE 'xgettext: Shell extraction with $variable' '
+ printf "TILRAUN: Skeljartilraunastrengur með breytunni a var i able" >x-expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" variable="a var i able" eval_gettext "TEST: A Shell test \$variable" >x-actual &&
+ test_cmp x-expect x-actual
+'
+
+# xgettext from Perl
+test_expect_success GETTEXT_LOCALE 'xgettext: Perl extraction' '
+ printf "TILRAUN: Perl tilraunastrengur" >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A Perl test string" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GETTEXT_LOCALE 'xgettext: Perl extraction with %s' '
+ printf "TILRAUN: Perl tilraunastrengur með breytunni %%s" >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A Perl test variable %s" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GETTEXT_LOCALE 'sanity: Some gettext("") data for real locale' '
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "" >real-locale &&
+ test -s real-locale
+'
+
+test_done
diff --git a/t/t0200/test.c b/t/t0200/test.c
new file mode 100644
index 0000000..584d45c
--- /dev/null
+++ b/t/t0200/test.c
@@ -0,0 +1,23 @@
+/* This is a phony C program that's only here to test xgettext message extraction */
+
+const char help[] =
+ /* TRANSLATORS: This is a test. You don't need to translate it. */
+ N_("See 'git help COMMAND' for more information on a specific command.");
+
+int main(void)
+{
+ /* TRANSLATORS: This is a test. You don't need to translate it. */
+ puts(_("TEST: A C test string"));
+
+ /* TRANSLATORS: This is a test. You don't need to translate it. */
+ printf(_("TEST: A C test string %s"), "variable");
+
+ /* TRANSLATORS: This is a test. You don't need to translate it. */
+ printf(_("TEST: Hello World!"));
+
+ /* TRANSLATORS: This is a test. You don't need to translate it. */
+ printf(_("TEST: Old English Runes"));
+
+ /* TRANSLATORS: This is a test. You don't need to translate it. */
+ printf(_("TEST: ‘single’ and “double” quotes"));
+}
diff --git a/t/t0200/test.perl b/t/t0200/test.perl
new file mode 100644
index 0000000..36fba34
--- /dev/null
+++ b/t/t0200/test.perl
@@ -0,0 +1,14 @@
+# This is a phony Perl program that's only here to test xgettext
+# message extraction
+
+# so the above comment won't be folded into the next one by xgettext
+1;
+
+# TRANSLATORS: This is a test. You don't need to translate it.
+print __("TEST: A Perl test string");
+
+# TRANSLATORS: This is a test. You don't need to translate it.
+printf __("TEST: A Perl test variable %s"), "moo";
+
+# TRANSLATORS: If you see this, Git has a bug
+print _"TEST: A Perl string xgettext will not get";
diff --git a/t/t0200/test.sh b/t/t0200/test.sh
new file mode 100644
index 0000000..022d607
--- /dev/null
+++ b/t/t0200/test.sh
@@ -0,0 +1,14 @@
+# This is a phony Shell program that's only here to test xgettext
+# message extraction
+
+# so the above comment won't be folded into the next one by xgettext
+echo
+
+# TRANSLATORS: This is a test. You don't need to translate it.
+gettext "TEST: A Shell test string"
+
+# TRANSLATORS: This is a test. You don't need to translate it.
+eval_gettext "TEST: A Shell test \$variable"
+
+# TRANSLATORS: If you see this, Git has a bug
+_("TEST: A Shell string xgettext won't get")
diff --git a/t/t0201-gettext-fallbacks.sh b/t/t0201-gettext-fallbacks.sh
index 54d98b9..52b1c27 100755
--- a/t/t0201-gettext-fallbacks.sh
+++ b/t/t0201-gettext-fallbacks.sh
@@ -5,8 +5,24 @@
test_description='Gettext Shell fallbacks'
-. ./test-lib.sh
-. "$GIT_BUILD_DIR"/git-sh-i18n
+GIT_INTERNAL_GETTEXT_TEST_FALLBACKS=YesPlease
+export GIT_INTERNAL_GETTEXT_TEST_FALLBACKS
+
+. ./lib-gettext.sh
+
+test_expect_success "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" '
+ test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME"
+'
+
+test_expect_success 'sanity: $GIT_INTERNAL_GETTEXT_TEST_FALLBACKS is set' '
+ test -n "$GIT_INTERNAL_GETTEXT_TEST_FALLBACKS"
+'
+
+test_expect_success C_LOCALE_OUTPUT 'sanity: $GIT_INTERNAL_GETTEXT_SH_SCHEME" is fallthrough' '
+ echo fallthrough >expect &&
+ echo $GIT_INTERNAL_GETTEXT_SH_SCHEME >actual &&
+ test_cmp expect actual
+'
test_expect_success 'gettext: our gettext() fallback has pass-through semantics' '
printf "test" >expect &&
diff --git a/t/t0202-gettext-perl.sh b/t/t0202-gettext-perl.sh
new file mode 100755
index 0000000..428ebb0
--- /dev/null
+++ b/t/t0202-gettext-perl.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
+#
+
+test_description='Perl gettext interface (Git::I18N)'
+
+. ./lib-gettext.sh
+
+if ! test_have_prereq PERL; then
+ skip_all='skipping perl interface tests, perl not available'
+ test_done
+fi
+
+"$PERL_PATH" -MTest::More -e 0 2>/dev/null || {
+ skip_all="Perl Test::More unavailable, skipping test"
+ test_done
+}
+
+# The external test will outputs its own plan
+test_external_has_tap=1
+
+test_external_without_stderr \
+ 'Perl Git::I18N API' \
+ "$PERL_PATH" "$TEST_DIRECTORY"/t0202/test.pl
+
+test_done
diff --git a/t/t0202/test.pl b/t/t0202/test.pl
new file mode 100644
index 0000000..2c10cb4
--- /dev/null
+++ b/t/t0202/test.pl
@@ -0,0 +1,110 @@
+#!/usr/bin/perl
+use 5.008;
+use lib (split(/:/, $ENV{GITPERLLIB}));
+use strict;
+use warnings;
+use POSIX qw(:locale_h);
+use Test::More tests => 8;
+use Git::I18N;
+
+my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;
+
+ok(1, "Testing Git::I18N with " .
+ ($has_gettext_library
+ ? (defined $Locale::Messages::VERSION
+ ? "Locale::Messages version $Locale::Messages::VERSION"
+ # Versions of Locale::Messages before 1.17 didn't have a
+ # $VERSION variable.
+ : "Locale::Messages version <1.17")
+ : "NO Perl gettext library"));
+ok(1, "Git::I18N is located at $INC{'Git/I18N.pm'}");
+
+{
+ my $exports = @Git::I18N::EXPORT;
+ ok($exports, "sanity: Git::I18N has $exports export(s)");
+}
+is_deeply(\@Git::I18N::EXPORT, \@Git::I18N::EXPORT_OK, "sanity: Git::I18N exports everything by default");
+
+# prototypes
+{
+ # Add prototypes here when modifying the public interface to add
+ # more gettext wrapper functions.
+ my %prototypes = (qw(
+ __ $
+ ));
+ while (my ($sub, $proto) = each %prototypes) {
+ is(prototype(\&{"Git::I18N::$sub"}), $proto, "sanity: $sub has a $proto prototype");
+ }
+}
+
+# Test basic passthrough in the C locale
+{
+ local $ENV{LANGUAGE} = 'C';
+ local $ENV{LC_ALL} = 'C';
+ local $ENV{LANG} = 'C';
+
+ my ($got, $expect) = (('TEST: A Perl test string') x 2);
+
+ is(__($got), $expect, "Passing a string through __() in the C locale works");
+}
+
+# Test a basic message on different locales
+SKIP: {
+ unless ($ENV{GETTEXT_LOCALE}) {
+ # Can't reliably test __() with a non-C locales because the
+ # required locales may not be installed on the system.
+ #
+ # We test for these anyway as part of the shell
+ # tests. Skipping these here will eliminate failures on odd
+ # platforms with incomplete locale data.
+
+ skip "GETTEXT_LOCALE must be set by lib-gettext.sh for exhaustive Git::I18N tests", 2;
+ }
+
+ # The is_IS UTF-8 locale passed from lib-gettext.sh
+ my $is_IS_locale = $ENV{is_IS_locale};
+
+ my $test = sub {
+ my ($got, $expect, $msg, $locale) = @_;
+ # Maybe this system doesn't have the locale we're trying to
+ # test.
+ my $locale_ok = setlocale(LC_ALL, $locale);
+ is(__($got), $expect, "$msg a gettext library + <$locale> locale <$got> turns into <$expect>");
+ };
+
+ my $env_C = sub {
+ $ENV{LANGUAGE} = 'C';
+ $ENV{LC_ALL} = 'C';
+ };
+
+ my $env_is = sub {
+ $ENV{LANGUAGE} = 'is';
+ $ENV{LC_ALL} = $is_IS_locale;
+ };
+
+ # Translation's the same as the original
+ my ($got, $expect) = (('TEST: A Perl test string') x 2);
+
+ if ($has_gettext_library) {
+ {
+ local %ENV; $env_C->();
+ $test->($got, $expect, "With", 'C');
+ }
+
+ {
+ my ($got, $expect) = ($got, 'TILRAUN: Perl tilraunastrengur');
+ local %ENV; $env_is->();
+ $test->($got, $expect, "With", $is_IS_locale);
+ }
+ } else {
+ {
+ local %ENV; $env_C->();
+ $test->($got, $expect, "Without", 'C');
+ }
+
+ {
+ local %ENV; $env_is->();
+ $test->($got, $expect, "Without", 'is');
+ }
+ }
+}
diff --git a/t/t0203-gettext-setlocale-sanity.sh b/t/t0203-gettext-setlocale-sanity.sh
new file mode 100755
index 0000000..a212460
--- /dev/null
+++ b/t/t0203-gettext-setlocale-sanity.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
+#
+
+test_description="The Git C functions aren't broken by setlocale(3)"
+
+. ./lib-gettext.sh
+
+test_expect_success 'git show a ISO-8859-1 commit under C locale' '
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
+ test_commit "iso-c-commit" iso-under-c &&
+ git show >out 2>err &&
+ ! test -s err &&
+ grep -q "iso-c-commit" out
+'
+
+test_expect_success GETTEXT_LOCALE 'git show a ISO-8859-1 commit under a UTF-8 locale' '
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
+ test_commit "iso-utf8-commit" iso-under-utf8 &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" git show >out 2>err &&
+ ! test -s err &&
+ grep -q "iso-utf8-commit" out
+'
+
+test_done
diff --git a/t/t0204-gettext-reencode-sanity.sh b/t/t0204-gettext-reencode-sanity.sh
new file mode 100755
index 0000000..189af90
--- /dev/null
+++ b/t/t0204-gettext-reencode-sanity.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
+#
+
+test_description="Gettext reencoding of our *.po/*.mo files works"
+
+. ./lib-gettext.sh
+
+
+test_expect_success GETTEXT_LOCALE 'gettext: Emitting UTF-8 from our UTF-8 *.mo files / Icelandic' '
+ printf "TILRAUN: Halló Heimur!" >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: Hello World!" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GETTEXT_LOCALE 'gettext: Emitting UTF-8 from our UTF-8 *.mo files / Runes' '
+ printf "TILRAUN: ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ" >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: Old English Runes" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GETTEXT_ISO_LOCALE 'gettext: Emitting ISO-8859-1 from our UTF-8 *.mo files / Icelandic' '
+ printf "TILRAUN: Halló Heimur!" | iconv -f UTF-8 -t ISO8859-1 >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_iso_locale" gettext "TEST: Hello World!" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GETTEXT_ISO_LOCALE 'gettext: Emitting ISO-8859-1 from our UTF-8 *.mo files / Runes' '
+ LANGUAGE=is LC_ALL="$is_IS_iso_locale" gettext "TEST: Old English Runes" >runes &&
+
+ if grep "^TEST: Old English Runes$" runes
+ then
+ say "Your system can not handle this complexity and returns the string as-is"
+ else
+ # Both Solaris and GNU libintl will return this stream of
+ # question marks, so it is s probably portable enough
+ printf "TILRAUN: ?? ???? ??? ?? ???? ?? ??? ????? ??????????? ??? ?? ????" >runes-expect &&
+ test_cmp runes-expect runes
+ fi
+'
+
+test_expect_success GETTEXT_LOCALE 'gettext: Fetching a UTF-8 msgid -> UTF-8' '
+ printf "TILRAUN: ‚einfaldar‘ og „tvöfaldar“ gæsalappir" >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: ‘single’ and “double” quotes" >actual &&
+ test_cmp expect actual
+'
+
+# How these quotes get transliterated depends on the gettext implementation:
+#
+# Debian: ,einfaldar' og ,,tvöfaldar" [GNU libintl]
+# FreeBSD: `einfaldar` og "tvöfaldar" [GNU libintl]
+# Solaris: ?einfaldar? og ?tvöfaldar? [Solaris libintl]
+#
+# Just make sure the contents are transliterated, and don't use grep -q
+# so that these differences are emitted under --verbose for curious
+# eyes.
+test_expect_success GETTEXT_ISO_LOCALE 'gettext: Fetching a UTF-8 msgid -> ISO-8859-1' '
+ LANGUAGE=is LC_ALL="$is_IS_iso_locale" gettext "TEST: ‘single’ and “double” quotes" >actual &&
+ grep "einfaldar" actual &&
+ grep "$(echo tvöfaldar | iconv -f UTF-8 -t ISO8859-1)" actual
+'
+
+test_expect_success GETTEXT_LOCALE 'gettext.c: git init UTF-8 -> UTF-8' '
+ printf "Bjó til tóma Git lind" >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_locale" git init repo >actual &&
+ test_when_finished "rm -rf repo" &&
+ grep "^$(cat expect) " actual
+'
+
+test_expect_success GETTEXT_ISO_LOCALE 'gettext.c: git init UTF-8 -> ISO-8859-1' '
+ printf "Bjó til tóma Git lind" >expect &&
+ LANGUAGE=is LC_ALL="$is_IS_iso_locale" git init repo >actual &&
+ test_when_finished "rm -rf repo" &&
+ grep "^$(cat expect | iconv -f UTF-8 -t ISO8859-1) " actual
+'
+
+test_done
diff --git a/t/t0205-gettext-poison.sh b/t/t0205-gettext-poison.sh
new file mode 100755
index 0000000..2361590
--- /dev/null
+++ b/t/t0205-gettext-poison.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
+#
+
+test_description='Gettext Shell poison'
+
+. ./lib-gettext.sh
+
+test_expect_success GETTEXT_POISON "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" '
+ test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME"
+'
+
+test_expect_success GETTEXT_POISON 'sanity: $GIT_INTERNAL_GETTEXT_SH_SCHEME" is poison' '
+ test "$GIT_INTERNAL_GETTEXT_SH_SCHEME" = "poison"
+'
+
+test_expect_success GETTEXT_POISON 'gettext: our gettext() fallback has poison semantics' '
+ printf "# GETTEXT POISON #" >expect &&
+ gettext "test" >actual &&
+ test_cmp expect actual &&
+ printf "# GETTEXT POISON #" >expect &&
+ gettext "test more words" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GETTEXT_POISON 'eval_gettext: our eval_gettext() fallback has poison semantics' '
+ printf "# GETTEXT POISON #" >expect &&
+ eval_gettext "test" >actual &&
+ test_cmp expect actual &&
+ printf "# GETTEXT POISON #" >expect &&
+ eval_gettext "test more words" >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index bdd9513..9cfabe4 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -44,6 +44,7 @@ export LANG LC_ALL PAGER TERM TZ
EDITOR=:
unset VISUAL
unset EMAIL
+unset LANGUAGE
unset $(perl -e '
my @env = keys %ENV;
my $ok = join("|", qw(
@@ -1113,12 +1114,14 @@ esac
test -z "$NO_PERL" && test_set_prereq PERL
test -z "$NO_PYTHON" && test_set_prereq PYTHON
test -n "$USE_LIBPCRE" && test_set_prereq LIBPCRE
+test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
# Can we rely on git's output in the C locale?
if test -n "$GETTEXT_POISON"
then
GIT_GETTEXT_POISON=YesPlease
export GIT_GETTEXT_POISON
+ test_set_prereq GETTEXT_POISON
else
test_set_prereq C_LOCALE_OUTPUT
fi
diff --git a/upload-pack.c b/upload-pack.c
index 470cffd..6f36f62 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -784,6 +784,8 @@ int main(int argc, char **argv)
int i;
int strict = 0;
+ git_setup_gettext();
+
packet_trace_identity("upload-pack");
git_extract_argv0_path(argv[0]);
read_replace_refs = 0;
diff --git a/wrap-for-bin.sh b/wrap-for-bin.sh
index 09feb1f..53a8dd0 100644
--- a/wrap-for-bin.sh
+++ b/wrap-for-bin.sh
@@ -15,7 +15,8 @@ else
export GIT_TEMPLATE_DIR
fi
GITPERLLIB='@@BUILD_DIR@@/perl/blib/lib'
+GIT_TEXTDOMAINDIR='@@BUILD_DIR@@/po/build/locale'
PATH='@@BUILD_DIR@@/bin-wrappers:'"$PATH"
-export GIT_EXEC_PATH GITPERLLIB PATH
+export GIT_EXEC_PATH GITPERLLIB PATH GIT_TEXTDOMAINDIR
exec "${GIT_EXEC_PATH}/@@PROG@@" "$@"
--
1.7.8.145.gd94c5
^ permalink raw reply related
* What's cooking in git.git (Dec 2011, #02; Mon, 5)
From: Junio C Hamano @ 2011-12-06 5:01 UTC (permalink / raw)
To: git
Here are the topics that have been cooking. Commits prefixed with '-' are
only in 'pu' (proposed updates) while commits prefixed with '+' are in
'next'.
The tip of 'next' will be rewound soonish, kicking a handful of topics
back to 'pu' that are important enough to get them right rather than
piling "oops, that was a mistake" fix-ups in 'next'.
All of the topics in Stalled section will be purged without prejudice;
owners of respective topics are free to re-submit after addressing the
issues raised during the previous reviews and re-ignite the discussion.
Here are the repositories that have my integration branches:
With maint, master, next, pu, todo:
git://git.kernel.org/pub/scm/git/git.git
git://repo.or.cz/alt-git.git
https://code.google.com/p/git-core/
https://github.com/git/git
With only maint and master:
git://git.sourceforge.jp/gitroot/git-core/git.git
git://git-core.git.sourceforge.net/gitroot/git-core/git-core
With all the topics and integration branches:
https://github.com/gitster/git
The preformatted documentation in HTML and man format are found in:
git://git.kernel.org/pub/scm/git/git-{htmldocs,manpages}.git/
git://repo.or.cz/git-{htmldocs,manpages}.git/
https://code.google.com/p/git-{htmldocs,manpages}.git/
https://github.com/gitster/git-{htmldocs,manpages}.git/
--------------------------------------------------
[New Topics]
* bc/maint-apply-check-no-patch (2011-12-05) 2 commits
- builtin/apply.c: report error on failure to recognize input
- t/t4131-apply-fake-ancestor.sh: fix broken test
Will merge to 'next'.
--------------------------------------------------
[Graduated to "master"]
* ab/clang-lints (2011-11-06) 2 commits
(merged to 'next' on 2011-11-13 at a573aec)
+ cast variable in call to free() in builtin/diff.c and submodule.c
+ apply: get rid of useless x < 0 comparison on a size_t type
* gh/userdiff-matlab (2011-11-15) 1 commit
(merged to 'next' on 2011-11-18 at 10cd275)
+ Add built-in diff patterns for MATLAB code
* jc/maint-pack-object-cycle (2011-11-16) 1 commit
(merged to 'next' on 2011-11-18 at 3715a81)
+ pack-object: tolerate broken packs that have duplicated objects
Make the client side more robust against bogus pack stream; the problem
was discovered by accident while repacking a clone obtained from somewhat
buggy test server.
* jc/index-pack-reject-dups (2011-11-16) 1 commit
(merged to 'next' on 2011-11-18 at 2090221)
+ receive-pack, fetch-pack: reject bogus pack that records objects twice
And this is the prevention to reject such pack stream in the first place.
* jk/refresh-porcelain-output (2011-11-18) 3 commits
(merged to 'next' on 2011-11-18 at 872f25e)
+ refresh_index: make porcelain output more specific
+ refresh_index: rename format variables
+ read-cache: let refresh_cache_ent pass up changed flags
* mf/curl-select-fdset (2011-11-04) 4 commits
(merged to 'next' on 2011-11-06 at a49516f)
+ http: drop "local" member from request struct
+ http.c: Rely on select instead of tracking whether data was received
+ http.c: Use timeout suggested by curl instead of fixed 50ms timeout
+ http.c: Use curl_multi_fdset to select on curl fds instead of just sleeping
Reduces unnecessary waits.
* na/strtoimax (2011-11-05) 3 commits
(merged to 'next' on 2011-11-14 at b64e1cb)
+ Support sizes >=2G in various config options accepting 'g' sizes.
+ Compatibility: declare strtoimax() under NO_STRTOUMAX
+ Add strtoimax() compatibility function.
* nd/fsck-progress (2011-11-06) 4 commits
(merged to 'next' on 2011-11-13 at 8831811)
+ fsck: print progress
+ fsck: avoid reading every object twice
+ verify_packfile(): check as many object as possible in a pack
+ fsck: return error code when verify_pack() goes wrong
* nd/maint-ignore-exclude (2011-11-28) 1 commit
+ checkout,merge: loosen overwriting untracked file check based on info/exclude
(this branch is used by nd/ignore-might-be-precious.)
* nd/misc-cleanups (2011-10-27) 6 commits
(merged to 'next' on 2011-10-28 at 2527a49)
+ unpack_object_header_buffer(): clear the size field upon error
+ tree_entry_interesting: make use of local pointer "item"
+ tree_entry_interesting(): give meaningful names to return values
+ read_directory_recursive: reduce one indentation level
+ get_tree_entry(): do not call find_tree_entry() on an empty tree
+ tree-walk.c: do not leak internal structure in tree_entry_len()
* nd/prune-progress (2011-11-07) 3 commits
(merged to 'next' on 2011-11-13 at c5722ac)
+ reachable: per-object progress
+ prune: handle --progress/no-progress
+ prune: show progress while marking reachable objects
* vr/git-merge-doc (2011-11-21) 1 commit
+ Show error for 'git merge' with unset merge.defaultToUpstream
* vr/msvc (2011-10-31) 3 commits
(merged to 'next' on 2011-11-14 at f46d021)
+ MSVC: Remove unneeded header stubs
+ Compile fix for MSVC: Include <io.h>
+ Compile fix for MSVC: Do not include sys/resources.h
--------------------------------------------------
[Stalled]
All of the topics in Stalled section will be discarded soonish (see the
cover).
* hv/submodule-merge-search (2011-10-13) 4 commits
- submodule.c: make two functions static
- allow multiple calls to submodule merge search for the same path
- push: Don't push a repository with unpushed submodules
- push: teach --recurse-submodules the on-demand option
What the topic aims to achieve may make sense, but the implementation
looked somewhat suboptimal.
* sr/transport-helper-fix-rfc (2011-07-19) 2 commits
- t5800: point out that deleting branches does not work
- t5800: document inability to push new branch with old content
See comments on sr/fix-fast-export-tips topic.
* sr/fix-fast-export-tips (2011-11-05) 3 commits
- fast-export: output reset command for commandline revs
- fast-export: do not refer to non-existing marks
- t9350: point out that refs are not updated correctly
The bottom commit from the stalled sr/transport-helper-fix-rfc topic is
fixed with this. It may make sense to drop the other topic and include
that commit in this series.
The command line parser is still too lax and accepts malformed input, but
this is a step in the right direction and tightening the command line now
should be doable without a low level surgery that touches codepaths that
are unrelated to the command line processing like the previous attempt
used to do.
* jc/lookup-object-hash (2011-08-11) 6 commits
- object hash: replace linear probing with 4-way cuckoo hashing
- object hash: we know the table size is a power of two
- object hash: next_size() helper for readability
- pack-objects --count-only
- object.c: remove duplicated code for object hashing
- object.c: code movement for readability
I do not think there is anything fundamentally wrong with this series, but
the risk of breakage far outweighs observed performance gain in one
particular workload.
* jc/verbose-checkout (2011-10-16) 2 commits
- checkout -v: give full status output after switching branches
- checkout: move the local changes report to the end
This is just to leave a record that the reason why we do not do this not
because we are incapable of coding this, but because it is not a good idea
to do this. I suspect people who are new to git that might think they need
it would soon realize the don't.
Will drop.
* eh/grep-scale-to-cpunum (2011-11-05) 1 commit
- grep: detect number of CPUs for thread spawning
Kills I/O parallelism and needs to be improved or discarded.
* jc/commit-tree-extra (2011-11-12) 2 commits
- commit-tree: teach -C <extra-commit>
- commit-tree: teach -x <extra>
(this branch uses jc/pull-signed-tag; is tangled with jc/signed-commit.)
Not absolutely needed; parked in 'pu' but may drop.
* cb/daemon-permission-errors (2011-10-17) 2 commits
- daemon: report permission denied error to clients
- daemon: add tests
The tip commit might be loosening things a bit too much.
--------------------------------------------------
[Cooking]
* sg/complete-refs (2011-10-21) 9 commits
(merged to 'next' on 2011-10-26 at d65e2b4)
+ completion: remove broken dead code from __git_heads() and __git_tags()
+ completion: fast initial completion for config 'remote.*.fetch' value
+ completion: improve ls-remote output filtering in __git_refs_remotes()
+ completion: query only refs/heads/ in __git_refs_remotes()
+ completion: support full refs from remote repositories
+ completion: improve ls-remote output filtering in __git_refs()
+ completion: make refs completion consistent for local and remote repos
+ completion: optimize refs completion
+ completion: document __gitcomp()
Will merge to 'master.
* aw/rebase-i-stop-on-failure-to-amend (2011-11-30) 1 commit
- rebase -i: interrupt rebase when "commit --amend" failed during "reword"
Will merge to 'next'.
* jc/split-blob (2011-12-01) 6 commits
. WIP (streaming chunked)
- chunked-object: fallback checkout codepaths
- bulk-checkin: support chunked-object encoding
- bulk-checkin: allow the same data to be multiply hashed
- new representation types in the packstream
- varint-in-pack: refactor varint encoding/decoding
(this branch uses jc/stream-to-pack.)
Not ready.
* jh/fast-import-notes (2011-11-28) 3 commits
- fast-import: Fix incorrect fanout level when modifying existing notes refs
- t9301: Add 2nd testcase exposing bugs in fast-import's notes fanout handling
- t9301: Fix testcase covering up a bug in fast-import's notes fanout handling
Will merge to 'next'.
* ld/p4-labels-branches (2011-11-30) 4 commits
- git-p4: importing labels should cope with missing owner
- git-p4: add test for p4 labels
- git-p4: cope with labels with empty descriptions
- git-p4: handle p4 branches and labels containing shell chars
I understand this has been retracted---please correct me otherwise.
Will discard, expecting a reroll.
* tj/maint-imap-send-remove-unused (2011-11-23) 2 commits
- Merge branch 'maint' into tj/imap-send-remove-unused
- imap-send: Remove unused 'use_namespace' variable
Will merge to 'next'.
* cn/maint-lf-to-crlf-filter (2011-11-28) 1 commit
- convert: track state in LF-to-CRLF filter
Will merge to 'next' after taking another look.
* jn/branch-move-to-self (2011-11-28) 2 commits
- Allow checkout -B <current-branch> to update the current branch
- branch: allow a no-op "branch -M <current-branch> HEAD"
Will merge to 'next' after taking another look.
* jk/credentials (2011-11-28) 20 commits
- fixup! 034c066e
- compat/getpass: add a /dev/tty implementation
- credential: use git_prompt instead of git_getpass
- prompt: add PROMPT_ECHO flag
- stub out getpass_echo function
- refactor git_getpass into generic prompt function
- move git_getpass to its own source file
- t: add test harness for external credential helpers
- credentials: add "store" helper
- strbuf: add strbuf_add*_urlencode
- credentials: add "cache" helper
- docs: end-user documentation for the credential subsystem
- credential: make relevance of http path configurable
- credential: add credential.*.username
- credential: apply helper config
- http: use credential API to get passwords
- credential: add function for parsing url components
- introduce credentials API
- t5550: fix typo
- test-lib: add test_config_global variant
Expecting a reroll?
* nd/ignore-might-be-precious (2011-11-28) 2 commits
- checkout,merge: disallow overwriting ignored files with --no-overwrite-ignore
- Merge branch 'nd/maint-ignore-exclude' into nd/ignore-might-be-precious
Will merge to 'next' after taking another look.
* jk/upload-archive-use-start-command (2011-11-21) 1 commit
- upload-archive: use start_command instead of fork
What's the status of this one?
* jk/maint-1.6.2-upload-archive (2011-11-21) 1 commit
- archive: don't let remote clients get unreachable commits
(this branch is used by jk/maint-upload-archive.)
* jk/maint-upload-archive (2011-11-21) 1 commit
- Merge branch 'jk/maint-1.6.2-upload-archive' into jk/maint-upload-archive
(this branch uses jk/maint-1.6.2-upload-archive.)
Will merge to 'next' after taking another look.
* ab/enable-i18n (2011-12-05) 2 commits
- Makefile: Add missing "sparse object" to gettext target-specific rule
- i18n: add infrastructure for translating Git with gettext
Will merge to 'next' after squashing the two and re-sending to the list
for review comments.
* nd/resolve-ref (2011-12-05) 2 commits
(merged to 'next' on 2011-12-05 at cc79e86)
+ Copy resolve_ref() return value for longer use
+ Convert many resolve_ref() calls to read_ref*() and ref_exists()
Will merge to 'master'.
* jc/signed-commit (2011-11-29) 5 commits
- gpg-interface: allow use of a custom GPG binary
- pretty: %G[?GS] placeholders
- test "commit -S" and "log --show-signature"
- log: --show-signature
- commit: teach --gpg-sign option
(this branch uses jc/pull-signed-tag; is tangled with jc/commit-tree-extra.)
Not exactly urgent.
Will concentrate on getting jc/pull-signed-tag in first.
* jc/pull-signed-tag (2011-11-12) 15 commits
(merged to 'next' on 2011-11-14 at 25e8838)
+ commit-tree: teach -m/-F options to read logs from elsewhere
+ commit-tree: update the command line parsing
+ commit: teach --amend to carry forward extra headers
+ merge: force edit and no-ff mode when merging a tag object
+ commit: copy merged signed tags to headers of merge commit
+ merge: record tag objects without peeling in MERGE_HEAD
+ merge: make usage of commit->util more extensible
+ fmt-merge-msg: Add contents of merged tag in the merge message
+ fmt-merge-msg: package options into a structure
+ fmt-merge-msg: avoid early returns
+ refs DWIMmery: use the same rule for both "git fetch" and others
+ fetch: allow "git fetch $there v1.0" to fetch a tag
+ merge: notice local merging of tags and keep it unwrapped
+ fetch: do not store peeled tag object names in FETCH_HEAD
+ Split GPG interface into its own helper library
(this branch is used by jc/commit-tree-extra and jc/signed-commit.)
Allow pulling/merging a signed tag instead of a branch tip, and record
the GPG signature in the merge commit for later audit.
Will merge to 'master'.
* jc/request-pull-show-head-4 (2011-11-09) 12 commits
(merged to 'next' on 2011-11-13 at e473fd2)
+ request-pull: use the annotated tag contents
(merged to 'next' on 2011-10-15 at 7e340ff)
+ fmt-merge-msg.c: Fix an "dubious one-bit signed bitfield" sparse error
(merged to 'next' on 2011-10-10 at 092175e)
+ environment.c: Fix an sparse "symbol not declared" warning
+ builtin/log.c: Fix an "Using plain integer as NULL pointer" warning
(merged to 'next' on 2011-10-07 at fcaeca0)
+ fmt-merge-msg: use branch.$name.description
(merged to 'next' on 2011-10-06 at fa5e0fe)
+ request-pull: use the branch description
+ request-pull: state what commit to expect
+ request-pull: modernize style
+ branch: teach --edit-description option
+ format-patch: use branch description in cover letter
+ branch: add read_branch_desc() helper function
+ Merge branch 'bk/ancestry-path' into jc/branch-desc
Allow setting "description" for branches and use it to help communications
between humans in various workflow elements. It also allows requesting for
a signed tag to be pulled and shows the tag message in the generated message.
Will merge to 'master'.
* ab/pull-rebase-config (2011-11-07) 1 commit
(merged to 'next' on 2011-11-13 at 72bb2d5)
+ pull: introduce a pull.rebase option to enable --rebase
Will merge to 'master'.
* jc/stream-to-pack (2011-12-01) 5 commits
- bulk-checkin: replace fast-import based implementation
- csum-file: introduce sha1file_checkpoint
- finish_tmp_packfile(): a helper function
- create_tmp_packfile(): a helper function
- write_pack_header(): a helper function
(this branch is used by jc/split-blob.)
Teaches "git add" to send large-ish blob data straight to a packfile.
This is a continuation to the "large file support" topic. The codepath to
move data from worktree to repository is made aware of streaming, just
like the checkout codepath that goes the other way, which was done in the
previous "large file support" topic in the 1.7.7 cycle.
Will merge to 'next'.
* jn/gitweb-side-by-side-diff (2011-10-31) 8 commits
- gitweb: Add navigation to select side-by-side diff
- gitweb: Use href(-replay=>1,...) for formats links in "commitdiff"
- t9500: Add basic sanity tests for side-by-side diff in gitweb
- t9500: Add test for handling incomplete lines in diff by gitweb
- gitweb: Give side-by-side diff extra CSS styling
- gitweb: Add a feature to show side-by-side diff
- gitweb: Extract formatting of diff chunk header
- gitweb: Refactor diff body line classification
Replaces a series from Kato Kazuyoshi on the same topic.
Is this ready for 'next'?
* rs/allocate-cache-entry-individually (2011-10-26) 2 commits
(merged to 'next' on 2011-10-27 at 2e4acd6)
+ cache.h: put single NUL at end of struct cache_entry
+ read-cache.c: allocate index entries individually
Will merge to 'master'.
* rr/revert-cherry-pick (2011-10-23) 5 commits
(merged to 'next' on 2011-10-26 at 27b7496)
+ revert: simplify communicating command-line arguments
+ revert: allow mixed pick and revert instructions
+ revert: make commit subjects in insn sheet optional
+ revert: simplify getting commit subject in format_todo()
+ revert: free msg in format_todo()
The internals of "git revert/cherry-pick" has been further refactored to
serve as the basis for the sequencer.
Is this ready for 'master', or should we eject it to 'pu', expecing a
re-roll?
* mh/ref-api-2 (2011-11-16) 15 commits
(merged to 'next' on 2011-11-16 at 511457f)
+ refs: loosen over-strict "format" check
(merged to 'next' on 2011-10-19 at cc89f0e)
+ resolve_gitlink_ref_recursive(): change to work with struct ref_cache
+ Pass a (ref_cache *) to the resolve_gitlink_*() helper functions
+ resolve_gitlink_ref(): improve docstring
+ get_ref_dir(): change signature
+ refs: change signatures of get_packed_refs() and get_loose_refs()
+ is_dup_ref(): extract function from sort_ref_array()
+ add_ref(): add docstring
+ parse_ref_line(): add docstring
+ is_refname_available(): remove the "quiet" argument
+ clear_ref_array(): rename from free_ref_array()
+ refs: rename parameters result -> sha1
+ refs: rename "refname" variables
+ struct ref_entry: document name member
+ cache.h: add comments for git_path() and git_path_submodule()
(this branch is tangled with mh/ref-api-3.)
Expecting a re-roll; will eject from 'pu' so that the topic can lose the
hot-fix at the tip.
* mh/ref-api-3 (2011-11-16) 26 commits
(merged to 'next' on 2011-11-16 at cc76151)
+ refs: loosen over-strict "format" check
(merged to 'next' on 2011-10-23 at 92e2d35)
+ is_refname_available(): reimplement using do_for_each_ref_in_array()
+ names_conflict(): simplify implementation
+ names_conflict(): new function, extracted from is_refname_available()
+ repack_without_ref(): reimplement using do_for_each_ref_in_array()
+ do_for_each_ref_in_array(): new function
+ do_for_each_ref(): correctly terminate while processesing extra_refs
+ add_ref(): take a (struct ref_entry *) parameter
+ create_ref_entry(): extract function from add_ref()
+ parse_ref_line(): add a check that the refname is properly formatted
+ repack_without_ref(): remove temporary
+ Rename another local variable name -> refname
(merged to 'next' on 2011-10-19 at cc89f0e)
+ resolve_gitlink_ref_recursive(): change to work with struct ref_cache
+ Pass a (ref_cache *) to the resolve_gitlink_*() helper functions
+ resolve_gitlink_ref(): improve docstring
+ get_ref_dir(): change signature
+ refs: change signatures of get_packed_refs() and get_loose_refs()
+ is_dup_ref(): extract function from sort_ref_array()
+ add_ref(): add docstring
+ parse_ref_line(): add docstring
+ is_refname_available(): remove the "quiet" argument
+ clear_ref_array(): rename from free_ref_array()
+ refs: rename parameters result -> sha1
+ refs: rename "refname" variables
+ struct ref_entry: document name member
+ cache.h: add comments for git_path() and git_path_submodule()
(this branch is tangled with mh/ref-api-2.)
Expecting a re-roll; will eject from 'pu' so that the topioc can lose the
hot-fix at the tip.
^ permalink raw reply
* Re: [PATCH] git-svn.perl: close the edit for propedits even with no mods
From: Junio C Hamano @ 2011-12-06 5:03 UTC (permalink / raw)
To: Eric Wong; +Cc: Steven Walter, git
In-Reply-To: <20111206011036.GA26704@dcvr.yhbt.net>
Eric Wong <normalperson@yhbt.net> writes:
> Steven Walter <stevenrwalter@gmail.com> wrote:
>> It's legitimate to update the mergeinfo property without
>> actually changing any files. This can happen when changes are
>> backported to a branch, and then that branch is merged back
>> into mainline. We still want to record the updated mergeinfo
>> for book-keeping.
>>
>> Signed-off-by: Steven Walter <stevenrwalter@gmail.com>
>
> Acked-by: Eric Wong <normalperson@yhbt.net>
>
> Pushed to "master" of git://bogomips.org/git-svn.git
>
> (Btw, you got my email address wrong in the Cc:)
Pulled. Thanks.
^ 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