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 <sys/queue.h>
29 #include "got_error.h"
30 #include "got_object.h"
31 #include "got_repository.h"
34 #include "got_lib_gitconfig.h"
35 #include "got_lib_delta.h"
36 #include "got_lib_object.h"
37 #include "got_lib_object_cache.h"
38 #include "got_lib_privsep.h"
39 #include "got_lib_pack.h"
40 #include "got_lib_repository.h"
43 get_boolean_val(char *val
)
45 return (strcasecmp(val
, "true") == 0 ||
46 strcasecmp(val
, "on") == 0 ||
47 strcasecmp(val
, "yes") == 0 ||
48 strcmp(val
, "1") == 0);
51 const struct got_error
*
52 got_repo_read_gitconfig(int *gitconfig_repository_format_version
,
53 char **gitconfig_author_name
, char **gitconfig_author_email
,
54 struct got_remote_repo
**remotes
, int *nremotes
,
55 char **gitconfig_owner
, char ***extnames
, char ***extvals
,
56 int *nextensions
, const char *gitconfig_path
)
58 const struct got_error
*err
= NULL
;
59 struct got_gitconfig
*gitconfig
= NULL
;
60 struct got_gitconfig_list
*tags
;
61 struct got_gitconfig_list_node
*node
;
63 const char *author
, *email
, *owner
;
65 *gitconfig_repository_format_version
= 0;
72 *gitconfig_author_name
= NULL
;
73 *gitconfig_author_email
= NULL
;
79 *gitconfig_owner
= NULL
;
81 fd
= open(gitconfig_path
, O_RDONLY
| O_CLOEXEC
);
85 return got_error_from_errno2("open", gitconfig_path
);
88 err
= got_gitconfig_open(&gitconfig
, fd
);
92 *gitconfig_repository_format_version
= got_gitconfig_get_num(gitconfig
,
93 "core", "repositoryformatversion", 0);
95 tags
= got_gitconfig_get_tag_list(gitconfig
, "extensions");
96 if (extnames
&& extvals
&& nextensions
&& tags
) {
98 TAILQ_FOREACH(node
, &tags
->fields
, link
) {
99 char *ext
= node
->field
;
100 char *val
= got_gitconfig_get_str(gitconfig
,
102 if (get_boolean_val(val
))
105 *extnames
= calloc(numext
, sizeof(char *));
106 if (*extnames
== NULL
) {
107 err
= got_error_from_errno("calloc");
110 *extvals
= calloc(numext
, sizeof(char *));
111 if (*extvals
== NULL
) {
112 err
= got_error_from_errno("calloc");
115 TAILQ_FOREACH(node
, &tags
->fields
, link
) {
116 char *ext
= node
->field
;
117 char *val
= got_gitconfig_get_str(gitconfig
,
119 if (get_boolean_val(val
)) {
120 char *extstr
= NULL
, *valstr
= NULL
;
122 extstr
= strdup(ext
);
123 if (extstr
== NULL
) {
124 err
= got_error_from_errno("strdup");
127 valstr
= strdup(val
);
128 if (valstr
== NULL
) {
129 err
= got_error_from_errno("strdup");
132 (*extnames
)[(*nextensions
)] = extstr
;
133 (*extvals
)[(*nextensions
)] = valstr
;
139 author
= got_gitconfig_get_str(gitconfig
, "user", "name");
141 *gitconfig_author_name
= strdup(author
);
142 if (*gitconfig_author_name
== NULL
) {
143 err
= got_error_from_errno("strdup");
148 email
= got_gitconfig_get_str(gitconfig
, "user", "email");
150 *gitconfig_author_email
= strdup(email
);
151 if (*gitconfig_author_email
== NULL
) {
152 err
= got_error_from_errno("strdup");
157 if (gitconfig_owner
) {
158 owner
= got_gitconfig_get_str(gitconfig
, "gotweb", "owner");
160 owner
= got_gitconfig_get_str(gitconfig
, "gitweb",
163 *gitconfig_owner
= strdup(owner
);
164 if (*gitconfig_owner
== NULL
) {
165 err
= got_error_from_errno("strdup");
172 if (remotes
&& nremotes
) {
173 struct got_gitconfig_list
*sections
;
175 err
= got_gitconfig_get_section_list(§ions
, gitconfig
);
178 TAILQ_FOREACH(node
, §ions
->fields
, link
) {
179 if (strncasecmp("remote \"", node
->field
, 8) != 0)
184 *remotes
= recallocarray(NULL
, 0, nalloc
, sizeof(**remotes
));
185 if (*remotes
== NULL
) {
186 err
= got_error_from_errno("recallocarray");
191 TAILQ_FOREACH(node
, §ions
->fields
, link
) {
192 struct got_remote_repo
*remote
;
193 char *name
, *end
, *mirror
;
194 const char *fetch_url
, *send_url
;
196 if (strncasecmp("remote \"", node
->field
, 8) != 0)
199 remote
= &(*remotes
)[i
];
201 name
= strdup(node
->field
+ 8);
203 err
= got_error_from_errno("strdup");
206 end
= strrchr(name
, '"');
211 fetch_url
= got_gitconfig_get_str(gitconfig
,
213 if (fetch_url
== NULL
) {
214 err
= got_error(GOT_ERR_GITCONFIG_SYNTAX
);
219 remote
->fetch_url
= strdup(fetch_url
);
220 if (remote
->fetch_url
== NULL
) {
221 err
= got_error_from_errno("strdup");
227 send_url
= got_gitconfig_get_str(gitconfig
,
228 node
->field
, "pushurl");
229 if (send_url
== NULL
)
230 send_url
= got_gitconfig_get_str(gitconfig
,
232 if (send_url
== NULL
) {
233 err
= got_error(GOT_ERR_GITCONFIG_SYNTAX
);
236 free(remote
->fetch_url
);
237 remote
->fetch_url
= NULL
;
240 remote
->send_url
= strdup(send_url
);
241 if (remote
->send_url
== NULL
) {
242 err
= got_error_from_errno("strdup");
245 free(remote
->fetch_url
);
246 remote
->fetch_url
= NULL
;
250 remote
->mirror_references
= 0;
251 mirror
= got_gitconfig_get_str(gitconfig
, node
->field
,
253 if (mirror
!= NULL
&& get_boolean_val(mirror
))
254 remote
->mirror_references
= 1;
264 got_gitconfig_close(gitconfig
);
266 if (extnames
&& extvals
&& nextensions
) {
267 for (i
= 0; i
< (*nextensions
); i
++) {
268 free((*extnames
)[i
]);
277 if (remotes
&& nremotes
) {
278 for (i
= 0; i
< (*nremotes
); i
++) {
279 struct got_remote_repo
*remote
;
280 remote
= &(*remotes
)[i
];
282 free(remote
->fetch_url
);
283 free(remote
->send_url
);