6
7
static struct lock_file credential_lock;
8
9
-static void parse_credential_file(const char *fn,
9
+static int parse_credential_file(const char *fn,
10
struct credential *c,
11
void (*match_cb)(struct credential *),
12
void (*other_cb)(struct strbuf *))
14
FILE *fh;
15
struct strbuf line = STRBUF_INIT;
16
struct credential entry = CREDENTIAL_INIT;
17
+ int found_credential = 0;
18
19
fh = fopen(fn, "r");
20
if (!fh) {
20
- if (errno != ENOENT)
21
+ if (errno != ENOENT && errno != EACCES)
22
die_errno("unable to open %s", fn);
22
- return;
23
+ return found_credential;
24
}
25
26
while (strbuf_getline(&line, fh, '\n') != EOF) {
27
credential_from_url(&entry, line.buf);
28
if (entry.username && entry.password &&
29
credential_match(c, &entry)) {
30
+ found_credential = 1;
31
if (match_cb) {
32
match_cb(&entry);
33
break;
40
credential_clear(&entry);
41
strbuf_release(&line);
42
fclose(fh);
43
+ return found_credential;
44
}
45
46
static void print_entry(struct credential *c)
67
die_errno("unable to commit credential store");
68
}
69
67
-static void store_credential(const char *fn, struct credential *c)
70
+static void store_credential_file(const char *fn, struct credential *c)
71
{
72
struct strbuf buf = STRBUF_INIT;
73
71
- /*
72
- * Sanity check that what we are storing is actually sensible.
73
- * In particular, we can't make a URL without a protocol field.
74
- * Without either a host or pathname (depending on the scheme),
75
- * we have no primary key. And without a username and password,
76
- * we are not actually storing a credential.
77
- */
78
- if (!c->protocol || !(c->host || c->path) ||
79
- !c->username || !c->password)
80
- return;
81
-
74
strbuf_addf(&buf, "%s://", c->protocol);
75
strbuf_addstr_urlencode(&buf, c->username, 1);
76
strbuf_addch(&buf, ':');
87
strbuf_release(&buf);
88
}
89
98
-static void remove_credential(const char *fn, struct credential *c)
90
+static void store_credential(const struct string_list *fns, struct credential *c)
91
{
92
+ struct string_list_item *fn;
93
+
94
+ /*
95
+ * Sanity check that what we are storing is actually sensible.
96
+ * In particular, we can't make a URL without a protocol field.
97
+ * Without either a host or pathname (depending on the scheme),
98
+ * we have no primary key. And without a username and password,
99
+ * we are not actually storing a credential.
100
+ */
101
+ if (!c->protocol || !(c->host || c->path) || !c->username || !c->password)
102
+ return;
103
+
104
+ for_each_string_list_item(fn, fns)
105
+ if (!access(fn->string, F_OK)) {
106
+ store_credential_file(fn->string, c);
107
+ return;
108
+ }
109
+ /*
110
+ * Write credential to the filename specified by fns->items[0], thus
111
+ * creating it
112
+ */
113
+ if (fns->nr)
114
+ store_credential_file(fns->items[0].string, c);
115
+}
116
+
117
+static void remove_credential(const struct string_list *fns, struct credential *c)
118
+{
119
+ struct string_list_item *fn;
120
+
121
/*
122
* Sanity check that we actually have something to match
123
* against. The input we get is a restrictive pattern,
126
* to empty input. So explicitly disallow it, and require that the
127
* pattern have some actual content to match.
128
*/
108
- if (c->protocol || c->host || c->path || c->username)
109
- rewrite_credential_file(fn, c, NULL);
129
+ if (!c->protocol && !c->host && !c->path && !c->username)
130
+ return;
131
+ for_each_string_list_item(fn, fns)
132
+ if (!access(fn->string, F_OK))
133
+ rewrite_credential_file(fn->string, c, NULL);
134
}
135
112
-static int lookup_credential(const char *fn, struct credential *c)
136
+static void lookup_credential(const struct string_list *fns, struct credential *c)
137
{
114
- parse_credential_file(fn, c, print_entry, NULL);
115
- return c->username && c->password;
138
+ struct string_list_item *fn;
139
+
140
+ for_each_string_list_item(fn, fns)
141
+ if (parse_credential_file(fn->string, c, print_entry, NULL))
142
+ return; /* Found credential */
143
}
144
145
int main(int argc, char **argv)
150
};
151
const char *op;
152
struct credential c = CREDENTIAL_INIT;
153
+ struct string_list fns = STRING_LIST_INIT_DUP;
154
char *file = NULL;
155
struct option options[] = {
156
OPT_STRING(0, "file", &file, "path",
167
168
if (!file)
169
file = expand_user_path("~/.git-credentials");
142
- if (!file)
170
+ if (file)
171
+ string_list_append(&fns, file);
172
+ else
173
die("unable to set up default path; use --file");
174
175
if (credential_read(&c, stdin) < 0)
176
die("unable to read credential");
177
178
if (!strcmp(op, "get"))
149
- lookup_credential(file, &c);
179
+ lookup_credential(&fns, &c);
180
else if (!strcmp(op, "erase"))
151
- remove_credential(file, &c);
181
+ remove_credential(&fns, &c);
182
else if (!strcmp(op, "store"))
153
- store_credential(file, &c);
183
+ store_credential(&fns, &c);
184
else
185
; /* Ignore unknown operation. */
186
187
+ string_list_clear(&fns, 0);
188
return 0;
189
}