git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCHv5] Add contrib/credentials/netrc with GPG support

From
Junio C Hamano <gitster@pobox.com>
Date
Feb 5, 2013, 22:24 UTC
Message-ID
<7vip66qu0u.fsf@alter.siamese.dyndns.org>
In-Reply-To
<8738xaqy40.fsf_-_@lifelogs.com>
Ted Zlatanov <tzz@lifelogs.com> writes:
Show 5 quoted lines
> +	unless (scalar @entries) {
> +		if ($!) {
> +			log_verbose("Unable to open $file: $!");
> +		}
> +		else {
	} else {
Show 7 quoted lines
> +			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.
Show 30 quoted lines
> +	# 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.
Show 26 quoted lines
> +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.

Show 88 quoted 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;
> +}
I'll leave this part to Peff to comment on.
Show 30 quoted lines
> +
> +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.
Previous: Ted ZlatanovNext: Junio C Hamano
Message 25 of 38 in “Add contrib/credentials/netrc with GPG support”
  1. Add contrib/credentials/netrc with GPG supportTed Zlatanov, Feb 4, 2013
  2. Jeff KingFeb 4, 2013
  3. Ted ZlatanovFeb 4, 2013
  4. Add contrib/credentials/netrc with GPG support, try #2Ted Zlatanov, Feb 4, 2013
  5. Junio C HamanoFeb 4, 2013
  6. Jeff KingFeb 4, 2013
  7. Junio C HamanoFeb 4, 2013
  8. Ted ZlatanovFeb 4, 2013
  9. [PATCHv3] Add contrib/credentials/netrc with GPG supportTed Zlatanov, Feb 4, 2013
  10. Ted ZlatanovFeb 4, 2013
  11. Junio C HamanoFeb 4, 2013
  12. Ted ZlatanovFeb 4, 2013
  13. Junio C HamanoFeb 5, 2013
  14. Ted ZlatanovFeb 5, 2013
  15. Junio C HamanoFeb 5, 2013
  16. Junio C HamanoFeb 5, 2013
  17. Junio C HamanoFeb 5, 2013
  18. Ted ZlatanovFeb 5, 2013
  19. [PATCHv4] Add contrib/credentials/netrc with GPG supportTed Zlatanov, Feb 5, 2013
  20. Junio C HamanoFeb 5, 2013
  21. Ted ZlatanovFeb 5, 2013
  22. Junio C HamanoFeb 5, 2013
  23. Ted ZlatanovFeb 5, 2013
  24. [PATCHv5] Add contrib/credentials/netrc with GPG supportTed Zlatanov, Feb 5, 2013
  25. Junio C HamanoFeb 5, 2013
  26. Junio C HamanoFeb 5, 2013
  27. [PATCHv6] Add contrib/credentials/netrc with GPG supportTed Zlatanov, Feb 6, 2013
  28. Junio C HamanoFeb 7, 2013
  29. Ted ZlatanovFeb 8, 2013
  30. Junio C HamanoFeb 8, 2013
  31. Jeff KingFeb 8, 2013
  32. Ted ZlatanovFeb 25, 2013
  33. Add contrib/credentials/netrc with GPG supportTed Zlatanov, Feb 25, 2013
  34. Ted ZlatanovFeb 6, 2013
  35. Junio C HamanoFeb 5, 2013
  36. Ted ZlatanovFeb 5, 2013
  37. Junio C HamanoFeb 5, 2013
  38. Ted ZlatanovFeb 5, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.