* Re: [PATCH] tests: turn on test-lint-shell-syntax by default
From: Junio C Hamano @ 2013-02-05 20:52 UTC (permalink / raw)
To: Torsten Bögershausen; +Cc: Jonathan Nieder, git, kraai
In-Reply-To: <51116D3E.3070409@web.de>
Torsten Bögershausen <tboegi@web.de> writes:
> Thanks for the detailed suggestion.
> Instead of using a file for putting out non portable syntax,
> can we can use a similar logic as test_failure ?
Your test_bad_syntax_ function can be called from a subshell, and
its "exit 1" will not exit, no?
test_expect_success 'prepare a blob with incomplete line' '
(
echo first line
echo second line
echo -n final and incomplete line
) >incomplete.txt
'
^ permalink raw reply
* [PATCHv5] Add contrib/credentials/netrc with GPG support
From: Ted Zlatanov @ 2013-02-05 20:55 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, git
In-Reply-To: <7vhalqsfkf.fsf@alter.siamese.dyndns.org>
Add Git credential helper that can parse netrc/authinfo files.
This credential helper support multiple files, returning the first one
that matches. It checks file permissions and owner. For *.gpg files,
it will run GPG to decrypt the file.
Signed-off-by: Ted Zlatanov <tzz@lifelogs.com>
---
Changes since PATCHv4:
- indentation and brace fixes
- test makefile uses "=>" as the decorative prefix
- documentation fixes about order and show query with "hostname"
- add --insecure to ignore owner and permission checks
- check permissions just once and only for unencrypted files
- change IO::File to simple open() and quote $file
- fixed macdef buglet from Net::Netrc
- ignore 'default' entries
contrib/credential/netrc/Makefile | 12 +
contrib/credential/netrc/git-credential-netrc | 424 +++++++++++++++++++++++++
2 files changed, 436 insertions(+), 0 deletions(-)
create mode 100644 contrib/credential/netrc/Makefile
create mode 100755 contrib/credential/netrc/git-credential-netrc
diff --git a/contrib/credential/netrc/Makefile b/contrib/credential/netrc/Makefile
new file mode 100644
index 0000000..18a924f
--- /dev/null
+++ b/contrib/credential/netrc/Makefile
@@ -0,0 +1,12 @@
+test_netrc:
+ @(echo "bad data" | ./git-credential-netrc -f A -d -v) || echo "Bad invocation test, ignoring failure"
+ @echo "=> Silent invocation... nothing should show up here with a missing file"
+ @echo "bad data" | ./git-credential-netrc -f A get
+ @echo "=> Back to noisy: -v and -d used below, missing file"
+ echo "bad data" | ./git-credential-netrc -f A -d -v get
+ @echo "=> Look for any entry in the default file set"
+ echo "" | ./git-credential-netrc -d -v get
+ @echo "=> Look for github.com in the default file set"
+ echo "host=google.com" | ./git-credential-netrc -d -v get
+ @echo "=> Look for a nonexistent machine in the default file set"
+ echo "host=korovamilkbar" | ./git-credential-netrc -d -v get
diff --git a/contrib/credential/netrc/git-credential-netrc b/contrib/credential/netrc/git-credential-netrc
new file mode 100755
index 0000000..8298564
--- /dev/null
+++ b/contrib/credential/netrc/git-credential-netrc
@@ -0,0 +1,424 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+use File::Basename;
+
+my $VERSION = "0.1";
+
+my %options = (
+ help => 0,
+ debug => 0,
+ verbose => 0,
+ insecure => 0,
+ file => [],
+
+ # identical token maps, e.g. host -> host, will be inserted later
+ tmap => {
+ port => 'protocol',
+ machine => 'host',
+ path => 'path',
+ login => 'username',
+ user => 'username',
+ password => 'password',
+ }
+ );
+
+# Map each credential protocol token to itself on the netrc side.
+foreach (values %{$options{tmap}}) {
+ $options{tmap}->{$_} = $_;
+}
+
+# Now, $options{tmap} has a mapping from the netrc format to the Git credential
+# helper protocol.
+
+# Next, we build the reverse token map.
+
+# When $rmap{foo} contains 'bar', that means that what the Git credential helper
+# protocol calls 'bar' is found as 'foo' in the netrc/authinfo file. Keys in
+# %rmap are what we expect to read from the netrc/authinfo file.
+
+my %rmap;
+foreach my $k (keys %{$options{tmap}}) {
+ push @{$rmap{$options{tmap}->{$k}}}, $k;
+}
+
+Getopt::Long::Configure("bundling");
+
+# TODO: maybe allow the token map $options{tmap} to be configurable.
+GetOptions(\%options,
+ "help|h",
+ "debug|d",
+ "insecure|k",
+ "verbose|v",
+ "file|f=s@",
+ );
+
+if ($options{help}) {
+ my $shortname = basename($0);
+ $shortname =~ s/git-credential-//;
+
+ print <<EOHIPPUS;
+
+$0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] [-v] [-k] get
+
+Version $VERSION by tzz\@lifelogs.com. License: BSD.
+
+Options:
+
+ -f|--file AUTHFILE : specify netrc-style files. Files with the .gpg extension
+ will be decrypted by GPG before parsing. Multiple -f
+ arguments are OK. They are processed in order, and the
+ first matching entry found is returned via the credential
+ helper protocol (see below).
+
+ -k|--insecure : ignore bad file ownership or permissions
+
+ -d|--debug : turn on debugging (developer info)
+
+ -v|--verbose : be more verbose (show files and information found)
+
+To enable this credential helper:
+
+ git config credential.helper '$shortname -f AUTHFILE1 -f AUTHFILE2'
+
+(Note that Git will prepend "git-credential-" to the helper name and look for it
+in the path.)
+
+...and if you want lots of debugging info:
+
+ git config credential.helper '$shortname -f AUTHFILE -d'
+
+...or to see the files opened and data found:
+
+ git config credential.helper '$shortname -f AUTHFILE -v'
+
+Only "get" mode is supported by this credential helper. It opens every AUTHFILE
+and looks for the first entry that matches the requested search criteria:
+
+ 'port|protocol':
+ The protocol that will be used (e.g., https). (protocol=X)
+
+ 'machine|host':
+ The remote hostname for a network credential. (host=X)
+
+ 'path':
+ The path with which the credential will be used. (path=X)
+
+ 'login|user|username':
+ The credential’s username, if we already have one. (username=X)
+
+Thus, when we get this query on STDIN:
+
+host=github.com
+protocol=https
+username=tzz
+
+this credential helper will look for the first entry in every AUTHFILE that
+matches
+
+machine github.com port https login tzz
+
+OR
+
+machine github.com protocol https login tzz
+
+OR... etc. acceptable tokens as listed above. Any unknown tokens are
+simply ignored.
+
+Then, the helper will print out whatever tokens it got from the entry, including
+"password" tokens, mapping back to Git's helper protocol; e.g. "port" is mapped
+back to "protocol". Any redundant entry tokens (part of the original query) are
+skipped.
+
+Again, note that only the first matching entry from all the AUTHFILEs, processed
+in the sequence given on the command line, is used.
+
+Netrc/authinfo tokens can be quoted as 'STRING' or "STRING".
+
+No caching is performed by this credential helper.
+
+EOHIPPUS
+
+ exit 0;
+}
+
+my $mode = shift @ARGV;
+
+# Credentials must get a parameter, so die if it's missing.
+die "Syntax: $0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] get" unless defined $mode;
+
+# Only support 'get' mode; with any other unsupported ones we just exit.
+exit 0 unless $mode eq 'get';
+
+my $files = $options{file};
+
+# if no files were given, use a predefined list.
+# note that .gpg files come first
+unless (scalar @$files) {
+ my @candidates = qw[
+ ~/.authinfo.gpg
+ ~/.netrc.gpg
+ ~/.authinfo
+ ~/.netrc
+ ];
+
+ $files = $options{file} = [ map { glob $_ } @candidates ];
+}
+
+my $query = read_credential_data_from_stdin();
+
+FILE:
+foreach my $file (@$files) {
+ my $gpgmode = $file =~ m/\.gpg$/;
+ unless (-r $file) {
+ log_verbose("Unable to read $file; skipping it");
+ next FILE;
+ }
+
+ # the following check is copied from Net::Netrc, for non-GPG files
+ # OS/2 and Win32 do not handle stat in a way compatable with this check :-(
+ unless ($gpgmode || $options{insecure} ||
+ $^O eq 'os2'
+ || $^O eq 'MSWin32'
+ || $^O eq 'MacOS'
+ || $^O =~ /^cygwin/) {
+ my @stat = stat($file);
+
+ if (@stat) {
+ if ($stat[2] & 077) {
+ log_verbose("Insecure $file (mode=%04o); skipping it",
+ $stat[2] & 07777);
+ next FILE;
+ }
+
+ if ($stat[4] != $<) {
+ log_verbose("Not owner of $file; skipping it");
+ next FILE;
+ }
+ }
+ }
+
+ my @entries = load_netrc($file, $gpgmode);
+
+ unless (scalar @entries) {
+ if ($!) {
+ log_verbose("Unable to open $file: $!");
+ }
+ else {
+ log_verbose("No netrc entries found in $file");
+ }
+
+ next FILE;
+ }
+
+ my $entry = find_netrc_entry($query, @entries);
+ if ($entry) {
+ print_credential_data($entry, $query);
+ # we're done!
+ last FILE;
+ }
+}
+
+exit 0;
+
+sub load_netrc {
+ my $file = shift @_;
+ my $gpgmode = shift @_;
+
+ my $io;
+ if ($gpgmode) {
+ # typical shell character escapes from http://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html
+ my $f = $file;
+ $f =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;
+ # GPG doesn't work well with 2- or 3-argument open
+ my $cmd = "gpg --decrypt $f";
+ log_verbose("Using GPG to open $file: [$cmd]");
+ open $io, "$cmd|";
+ }
+ else {
+ log_verbose("Opening $file...");
+ open $io, '<', $file;
+ }
+
+ # nothing to do if the open failed (we log the error later)
+ return unless $io;
+
+ # Net::Netrc does this, but the functionality is merged with the file
+ # detection logic, so we have to extract just the part we need
+ my @netrc_entries = net_netrc_loader($io);
+
+ # these entries will use the credential helper protocol token names
+ my @entries;
+
+ foreach my $nentry (@netrc_entries) {
+ my %entry;
+ my $num_port;
+
+ if (defined $nentry->{port} && $nentry->{port} =~ m/^\d+$/) {
+ $num_port = $nentry->{port};
+ delete $nentry->{port};
+ }
+
+ # create the new entry for the credential helper protocol
+ $entry{$options{tmap}->{$_}} = $nentry->{$_} foreach keys %$nentry;
+
+ # for "host X port Y" where Y is an integer (captured by
+ # $num_port above), set the host to "X:Y"
+ if (defined $entry{host} && defined $num_port) {
+ $entry{host} = join(':', $entry{host}, $num_port);
+ }
+
+ push @entries, \%entry;
+ }
+
+ return @entries;
+}
+
+sub net_netrc_loader {
+ my $fh = shift @_;
+ my @entries;
+ my ($mach, $macdef, $tok, @tok);
+
+ LINE:
+ while (<$fh>) {
+ undef $macdef if /\A\n\Z/;
+
+ if ($macdef) {
+ next LINE;
+ }
+
+ s/^\s*//;
+ chomp;
+
+ while (length && s/^("((?:[^"]+|\\.)*)"|((?:[^\\\s]+|\\.)*))\s*//) {
+ (my $tok = $+) =~ s/\\(.)/$1/g;
+ push(@tok, $tok);
+ }
+
+ TOKEN:
+ while (@tok) {
+ if ($tok[0] eq "default") {
+ shift(@tok);
+ undef $mach; # ignore 'default' lines
+
+ next TOKEN;
+ }
+
+ $tok = shift(@tok);
+
+ if ($tok eq "machine") {
+ my $host = shift @tok;
+ $mach = { machine => $host };
+ push @entries, $mach;
+ }
+ elsif (exists $options{tmap}->{$tok}) {
+ unless ($mach) {
+ log_debug("Skipping token $tok because no machine was given");
+ next TOKEN;
+ }
+
+ my $value = shift @tok;
+ unless (defined $value) {
+ log_debug("Token $tok had no value, skipping it.");
+ next TOKEN;
+ }
+
+ # Following line added by rmerrell to remove '/' escape char in .netrc
+ $value =~ s/\/\\/\\/g;
+ $mach->{$tok} = $value;
+ }
+ elsif ($tok eq "macdef") { # we ignore macros
+ next TOKEN unless $mach;
+ my $value = shift @tok;
+ $macdef = 1;
+ }
+ }
+ }
+
+ return @entries;
+}
+
+sub read_credential_data_from_stdin {
+ # the query: start with every token with no value
+ my %q = map { $_ => undef } values(%{$options{tmap}});
+
+ while (<STDIN>) {
+ next unless m/^([^=]+)=(.+)/;
+
+ my ($token, $value) = ($1, $2);
+ die "Unknown search token $token" unless exists $q{$token};
+ $q{$token} = $value;
+ log_debug("We were given search token $token and value $value");
+ }
+
+ foreach (sort keys %q) {
+ log_debug("Searching for %s = %s", $_, $q{$_} || '(any value)');
+ }
+
+ return \%q;
+}
+
+# takes the search tokens and then a list of entries
+# each entry is a hash reference
+sub find_netrc_entry {
+ my $query = shift @_;
+
+ ENTRY:
+ foreach my $entry (@_)
+ {
+ my $entry_text = join ', ', map { "$_=$entry->{$_}" } keys %$entry;
+ foreach my $check (sort keys %$query) {
+ if (defined $query->{$check}) {
+ log_debug("compare %s [%s] to [%s] (entry: %s)",
+ $check,
+ $entry->{$check},
+ $query->{$check},
+ $entry_text);
+ unless ($query->{$check} eq $entry->{$check}) {
+ next ENTRY;
+ }
+ }
+ else {
+ log_debug("OK: any value satisfies check $check");
+ }
+ }
+
+ return $entry;
+ }
+
+ # nothing was found
+ return;
+}
+
+sub print_credential_data {
+ my $entry = shift @_;
+ my $query = shift @_;
+
+ log_debug("entry has passed all the search checks");
+ TOKEN:
+ foreach my $git_token (sort keys %$entry) {
+ log_debug("looking for useful token $git_token");
+ # don't print unknown (to the credential helper protocol) tokens
+ next TOKEN unless exists $query->{$git_token};
+
+ # don't print things asked in the query (the entry matches them)
+ next TOKEN if defined $query->{$git_token};
+
+ log_debug("FOUND: $git_token=$entry->{$git_token}");
+ printf "%s=%s\n", $git_token, $entry->{$git_token};
+ }
+}
+sub log_verbose {
+ return unless $options{verbose};
+ printf STDERR @_;
+ printf STDERR "\n";
+}
+
+sub log_debug {
+ return unless $options{debug};
+ printf STDERR @_;
+ printf STDERR "\n";
+}
--
1.7.9.rc2
^ permalink raw reply related
* Re: [PATCH] Add contrib/credentials/netrc with GPG support, try #2
From: Ted Zlatanov @ 2013-02-05 21:00 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, git
In-Reply-To: <7vd2wese6z.fsf@alter.siamese.dyndns.org>
On Tue, 05 Feb 2013 12:23:00 -0800 Junio C Hamano <gitster@pobox.com> wrote:
JCH> Ted Zlatanov <tzz@lifelogs.com> writes:
JCH> You still need to parse a file that has a "default" entry correctly;
JCH> otherwise the users won't be able to share existing .netrc files
JCH> with other applications e.g. ftp, which is the whole point of this
JCH> series. Not using values from the "default" entry is probably fine,
JCH> though.
>>
>> OK; done in PATCHv4.
JCH> Hmph.
JCH> Didn't you remove that from your version of net_netrc_loader when
JCH> you borrowed the bulk of the code from Net::Netrc::_readrc? I see
JCH> "default" token handled at the beginning of "TOKEN: while (@tok)"
JCH> loop in the original but not in your version I see in v4.
Damn, I accidentally moved that check to /dev/null. OK, I added it in
PATCHv5. Thanks for catching that.
Ted
^ permalink raw reply
* Re: Bug in "git log --graph -p -m" (version 1.7.7.6)
From: Matthieu Moy @ 2013-02-05 21:09 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Dale R. Worley, git
In-Reply-To: <7vtxpqslpm.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> worley@alum.mit.edu (Dale R. Worley) writes:
>
>> I have found a situation where "git log" produces (apparently)
>> endless output. Presumably this is a bug. Following is a (Linux)
>> script that reliably reproduces the error for me (on Fedora 16):
>
> Wasn't this fixed at v1.8.1.1~13 or is this a different issue?
In any case, I can't reproduce with 1.8.1.2.526.gf51a757: I don't get
undless output. On the other hand, I get a slightly misformatted output:
* commit a393ed598e9fb11436f85bd58f1a38c82f2cadb7 (from 2c1e6a36f4b712e914fac994463da7d0fdb2bc6d)
|\ Merge: 2c1e6a3 33e70e7
| | Author: Matthieu Moy <Matthieu.Moy@imag.fr>
| | Date: Tue Feb 5 22:05:33 2013 +0100
| |
| | Commit S
| |
| | diff --git a/file b/file
| | index 6bb4d3e..afd2e75 100644
| | --- a/file
| | +++ b/file
| | @@ -1,4 +1,5 @@
| | 1
| | 1a
| | 2
| | +2a
| | 3
| |
commit a393ed598e9fb11436f85bd58f1a38c82f2cadb7 (from 33e70e70c0173d634826b998bdc304f93c0966b8)
| | Merge: 2c1e6a3 33e70e7
| | Author: Matthieu Moy <Matthieu.Moy@imag.fr>
| | Date: Tue Feb 5 22:05:33 2013 +0100
The second "commit" line (diff with second parent) doesn't have the
"| |" prefix, I don't think this is intentional.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* [PATCH v2] t4038: add tests for "diff --cc --raw <trees>"
From: John Keeping @ 2013-02-05 21:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Antoine Pelisse
In-Reply-To: <7v8v72sczp.fsf@alter.siamese.dyndns.org>
Signed-off-by: John Keeping <john@keeping.me.uk>
---
Changes since v1:
- more spaces around '|'
- create trees with line feeds and use 'sed -e 4q'
---
t/t4038-diff-combined.sh | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index 40277c7..614425a 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -89,4 +89,28 @@ test_expect_success 'diagnose truncated file' '
grep "diff --cc file" out
'
+test_expect_success 'setup for --cc --raw' '
+ blob=$(echo file | git hash-object --stdin -w) &&
+ base_tree=$(echo "100644 blob $blob file" | git mktree) &&
+ trees= &&
+ for i in `test_seq 1 40`
+ do
+ blob=$(echo file$i | git hash-object --stdin -w) &&
+ trees="$trees$(echo "100644 blob $blob file" | git mktree)$LF"
+ done
+'
+
+test_expect_success 'check --cc --raw with four trees' '
+ four_trees=$(echo "$trees" | sed -e 4q) &&
+ git diff --cc --raw $four_trees $base_tree >out &&
+ # Check for four leading colons in the output:
+ grep "^::::[^:]" out
+'
+
+test_expect_success 'check --cc --raw with forty trees' '
+ git diff --cc --raw $trees $base_tree >out &&
+ # Check for forty leading colons in the output:
+ grep "^::::::::::::::::::::::::::::::::::::::::[^:]" out
+'
+
test_done
--
1.8.1.2.689.g36c777b
^ permalink raw reply related
* importing two different trees into a fresh git repo
From: Constantine A. Murenin @ 2013-02-05 21:46 UTC (permalink / raw)
To: git
Hi,
I have two distinct trees that were not managed by any RCS, and I'd
like to import them into a single repository into two separate orphan
branches, then make sense of what's in there, merge, and unify into
'master'.
(To give some context, it's /etc/nginx config files from nginx/1.0.12
on Debian 6 and nginx/1.2.2 on OpenBSD 5.2.)
I've encountered two problems so far:
0. After initialising the repository, I was unable to `git checkout
--orphan Debian-6.0.4-nginx-1.0.12` -- presumably it doesn't work when
the repo is empty? This sounds like a bug or an artefact of
implementation. I presume this can be worked around by committing
into master instead, and then doing `git checkout -b
Debian-6.0.4-nginx-1.0.12`, and then force-fixing the master somehow
later on.
1. After making a mistake on my first commit (my first commit into
OpenBSD-5.2-nginx-1.2.2 orphan branch ended up including a directory
from master by mistake), I am now unable to rebase and "fixup" the
changes -- `git rebase --interactive HEAD~2` doesn't work, which, from
one perspective, makes perfect sense (indeed there's no prior
revision), but, from another, it's not immediately obvious how to
quickly work around it.
Any suggestions?
It would seem like making some kind of a dummy first commit into
master would be the best workaround for both of these problems. Is
that basically the suggested approach?
Best regards,
Constantine.
^ permalink raw reply
* Re: [PATCH] tests: turn on test-lint-shell-syntax by default
From: Junio C Hamano @ 2013-02-05 21:56 UTC (permalink / raw)
To: Torsten Bögershausen; +Cc: Jonathan Nieder, git, kraai
In-Reply-To: <7v4nhqsctb.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Torsten Bögershausen <tboegi@web.de> writes:
>
>> Thanks for the detailed suggestion.
>> Instead of using a file for putting out non portable syntax,
>> can we can use a similar logic as test_failure ?
>
> Your test_bad_syntax_ function can be called from a subshell, and
> its "exit 1" will not exit, no?
What is more important is that the increment to $test_bad_syntax
done in that function will not be propagated up to the main process
that runs the test framework.
Of course, that is why I mentioned communicating using the
filesystem.
^ permalink raw reply
* Re: [PATCHv5] Add contrib/credentials/netrc with GPG support
From: Junio C Hamano @ 2013-02-05 22:24 UTC (permalink / raw)
To: Ted Zlatanov; +Cc: Jeff King, git
In-Reply-To: <8738xaqy40.fsf_-_@lifelogs.com>
Ted Zlatanov <tzz@lifelogs.com> writes:
> + unless (scalar @entries) {
> + if ($!) {
> + log_verbose("Unable to open $file: $!");
> + }
> + else {
} else {
> + log_verbose("No netrc entries found in $file");
> + }
> +
> + if ($gpgmode) {
> + # typical shell character escapes from http://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html
> + my $f = $file;
> + $f =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;
Yuck. If you really have to quote, it is often far simpler to take
advantage of the fact that quoting rule for shell is much simpler
inside '', i.e.
sub sq {
my ($string) = @_;
$string =~ s|'|'\\''|g;
return "'$string'";
}
The only thing you have to worry about is a single quote, which
would close the single quote you want to be in, and you express it
by first closing the single quote you opened, put the single quote
by emitting a backslash and a single quote, and then immediately
open another single quote.
> + # GPG doesn't work well with 2- or 3-argument open
I think I commented on this in a separate message.
> + # Net::Netrc does this, but the functionality is merged with the file
> + # detection logic, so we have to extract just the part we need
> + my @netrc_entries = net_netrc_loader($io);
> +
> + # these entries will use the credential helper protocol token names
> + my @entries;
> +
> + foreach my $nentry (@netrc_entries) {
> + my %entry;
> + my $num_port;
> +
> + if (defined $nentry->{port} && $nentry->{port} =~ m/^\d+$/) {
> + $num_port = $nentry->{port};
> + delete $nentry->{port};
> + }
> +
> + # create the new entry for the credential helper protocol
> + $entry{$options{tmap}->{$_}} = $nentry->{$_} foreach keys %$nentry;
> +
> + # for "host X port Y" where Y is an integer (captured by
> + # $num_port above), set the host to "X:Y"
> + if (defined $entry{host} && defined $num_port) {
> + $entry{host} = join(':', $entry{host}, $num_port);
> + }
> +
> + push @entries, \%entry;
> + }
> +
> + return @entries;
> +}
I'll leave this part to Peff to comment on.
> +sub net_netrc_loader {
> + my $fh = shift @_;
> + my @entries;
> + my ($mach, $macdef, $tok, @tok);
> +
> + LINE:
> + while (<$fh>) {
> + undef $macdef if /\A\n\Z/;
> +
> + if ($macdef) {
> + next LINE;
> + }
> +
> + s/^\s*//;
> + chomp;
> +
> + while (length && s/^("((?:[^"]+|\\.)*)"|((?:[^\\\s]+|\\.)*))\s*//) {
> + (my $tok = $+) =~ s/\\(.)/$1/g;
> + push(@tok, $tok);
> + }
> +
> + TOKEN:
> + while (@tok) {
> + if ($tok[0] eq "default") {
> + shift(@tok);
> + undef $mach; # ignore 'default' lines
I think it is saner to do something like this instead here:
$mach = { machine => undef }
Otherwise your log_debug() will be filled by the tokens used for the
default entry, and also this "undef $mach" here will break your
macdef skipping logic if the default entry has a macdef, I think.
You can ignore an entry with undefined "machine" in the loop at the
end of load_netrc.
> + next TOKEN;
> + }
> +
> + $tok = shift(@tok);
> +
> + if ($tok eq "machine") {
> + my $host = shift @tok;
> + $mach = { machine => $host };
> + push @entries, $mach;
> + }
> + elsif (exists $options{tmap}->{$tok}) {
> + unless ($mach) {
> + log_debug("Skipping token $tok because no machine was given");
> + next TOKEN;
> + }
> +
> + my $value = shift @tok;
> + unless (defined $value) {
> + log_debug("Token $tok had no value, skipping it.");
> + next TOKEN;
> + }
> +
> + # Following line added by rmerrell to remove '/' escape char in .netrc
> + $value =~ s/\/\\/\\/g;
> + $mach->{$tok} = $value;
> + }
> + elsif ($tok eq "macdef") { # we ignore macros
> + next TOKEN unless $mach;
> + my $value = shift @tok;
> + $macdef = 1;
> + }
> + }
> + }
> +
> + return @entries;
> +}
> +
> +sub read_credential_data_from_stdin {
> + # the query: start with every token with no value
> + my %q = map { $_ => undef } values(%{$options{tmap}});
> +
> + while (<STDIN>) {
> + next unless m/^([^=]+)=(.+)/;
> +
> + my ($token, $value) = ($1, $2);
> + die "Unknown search token $token" unless exists $q{$token};
> + $q{$token} = $value;
> + log_debug("We were given search token $token and value $value");
> + }
> +
> + foreach (sort keys %q) {
> + log_debug("Searching for %s = %s", $_, $q{$_} || '(any value)');
> + }
> +
> + return \%q;
> +}
> +
> +# takes the search tokens and then a list of entries
> +# each entry is a hash reference
> +sub find_netrc_entry {
> + my $query = shift @_;
> +
> + ENTRY:
> + foreach my $entry (@_)
> + {
> + my $entry_text = join ', ', map { "$_=$entry->{$_}" } keys %$entry;
> + foreach my $check (sort keys %$query) {
> + if (defined $query->{$check}) {
> + log_debug("compare %s [%s] to [%s] (entry: %s)",
> + $check,
> + $entry->{$check},
> + $query->{$check},
> + $entry_text);
> + unless ($query->{$check} eq $entry->{$check}) {
> + next ENTRY;
> + }
> + }
> + else {
> + log_debug("OK: any value satisfies check $check");
> + }
> + }
> +
> + return $entry;
> + }
> +
> + # nothing was found
> + return;
> +}
I'll leave this part to Peff to comment on.
> +
> +sub print_credential_data {
> + my $entry = shift @_;
> + my $query = shift @_;
> +
> + log_debug("entry has passed all the search checks");
> + TOKEN:
> + foreach my $git_token (sort keys %$entry) {
> + log_debug("looking for useful token $git_token");
> + # don't print unknown (to the credential helper protocol) tokens
> + next TOKEN unless exists $query->{$git_token};
> +
> + # don't print things asked in the query (the entry matches them)
> + next TOKEN if defined $query->{$git_token};
> +
> + log_debug("FOUND: $git_token=$entry->{$git_token}");
> + printf "%s=%s\n", $git_token, $entry->{$git_token};
> + }
> +}
> +sub log_verbose {
> + return unless $options{verbose};
> + printf STDERR @_;
> + printf STDERR "\n";
> +}
> +
> +sub log_debug {
> + return unless $options{debug};
> + printf STDERR @_;
> + printf STDERR "\n";
> +}
Otherwise, looks almost ready to me.
Thanks.
^ permalink raw reply
* Re: [PATCHv4] Add contrib/credentials/netrc with GPG support
From: Junio C Hamano @ 2013-02-05 22:09 UTC (permalink / raw)
To: Ted Zlatanov; +Cc: Jeff King, git
In-Reply-To: <877gmmqyho.fsf@lifelogs.com>
Ted Zlatanov <tzz@lifelogs.com> writes:
> On Tue, 05 Feb 2013 11:53:20 -0800 Junio C Hamano <gitster@pobox.com> wrote:
>
> I think it's more readable with large loops, and it actually makes sense
> when you read the code. Not a big deal to me either, I just felt for
> this particular script it was OK.
>
>>> + if ($file =~ m/\.gpg$/) {
>>> + log_verbose("Using GPG to open $file");
>>> + # GPG doesn't work well with 2- or 3-argument open
>
> JCH> If that is the case, please quote $file properly against shell
> JCH> munging it.
>
> Ahhh that gets ugly. OK, quoted.
>
> JCH> The only thing you do on $io is to read from it via "while (<$io>)",
> JCH> so I would personally have written this part like this without
> JCH> having to use IO::File(), though:
>
> JCH> $io = open("-|", qw(gpg --decrypt), $file);
>
> That doesn't work for me, unfortunately. I'm trying to avoid the IPC::*
> modules and such. Please test it yourself with GPG. I'm on Perl
> 5.14.2.
This works for me as expected (sorry for that open $io syntax
gotcha).
-- cut here -- >8 -- cut here --
#!/usr/bin/perl
my $io;
open $io, "-|", qw(gpg --decrypt), $ARGV[0]
or die "$!: gpg open";
while (<$io>) {
print;
}
close $io
or die "$!: gpg close";
-- cut here -- 8< -- cut here --
$ perl --version
This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi
^ permalink raw reply
* Re: [PATCH v2] t4038: add tests for "diff --cc --raw <trees>"
From: Junio C Hamano @ 2013-02-05 22:27 UTC (permalink / raw)
To: John Keeping; +Cc: git, Antoine Pelisse
In-Reply-To: <20130205213949.GY1342@serenity.lan>
Thanks.
^ permalink raw reply
* Re: importing two different trees into a fresh git repo
From: Junio C Hamano @ 2013-02-05 22:29 UTC (permalink / raw)
To: Constantine A. Murenin; +Cc: git
In-Reply-To: <CAPKkNb6+ojb+uvBW+AkhGrhjR85LrJEbmR0KmvaKYb2Cj5Aa4g@mail.gmail.com>
"Constantine A. Murenin" <mureninc@gmail.com> writes:
> I have two distinct trees that were not managed by any RCS, and I'd
> like to import them into a single repository into two separate orphan
> branches, then make sense of what's in there, merge, and unify into
> 'master'.
>
> (To give some context, it's /etc/nginx config files from nginx/1.0.12
> on Debian 6 and nginx/1.2.2 on OpenBSD 5.2.)
As these come from two totally separate sources, I'd find it more
natural to do two repositories, deb-nginx-conf and obsd-nginx-conf,
each with one commit and then pull one into the other (or pull both
to master-nginx-conf if you really wanted to), to me.
^ permalink raw reply
* Re: [PATCHv4] Add contrib/credentials/netrc with GPG support
From: Ted Zlatanov @ 2013-02-05 22:30 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, git
In-Reply-To: <7vpq0equo9.fsf@alter.siamese.dyndns.org>
On Tue, 05 Feb 2013 14:09:58 -0800 Junio C Hamano <gitster@pobox.com> wrote:
JCH> open $io, "-|", qw(gpg --decrypt), $ARGV[0]
OK, the below will be in PATCHv6 (I'll wait on mailing it until after
you've reviewed the rest of PATCHv5). Thanks for checking... I must
have had a typo or a missing comma or something, I could swear I tried
exactly what you show.
Ted
diff --git a/contrib/credential/netrc/git-credential-netrc b/contrib/credential/netrc/git-credential-netrc
index 8298564..5f91630 100755
--- a/contrib/credential/netrc/git-credential-netrc
+++ b/contrib/credential/netrc/git-credential-netrc
@@ -230,13 +230,9 @@ sub load_netrc {
my $io;
if ($gpgmode) {
- # typical shell character escapes from http://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html
- my $f = $file;
- $f =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;
- # GPG doesn't work well with 2- or 3-argument open
- my $cmd = "gpg --decrypt $f";
- log_verbose("Using GPG to open $file: [$cmd]");
- open $io, "$cmd|";
+ my @cmd = (qw(gpg --decrypt), $file);
+ log_verbose("Using GPG to open $file: [@cmd]");
+ open $io, "-|", @cmd;
}
else {
log_verbose("Opening $file...");
^ permalink raw reply related
* Re: [PATCH] git-send-email: add ~/.authinfo parsing
From: Junio C Hamano @ 2013-02-05 23:10 UTC (permalink / raw)
To: Jeff King; +Cc: Michal Nazarewicz, git, Krzysztof Mazur, Michal Nazarewicz
In-Reply-To: <20130130074306.GA17868@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> On Tue, Jan 29, 2013 at 11:53:19AM -0800, Junio C Hamano wrote:
>
>> Either way it still encourages a plaintext password to be on disk,
>> which may not be what we want, even though it may be slight if not
>> really much of an improvement. Again the Help-for-users has this
>> amusing bit:
>
> I do not mind a .netrc or .authinfo parser, because while those formats
> do have security problems, they are standard files that may already be
> in use. So as long as we are not encouraging their use, I do not see a
> problem in supporting them (and we already do the same with curl's netrc
> support).
>
> But it would probably make sense for send-email to support the existing
> git-credential subsystem, so that it can take advantage of secure
> system-specific storage. And that is where we should be pointing new
> users. I think contrib/mw-to-git even has credential support written in
> perl, so it would just need to be factored out to Git.pm.
I see a lot of rerolls on the credential helper front, but is there
anybody working on hooking send-email to the credential framework?
^ permalink raw reply
* Re: Rebased git-subtree changes
From: Junio C Hamano @ 2013-02-05 23:18 UTC (permalink / raw)
To: David A. Greene; +Cc: git
In-Reply-To: <1360064219-28789-1-git-send-email-greened@obbligato.org>
This looks to be of mixed quality. The earlier ones look fairly
finished, while the later ones not so much.
I am tempted to take up to 06/13 and advance them to 'next', without
the rest.
^ permalink raw reply
* Re: [PATCHv5] Add contrib/credentials/netrc with GPG support
From: Junio C Hamano @ 2013-02-05 23:58 UTC (permalink / raw)
To: Ted Zlatanov; +Cc: Jeff King, git
In-Reply-To: <7vip66qu0u.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Otherwise, looks almost ready to me.
For now, I've queued this as a minimum fix-up on top of your patch
and pushed the result out. It is an equivalent of the previous
review comments in a patch form. Please review and incorporate in
your reroll as appropriate.
I haven't looked at the part that interacts with the credential
subsystem itself, though.
contrib/credential/netrc/git-credential-netrc | 35 ++++++++++++---------------
1 file changed, 16 insertions(+), 19 deletions(-)
diff --git a/contrib/credential/netrc/git-credential-netrc b/contrib/credential/netrc/git-credential-netrc
index 8298564..30e05fb 100755
--- a/contrib/credential/netrc/git-credential-netrc
+++ b/contrib/credential/netrc/git-credential-netrc
@@ -74,6 +74,10 @@ Options:
first matching entry found is returned via the credential
helper protocol (see below).
+ When no -f option is given, .authinfo.gpg, .netrc.gpg,
+ .authinfo, and .netrc files in your home directory are used
+ in this order.
+
-k|--insecure : ignore bad file ownership or permissions
-d|--debug : turn on debugging (developer info)
@@ -206,8 +210,7 @@ foreach my $file (@$files) {
unless (scalar @entries) {
if ($!) {
log_verbose("Unable to open $file: $!");
- }
- else {
+ } else {
log_verbose("No netrc entries found in $file");
}
@@ -230,15 +233,10 @@ sub load_netrc {
my $io;
if ($gpgmode) {
- # typical shell character escapes from http://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html
- my $f = $file;
- $f =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;
- # GPG doesn't work well with 2- or 3-argument open
- my $cmd = "gpg --decrypt $f";
- log_verbose("Using GPG to open $file: [$cmd]");
- open $io, "$cmd|";
- }
- else {
+ my @cmd = (qw(gpg --decrypt), $file)
+ log_verbose("Using GPG to open $file: [@cmd]");
+ open $io, "-|", @cmd;
+ } else {
log_verbose("Opening $file...");
open $io, '<', $file;
}
@@ -257,6 +255,9 @@ sub load_netrc {
my %entry;
my $num_port;
+ if (!defined $nentry->{machine}) {
+ next;
+ }
if (defined $nentry->{port} && $nentry->{port} =~ m/^\d+$/) {
$num_port = $nentry->{port};
delete $nentry->{port};
@@ -302,8 +303,7 @@ sub net_netrc_loader {
while (@tok) {
if ($tok[0] eq "default") {
shift(@tok);
- undef $mach; # ignore 'default' lines
-
+ $mach = { machine => undef }
next TOKEN;
}
@@ -313,8 +313,7 @@ sub net_netrc_loader {
my $host = shift @tok;
$mach = { machine => $host };
push @entries, $mach;
- }
- elsif (exists $options{tmap}->{$tok}) {
+ } elsif (exists $options{tmap}->{$tok}) {
unless ($mach) {
log_debug("Skipping token $tok because no machine was given");
next TOKEN;
@@ -329,8 +328,7 @@ sub net_netrc_loader {
# Following line added by rmerrell to remove '/' escape char in .netrc
$value =~ s/\/\\/\\/g;
$mach->{$tok} = $value;
- }
- elsif ($tok eq "macdef") { # we ignore macros
+ } elsif ($tok eq "macdef") { # we ignore macros
next TOKEN unless $mach;
my $value = shift @tok;
$macdef = 1;
@@ -380,8 +378,7 @@ sub find_netrc_entry {
unless ($query->{$check} eq $entry->{$check}) {
next ENTRY;
}
- }
- else {
+ } else {
log_debug("OK: any value satisfies check $check");
}
}
--
1.8.1.2.641.g0b90ac4
^ permalink raw reply related
* Re: [PATCH v2 2/2] i18n: mark OPTION_NUMBER (-NUM) for translation
From: Jiang Xin @ 2013-02-06 0:15 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Duy Nguyen, Git List
In-Reply-To: <7vd2weu1sq.fsf@alter.siamese.dyndns.org>
2013/2/6 Junio C Hamano <gitster@pobox.com>:
> I somehow suspect that this is going in a direction that makes this
> piece of code much less maintainable.
>
> Look at the entire function and see how many places you do fprintf
> on strings that are marked with _(). short_name and long_name are
> not likely to be translated, but everything else is, especially
> multiple places that show _(opts->help) neither of these patches
> touch.
>
> I wonder if it makes more sense to add a helper function that
> returns the number of column positions (not bytes) with a signature
> similar to fprintf() and use that throughout the function instead.
I agree, a helper named 'utf8_fprintf' in utf8.c is better.
I will send a patch latter.
--
Jiang Xin
^ permalink raw reply
* Re: [PATCHv5] Add contrib/credentials/netrc with GPG support
From: Ted Zlatanov @ 2013-02-06 0:34 UTC (permalink / raw)
To: git
In-Reply-To: <7vip66qu0u.fsf@alter.siamese.dyndns.org>
On Tue, 05 Feb 2013 14:24:01 -0800 Junio C Hamano <gitster@pobox.com> wrote:
JCH> Ted Zlatanov <tzz@lifelogs.com> writes:
>> + $f =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;
JCH> Yuck. If you really have to quote, it is often far simpler to take
JCH> advantage of the fact that quoting rule for shell is much simpler
JCH> inside '', i.e.
JCH> sub sq {
JCH> my ($string) = @_;
JCH> $string =~ s|'|'\\''|g;
JCH> return "'$string'";
JCH> }
Oh, that's nice. Thanks. We don't need it anymore, but I'm sad to see
it go unused.
JCH> I think it is saner to do something like this instead here:
JCH> $mach = { machine => undef }
JCH> Otherwise your log_debug() will be filled by the tokens used for the
JCH> default entry, and also this "undef $mach" here will break your
JCH> macdef skipping logic if the default entry has a macdef, I think.
JCH> You can ignore an entry with undefined "machine" in the loop at the
JCH> end of load_netrc.
Cool, I merged your changes into PATCHv6. I'll keep in mind about
merging the trailing else braces, too. I forgot that setting for
cperl-mode (`cperl-merge-trailing-else . t').
Thanks
Ted
^ permalink raw reply
* Re: importing two different trees into a fresh git repo
From: Constantine A. Murenin @ 2013-02-06 0:35 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7va9riqtro.fsf@alter.siamese.dyndns.org>
On 5 February 2013 14:29, Junio C Hamano <gitster@pobox.com> wrote:
> "Constantine A. Murenin" <mureninc@gmail.com> writes:
>
>> I have two distinct trees that were not managed by any RCS, and I'd
>> like to import them into a single repository into two separate orphan
>> branches, then make sense of what's in there, merge, and unify into
>> 'master'.
>>
>> (To give some context, it's /etc/nginx config files from nginx/1.0.12
>> on Debian 6 and nginx/1.2.2 on OpenBSD 5.2.)
>
> As these come from two totally separate sources, I'd find it more
> natural to do two repositories, deb-nginx-conf and obsd-nginx-conf,
> each with one commit and then pull one into the other (or pull both
> to master-nginx-conf if you really wanted to), to me.
Yeah, I guess it might be more of a git-style to have two/three
separate repositories here. (The sources are just a couple of files,
so I think my specific example still calls for merely two orphan
branches.)
Still, is it really expected that you can't create an orphan branch in
an empty repository? On the outside, this sounds like a rather benign
bug.
C.
^ permalink raw reply
* [PATCHv6] Add contrib/credentials/netrc with GPG support
From: Ted Zlatanov @ 2013-02-06 0:38 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, git
In-Reply-To: <7vtxpqnwiv.fsf@alter.siamese.dyndns.org>
Add Git credential helper that can parse netrc/authinfo files.
This credential helper supports multiple files, returning the first one
that matches. It checks file permissions and owner. For *.gpg files,
it will run GPG to decrypt the file.
Signed-off-by: Ted Zlatanov <tzz@lifelogs.com>
---
Changes since PATCHv5:
- reroll from tz/credential-authinfo:
* brace fixes
* list attempted default files in help doc
* 3-arg open() for the GPG pipe
* instead of skipping 'default' tokens, store them as machine => undef
contrib/credential/netrc/Makefile | 12 +
contrib/credential/netrc/git-credential-netrc | 421 +++++++++++++++++++++++++
2 files changed, 433 insertions(+), 0 deletions(-)
create mode 100644 contrib/credential/netrc/Makefile
create mode 100755 contrib/credential/netrc/git-credential-netrc
diff --git a/contrib/credential/netrc/Makefile b/contrib/credential/netrc/Makefile
new file mode 100644
index 0000000..18a924f
--- /dev/null
+++ b/contrib/credential/netrc/Makefile
@@ -0,0 +1,12 @@
+test_netrc:
+ @(echo "bad data" | ./git-credential-netrc -f A -d -v) || echo "Bad invocation test, ignoring failure"
+ @echo "=> Silent invocation... nothing should show up here with a missing file"
+ @echo "bad data" | ./git-credential-netrc -f A get
+ @echo "=> Back to noisy: -v and -d used below, missing file"
+ echo "bad data" | ./git-credential-netrc -f A -d -v get
+ @echo "=> Look for any entry in the default file set"
+ echo "" | ./git-credential-netrc -d -v get
+ @echo "=> Look for github.com in the default file set"
+ echo "host=google.com" | ./git-credential-netrc -d -v get
+ @echo "=> Look for a nonexistent machine in the default file set"
+ echo "host=korovamilkbar" | ./git-credential-netrc -d -v get
diff --git a/contrib/credential/netrc/git-credential-netrc b/contrib/credential/netrc/git-credential-netrc
new file mode 100755
index 0000000..30e05fb
--- /dev/null
+++ b/contrib/credential/netrc/git-credential-netrc
@@ -0,0 +1,421 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+use File::Basename;
+
+my $VERSION = "0.1";
+
+my %options = (
+ help => 0,
+ debug => 0,
+ verbose => 0,
+ insecure => 0,
+ file => [],
+
+ # identical token maps, e.g. host -> host, will be inserted later
+ tmap => {
+ port => 'protocol',
+ machine => 'host',
+ path => 'path',
+ login => 'username',
+ user => 'username',
+ password => 'password',
+ }
+ );
+
+# Map each credential protocol token to itself on the netrc side.
+foreach (values %{$options{tmap}}) {
+ $options{tmap}->{$_} = $_;
+}
+
+# Now, $options{tmap} has a mapping from the netrc format to the Git credential
+# helper protocol.
+
+# Next, we build the reverse token map.
+
+# When $rmap{foo} contains 'bar', that means that what the Git credential helper
+# protocol calls 'bar' is found as 'foo' in the netrc/authinfo file. Keys in
+# %rmap are what we expect to read from the netrc/authinfo file.
+
+my %rmap;
+foreach my $k (keys %{$options{tmap}}) {
+ push @{$rmap{$options{tmap}->{$k}}}, $k;
+}
+
+Getopt::Long::Configure("bundling");
+
+# TODO: maybe allow the token map $options{tmap} to be configurable.
+GetOptions(\%options,
+ "help|h",
+ "debug|d",
+ "insecure|k",
+ "verbose|v",
+ "file|f=s@",
+ );
+
+if ($options{help}) {
+ my $shortname = basename($0);
+ $shortname =~ s/git-credential-//;
+
+ print <<EOHIPPUS;
+
+$0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] [-v] [-k] get
+
+Version $VERSION by tzz\@lifelogs.com. License: BSD.
+
+Options:
+
+ -f|--file AUTHFILE : specify netrc-style files. Files with the .gpg extension
+ will be decrypted by GPG before parsing. Multiple -f
+ arguments are OK. They are processed in order, and the
+ first matching entry found is returned via the credential
+ helper protocol (see below).
+
+ When no -f option is given, .authinfo.gpg, .netrc.gpg,
+ .authinfo, and .netrc files in your home directory are used
+ in this order.
+
+ -k|--insecure : ignore bad file ownership or permissions
+
+ -d|--debug : turn on debugging (developer info)
+
+ -v|--verbose : be more verbose (show files and information found)
+
+To enable this credential helper:
+
+ git config credential.helper '$shortname -f AUTHFILE1 -f AUTHFILE2'
+
+(Note that Git will prepend "git-credential-" to the helper name and look for it
+in the path.)
+
+...and if you want lots of debugging info:
+
+ git config credential.helper '$shortname -f AUTHFILE -d'
+
+...or to see the files opened and data found:
+
+ git config credential.helper '$shortname -f AUTHFILE -v'
+
+Only "get" mode is supported by this credential helper. It opens every AUTHFILE
+and looks for the first entry that matches the requested search criteria:
+
+ 'port|protocol':
+ The protocol that will be used (e.g., https). (protocol=X)
+
+ 'machine|host':
+ The remote hostname for a network credential. (host=X)
+
+ 'path':
+ The path with which the credential will be used. (path=X)
+
+ 'login|user|username':
+ The credential’s username, if we already have one. (username=X)
+
+Thus, when we get this query on STDIN:
+
+host=github.com
+protocol=https
+username=tzz
+
+this credential helper will look for the first entry in every AUTHFILE that
+matches
+
+machine github.com port https login tzz
+
+OR
+
+machine github.com protocol https login tzz
+
+OR... etc. acceptable tokens as listed above. Any unknown tokens are
+simply ignored.
+
+Then, the helper will print out whatever tokens it got from the entry, including
+"password" tokens, mapping back to Git's helper protocol; e.g. "port" is mapped
+back to "protocol". Any redundant entry tokens (part of the original query) are
+skipped.
+
+Again, note that only the first matching entry from all the AUTHFILEs, processed
+in the sequence given on the command line, is used.
+
+Netrc/authinfo tokens can be quoted as 'STRING' or "STRING".
+
+No caching is performed by this credential helper.
+
+EOHIPPUS
+
+ exit 0;
+}
+
+my $mode = shift @ARGV;
+
+# Credentials must get a parameter, so die if it's missing.
+die "Syntax: $0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] get" unless defined $mode;
+
+# Only support 'get' mode; with any other unsupported ones we just exit.
+exit 0 unless $mode eq 'get';
+
+my $files = $options{file};
+
+# if no files were given, use a predefined list.
+# note that .gpg files come first
+unless (scalar @$files) {
+ my @candidates = qw[
+ ~/.authinfo.gpg
+ ~/.netrc.gpg
+ ~/.authinfo
+ ~/.netrc
+ ];
+
+ $files = $options{file} = [ map { glob $_ } @candidates ];
+}
+
+my $query = read_credential_data_from_stdin();
+
+FILE:
+foreach my $file (@$files) {
+ my $gpgmode = $file =~ m/\.gpg$/;
+ unless (-r $file) {
+ log_verbose("Unable to read $file; skipping it");
+ next FILE;
+ }
+
+ # the following check is copied from Net::Netrc, for non-GPG files
+ # OS/2 and Win32 do not handle stat in a way compatable with this check :-(
+ unless ($gpgmode || $options{insecure} ||
+ $^O eq 'os2'
+ || $^O eq 'MSWin32'
+ || $^O eq 'MacOS'
+ || $^O =~ /^cygwin/) {
+ my @stat = stat($file);
+
+ if (@stat) {
+ if ($stat[2] & 077) {
+ log_verbose("Insecure $file (mode=%04o); skipping it",
+ $stat[2] & 07777);
+ next FILE;
+ }
+
+ if ($stat[4] != $<) {
+ log_verbose("Not owner of $file; skipping it");
+ next FILE;
+ }
+ }
+ }
+
+ my @entries = load_netrc($file, $gpgmode);
+
+ unless (scalar @entries) {
+ if ($!) {
+ log_verbose("Unable to open $file: $!");
+ } else {
+ log_verbose("No netrc entries found in $file");
+ }
+
+ next FILE;
+ }
+
+ my $entry = find_netrc_entry($query, @entries);
+ if ($entry) {
+ print_credential_data($entry, $query);
+ # we're done!
+ last FILE;
+ }
+}
+
+exit 0;
+
+sub load_netrc {
+ my $file = shift @_;
+ my $gpgmode = shift @_;
+
+ my $io;
+ if ($gpgmode) {
+ my @cmd = (qw(gpg --decrypt), $file)
+ log_verbose("Using GPG to open $file: [@cmd]");
+ open $io, "-|", @cmd;
+ } else {
+ log_verbose("Opening $file...");
+ open $io, '<', $file;
+ }
+
+ # nothing to do if the open failed (we log the error later)
+ return unless $io;
+
+ # Net::Netrc does this, but the functionality is merged with the file
+ # detection logic, so we have to extract just the part we need
+ my @netrc_entries = net_netrc_loader($io);
+
+ # these entries will use the credential helper protocol token names
+ my @entries;
+
+ foreach my $nentry (@netrc_entries) {
+ my %entry;
+ my $num_port;
+
+ if (!defined $nentry->{machine}) {
+ next;
+ }
+ if (defined $nentry->{port} && $nentry->{port} =~ m/^\d+$/) {
+ $num_port = $nentry->{port};
+ delete $nentry->{port};
+ }
+
+ # create the new entry for the credential helper protocol
+ $entry{$options{tmap}->{$_}} = $nentry->{$_} foreach keys %$nentry;
+
+ # for "host X port Y" where Y is an integer (captured by
+ # $num_port above), set the host to "X:Y"
+ if (defined $entry{host} && defined $num_port) {
+ $entry{host} = join(':', $entry{host}, $num_port);
+ }
+
+ push @entries, \%entry;
+ }
+
+ return @entries;
+}
+
+sub net_netrc_loader {
+ my $fh = shift @_;
+ my @entries;
+ my ($mach, $macdef, $tok, @tok);
+
+ LINE:
+ while (<$fh>) {
+ undef $macdef if /\A\n\Z/;
+
+ if ($macdef) {
+ next LINE;
+ }
+
+ s/^\s*//;
+ chomp;
+
+ while (length && s/^("((?:[^"]+|\\.)*)"|((?:[^\\\s]+|\\.)*))\s*//) {
+ (my $tok = $+) =~ s/\\(.)/$1/g;
+ push(@tok, $tok);
+ }
+
+ TOKEN:
+ while (@tok) {
+ if ($tok[0] eq "default") {
+ shift(@tok);
+ $mach = { machine => undef }
+ next TOKEN;
+ }
+
+ $tok = shift(@tok);
+
+ if ($tok eq "machine") {
+ my $host = shift @tok;
+ $mach = { machine => $host };
+ push @entries, $mach;
+ } elsif (exists $options{tmap}->{$tok}) {
+ unless ($mach) {
+ log_debug("Skipping token $tok because no machine was given");
+ next TOKEN;
+ }
+
+ my $value = shift @tok;
+ unless (defined $value) {
+ log_debug("Token $tok had no value, skipping it.");
+ next TOKEN;
+ }
+
+ # Following line added by rmerrell to remove '/' escape char in .netrc
+ $value =~ s/\/\\/\\/g;
+ $mach->{$tok} = $value;
+ } elsif ($tok eq "macdef") { # we ignore macros
+ next TOKEN unless $mach;
+ my $value = shift @tok;
+ $macdef = 1;
+ }
+ }
+ }
+
+ return @entries;
+}
+
+sub read_credential_data_from_stdin {
+ # the query: start with every token with no value
+ my %q = map { $_ => undef } values(%{$options{tmap}});
+
+ while (<STDIN>) {
+ next unless m/^([^=]+)=(.+)/;
+
+ my ($token, $value) = ($1, $2);
+ die "Unknown search token $token" unless exists $q{$token};
+ $q{$token} = $value;
+ log_debug("We were given search token $token and value $value");
+ }
+
+ foreach (sort keys %q) {
+ log_debug("Searching for %s = %s", $_, $q{$_} || '(any value)');
+ }
+
+ return \%q;
+}
+
+# takes the search tokens and then a list of entries
+# each entry is a hash reference
+sub find_netrc_entry {
+ my $query = shift @_;
+
+ ENTRY:
+ foreach my $entry (@_)
+ {
+ my $entry_text = join ', ', map { "$_=$entry->{$_}" } keys %$entry;
+ foreach my $check (sort keys %$query) {
+ if (defined $query->{$check}) {
+ log_debug("compare %s [%s] to [%s] (entry: %s)",
+ $check,
+ $entry->{$check},
+ $query->{$check},
+ $entry_text);
+ unless ($query->{$check} eq $entry->{$check}) {
+ next ENTRY;
+ }
+ } else {
+ log_debug("OK: any value satisfies check $check");
+ }
+ }
+
+ return $entry;
+ }
+
+ # nothing was found
+ return;
+}
+
+sub print_credential_data {
+ my $entry = shift @_;
+ my $query = shift @_;
+
+ log_debug("entry has passed all the search checks");
+ TOKEN:
+ foreach my $git_token (sort keys %$entry) {
+ log_debug("looking for useful token $git_token");
+ # don't print unknown (to the credential helper protocol) tokens
+ next TOKEN unless exists $query->{$git_token};
+
+ # don't print things asked in the query (the entry matches them)
+ next TOKEN if defined $query->{$git_token};
+
+ log_debug("FOUND: $git_token=$entry->{$git_token}");
+ printf "%s=%s\n", $git_token, $entry->{$git_token};
+ }
+}
+sub log_verbose {
+ return unless $options{verbose};
+ printf STDERR @_;
+ printf STDERR "\n";
+}
+
+sub log_debug {
+ return unless $options{debug};
+ printf STDERR @_;
+ printf STDERR "\n";
+}
--
1.7.9.rc2
^ permalink raw reply related
* [PATCH v3] Add utf8_fprintf helper which returns correct columns
From: Jiang Xin @ 2013-02-06 1:16 UTC (permalink / raw)
To: Junio C Hamano, Nguyễn Thái Ngọc Duy; +Cc: Git List, Jiang Xin
In-Reply-To: <7vd2weu1sq.fsf@alter.siamese.dyndns.org>
Since command usages can be translated, they may not align well especially
when they are translated to CJK. A wrapper utf8_fprintf can help to return
the correct columns required.
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
parse-options.c | 5 +++--
utf8.c | 20 ++++++++++++++++++++
utf8.h | 1 +
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/parse-options.c b/parse-options.c
index 67e98..a6ce9e 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -3,6 +3,7 @@
#include "cache.h"
#include "commit.h"
#include "color.h"
+#include "utf8.h"
static int parse_options_usage(struct parse_opt_ctx_t *ctx,
const char * const *usagestr,
@@ -482,7 +483,7 @@ static int usage_argh(const struct option *opts, FILE *outfile)
s = literal ? "[%s]" : "[<%s>]";
else
s = literal ? " %s" : " <%s>";
- return fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
+ return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
}
#define USAGE_OPTS_WIDTH 24
@@ -541,7 +542,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
if (opts->long_name)
pos += fprintf(outfile, "--%s", opts->long_name);
if (opts->type == OPTION_NUMBER)
- pos += fprintf(outfile, "-NUM");
+ pos += utf8_fprintf(outfile, _("-NUM"));
if ((opts->flags & PARSE_OPT_LITERAL_ARGHELP) ||
!(opts->flags & PARSE_OPT_NOARG))
diff --git a/utf8.c b/utf8.c
index a4ee6..52dbd 100644
--- a/utf8.c
+++ b/utf8.c
@@ -430,6 +430,26 @@ int same_encoding(const char *src, const char *dst)
}
/*
+ * Wrapper for fprintf and returns the total number of columns required
+ * for the printed string, assuming that the string is utf8.
+ */
+int utf8_fprintf(FILE *stream, const char *format, ...)
+{
+ struct strbuf buf = STRBUF_INIT;
+ va_list arg;
+ int columns;
+
+ va_start (arg, format);
+ strbuf_vaddf(&buf, format, arg);
+ va_end (arg);
+
+ fputs(buf.buf, stream);
+ columns = utf8_strwidth(buf.buf);
+ strbuf_release(&buf);
+ return columns;
+}
+
+/*
* Given a buffer and its encoding, return it re-encoded
* with iconv. If the conversion fails, returns NULL.
*/
diff --git a/utf8.h b/utf8.h
index a2142..501b2 100644
--- a/utf8.h
+++ b/utf8.h
@@ -8,6 +8,7 @@ int utf8_strwidth(const char *string);
int is_utf8(const char *text);
int is_encoding_utf8(const char *name);
int same_encoding(const char *, const char *);
+int utf8_fprintf(FILE *, const char *, ...);
void strbuf_add_wrapped_text(struct strbuf *buf,
const char *text, int indent, int indent2, int width);
--
1.8.1.1.370.g47b6ee8.dirty
^ permalink raw reply
* Re: [PATCH v2 2/2] i18n: mark OPTION_NUMBER (-NUM) for translation
From: Junio C Hamano @ 2013-02-06 2:44 UTC (permalink / raw)
To: Jiang Xin; +Cc: Duy Nguyen, Git List
In-Reply-To: <CANYiYbF1cS=K9M0cwE5V0pUJMPEYGiJOjJwg5KQScCf8pjyTqw@mail.gmail.com>
Jiang Xin <worldhello.net@gmail.com> writes:
> 2013/2/6 Junio C Hamano <gitster@pobox.com>:
>> I somehow suspect that this is going in a direction that makes this
>> piece of code much less maintainable.
>>
>> Look at the entire function and see how many places you do fprintf
>> on strings that are marked with _(). short_name and long_name are
>> not likely to be translated, but everything else is, especially
>> multiple places that show _(opts->help) neither of these patches
>> touch.
>>
>> I wonder if it makes more sense to add a helper function that
>> returns the number of column positions (not bytes) with a signature
>> similar to fprintf() and use that throughout the function instead.
>
> I agree, a helper named 'utf8_fprintf' in utf8.c is better.
> I will send a patch latter.
Yeah, the idea of a helper function I agree with; I am not thrilled
with the name utf8_fprintf() though. People use the return value of
fprintf() for error detection (negative return value means an error)
most of the time (even though non-negative value gives the number of
bytes shown), but the primary use of the return value from the
utf8_fprintf() function will be to get the display width, and the
name does not quite capture that.
^ permalink raw reply
* Re: [PATCH v2 2/2] i18n: mark OPTION_NUMBER (-NUM) for translation
From: Jiang Xin @ 2013-02-06 3:02 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Duy Nguyen, Git List
In-Reply-To: <7vpq0enoui.fsf@alter.siamese.dyndns.org>
2013/2/6 Junio C Hamano <gitster@pobox.com>:
> Jiang Xin <worldhello.net@gmail.com> writes:
>> I agree, a helper named 'utf8_fprintf' in utf8.c is better.
>> I will send a patch latter.
>
> Yeah, the idea of a helper function I agree with; I am not thrilled
> with the name utf8_fprintf() though. People use the return value of
> fprintf() for error detection (negative return value means an error)
> most of the time (even though non-negative value gives the number of
> bytes shown), but the primary use of the return value from the
> utf8_fprintf() function will be to get the display width, and the
> name does not quite capture that.
>
How about this since [PATCH v3]:
diff --git a/utf8.c b/utf8.c
index 52dbd..b893a 100644
--- a/utf8.c
+++ b/utf8.c
@@ -443,8 +443,11 @@ int utf8_fprintf(FILE *stream, const char *format, ...)
strbuf_vaddf(&buf, format, arg);
va_end (arg);
- fputs(buf.buf, stream);
- columns = utf8_strwidth(buf.buf);
+ columns = fputs(buf.buf, stream);
+ /* If no error occurs, and really write something (columns > 0),
+ * calculate really columns width with utf8_strwidth. */
+ if (columns > 0)
+ columns = utf8_strwidth(buf.buf);
strbuf_release(&buf);
return columns;
}
--
蒋鑫
北京群英汇信息技术有限公司
邮件: worldhello.net@gmail.com
网址: http://www.ossxp.com/
博客: http://www.worldhello.net/
微博: http://weibo.com/gotgit/
电话: 010-51262007, 18601196889
^ permalink raw reply
* Re: [PATCH v2 2/2] i18n: mark OPTION_NUMBER (-NUM) for translation
From: Junio C Hamano @ 2013-02-06 4:35 UTC (permalink / raw)
To: Jiang Xin; +Cc: Duy Nguyen, Git List
In-Reply-To: <CANYiYbF8DCPxqGQ2AFFXpSm0nO+wFDg=qrn9C8uoZO6fj__NHA@mail.gmail.com>
Jiang Xin <worldhello.net@gmail.com> writes:
> 2013/2/6 Junio C Hamano <gitster@pobox.com>:
>> Jiang Xin <worldhello.net@gmail.com> writes:
>>> I agree, a helper named 'utf8_fprintf' in utf8.c is better.
>>> I will send a patch latter.
>>
>> Yeah, the idea of a helper function I agree with; I am not thrilled
>> with the name utf8_fprintf() though. People use the return value of
>> fprintf() for error detection (negative return value means an error)
>> most of the time (even though non-negative value gives the number of
>> bytes shown), but the primary use of the return value from the
>> utf8_fprintf() function will be to get the display width, and the
>> name does not quite capture that.
>>
>
> How about this since [PATCH v3]:
>
> diff --git a/utf8.c b/utf8.c
> index 52dbd..b893a 100644
> --- a/utf8.c
> +++ b/utf8.c
> @@ -443,8 +443,11 @@ int utf8_fprintf(FILE *stream, const char *format, ...)
> strbuf_vaddf(&buf, format, arg);
> va_end (arg);
>
> - fputs(buf.buf, stream);
> - columns = utf8_strwidth(buf.buf);
> + columns = fputs(buf.buf, stream);
> + /* If no error occurs, and really write something (columns > 0),
> + * calculate really columns width with utf8_strwidth. */
> + if (columns > 0)
> + columns = utf8_strwidth(buf.buf);
> strbuf_release(&buf);
> return columns;
> }
Yeah, the error checking is necessary; it would make your intention
more clear to say:
if (0 <= columns)
columns = utf8_strwidth(buf.buf);
though, as buf.buf _may_ be an empty string, and with the "if"
statement you are saying "we return the width only when output did
not result in an error".
The above bugfix does not address my original concern about
the name, though.
^ permalink raw reply
* Adding Missing Tags to a Repository
From: Neil @ 2013-02-06 4:45 UTC (permalink / raw)
To: git
Hi everyone,
A while back I did a svn-to-git migration for my team. Our subversion
repository had about 30K+ commits, 100+ branches, 2K+ tags, all made
over a 20+ year period. I was doing the migration using git-svn, and
my big problem was the tags. git-svn seemed to want to traverse the
entire history of each tag, which was taking a long time. Because time
and resources were limited, I ended up just migrating the branches and
trunk, with the idea that I would handle the tags at a later date. My
original plan to do that was to crawl the subversion log, find where
the tags were made, and apply a git tag to the commit that was the
source of the tag. This was a bad idea.
I've found that over the years, people have made tags that are only
subdirectories of the source tree, made tags off of other tags, and
committed to tags. The latter is the biggest problem, since those
commits don't seem to be stored in the git repository because they
never appeared in the branches/trunk.
So, I'm wondering what my options are to bring back this history. One
idea is to somehow resume the git-svn download, but changing it to
also scan tags (it sounds like it should be possible, but I haven't
tried it yet). Or maybe there's some other tool that will more quickly
clone the repository including tags, and then I can somehow splice the
tags back into the repository we're already using?
Any ideas or suggestions?
Thanks!
^ permalink raw reply
* Re: [PATCH] git-send-email: add ~/.authinfo parsing
From: Matthieu Moy @ 2013-02-06 8:11 UTC (permalink / raw)
To: Junio C Hamano
Cc: Jeff King, Michal Nazarewicz, git, Krzysztof Mazur,
Michal Nazarewicz
In-Reply-To: <7v6226pdb7.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> I see a lot of rerolls on the credential helper front, but is there
> anybody working on hooking send-email to the credential framework?
Not answering the question, but git-remote-mediawiki supports the
credential framework. It is written in perl, and the credential support
is rather cleanly written and doesn't have dependencies on the wiki
part, so the way to go for send-email is probably to libify the
credential support in git-remote-mediawiki, and to use it in send-email.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox