Commit 8d36b253 by Vicent Martí

Merge pull request #565 from carlosmn/multimap

Add config multivar support
parents 20ed8983 b13dbb91
...@@ -28,6 +28,10 @@ FILE(GLOB SRC_HTTP deps/http-parser/*.c) ...@@ -28,6 +28,10 @@ FILE(GLOB SRC_HTTP deps/http-parser/*.c)
IF (NOT WIN32) IF (NOT WIN32)
FIND_PACKAGE(ZLIB) FIND_PACKAGE(ZLIB)
ELSE()
# Windows doesn't understand POSIX regex on its own
INCLUDE_DIRECTORIES(deps/regex)
SET(SRC_REGEX deps/regex/regex.c)
ENDIF() ENDIF()
IF (ZLIB_FOUND) IF (ZLIB_FOUND)
...@@ -99,7 +103,7 @@ ELSE() ...@@ -99,7 +103,7 @@ ELSE()
ENDIF () ENDIF ()
# Compile and link libgit2 # Compile and link libgit2
ADD_LIBRARY(git2 ${SRC} ${SRC_ZLIB} ${SRC_HTTP} ${WIN_RC}) ADD_LIBRARY(git2 ${SRC} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${WIN_RC})
IF (WIN32) IF (WIN32)
TARGET_LINK_LIBRARIES(git2 ws2_32) TARGET_LINK_LIBRARIES(git2 ws2_32)
...@@ -130,7 +134,7 @@ IF (BUILD_TESTS) ...@@ -130,7 +134,7 @@ IF (BUILD_TESTS)
INCLUDE_DIRECTORIES(tests) INCLUDE_DIRECTORIES(tests)
FILE(GLOB SRC_TEST tests/t??-*.c) FILE(GLOB SRC_TEST tests/t??-*.c)
ADD_EXECUTABLE(libgit2_test tests/test_main.c tests/test_lib.c tests/test_helpers.c ${SRC} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP}) ADD_EXECUTABLE(libgit2_test tests/test_main.c tests/test_lib.c tests/test_helpers.c ${SRC} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX})
TARGET_LINK_LIBRARIES(libgit2_test ${CMAKE_THREAD_LIBS_INIT}) TARGET_LINK_LIBRARIES(libgit2_test ${CMAKE_THREAD_LIBS_INIT})
IF (WIN32) IF (WIN32)
TARGET_LINK_LIBRARIES(libgit2_test ws2_32) TARGET_LINK_LIBRARIES(libgit2_test ws2_32)
...@@ -158,7 +162,7 @@ IF (BUILD_CLAR) ...@@ -158,7 +162,7 @@ IF (BUILD_CLAR)
DEPENDS ${CLAR_PATH}/clar ${SRC_TEST} DEPENDS ${CLAR_PATH}/clar ${SRC_TEST}
WORKING_DIRECTORY ${CLAR_PATH} WORKING_DIRECTORY ${CLAR_PATH}
) )
ADD_EXECUTABLE(libgit2_clar ${SRC} ${CLAR_PATH}/clar_main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP}) ADD_EXECUTABLE(libgit2_clar ${SRC} ${CLAR_PATH}/clar_main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX})
TARGET_LINK_LIBRARIES(libgit2_clar ${CMAKE_THREAD_LIBS_INIT}) TARGET_LINK_LIBRARIES(libgit2_clar ${CMAKE_THREAD_LIBS_INIT})
IF (WIN32) IF (WIN32)
TARGET_LINK_LIBRARIES(libgit2_clar ws2_32) TARGET_LINK_LIBRARIES(libgit2_clar ws2_32)
......
#ifndef _REGEX_CONFIG_H_
#define _REGEX_CONFIG_H_
# define GAWK
# define NO_MBSUPPORT
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
/* Extended regular expression matching and search library.
Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA. */
#include "config.h"
/* Make sure noone compiles this code with a C++ compiler. */
#ifdef __cplusplus
# error "This is C code, use a C compiler"
#endif
#ifdef _LIBC
/* We have to keep the namespace clean. */
# define regfree(preg) __regfree (preg)
# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
# define regerror(errcode, preg, errbuf, errbuf_size) \
__regerror(errcode, preg, errbuf, errbuf_size)
# define re_set_registers(bu, re, nu, st, en) \
__re_set_registers (bu, re, nu, st, en)
# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
# define re_match(bufp, string, size, pos, regs) \
__re_match (bufp, string, size, pos, regs)
# define re_search(bufp, string, size, startpos, range, regs) \
__re_search (bufp, string, size, startpos, range, regs)
# define re_compile_pattern(pattern, length, bufp) \
__re_compile_pattern (pattern, length, bufp)
# define re_set_syntax(syntax) __re_set_syntax (syntax)
# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
# include "../locale/localeinfo.h"
#endif
#if defined (_MSC_VER)
#include <stdio.h> /* for size_t */
#endif
/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
GNU regex allows. Include it before <regex.h>, which correctly
#undefs RE_DUP_MAX and sets it to the right value. */
#include <limits.h>
#ifdef GAWK
#undef alloca
#define alloca alloca_is_bad_you_should_never_use_it
#endif
#include <regex.h>
#include "regex_internal.h"
#include "regex_internal.c"
#ifdef GAWK
#define bool int
#define true (1)
#define false (0)
#endif
#include "regcomp.c"
#include "regexec.c"
/* Binary backward compatibility. */
#if _LIBC
# include <shlib-compat.h>
# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
int re_max_failures = 2000;
# endif
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -29,7 +29,9 @@ struct git_config_file { ...@@ -29,7 +29,9 @@ struct git_config_file {
/* Open means open the file/database and parse if necessary */ /* Open means open the file/database and parse if necessary */
int (*open)(struct git_config_file *); int (*open)(struct git_config_file *);
int (*get)(struct git_config_file *, const char *key, const char **value); int (*get)(struct git_config_file *, const char *key, const char **value);
int (*get_multivar)(struct git_config_file *, const char *key, const char *regexp, int (*fn)(const char *, void *), void *data);
int (*set)(struct git_config_file *, const char *key, const char *value); int (*set)(struct git_config_file *, const char *key, const char *value);
int (*set_multivar)(git_config_file *cfg, const char *name, const char *regexp, const char *value);
int (*del)(struct git_config_file *, const char *key); int (*del)(struct git_config_file *, const char *key);
int (*foreach)(struct git_config_file *, int (*fn)(const char *, const char *, void *), void *data); int (*foreach)(struct git_config_file *, int (*fn)(const char *, const char *, void *), void *data);
void (*free)(struct git_config_file *); void (*free)(struct git_config_file *);
...@@ -206,6 +208,20 @@ GIT_EXTERN(int) git_config_get_bool(git_config *cfg, const char *name, int *out) ...@@ -206,6 +208,20 @@ GIT_EXTERN(int) git_config_get_bool(git_config *cfg, const char *name, int *out)
GIT_EXTERN(int) git_config_get_string(git_config *cfg, const char *name, const char **out); GIT_EXTERN(int) git_config_get_string(git_config *cfg, const char *name, const char **out);
/** /**
* Get each value of a multivar.
*
* The callback will be called on each variable found
*
* @param cfg where to look for the variable
* @param name the variable's name
* @param regexp regular expression to filter which variables we're
* interested in. Use NULL to indicate all
* @param fn the function to be called on each value of the variable
* @param data opaque pointer to pass to the callback
*/
GIT_EXTERN(int) git_config_get_multivar(git_config *cfg, const char *name, const char *regexp, int (*fn)(const char *, void *), void *data);
/**
* Set the value of an integer config variable. * Set the value of an integer config variable.
* *
* @param cfg where to look for the variable * @param cfg where to look for the variable
...@@ -248,6 +264,17 @@ GIT_EXTERN(int) git_config_set_bool(git_config *cfg, const char *name, int value ...@@ -248,6 +264,17 @@ GIT_EXTERN(int) git_config_set_bool(git_config *cfg, const char *name, int value
*/ */
GIT_EXTERN(int) git_config_set_string(git_config *cfg, const char *name, const char *value); GIT_EXTERN(int) git_config_set_string(git_config *cfg, const char *name, const char *value);
/**
* Set a multivar
*
* @param cfg where to look for the variable
* @param name the variable's name
* @param regexp a regular expression to indicate which values to replace
* @param value the new value.
*/
GIT_EXTERN(int) git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value);
/** /**
* Delete a config variable * Delete a config variable
* *
......
...@@ -337,6 +337,51 @@ int git_config_get_string(git_config *cfg, const char *name, const char **out) ...@@ -337,6 +337,51 @@ int git_config_get_string(git_config *cfg, const char *name, const char **out)
return git__throw(error, "Config value '%s' not found", name); return git__throw(error, "Config value '%s' not found", name);
} }
int git_config_get_multivar(git_config *cfg, const char *name, const char *regexp,
int (*fn)(const char *value, void *data), void *data)
{
file_internal *internal;
git_config_file *file;
int error = GIT_ENOTFOUND;
unsigned int i;
if (cfg->files.length == 0)
return git__throw(GIT_EINVALIDARGS, "Cannot get variable value; no files open in the `git_config` instance");
/*
* This loop runs the "wrong" way 'round because we need to
* look at every value from the most general to most specific
*/
for (i = cfg->files.length; i > 0; --i) {
internal = git_vector_get(&cfg->files, i - 1);
file = internal->file;
error = file->get_multivar(file, name, regexp, fn, data);
if (error < GIT_SUCCESS && error != GIT_ENOTFOUND)
git__rethrow(error, "Failed to get multivar");
}
return GIT_SUCCESS;
}
int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
{
file_internal *internal;
git_config_file *file;
int error = GIT_ENOTFOUND;
unsigned int i;
for (i = cfg->files.length; i > 0; --i) {
internal = git_vector_get(&cfg->files, i - 1);
file = internal->file;
error = file->set_multivar(file, name, regexp, value);
if (error < GIT_SUCCESS && error != GIT_ENOTFOUND)
git__rethrow(error, "Failed to replace multivar");
}
return GIT_SUCCESS;
}
int git_config_find_global_r(git_buf *path) int git_config_find_global_r(git_buf *path)
{ {
return git_futils_find_global_file(path, GIT_CONFIG_FILENAME); return git_futils_find_global_file(path, GIT_CONFIG_FILENAME);
......
#include "clar_libgit2.h"
static int mv_read_cb(const char *name, const char *GIT_UNUSED(value), void *data)
{
int *n = (int *) data;
if (!strcmp(name, "remote.fancy.url"))
(*n)++;
return 0;
}
void test_config_multivar__foreach(void)
{
git_config *cfg;
int n = 0;
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config11")));
cl_git_pass(git_config_foreach(cfg, mv_read_cb, &n));
cl_assert(n == 2);
git_config_free(cfg);
}
static int cb(const char *GIT_UNUSED(val), void *data)
{
int *n = (int *) data;
(*n)++;
return GIT_SUCCESS;
}
void test_config_multivar__get(void)
{
git_config *cfg;
const char *name = "remote.fancy.url";
int n;
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config11")));
n = 0;
cl_git_pass(git_config_get_multivar(cfg, name, NULL, cb, &n));
cl_assert(n == 2);
n = 0;
cl_git_pass(git_config_get_multivar(cfg, name, "example", cb, &n));
cl_assert(n == 1);
git_config_free(cfg);
}
void test_config_multivar__add(void)
{
git_config *cfg;
const char *name = "remote.fancy.url";
int n;
cl_fixture_sandbox("config");
cl_git_pass(git_config_open_ondisk(&cfg, "config/config11"));
cl_git_pass(git_config_set_multivar(cfg, name, "^$", "git://git.otherplace.org/libgit2"));
n = 0;
cl_git_pass(git_config_get_multivar(cfg, name, NULL, cb, &n));
cl_assert(n == 3);
n = 0;
cl_git_pass(git_config_get_multivar(cfg, name, "otherplace", cb, &n));
cl_assert(n == 1);
git_config_free(cfg);
/* We know it works in memory, let's see if the file is written correctly */
cl_git_pass(git_config_open_ondisk(&cfg, "config/config11"));
n = 0;
cl_git_pass(git_config_get_multivar(cfg, name, NULL, cb, &n));
cl_assert(n == 3);
n = 0;
cl_git_pass(git_config_get_multivar(cfg, name, "otherplace", cb, &n));
cl_assert(n == 1);
git_config_free(cfg);
}
[remote "fancy"]
url = git://github.com/libgit2/libgit2
url = git://git.example.com/libgit2
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment