6
6
7
7
static struct lock_file credential_lock ;
8
8
9
- static void parse_credential_file (const char * fn ,
9
+ static int parse_credential_file (const char * fn ,
10
10
struct credential * c ,
11
11
void (* match_cb )(struct credential * ),
12
12
void (* other_cb )(struct strbuf * ))
13
13
{
14
14
FILE * fh ;
15
15
struct strbuf line = STRBUF_INIT ;
16
16
struct credential entry = CREDENTIAL_INIT ;
17
+ int found_credential = 0 ;
17
18
18
19
fh = fopen (fn , "r" );
19
20
if (!fh ) {
20
- if (errno != ENOENT )
21
+ if (errno != ENOENT && errno != EACCES )
21
22
die_errno ("unable to open %s" , fn );
22
- return ;
23
+ return found_credential ;
23
24
}
24
25
25
26
while (strbuf_getline (& line , fh , '\n' ) != EOF ) {
26
27
credential_from_url (& entry , line .buf );
27
28
if (entry .username && entry .password &&
28
29
credential_match (c , & entry )) {
30
+ found_credential = 1 ;
29
31
if (match_cb ) {
30
32
match_cb (& entry );
31
33
break ;
@@ -38,6 +40,7 @@ static void parse_credential_file(const char *fn,
38
40
credential_clear (& entry );
39
41
strbuf_release (& line );
40
42
fclose (fh );
43
+ return found_credential ;
41
44
}
42
45
43
46
static void print_entry (struct credential * c )
@@ -64,21 +67,10 @@ static void rewrite_credential_file(const char *fn, struct credential *c,
64
67
die_errno ("unable to commit credential store" );
65
68
}
66
69
67
- static void store_credential (const char * fn , struct credential * c )
70
+ static void store_credential_file (const char * fn , struct credential * c )
68
71
{
69
72
struct strbuf buf = STRBUF_INIT ;
70
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
-
82
74
strbuf_addf (& buf , "%s://" , c -> protocol );
83
75
strbuf_addstr_urlencode (& buf , c -> username , 1 );
84
76
strbuf_addch (& buf , ':' );
@@ -95,8 +87,37 @@ static void store_credential(const char *fn, struct credential *c)
95
87
strbuf_release (& buf );
96
88
}
97
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 )
99
118
{
119
+ struct string_list_item * fn ;
120
+
100
121
/*
101
122
* Sanity check that we actually have something to match
102
123
* against. The input we get is a restrictive pattern,
@@ -105,14 +126,20 @@ static void remove_credential(const char *fn, struct credential *c)
105
126
* to empty input. So explicitly disallow it, and require that the
106
127
* pattern have some actual content to match.
107
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 );
110
134
}
111
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 )
113
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 */
116
143
}
117
144
118
145
int main (int argc , char * * argv )
@@ -123,6 +150,7 @@ int main(int argc, char **argv)
123
150
};
124
151
const char * op ;
125
152
struct credential c = CREDENTIAL_INIT ;
153
+ struct string_list fns = STRING_LIST_INIT_DUP ;
126
154
char * file = NULL ;
127
155
struct option options [] = {
128
156
OPT_STRING (0 , "file" , & file , "path" ,
@@ -137,22 +165,30 @@ int main(int argc, char **argv)
137
165
usage_with_options (usage , options );
138
166
op = argv [0 ];
139
167
140
- if (!file )
141
- file = expand_user_path ("~/.git-credentials" );
142
- if (!file )
168
+ if (file ) {
169
+ string_list_append (& fns , file );
170
+ } else {
171
+ if ((file = expand_user_path ("~/.git-credentials" )))
172
+ string_list_append_nodup (& fns , file );
173
+ home_config_paths (NULL , & file , "credentials" );
174
+ if (file )
175
+ string_list_append_nodup (& fns , file );
176
+ }
177
+ if (!fns .nr )
143
178
die ("unable to set up default path; use --file" );
144
179
145
180
if (credential_read (& c , stdin ) < 0 )
146
181
die ("unable to read credential" );
147
182
148
183
if (!strcmp (op , "get" ))
149
- lookup_credential (file , & c );
184
+ lookup_credential (& fns , & c );
150
185
else if (!strcmp (op , "erase" ))
151
- remove_credential (file , & c );
186
+ remove_credential (& fns , & c );
152
187
else if (!strcmp (op , "store" ))
153
- store_credential (file , & c );
188
+ store_credential (& fns , & c );
154
189
else
155
190
; /* Ignore unknown operation. */
156
191
192
+ string_list_clear (& fns , 0 );
157
193
return 0 ;
158
194
}
0 commit comments