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
5d346c11
Unverified
Commit
5d346c11
authored
Apr 22, 2018
by
Edward Thomson
Committed by
GitHub
Apr 22, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4525 from pks-t/pks/config-iterate-in-order
Configuration entry iteration in order
parents
2b967226
6a15f657
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
182 additions
and
210 deletions
+182
-210
include/git2/config.h
+1
-0
src/config_file.c
+171
-210
tests/config/read.c
+10
-0
No files found.
include/git2/config.h
View file @
5d346c11
...
...
@@ -64,6 +64,7 @@ typedef enum {
typedef
struct
git_config_entry
{
const
char
*
name
;
/**< Name of the entry (normalised) */
const
char
*
value
;
/**< String value of the entry */
unsigned
int
include_depth
;
/**< Depth of includes where this variable was found */
git_config_level_t
level
;
/**< Which config file this was found in */
void
(
*
free
)(
struct
git_config_entry
*
entry
);
/**< Free function for this entry */
void
*
payload
;
/**< Opaque value for the free function. Do not read or write */
...
...
src/config_file.c
View file @
5d346c11
...
...
@@ -23,69 +23,30 @@
#include <sys/types.h>
#include <regex.h>
typedef
struct
c
var_
t
{
struct
c
var_
t
*
next
;
typedef
struct
c
onfig_entry_lis
t
{
struct
c
onfig_entry_lis
t
*
next
;
git_config_entry
*
entry
;
bool
included
;
/* whether this is part of [include] */
}
cvar_t
;
}
config_entry_list
;
typedef
struct
git_config_file_iter
{
git_config_iterator
parent
;
git_strmap_iter
iter
;
cvar_t
*
next_var
;
config_entry_list
*
head
;
}
git_config_file_iter
;
/* Max depth for [include] directives */
#define MAX_INCLUDE_DEPTH 10
#define CVAR_LIST_HEAD(list) ((list)->head)
#define CVAR_LIST_TAIL(list) ((list)->tail)
#define CVAR_LIST_NEXT(var) ((var)->next)
#define CVAR_LIST_EMPTY(list) ((list)->head == NULL)
#define CVAR_LIST_APPEND(list, var) do {\
if (CVAR_LIST_EMPTY(list)) {\
CVAR_LIST_HEAD(list) = CVAR_LIST_TAIL(list) = var;\
} else {\
CVAR_LIST_NEXT(CVAR_LIST_TAIL(list)) = var;\
CVAR_LIST_TAIL(list) = var;\
}\
} while(0)
#define CVAR_LIST_REMOVE_HEAD(list) do {\
CVAR_LIST_HEAD(list) = CVAR_LIST_NEXT(CVAR_LIST_HEAD(list));\
} while(0)
#define CVAR_LIST_REMOVE_AFTER(var) do {\
CVAR_LIST_NEXT(var) = CVAR_LIST_NEXT(CVAR_LIST_NEXT(var));\
} while(0)
#define CVAR_LIST_FOREACH(list, iter)\
for ((iter) = CVAR_LIST_HEAD(list);\
(iter) != NULL;\
(iter) = CVAR_LIST_NEXT(iter))
/*
* Inspired by the FreeBSD functions
*/
#define CVAR_LIST_FOREACH_SAFE(start, iter, tmp)\
for ((iter) = CVAR_LIST_HEAD(vars);\
(iter) && (((tmp) = CVAR_LIST_NEXT(iter) || 1));\
(iter) = (tmp))
typedef
struct
{
git_atomic
refcount
;
git_strmap
*
values
;
}
refcounted_strmap
;
git_strmap
*
map
;
config_entry_list
*
list
;
}
diskfile_entries
;
typedef
struct
{
git_config_backend
parent
;
/* mutex to coordinate accessing the values */
git_mutex
values_mutex
;
refcounted_strmap
*
valu
es
;
diskfile_entries
*
entri
es
;
const
git_repository
*
repo
;
git_config_level_t
level
;
}
diskfile_header
;
...
...
@@ -108,7 +69,15 @@ typedef struct {
diskfile_backend
*
snapshot_from
;
}
diskfile_readonly_backend
;
static
int
config_read
(
git_strmap
*
values
,
const
git_repository
*
repo
,
git_config_file
*
file
,
git_config_level_t
level
,
int
depth
);
typedef
struct
{
const
git_repository
*
repo
;
const
char
*
file_path
;
diskfile_entries
*
entries
;
git_config_level_t
level
;
unsigned
int
depth
;
}
diskfile_parse_state
;
static
int
config_read
(
diskfile_entries
*
entries
,
const
git_repository
*
repo
,
git_config_file
*
file
,
git_config_level_t
level
,
int
depth
);
static
int
config_write
(
diskfile_backend
*
cfg
,
const
char
*
orig_key
,
const
char
*
key
,
const
regex_t
*
preg
,
const
char
*
value
);
static
char
*
escape_value
(
const
char
*
ptr
);
...
...
@@ -121,15 +90,20 @@ static int config_error_readonly(void)
return
-
1
;
}
static
void
c
var_free
(
cvar_t
*
var
)
static
void
c
onfig_entry_list_free
(
config_entry_list
*
list
)
{
if
(
var
==
NULL
)
return
;
config_entry_list
*
next
;
git__free
((
char
*
)
var
->
entry
->
name
);
git__free
((
char
*
)
var
->
entry
->
value
);
git__free
(
var
->
entry
);
git__free
(
var
);
while
(
list
!=
NULL
)
{
next
=
list
->
next
;
git__free
((
char
*
)
list
->
entry
->
name
);
git__free
((
char
*
)
list
->
entry
->
value
);
git__free
(
list
->
entry
);
git__free
(
list
);
list
=
next
;
};
}
int
git_config_file_normalize_section
(
char
*
start
,
char
*
end
)
...
...
@@ -155,57 +129,70 @@ int git_config_file_normalize_section(char *start, char *end)
return
0
;
}
static
void
config_entry_list_append
(
config_entry_list
**
list
,
config_entry_list
*
entry
)
{
config_entry_list
*
head
=
*
list
;
if
(
head
)
{
while
(
head
->
next
!=
NULL
)
head
=
head
->
next
;
head
->
next
=
entry
;
}
else
{
*
list
=
entry
;
}
}
/* Add or append the new config option */
static
int
append_entry
(
git_strmap
*
values
,
cvar_t
*
var
)
static
int
diskfile_entries_append
(
diskfile_entries
*
entries
,
git_config_entry
*
entry
)
{
git_strmap_iter
pos
;
c
var_t
*
existing
;
c
onfig_entry_list
*
existing
,
*
var
;
int
error
=
0
;
pos
=
git_strmap_lookup_index
(
values
,
var
->
entry
->
name
);
if
(
!
git_strmap_valid_index
(
values
,
pos
))
{
git_strmap_insert
(
values
,
var
->
entry
->
name
,
var
,
&
error
);
var
=
git__calloc
(
1
,
sizeof
(
config_entry_list
));
GITERR_CHECK_ALLOC
(
var
);
var
->
entry
=
entry
;
pos
=
git_strmap_lookup_index
(
entries
->
map
,
entry
->
name
);
if
(
!
git_strmap_valid_index
(
entries
->
map
,
pos
))
{
git_strmap_insert
(
entries
->
map
,
entry
->
name
,
var
,
&
error
);
if
(
error
>
0
)
error
=
0
;
}
else
{
existing
=
git_strmap_value_at
(
values
,
pos
);
while
(
existing
->
next
!=
NULL
)
{
existing
=
existing
->
next
;
}
existing
->
next
=
var
;
existing
=
git_strmap_value_at
(
entries
->
map
,
pos
);
config_entry_list_append
(
&
existing
,
var
);
}
if
(
error
>
0
)
error
=
0
;
var
=
git__calloc
(
1
,
sizeof
(
config_entry_list
));
GITERR_CHECK_ALLOC
(
var
);
var
->
entry
=
entry
;
config_entry_list_append
(
&
entries
->
list
,
var
);
return
error
;
}
static
void
free_vars
(
git_strmap
*
valu
es
)
static
void
diskfile_entries_free
(
diskfile_entries
*
entri
es
)
{
c
var_t
*
var
=
NULL
;
c
onfig_entry_list
*
list
=
NULL
,
*
next
;
if
(
values
==
NULL
)
if
(
!
entries
)
return
;
git_strmap_foreach_value
(
values
,
var
,
while
(
var
!=
NULL
)
{
cvar_t
*
next
=
CVAR_LIST_NEXT
(
var
);
cvar_free
(
var
);
var
=
next
;
});
git_strmap_free
(
values
);
}
static
void
refcounted_strmap_free
(
refcounted_strmap
*
map
)
{
if
(
!
map
)
if
(
git_atomic_dec
(
&
entries
->
refcount
)
!=
0
)
return
;
if
(
git_atomic_dec
(
&
map
->
refcount
)
!=
0
)
return
;
git_strmap_foreach_value
(
entries
->
map
,
list
,
config_entry_list_free
(
list
));
git_strmap_free
(
entries
->
map
);
list
=
entries
->
list
;
while
(
list
!=
NULL
)
{
next
=
list
->
next
;
git__free
(
list
);
list
=
next
;
}
free_vars
(
map
->
values
);
git__free
(
map
);
git__free
(
entries
);
}
/**
...
...
@@ -213,37 +200,37 @@ static void refcounted_strmap_free(refcounted_strmap *map)
* refcount. This is its own function to make sure we use the mutex to
* avoid the map pointer from changing under us.
*/
static
refcounted_strmap
*
refcounted_strmap
_take
(
diskfile_header
*
h
)
static
diskfile_entries
*
diskfile_entries
_take
(
diskfile_header
*
h
)
{
refcounted_strmap
*
map
;
diskfile_entries
*
entries
;
if
(
git_mutex_lock
(
&
h
->
values_mutex
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"failed to lock config backend"
);
return
NULL
;
}
map
=
h
->
valu
es
;
git_atomic_inc
(
&
map
->
refcount
);
entries
=
h
->
entri
es
;
git_atomic_inc
(
&
entries
->
refcount
);
git_mutex_unlock
(
&
h
->
values_mutex
);
return
map
;
return
entries
;
}
static
int
refcounted_strmap_alloc
(
refcounted_strmap
**
out
)
static
int
diskfile_entries_alloc
(
diskfile_entries
**
out
)
{
refcounted_strmap
*
map
;
diskfile_entries
*
entries
;
int
error
;
map
=
git__calloc
(
1
,
sizeof
(
refcounted_strmap
));
GITERR_CHECK_ALLOC
(
map
);
entries
=
git__calloc
(
1
,
sizeof
(
diskfile_entries
));
GITERR_CHECK_ALLOC
(
entries
);
git_atomic_set
(
&
map
->
refcount
,
1
);
git_atomic_set
(
&
entries
->
refcount
,
1
);
if
((
error
=
git_strmap_alloc
(
&
map
->
values
))
<
0
)
git__free
(
map
);
if
((
error
=
git_strmap_alloc
(
&
entries
->
map
))
<
0
)
git__free
(
entries
);
else
*
out
=
map
;
*
out
=
entries
;
return
error
;
}
...
...
@@ -272,15 +259,15 @@ static int config_open(git_config_backend *cfg, git_config_level_t level, const
b
->
header
.
level
=
level
;
b
->
header
.
repo
=
repo
;
if
((
res
=
refcounted_strmap_alloc
(
&
b
->
header
.
valu
es
))
<
0
)
if
((
res
=
diskfile_entries_alloc
(
&
b
->
header
.
entri
es
))
<
0
)
return
res
;
if
(
!
git_path_exists
(
b
->
file
.
path
))
return
0
;
if
(
res
<
0
||
(
res
=
config_read
(
b
->
header
.
values
->
valu
es
,
repo
,
&
b
->
file
,
level
,
0
))
<
0
)
{
refcounted_strmap_free
(
b
->
header
.
valu
es
);
b
->
header
.
valu
es
=
NULL
;
if
(
res
<
0
||
(
res
=
config_read
(
b
->
header
.
entri
es
,
repo
,
&
b
->
file
,
level
,
0
))
<
0
)
{
diskfile_entries_free
(
b
->
header
.
entri
es
);
b
->
header
.
entri
es
=
NULL
;
}
return
res
;
...
...
@@ -321,7 +308,7 @@ out:
static
int
config_refresh
(
git_config_backend
*
cfg
)
{
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
refcounted_strmap
*
valu
es
=
NULL
,
*
tmp
;
diskfile_entries
*
entri
es
=
NULL
,
*
tmp
;
git_config_file
*
include
;
int
error
,
modified
;
uint32_t
i
;
...
...
@@ -336,7 +323,7 @@ static int config_refresh(git_config_backend *cfg)
if
(
!
modified
)
return
0
;
if
((
error
=
refcounted_strmap_alloc
(
&
valu
es
))
<
0
)
if
((
error
=
diskfile_entries_alloc
(
&
entri
es
))
<
0
)
goto
out
;
/* Reparse the current configuration */
...
...
@@ -345,7 +332,7 @@ static int config_refresh(git_config_backend *cfg)
}
git_array_clear
(
b
->
file
.
includes
);
if
((
error
=
config_read
(
values
->
valu
es
,
b
->
header
.
repo
,
&
b
->
file
,
b
->
header
.
level
,
0
))
<
0
)
if
((
error
=
config_read
(
entri
es
,
b
->
header
.
repo
,
&
b
->
file
,
b
->
header
.
level
,
0
))
<
0
)
goto
out
;
if
((
error
=
git_mutex_lock
(
&
b
->
header
.
values_mutex
))
<
0
)
{
...
...
@@ -353,14 +340,14 @@ static int config_refresh(git_config_backend *cfg)
goto
out
;
}
tmp
=
b
->
header
.
valu
es
;
b
->
header
.
values
=
valu
es
;
valu
es
=
tmp
;
tmp
=
b
->
header
.
entri
es
;
b
->
header
.
entries
=
entri
es
;
entri
es
=
tmp
;
git_mutex_unlock
(
&
b
->
header
.
values_mutex
);
out:
refcounted_strmap_free
(
valu
es
);
diskfile_entries_free
(
entri
es
);
return
(
error
==
GIT_ENOTFOUND
)
?
0
:
error
;
}
...
...
@@ -373,7 +360,7 @@ static void backend_free(git_config_backend *_backend)
return
;
config_file_clear
(
&
backend
->
file
);
refcounted_strmap_free
(
backend
->
header
.
valu
es
);
diskfile_entries_free
(
backend
->
header
.
entri
es
);
git_mutex_free
(
&
backend
->
header
.
values_mutex
);
git__free
(
backend
);
}
...
...
@@ -390,24 +377,12 @@ static int config_iterator_next(
git_config_iterator
*
iter
)
{
git_config_file_iter
*
it
=
(
git_config_file_iter
*
)
iter
;
diskfile_header
*
h
=
(
diskfile_header
*
)
it
->
parent
.
backend
;
git_strmap
*
values
=
h
->
values
->
values
;
int
err
=
0
;
cvar_t
*
var
;
if
(
it
->
next_var
==
NULL
)
{
err
=
git_strmap_next
((
void
**
)
&
var
,
&
(
it
->
iter
),
values
);
}
else
{
var
=
it
->
next_var
;
}
if
(
err
<
0
)
{
it
->
next_var
=
NULL
;
return
err
;
}
if
(
!
it
->
head
)
return
GIT_ITEROVER
;
*
entry
=
var
->
entry
;
it
->
next_var
=
CVAR_LIST_NEXT
(
var
)
;
*
entry
=
it
->
head
->
entry
;
it
->
head
=
it
->
head
->
next
;
return
0
;
}
...
...
@@ -433,15 +408,11 @@ static int config_iterator_new(
h
=
(
diskfile_header
*
)
snapshot
;
/* strmap_begin() is currently a macro returning 0 */
GIT_UNUSED
(
h
);
it
->
parent
.
backend
=
snapshot
;
it
->
iter
=
git_strmap_begin
(
h
->
values
);
it
->
next_var
=
NULL
;
it
->
head
=
h
->
entries
->
list
;
it
->
parent
.
next
=
config_iterator_next
;
it
->
parent
.
free
=
config_iterator_free
;
*
iter
=
(
git_config_iterator
*
)
it
;
return
0
;
...
...
@@ -450,8 +421,8 @@ static int config_iterator_new(
static
int
config_set
(
git_config_backend
*
cfg
,
const
char
*
name
,
const
char
*
value
)
{
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
refcounted_strmap
*
map
;
git_strmap
*
values
;
diskfile_entries
*
entries
;
git_strmap
*
entry_map
;
char
*
key
,
*
esc_value
=
NULL
;
khiter_t
pos
;
int
rval
,
ret
;
...
...
@@ -459,17 +430,17 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
if
((
rval
=
git_config__normalize_name
(
name
,
&
key
))
<
0
)
return
rval
;
if
((
map
=
refcounted_strmap
_take
(
&
b
->
header
))
==
NULL
)
if
((
entries
=
diskfile_entries
_take
(
&
b
->
header
))
==
NULL
)
return
-
1
;
values
=
map
->
values
;
entry_map
=
entries
->
map
;
/*
* Try to find it in the existing values and update it if it
* only has one value.
*/
pos
=
git_strmap_lookup_index
(
values
,
key
);
if
(
git_strmap_valid_index
(
values
,
pos
))
{
c
var_t
*
existing
=
git_strmap_value_at
(
values
,
pos
);
pos
=
git_strmap_lookup_index
(
entry_map
,
key
);
if
(
git_strmap_valid_index
(
entry_map
,
pos
))
{
c
onfig_entry_list
*
existing
=
git_strmap_value_at
(
entry_map
,
pos
);
if
(
existing
->
next
!=
NULL
)
{
giterr_set
(
GITERR_CONFIG
,
"multivar incompatible with simple set"
);
...
...
@@ -477,7 +448,7 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
goto
out
;
}
if
(
existing
->
included
)
{
if
(
existing
->
entry
->
include_depth
)
{
giterr_set
(
GITERR_CONFIG
,
"modifying included variable is not supported"
);
ret
=
-
1
;
goto
out
;
...
...
@@ -505,17 +476,17 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
ret
=
config_refresh
(
cfg
);
out:
refcounted_strmap_free
(
map
);
diskfile_entries_free
(
entries
);
git__free
(
esc_value
);
git__free
(
key
);
return
ret
;
}
/* release the map containing the entry as an equivalent to freeing it */
static
void
release_map
(
git_config_entry
*
entry
)
static
void
free_diskfile_entry
(
git_config_entry
*
entry
)
{
refcounted_strmap
*
map
=
(
refcounted_strmap
*
)
entry
->
payload
;
refcounted_strmap
_free
(
map
);
diskfile_entries
*
map
=
(
diskfile_entries
*
)
entry
->
payload
;
diskfile_entries
_free
(
map
);
}
/*
...
...
@@ -524,34 +495,34 @@ static void release_map(git_config_entry *entry)
static
int
config_get
(
git_config_backend
*
cfg
,
const
char
*
key
,
git_config_entry
**
out
)
{
diskfile_header
*
h
=
(
diskfile_header
*
)
cfg
;
refcounted_strmap
*
map
;
git_strmap
*
values
;
diskfile_entries
*
entries
;
git_strmap
*
entry_map
;
khiter_t
pos
;
c
var_
t
*
var
;
c
onfig_entry_lis
t
*
var
;
int
error
=
0
;
if
(
!
h
->
parent
.
readonly
&&
((
error
=
config_refresh
(
cfg
))
<
0
))
return
error
;
if
((
map
=
refcounted_strmap
_take
(
h
))
==
NULL
)
if
((
entries
=
diskfile_entries
_take
(
h
))
==
NULL
)
return
-
1
;
values
=
map
->
values
;
entry_map
=
entries
->
map
;
pos
=
git_strmap_lookup_index
(
values
,
key
);
pos
=
git_strmap_lookup_index
(
entry_map
,
key
);
/* no error message; the config system will write one */
if
(
!
git_strmap_valid_index
(
values
,
pos
))
{
refcounted_strmap_free
(
map
);
if
(
!
git_strmap_valid_index
(
entry_map
,
pos
))
{
diskfile_entries_free
(
entries
);
return
GIT_ENOTFOUND
;
}
var
=
git_strmap_value_at
(
values
,
pos
);
var
=
git_strmap_value_at
(
entry_map
,
pos
);
while
(
var
->
next
)
var
=
var
->
next
;
*
out
=
var
->
entry
;
(
*
out
)
->
free
=
release_map
;
(
*
out
)
->
payload
=
map
;
(
*
out
)
->
free
=
free_diskfile_entry
;
(
*
out
)
->
payload
=
entries
;
return
error
;
}
...
...
@@ -591,9 +562,10 @@ out:
static
int
config_delete
(
git_config_backend
*
cfg
,
const
char
*
name
)
{
c
var_
t
*
var
;
c
onfig_entry_lis
t
*
var
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
refcounted_strmap
*
map
;
git_strmap
*
values
;
diskfile_entries
*
map
;
git_strmap
*
entry_map
;
char
*
key
;
int
result
;
khiter_t
pos
;
...
...
@@ -601,23 +573,23 @@ static int config_delete(git_config_backend *cfg, const char *name)
if
((
result
=
git_config__normalize_name
(
name
,
&
key
))
<
0
)
return
result
;
if
((
map
=
refcounted_strmap
_take
(
&
b
->
header
))
==
NULL
)
if
((
map
=
diskfile_entries
_take
(
&
b
->
header
))
==
NULL
)
return
-
1
;
values
=
b
->
header
.
values
->
values
;
entry_map
=
b
->
header
.
entries
->
map
;
pos
=
git_strmap_lookup_index
(
values
,
key
);
pos
=
git_strmap_lookup_index
(
entry_map
,
key
);
git__free
(
key
);
if
(
!
git_strmap_valid_index
(
values
,
pos
))
{
refcounted_strmap
_free
(
map
);
if
(
!
git_strmap_valid_index
(
entry_map
,
pos
))
{
diskfile_entries
_free
(
map
);
giterr_set
(
GITERR_CONFIG
,
"could not find key '%s' to delete"
,
name
);
return
GIT_ENOTFOUND
;
}
var
=
git_strmap_value_at
(
values
,
pos
);
refcounted_strmap
_free
(
map
);
var
=
git_strmap_value_at
(
entry_map
,
pos
);
diskfile_entries
_free
(
map
);
if
(
var
->
included
)
{
if
(
var
->
entry
->
include_depth
)
{
giterr_set
(
GITERR_CONFIG
,
"cannot delete included variable"
);
return
-
1
;
}
...
...
@@ -636,8 +608,8 @@ static int config_delete(git_config_backend *cfg, const char *name)
static
int
config_delete_multivar
(
git_config_backend
*
cfg
,
const
char
*
name
,
const
char
*
regexp
)
{
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
refcounted_strmap
*
map
;
git_strmap
*
values
;
diskfile_entries
*
map
;
git_strmap
*
entry_map
;
char
*
key
;
regex_t
preg
;
int
result
;
...
...
@@ -646,20 +618,20 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con
if
((
result
=
git_config__normalize_name
(
name
,
&
key
))
<
0
)
return
result
;
if
((
map
=
refcounted_strmap
_take
(
&
b
->
header
))
==
NULL
)
if
((
map
=
diskfile_entries
_take
(
&
b
->
header
))
==
NULL
)
return
-
1
;
values
=
b
->
header
.
values
->
values
;
entry_map
=
b
->
header
.
entries
->
map
;
pos
=
git_strmap_lookup_index
(
values
,
key
);
pos
=
git_strmap_lookup_index
(
entry_map
,
key
);
if
(
!
git_strmap_valid_index
(
values
,
pos
))
{
refcounted_strmap
_free
(
map
);
if
(
!
git_strmap_valid_index
(
entry_map
,
pos
))
{
diskfile_entries
_free
(
map
);
git__free
(
key
);
giterr_set
(
GITERR_CONFIG
,
"could not find key '%s' to delete"
,
name
);
return
GIT_ENOTFOUND
;
}
refcounted_strmap
_free
(
map
);
diskfile_entries
_free
(
map
);
result
=
p_regcomp
(
&
preg
,
regexp
,
REG_EXTENDED
);
if
(
result
!=
0
)
{
...
...
@@ -812,7 +784,7 @@ static void backend_readonly_free(git_config_backend *_backend)
if
(
backend
==
NULL
)
return
;
refcounted_strmap_free
(
backend
->
header
.
valu
es
);
diskfile_entries_free
(
backend
->
header
.
entri
es
);
git_mutex_free
(
&
backend
->
header
.
values_mutex
);
git__free
(
backend
);
}
...
...
@@ -822,7 +794,7 @@ static int config_readonly_open(git_config_backend *cfg, git_config_level_t leve
diskfile_readonly_backend
*
b
=
(
diskfile_readonly_backend
*
)
cfg
;
diskfile_backend
*
src
=
b
->
snapshot_from
;
diskfile_header
*
src_header
=
&
src
->
header
;
refcounted_strmap
*
src_map
;
diskfile_entries
*
entries
;
int
error
;
if
(
!
src_header
->
parent
.
readonly
&&
(
error
=
config_refresh
(
&
src_header
->
parent
))
<
0
)
...
...
@@ -832,9 +804,9 @@ static int config_readonly_open(git_config_backend *cfg, git_config_level_t leve
GIT_UNUSED
(
level
);
GIT_UNUSED
(
repo
);
if
((
src_map
=
refcounted_strmap
_take
(
src_header
))
==
NULL
)
if
((
entries
=
diskfile_entries
_take
(
src_header
))
==
NULL
)
return
-
1
;
b
->
header
.
values
=
src_map
;
b
->
header
.
entries
=
entries
;
return
0
;
}
...
...
@@ -912,16 +884,8 @@ static char *escape_value(const char *ptr)
return
git_buf_detach
(
&
buf
);
}
struct
parse_data
{
const
git_repository
*
repo
;
const
char
*
file_path
;
git_strmap
*
values
;
git_config_level_t
level
;
int
depth
;
};
static
int
parse_include
(
git_config_parser
*
reader
,
struct
parse_data
*
parse_data
,
const
char
*
file
)
diskfile_parse_state
*
parse_data
,
const
char
*
file
)
{
struct
config_file
*
include
;
git_buf
path
=
GIT_BUF_INIT
;
...
...
@@ -943,7 +907,7 @@ static int parse_include(git_config_parser *reader,
git_array_init
(
include
->
includes
);
include
->
path
=
git_buf_detach
(
&
path
);
result
=
config_read
(
parse_data
->
valu
es
,
parse_data
->
repo
,
result
=
config_read
(
parse_data
->
entri
es
,
parse_data
->
repo
,
include
,
parse_data
->
level
,
parse_data
->
depth
+
1
);
if
(
result
==
GIT_ENOTFOUND
)
{
...
...
@@ -1023,7 +987,7 @@ static const struct {
};
static
int
parse_conditional_include
(
git_config_parser
*
reader
,
struct
parse_data
*
parse_data
,
const
char
*
section
,
const
char
*
file
)
diskfile_parse_state
*
parse_data
,
const
char
*
section
,
const
char
*
file
)
{
char
*
condition
;
size_t
i
;
...
...
@@ -1064,9 +1028,9 @@ static int read_on_variable(
size_t
line_len
,
void
*
data
)
{
struct
parse_data
*
parse_data
=
(
struct
parse_data
*
)
data
;
diskfile_parse_state
*
parse_data
=
(
diskfile_parse_state
*
)
data
;
git_buf
buf
=
GIT_BUF_INIT
;
cvar_t
*
var
;
git_config_entry
*
entry
;
int
result
=
0
;
GIT_UNUSED
(
line
);
...
...
@@ -1081,41 +1045,38 @@ static int read_on_variable(
return
-
1
;
}
var
=
git__calloc
(
1
,
sizeof
(
cvar_t
));
GITERR_CHECK_ALLOC
(
var
);
var
->
entry
=
git__calloc
(
1
,
sizeof
(
git_config_entry
));
GITERR_CHECK_ALLOC
(
var
->
entry
);
var
->
entry
->
name
=
git_buf_detach
(
&
buf
);
var
->
entry
->
value
=
var_value
;
var
->
entry
->
level
=
parse_data
->
level
;
var
->
included
=
!!
parse_data
->
depth
;
entry
=
git__calloc
(
1
,
sizeof
(
git_config_entry
));
GITERR_CHECK_ALLOC
(
entry
);
entry
->
name
=
git_buf_detach
(
&
buf
);
entry
->
value
=
var_value
;
entry
->
level
=
parse_data
->
level
;
entry
->
include_depth
=
parse_data
->
depth
;
if
((
result
=
append_entry
(
parse_data
->
values
,
var
))
<
0
)
if
((
result
=
diskfile_entries_append
(
parse_data
->
entries
,
entry
))
<
0
)
return
result
;
result
=
0
;
/* Add or append the new config option */
if
(
!
git__strcmp
(
var
->
entry
->
name
,
"include.path"
))
result
=
parse_include
(
reader
,
parse_data
,
var
->
entry
->
value
);
else
if
(
!
git__prefixcmp
(
var
->
entry
->
name
,
"includeif."
)
&&
!
git__suffixcmp
(
var
->
entry
->
name
,
".path"
))
if
(
!
git__strcmp
(
entry
->
name
,
"include.path"
))
result
=
parse_include
(
reader
,
parse_data
,
entry
->
value
);
else
if
(
!
git__prefixcmp
(
entry
->
name
,
"includeif."
)
&&
!
git__suffixcmp
(
entry
->
name
,
".path"
))
result
=
parse_conditional_include
(
reader
,
parse_data
,
var
->
entry
->
name
,
var
->
entry
->
value
);
entry
->
name
,
entry
->
value
);
return
result
;
}
static
int
config_read
(
git_strmap
*
valu
es
,
diskfile_entries
*
entri
es
,
const
git_repository
*
repo
,
git_config_file
*
file
,
git_config_level_t
level
,
int
depth
)
{
struct
parse_data
parse_data
;
diskfile_parse_state
parse_data
;
git_config_parser
reader
;
git_buf
contents
=
GIT_BUF_INIT
;
int
error
;
...
...
@@ -1143,7 +1104,7 @@ static int config_read(
parse_data
.
repo
=
repo
;
parse_data
.
file_path
=
file
->
path
;
parse_data
.
values
=
valu
es
;
parse_data
.
entries
=
entri
es
;
parse_data
.
level
=
level
;
parse_data
.
depth
=
depth
;
...
...
tests/config/read.c
View file @
5d346c11
...
...
@@ -306,6 +306,15 @@ void test_config_read__foreach(void)
void
test_config_read__iterator
(
void
)
{
const
char
*
keys
[]
=
{
"core.dummy2"
,
"core.verylong"
,
"core.dummy"
,
"remote.ab.url"
,
"remote.abba.url"
,
"core.dummy2"
,
"core.global"
};
git_config
*
cfg
;
git_config_iterator
*
iter
;
git_config_entry
*
entry
;
...
...
@@ -321,6 +330,7 @@ void test_config_read__iterator(void)
cl_git_pass
(
git_config_iterator_new
(
&
iter
,
cfg
));
while
((
ret
=
git_config_next
(
&
entry
,
iter
))
==
0
)
{
cl_assert_equal_s
(
entry
->
name
,
keys
[
count
]);
count
++
;
}
...
...
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