FIXME: hotpatch for compatibility with latest hg
[git] / credential-store.c
1 #include "cache.h"
2 #include "credential.h"
3 #include "string-list.h"
4 #include "parse-options.h"
5
6 static int lookup_credential(const char *fn, struct credential *c)
7 {
8         config_exclusive_filename = fn;
9         credential_from_config(c);
10         return c->username && c->password;
11 }
12
13 static void store_item(const char *fn, const char *unique,
14                        const char *item, const char *value)
15 {
16         struct strbuf key = STRBUF_INIT;
17
18         if (!unique)
19                 return;
20
21         config_exclusive_filename = fn;
22         umask(077);
23
24         strbuf_addf(&key, "credential.%s.%s", unique, item);
25         git_config_set(key.buf, value);
26         strbuf_release(&key);
27 }
28
29 static void store_credential(const char *fn, struct credential *c)
30 {
31         store_item(fn, c->unique, "username", c->username);
32         store_item(fn, c->unique, "password", c->password);
33 }
34
35 static void remove_credential(const char *fn, struct credential *c)
36 {
37         store_item(fn, c->unique, "username", NULL);
38         store_item(fn, c->unique, "password", NULL);
39 }
40
41 int main(int argc, const char **argv)
42 {
43         const char * const usage[] = {
44                 "git credential-store [options]",
45                 NULL
46         };
47         struct credential c = { NULL };
48         struct string_list chain = STRING_LIST_INIT_NODUP;
49         char *store = NULL;
50         int reject = 0;
51         struct option options[] = {
52                 OPT_STRING_LIST(0, "store", &store, "file",
53                                 "fetch and store credentials in <file>"),
54                 OPT_STRING_LIST(0, "chain", &chain, "helper",
55                                 "use <helper> to get non-cached credentials"),
56                 OPT_BOOLEAN(0, "reject", &reject,
57                             "reject a stored credential"),
58                 OPT_STRING(0, "username", &c.username, "name",
59                            "an existing username"),
60                 OPT_STRING(0, "description", &c.description, "desc",
61                            "human-readable description of the credential"),
62                 OPT_STRING(0, "unique", &c.unique, "token",
63                            "a unique context for the credential"),
64                 OPT_END()
65         };
66
67         argc = parse_options(argc, argv, NULL, options, usage, 0);
68         if (argc)
69                 usage_with_options(usage, options);
70
71         if (!store)
72                 store = expand_user_path("~/.git-credentials");
73         if (!store)
74                 die("unable to set up default store; use --store");
75
76         if (reject)
77                 remove_credential(store, &c);
78         else {
79                 if (!lookup_credential(store, &c)) {
80                         credential_fill(&c, &chain);
81                         store_credential(store, &c);
82                 }
83                 printf("username=%s\n", c.username);
84                 printf("password=%s\n", c.password);
85         }
86         return 0;
87 }