{"thread":{"id":"49398","subject":"credential.<url>.helper with partial url path","startedAt":"2018-09-21T17:01:37Z","lastAt":"2018-09-21T22:55:42Z","messageCount":2,"participants":["Zych, David M","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"358616","messageId":"c3147945-2b5c-68f8-91e7-6edc78a05801@illinois.edu","threadId":"49398","inReplyTo":null,"subject":"credential.<url>.helper with partial url path","fromName":"Zych, David M","fromEmail":"dmrz@illinois.edu","sentAt":"2018-09-21T16:56:20Z","receivedAt":"2018-09-21T17:01:37Z","isPatch":false,"sender":{"key":"dmrz@illinois.edu","avatar":null},"body":"Suppose I need to use different credential.helper values for different \nrepositories on the same HTTPS host.  Ideally I would like to be able to \nwrite this logic using a partial URL path prefix, for example in \n~/.gitconfig\n\n[credential \"https://example.com/prefix1/foo.git\"]\n         helper = !ZZZ\n[credential \"https://example.com/prefix1/\"]\n         helper = !YYY\n[credential \"https://example.com/\"]\n         useHttpPath = true\n         helper = !XXX\n\nFor prefix1/foo.git (exact path match) this tries ZZZ first as desired:\n\n$ git credential fill\nprotocol=https\nhost=example.com\npath=prefix1/foo.git\n\nZZZ get: ZZZ: command not found\nXXX get: XXX: command not found\nUsername for 'https://example.com/prefix1/foo.git': ^C\n\nHowever, prefix1/bar.git does not try YYY:\n\n$ git credential fill\nprotocol=https\nhost=example.com\npath=prefix1/bar.git\n\nXXX get: XXX: command not found\nUsername for 'https://example.com/prefix1/bar.git': ^C\n\neven though (AFAICT) the general behavior of git-config seems to imply \nthat it would do so:\n\n$ git config --get-urlmatch credential https://example.com/prefix1/bar.git\ncredential.helper !YYY\ncredential.usehttppath true\n\nIs this discrepancy intended?\n\nThe documentation in `man gitcredentials` \n(https://git-scm.com/docs/gitcredentials) points out quite explicitly \nthat my patterns will not match foo.example.com nor plain http, but both \nof those rules are consistent with what git-config reports:\n\n$ git config --get-urlmatch credential https://foo.example.com/\ncredential.helper osxkeychain\n$ git config --get-urlmatch credential http://example.com/\ncredential.helper osxkeychain\n\nIf indeed the current behavior of git-credential is as intended, I think \nit would be helpful for that manpage to explicitly mention it (i.e. that \nyou may specify a URL path component but that it must match exactly). \nRight now the only example given is one in which 'the \"pattern\" URL does \nnot care about the path component at all.'\n\nI'm testing against\n\n$ git --version\ngit version 2.19.0\n\ninstalled via homebrew on Mac OS X.\n\nThanks,\nDavid\n\n-- \nDavid Zych\nLead Network Service Engineer\nUniversity of Illinois Technology Services\n"},{"id":"358682","messageId":"20180921225539.GF11177@sigill.intra.peff.net","threadId":"49398","inReplyTo":"c3147945-2b5c-68f8-91e7-6edc78a05801@illinois.edu","subject":"Re: credential.<url>.helper with partial url path","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2018-09-21T22:55:39Z","receivedAt":"2018-09-21T22:55:42Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Sep 21, 2018 at 04:56:20PM +0000, Zych, David M wrote:\n\n> Suppose I need to use different credential.helper values for different \n> repositories on the same HTTPS host.  Ideally I would like to be able to \n> write this logic using a partial URL path prefix, for example in \n> ~/.gitconfig\n> \n> [credential \"https://example.com/prefix1/foo.git\"]\n>          helper = !ZZZ\n> [credential \"https://example.com/prefix1/\"]\n>          helper = !YYY\n> [credential \"https://example.com/\"]\n>          useHttpPath = true\n>          helper = !XXX\n> [...]\n> $ git config --get-urlmatch credential https://example.com/prefix1/bar.git\n> credential.helper !YYY\n> credential.usehttppath true\n> \n> Is this discrepancy intended?\n\nSort of. The matching done by the credential code predates the config\ncode learning about url matching, so it uses a much more basic system.\nIt walks through the config in order for a particular request, throwing\naway any entries whose subsections don't match, and then applying (in\nthe order it finds them) any entries which do. The matching for paths is\ndone using the whole path, not a prefix match.\n\nThere's something else going on, too: credential.helper is a\nmulti-valued variable, so it's going to try each matching helper in\nturn. Whereas \"git config --get\" (and \"--get-urlmatch\") assume you're\nlooking for a single value, and use the last-one-wins rule that most\nvariables use.\n\nNormally you'd want to use \"--get-all\" for that, though I don't know if\nthere's a way to combine it with url matching.\n\nSo what you're seeing is the code working as designed, but I agree the\nresult kind of sucks. I wouldn't be sad to see the credential code moved\nover to use the same url-matching as http.* uses. It would technically\nbe backwards-incompatible in a few cases, but I think the new behavior\nwould almost always be what the person intended in the first place.\n\nWith the current code, you'd have to teach your helper to be more clever\nabout matching the path. E.g., by wrapping your existing helper with\nsomething like:\n\n-- >8 --\n#!/usr/bin/perl\n\nmy %input = map { /(.*?)=(.*)/ } <STDIN>;\nmy $helper =\n  $input{path} =~ m{^prefix1/foo\\.git} ? 'ZZZ' :\n  $input{path} =~ m{^prefix1/} ? 'YYY' :\n  'XXX';\n\nmy $pid = open(my $out, '|-', $helper, @ARGV);\nprint $out \"$_=$input{$_}\\n\" for keys(%input);\nclose($out);\nwaitpid $pid, 0;\n-- >8 --\n\nI know that's pretty nasty for your simple use case, but I think it's\nthe best you can do with the current system.\n\n> If indeed the current behavior of git-credential is as intended, I think \n> it would be helpful for that manpage to explicitly mention it (i.e. that \n> you may specify a URL path component but that it must match exactly). \n> Right now the only example given is one in which 'the \"pattern\" URL does \n> not care about the path component at all.'\n\nYes, I think this could be more clear in the \"credential contexts\"\nsection of gitcredentials(7). Do you want to try to make a patch?\n\n-Peff\n"}]}