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_object.h"
39 #include "got_lib_object_cache.h"
40 #include "got_lib_privsep.h"
41 #include "got_lib_pack.h"
42 #include "got_lib_repository.h"
45 get_boolean_val(char *val
)
47 return (strcasecmp(val
, "true") == 0 ||
48 strcasecmp(val
, "on") == 0 ||
49 strcasecmp(val
, "yes") == 0 ||
50 strcmp(val
, "1") == 0);
53 const struct got_error
*
54 got_repo_read_gitconfig(int *gitconfig_repository_format_version
,
55 char **gitconfig_author_name
, char **gitconfig_author_email
,
56 struct got_remote_repo
**remotes
, int *nremotes
,
57 char **gitconfig_owner
, char ***extnames
, char ***extvals
,
58 int *nextensions
, const char *gitconfig_path
)
60 const struct got_error
*err
= NULL
;
61 struct got_gitconfig
*gitconfig
= NULL
;
62 struct got_gitconfig_list
*tags
;
63 struct got_gitconfig_list_node
*node
;
65 const char *author
, *email
, *owner
;
67 *gitconfig_repository_format_version
= 0;
74 *gitconfig_author_name
= NULL
;
75 *gitconfig_author_email
= NULL
;
81 *gitconfig_owner
= NULL
;
83 fd
= open(gitconfig_path
, O_RDONLY
| O_CLOEXEC
);
87 return got_error_from_errno2("open", gitconfig_path
);
90 err
= got_gitconfig_open(&gitconfig
, fd
);
94 *gitconfig_repository_format_version
= got_gitconfig_get_num(gitconfig
,
95 "core", "repositoryformatversion", 0);
97 tags
= got_gitconfig_get_tag_list(gitconfig
, "extensions");
98 if (extnames
&& extvals
&& nextensions
&& tags
) {
100 TAILQ_FOREACH(node
, &tags
->fields
, link
) {
101 char *ext
= node
->field
;
102 char *val
= got_gitconfig_get_str(gitconfig
,
104 if (get_boolean_val(val
))
107 *extnames
= calloc(numext
, sizeof(char *));
108 if (*extnames
== NULL
) {
109 err
= got_error_from_errno("calloc");
112 *extvals
= calloc(numext
, sizeof(char *));
113 if (*extvals
== NULL
) {
114 err
= got_error_from_errno("calloc");
117 TAILQ_FOREACH(node
, &tags
->fields
, link
) {
118 char *ext
= node
->field
;
119 char *val
= got_gitconfig_get_str(gitconfig
,
121 if (get_boolean_val(val
)) {
122 char *extstr
= NULL
, *valstr
= NULL
;
124 extstr
= strdup(ext
);
125 if (extstr
== NULL
) {
126 err
= got_error_from_errno("strdup");
129 valstr
= strdup(val
);
130 if (valstr
== NULL
) {
131 err
= got_error_from_errno("strdup");
134 (*extnames
)[(*nextensions
)] = extstr
;
135 (*extvals
)[(*nextensions
)] = valstr
;
141 author
= got_gitconfig_get_str(gitconfig
, "user", "name");
143 *gitconfig_author_name
= strdup(author
);
144 if (*gitconfig_author_name
== NULL
) {
145 err
= got_error_from_errno("strdup");
150 email
= got_gitconfig_get_str(gitconfig
, "user", "email");
152 *gitconfig_author_email
= strdup(email
);
153 if (*gitconfig_author_email
== NULL
) {
154 err
= got_error_from_errno("strdup");
159 if (gitconfig_owner
) {
160 owner
= got_gitconfig_get_str(gitconfig
, "gotweb", "owner");
162 owner
= got_gitconfig_get_str(gitconfig
, "gitweb",
165 *gitconfig_owner
= strdup(owner
);
166 if (*gitconfig_owner
== NULL
) {
167 err
= got_error_from_errno("strdup");
174 if (remotes
&& nremotes
) {
175 struct got_gitconfig_list
*sections
;
177 err
= got_gitconfig_get_section_list(§ions
, gitconfig
);
180 TAILQ_FOREACH(node
, §ions
->fields
, link
) {
181 if (strncasecmp("remote \"", node
->field
, 8) != 0)
186 *remotes
= recallocarray(NULL
, 0, nalloc
, sizeof(**remotes
));
187 if (*remotes
== NULL
) {
188 err
= got_error_from_errno("recallocarray");
193 TAILQ_FOREACH(node
, §ions
->fields
, link
) {
194 struct got_remote_repo
*remote
;
195 char *name
, *end
, *mirror
;
196 const char *fetch_url
, *send_url
;
198 if (strncasecmp("remote \"", node
->field
, 8) != 0)
201 remote
= &(*remotes
)[i
];
203 name
= strdup(node
->field
+ 8);
205 err
= got_error_from_errno("strdup");
208 end
= strrchr(name
, '"');
213 fetch_url
= got_gitconfig_get_str(gitconfig
,
215 if (fetch_url
== NULL
) {
216 err
= got_error(GOT_ERR_GITCONFIG_SYNTAX
);
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 if (send_url
== NULL
) {
235 err
= got_error(GOT_ERR_GITCONFIG_SYNTAX
);
238 free(remote
->fetch_url
);
239 remote
->fetch_url
= NULL
;
242 remote
->send_url
= strdup(send_url
);
243 if (remote
->send_url
== NULL
) {
244 err
= got_error_from_errno("strdup");
247 free(remote
->fetch_url
);
248 remote
->fetch_url
= NULL
;
252 remote
->mirror_references
= 0;
253 mirror
= got_gitconfig_get_str(gitconfig
, node
->field
,
255 if (mirror
!= NULL
&& get_boolean_val(mirror
))
256 remote
->mirror_references
= 1;
266 got_gitconfig_close(gitconfig
);
268 if (extnames
&& extvals
&& nextensions
) {
269 for (i
= 0; i
< (*nextensions
); i
++) {
270 free((*extnames
)[i
]);
279 if (remotes
&& nremotes
) {
280 for (i
= 0; i
< (*nremotes
); i
++) {
281 struct got_remote_repo
*remote
;
282 remote
= &(*remotes
)[i
];
284 free(remote
->fetch_url
);
285 free(remote
->send_url
);