diff options
author | Junio C Hamano <gitster@pobox.com> | 2015-06-05 12:00:03 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-06-05 12:00:04 -0700 |
commit | d9c82fa7a75ae617718f195bb5f5ff5c904f2687 (patch) | |
tree | 202fad68c8cd4f1dc82f7e51bbd3b53eb391c077 /credential-store.c | |
parent | 9eabf5b536662000f79978c4d1b6e4eff5c8d785 (diff) | |
parent | 846e5dfbab5d5a0a85252c1400dc0371e02e75a8 (diff) | |
download | git-d9c82fa7a75ae617718f195bb5f5ff5c904f2687.tar.gz |
Merge branch 'pt/xdg-config-path' into maint
Code clean-up for xdg configuration path support.
* pt/xdg-config-path:
path.c: remove home_config_paths()
git-config: replace use of home_config_paths()
git-commit: replace use of home_config_paths()
credential-store.c: replace home_config_paths() with xdg_config_home()
dir.c: replace home_config_paths() with xdg_config_home()
attr.c: replace home_config_paths() with xdg_config_home()
path.c: implement xdg_config_home()
t0302: "unreadable" test needs POSIXPERM
t0302: test credential-store support for XDG_CONFIG_HOME
git-credential-store: support XDG_CONFIG_HOME
git-credential-store: support multiple credential files
Diffstat (limited to 'credential-store.c')
-rw-r--r-- | credential-store.c | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/credential-store.c b/credential-store.c index 925d3f4024..f6925096ff 100644 --- a/credential-store.c +++ b/credential-store.c @@ -6,7 +6,7 @@ static struct lock_file credential_lock; -static void parse_credential_file(const char *fn, +static int parse_credential_file(const char *fn, struct credential *c, void (*match_cb)(struct credential *), void (*other_cb)(struct strbuf *)) @@ -14,18 +14,20 @@ static void parse_credential_file(const char *fn, FILE *fh; struct strbuf line = STRBUF_INIT; struct credential entry = CREDENTIAL_INIT; + int found_credential = 0; fh = fopen(fn, "r"); if (!fh) { - if (errno != ENOENT) + if (errno != ENOENT && errno != EACCES) die_errno("unable to open %s", fn); - return; + return found_credential; } while (strbuf_getline(&line, fh, '\n') != EOF) { credential_from_url(&entry, line.buf); if (entry.username && entry.password && credential_match(c, &entry)) { + found_credential = 1; if (match_cb) { match_cb(&entry); break; @@ -38,6 +40,7 @@ static void parse_credential_file(const char *fn, credential_clear(&entry); strbuf_release(&line); fclose(fh); + return found_credential; } static void print_entry(struct credential *c) @@ -64,21 +67,10 @@ static void rewrite_credential_file(const char *fn, struct credential *c, die_errno("unable to commit credential store"); } -static void store_credential(const char *fn, struct credential *c) +static void store_credential_file(const char *fn, struct credential *c) { struct strbuf buf = STRBUF_INIT; - /* - * Sanity check that what we are storing is actually sensible. - * In particular, we can't make a URL without a protocol field. - * Without either a host or pathname (depending on the scheme), - * we have no primary key. And without a username and password, - * we are not actually storing a credential. - */ - if (!c->protocol || !(c->host || c->path) || - !c->username || !c->password) - return; - strbuf_addf(&buf, "%s://", c->protocol); strbuf_addstr_urlencode(&buf, c->username, 1); strbuf_addch(&buf, ':'); @@ -95,8 +87,37 @@ static void store_credential(const char *fn, struct credential *c) strbuf_release(&buf); } -static void remove_credential(const char *fn, struct credential *c) +static void store_credential(const struct string_list *fns, struct credential *c) +{ + struct string_list_item *fn; + + /* + * Sanity check that what we are storing is actually sensible. + * In particular, we can't make a URL without a protocol field. + * Without either a host or pathname (depending on the scheme), + * we have no primary key. And without a username and password, + * we are not actually storing a credential. + */ + if (!c->protocol || !(c->host || c->path) || !c->username || !c->password) + return; + + for_each_string_list_item(fn, fns) + if (!access(fn->string, F_OK)) { + store_credential_file(fn->string, c); + return; + } + /* + * Write credential to the filename specified by fns->items[0], thus + * creating it + */ + if (fns->nr) + store_credential_file(fns->items[0].string, c); +} + +static void remove_credential(const struct string_list *fns, struct credential *c) { + struct string_list_item *fn; + /* * Sanity check that we actually have something to match * against. The input we get is a restrictive pattern, @@ -105,14 +126,20 @@ static void remove_credential(const char *fn, struct credential *c) * to empty input. So explicitly disallow it, and require that the * pattern have some actual content to match. */ - if (c->protocol || c->host || c->path || c->username) - rewrite_credential_file(fn, c, NULL); + if (!c->protocol && !c->host && !c->path && !c->username) + return; + for_each_string_list_item(fn, fns) + if (!access(fn->string, F_OK)) + rewrite_credential_file(fn->string, c, NULL); } -static int lookup_credential(const char *fn, struct credential *c) +static void lookup_credential(const struct string_list *fns, struct credential *c) { - parse_credential_file(fn, c, print_entry, NULL); - return c->username && c->password; + struct string_list_item *fn; + + for_each_string_list_item(fn, fns) + if (parse_credential_file(fn->string, c, print_entry, NULL)) + return; /* Found credential */ } int main(int argc, char **argv) @@ -123,6 +150,7 @@ int main(int argc, char **argv) }; const char *op; struct credential c = CREDENTIAL_INIT; + struct string_list fns = STRING_LIST_INIT_DUP; char *file = NULL; struct option options[] = { OPT_STRING(0, "file", &file, "path", @@ -137,22 +165,30 @@ int main(int argc, char **argv) usage_with_options(usage, options); op = argv[0]; - if (!file) - file = expand_user_path("~/.git-credentials"); - if (!file) + if (file) { + string_list_append(&fns, file); + } else { + if ((file = expand_user_path("~/.git-credentials"))) + string_list_append_nodup(&fns, file); + file = xdg_config_home("credentials"); + if (file) + string_list_append_nodup(&fns, file); + } + if (!fns.nr) die("unable to set up default path; use --file"); if (credential_read(&c, stdin) < 0) die("unable to read credential"); if (!strcmp(op, "get")) - lookup_credential(file, &c); + lookup_credential(&fns, &c); else if (!strcmp(op, "erase")) - remove_credential(file, &c); + remove_credential(&fns, &c); else if (!strcmp(op, "store")) - store_credential(file, &c); + store_credential(&fns, &c); else ; /* Ignore unknown operation. */ + string_list_clear(&fns, 0); return 0; } |