]>
git.proxmox.com Git - libgit2.git/blob - src/config.c
2 * Copyright (C) 2009-2011 the libgit2 contributors
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
10 #include "hashtable.h"
12 #include "git2/config.h"
21 git_config_file
*file
;
25 void git_config_free(git_config
*cfg
)
28 git_config_file
*file
;
29 file_internal
*internal
;
34 for(i
= 0; i
< cfg
->files
.length
; ++i
){
35 internal
= git_vector_get(&cfg
->files
, i
);
36 file
= internal
->file
;
41 git_vector_free(&cfg
->files
);
45 static int config_backend_cmp(const void *a
, const void *b
)
47 const file_internal
*bk_a
= (const file_internal
*)(a
);
48 const file_internal
*bk_b
= (const file_internal
*)(b
);
50 return bk_b
->priority
- bk_a
->priority
;
53 int git_config_new(git_config
**out
)
57 cfg
= git__malloc(sizeof(git_config
));
61 memset(cfg
, 0x0, sizeof(git_config
));
63 if (git_vector_init(&cfg
->files
, 3, config_backend_cmp
) < 0) {
73 int git_config_add_file_ondisk(git_config
*cfg
, const char *path
, int priority
)
75 git_config_file
*file
= NULL
;
78 error
= git_config_file__ondisk(&file
, path
);
79 if (error
< GIT_SUCCESS
)
82 error
= git_config_add_file(cfg
, file
, priority
);
83 if (error
< GIT_SUCCESS
) {
85 * free manually; the file is not owned by the config
86 * instance yet and will not be freed on cleanup
95 int git_config_open_ondisk(git_config
**cfg
, const char *path
)
99 error
= git_config_new(cfg
);
100 if (error
< GIT_SUCCESS
)
103 error
= git_config_add_file_ondisk(*cfg
, path
, 1);
104 if (error
< GIT_SUCCESS
)
105 git_config_free(*cfg
);
110 int git_config_add_file(git_config
*cfg
, git_config_file
*file
, int priority
)
112 file_internal
*internal
;
117 if ((error
= file
->open(file
)) < GIT_SUCCESS
)
118 return git__rethrow(error
, "Failed to open config file");
120 internal
= git__malloc(sizeof(file_internal
));
121 if (internal
== NULL
)
124 internal
->file
= file
;
125 internal
->priority
= priority
;
127 if (git_vector_insert(&cfg
->files
, internal
) < 0) {
132 git_vector_sort(&cfg
->files
);
133 internal
->file
->cfg
= cfg
;
139 * Loop over all the variables
142 int git_config_foreach(git_config
*cfg
, int (*fn
)(const char *, const char *, void *), void *data
)
144 int ret
= GIT_SUCCESS
;
146 file_internal
*internal
;
147 git_config_file
*file
;
149 for(i
= 0; i
< cfg
->files
.length
&& ret
== 0; ++i
) {
150 internal
= git_vector_get(&cfg
->files
, i
);
151 file
= internal
->file
;
152 ret
= file
->foreach(file
, fn
, data
);
158 int git_config_delete(git_config
*cfg
, const char *name
)
160 return git_config_set_string(cfg
, name
, NULL
);
167 int git_config_set_int64(git_config
*cfg
, const char *name
, int64_t value
)
169 char str_value
[32]; /* All numbers should fit in here */
170 p_snprintf(str_value
, sizeof(str_value
), "%" PRId64
, value
);
171 return git_config_set_string(cfg
, name
, str_value
);
174 int git_config_set_int32(git_config
*cfg
, const char *name
, int32_t value
)
176 return git_config_set_int64(cfg
, name
, (int64_t)value
);
179 int git_config_set_bool(git_config
*cfg
, const char *name
, int value
)
181 return git_config_set_string(cfg
, name
, value
? "true" : "false");
184 int git_config_set_string(git_config
*cfg
, const char *name
, const char *value
)
186 file_internal
*internal
;
187 git_config_file
*file
;
189 if (cfg
->files
.length
== 0)
190 return git__throw(GIT_EINVALIDARGS
, "Cannot set variable value; no files open in the `git_config` instance");
192 internal
= git_vector_get(&cfg
->files
, 0);
193 file
= internal
->file
;
195 return file
->set(file
, name
, value
);
202 int git_config_get_int64(git_config
*cfg
, const char *name
, int64_t *out
)
204 const char *value
, *num_end
;
208 ret
= git_config_get_string(cfg
, name
, &value
);
209 if (ret
< GIT_SUCCESS
)
210 return git__rethrow(ret
, "Failed to retrieve value for '%s'", name
);
212 ret
= git__strtol64(&num
, value
, &num_end
, 0);
213 if (ret
< GIT_SUCCESS
)
214 return git__rethrow(ret
, "Failed to convert value for '%s'", name
);
231 /* check that that there are no more characters after the
232 * given modifier suffix */
233 if (num_end
[1] != '\0')
234 return git__throw(GIT_EINVALIDTYPE
,
235 "Failed to get value for '%s'. Invalid type suffix", name
);
244 return git__throw(GIT_EINVALIDTYPE
,
245 "Failed to get value for '%s'. Value is of invalid type", name
);
249 int git_config_get_int32(git_config
*cfg
, const char *name
, int32_t *out
)
255 ret
= git_config_get_int64(cfg
, name
, &tmp_long
);
256 if (ret
< GIT_SUCCESS
)
257 return git__rethrow(ret
, "Failed to convert value for '%s'", name
);
259 tmp_int
= tmp_long
& 0xFFFFFFFF;
260 if (tmp_int
!= tmp_long
)
261 return git__throw(GIT_EOVERFLOW
, "Value for '%s' is too large", name
);
268 int git_config_get_bool(git_config
*cfg
, const char *name
, int *out
)
271 int error
= GIT_SUCCESS
;
273 error
= git_config_get_string(cfg
, name
, &value
);
274 if (error
< GIT_SUCCESS
)
275 return git__rethrow(error
, "Failed to get value for %s", name
);
277 /* A missing value means true */
283 if (!strcasecmp(value
, "true") ||
284 !strcasecmp(value
, "yes") ||
285 !strcasecmp(value
, "on")) {
289 if (!strcasecmp(value
, "false") ||
290 !strcasecmp(value
, "no") ||
291 !strcasecmp(value
, "off")) {
296 /* Try to parse it as an integer */
297 error
= git_config_get_int32(cfg
, name
, out
);
298 if (error
== GIT_SUCCESS
)
301 if (error
< GIT_SUCCESS
)
302 return git__rethrow(error
, "Failed to get value for %s", name
);
306 int git_config_get_string(git_config
*cfg
, const char *name
, const char **out
)
308 file_internal
*internal
;
309 git_config_file
*file
;
310 int error
= GIT_ENOTFOUND
;
313 if (cfg
->files
.length
== 0)
314 return git__throw(GIT_EINVALIDARGS
, "Cannot get variable value; no files open in the `git_config` instance");
316 for (i
= 0; i
< cfg
->files
.length
; ++i
) {
317 internal
= git_vector_get(&cfg
->files
, i
);
318 file
= internal
->file
;
319 if ((error
= file
->get(file
, name
, out
)) == GIT_SUCCESS
)
323 return git__throw(error
, "Config value '%s' not found", name
);
326 int git_config_find_global(char *global_config_path
)
330 home
= getenv("HOME");
334 home
= getenv("USERPROFILE");
338 return git__throw(GIT_EOSERR
, "Failed to open global config file. Cannot locate the user's home directory");
340 git_path_join(global_config_path
, home
, GIT_CONFIG_FILENAME
);
342 if (git_futils_exists(global_config_path
) < GIT_SUCCESS
)
343 return git__throw(GIT_EOSERR
, "Failed to open global config file. The file does not exist");
351 static int win32_find_system(char *system_config_path
)
353 const wchar_t *query
= L
"%PROGRAMFILES%\\Git\\etc\\gitconfig";
354 wchar_t *apphome_utf16
;
358 size
= ExpandEnvironmentStringsW(query
, NULL
, 0);
359 /* The function gave us the full size of the buffer in chars, including NUL */
360 apphome_utf16
= git__malloc(size
* sizeof(wchar_t));
361 if (apphome_utf16
== NULL
)
364 ret
= ExpandEnvironmentStringsW(query
, apphome_utf16
, size
);
366 return git__throw(GIT_ERROR
, "Failed to expand environment strings");
368 if (_waccess(apphome_utf16
, F_OK
) < 0) {
370 return GIT_ENOTFOUND
;
373 apphome_utf8
= conv_utf16_to_utf8(apphome_utf16
);
376 if (strlen(apphome_utf8
) >= GIT_PATH_MAX
) {
378 return git__throw(GIT_ESHORTBUFFER
, "Path is too long");
381 strcpy(system_config_path
, apphome_utf8
);
387 int git_config_find_system(char *system_config_path
)
389 const char *etc
= "/etc/gitconfig";
391 if (git_futils_exists(etc
) == GIT_SUCCESS
) {
392 memcpy(system_config_path
, etc
, strlen(etc
) + 1);
397 return win32_find_system(system_config_path
);
399 return GIT_ENOTFOUND
;
403 int git_config_open_global(git_config
**out
)
406 char global_path
[GIT_PATH_MAX
];
408 if ((error
= git_config_find_global(global_path
)) < GIT_SUCCESS
)
411 return git_config_open_ondisk(out
, global_path
);