* Re: RFH: unexpected reflog behavior with --since=
From: Miles Bader @ 2011-11-10 11:06 UTC (permalink / raw)
To: Jeff King; +Cc: Eric Raible, git@vger.kernel.org
In-Reply-To: <20111110080851.GA28342@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> The only point would be to leave "--since" to act on the commit
> timestamps, so that you don't have to resort to the external grepping I
> mentioned above. However, I'm not convinced anybody even cares about
> that use case.
>
> I think the behavior you want is much more sensible.
I think there's already confusion in this area, e.g., with @{...} using
reflog dates, but "git log --since" using commit dates. This can be an
easy trap to fall into because _often_ the two have similar granularity
(when you're mostly pushing changes), but not _always_ (when you pull a
big batch of changes).
Soooo, being really really explicit about using reflog dates vs. commit
dates -- and e.g., having option names like "--since" _always_ refer to
commit dates -- would be a good thing, I think...
-Miles
--
Future, n. That period of time in which our affairs prosper, our friends
are true and our happiness is assured.
^ permalink raw reply
* Re: [fyi] patches used by git distributors
From: Erik Faye-Lund @ 2011-11-10 12:07 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: git
In-Reply-To: <20111108090251.GB17954@elie.hsd1.il.comcast.net>
On Tue, Nov 8, 2011 at 10:02 AM, Jonathan Nieder <jrnieder@gmail.com> wrote:
> Hi,
>
> In an ideal world, each patch applied by downstream distributors would
> fall into one of two categories: (a) adapting the package to some
> esoteric distro-specific requirement (i.e., special-interest patches)
> or (b) in the process of being generalized and reviewed for eventual
> application upstream, so everyone can benefit from it. Unfortunately
> that takes time. I should do better --- sorry about that.
>
> As an experiment, here's a quick summary of the patches being used
> in Debian, for people curious about that and for people interested in
> grabbing useful patches to polish and not knowing where to start.
>
> (Links point to relevant discussion, not necessarily the patch used):
>
> Frédéric Brière (1):
> gitk: Skip over AUTHOR/COMMIT_DATE when searching all fields [1]
>
> Gerrit Pape (1):
> bug#506445: hooks/post-receive-email: set encoding to utf-8 [2]
>
> Jonathan Nieder (12):
> remove shebang line from shell libraries [3]
> pre-rebase hook: capture documentation in a <<here document [4]
> gitk: use symbolic font names "sans" and "monospace"
> transport: expose git_tcp_connect and friends in new tcp.h [5]
> daemon: make host resolution into a separate function [5]
> daemon: move locate_host to tcp.c [5]
> tcp: unify ipv4 and ipv6 code paths [5]
> daemon: check for errors retrieving IP address [5]
> tcp: make dns_resolve return an error code [5]
> transport: optionally honor DNS SRV records [5]
> srv: make errors less quiet [5]
> Makefile: add a knob to turn off hardlinks within same directory [6]
>
> The patches listed above are on the candidate+patches branch of [7].
> Questions and improvements can go to git@packages.debian.org.
>
> A few other packaging projects:
>
> - git://pkgs.fedoraproject.org/git.git master --- 3 patches (using
> SERVER_NAME for home link, reviving vc-git.el, compatibility with
> newer cvsps)
> - http://www.freebsd.org/cgi/cvsweb.cgi/ports/devel/git/files/ ---
> 1 patch (capping individual reads and writes at INT_MAX chars)
> - https://build.opensuse.org/package/files?package=git&project=devel%3Atools%3Ascm
> --- 4 patches (a python build fix, making gitweb::prevent_xss
> default to true, turning off hardlinks for builtins at installation
> time, protecting COMP_WORDBREAKS from mangling in the completion
> script)
> - http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/dev-vcs/git/files/
> --- 1 patch (a NO_CVS knob for the makefile). Very nice.
> - http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/devel/scmgit-base/patches/
> --- 3 patches (putting CFLAGS at the end of ALL_CFLAGS so it can
> override BASIC_CFLAGS, setting INSTALLDIRS=vendor in perl makefile,
> improving tk support on Darwin 8)
> - http://www.openbsd.org/cgi-bin/cvsweb/ports/devel/git/patches/ ---
> 8 patches (updating OpenBSD makefile defaults, using raw perlio in
> gitweb blob view, removing "set -e" in t9117, passing --text [well,
> -a] to grep in t9200, avoiding nonportable regex \+ in t9400)
> - ftp://ftp.cygwin.org/pub/cygwin/release/git/git-1.7.5.1-1-src.tar.bz2
> --- 3 patches (tcl 8.4.1 support, updating Cygwin makefile defaults,
> case-insensitive path comparison in makefile, special Windows-specific
> wish script preamble)
>
Here's what we have for msysGit (the commits themselves can be found
in git://github.com/msysgit/git.git devel):
$ git log --no-merges --first-parent --oneline 319312f..origin/devel
9e47e31 Unicode console: fix font warning on Vista and Win7
778774d MSVC: require pton and ntop emulation
a49c818 MSVC: fix winansi.c compile errors
9ca8039 MSVC: fix poll-related macro redefines
0a6d148 MSVC: Remove unneeded header stubs
18f5b9e Compile fix for MSVC: Include <io.h>
fd6f6aa Compile fix for MSVC: Do not include sys/resources.h
ae69aaf Handle the branch.<name>.rebase value 'interactive'
5d1168b Teach 'git pull' to handle --rebase=interactive
5d6f1d9 Windows: define S_ISUID properly
5084033 Fixed wrong path delimiter in exe finding
77a30da gitweb (SyntaxHighlighter): interpret #l<line-number>
4654bdd Only switch on the line number toggle when highlighting is activated
3efcd98 Gitweb: add support for Alex Gorbatchev's SyntaxHighlighter in
Javascript
1d9ac66 MinGW: disable CRT command line globbing
e0f2492 Win32: move main macro to a function
8258c82 Win32: fix potential multi-threading issue
c45b052 Win32 dirent: improve dirent implementation
ab7ab7a Win32 dirent: clarify #include directives
9d46513 Win32 dirent: change FILENAME_MAX to MAX_PATH
18cf321 Win32 dirent: remove unused dirent.d_reclen member
2741409 Win32 dirent: remove unused dirent.d_ino member
a27af5c Revert "MinGW: Add missing file mode bit defines"
3e4b790 submodule: Fix t7400, t7405, t7406 for msysGit
f72cc9a t5407: Fix line-ending dependency in post-rewrite.args
77de716 submodule: Use cat instead of echo to avoid DOS line-endings
fece0cb t3102: Windows filesystems may not use a literal asterisk in filenames.
d3abd84 Disable test on MinGW that challenges its bash quoting
3f65607 MinGW: Skip test redirecting to fd 4
2e1f250 mingw: do not hide bare repositories
8089c85c Git.pm: Use stream-like writing in cat_blob()
d3d677e Amend "git grep -O -i: if the pager is 'less', pass the '-i' option"
ed7b275 git grep -O -i: if the pager is 'less', pass the '-i' option
30d3f9e Handle new t1501 test case properly with MinGW
64f7bec Do not compile compat/**/*.c with -Wold-style-definition
68acf50 Fix old-style function declaration
aa1c11f Make CFLAGS more strict
c592e94 grep -I: do not bother to read known-binary files
352f3d0 Let deny.currentBranch=updateInstead ignore submodules
5cf00b3 add -e: ignore dirty submodules
bf239f8 Handle http.* config variables pointing to files gracefully on Windows
621a958 Gitweb: make line number toggling work for Firefox and Safari
ff19df4 gitweb: Allow line number toggling with Javascript
feab003 Give commit message reencoding for output on MinGW a chance
6f86c3e Warn if the Windows console font doesn't support Unicode
bfcdc94 Detect console streams more reliably on Windows
9b505ab Support Unicode console output on Windows
e3356ac Enable color output in Windows cmd.exe
3bef266 Fix another invocation of git from gitk with an overly long command-line
d0a4bbe git gui: set GIT_ASKPASS=git-gui--askpass if not set yet
7602e52 Make mingw_offset_1st_component() behave consistently for all paths.
1c072a6 config.c: trivial fix for compile-time warning
1f3a4f8 Allow using UNC path for git repository
3d08379 work around misdetection of stdin attached to a tty
fef92f8 git am: ignore dirty submodules
d23ce6f t7602: cope with CR/LF
3649391 Add a Windows-specific fallback to getenv("HOME");
ede54b1 send-email: handle Windows paths for display just like we do
for processing
32eefc4 send-email: accept absolute path even on Windows
6274596 Add a few more values for receive.denyCurrentBranch
2afff36 Work around funny CR issue
b81e593 mingw: add tests for the hidden attribute on the git directory
f9445e4 Work around the command line limit on Windows
59e0e60 git-gui: provide question helper for retry fallback on Windows
9e89381 Revert "git-gui: set GIT_DIR and GIT_WORK_TREE after setup"
40e6ef7 criss cross rename failure workaround
d24ec01 When initializing .git/, record the current setting of core.hideDotFiles
c40046b core.hidedotfiles: hide '.git' dir by default
73afc46 MinGW: Add missing file mode bit defines
Some of these might be useful for upstream as well...
^ permalink raw reply
* Disappearing change on pull rebase
From: Pitucha, Stanislaw Izaak @ 2011-11-10 13:15 UTC (permalink / raw)
To: git@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 1038 bytes --]
Hi all,
I've got an issue with some operations. It seems like git eats one of my commits (it's still in reflog, but in normal tree, it's unavailable).
What I did is:
checkout -b feature/....
(edit files and commit)
checkout master
merge --no-ff --no-commit feature/...
(edit some files, change versions, changelog)
commit
Now I've got the change committed in the branch and some more changes on the merge commit.
So before pushing to the main repo, I'd like to check if any other changes are there:
pull --rebase
Now my merge commit disappears completely along with the changes without any warning. I get the branch commits duplicated on top of master and the branch stays as it was.
That looks like a data loss bug to me since I can only recover a committed change from reflog and there are no warnings before that change goes away (using 1.7.4.1). Actually no changes were done in upstream in the meantime, so the rebase was not even needed.
Regards,
Stanisław Pitucha
Cloud Services
Hewlett Packard
[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6216 bytes --]
^ permalink raw reply
* Re: Disappearing change on pull rebase
From: Kirill Likhodedov @ 2011-11-10 14:23 UTC (permalink / raw)
To: Pitucha, Stanislaw Izaak; +Cc: git@vger.kernel.org
In-Reply-To: <3FF1328CB05DB74898F769F1BA17812C3E49B74671@GVW1348EXA.americas.hpqcorp.net>
10.11.2011, в 16:15, Pitucha, Stanislaw Izaak:
> Hi all,
> I've got an issue with some operations. It seems like git eats one of my commits (it's still in reflog, but in normal tree, it's unavailable).
>
> What I did is:
>
> checkout -b feature/....
> (edit files and commit)
> checkout master
> merge --no-ff --no-commit feature/...
> (edit some files, change versions, changelog)
> commit
>
> Now I've got the change committed in the branch and some more changes on the merge commit.
> So before pushing to the main repo, I'd like to check if any other changes are there:
>
> pull --rebase
>
> Now my merge commit disappears completely along with the changes without any warning. I get the branch commits duplicated on top of master and the branch stays as it was.
> That looks like a data loss bug to me since I can only recover a committed change from reflog and there are no warnings before that change goes away (using 1.7.4.1). Actually no changes were done in upstream in the meantime, so the rebase was not even needed.
>
That is definitely not a bug.
"git pull --rebase" is (almost?) equal to "git fetch ; git rebase origin/master"
When you perform a rebase, at first your HEAD is rolled back to the commit before your changes, then it is fast-forwared to the remote HEAD (in your case, no fast-forward was made, because there were no remote changes); then your commits are applied one by one.
Of couse, when your commits are applied, they are applied like patches. That mean, that they are different from the original commits (at least, by the commit time). That causes the duplication.
And the merge commit "dissapeared", because it contained no changes, so the patch was empty, and there was nothing to reapply.
If the merge commit contained some changes, and it really was not applied during rebase, it is a bug, but more details will be needed, I think.
If you want to preserve your branch history, you should do "pull" without "rebase".
Kirill.
^ permalink raw reply
* RE: Disappearing change on pull rebase
From: Pitucha, Stanislaw Izaak @ 2011-11-10 13:35 UTC (permalink / raw)
To: git@vger.kernel.org
In-Reply-To: <B5934593-5EE9-4A9F-96D5-0E36B696EFBD@jetbrains.com>
[-- Attachment #1: Type: text/plain, Size: 2286 bytes --]
As mentioned in the original mail - the merge commit did have changes. Here's the log of reproducing it. The line containing "2" in changelog is gone from master after pull --rebase.
$ git init fake_upstream
Initialized empty Git repository in /tmp/fake_upstream/.git/
$ cd fake_upstream/
fake_upstream$ echo some_content > test
fake_upstream$ echo 1 > changelog
fake_upstream$ git add test changelog
fake_upstream$ git commit -m 'first commit'
[master (root-commit) b1b683d] first commit
2 files changed, 2 insertions(+), 0 deletions(-)
create mode 100644 changelog
create mode 100644 test
fake_upstream$ cd ..
$ git clone /tmp/fake_upstream/ disappearing_commit
Cloning into disappearing_commit...
done.
$ cd disappearing_commit/
disappearing_commit$ git checkout -b some-branch
Switched to a new branch 'some-branch'
disappearing_commit$ echo blah >> test
disappearing_commit$ git commit test -m 'branch modification'
[some-branch 528f166] branch modification
1 files changed, 1 insertions(+), 0 deletions(-)
disappearing_commit$ git checkout master
Switched to branch 'master'
disappearing_commit$ git merge --no-ff --no-commit some-branch
Automatic merge went well; stopped before committing as requested
disappearing_commit$ echo 2 >> changelog
disappearing_commit$ git add changelog
disappearing_commit$ git commit
[master e41e4c9] Merge branch 'some-branch'
disappearing_commit$ git show
commit e41e4c963a72528e3b2b5945ca419e19cdba1e4b
Merge: b1b683d 528f166
Author: Stanislaw Pitucha <stanislaw.pitucha@hp.com>
Date: Thu Nov 10 13:30:04 2011 +0000
Merge branch 'some-branch'
diff --cc changelog
index d00491f,d00491f..1191247
--- a/changelog
+++ b/changelog
@@@ -1,1 -1,1 +1,2 @@@
1
++2
disappearing_commit$ git pull --rebase
First, rewinding head to replay your work on top of it...
Applying: branch modification
disappearing_commit$ git show
commit ef8f5e40db9fe7efbd4e493ff68b12327acde283
Author: Stanislaw Pitucha <stanislaw.pitucha@hp.com>
Date: Thu Nov 10 13:29:33 2011 +0000
branch modification
diff --git a/test b/test
index 6e099dc..2f3f685 100644
--- a/test
+++ b/test
@@ -1 +1,2 @@
some_content
+blah
Regards,
Stanisław Pitucha
Cloud Services
Hewlett Packard
[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6216 bytes --]
^ permalink raw reply related
* Re: [git patches] libata updates, GPG signed (but see admin notes)
From: David Woodhouse @ 2011-11-10 13:51 UTC (permalink / raw)
To: Linus Torvalds
Cc: Jochen Striepe, Shawn Pearce, Junio C Hamano, git,
James Bottomley, Jeff Garzik, Andrew Morton, linux-ide, LKML
In-Reply-To: <CA+55aFyG4VuiRN3kcyDVF4sw7b89m-2bOBeQLOGWTcd9o3akzQ@mail.gmail.com>
On Wed, 2011-11-02 at 21:13 -0700, Linus Torvalds wrote:
> No, my main objection to saving the data is that it's ugly and it's
> redundant. Sure, in practice you can check the signatures later fine
> (with the rare exceptions you mention), but even when you can do it,
> what's the big upside?
Another objection (although it may not be insurmountable) is that it's
not necessarily *entirely* clear what's being signed.
In the simple case where I clone your tree, make a few commits with my
Signed-off-by:, sign a tag and then ask you to pull, that's easy enough.
I'm vouching for what I committed, and not for everything that was in
your tree beforehand.
But what if I'm working on top of someone else's published git tree?
Does a signed tag at the top of *my* work imply that I'm vouching for
all of theirs too?
In the case where the signature is ephemeral and only used for you to
trust my pull request, the answer is simple: If that other work wasn't
in your tree yet at the time I send my pull request, I'd damn well
better be vouching for it when I ask you to pull it. Nothing new there.
But if we're keeping signatures around for auditing purposes, we'd
better have a coherent answer to that question. One that isn't "a
signature cover everything since the last commit with torvalds@ as the
committer", if we want it to be useful for the general case.
--
dwmw2
^ permalink raw reply
* Re: [git patches] libata updates, GPG signed (but see admin notes)
From: David Woodhouse @ 2011-11-10 13:52 UTC (permalink / raw)
To: Linus Torvalds
Cc: Junio C Hamano, git, James Bottomley, Jeff Garzik, Andrew Morton,
linux-ide, LKML
In-Reply-To: <CA+55aFx_rAA6TJkZn1Zvu6u9UjxnmTVt0HpMnvaE_q9Sx-jzPg@mail.gmail.com>
On Tue, 2011-11-01 at 14:21 -0700, Linus Torvalds wrote:
> I hate how anonymous our branches are. Sure, we can use good names for
> them, but it was a mistake to think we should describe the repository
> (for gitweb), rather than the branch.
>
> Ok, "hate" is a strong word. I don't "hate" it. I don't even think
> it's a major design issue. But I do think that it would have been
> nicer if we had had some branch description model.
I actually quite like it. I take it as a hint: if the contents of a
branch are *so* wildly different from the main repository that they need
a different description, perhaps I should be using a separate repository
instead of just a branch.
--
dwmw2
^ permalink raw reply
* Re: Bash tab completion for _git_fetch alias is broken on Git 1.7.7.1
From: Nathan Broadbent @ 2011-11-10 14:28 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <CAPXHQbP2O2C6sDVYLB=eMu0UpdMm79t3fqopqBvNpmdpKPRsXQ@mail.gmail.com>
> No change with 1.7.8-rc1, tab completion still fails
^ permalink raw reply
* Re: Bash tab completion for _git_fetch alias is broken on Git 1.7.7.1
From: SZEDER Gábor @ 2011-11-10 15:14 UTC (permalink / raw)
To: Nathan Broadbent; +Cc: Johannes Sixt, Junio C Hamano, git
In-Reply-To: <CAPXHQbP4yCzZ96WEKuHsV_8Pny0MRzcLOY7qi5W3_L_5CnY0vA@mail.gmail.com>
Hi,
[Please don't top-post.]
> On Thu, Nov 10, 2011 at 3:09 PM, Johannes Sixt <j.sixt@viscovery.net> wrote:
> >
> > Am 11/10/2011 4:21, schrieb Junio C Hamano:
> > > Nathan Broadbent <nathan.f77@gmail.com> writes:
> > >
> > >> Dear git mailing list,
> > >>
> > >> I'm assigning the `_git_fetch` bash tab completion to the alias `gf`,
> > >> with the following command:
> > >>
> > >> complete -o default -o nospace -F _git_fetch gf
I assume you have an
alias gf="git fetch"
somewhere, right?
> > >> The tab completion then works fine in git 1.7.0.4, but breaks on git
> > >> 1.7.7.1, with the following error:
I didn't actually tried, but I guess this is a side-effect of da4902a7
(completion: remove unnecessary _get_comp_words_by_ref() invocations,
2011-04-28), which was in v1.7.6. Since the clean-up in that commit
we only call _get_comp_words_by_ref() in the top-level completion
functions _git() and _gitk() to populate completion-related variables
($cur, $prev, $words, $cword), so invoking any _git_<cmd>() completion
function directly causes an error or wrong behavior, because all those
variables are empty.
Calling a completion function directly was not an issue earlier,
because every _git_<cmd>() completion function invoked
_get_comp_words_by_ref() to populate those variables, or in the
pre-_get_comp_words_by_ref() times they just accessed the
completion-related bash variables $COMP_WORDS and $COMP_CWORD
directly.
On Thu, Nov 10, 2011 at 04:52:33PM +0800, Nathan Broadbent wrote:
> So, this is a feature, not a bug... Tab completion for aliases is
> really useful. It's important enough to me that I won't stop until
> I've found a solution.
> I can appreciate that _git_fetch is not currently meant to be called
> directly, but we found a way to utilize it when it previously worked.
> Perhaps the scope of these completion functions could be expanded to
> allow for aliases? I'll attempt to submit a patch if someone can give
> me approval.
The quickest way would be to just revert da4902a7, but it would be the
dirtiest, too: it would bring back a lot of redundant calls to
_get_comp_words_by_ref() and it might have side-effects under zsh (but
I didn't think this through).
It would be a bit more clever to revert only parts of da4902a7, i.e.
to bring back _get_comp_words_by_ref() calls in _git_<cmd> completion
functions but not in __git_<whatever>() helper functions. This way
_git_<cmd>() functions would have their completion-related variables
initialized even when called directly instead through _git(), and
_get_comp_words_by_ref() would be called "only" twice during a single
completion. But that's still one too many, and again: there can be
issues with zsh.
Alternatively, you could easily create your own wrapper function
around _git_fetch(), like this:
_gf () {
local cur prev words cword
_get_comp_words_by_ref -n =: cur prev words cword
_git_fetch
}
However.
Having said all that, I'd like to point out that even if _git_fetch()
didn't error out when called for the 'gf' alias, it still wouldn't
work properly. After 'gf origin <TAB>' it offers the list of remotes
again and it never offers refspecs, because it calls
__git_complete_remote_or_refspec(), which
- depends on the fact that there must be at least two words ('git'
and 'fetch') on the command line before the remote, and
- needs to know the git command (i.e. fetch, pull, or push) to offer
the proper refspecs, but it can't find that out from your alias.
Best,
Gábor
^ permalink raw reply
* Re: [git patches] libata updates, GPG signed (but see admin notes)
From: Junio C Hamano @ 2011-11-10 15:15 UTC (permalink / raw)
To: Johan Herland
Cc: Linus Torvalds, Ted Ts'o, Shawn Pearce, git, James Bottomley,
Jeff Garzik, Andrew Morton, linux-ide, LKML
In-Reply-To: <CALKQrgfZtELcK3H5ZYvmcW8RrtKMVRACFTvw3s5SidFvmFWkGw@mail.gmail.com>
Johan Herland <johan@herland.net> writes:
> On Wed, Nov 9, 2011 at 18:26, Junio C Hamano <gitster@pobox.com> wrote:
>> - "git notes" is represented as a commit that records a tree that holds
>> the entire mapping from commit to its annotations, and the only way to
>> transferr it is to send it together with its history as a whole. It
>> does not have the nice auto-following property that transfers only the
>> relevant annotations.
>
> True. However, consider these mitigating factors:
> ...
>
> My point is that although "notes" might end up transferring more
> annotations than strictly necessary, I believe that in practice all the
> notes being transferred are already (or will soon become) relevant.
Sorry, but I do not think you are considering what would happen when you
have many branches with different purposes, whose commits near tips will
never get merged with each other. "automatic following" semantics like
what "git fetch" does for signed tags is absolutely necessary in such a
case, and the above are not mitigating factors at all in that context.
^ permalink raw reply
* Re: [git patches] libata updates, GPG signed (but see admin notes)
From: Marc Branchaud @ 2011-11-10 15:23 UTC (permalink / raw)
To: David Woodhouse
Cc: Linus Torvalds, Jochen Striepe, Shawn Pearce, Junio C Hamano, git,
James Bottomley, Jeff Garzik, Andrew Morton, linux-ide, LKML
In-Reply-To: <1320933118.17392.23.camel@i7.infradead.org>
On 11-11-10 08:51 AM, David Woodhouse wrote:
> On Wed, 2011-11-02 at 21:13 -0700, Linus Torvalds wrote:
>> No, my main objection to saving the data is that it's ugly and it's
>> redundant. Sure, in practice you can check the signatures later fine
>> (with the rare exceptions you mention), but even when you can do it,
>> what's the big upside?
>
> Another objection (although it may not be insurmountable) is that it's
> not necessarily *entirely* clear what's being signed.
I think this is a non-issue as far as the implementation is concerned. That
is, the question exists regardless of what actual bits get (hashed and)
encrypted by a private key. Furthermore, the answer will depend on who's
using the signatures and in what context, and it's not appropriate for the
git tool to make assumptions about those things.
> In the simple case where I clone your tree, make a few commits with my
> Signed-off-by:, sign a tag and then ask you to pull, that's easy enough.
> I'm vouching for what I committed, and not for everything that was in
> your tree beforehand.
>
> But what if I'm working on top of someone else's published git tree?
> Does a signed tag at the top of *my* work imply that I'm vouching for
> all of theirs too?
<philosophy>
It all depends on what you mean by "vouch for".
You obviously thought that the 3rd-party repo was good for something,
otherwise why did you base your work on it in the first place? So maybe
you're just vouching for the 3rd-party repo being good enough for what you're
trying to do.
Or, maybe you've done a thorough analysis of the 3rd-party code and are ready
to certify it as completely memory-leak-free or something.
Or or, maybe you're only making a statement about the commits that you've
authored yourself. (You probably want to individually sign each of those
commits in this case.)
These sorts of issues have been debated on PKI mailing lists ad nauseum. I
think the best approach is that if you want your signature to have a
particular meaning, then put that into some text that's part of what's being
signed. Let other humans read that text and make their own decisions.
</philosophy>
And whatever the case, the software that makes and validates the signatures
shouldn't make any assertions about how to interpret good or bad signatures.
(Yes, other software could interpret meanings according to some criteria,
and that software could exist alongside or be incorporated into the basic
digital signature software, but the interpretation software is doing a
different job.)
M.
^ permalink raw reply
* Re: [git patches] libata updates, GPG signed (but see admin notes)
From: Johan Herland @ 2011-11-10 16:03 UTC (permalink / raw)
To: Junio C Hamano
Cc: Linus Torvalds, Ted Ts'o, Shawn Pearce, git, James Bottomley,
Jeff Garzik, Andrew Morton, linux-ide, LKML
In-Reply-To: <7vaa84t3ek.fsf@alter.siamese.dyndns.org>
On Thu, Nov 10, 2011 at 16:15, Junio C Hamano <junio@pobox.com> wrote:
> Johan Herland <johan@herland.net> writes:
>> On Wed, Nov 9, 2011 at 18:26, Junio C Hamano <gitster@pobox.com> wrote:
>>> - "git notes" is represented as a commit that records a tree that holds
>>> the entire mapping from commit to its annotations, and the only way to
>>> transferr it is to send it together with its history as a whole. It
>>> does not have the nice auto-following property that transfers only the
>>> relevant annotations.
>>
>> True. However, consider these mitigating factors:
>> ...
>>
>> My point is that although "notes" might end up transferring more
>> annotations than strictly necessary, I believe that in practice all the
>> notes being transferred are already (or will soon become) relevant.
>
> Sorry, but I do not think you are considering what would happen when you
> have many branches with different purposes, whose commits near tips will
> never get merged with each other. "automatic following" semantics like
> what "git fetch" does for signed tags is absolutely necessary in such a
> case, and the above are not mitigating factors at all in that context.
What about having one notes ref per branch? If/when the branch is merged,
the associated notes ref containing the annotations for the commits on that
branch would be merged as well (using "git notes merge").
Sure, using one notes ref per branch is more expensive than a single notes
ref, but it's still cheaper than one ref per signed commit (which is what we
get when using annotated tags). And it prevents the added code and
complexity of the timestamped mapping approach.
...Johan
--
Johan Herland, <johan@herland.net>
www.herland.net
^ permalink raw reply
* "make quick-install-man" on git.git HEAD has failed for two days
From: Randal L. Schwartz @ 2011-11-10 16:17 UTC (permalink / raw)
To: git
Known issue? Should I have done something differently?
"make install quick-install-man" ends with:
make[2]: `GIT-VERSION-FILE' is up to date.
git-manpages repository must exist at ../../git-manpages
make[1]: *** [require-manrepo] Error 1
make: *** [quick-install-man] Error 2
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.posterous.com/ for Smalltalk discussion
^ permalink raw reply
* Re: [fyi] patches used by git distributors
From: Todd Zullinger @ 2011-11-10 16:12 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: git
In-Reply-To: <20111108090251.GB17954@elie.hsd1.il.comcast.net>
[-- Attachment #1: Type: text/plain, Size: 3262 bytes --]
Hi Jonathan,
Thanks for putting this together.
Jonathan Nieder wrote:
> In an ideal world, each patch applied by downstream distributors would
> fall into one of two categories: (a) adapting the package to some
> esoteric distro-specific requirement (i.e., special-interest patches)
> or (b) in the process of being generalized and reviewed for eventual
> application upstream, so everyone can benefit from it. Unfortunately
> that takes time. I should do better --- sorry about that.
> A few other packaging projects:
>
> - git://pkgs.fedoraproject.org/git.git master --- 3 patches (using
> SERVER_NAME for home link, reviving vc-git.el, compatibility with
> newer cvsps)
To review the patches we have in Fedora/EPEL:
- git-1.5-gitweb-home-link.patch¹
This predates my involvement in git packaging. The default for
++GITWEB_HOME_LINK_STR++ is projects. The patch just uses
git://$SERVER_NAME if SERVER_NAME is available, falling back to
projects if it is not.
I'm not sure exactly why that's an improvement over using projects, to
be honest. It's only a text string and it links to the gitweb home,
not to the contents of the string, so whether it reads projects or
git://$SERVER_NAME it takes the user to the same place. Definitely
doesn't seem like something we'd want to push into gitweb and I'm
wondering why we even want to carry it in Fedora/EPEL at this point in
the morning. :)
- git-1.7-el5-emacs-support.patch²
This is only applied to builds for EL-5, where emacs is too old for
the current emacs git support. From the commit message:
This is the vc-git.el from 1.6.4.1, the last version to include
it. Most uses will be better served by the vc-git.el which is
provided by emacs >= 22.2, but on EL-5 we don't have the luxury of
a modern emacs.
Basically, to not break emacs support for folks who were using
git-1.5.x from EPEL, we had to provide something to allow us to push
git-1.7.x. It seems there are relatively few emacs-git users running
EL-5, as getting testers for this was difficult. At the same time,
we've gotten 0 bug reports. So it either works about as well as it
did with git-1.5.x or no one uses it to notice that it doesn't work.
- git-cvsimport-Ignore-cvsps-2.2b1-Branches-output.patch³
This one became necessary when Fedora moved to cvsps 2.2b1 and git
cvsimport got noisy⁴. As cvsps is pretty much dead upstream, it didn't
seem like this patch was worthy of inclusion in git.
If any of these seem like candidates for inclusion, I'm happy to
properly submit them.
¹ http://pkgs.fedoraproject.org/gitweb/?p=git.git;a=blob;f=git-1.5-gitweb-home-link.patch;hb=HEAD
² http://pkgs.fedoraproject.org/gitweb/?p=git.git;a=blob;f=git-1.7-el5-emacs-support.patch;hb=HEAD
³ http://pkgs.fedoraproject.org/gitweb/?p=git.git;a=blob;f=git-cvsimport-Ignore-cvsps-2.2b1-Branches-output.patch;hb=HEAD
⁴ https://bugzilla.redhat.com/490602
--
Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dope will get you through times of no money better than money will get
you through times of no dope.
-- Freewheelin' Franklin
[-- Attachment #2: Type: application/pgp-signature, Size: 482 bytes --]
^ permalink raw reply
* Re: "make quick-install-man" on git.git HEAD has failed for two days
From: Stefan Näwe @ 2011-11-10 16:33 UTC (permalink / raw)
To: Randal L. Schwartz; +Cc: git@vger.kernel.org
In-Reply-To: <861utgymsv.fsf@red.stonehenge.com>
Am 10.11.2011 17:17, schrieb Randal L. Schwartz:
>
> Known issue? Should I have done something differently?
>
> "make install quick-install-man" ends with:
>
> make[2]: `GIT-VERSION-FILE' is up to date.
> git-manpages repository must exist at ../../git-manpages
> make[1]: *** [require-manrepo] Error 1
> make: *** [quick-install-man] Error 2
This should be fixed with fcbebfd "docs: Update install-doc-quick".
(It's in master)
You need to clone git-manpages.git next to git.git.
Stefan
--
----------------------------------------------------------------
/dev/random says: Useless Invention: Fireproof cigarettes.
python -c "print '73746566616e2e6e616577654061746c61732d656c656b74726f6e696b2e636f6d'.decode('hex')"
^ permalink raw reply
* Re: "make quick-install-man" on git.git HEAD has failed for two days
From: Stefan Näwe @ 2011-11-10 16:40 UTC (permalink / raw)
To: Randal L. Schwartz; +Cc: git@vger.kernel.org
In-Reply-To: <4EBBFCD2.9060000@atlas-elektronik.com>
Am 10.11.2011 17:33, schrieb Stefan Näwe:
> Am 10.11.2011 17:17, schrieb Randal L. Schwartz:
>>
>> Known issue? Should I have done something differently?
>>
>> "make install quick-install-man" ends with:
>>
>> make[2]: `GIT-VERSION-FILE' is up to date.
>> git-manpages repository must exist at ../../git-manpages
>> make[1]: *** [require-manrepo] Error 1
>> make: *** [quick-install-man] Error 2
>
> This should be fixed with fcbebfd "docs: Update install-doc-quick".
> (It's in master)
>
> You need to clone git-manpages.git next to git.git.
FYI:
http://thread.gmane.org/gmane.comp.version-control.git/184930/focus=185084
Stefan
--
----------------------------------------------------------------
/dev/random says: Useless Invention: Fireproof cigarettes.
python -c "print '73746566616e2e6e616577654061746c61732d656c656b74726f6e696b2e636f6d'.decode('hex')"
^ permalink raw reply
* Re: "make quick-install-man" on git.git HEAD has failed for two days
From: Stefan Näwe @ 2011-11-10 16:46 UTC (permalink / raw)
To: Randal L. Schwartz; +Cc: git@vger.kernel.org
In-Reply-To: <4EBBFCD2.9060000@atlas-elektronik.com>
Am 10.11.2011 17:33, schrieb Stefan Näwe:
> Am 10.11.2011 17:17, schrieb Randal L. Schwartz:
>>
>> Known issue? Should I have done something differently?
>>
>> "make install quick-install-man" ends with:
>>
>> make[2]: `GIT-VERSION-FILE' is up to date.
>> git-manpages repository must exist at ../../git-manpages
>> make[1]: *** [require-manrepo] Error 1
>> make: *** [quick-install-man] Error 2
>
> This should be fixed with fcbebfd "docs: Update install-doc-quick".
> (It's in master)
Errr...
"fcbebfd" is the cause, not the fix for it, of course.
> You need to clone git-manpages.git next to git.git.
Still true.
Stefan
--
----------------------------------------------------------------
/dev/random says: Time wounds all heels...
python -c "print '73746566616e2e6e616577654061746c61732d656c656b74726f6e696b2e636f6d'.decode('hex')"
^ permalink raw reply
* Re: "make quick-install-man" on git.git HEAD has failed for two days
From: Randal L. Schwartz @ 2011-11-10 16:53 UTC (permalink / raw)
To: Stefan Näwe; +Cc: git@vger.kernel.org
In-Reply-To: <4EBBFCD2.9060000@atlas-elektronik.com>
>>>>> "Stefan" == Stefan Näwe <stefan.naewe@atlas-elektronik.com> writes:
Stefan> You need to clone git-manpages.git next to git.git.
Thanks. New instructions, buried in a place I didn't read again. :)
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.posterous.com/ for Smalltalk discussion
^ permalink raw reply
* Re: [git patches] libata updates, GPG signed (but see admin notes)
From: Junio C Hamano @ 2011-11-10 17:18 UTC (permalink / raw)
To: Johan Herland
Cc: Linus Torvalds, Ted Ts'o, Shawn Pearce, git, James Bottomley,
Jeff Garzik, Andrew Morton, linux-ide, LKML
In-Reply-To: <CALKQrgdxEXQGKQ3t9Sh82=U933ypHNg8duyVmG9uJbg2iST5fw@mail.gmail.com>
Johan Herland <johan@herland.net> writes:
> What about having one notes ref per branch? If/when the branch is merged,
> the associated notes ref containing the annotations for the commits on that
> branch would be merged as well (using "git notes merge").
That is a crude workaround that you could (with help from users) make it
work, but it does not change the fact that the current mechanism to
transfer and integrate notes across repositories is a bad match for what
the "signed commit" type annotations wants to achieve. In fact, the need
for such a workaround is an illustration of how bad a match the mechanism
is.
When you merge a history that has commit A into another history that did
not have that commit, the act of creating a merge commit itself should be
enough to make the resulting history to contain that commit. The commit
DAG already expresses it, and if a parallel "notes" mechanism needs to be
futzed with to match that DAG, and command like "merge" needs to be told
to help that process, that is a shortcoming of the "notes" mechanism.
^ permalink raw reply
* Re: RFH: unexpected reflog behavior with --since=
From: Eric Raible @ 2011-11-10 18:18 UTC (permalink / raw)
To: Miles Bader; +Cc: Jeff King, git@vger.kernel.org
In-Reply-To: <buok4785j8v.fsf@dhlpc061.dev.necel.com>
On 11/10/2011 3:06 AM, Miles Bader wrote:
> I think there's already confusion in this area, e.g., with @{...} using
> reflog dates, but "git log --since" using commit dates. This can be an
> easy trap to fall into because _often_ the two have similar granularity
> (when you're mostly pushing changes), but not _always_ (when you pull a
> big batch of changes).
>
> Soooo, being really really explicit about using reflog dates vs. commit
> dates -- and e.g., having option names like "--since" _always_ refer to
> commit dates -- would be a good thing, I think...
>
> -Miles
Surely you agree that my original example shows that the current behavior
is confusing, yes?
So you're advocating --reflog-since (or some such)?
Or to disable the early --since early exit when walking the reflog?
Or for something else?
- Eric
^ permalink raw reply
* Re: [PATCH 14/14] clone: give advice on how to resume a failed clone
From: Junio C Hamano @ 2011-11-10 21:21 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <20111110075654.GN27950@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> We could make "git clone ..." automatically resume, but I'm a little
> nervous about that. I wrote a patch that did so, and it did work, but
> there are a lot of little hiccups as we violate the assumption that the
> directory didn't already exist (e.g., it writes multiple fetch refspec
> lines to the config).
Sorry, but I do not think the worry is quite justified.
The "assumption that directory didn't already exist" becomes an issue only
if you implement your "git clone" that automatically resumes as a thin
wrapper around the current "git clone" in the form of
until git clone ...
do
echo retrying...
done
Stepping back a bit, I think there are two different situations where
resumable clone is beneficial. The "git clone" process died either by the
machine crashing or the user hitting a \C-c, or the connection between the
server and the "git clone" got severed for some reason.
Right now, the "got disconnected" case results in "git clone" voluntarily
dying and as the result of this, the symptom appears the same. But it
does not have to be that way. If we know the underlying transport is
resumable, e.g. when you are fetching a prepared bundle over the wire.
I have this suspicion that in practice the "got disconnected" case is the
majority. If "git clone" does not die upon disconnect while fetching a
bundle, but instead the fetching of the bundle is resumed internally by
reconnecting to the server and requesting a range transfer, there is no
risk of "writes multiple fetch refspec lines" etc, no?
Of course, it is _also_ beneficial if we made "git clone" resumable after
you purposefully kill it (maybe you thought it will clone within minutes,
but it turns out that it may take hours and you have to turn off the
machine in the next five minutes before leaving the work, or something).
A solution for that case _could_ be used for the "got disconnected" case
by letting it voluntarily die as we currently do, but I do not think that
is an optimal solution to the "got disconnected" case.
^ permalink raw reply
* Re: [git patches] libata updates, GPG signed (but see admin notes)
From: Junio C Hamano @ 2011-11-10 21:41 UTC (permalink / raw)
To: Johan Herland; +Cc: git
In-Reply-To: <CALKQrgfZtELcK3H5ZYvmcW8RrtKMVRACFTvw3s5SidFvmFWkGw@mail.gmail.com>
Johan Herland <johan@herland.net> writes:
> You would also have to keep track of deleted annotations, to enable the local
> side to delete an annotation corresponding to an already-deleted annotation
> on the remote side.
For the "signed commit or pull request" use case, I think "delete" is
probably not something you want to do in the first place.
If there is a "certificate" that says "I made this commit" or "I agree
this is a good topic to be merged to my history" that later turns out to
be incorrect, you do not just want to excise it from your repository and
the place you push to. You would instead want to distribute revocation
notice for such certificiate, which would be a new "note" that will be
attached to the commit or merge in question, so that other people who got
the "certificate" from you or the place you push to will know about the
removal using the same mechanism.
Of course the "UI" layer could match a "certificate" and a "revocation"
against each other and do something intelligent about them (like, not
showing revoked ones by default), so in that sense a moral equivalent of
"delete" from the end user's point of view can easily be supported [*1*].
Note that in this thread, I am not saying that "git notes" mechanism is
not good for anything. A tree whose node names encode an object name is a
valid way to store the mapping from that object to a set of other objects,
and we already agreed that as the "local" storage mechanism, "git notes"
may be used as-is for the purpose of this thread.
But the transfer and merge semantics "git notes" mechanism offers treats
the entire "notes" that appear in _one_ repository and merging that set to
the entire "notes" in another repository and it is not a good match for
the purpose of this thread.
[Footnote]
*1* The point is, it is not the only way to implement a "delete" to keep a
history with common ancestor that has something and your latest that does
not have that thing, which is what "git notes" gives you. If having to
keep the history brings other undesired semantic baggage, other ways that
do not have such undesired property need to be explored.
^ permalink raw reply
* (unknown),
From: Marcel Schaible @ 2011-11-10 22:56 UTC (permalink / raw)
To: git
subscribe
^ permalink raw reply
* [RFC/PATCH] i18n back from the dead
From: Ævar Arnfjörð Bjarmason @ 2011-11-11 0:09 UTC (permalink / raw)
To: git; +Cc: Ævar Arnfjörð Bjarmason
Or, a patch so huge it needs it own cover letter.
After looking at my dormant i18n series I found that it was spread out
over so many pieces that even I didn't understand it anymore.
So here's an attempt to fix that. I've squashed everything we'll need
to get i18n working in Git down to one patch. Much of the previous
complexity came about because I was adding little things to it
incrementally, and I kept carrying around commits that were
effectively bugfixes on top of the original code.
Now it's all in one big patch, and while the diffstat looks scary at
first a lot of it is tests, documentation and a giant comment.
It's an RFC because there are bound to be bugs in there that I haven't
spotted, and po/README is out of date, I haven't updated it for some
of the new C and Shell functions we now have.
But it seems to function just fine. I've tested it on two Linux boxes
and a Solaris box and it works as intended, but review and testing on
other platforms would be most welcome.
This is all we need to start using PO files that are dropped in po/,
which I don't think is all that shabby for 1300 lines changed.
Ævar Arnfjörð Bjarmason (1):
i18n: add infrastructure for translating Git with gettext
.gitignore | 1 +
Documentation/CodingGuidelines | 7 +
INSTALL | 12 ++
Makefile | 81 +++++++++++++-
config.mak.in | 3 +
configure.ac | 19 +++
daemon.c | 2 +
fast-import.c | 2 +
gettext.c | 116 +++++++++++++++++++
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/README | 209 +++++++++++++++++++++++++++++++++++
po/is.po | 93 ++++++++++++++++
shell.c | 1 +
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, 1269 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
--
1.7.6.3
^ permalink raw reply
* [RFC/PATCH] i18n: add infrastructure for translating Git with gettext
From: Ævar Arnfjörð Bjarmason @ 2011-11-11 0:09 UTC (permalink / raw)
To: git; +Cc: Ævar Arnfjörð Bjarmason
In-Reply-To: <1320970164-31694-1-git-send-email-avarab@gmail.com>
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 libint 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 fall 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 wants 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.
I originally tried to detect if the system supported `echo -n' but
I found this to be a waste of time. My benchmarks on Linux, Solaris
and FreeBSD reveal that printf(1) is fast enough, especially since
we aren't calling gettext() from within any tight loops, and
unlikely to ever do so.
= 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.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
.gitignore | 1 +
Documentation/CodingGuidelines | 7 +
INSTALL | 12 ++
Makefile | 81 +++++++++++++-
config.mak.in | 3 +
configure.ac | 19 +++
daemon.c | 2 +
fast-import.c | 2 +
gettext.c | 116 +++++++++++++++++++
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/README | 209 +++++++++++++++++++++++++++++++++++
po/is.po | 93 ++++++++++++++++
shell.c | 1 +
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, 1269 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/.gitignore b/.gitignore
index 8572c8c..c47f3a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -224,3 +224,4 @@
*.pdb
/Debug/
/Release/
+/share/
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..28dde47 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_CHECK if your implementation of msgfmt does not
+# support the --check GNU extension to msgfmt(1)
+#
# 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_CHECK = 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_CHECK
+ MSGFMT += --check
+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.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,share/locale/%/LC_MESSAGES/git.mo,$(POFILES))
+
+ifndef NO_GETTEXT
+all:: $(MOFILES)
+endif
+
+share/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 share/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/git.pot share/
$(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..08bdb07 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,107 @@ 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'
+
+ Bj? til t?ma Git lind ? /hl/agh/.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 í /hl/agh/.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 for a regression test
+ that makes sure this code is functioning correctly.
+
+ 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/README b/po/README
new file mode 100644
index 0000000..eff16dd
--- /dev/null
+++ b/po/README
@@ -0,0 +1,209 @@
+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"), me);
+
+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);
+
+ - 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
+
+ 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=gettextize 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 add a C_LOCALE_OUTPUT prerequisite to the test (as
+documented in t/README). 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..713def9 100644
--- a/shell.c
+++ b/shell.c
@@ -137,6 +137,7 @@ 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..a54a9f8
--- /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/share/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..a0e1501
--- /dev/null
+++ b/t/t0202/test.pl
@@ -0,0 +1,110 @@
+#!/usr/bin/perl
+use 5.008;
+use lib (split(/:/, $ENV{GITPERLLIB}));
+use warnings;
+use strict;
+use Test::More tests => 8;
+use Git::I18N;
+use POSIX qw(:locale_h);
+
+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..d2d9dcc 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@@/share/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.6.3
^ permalink raw reply related
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