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