2 * Copyright (c) 2022 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "got_compat.h"
19 #include <sys/queue.h>
31 #include "got_error.h"
32 #include "got_object.h"
33 #include "got_repository.h"
36 #include "got_lib_gitconfig.h"
37 #include "got_lib_delta.h"
38 #include "got_lib_hash.h"
39 #include "got_lib_object.h"
40 #include "got_lib_object_cache.h"
41 #include "got_lib_privsep.h"
42 #include "got_lib_pack.h"
43 #include "got_lib_repository.h"
46 get_boolean_val(char *val
)
48 return (strcasecmp(val
, "true") == 0 ||
49 strcasecmp(val
, "on") == 0 ||
50 strcasecmp(val
, "yes") == 0 ||
51 strcmp(val
, "1") == 0);
55 skip_node(struct got_gitconfig
*gitconfig
,
56 struct got_gitconfig_list_node
*node
)
59 * Skip config nodes which do not describe remotes, and remotes
60 * which do not have a fetch URL defined (as used by git-annex).
62 return (strncasecmp("remote \"", node
->field
, 8) != 0 ||
63 got_gitconfig_get_str(gitconfig
, node
->field
, "url") == NULL
);
66 const struct got_error
*
67 got_repo_read_gitconfig(int *gitconfig_repository_format_version
,
68 char **gitconfig_author_name
, char **gitconfig_author_email
,
69 struct got_remote_repo
**remotes
, int *nremotes
,
70 char **gitconfig_owner
, char ***extnames
, char ***extvals
,
71 int *nextensions
, const char *gitconfig_path
)
73 const struct got_error
*err
= NULL
;
74 struct got_gitconfig
*gitconfig
= NULL
;
75 struct got_gitconfig_list
*tags
;
76 struct got_gitconfig_list_node
*node
;
78 const char *author
, *email
, *owner
;
80 *gitconfig_repository_format_version
= 0;
87 *gitconfig_author_name
= NULL
;
88 *gitconfig_author_email
= NULL
;
94 *gitconfig_owner
= NULL
;
96 fd
= open(gitconfig_path
, O_RDONLY
| O_CLOEXEC
);
100 return got_error_from_errno2("open", gitconfig_path
);
103 err
= got_gitconfig_open(&gitconfig
, fd
);
107 *gitconfig_repository_format_version
= got_gitconfig_get_num(gitconfig
,
108 "core", "repositoryformatversion", 0);
110 tags
= got_gitconfig_get_tag_list(gitconfig
, "extensions");
111 if (extnames
&& extvals
&& nextensions
&& tags
) {
113 TAILQ_FOREACH(node
, &tags
->fields
, link
)
115 *extnames
= calloc(numext
, sizeof(char *));
116 if (*extnames
== NULL
) {
117 err
= got_error_from_errno("calloc");
120 *extvals
= calloc(numext
, sizeof(char *));
121 if (*extvals
== NULL
) {
122 err
= got_error_from_errno("calloc");
125 TAILQ_FOREACH(node
, &tags
->fields
, link
) {
126 char *ext
= node
->field
;
127 char *val
= got_gitconfig_get_str(gitconfig
,
129 char *extstr
= NULL
, *valstr
= NULL
;
131 extstr
= strdup(ext
);
132 if (extstr
== NULL
) {
133 err
= got_error_from_errno("strdup");
136 valstr
= strdup(val
);
137 if (valstr
== NULL
) {
138 err
= got_error_from_errno("strdup");
141 (*extnames
)[(*nextensions
)] = extstr
;
142 (*extvals
)[(*nextensions
)] = valstr
;
147 author
= got_gitconfig_get_str(gitconfig
, "user", "name");
149 *gitconfig_author_name
= strdup(author
);
150 if (*gitconfig_author_name
== NULL
) {
151 err
= got_error_from_errno("strdup");
156 email
= got_gitconfig_get_str(gitconfig
, "user", "email");
158 *gitconfig_author_email
= strdup(email
);
159 if (*gitconfig_author_email
== NULL
) {
160 err
= got_error_from_errno("strdup");
165 if (gitconfig_owner
) {
166 owner
= got_gitconfig_get_str(gitconfig
, "gotweb", "owner");
168 owner
= got_gitconfig_get_str(gitconfig
, "gitweb",
171 *gitconfig_owner
= strdup(owner
);
172 if (*gitconfig_owner
== NULL
) {
173 err
= got_error_from_errno("strdup");
180 if (remotes
&& nremotes
) {
181 struct got_gitconfig_list
*sections
;
183 err
= got_gitconfig_get_section_list(§ions
, gitconfig
);
186 TAILQ_FOREACH(node
, §ions
->fields
, link
) {
187 if (skip_node(gitconfig
, node
))
192 *remotes
= recallocarray(NULL
, 0, nalloc
, sizeof(**remotes
));
193 if (*remotes
== NULL
) {
194 err
= got_error_from_errno("recallocarray");
199 TAILQ_FOREACH(node
, §ions
->fields
, link
) {
200 struct got_remote_repo
*remote
;
201 char *name
, *end
, *mirror
;
202 const char *fetch_url
, *send_url
;
204 if (skip_node(gitconfig
, node
) != 0)
207 remote
= &(*remotes
)[i
];
209 name
= strdup(node
->field
+ 8);
211 err
= got_error_from_errno("strdup");
214 end
= strrchr(name
, '"');
219 fetch_url
= got_gitconfig_get_str(gitconfig
,
221 remote
->fetch_url
= strdup(fetch_url
);
222 if (remote
->fetch_url
== NULL
) {
223 err
= got_error_from_errno("strdup");
229 send_url
= got_gitconfig_get_str(gitconfig
,
230 node
->field
, "pushurl");
231 if (send_url
== NULL
)
232 send_url
= got_gitconfig_get_str(gitconfig
,
234 remote
->send_url
= strdup(send_url
);
235 if (remote
->send_url
== NULL
) {
236 err
= got_error_from_errno("strdup");
239 free(remote
->fetch_url
);
240 remote
->fetch_url
= NULL
;
244 remote
->mirror_references
= 0;
245 mirror
= got_gitconfig_get_str(gitconfig
, node
->field
,
247 if (mirror
!= NULL
&& get_boolean_val(mirror
))
248 remote
->mirror_references
= 1;
258 got_gitconfig_close(gitconfig
);
260 if (extnames
&& extvals
&& nextensions
) {
261 for (i
= 0; i
< (*nextensions
); i
++) {
262 free((*extnames
)[i
]);
271 if (remotes
&& nremotes
) {
272 for (i
= 0; i
< (*nremotes
); i
++) {
273 struct got_remote_repo
*remote
;
274 remote
= &(*remotes
)[i
];
276 free(remote
->fetch_url
);
277 free(remote
->send_url
);