mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-11 07:53:55 +00:00
Merge pull request #110 from carlosmn/config
Implement config parsing. Finally!
This commit is contained in:
commit
587926efa4
@ -52,5 +52,6 @@
|
|||||||
#include "git2/tree.h"
|
#include "git2/tree.h"
|
||||||
|
|
||||||
#include "git2/index.h"
|
#include "git2/index.h"
|
||||||
|
#include "git2/config.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
171
include/git2/config.h
Normal file
171
include/git2/config.h
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* In addition to the permissions in the GNU General Public License,
|
||||||
|
* the authors give you unlimited permission to link the compiled
|
||||||
|
* version of this file into combinations with other programs,
|
||||||
|
* and to distribute those combinations without any restriction
|
||||||
|
* coming from the use of this file. (The General Public License
|
||||||
|
* restrictions do apply in other respects; for example, they cover
|
||||||
|
* modification of the file, and distribution when not linked into
|
||||||
|
* a combined executable.)
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDE_git_config_h__
|
||||||
|
#define INCLUDE_git_config_h__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file git2/config.h
|
||||||
|
* @brief Git config management routines
|
||||||
|
* @defgroup git_config Git config management routines
|
||||||
|
* @ingroup Git
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
GIT_BEGIN_DECL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new configuration
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_new(git_config **out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a configuration file
|
||||||
|
*
|
||||||
|
* @param cfg_out pointer to the configuration data
|
||||||
|
* @param path where to load the confiration from
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_open_bare(git_config **cfg_out, const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_add_backend(git_config *cfg, git_config_backend *backend, int priority);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the configuration and its associated memory
|
||||||
|
*
|
||||||
|
* @param cfg the configuration to free
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(void) git_config_free(git_config *cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of an integer config variable.
|
||||||
|
*
|
||||||
|
* @param cfg where to look for the variable
|
||||||
|
* @param name the variable's name
|
||||||
|
* @param out pointer to the variable where the value should be stored
|
||||||
|
* @return GIT_SUCCESS on success; error code otherwise
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_get_int(git_config *cfg, const char *name, int *out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a long integer config variable.
|
||||||
|
*
|
||||||
|
* @param cfg where to look for the variable
|
||||||
|
* @param name the variable's name
|
||||||
|
* @param out pointer to the variable where the value should be stored
|
||||||
|
* @return GIT_SUCCESS on success; error code otherwise
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_get_long(git_config *cfg, const char *name, long int *out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a boolean config variable.
|
||||||
|
*
|
||||||
|
* This function uses the usual C convention of 0 being false and
|
||||||
|
* anything else true.
|
||||||
|
*
|
||||||
|
* @param cfg where to look for the variable
|
||||||
|
* @param name the variable's name
|
||||||
|
* @param out pointer to the variable where the value should be stored
|
||||||
|
* @return GIT_SUCCESS on success; error code otherwise
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_get_bool(git_config *cfg, const char *name, int *out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a string config variable.
|
||||||
|
*
|
||||||
|
* The string is owned by the variable and should not be freed by the
|
||||||
|
* user.
|
||||||
|
*
|
||||||
|
* @param cfg where to look for the variable
|
||||||
|
* @param name the variable's name
|
||||||
|
* @param out pointer to the variable's value
|
||||||
|
* @return GIT_SUCCESS on success; error code otherwise
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_get_string(git_config *cfg, const char *name, const char **out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of an integer config variable.
|
||||||
|
*
|
||||||
|
* @param cfg where to look for the variable
|
||||||
|
* @param name the variable's name
|
||||||
|
* @param out pointer to the variable where the value should be stored
|
||||||
|
* @return GIT_SUCCESS on success; error code otherwise
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_set_int(git_config *cfg, const char *name, int value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of a long integer config variable.
|
||||||
|
*
|
||||||
|
* @param cfg where to look for the variable
|
||||||
|
* @param name the variable's name
|
||||||
|
* @param out pointer to the variable where the value should be stored
|
||||||
|
* @return GIT_SUCCESS on success; error code otherwise
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_set_long(git_config *cfg, const char *name, long int value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of a boolean config variable.
|
||||||
|
*
|
||||||
|
* @param cfg where to look for the variable
|
||||||
|
* @param name the variable's name
|
||||||
|
* @param value the value to store
|
||||||
|
* @return GIT_SUCCESS on success; error code otherwise
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_set_bool(git_config *cfg, const char *name, int value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of a string config variable.
|
||||||
|
*
|
||||||
|
* A copy of the string is made and the user is free to use it
|
||||||
|
* afterwards.
|
||||||
|
*
|
||||||
|
* @param cfg where to look for the variable
|
||||||
|
* @param name the variable's name
|
||||||
|
* @param value the string to store.
|
||||||
|
* @return GIT_SUCCESS on success; error code otherwise
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_set_string(git_config *cfg, const char *name, const char *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an operation on each config variable.
|
||||||
|
*
|
||||||
|
* The callback is passed a pointer to a config variable name and the
|
||||||
|
* data pointer passed to this function. As soon as one of the
|
||||||
|
* callback functions returns something other than 0, this function
|
||||||
|
* returns that value.
|
||||||
|
*
|
||||||
|
* @param cfg where to get the variables from
|
||||||
|
* @param callback the function to call on each variable
|
||||||
|
* @param data the data to pass to the callback
|
||||||
|
* @return GIT_SUCCESS or the return value of the callback which didn't return 0
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_foreach(git_config *cfg, int (*callback)(const char *, void *data), void *data);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
GIT_END_DECL
|
||||||
|
#endif
|
57
include/git2/config_backend.h
Normal file
57
include/git2/config_backend.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* In addition to the permissions in the GNU General Public License,
|
||||||
|
* the authors give you unlimited permission to link the compiled
|
||||||
|
* version of this file into combinations with other programs,
|
||||||
|
* and to distribute those combinations without any restriction
|
||||||
|
* coming from the use of this file. (The General Public License
|
||||||
|
* restrictions do apply in other respects; for example, they cover
|
||||||
|
* modification of the file, and distribution when not linked into
|
||||||
|
* a combined executable.)
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDE_git_config_backend_h__
|
||||||
|
#define INCLUDE_git_config_backend_h__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
GIT_BEGIN_DECL
|
||||||
|
|
||||||
|
struct git_config;
|
||||||
|
|
||||||
|
struct git_config_backend {
|
||||||
|
struct git_config *cfg;
|
||||||
|
/* Open means open the file/database and parse if necessary */
|
||||||
|
int (*open)(struct git_config_backend *);
|
||||||
|
int (* get)(struct git_config_backend *, const char *key, const char **value);
|
||||||
|
int (* set)(struct git_config_backend *, const char *key, const char *value);
|
||||||
|
int (*foreach)(struct git_config_backend *, int (*fn)(const char *, void *), void *data);
|
||||||
|
void (*free)(struct git_config_backend *);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a file-backed configuration backend
|
||||||
|
*
|
||||||
|
* @param out the new backend
|
||||||
|
* @path where the config file is located
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_backend_file(struct git_config_backend **out, const char *path);
|
||||||
|
|
||||||
|
GIT_END_DECL
|
||||||
|
|
||||||
|
#endif
|
@ -130,6 +130,15 @@ typedef struct git_treebuilder git_treebuilder;
|
|||||||
/** Memory representation of an index file. */
|
/** Memory representation of an index file. */
|
||||||
typedef struct git_index git_index;
|
typedef struct git_index git_index;
|
||||||
|
|
||||||
|
/** Memory representation of a config file */
|
||||||
|
typedef struct git_config git_config;
|
||||||
|
|
||||||
|
/** A specific implementation of a config backend */
|
||||||
|
typedef struct git_config_backend git_config_backend;
|
||||||
|
|
||||||
|
/** Memory representation of a config variable */
|
||||||
|
typedef struct git_cvar git_cvar;
|
||||||
|
|
||||||
/** Time in a signature */
|
/** Time in a signature */
|
||||||
typedef struct git_time {
|
typedef struct git_time {
|
||||||
git_time_t time; /** time in seconds from epoch */
|
git_time_t time; /** time in seconds from epoch */
|
||||||
|
337
src/config.c
Normal file
337
src/config.c
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* In addition to the permissions in the GNU General Public License,
|
||||||
|
* the authors give you unlimited permission to link the compiled
|
||||||
|
* version of this file into combinations with other programs,
|
||||||
|
* and to distribute those combinations without any restriction
|
||||||
|
* coming from the use of this file. (The General Public License
|
||||||
|
* restrictions do apply in other respects; for example, they cover
|
||||||
|
* modification of the file, and distribution when not linked into
|
||||||
|
* a combined executable.)
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "hashtable.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "git2/config_backend.h"
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
git_config_backend *backend;
|
||||||
|
int priority;
|
||||||
|
} backend_internal;
|
||||||
|
|
||||||
|
void git__strntolower(char *str, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
str[i] = tolower(str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void git__strtolower(char *str)
|
||||||
|
{
|
||||||
|
git__strntolower(str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_config_open_bare(git_config **out, const char *path)
|
||||||
|
{
|
||||||
|
git_config_backend *backend = NULL;
|
||||||
|
git_config *cfg = NULL;
|
||||||
|
int error = GIT_SUCCESS;
|
||||||
|
|
||||||
|
error = git_config_new(&cfg);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
error = git_config_backend_file(&backend, path);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
error = git_config_add_backend(cfg, backend, 1);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
error = backend->open(backend);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
*out = cfg;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if(backend)
|
||||||
|
backend->free(backend);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void git_config_free(git_config *cfg)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
git_config_backend *backend;
|
||||||
|
backend_internal *internal;
|
||||||
|
|
||||||
|
for(i = 0; i < cfg->backends.length; ++i){
|
||||||
|
internal = git_vector_get(&cfg->backends, i);
|
||||||
|
backend = internal->backend;
|
||||||
|
backend->free(backend);
|
||||||
|
free(internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
git_vector_free(&cfg->backends);
|
||||||
|
free(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int config_backend_cmp(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const backend_internal *bk_a = *(const backend_internal **)(a);
|
||||||
|
const backend_internal *bk_b = *(const backend_internal **)(b);
|
||||||
|
|
||||||
|
return bk_b->priority - bk_a->priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_config_new(git_config **out)
|
||||||
|
{
|
||||||
|
git_config *cfg;
|
||||||
|
|
||||||
|
cfg = git__malloc(sizeof(git_config));
|
||||||
|
if (cfg == NULL)
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
memset(cfg, 0x0, sizeof(git_config));
|
||||||
|
|
||||||
|
if (git_vector_init(&cfg->backends, 3, config_backend_cmp) < 0) {
|
||||||
|
free(cfg);
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = cfg;
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_config_add_backend(git_config *cfg, git_config_backend *backend, int priority)
|
||||||
|
{
|
||||||
|
backend_internal *internal;
|
||||||
|
|
||||||
|
assert(cfg && backend);
|
||||||
|
|
||||||
|
internal = git__malloc(sizeof(backend_internal));
|
||||||
|
if (internal == NULL)
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
internal->backend = backend;
|
||||||
|
internal->priority = priority;
|
||||||
|
|
||||||
|
if (git_vector_insert(&cfg->backends, internal) < 0) {
|
||||||
|
free(internal);
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
git_vector_sort(&cfg->backends);
|
||||||
|
internal->backend->cfg = cfg;
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loop over all the variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
int git_config_foreach(git_config *cfg, int (*fn)(const char *, void *), void *data)
|
||||||
|
{
|
||||||
|
int ret = GIT_SUCCESS;
|
||||||
|
unsigned int i;
|
||||||
|
backend_internal *internal;
|
||||||
|
git_config_backend *backend;
|
||||||
|
|
||||||
|
for(i = 0; i < cfg->backends.length && ret == 0; ++i) {
|
||||||
|
internal = git_vector_get(&cfg->backends, i);
|
||||||
|
backend = internal->backend;
|
||||||
|
ret = backend->foreach(backend, fn, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************
|
||||||
|
* Setters
|
||||||
|
**************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal function to actually set the string value of a variable
|
||||||
|
*/
|
||||||
|
|
||||||
|
int git_config_set_long(git_config *cfg, const char *name, long int value)
|
||||||
|
{
|
||||||
|
char str_value[5]; /* Most numbers should fit in here */
|
||||||
|
int buf_len = sizeof(str_value), ret;
|
||||||
|
char *help_buf = NULL;
|
||||||
|
|
||||||
|
if ((ret = snprintf(str_value, buf_len, "%ld", value)) >= buf_len - 1){
|
||||||
|
/* The number is too large, we need to allocate more memory */
|
||||||
|
buf_len = ret + 1;
|
||||||
|
help_buf = git__malloc(buf_len);
|
||||||
|
snprintf(help_buf, buf_len, "%ld", value);
|
||||||
|
ret = git_config_set_string(cfg, name, help_buf);
|
||||||
|
free(help_buf);
|
||||||
|
} else {
|
||||||
|
ret = git_config_set_string(cfg, name, str_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_config_set_int(git_config *cfg, const char *name, int value)
|
||||||
|
{
|
||||||
|
return git_config_set_long(cfg, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_config_set_bool(git_config *cfg, const char *name, int value)
|
||||||
|
{
|
||||||
|
const char *str_value;
|
||||||
|
|
||||||
|
if (value == 0)
|
||||||
|
str_value = "false";
|
||||||
|
else
|
||||||
|
str_value = "true";
|
||||||
|
|
||||||
|
return git_config_set_string(cfg, name, str_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_config_set_string(git_config *cfg, const char *name, const char *value)
|
||||||
|
{
|
||||||
|
backend_internal *internal;
|
||||||
|
git_config_backend *backend;
|
||||||
|
|
||||||
|
assert(cfg->backends.length > 0);
|
||||||
|
|
||||||
|
internal = git_vector_get(&cfg->backends, 0);
|
||||||
|
backend = internal->backend;
|
||||||
|
|
||||||
|
return backend->set(backend, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********
|
||||||
|
* Getters
|
||||||
|
***********/
|
||||||
|
|
||||||
|
int git_config_get_long(git_config *cfg, const char *name, long int *out)
|
||||||
|
{
|
||||||
|
const char *value, *num_end;
|
||||||
|
int ret;
|
||||||
|
long int num;
|
||||||
|
|
||||||
|
ret = git_config_get_string(cfg, name, &value);
|
||||||
|
if (ret < GIT_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = git__strtol32(&num, value, &num_end, 0);
|
||||||
|
if (ret < GIT_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
switch (*num_end) {
|
||||||
|
case '\0':
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
case 'K':
|
||||||
|
num *= 1024;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
num *= 1024 * 1024;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
case 'G':
|
||||||
|
num *= 1024 * 1024 * 1024;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return GIT_EINVALIDTYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = num;
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_config_get_int(git_config *cfg, const char *name, int *out)
|
||||||
|
{
|
||||||
|
long int tmp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = git_config_get_long(cfg, name, &tmp);
|
||||||
|
|
||||||
|
*out = (int) tmp;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_config_get_bool(git_config *cfg, const char *name, int *out)
|
||||||
|
{
|
||||||
|
const char *value;
|
||||||
|
int error = GIT_SUCCESS;
|
||||||
|
|
||||||
|
error = git_config_get_string(cfg, name, &value);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
/* A missing value means true */
|
||||||
|
if (value == NULL) {
|
||||||
|
*out = 1;
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcasecmp(value, "true") ||
|
||||||
|
!strcasecmp(value, "yes") ||
|
||||||
|
!strcasecmp(value, "on")) {
|
||||||
|
*out = 1;
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
if (!strcasecmp(value, "false") ||
|
||||||
|
!strcasecmp(value, "no") ||
|
||||||
|
!strcasecmp(value, "off")) {
|
||||||
|
*out = 0;
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to parse it as an integer */
|
||||||
|
error = git_config_get_int(cfg, name, out);
|
||||||
|
if (error == GIT_SUCCESS)
|
||||||
|
*out = !!(*out);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_config_get_string(git_config *cfg, const char *name, const char **out)
|
||||||
|
{
|
||||||
|
backend_internal *internal;
|
||||||
|
git_config_backend *backend;
|
||||||
|
|
||||||
|
assert(cfg->backends.length > 0);
|
||||||
|
|
||||||
|
internal = git_vector_get(&cfg->backends, 0);
|
||||||
|
backend = internal->backend;
|
||||||
|
|
||||||
|
return backend->get(backend, name, out);
|
||||||
|
}
|
||||||
|
|
15
src/config.h
Normal file
15
src/config.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef INCLUDE_config_h__
|
||||||
|
#define INCLUDE_config_h__
|
||||||
|
|
||||||
|
#include "git2.h"
|
||||||
|
#include "git2/config.h"
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
struct git_config {
|
||||||
|
git_vector backends;
|
||||||
|
};
|
||||||
|
|
||||||
|
void git__strtolower(char *str);
|
||||||
|
void git__strntolower(char *str, int len);
|
||||||
|
|
||||||
|
#endif
|
1011
src/config_file.c
Normal file
1011
src/config_file.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -42,7 +42,7 @@ static struct {
|
|||||||
{GIT_EOBJTYPE, "The specified object is of invalid type"},
|
{GIT_EOBJTYPE, "The specified object is of invalid type"},
|
||||||
{GIT_EOBJCORRUPTED, "The specified object has its data corrupted"},
|
{GIT_EOBJCORRUPTED, "The specified object has its data corrupted"},
|
||||||
{GIT_ENOTAREPO, "The specified repository is invalid"},
|
{GIT_ENOTAREPO, "The specified repository is invalid"},
|
||||||
{GIT_EINVALIDTYPE, "The object type is invalid or doesn't match"},
|
{GIT_EINVALIDTYPE, "The object or config variable type is invalid or doesn't match"},
|
||||||
{GIT_EMISSINGOBJDATA, "The object cannot be written that because it's missing internal data"},
|
{GIT_EMISSINGOBJDATA, "The object cannot be written that because it's missing internal data"},
|
||||||
{GIT_EPACKCORRUPTED, "The packfile for the ODB is corrupted"},
|
{GIT_EPACKCORRUPTED, "The packfile for the ODB is corrupted"},
|
||||||
{GIT_EFLOCKFAIL, "Failed to adquire or release a file lock"},
|
{GIT_EFLOCKFAIL, "Failed to adquire or release a file lock"},
|
||||||
|
BIN
tests/resources/config/config0
Normal file
BIN
tests/resources/config/config0
Normal file
Binary file not shown.
BIN
tests/resources/config/config1
Normal file
BIN
tests/resources/config/config1
Normal file
Binary file not shown.
BIN
tests/resources/config/config2
Normal file
BIN
tests/resources/config/config2
Normal file
Binary file not shown.
BIN
tests/resources/config/config3
Normal file
BIN
tests/resources/config/config3
Normal file
Binary file not shown.
BIN
tests/resources/config/config4
Normal file
BIN
tests/resources/config/config4
Normal file
Binary file not shown.
BIN
tests/resources/config/config5
Normal file
BIN
tests/resources/config/config5
Normal file
Binary file not shown.
171
tests/t15-config.c
Normal file
171
tests/t15-config.c
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* In addition to the permissions in the GNU General Public License,
|
||||||
|
* the authors give you unlimited permission to link the compiled
|
||||||
|
* version of this file into combinations with other programs,
|
||||||
|
* and to distribute those combinations without any restriction
|
||||||
|
* coming from the use of this file. (The General Public License
|
||||||
|
* restrictions do apply in other respects; for example, they cover
|
||||||
|
* modification of the file, and distribution when not linked into
|
||||||
|
* a combined executable.)
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "test_lib.h"
|
||||||
|
#include "test_helpers.h"
|
||||||
|
|
||||||
|
#include <git2.h>
|
||||||
|
|
||||||
|
#define CONFIG_BASE TEST_RESOURCES "/config"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This one is so we know the code isn't completely broken
|
||||||
|
*/
|
||||||
|
BEGIN_TEST(config0, "read a simple configuration")
|
||||||
|
git_config *cfg;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config0"));
|
||||||
|
must_pass(git_config_get_int(cfg, "core.repositoryformatversion", &i));
|
||||||
|
must_be_true(i == 0);
|
||||||
|
must_pass(git_config_get_bool(cfg, "core.filemode", &i));
|
||||||
|
must_be_true(i == 1);
|
||||||
|
must_pass(git_config_get_bool(cfg, "core.bare", &i));
|
||||||
|
must_be_true(i == 0);
|
||||||
|
must_pass(git_config_get_bool(cfg, "core.logallrefupdates", &i));
|
||||||
|
must_be_true(i == 1);
|
||||||
|
|
||||||
|
git_config_free(cfg);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [this "that"] and [this "That] are different namespaces. Make sure
|
||||||
|
* each returns the correct one.
|
||||||
|
*/
|
||||||
|
BEGIN_TEST(config1, "case sensitivity")
|
||||||
|
git_config *cfg;
|
||||||
|
int i;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config1"));
|
||||||
|
|
||||||
|
must_pass(git_config_get_string(cfg, "this.that.other", &str));
|
||||||
|
must_be_true(!strcmp(str, "true"));
|
||||||
|
must_pass(git_config_get_string(cfg, "this.That.other", &str));
|
||||||
|
must_be_true(!strcmp(str, "yes"));
|
||||||
|
|
||||||
|
must_pass(git_config_get_bool(cfg, "this.that.other", &i));
|
||||||
|
must_be_true(i == 1);
|
||||||
|
must_pass(git_config_get_bool(cfg, "this.That.other", &i));
|
||||||
|
must_be_true(i == 1);
|
||||||
|
|
||||||
|
/* This one doesn't exist */
|
||||||
|
must_fail(git_config_get_bool(cfg, "this.thaT.other", &i));
|
||||||
|
|
||||||
|
git_config_free(cfg);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If \ is the last non-space character on the line, we read the next
|
||||||
|
* one, separating each line with SP.
|
||||||
|
*/
|
||||||
|
BEGIN_TEST(config2, "parse a multiline value")
|
||||||
|
git_config *cfg;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config2"));
|
||||||
|
|
||||||
|
must_pass(git_config_get_string(cfg, "this.That.and", &str));
|
||||||
|
must_be_true(!strcmp(str, "one one one two two three three"));
|
||||||
|
|
||||||
|
git_config_free(cfg);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This kind of subsection declaration is case-insensitive
|
||||||
|
*/
|
||||||
|
BEGIN_TEST(config3, "parse a [section.subsection] header")
|
||||||
|
git_config *cfg;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config3"));
|
||||||
|
|
||||||
|
must_pass(git_config_get_string(cfg, "section.subsection.var", &str));
|
||||||
|
must_be_true(!strcmp(str, "hello"));
|
||||||
|
|
||||||
|
/* Avoid a false positive */
|
||||||
|
str = "nohello";
|
||||||
|
must_pass(git_config_get_string(cfg, "section.subSectIon.var", &str));
|
||||||
|
must_be_true(!strcmp(str, "hello"));
|
||||||
|
|
||||||
|
git_config_free(cfg);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
BEGIN_TEST(config4, "a variable name on its own is valid")
|
||||||
|
git_config *cfg;
|
||||||
|
const char *str;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config4"));
|
||||||
|
|
||||||
|
must_pass(git_config_get_string(cfg, "some.section.variable", &str));
|
||||||
|
must_be_true(str == NULL);
|
||||||
|
|
||||||
|
must_pass(git_config_get_bool(cfg, "some.section.variable", &i));
|
||||||
|
must_be_true(i == 1);
|
||||||
|
|
||||||
|
|
||||||
|
git_config_free(cfg);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
BEGIN_TEST(config5, "test number suffixes")
|
||||||
|
git_config *cfg;
|
||||||
|
const char *str;
|
||||||
|
long int i;
|
||||||
|
|
||||||
|
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config5"));
|
||||||
|
|
||||||
|
must_pass(git_config_get_long(cfg, "number.simple", &i));
|
||||||
|
must_be_true(i == 1);
|
||||||
|
|
||||||
|
must_pass(git_config_get_long(cfg, "number.k", &i));
|
||||||
|
must_be_true(i == 1 * 1024);
|
||||||
|
|
||||||
|
must_pass(git_config_get_long(cfg, "number.kk", &i));
|
||||||
|
must_be_true(i == 1 * 1024);
|
||||||
|
|
||||||
|
must_pass(git_config_get_long(cfg, "number.m", &i));
|
||||||
|
must_be_true(i == 1 * 1024 * 1024);
|
||||||
|
|
||||||
|
must_pass(git_config_get_long(cfg, "number.mm", &i));
|
||||||
|
must_be_true(i == 1 * 1024 * 1024);
|
||||||
|
|
||||||
|
must_pass(git_config_get_long(cfg, "number.g", &i));
|
||||||
|
must_be_true(i == 1 * 1024 * 1024 * 1024);
|
||||||
|
|
||||||
|
must_pass(git_config_get_long(cfg, "number.gg", &i));
|
||||||
|
must_be_true(i == 1 * 1024 * 1024 * 1024);
|
||||||
|
|
||||||
|
git_config_free(cfg);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
|
BEGIN_SUITE(config)
|
||||||
|
ADD_TEST(config0);
|
||||||
|
ADD_TEST(config1);
|
||||||
|
ADD_TEST(config2);
|
||||||
|
ADD_TEST(config3);
|
||||||
|
ADD_TEST(config4);
|
||||||
|
ADD_TEST(config5);
|
||||||
|
END_SUITE
|
@ -44,6 +44,7 @@ DECLARE_SUITE(sqlite);
|
|||||||
DECLARE_SUITE(hiredis);
|
DECLARE_SUITE(hiredis);
|
||||||
DECLARE_SUITE(repository);
|
DECLARE_SUITE(repository);
|
||||||
DECLARE_SUITE(threads);
|
DECLARE_SUITE(threads);
|
||||||
|
DECLARE_SUITE(config);
|
||||||
|
|
||||||
static libgit2_suite suite_methods[]= {
|
static libgit2_suite suite_methods[]= {
|
||||||
SUITE_NAME(core),
|
SUITE_NAME(core),
|
||||||
@ -60,7 +61,8 @@ static libgit2_suite suite_methods[]= {
|
|||||||
SUITE_NAME(sqlite),
|
SUITE_NAME(sqlite),
|
||||||
SUITE_NAME(repository),
|
SUITE_NAME(repository),
|
||||||
SUITE_NAME(threads),
|
SUITE_NAME(threads),
|
||||||
SUITE_NAME(hiredis)
|
SUITE_NAME(hiredis),
|
||||||
|
SUITE_NAME(config),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GIT_SUITE_COUNT (ARRAY_SIZE(suite_methods))
|
#define GIT_SUITE_COUNT (ARRAY_SIZE(suite_methods))
|
||||||
|
Loading…
Reference in New Issue
Block a user