Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
b8b22d77
Commit
b8b22d77
authored
Aug 28, 2013
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1772 from libgit2/config-iter
Configuration iterators redux
parents
21a3bbe4
f4be8209
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
680 additions
and
207 deletions
+680
-207
include/git2/config.h
+72
-2
include/git2/sys/config.h
+28
-2
src/config.c
+365
-27
src/config.h
+3
-0
src/config_file.c
+53
-141
src/config_file.h
+2
-2
src/diff_driver.c
+2
-2
src/remote.c
+1
-1
src/strmap.c
+32
-0
src/strmap.h
+11
-0
tests-clar/config/multivar.c
+47
-29
tests-clar/config/read.c
+63
-0
tests-clar/config/validkeyname.c
+1
-1
No files found.
include/git2/config.h
View file @
b8b22d77
...
@@ -61,6 +61,7 @@ typedef struct {
...
@@ -61,6 +61,7 @@ typedef struct {
}
git_config_entry
;
}
git_config_entry
;
typedef
int
(
*
git_config_foreach_cb
)(
const
git_config_entry
*
,
void
*
);
typedef
int
(
*
git_config_foreach_cb
)(
const
git_config_entry
*
,
void
*
);
typedef
struct
git_config_iterator
git_config_iterator
;
typedef
enum
{
typedef
enum
{
GIT_CVAR_FALSE
=
0
,
GIT_CVAR_FALSE
=
0
,
...
@@ -327,7 +328,7 @@ GIT_EXTERN(int) git_config_get_bool(int *out, const git_config *cfg, const char
...
@@ -327,7 +328,7 @@ GIT_EXTERN(int) git_config_get_bool(int *out, const git_config *cfg, const char
GIT_EXTERN
(
int
)
git_config_get_string
(
const
char
**
out
,
const
git_config
*
cfg
,
const
char
*
name
);
GIT_EXTERN
(
int
)
git_config_get_string
(
const
char
**
out
,
const
git_config
*
cfg
,
const
char
*
name
);
/**
/**
* Get each value of a multivar
.
* Get each value of a multivar
in a foreach callback
*
*
* The callback will be called on each variable found
* The callback will be called on each variable found
*
*
...
@@ -338,7 +339,34 @@ GIT_EXTERN(int) git_config_get_string(const char **out, const git_config *cfg, c
...
@@ -338,7 +339,34 @@ GIT_EXTERN(int) git_config_get_string(const char **out, const git_config *cfg, c
* @param callback the function to be called on each value of the variable
* @param callback the function to be called on each value of the variable
* @param payload opaque pointer to pass to the callback
* @param payload opaque pointer to pass to the callback
*/
*/
GIT_EXTERN
(
int
)
git_config_get_multivar
(
const
git_config
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
git_config_foreach_cb
callback
,
void
*
payload
);
GIT_EXTERN
(
int
)
git_config_get_multivar_foreach
(
const
git_config
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
git_config_foreach_cb
callback
,
void
*
payload
);
/**
* Get each value of a multivar
*
* @param out pointer to store the iterator
* @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
*/
GIT_EXTERN
(
int
)
git_config_multivar_iterator_new
(
git_config_iterator
**
out
,
const
git_config
*
cfg
,
const
char
*
name
,
const
char
*
regexp
);
/**
* Return the current entry and advance the iterator
*
* @param entry pointer to store the entry
* @param iter the iterator
* @return 0 or an error code. GIT_ITEROVER if the iteration has completed
*/
GIT_EXTERN
(
int
)
git_config_next
(
git_config_entry
**
entry
,
git_config_iterator
*
iter
);
/**
* Free a config iterator
*
* @param iter the iterator to free
*/
GIT_EXTERN
(
void
)
git_config_iterator_free
(
git_config_iterator
*
iter
);
/**
/**
* Set the value of an integer config variable in the config file
* Set the value of an integer config variable in the config file
...
@@ -425,6 +453,29 @@ GIT_EXTERN(int) git_config_foreach(
...
@@ -425,6 +453,29 @@ GIT_EXTERN(int) git_config_foreach(
void
*
payload
);
void
*
payload
);
/**
/**
* Iterate over all the config variables
*
* Use `git_config_next` to advance the iteration and
* `git_config_iterator_free` when done.
*
* @param out pointer to store the iterator
* @param cfg where to ge the variables from
*/
GIT_EXTERN
(
int
)
git_config_iterator_new
(
git_config_iterator
**
out
,
const
git_config
*
cfg
);
/**
* Iterate over all the config variables whose name matches a pattern
*
* Use `git_config_next` to advance the iteration and
* `git_config_iterator_free` when done.
*
* @param out pointer to store the iterator
* @param cfg where to ge the variables from
* @param regexp regular expression to match the names
*/
GIT_EXTERN
(
int
)
git_config_iterator_glob_new
(
git_config_iterator
**
out
,
const
git_config
*
cfg
,
const
char
*
regexp
);
/**
* Perform an operation on each config variable matching a regular expression.
* Perform an operation on each config variable matching a regular expression.
*
*
* This behaviors like `git_config_foreach` with an additional filter of a
* This behaviors like `git_config_foreach` with an additional filter of a
...
@@ -535,6 +586,25 @@ GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value);
...
@@ -535,6 +586,25 @@ GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value);
GIT_EXTERN
(
int
)
git_config_parse_int64
(
int64_t
*
out
,
const
char
*
value
);
GIT_EXTERN
(
int
)
git_config_parse_int64
(
int64_t
*
out
,
const
char
*
value
);
/**
* Perform an operation on each config variable in given config backend
* matching a regular expression.
*
* This behaviors like `git_config_foreach_match` except instead of all config
* entries it just enumerates through the given backend entry.
*
* @param backend where to get the variables from
* @param regexp regular expression to match against config names (can be NULL)
* @param callback the function to call on each variable
* @param payload the data to pass to the callback
*/
GIT_EXTERN
(
int
)
git_config_backend_foreach_match
(
git_config_backend
*
backend
,
const
char
*
regexp
,
int
(
*
fn
)(
const
git_config_entry
*
,
void
*
),
void
*
data
);
/** @} */
/** @} */
GIT_END_DECL
GIT_END_DECL
#endif
#endif
include/git2/sys/config.h
View file @
b8b22d77
...
@@ -21,6 +21,33 @@
...
@@ -21,6 +21,33 @@
GIT_BEGIN_DECL
GIT_BEGIN_DECL
/**
/**
* Every iterator must have this struct as its first element, so the
* API can talk to it. You'd define your iterator as
*
* struct my_iterator {
* git_config_iterator parent;
* ...
* }
*
* and assign `iter->parent.backend` to your `git_config_backend`.
*/
struct
git_config_iterator
{
git_config_backend
*
backend
;
unsigned
int
flags
;
/**
* Return the current entry and advance the iterator. The
* memory belongs to the library.
*/
int
(
*
next
)(
git_config_entry
**
entry
,
git_config_iterator
*
iter
);
/**
* Free the iterator
*/
void
(
*
free
)(
git_config_iterator
*
iter
);
};
/**
* Generic backend that implements the interface to
* Generic backend that implements the interface to
* access a configuration file
* access a configuration file
*/
*/
...
@@ -31,11 +58,10 @@ struct git_config_backend {
...
@@ -31,11 +58,10 @@ struct git_config_backend {
/* 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_backend
*
,
git_config_level_t
level
);
int
(
*
open
)(
struct
git_config_backend
*
,
git_config_level_t
level
);
int
(
*
get
)(
const
struct
git_config_backend
*
,
const
char
*
key
,
const
git_config_entry
**
entry
);
int
(
*
get
)(
const
struct
git_config_backend
*
,
const
char
*
key
,
const
git_config_entry
**
entry
);
int
(
*
get_multivar
)(
struct
git_config_backend
*
,
const
char
*
key
,
const
char
*
regexp
,
git_config_foreach_cb
callback
,
void
*
payload
);
int
(
*
set
)(
struct
git_config_backend
*
,
const
char
*
key
,
const
char
*
value
);
int
(
*
set
)(
struct
git_config_backend
*
,
const
char
*
key
,
const
char
*
value
);
int
(
*
set_multivar
)(
git_config_backend
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
char
*
value
);
int
(
*
set_multivar
)(
git_config_backend
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
char
*
value
);
int
(
*
del
)(
struct
git_config_backend
*
,
const
char
*
key
);
int
(
*
del
)(
struct
git_config_backend
*
,
const
char
*
key
);
int
(
*
foreach
)(
struct
git_config_backend
*
,
const
char
*
,
git_config_foreach_cb
callback
,
void
*
payload
);
int
(
*
iterator
)(
git_config_iterator
**
,
struct
git_config_backend
*
);
int
(
*
refresh
)(
struct
git_config_backend
*
);
int
(
*
refresh
)(
struct
git_config_backend
*
);
void
(
*
free
)(
struct
git_config_backend
*
);
void
(
*
free
)(
struct
git_config_backend
*
);
};
};
...
...
src/config.c
View file @
b8b22d77
...
@@ -315,30 +315,241 @@ int git_config_refresh(git_config *cfg)
...
@@ -315,30 +315,241 @@ int git_config_refresh(git_config *cfg)
* Loop over all the variables
* Loop over all the variables
*/
*/
typedef
struct
{
git_config_iterator
parent
;
git_config_iterator
*
current
;
const
git_config
*
cfg
;
regex_t
regex
;
int
has_regex
;
size_t
i
;
}
all_iter
;
static
int
find_next_backend
(
size_t
*
out
,
const
git_config
*
cfg
,
size_t
i
)
{
file_internal
*
internal
;
for
(;
i
>
0
;
--
i
)
{
internal
=
git_vector_get
(
&
cfg
->
files
,
i
-
1
);
if
(
!
internal
||
!
internal
->
file
)
continue
;
*
out
=
i
;
return
0
;
}
return
-
1
;
}
static
int
all_iter_next
(
git_config_entry
**
entry
,
git_config_iterator
*
_iter
)
{
all_iter
*
iter
=
(
all_iter
*
)
_iter
;
file_internal
*
internal
;
git_config_backend
*
backend
;
size_t
i
;
int
error
=
0
;
if
(
iter
->
current
!=
NULL
&&
(
error
=
iter
->
current
->
next
(
entry
,
iter
->
current
))
==
0
)
{
return
0
;
}
if
(
error
<
0
&&
error
!=
GIT_ITEROVER
)
return
error
;
do
{
if
(
find_next_backend
(
&
i
,
iter
->
cfg
,
iter
->
i
)
<
0
)
return
GIT_ITEROVER
;
internal
=
git_vector_get
(
&
iter
->
cfg
->
files
,
i
-
1
);
backend
=
internal
->
file
;
iter
->
i
=
i
-
1
;
if
(
iter
->
current
)
iter
->
current
->
free
(
iter
->
current
);
iter
->
current
=
NULL
;
error
=
backend
->
iterator
(
&
iter
->
current
,
backend
);
if
(
error
==
GIT_ENOTFOUND
)
continue
;
if
(
error
<
0
)
return
error
;
error
=
iter
->
current
->
next
(
entry
,
iter
->
current
);
/* If this backend is empty, then keep going */
if
(
error
==
GIT_ITEROVER
)
continue
;
return
error
;
}
while
(
1
);
return
GIT_ITEROVER
;
}
static
int
all_iter_glob_next
(
git_config_entry
**
entry
,
git_config_iterator
*
_iter
)
{
int
error
;
all_iter
*
iter
=
(
all_iter
*
)
_iter
;
/*
* We use the "normal" function to grab the next one across
* backends and then apply the regex
*/
while
((
error
=
all_iter_next
(
entry
,
_iter
))
==
0
)
{
/* skip non-matching keys if regexp was provided */
if
(
regexec
(
&
iter
->
regex
,
(
*
entry
)
->
name
,
0
,
NULL
,
0
)
!=
0
)
continue
;
/* and simply return if we like the entry's name */
return
0
;
}
return
error
;
}
static
void
all_iter_free
(
git_config_iterator
*
_iter
)
{
all_iter
*
iter
=
(
all_iter
*
)
_iter
;
if
(
iter
->
current
)
iter
->
current
->
free
(
iter
->
current
);
git__free
(
iter
);
}
static
void
all_iter_glob_free
(
git_config_iterator
*
_iter
)
{
all_iter
*
iter
=
(
all_iter
*
)
_iter
;
regfree
(
&
iter
->
regex
);
all_iter_free
(
_iter
);
}
int
git_config_iterator_new
(
git_config_iterator
**
out
,
const
git_config
*
cfg
)
{
all_iter
*
iter
;
iter
=
git__calloc
(
1
,
sizeof
(
all_iter
));
GITERR_CHECK_ALLOC
(
iter
);
iter
->
parent
.
free
=
all_iter_free
;
iter
->
parent
.
next
=
all_iter_next
;
iter
->
i
=
cfg
->
files
.
length
;
iter
->
cfg
=
cfg
;
*
out
=
(
git_config_iterator
*
)
iter
;
return
0
;
}
int
git_config_iterator_glob_new
(
git_config_iterator
**
out
,
const
git_config
*
cfg
,
const
char
*
regexp
)
{
all_iter
*
iter
;
int
result
;
if
(
regexp
==
NULL
)
return
git_config_iterator_new
(
out
,
cfg
);
iter
=
git__calloc
(
1
,
sizeof
(
all_iter
));
GITERR_CHECK_ALLOC
(
iter
);
if
((
result
=
regcomp
(
&
iter
->
regex
,
regexp
,
REG_EXTENDED
))
<
0
)
{
giterr_set_regex
(
&
iter
->
regex
,
result
);
regfree
(
&
iter
->
regex
);
return
-
1
;
}
iter
->
parent
.
next
=
all_iter_glob_next
;
iter
->
parent
.
free
=
all_iter_glob_free
;
iter
->
i
=
cfg
->
files
.
length
;
iter
->
cfg
=
cfg
;
*
out
=
(
git_config_iterator
*
)
iter
;
return
0
;
}
int
git_config_foreach
(
int
git_config_foreach
(
const
git_config
*
cfg
,
git_config_foreach_cb
cb
,
void
*
payload
)
const
git_config
*
cfg
,
git_config_foreach_cb
cb
,
void
*
payload
)
{
{
return
git_config_foreach_match
(
cfg
,
NULL
,
cb
,
payload
);
return
git_config_foreach_match
(
cfg
,
NULL
,
cb
,
payload
);
}
}
int
git_config_backend_foreach_match
(
git_config_backend
*
backend
,
const
char
*
regexp
,
int
(
*
fn
)(
const
git_config_entry
*
,
void
*
),
void
*
data
)
{
git_config_entry
*
entry
;
git_config_iterator
*
iter
;
regex_t
regex
;
int
result
=
0
;
if
(
regexp
!=
NULL
)
{
if
((
result
=
regcomp
(
&
regex
,
regexp
,
REG_EXTENDED
))
<
0
)
{
giterr_set_regex
(
&
regex
,
result
);
regfree
(
&
regex
);
return
-
1
;
}
}
if
((
result
=
backend
->
iterator
(
&
iter
,
backend
))
<
0
)
{
iter
=
NULL
;
return
-
1
;
}
while
(
!
(
iter
->
next
(
&
entry
,
iter
)
<
0
))
{
/* skip non-matching keys if regexp was provided */
if
(
regexp
&&
regexec
(
&
regex
,
entry
->
name
,
0
,
NULL
,
0
)
!=
0
)
continue
;
/* abort iterator on non-zero return value */
if
(
fn
(
entry
,
data
))
{
giterr_clear
();
result
=
GIT_EUSER
;
goto
cleanup
;
}
}
cleanup:
if
(
regexp
!=
NULL
)
regfree
(
&
regex
);
iter
->
free
(
iter
);
return
result
;
}
int
git_config_foreach_match
(
int
git_config_foreach_match
(
const
git_config
*
cfg
,
const
git_config
*
cfg
,
const
char
*
regexp
,
const
char
*
regexp
,
git_config_foreach_cb
cb
,
git_config_foreach_cb
cb
,
void
*
payload
)
void
*
payload
)
{
{
int
ret
=
0
;
int
error
;
size_t
i
;
git_config_iterator
*
iter
;
file_internal
*
internal
;
git_config_entry
*
entry
;
git_config_backend
*
file
;
for
(
i
=
0
;
i
<
cfg
->
files
.
length
&&
ret
==
0
;
++
i
)
{
if
((
error
=
git_config_iterator_glob_new
(
&
iter
,
cfg
,
regexp
))
<
0
)
internal
=
git_vector_get
(
&
cfg
->
files
,
i
);
return
error
;
file
=
internal
->
file
;
ret
=
file
->
foreach
(
file
,
regexp
,
cb
,
payload
);
while
((
error
=
git_config_next
(
&
entry
,
iter
))
==
0
)
{
if
(
cb
(
entry
,
payload
))
{
giterr_clear
();
error
=
GIT_EUSER
;
break
;
}
}
}
return
ret
;
git_config_iterator_free
(
iter
);
if
(
error
==
GIT_ITEROVER
)
error
=
0
;
return
error
;
}
}
/**************
/**************
...
@@ -528,32 +739,114 @@ int git_config_get_entry(const git_config_entry **out, const git_config *cfg, co
...
@@ -528,32 +739,114 @@ int git_config_get_entry(const git_config_entry **out, const git_config *cfg, co
return
config_error_notfound
(
name
);
return
config_error_notfound
(
name
);
}
}
int
git_config_get_multivar
(
int
git_config_get_multivar
_foreach
(
const
git_config
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
git_config
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
git_config_foreach_cb
cb
,
void
*
payload
)
git_config_foreach_cb
cb
,
void
*
payload
)
{
{
file_internal
*
internal
;
int
err
,
found
;
git_config_backend
*
file
;
git_config_iterator
*
iter
;
int
ret
=
GIT_ENOTFOUND
,
err
;
git_config_entry
*
entry
;
size_t
i
;
if
((
err
=
git_config_multivar_iterator_new
(
&
iter
,
cfg
,
name
,
regexp
))
<
0
)
return
err
;
found
=
0
;
while
((
err
=
iter
->
next
(
&
entry
,
iter
))
==
0
)
{
found
=
1
;
if
(
cb
(
entry
,
payload
))
{
iter
->
free
(
iter
);
return
GIT_EUSER
;
}
}
/*
iter
->
free
(
iter
);
* This loop runs the "wrong" way 'round because we need to
if
(
err
==
GIT_ITEROVER
)
* look at every value from the most general to most specific
err
=
0
;
*/
for
(
i
=
cfg
->
files
.
length
;
i
>
0
;
--
i
)
{
if
(
found
==
0
&&
err
==
0
)
internal
=
git_vector_get
(
&
cfg
->
files
,
i
-
1
);
err
=
config_error_notfound
(
name
);
if
(
!
internal
||
!
internal
->
file
)
return
err
;
}
typedef
struct
{
git_config_iterator
parent
;
git_config_iterator
*
iter
;
char
*
name
;
regex_t
regex
;
int
have_regex
;
}
multivar_iter
;
static
int
multivar_iter_next
(
git_config_entry
**
entry
,
git_config_iterator
*
_iter
)
{
multivar_iter
*
iter
=
(
multivar_iter
*
)
_iter
;
int
error
=
0
;
while
((
error
=
iter
->
iter
->
next
(
entry
,
iter
->
iter
))
==
0
)
{
if
(
git__strcmp
(
iter
->
name
,
(
*
entry
)
->
name
))
continue
;
continue
;
file
=
internal
->
file
;
if
(
!
(
err
=
file
->
get_multivar
(
file
,
name
,
regexp
,
cb
,
payload
)))
if
(
!
iter
->
have_regex
)
ret
=
0
;
return
0
;
else
if
(
err
!=
GIT_ENOTFOUND
)
return
err
;
if
(
regexec
(
&
iter
->
regex
,
(
*
entry
)
->
value
,
0
,
NULL
,
0
)
==
0
)
return
0
;
}
return
error
;
}
void
multivar_iter_free
(
git_config_iterator
*
_iter
)
{
multivar_iter
*
iter
=
(
multivar_iter
*
)
_iter
;
iter
->
iter
->
free
(
iter
->
iter
);
git__free
(
iter
->
name
);
regfree
(
&
iter
->
regex
);
git__free
(
iter
);
}
int
git_config_multivar_iterator_new
(
git_config_iterator
**
out
,
const
git_config
*
cfg
,
const
char
*
name
,
const
char
*
regexp
)
{
multivar_iter
*
iter
=
NULL
;
git_config_iterator
*
inner
=
NULL
;
int
error
;
if
((
error
=
git_config_iterator_new
(
&
inner
,
cfg
))
<
0
)
return
error
;
iter
=
git__calloc
(
1
,
sizeof
(
multivar_iter
));
GITERR_CHECK_ALLOC
(
iter
);
if
((
error
=
git_config__normalize_name
(
name
,
&
iter
->
name
))
<
0
)
goto
on_error
;
if
(
regexp
!=
NULL
)
{
error
=
regcomp
(
&
iter
->
regex
,
regexp
,
REG_EXTENDED
);
if
(
error
<
0
)
{
giterr_set_regex
(
&
iter
->
regex
,
error
);
error
=
-
1
;
regfree
(
&
iter
->
regex
);
goto
on_error
;
}
iter
->
have_regex
=
1
;
}
}
return
(
ret
==
GIT_ENOTFOUND
)
?
config_error_notfound
(
name
)
:
0
;
iter
->
iter
=
inner
;
iter
->
parent
.
free
=
multivar_iter_free
;
iter
->
parent
.
next
=
multivar_iter_next
;
*
out
=
(
git_config_iterator
*
)
iter
;
return
0
;
on_error:
inner
->
free
(
inner
);
git__free
(
iter
);
return
error
;
}
}
int
git_config_set_multivar
(
git_config
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
char
*
value
)
int
git_config_set_multivar
(
git_config
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
char
*
value
)
...
@@ -569,6 +862,16 @@ int git_config_set_multivar(git_config *cfg, const char *name, const char *regex
...
@@ -569,6 +862,16 @@ int git_config_set_multivar(git_config *cfg, const char *name, const char *regex
return
file
->
set_multivar
(
file
,
name
,
regexp
,
value
);
return
file
->
set_multivar
(
file
,
name
,
regexp
,
value
);
}
}
int
git_config_next
(
git_config_entry
**
entry
,
git_config_iterator
*
iter
)
{
return
iter
->
next
(
entry
,
iter
);
}
void
git_config_iterator_free
(
git_config_iterator
*
iter
)
{
iter
->
free
(
iter
);
}
static
int
git_config__find_file_to_path
(
static
int
git_config__find_file_to_path
(
char
*
out
,
size_t
outlen
,
int
(
*
find
)(
git_buf
*
buf
))
char
*
out
,
size_t
outlen
,
int
(
*
find
)(
git_buf
*
buf
))
{
{
...
@@ -812,6 +1115,41 @@ fail_parse:
...
@@ -812,6 +1115,41 @@ fail_parse:
return
-
1
;
return
-
1
;
}
}
/* Take something the user gave us and make it nice for our hash function */
int
git_config__normalize_name
(
const
char
*
in
,
char
**
out
)
{
char
*
name
,
*
fdot
,
*
ldot
;
assert
(
in
&&
out
);
name
=
git__strdup
(
in
);
GITERR_CHECK_ALLOC
(
name
);
fdot
=
strchr
(
name
,
'.'
);
ldot
=
strrchr
(
name
,
'.'
);
if
(
fdot
==
NULL
||
fdot
==
name
||
ldot
==
NULL
||
!
ldot
[
1
])
goto
invalid
;
/* Validate and downcase up to first dot and after last dot */
if
(
git_config_file_normalize_section
(
name
,
fdot
)
<
0
||
git_config_file_normalize_section
(
ldot
+
1
,
NULL
)
<
0
)
goto
invalid
;
/* If there is a middle range, make sure it doesn't have newlines */
while
(
fdot
<
ldot
)
if
(
*
fdot
++
==
'\n'
)
goto
invalid
;
*
out
=
name
;
return
0
;
invalid:
git__free
(
name
);
giterr_set
(
GITERR_CONFIG
,
"Invalid config item name '%s'"
,
in
);
return
GIT_EINVALIDSPEC
;
}
struct
rename_data
{
struct
rename_data
{
git_config
*
config
;
git_config
*
config
;
git_buf
*
name
;
git_buf
*
name
;
...
...
src/config.h
View file @
b8b22d77
...
@@ -49,4 +49,7 @@ extern int git_config_rename_section(
...
@@ -49,4 +49,7 @@ extern int git_config_rename_section(
*/
*/
extern
int
git_config_file__ondisk
(
struct
git_config_backend
**
out
,
const
char
*
path
);
extern
int
git_config_file__ondisk
(
struct
git_config_backend
**
out
,
const
char
*
path
);
extern
int
git_config__normalize_name
(
const
char
*
in
,
char
**
out
);
#endif
#endif
src/config_file.c
View file @
b8b22d77
...
@@ -27,6 +27,13 @@ typedef struct cvar_t {
...
@@ -27,6 +27,13 @@ typedef struct cvar_t {
git_config_entry
*
entry
;
git_config_entry
*
entry
;
}
cvar_t
;
}
cvar_t
;
typedef
struct
git_config_file_iter
{
git_config_iterator
parent
;
git_strmap_iter
iter
;
cvar_t
*
next_var
;
}
git_config_file_iter
;
#define CVAR_LIST_HEAD(list) ((list)->head)
#define CVAR_LIST_HEAD(list) ((list)->head)
#define CVAR_LIST_TAIL(list) ((list)->tail)
#define CVAR_LIST_TAIL(list) ((list)->tail)
...
@@ -129,41 +136,6 @@ int git_config_file_normalize_section(char *start, char *end)
...
@@ -129,41 +136,6 @@ int git_config_file_normalize_section(char *start, char *end)
return
0
;
return
0
;
}
}
/* Take something the user gave us and make it nice for our hash function */
static
int
normalize_name
(
const
char
*
in
,
char
**
out
)
{
char
*
name
,
*
fdot
,
*
ldot
;
assert
(
in
&&
out
);
name
=
git__strdup
(
in
);
GITERR_CHECK_ALLOC
(
name
);
fdot
=
strchr
(
name
,
'.'
);
ldot
=
strrchr
(
name
,
'.'
);
if
(
fdot
==
NULL
||
fdot
==
name
||
ldot
==
NULL
||
!
ldot
[
1
])
goto
invalid
;
/* Validate and downcase up to first dot and after last dot */
if
(
git_config_file_normalize_section
(
name
,
fdot
)
<
0
||
git_config_file_normalize_section
(
ldot
+
1
,
NULL
)
<
0
)
goto
invalid
;
/* If there is a middle range, make sure it doesn't have newlines */
while
(
fdot
<
ldot
)
if
(
*
fdot
++
==
'\n'
)
goto
invalid
;
*
out
=
name
;
return
0
;
invalid:
git__free
(
name
);
giterr_set
(
GITERR_CONFIG
,
"Invalid config item name '%s'"
,
in
);
return
GIT_EINVALIDSPEC
;
}
static
void
free_vars
(
git_strmap
*
values
)
static
void
free_vars
(
git_strmap
*
values
)
{
{
cvar_t
*
var
=
NULL
;
cvar_t
*
var
=
NULL
;
...
@@ -247,51 +219,56 @@ static void backend_free(git_config_backend *_backend)
...
@@ -247,51 +219,56 @@ static void backend_free(git_config_backend *_backend)
git__free
(
backend
);
git__free
(
backend
);
}
}
static
int
file_foreach
(
static
void
config_iterator_free
(
git_config_backend
*
backend
,
git_config_iterator
*
iter
)
const
char
*
regexp
,
int
(
*
fn
)(
const
git_config_entry
*
,
void
*
),
void
*
data
)
{
{
diskfile_backend
*
b
=
(
diskfile_backend
*
)
backend
;
git__free
(
iter
);
cvar_t
*
var
,
*
next_var
;
}
const
char
*
key
;
regex_t
regex
;
int
result
=
0
;
if
(
!
b
->
values
)
static
int
config_iterator_next
(
return
0
;
git_config_entry
**
entry
,
git_config_iterator
*
iter
)
{
git_config_file_iter
*
it
=
(
git_config_file_iter
*
)
iter
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
it
->
parent
.
backend
;
int
err
=
0
;
cvar_t
*
var
;
if
(
regexp
!=
NULL
)
{
if
(
it
->
next_var
==
NULL
)
{
if
((
result
=
regcomp
(
&
regex
,
regexp
,
REG_EXTENDED
))
<
0
)
{
err
=
git_strmap_next
((
void
**
)
&
var
,
&
(
it
->
iter
),
b
->
values
);
giterr_set_regex
(
&
regex
,
result
);
}
else
{
regfree
(
&
regex
);
var
=
it
->
next_var
;
return
-
1
;
}
}
}
git_strmap_foreach
(
b
->
values
,
key
,
var
,
if
(
err
<
0
)
{
for
(;
var
!=
NULL
;
var
=
next_var
)
{
it
->
next_var
=
NULL
;
next_var
=
CVAR_LIST_NEXT
(
var
);
return
err
;
}
/* skip non-matching keys if regexp was provided */
*
entry
=
var
->
entry
;
if
(
regexp
&&
regexec
(
&
regex
,
key
,
0
,
NULL
,
0
)
!=
0
)
it
->
next_var
=
CVAR_LIST_NEXT
(
var
);
continue
;
/* abort iterator on non-zero return value */
return
0
;
if
(
fn
(
var
->
entry
,
data
))
{
}
giterr_clear
();
result
=
GIT_EUSER
;
static
int
config_iterator_new
(
goto
cleanup
;
git_config_iterator
**
iter
,
}
struct
git_config_backend
*
backend
)
}
{
);
diskfile_backend
*
b
=
(
diskfile_backend
*
)
backend
;
git_config_file_iter
*
it
=
git__calloc
(
1
,
sizeof
(
git_config_file_iter
));
cleanup:
GITERR_CHECK_ALLOC
(
it
);
if
(
regexp
!=
NULL
)
regfree
(
&
regex
);
return
result
;
it
->
parent
.
backend
=
backend
;
it
->
iter
=
git_strmap_begin
(
b
->
values
);
it
->
next_var
=
NULL
;
it
->
parent
.
next
=
config_iterator_next
;
it
->
parent
.
free
=
config_iterator_free
;
*
iter
=
(
git_config_iterator
*
)
it
;
return
0
;
}
}
static
int
config_set
(
git_config_backend
*
cfg
,
const
char
*
name
,
const
char
*
value
)
static
int
config_set
(
git_config_backend
*
cfg
,
const
char
*
name
,
const
char
*
value
)
...
@@ -302,7 +279,7 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
...
@@ -302,7 +279,7 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
khiter_t
pos
;
khiter_t
pos
;
int
rval
,
ret
;
int
rval
,
ret
;
if
((
rval
=
normalize_name
(
name
,
&
key
))
<
0
)
if
((
rval
=
git_config__
normalize_name
(
name
,
&
key
))
<
0
)
return
rval
;
return
rval
;
/*
/*
...
@@ -385,7 +362,7 @@ static int config_get(const git_config_backend *cfg, const char *name, const git
...
@@ -385,7 +362,7 @@ static int config_get(const git_config_backend *cfg, const char *name, const git
khiter_t
pos
;
khiter_t
pos
;
int
error
;
int
error
;
if
((
error
=
normalize_name
(
name
,
&
key
))
<
0
)
if
((
error
=
git_config__
normalize_name
(
name
,
&
key
))
<
0
)
return
error
;
return
error
;
pos
=
git_strmap_lookup_index
(
b
->
values
,
key
);
pos
=
git_strmap_lookup_index
(
b
->
values
,
key
);
...
@@ -400,70 +377,6 @@ static int config_get(const git_config_backend *cfg, const char *name, const git
...
@@ -400,70 +377,6 @@ static int config_get(const git_config_backend *cfg, const char *name, const git
return
0
;
return
0
;
}
}
static
int
config_get_multivar
(
git_config_backend
*
cfg
,
const
char
*
name
,
const
char
*
regex_str
,
int
(
*
fn
)(
const
git_config_entry
*
,
void
*
),
void
*
data
)
{
cvar_t
*
var
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
char
*
key
;
khiter_t
pos
;
int
error
;
if
((
error
=
normalize_name
(
name
,
&
key
))
<
0
)
return
error
;
pos
=
git_strmap_lookup_index
(
b
->
values
,
key
);
git__free
(
key
);
if
(
!
git_strmap_valid_index
(
b
->
values
,
pos
))
return
GIT_ENOTFOUND
;
var
=
git_strmap_value_at
(
b
->
values
,
pos
);
if
(
regex_str
!=
NULL
)
{
regex_t
regex
;
int
result
;
/* regex matching; build the regex */
result
=
regcomp
(
&
regex
,
regex_str
,
REG_EXTENDED
);
if
(
result
<
0
)
{
giterr_set_regex
(
&
regex
,
result
);
regfree
(
&
regex
);
return
-
1
;
}
/* and throw the callback only on the variables that
* match the regex */
do
{
if
(
regexec
(
&
regex
,
var
->
entry
->
value
,
0
,
NULL
,
0
)
==
0
)
{
/* early termination by the user is not an error;
* just break and return successfully */
if
(
fn
(
var
->
entry
,
data
)
<
0
)
break
;
}
var
=
var
->
next
;
}
while
(
var
!=
NULL
);
regfree
(
&
regex
);
}
else
{
/* no regex; go through all the variables */
do
{
/* early termination by the user is not an error;
* just break and return successfully */
if
(
fn
(
var
->
entry
,
data
)
<
0
)
break
;
var
=
var
->
next
;
}
while
(
var
!=
NULL
);
}
return
0
;
}
static
int
config_set_multivar
(
static
int
config_set_multivar
(
git_config_backend
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
char
*
value
)
git_config_backend
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
char
*
value
)
{
{
...
@@ -477,7 +390,7 @@ static int config_set_multivar(
...
@@ -477,7 +390,7 @@ static int config_set_multivar(
assert
(
regexp
);
assert
(
regexp
);
if
((
result
=
normalize_name
(
name
,
&
key
))
<
0
)
if
((
result
=
git_config__
normalize_name
(
name
,
&
key
))
<
0
)
return
result
;
return
result
;
pos
=
git_strmap_lookup_index
(
b
->
values
,
key
);
pos
=
git_strmap_lookup_index
(
b
->
values
,
key
);
...
@@ -550,7 +463,7 @@ static int config_delete(git_config_backend *cfg, const char *name)
...
@@ -550,7 +463,7 @@ static int config_delete(git_config_backend *cfg, const char *name)
int
result
;
int
result
;
khiter_t
pos
;
khiter_t
pos
;
if
((
result
=
normalize_name
(
name
,
&
key
))
<
0
)
if
((
result
=
git_config__
normalize_name
(
name
,
&
key
))
<
0
)
return
result
;
return
result
;
pos
=
git_strmap_lookup_index
(
b
->
values
,
key
);
pos
=
git_strmap_lookup_index
(
b
->
values
,
key
);
...
@@ -590,11 +503,10 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
...
@@ -590,11 +503,10 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
backend
->
parent
.
open
=
config_open
;
backend
->
parent
.
open
=
config_open
;
backend
->
parent
.
get
=
config_get
;
backend
->
parent
.
get
=
config_get
;
backend
->
parent
.
get_multivar
=
config_get_multivar
;
backend
->
parent
.
set
=
config_set
;
backend
->
parent
.
set
=
config_set
;
backend
->
parent
.
set_multivar
=
config_set_multivar
;
backend
->
parent
.
set_multivar
=
config_set_multivar
;
backend
->
parent
.
del
=
config_delete
;
backend
->
parent
.
del
=
config_delete
;
backend
->
parent
.
foreach
=
file_foreach
;
backend
->
parent
.
iterator
=
config_iterator_new
;
backend
->
parent
.
refresh
=
config_refresh
;
backend
->
parent
.
refresh
=
config_refresh
;
backend
->
parent
.
free
=
backend_free
;
backend
->
parent
.
free
=
backend_free
;
...
...
src/config_file.h
View file @
b8b22d77
...
@@ -42,7 +42,7 @@ GIT_INLINE(int) git_config_file_foreach(
...
@@ -42,7 +42,7 @@ GIT_INLINE(int) git_config_file_foreach(
int
(
*
fn
)(
const
git_config_entry
*
entry
,
void
*
data
),
int
(
*
fn
)(
const
git_config_entry
*
entry
,
void
*
data
),
void
*
data
)
void
*
data
)
{
{
return
cfg
->
forea
ch
(
cfg
,
NULL
,
fn
,
data
);
return
git_config_backend_foreach_mat
ch
(
cfg
,
NULL
,
fn
,
data
);
}
}
GIT_INLINE
(
int
)
git_config_file_foreach_match
(
GIT_INLINE
(
int
)
git_config_file_foreach_match
(
...
@@ -51,7 +51,7 @@ GIT_INLINE(int) git_config_file_foreach_match(
...
@@ -51,7 +51,7 @@ GIT_INLINE(int) git_config_file_foreach_match(
int
(
*
fn
)(
const
git_config_entry
*
entry
,
void
*
data
),
int
(
*
fn
)(
const
git_config_entry
*
entry
,
void
*
data
),
void
*
data
)
void
*
data
)
{
{
return
cfg
->
forea
ch
(
cfg
,
regexp
,
fn
,
data
);
return
git_config_backend_foreach_mat
ch
(
cfg
,
regexp
,
fn
,
data
);
}
}
extern
int
git_config_file_normalize_section
(
char
*
start
,
char
*
end
);
extern
int
git_config_file_normalize_section
(
char
*
start
,
char
*
end
);
...
...
src/diff_driver.c
View file @
b8b22d77
...
@@ -187,7 +187,7 @@ static int git_diff_driver_load(
...
@@ -187,7 +187,7 @@ static int git_diff_driver_load(
git_buf_truncate
(
&
name
,
namelen
+
strlen
(
"diff.."
));
git_buf_truncate
(
&
name
,
namelen
+
strlen
(
"diff.."
));
git_buf_put
(
&
name
,
"xfuncname"
,
strlen
(
"xfuncname"
));
git_buf_put
(
&
name
,
"xfuncname"
,
strlen
(
"xfuncname"
));
if
((
error
=
git_config_get_multivar
(
if
((
error
=
git_config_get_multivar
_foreach
(
cfg
,
name
.
ptr
,
NULL
,
diff_driver_xfuncname
,
drv
))
<
0
)
{
cfg
,
name
.
ptr
,
NULL
,
diff_driver_xfuncname
,
drv
))
<
0
)
{
if
(
error
!=
GIT_ENOTFOUND
)
if
(
error
!=
GIT_ENOTFOUND
)
goto
done
;
goto
done
;
...
@@ -196,7 +196,7 @@ static int git_diff_driver_load(
...
@@ -196,7 +196,7 @@ static int git_diff_driver_load(
git_buf_truncate
(
&
name
,
namelen
+
strlen
(
"diff.."
));
git_buf_truncate
(
&
name
,
namelen
+
strlen
(
"diff.."
));
git_buf_put
(
&
name
,
"funcname"
,
strlen
(
"funcname"
));
git_buf_put
(
&
name
,
"funcname"
,
strlen
(
"funcname"
));
if
((
error
=
git_config_get_multivar
(
if
((
error
=
git_config_get_multivar
_foreach
(
cfg
,
name
.
ptr
,
NULL
,
diff_driver_funcname
,
drv
))
<
0
)
{
cfg
,
name
.
ptr
,
NULL
,
diff_driver_funcname
,
drv
))
<
0
)
{
if
(
error
!=
GIT_ENOTFOUND
)
if
(
error
!=
GIT_ENOTFOUND
)
goto
done
;
goto
done
;
...
...
src/remote.c
View file @
b8b22d77
...
@@ -242,7 +242,7 @@ static int get_optional_config(
...
@@ -242,7 +242,7 @@ static int get_optional_config(
return
-
1
;
return
-
1
;
if
(
cb
!=
NULL
)
if
(
cb
!=
NULL
)
error
=
git_config_get_multivar
(
config
,
key
,
NULL
,
cb
,
payload
);
error
=
git_config_get_multivar
_foreach
(
config
,
key
,
NULL
,
cb
,
payload
);
else
else
error
=
git_config_get_string
(
payload
,
config
,
key
);
error
=
git_config_get_string
(
payload
,
config
,
key
);
...
...
src/strmap.c
0 → 100644
View file @
b8b22d77
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "strmap.h"
int
git_strmap_next
(
void
**
data
,
git_strmap_iter
*
iter
,
git_strmap
*
map
)
{
if
(
!
map
)
return
GIT_ERROR
;
while
(
*
iter
!=
git_strmap_end
(
map
))
{
if
(
!
(
git_strmap_has_data
(
map
,
*
iter
)))
{
++
(
*
iter
);
continue
;
}
*
data
=
git_strmap_value_at
(
map
,
*
iter
);
++
(
*
iter
);
return
GIT_OK
;
}
return
GIT_ITEROVER
;
}
src/strmap.h
View file @
b8b22d77
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
__KHASH_TYPE
(
str
,
const
char
*
,
void
*
);
__KHASH_TYPE
(
str
,
const
char
*
,
void
*
);
typedef
khash_t
(
str
)
git_strmap
;
typedef
khash_t
(
str
)
git_strmap
;
typedef
khiter_t
git_strmap_iter
;
#define GIT__USE_STRMAP \
#define GIT__USE_STRMAP \
__KHASH_IMPL(str, static kh_inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal)
__KHASH_IMPL(str, static kh_inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal)
...
@@ -31,7 +32,9 @@ typedef khash_t(str) git_strmap;
...
@@ -31,7 +32,9 @@ typedef khash_t(str) git_strmap;
#define git_strmap_valid_index(h, idx) (idx != kh_end(h))
#define git_strmap_valid_index(h, idx) (idx != kh_end(h))
#define git_strmap_exists(h, k) (kh_get(str, h, k) != kh_end(h))
#define git_strmap_exists(h, k) (kh_get(str, h, k) != kh_end(h))
#define git_strmap_has_data(h, idx) kh_exist(h, idx)
#define git_strmap_key(h, idx) kh_key(h, idx)
#define git_strmap_value_at(h, idx) kh_val(h, idx)
#define git_strmap_value_at(h, idx) kh_val(h, idx)
#define git_strmap_set_value_at(h, idx, v) kh_val(h, idx) = v
#define git_strmap_set_value_at(h, idx, v) kh_val(h, idx) = v
#define git_strmap_delete_at(h, idx) kh_del(str, h, idx)
#define git_strmap_delete_at(h, idx) kh_del(str, h, idx)
...
@@ -61,4 +64,12 @@ typedef khash_t(str) git_strmap;
...
@@ -61,4 +64,12 @@ typedef khash_t(str) git_strmap;
#define git_strmap_foreach kh_foreach
#define git_strmap_foreach kh_foreach
#define git_strmap_foreach_value kh_foreach_value
#define git_strmap_foreach_value kh_foreach_value
#define git_strmap_begin kh_begin
#define git_strmap_end kh_end
int
git_strmap_next
(
void
**
data
,
git_strmap_iter
*
iter
,
git_strmap
*
map
);
#endif
#endif
tests-clar/config/multivar.c
View file @
b8b22d77
...
@@ -46,60 +46,78 @@ static int cb(const git_config_entry *entry, void *data)
...
@@ -46,60 +46,78 @@ static int cb(const git_config_entry *entry, void *data)
return
0
;
return
0
;
}
}
static
void
check_get_multivar
(
static
void
check_get_multivar
_foreach
(
git_config
*
cfg
,
int
expected
,
int
expected_patterned
)
git_config
*
cfg
,
int
expected
,
int
expected_patterned
)
{
{
int
n
=
0
;
int
n
=
0
;
if
(
expected
>
0
)
{
if
(
expected
>
0
)
{
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_assert_equal_i
(
expected
,
n
);
cl_assert_equal_i
(
expected
,
n
);
}
else
{
}
else
{
cl_assert_equal_i
(
GIT_ENOTFOUND
,
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_config_get_multivar
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
git_config_get_multivar
_foreach
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
}
}
n
=
0
;
n
=
0
;
if
(
expected_patterned
>
0
)
{
if
(
expected_patterned
>
0
)
{
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
"example"
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
"example"
,
cb
,
&
n
));
cl_assert_equal_i
(
expected_patterned
,
n
);
cl_assert_equal_i
(
expected_patterned
,
n
);
}
else
{
}
else
{
cl_assert_equal_i
(
GIT_ENOTFOUND
,
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_config_get_multivar
(
cfg
,
_name
,
"example"
,
cb
,
&
n
));
git_config_get_multivar
_foreach
(
cfg
,
_name
,
"example"
,
cb
,
&
n
));
}
}
}
}
static
void
check_get_multivar
(
git_config
*
cfg
,
int
expected
)
{
git_config_iterator
*
iter
;
git_config_entry
*
entry
;
int
n
=
0
;
cl_git_pass
(
git_config_multivar_iterator_new
(
&
iter
,
cfg
,
_name
,
NULL
));
while
(
git_config_next
(
&
entry
,
iter
)
==
0
)
n
++
;
cl_assert_equal_i
(
expected
,
n
);
git_config_iterator_free
(
iter
);
}
void
test_config_multivar__get
(
void
)
void
test_config_multivar__get
(
void
)
{
{
git_config
*
cfg
;
git_config
*
cfg
;
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
check_get_multivar
(
cfg
,
2
,
1
);
check_get_multivar
_foreach
(
cfg
,
2
,
1
);
/* add another that has the _name entry */
/* add another that has the _name entry */
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config9"
,
GIT_CONFIG_LEVEL_SYSTEM
,
1
));
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config9"
,
GIT_CONFIG_LEVEL_SYSTEM
,
1
));
check_get_multivar
(
cfg
,
3
,
2
);
check_get_multivar
_foreach
(
cfg
,
3
,
2
);
/* add another that does not have the _name entry */
/* add another that does not have the _name entry */
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config0"
,
GIT_CONFIG_LEVEL_GLOBAL
,
1
));
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config0"
,
GIT_CONFIG_LEVEL_GLOBAL
,
1
));
check_get_multivar
(
cfg
,
3
,
2
);
check_get_multivar
_foreach
(
cfg
,
3
,
2
);
/* add another that does not have the _name entry at the end */
/* add another that does not have the _name entry at the end */
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config1"
,
GIT_CONFIG_LEVEL_APP
,
1
));
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config1"
,
GIT_CONFIG_LEVEL_APP
,
1
));
check_get_multivar
(
cfg
,
3
,
2
);
check_get_multivar
_foreach
(
cfg
,
3
,
2
);
/* drop original file */
/* drop original file */
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config2"
,
GIT_CONFIG_LEVEL_LOCAL
,
1
));
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config2"
,
GIT_CONFIG_LEVEL_LOCAL
,
1
));
check_get_multivar
(
cfg
,
1
,
1
);
check_get_multivar
_foreach
(
cfg
,
1
,
1
);
/* drop other file with match */
/* drop other file with match */
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config3"
,
GIT_CONFIG_LEVEL_SYSTEM
,
1
));
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config3"
,
GIT_CONFIG_LEVEL_SYSTEM
,
1
));
check_get_multivar
(
cfg
,
0
,
0
);
check_get_multivar
_foreach
(
cfg
,
0
,
0
);
/* reload original file (add different place in order) */
/* reload original file (add different place in order) */
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config11"
,
GIT_CONFIG_LEVEL_SYSTEM
,
1
));
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
"config/config11"
,
GIT_CONFIG_LEVEL_SYSTEM
,
1
));
check_get_multivar
(
cfg
,
2
,
1
);
check_get_multivar_foreach
(
cfg
,
2
,
1
);
check_get_multivar
(
cfg
,
2
);
git_config_free
(
cfg
);
git_config_free
(
cfg
);
}
}
...
@@ -113,12 +131,12 @@ void test_config_multivar__add(void)
...
@@ -113,12 +131,12 @@ void test_config_multivar__add(void)
cl_git_pass
(
git_config_set_multivar
(
cfg
,
_name
,
"nonexistant"
,
"git://git.otherplace.org/libgit2"
));
cl_git_pass
(
git_config_set_multivar
(
cfg
,
_name
,
"nonexistant"
,
"git://git.otherplace.org/libgit2"
));
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_assert
(
n
==
3
);
cl_assert
_equal_i
(
n
,
3
);
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
"otherplace"
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
"otherplace"
,
cb
,
&
n
));
cl_assert
(
n
==
1
);
cl_assert
_equal_i
(
n
,
1
);
git_config_free
(
cfg
);
git_config_free
(
cfg
);
...
@@ -127,12 +145,12 @@ void test_config_multivar__add(void)
...
@@ -127,12 +145,12 @@ void test_config_multivar__add(void)
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_assert
(
n
==
3
);
cl_assert
_equal_i
(
n
,
3
);
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
"otherplace"
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
"otherplace"
,
cb
,
&
n
));
cl_assert
(
n
==
1
);
cl_assert
_equal_i
(
n
,
1
);
git_config_free
(
cfg
);
git_config_free
(
cfg
);
}
}
...
@@ -147,8 +165,8 @@ void test_config_multivar__add_new(void)
...
@@ -147,8 +165,8 @@ void test_config_multivar__add_new(void)
cl_git_pass
(
git_config_set_multivar
(
cfg
,
var
,
""
,
"variable"
));
cl_git_pass
(
git_config_set_multivar
(
cfg
,
var
,
""
,
"variable"
));
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
var
,
NULL
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
var
,
NULL
,
cb
,
&
n
));
cl_assert
(
n
==
1
);
cl_assert
_equal_i
(
n
,
1
);
git_config_free
(
cfg
);
git_config_free
(
cfg
);
}
}
...
@@ -161,13 +179,13 @@ void test_config_multivar__replace(void)
...
@@ -161,13 +179,13 @@ void test_config_multivar__replace(void)
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_assert
(
n
==
2
);
cl_assert
(
n
==
2
);
cl_git_pass
(
git_config_set_multivar
(
cfg
,
_name
,
"github"
,
"git://git.otherplace.org/libgit2"
));
cl_git_pass
(
git_config_set_multivar
(
cfg
,
_name
,
"github"
,
"git://git.otherplace.org/libgit2"
));
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_assert
(
n
==
2
);
cl_assert
(
n
==
2
);
git_config_free
(
cfg
);
git_config_free
(
cfg
);
...
@@ -175,7 +193,7 @@ void test_config_multivar__replace(void)
...
@@ -175,7 +193,7 @@ void test_config_multivar__replace(void)
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
NULL
,
cb
,
&
n
));
cl_assert
(
n
==
2
);
cl_assert
(
n
==
2
);
git_config_free
(
cfg
);
git_config_free
(
cfg
);
...
@@ -190,16 +208,16 @@ void test_config_multivar__replace_multiple(void)
...
@@ -190,16 +208,16 @@ void test_config_multivar__replace_multiple(void)
cl_git_pass
(
git_config_set_multivar
(
cfg
,
_name
,
"git://"
,
"git://git.otherplace.org/libgit2"
));
cl_git_pass
(
git_config_set_multivar
(
cfg
,
_name
,
"git://"
,
"git://git.otherplace.org/libgit2"
));
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
"otherplace"
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
"otherplace"
,
cb
,
&
n
));
cl_assert
(
n
==
2
);
cl_assert
_equal_i
(
n
,
2
);
git_config_free
(
cfg
);
git_config_free
(
cfg
);
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"config/config11"
));
n
=
0
;
n
=
0
;
cl_git_pass
(
git_config_get_multivar
(
cfg
,
_name
,
"otherplace"
,
cb
,
&
n
));
cl_git_pass
(
git_config_get_multivar
_foreach
(
cfg
,
_name
,
"otherplace"
,
cb
,
&
n
));
cl_assert
(
n
==
2
);
cl_assert
_equal_i
(
n
,
2
);
git_config_free
(
cfg
);
git_config_free
(
cfg
);
}
}
tests-clar/config/read.c
View file @
b8b22d77
...
@@ -245,6 +245,37 @@ void test_config_read__foreach(void)
...
@@ -245,6 +245,37 @@ void test_config_read__foreach(void)
git_config_free
(
cfg
);
git_config_free
(
cfg
);
}
}
void
test_config_read__iterator
(
void
)
{
git_config
*
cfg
;
git_config_iterator
*
iter
;
git_config_entry
*
entry
;
int
count
,
ret
;
cl_git_pass
(
git_config_new
(
&
cfg
));
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
cl_fixture
(
"config/config9"
),
GIT_CONFIG_LEVEL_SYSTEM
,
0
));
cl_git_pass
(
git_config_add_file_ondisk
(
cfg
,
cl_fixture
(
"config/config15"
),
GIT_CONFIG_LEVEL_GLOBAL
,
0
));
count
=
0
;
cl_git_pass
(
git_config_iterator_new
(
&
iter
,
cfg
));
while
((
ret
=
git_config_next
(
&
entry
,
iter
))
==
0
)
{
count
++
;
}
git_config_iterator_free
(
iter
);
cl_assert_equal_i
(
GIT_ITEROVER
,
ret
);
cl_assert_equal_i
(
7
,
count
);
count
=
3
;
cl_git_pass
(
git_config_iterator_new
(
&
iter
,
cfg
));
git_config_iterator_free
(
iter
);
git_config_free
(
cfg
);
}
static
int
count_cfg_entries
(
const
git_config_entry
*
entry
,
void
*
payload
)
static
int
count_cfg_entries
(
const
git_config_entry
*
entry
,
void
*
payload
)
{
{
int
*
count
=
payload
;
int
*
count
=
payload
;
...
@@ -288,6 +319,38 @@ void test_config_read__foreach_match(void)
...
@@ -288,6 +319,38 @@ void test_config_read__foreach_match(void)
git_config_free
(
cfg
);
git_config_free
(
cfg
);
}
}
static
void
check_glob_iter
(
git_config
*
cfg
,
const
char
*
regexp
,
int
expected
)
{
git_config_iterator
*
iter
;
git_config_entry
*
entry
;
int
count
,
error
;
cl_git_pass
(
git_config_iterator_glob_new
(
&
iter
,
cfg
,
regexp
));
count
=
0
;
while
((
error
=
git_config_next
(
&
entry
,
iter
))
==
0
)
count
++
;
cl_assert_equal_i
(
GIT_ITEROVER
,
error
);
cl_assert_equal_i
(
expected
,
count
);
git_config_iterator_free
(
iter
);
}
void
test_config_read__iterator_glob
(
void
)
{
git_config
*
cfg
;
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
cl_fixture
(
"config/config9"
)));
check_glob_iter
(
cfg
,
"core.*"
,
3
);
check_glob_iter
(
cfg
,
"remote
\\
.ab.*"
,
2
);
check_glob_iter
(
cfg
,
".*url$"
,
2
);
check_glob_iter
(
cfg
,
".*dummy.*"
,
2
);
check_glob_iter
(
cfg
,
".*nomatch.*"
,
0
);
git_config_free
(
cfg
);
}
void
test_config_read__whitespace_not_required_around_assignment
(
void
)
void
test_config_read__whitespace_not_required_around_assignment
(
void
)
{
{
git_config
*
cfg
;
git_config
*
cfg
;
...
...
tests-clar/config/validkeyname.c
View file @
b8b22d77
...
@@ -28,7 +28,7 @@ static void assert_invalid_config_key_name(const char *name)
...
@@ -28,7 +28,7 @@ static void assert_invalid_config_key_name(const char *name)
GIT_EINVALIDSPEC
);
GIT_EINVALIDSPEC
);
cl_git_fail_with
(
git_config_delete_entry
(
cfg
,
name
),
cl_git_fail_with
(
git_config_delete_entry
(
cfg
,
name
),
GIT_EINVALIDSPEC
);
GIT_EINVALIDSPEC
);
cl_git_fail_with
(
git_config_get_multivar
(
cfg
,
name
,
"*"
,
NULL
,
NULL
),
cl_git_fail_with
(
git_config_get_multivar
_foreach
(
cfg
,
name
,
"*"
,
NULL
,
NULL
),
GIT_EINVALIDSPEC
);
GIT_EINVALIDSPEC
);
cl_git_fail_with
(
git_config_set_multivar
(
cfg
,
name
,
"*"
,
"42"
),
cl_git_fail_with
(
git_config_set_multivar
(
cfg
,
name
,
"*"
,
"42"
),
GIT_EINVALIDSPEC
);
GIT_EINVALIDSPEC
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment