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
e0568621
Commit
e0568621
authored
Jul 19, 2017
by
Edward Thomson
Committed by
GitHub
Jul 19, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4250 from pks-t/pks/config-file-iteration
Configuration file fixes with includes
parents
a94a5402
1b329089
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
208 additions
and
172 deletions
+208
-172
src/config_file.c
+153
-130
tests/config/include.c
+55
-42
No files found.
src/config_file.c
View file @
e0568621
...
@@ -74,9 +74,14 @@ typedef struct git_config_file_iter {
...
@@ -74,9 +74,14 @@ typedef struct git_config_file_iter {
(iter) && (((tmp) = CVAR_LIST_NEXT(iter) || 1));\
(iter) && (((tmp) = CVAR_LIST_NEXT(iter) || 1));\
(iter) = (tmp))
(iter) = (tmp))
struct
reader
{
struct
config_file
{
git_oid
checksum
;
git_oid
checksum
;
char
*
file_path
;
char
*
path
;
git_array_t
(
struct
config_file
)
includes
;
};
struct
reader
{
struct
config_file
*
file
;
git_buf
buffer
;
git_buf
buffer
;
char
*
read_ptr
;
char
*
read_ptr
;
int
line_number
;
int
line_number
;
...
@@ -100,13 +105,11 @@ typedef struct {
...
@@ -100,13 +105,11 @@ typedef struct {
git_config_level_t
level
;
git_config_level_t
level
;
git_array_t
(
struct
reader
)
readers
;
bool
locked
;
bool
locked
;
git_filebuf
locked_buf
;
git_filebuf
locked_buf
;
git_buf
locked_content
;
git_buf
locked_content
;
char
*
file_path
;
struct
config_file
file
;
}
diskfile_backend
;
}
diskfile_backend
;
typedef
struct
{
typedef
struct
{
...
@@ -115,7 +118,7 @@ typedef struct {
...
@@ -115,7 +118,7 @@ typedef struct {
diskfile_backend
*
snapshot_from
;
diskfile_backend
*
snapshot_from
;
}
diskfile_readonly_backend
;
}
diskfile_readonly_backend
;
static
int
config_read
(
git_strmap
*
values
,
diskfile_backend
*
cfg_file
,
struct
reader
*
reader
,
git_config_level_t
level
,
int
depth
);
static
int
config_read
(
git_strmap
*
values
,
struct
config_file
*
file
,
git_config_level_t
level
,
int
depth
);
static
int
config_write
(
diskfile_backend
*
cfg
,
const
char
*
key
,
const
regex_t
*
preg
,
const
char
*
value
);
static
int
config_write
(
diskfile_backend
*
cfg
,
const
char
*
key
,
const
regex_t
*
preg
,
const
char
*
value
);
static
char
*
escape_value
(
const
char
*
ptr
);
static
char
*
escape_value
(
const
char
*
ptr
);
...
@@ -125,7 +128,7 @@ static int config_snapshot(git_config_backend **out, git_config_backend *in);
...
@@ -125,7 +128,7 @@ static int config_snapshot(git_config_backend **out, git_config_backend *in);
static
void
set_parse_error
(
struct
reader
*
reader
,
int
col
,
const
char
*
error_str
)
static
void
set_parse_error
(
struct
reader
*
reader
,
int
col
,
const
char
*
error_str
)
{
{
giterr_set
(
GITERR_CONFIG
,
"failed to parse config file: %s (in %s:%d, column %d)"
,
giterr_set
(
GITERR_CONFIG
,
"failed to parse config file: %s (in %s:%d, column %d)"
,
error_str
,
reader
->
file
_
path
,
reader
->
line_number
,
col
);
error_str
,
reader
->
file
->
path
,
reader
->
line_number
,
col
);
}
}
static
int
config_error_readonly
(
void
)
static
int
config_error_readonly
(
void
)
...
@@ -261,10 +264,25 @@ static int refcounted_strmap_alloc(refcounted_strmap **out)
...
@@ -261,10 +264,25 @@ static int refcounted_strmap_alloc(refcounted_strmap **out)
return
error
;
return
error
;
}
}
static
void
config_file_clear
(
struct
config_file
*
file
)
{
struct
config_file
*
include
;
uint32_t
i
;
if
(
file
==
NULL
)
return
;
git_array_foreach
(
file
->
includes
,
i
,
include
)
{
config_file_clear
(
include
);
}
git_array_clear
(
file
->
includes
);
git__free
(
file
->
path
);
}
static
int
config_open
(
git_config_backend
*
cfg
,
git_config_level_t
level
)
static
int
config_open
(
git_config_backend
*
cfg
,
git_config_level_t
level
)
{
{
int
res
;
int
res
;
struct
reader
*
reader
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
b
->
level
=
level
;
b
->
level
=
level
;
...
@@ -272,51 +290,75 @@ static int config_open(git_config_backend *cfg, git_config_level_t level)
...
@@ -272,51 +290,75 @@ static int config_open(git_config_backend *cfg, git_config_level_t level)
if
((
res
=
refcounted_strmap_alloc
(
&
b
->
header
.
values
))
<
0
)
if
((
res
=
refcounted_strmap_alloc
(
&
b
->
header
.
values
))
<
0
)
return
res
;
return
res
;
git_array_init
(
b
->
readers
);
/* It's fine if the file doesn't exist */
reader
=
git_array_alloc
(
b
->
readers
);
if
(
!
git_path_exists
(
b
->
file
.
path
))
if
(
!
reader
)
{
return
0
;
if
(
res
<
0
||
(
res
=
config_read
(
b
->
header
.
values
->
values
,
&
b
->
file
,
level
,
0
))
<
0
)
{
refcounted_strmap_free
(
b
->
header
.
values
);
refcounted_strmap_free
(
b
->
header
.
values
);
return
-
1
;
b
->
header
.
values
=
NULL
;
}
}
memset
(
reader
,
0
,
sizeof
(
struct
reader
));
reader
->
file_path
=
git__strdup
(
b
->
file_path
);
return
res
;
GITERR_CHECK_ALLOC
(
reader
->
file_path
);
}
static
int
config_is_modified
(
int
*
modified
,
struct
config_file
*
file
)
{
struct
config_file
*
include
;
git_buf
buf
=
GIT_BUF_INIT
;
git_oid
hash
;
uint32_t
i
;
int
error
;
*
modified
=
0
;
git_buf_init
(
&
reader
->
buffer
,
0
);
if
((
error
=
git_futils_readbuffer
(
&
buf
,
file
->
path
))
<
0
)
res
=
git_futils_readbuffer_updated
(
goto
out
;
&
reader
->
buffer
,
b
->
file_path
,
&
reader
->
checksum
,
NULL
);
/* It's fine if the file doesn't exist */
if
((
error
=
git_hash_buf
(
&
hash
,
buf
.
ptr
,
buf
.
size
))
<
0
)
if
(
res
==
GIT_ENOTFOUND
)
goto
out
;
return
0
;
if
(
res
<
0
||
(
res
=
config_read
(
b
->
header
.
values
->
values
,
b
,
reader
,
level
,
0
))
<
0
)
{
if
(
!
git_oid_equal
(
&
hash
,
&
file
->
checksum
))
{
refcounted_strmap_free
(
b
->
header
.
values
);
*
modified
=
1
;
b
->
header
.
values
=
NULL
;
goto
out
;
}
git_array_foreach
(
file
->
includes
,
i
,
include
)
{
if
((
error
=
config_is_modified
(
modified
,
include
))
<
0
||
*
modified
)
goto
out
;
}
}
reader
=
git_array_get
(
b
->
readers
,
0
);
out:
git_buf_free
(
&
reader
->
buffer
);
git_buf_free
(
&
buf
);
return
res
;
return
error
;
}
}
/* The meat of the refresh, as we want to use it in different places */
static
int
config_refresh
(
git_config_backend
*
cfg
)
static
int
config__refresh
(
git_config_backend
*
cfg
)
{
{
refcounted_strmap
*
values
=
NULL
,
*
tmp
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
struct
reader
*
reader
=
NULL
;
refcounted_strmap
*
values
=
NULL
,
*
tmp
;
int
error
=
0
;
struct
config_file
*
include
;
int
error
,
modified
;
uint32_t
i
;
error
=
config_is_modified
(
&
modified
,
&
b
->
file
);
if
(
error
<
0
&&
error
!=
GIT_ENOTFOUND
)
goto
out
;
if
(
!
modified
)
return
0
;
if
((
error
=
refcounted_strmap_alloc
(
&
values
))
<
0
)
if
((
error
=
refcounted_strmap_alloc
(
&
values
))
<
0
)
goto
out
;
goto
out
;
reader
=
git_array_get
(
b
->
readers
,
git_array_size
(
b
->
readers
)
-
1
);
/* Reparse the current configuration */
GITERR_CHECK_ALLOC
(
reader
);
git_array_foreach
(
b
->
file
.
includes
,
i
,
include
)
{
config_file_clear
(
include
);
}
git_array_clear
(
b
->
file
.
includes
);
if
((
error
=
config_read
(
values
->
values
,
b
,
reader
,
b
->
level
,
0
))
<
0
)
if
((
error
=
config_read
(
values
->
values
,
&
b
->
file
,
b
->
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
)
{
...
@@ -332,52 +374,18 @@ static int config__refresh(git_config_backend *cfg)
...
@@ -332,52 +374,18 @@ static int config__refresh(git_config_backend *cfg)
out:
out:
refcounted_strmap_free
(
values
);
refcounted_strmap_free
(
values
);
if
(
reader
)
git_buf_free
(
&
reader
->
buffer
);
return
error
;
}
static
int
config_refresh
(
git_config_backend
*
cfg
)
{
int
error
=
0
,
updated
=
0
,
any_updated
=
0
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
struct
reader
*
reader
=
NULL
;
uint32_t
i
;
for
(
i
=
0
;
i
<
git_array_size
(
b
->
readers
);
i
++
)
{
reader
=
git_array_get
(
b
->
readers
,
i
);
error
=
git_futils_readbuffer_updated
(
&
reader
->
buffer
,
reader
->
file_path
,
&
reader
->
checksum
,
&
updated
);
if
(
error
<
0
&&
error
!=
GIT_ENOTFOUND
)
return
error
;
if
(
updated
)
any_updated
=
1
;
}
if
(
!
any_updated
)
return
(
error
==
GIT_ENOTFOUND
)
?
0
:
error
;
return
(
error
==
GIT_ENOTFOUND
)
?
0
:
error
;
return
config__refresh
(
cfg
);
}
}
static
void
backend_free
(
git_config_backend
*
_backend
)
static
void
backend_free
(
git_config_backend
*
_backend
)
{
{
diskfile_backend
*
backend
=
(
diskfile_backend
*
)
_backend
;
diskfile_backend
*
backend
=
(
diskfile_backend
*
)
_backend
;
uint32_t
i
;
if
(
backend
==
NULL
)
if
(
backend
==
NULL
)
return
;
return
;
for
(
i
=
0
;
i
<
git_array_size
(
backend
->
readers
);
i
++
)
{
config_file_clear
(
&
backend
->
file
);
struct
reader
*
r
=
git_array_get
(
backend
->
readers
,
i
);
git__free
(
r
->
file_path
);
}
git_array_clear
(
backend
->
readers
);
git__free
(
backend
->
file_path
);
refcounted_strmap_free
(
backend
->
header
.
values
);
refcounted_strmap_free
(
backend
->
header
.
values
);
git_mutex_free
(
&
backend
->
header
.
values_mutex
);
git_mutex_free
(
&
backend
->
header
.
values_mutex
);
git__free
(
backend
);
git__free
(
backend
);
...
@@ -482,6 +490,12 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
...
@@ -482,6 +490,12 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
goto
out
;
goto
out
;
}
}
if
(
existing
->
included
)
{
giterr_set
(
GITERR_CONFIG
,
"modifying included variable is not supported"
);
ret
=
-
1
;
goto
out
;
}
/* don't update if old and new values already match */
/* don't update if old and new values already match */
if
((
!
existing
->
entry
->
value
&&
!
value
)
||
if
((
!
existing
->
entry
->
value
&&
!
value
)
||
(
existing
->
entry
->
value
&&
value
&&
(
existing
->
entry
->
value
&&
value
&&
...
@@ -616,6 +630,11 @@ static int config_delete(git_config_backend *cfg, const char *name)
...
@@ -616,6 +630,11 @@ static int config_delete(git_config_backend *cfg, const char *name)
var
=
git_strmap_value_at
(
values
,
pos
);
var
=
git_strmap_value_at
(
values
,
pos
);
refcounted_strmap_free
(
map
);
refcounted_strmap_free
(
map
);
if
(
var
->
included
)
{
giterr_set
(
GITERR_CONFIG
,
"cannot delete included variable"
);
return
-
1
;
}
if
(
var
->
next
!=
NULL
)
{
if
(
var
->
next
!=
NULL
)
{
giterr_set
(
GITERR_CONFIG
,
"cannot delete multivar with a single delete"
);
giterr_set
(
GITERR_CONFIG
,
"cannot delete multivar with a single delete"
);
return
-
1
;
return
-
1
;
...
@@ -685,10 +704,10 @@ static int config_lock(git_config_backend *_cfg)
...
@@ -685,10 +704,10 @@ static int config_lock(git_config_backend *_cfg)
diskfile_backend
*
cfg
=
(
diskfile_backend
*
)
_cfg
;
diskfile_backend
*
cfg
=
(
diskfile_backend
*
)
_cfg
;
int
error
;
int
error
;
if
((
error
=
git_filebuf_open
(
&
cfg
->
locked_buf
,
cfg
->
file
_
path
,
0
,
GIT_CONFIG_FILE_MODE
))
<
0
)
if
((
error
=
git_filebuf_open
(
&
cfg
->
locked_buf
,
cfg
->
file
.
path
,
0
,
GIT_CONFIG_FILE_MODE
))
<
0
)
return
error
;
return
error
;
error
=
git_futils_readbuffer
(
&
cfg
->
locked_content
,
cfg
->
file
_
path
);
error
=
git_futils_readbuffer
(
&
cfg
->
locked_content
,
cfg
->
file
.
path
);
if
(
error
<
0
&&
error
!=
GIT_ENOTFOUND
)
{
if
(
error
<
0
&&
error
!=
GIT_ENOTFOUND
)
{
git_filebuf_cleanup
(
&
cfg
->
locked_buf
);
git_filebuf_cleanup
(
&
cfg
->
locked_buf
);
return
error
;
return
error
;
...
@@ -726,8 +745,9 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
...
@@ -726,8 +745,9 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
backend
->
header
.
parent
.
version
=
GIT_CONFIG_BACKEND_VERSION
;
backend
->
header
.
parent
.
version
=
GIT_CONFIG_BACKEND_VERSION
;
git_mutex_init
(
&
backend
->
header
.
values_mutex
);
git_mutex_init
(
&
backend
->
header
.
values_mutex
);
backend
->
file_path
=
git__strdup
(
path
);
backend
->
file
.
path
=
git__strdup
(
path
);
GITERR_CHECK_ALLOC
(
backend
->
file_path
);
GITERR_CHECK_ALLOC
(
backend
->
file
.
path
);
git_array_init
(
backend
->
file
.
includes
);
backend
->
header
.
parent
.
open
=
config_open
;
backend
->
header
.
parent
.
open
=
config_open
;
backend
->
header
.
parent
.
get
=
config_get
;
backend
->
header
.
parent
.
get
=
config_get
;
...
@@ -1486,10 +1506,10 @@ on_error:
...
@@ -1486,10 +1506,10 @@ on_error:
static
int
config_parse
(
static
int
config_parse
(
struct
reader
*
reader
,
struct
reader
*
reader
,
int
(
*
on_section
)(
struct
reader
*
*
reader
,
const
char
*
current_section
,
const
char
*
line
,
size_t
line_len
,
void
*
data
),
int
(
*
on_section
)(
struct
reader
*
reader
,
const
char
*
current_section
,
const
char
*
line
,
size_t
line_len
,
void
*
data
),
int
(
*
on_variable
)(
struct
reader
*
*
reader
,
const
char
*
current_section
,
char
*
var_name
,
char
*
var_value
,
const
char
*
line
,
size_t
line_len
,
void
*
data
),
int
(
*
on_variable
)(
struct
reader
*
reader
,
const
char
*
current_section
,
char
*
var_name
,
char
*
var_value
,
const
char
*
line
,
size_t
line_len
,
void
*
data
),
int
(
*
on_comment
)(
struct
reader
*
*
reader
,
const
char
*
line
,
size_t
line_len
,
void
*
data
),
int
(
*
on_comment
)(
struct
reader
*
reader
,
const
char
*
line
,
size_t
line_len
,
void
*
data
),
int
(
*
on_eof
)(
struct
reader
*
*
reader
,
const
char
*
current_section
,
void
*
data
),
int
(
*
on_eof
)(
struct
reader
*
reader
,
const
char
*
current_section
,
void
*
data
),
void
*
data
)
void
*
data
)
{
{
char
*
current_section
=
NULL
,
*
var_name
,
*
var_value
,
*
line_start
;
char
*
current_section
=
NULL
,
*
var_name
,
*
var_value
,
*
line_start
;
...
@@ -1515,7 +1535,7 @@ static int config_parse(
...
@@ -1515,7 +1535,7 @@ static int config_parse(
if
((
result
=
parse_section_header
(
reader
,
&
current_section
))
==
0
&&
on_section
)
{
if
((
result
=
parse_section_header
(
reader
,
&
current_section
))
==
0
&&
on_section
)
{
line_len
=
reader
->
read_ptr
-
line_start
;
line_len
=
reader
->
read_ptr
-
line_start
;
result
=
on_section
(
&
reader
,
current_section
,
line_start
,
line_len
,
data
);
result
=
on_section
(
reader
,
current_section
,
line_start
,
line_len
,
data
);
}
}
break
;
break
;
...
@@ -1526,21 +1546,21 @@ static int config_parse(
...
@@ -1526,21 +1546,21 @@ static int config_parse(
if
(
on_comment
)
{
if
(
on_comment
)
{
line_len
=
reader
->
read_ptr
-
line_start
;
line_len
=
reader
->
read_ptr
-
line_start
;
result
=
on_comment
(
&
reader
,
line_start
,
line_len
,
data
);
result
=
on_comment
(
reader
,
line_start
,
line_len
,
data
);
}
}
break
;
break
;
default
:
/* assume variable declaration */
default
:
/* assume variable declaration */
if
((
result
=
parse_variable
(
reader
,
&
var_name
,
&
var_value
))
==
0
&&
on_variable
)
{
if
((
result
=
parse_variable
(
reader
,
&
var_name
,
&
var_value
))
==
0
&&
on_variable
)
{
line_len
=
reader
->
read_ptr
-
line_start
;
line_len
=
reader
->
read_ptr
-
line_start
;
result
=
on_variable
(
&
reader
,
current_section
,
var_name
,
var_value
,
line_start
,
line_len
,
data
);
result
=
on_variable
(
reader
,
current_section
,
var_name
,
var_value
,
line_start
,
line_len
,
data
);
}
}
break
;
break
;
}
}
}
}
if
(
on_eof
)
if
(
on_eof
)
result
=
on_eof
(
&
reader
,
current_section
,
data
);
result
=
on_eof
(
reader
,
current_section
,
data
);
git__free
(
current_section
);
git__free
(
current_section
);
return
result
;
return
result
;
...
@@ -1548,14 +1568,12 @@ static int config_parse(
...
@@ -1548,14 +1568,12 @@ static int config_parse(
struct
parse_data
{
struct
parse_data
{
git_strmap
*
values
;
git_strmap
*
values
;
diskfile_backend
*
cfg_file
;
uint32_t
reader_idx
;
git_config_level_t
level
;
git_config_level_t
level
;
int
depth
;
int
depth
;
};
};
static
int
read_on_variable
(
static
int
read_on_variable
(
struct
reader
*
*
reader
,
struct
reader
*
reader
,
const
char
*
current_section
,
const
char
*
current_section
,
char
*
var_name
,
char
*
var_name
,
char
*
var_value
,
char
*
var_value
,
...
@@ -1597,21 +1615,13 @@ static int read_on_variable(
...
@@ -1597,21 +1615,13 @@ static int read_on_variable(
/* 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
(
var
->
entry
->
name
,
"include.path"
))
{
struct
reader
*
r
;
struct
config_file
*
include
;
git_buf
path
=
GIT_BUF_INIT
;
git_buf
path
=
GIT_BUF_INIT
;
char
*
dir
;
char
*
dir
;
uint32_t
index
;
r
=
git_array_alloc
(
parse_data
->
cfg_file
->
readers
);
/* The reader may have been reallocated */
*
reader
=
git_array_get
(
parse_data
->
cfg_file
->
readers
,
parse_data
->
reader_idx
);
memset
(
r
,
0
,
sizeof
(
struct
reader
));
if
((
result
=
git_path_dirname_r
(
&
path
,
(
*
reader
)
->
file_
path
))
<
0
)
if
((
result
=
git_path_dirname_r
(
&
path
,
reader
->
file
->
path
))
<
0
)
return
result
;
return
result
;
/* We need to know our index in the array, as the next config_parse call may realloc */
index
=
git_array_size
(
parse_data
->
cfg_file
->
readers
)
-
1
;
dir
=
git_buf_detach
(
&
path
);
dir
=
git_buf_detach
(
&
path
);
result
=
included_path
(
&
path
,
dir
,
var
->
entry
->
value
);
result
=
included_path
(
&
path
,
dir
,
var
->
entry
->
value
);
git__free
(
dir
);
git__free
(
dir
);
...
@@ -1619,51 +1629,60 @@ static int read_on_variable(
...
@@ -1619,51 +1629,60 @@ static int read_on_variable(
if
(
result
<
0
)
if
(
result
<
0
)
return
result
;
return
result
;
r
->
file_path
=
git_buf_detach
(
&
path
);
include
=
git_array_alloc
(
reader
->
file
->
includes
);
git_buf_init
(
&
r
->
buffer
,
0
);
memset
(
include
,
0
,
sizeof
(
*
include
));
git_array_init
(
include
->
includes
);
include
->
path
=
git_buf_detach
(
&
path
);
result
=
git_futils_readbuffer_updated
(
result
=
config_read
(
parse_data
->
values
,
include
,
parse_data
->
level
,
parse_data
->
depth
+
1
);
&
r
->
buffer
,
r
->
file_path
,
&
r
->
checksum
,
NULL
);
if
(
result
==
0
)
{
if
(
result
==
GIT_ENOTFOUND
)
{
result
=
config_read
(
parse_data
->
values
,
parse_data
->
cfg_file
,
r
,
parse_data
->
level
,
parse_data
->
depth
+
1
);
r
=
git_array_get
(
parse_data
->
cfg_file
->
readers
,
index
);
*
reader
=
git_array_get
(
parse_data
->
cfg_file
->
readers
,
parse_data
->
reader_idx
);
}
else
if
(
result
==
GIT_ENOTFOUND
)
{
giterr_clear
();
giterr_clear
();
result
=
0
;
result
=
0
;
}
}
git_buf_free
(
&
r
->
buffer
);
}
}
return
result
;
return
result
;
}
}
static
int
config_read
(
git_strmap
*
values
,
diskfile_backend
*
cfg_file
,
struct
reader
*
reader
,
git_config_level_t
level
,
int
depth
)
static
int
config_read
(
git_strmap
*
values
,
struct
config_file
*
file
,
git_config_level_t
level
,
int
depth
)
{
{
struct
parse_data
parse_data
;
struct
parse_data
parse_data
;
struct
reader
reader
;
int
error
;
if
(
depth
>=
MAX_INCLUDE_DEPTH
)
{
if
(
depth
>=
MAX_INCLUDE_DEPTH
)
{
giterr_set
(
GITERR_CONFIG
,
"maximum config include depth reached"
);
giterr_set
(
GITERR_CONFIG
,
"maximum config include depth reached"
);
return
-
1
;
return
-
1
;
}
}
git_buf_init
(
&
reader
.
buffer
,
0
);
if
((
error
=
git_futils_readbuffer
(
&
reader
.
buffer
,
file
->
path
))
<
0
)
goto
out
;
if
((
error
=
git_hash_buf
(
&
file
->
checksum
,
reader
.
buffer
.
ptr
,
reader
.
buffer
.
size
))
<
0
)
goto
out
;
/* Initialize the reading position */
/* Initialize the reading position */
reader
->
read_ptr
=
reader
->
buffer
.
ptr
;
reader
.
file
=
file
;
reader
->
eof
=
0
;
reader
.
line_number
=
0
;
reader
.
read_ptr
=
reader
.
buffer
.
ptr
;
reader
.
eof
=
0
;
/* If the file is empty, there's nothing for us to do */
/* If the file is empty, there's nothing for us to do */
if
(
*
reader
->
read_ptr
==
'\0'
)
if
(
*
reader
.
read_ptr
==
'\0'
)
return
0
;
goto
out
;
parse_data
.
values
=
values
;
parse_data
.
values
=
values
;
parse_data
.
cfg_file
=
cfg_file
;
parse_data
.
reader_idx
=
git_array_size
(
cfg_file
->
readers
)
-
1
;
parse_data
.
level
=
level
;
parse_data
.
level
=
level
;
parse_data
.
depth
=
depth
;
parse_data
.
depth
=
depth
;
return
config_parse
(
reader
,
NULL
,
read_on_variable
,
NULL
,
NULL
,
&
parse_data
);
error
=
config_parse
(
&
reader
,
NULL
,
read_on_variable
,
NULL
,
NULL
,
&
parse_data
);
out:
git_buf_free
(
&
reader
.
buffer
);
return
error
;
}
}
static
int
write_section
(
git_buf
*
fbuf
,
const
char
*
key
)
static
int
write_section
(
git_buf
*
fbuf
,
const
char
*
key
)
...
@@ -1760,7 +1779,7 @@ static int write_value(struct write_data *write_data)
...
@@ -1760,7 +1779,7 @@ static int write_value(struct write_data *write_data)
}
}
static
int
write_on_section
(
static
int
write_on_section
(
struct
reader
*
*
reader
,
struct
reader
*
reader
,
const
char
*
current_section
,
const
char
*
current_section
,
const
char
*
line
,
const
char
*
line
,
size_t
line_len
,
size_t
line_len
,
...
@@ -1796,7 +1815,7 @@ static int write_on_section(
...
@@ -1796,7 +1815,7 @@ static int write_on_section(
}
}
static
int
write_on_variable
(
static
int
write_on_variable
(
struct
reader
*
*
reader
,
struct
reader
*
reader
,
const
char
*
current_section
,
const
char
*
current_section
,
char
*
var_name
,
char
*
var_name
,
char
*
var_value
,
char
*
var_value
,
...
@@ -1846,7 +1865,7 @@ static int write_on_variable(
...
@@ -1846,7 +1865,7 @@ static int write_on_variable(
return
write_value
(
write_data
);
return
write_value
(
write_data
);
}
}
static
int
write_on_comment
(
struct
reader
*
*
reader
,
const
char
*
line
,
size_t
line_len
,
void
*
data
)
static
int
write_on_comment
(
struct
reader
*
reader
,
const
char
*
line
,
size_t
line_len
,
void
*
data
)
{
{
struct
write_data
*
write_data
;
struct
write_data
*
write_data
;
...
@@ -1857,7 +1876,7 @@ static int write_on_comment(struct reader **reader, const char *line, size_t lin
...
@@ -1857,7 +1876,7 @@ static int write_on_comment(struct reader **reader, const char *line, size_t lin
}
}
static
int
write_on_eof
(
static
int
write_on_eof
(
struct
reader
*
*
reader
,
const
char
*
current_section
,
void
*
data
)
struct
reader
*
reader
,
const
char
*
current_section
,
void
*
data
)
{
{
struct
write_data
*
write_data
=
(
struct
write_data
*
)
data
;
struct
write_data
*
write_data
=
(
struct
write_data
*
)
data
;
int
result
=
0
;
int
result
=
0
;
...
@@ -1896,31 +1915,35 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
...
@@ -1896,31 +1915,35 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
char
*
section
,
*
name
,
*
ldot
;
char
*
section
,
*
name
,
*
ldot
;
git_filebuf
file
=
GIT_FILEBUF_INIT
;
git_filebuf
file
=
GIT_FILEBUF_INIT
;
git_buf
buf
=
GIT_BUF_INIT
;
git_buf
buf
=
GIT_BUF_INIT
;
struct
reader
*
reader
=
git_array_get
(
cfg
->
readers
,
0
)
;
struct
reader
reader
;
struct
write_data
write_data
;
struct
write_data
write_data
;
memset
(
&
reader
,
0
,
sizeof
(
reader
));
git_buf_init
(
&
reader
.
buffer
,
0
);
reader
.
file
=
&
cfg
->
file
;
if
(
cfg
->
locked
)
{
if
(
cfg
->
locked
)
{
result
=
git_buf_puts
(
&
reader
->
buffer
,
git_buf_cstr
(
&
cfg
->
locked_content
));
result
=
git_buf_puts
(
&
reader
.
buffer
,
git_buf_cstr
(
&
cfg
->
locked_content
));
}
else
{
}
else
{
/* Lock the file */
/* Lock the file */
if
((
result
=
git_filebuf_open
(
if
((
result
=
git_filebuf_open
(
&
file
,
cfg
->
file
_
path
,
GIT_FILEBUF_HASH_CONTENTS
,
GIT_CONFIG_FILE_MODE
))
<
0
)
{
&
file
,
cfg
->
file
.
path
,
GIT_FILEBUF_HASH_CONTENTS
,
GIT_CONFIG_FILE_MODE
))
<
0
)
{
git_buf_free
(
&
reader
->
buffer
);
git_buf_free
(
&
reader
.
buffer
);
return
result
;
return
result
;
}
}
/* We need to read in our own config file */
/* We need to read in our own config file */
result
=
git_futils_readbuffer
(
&
reader
->
buffer
,
cfg
->
file_
path
);
result
=
git_futils_readbuffer
(
&
reader
.
buffer
,
cfg
->
file
.
path
);
}
}
/* Initialise the reading position */
/* Initialise the reading position */
if
(
result
==
GIT_ENOTFOUND
)
{
if
(
result
==
GIT_ENOTFOUND
)
{
reader
->
read_ptr
=
NULL
;
reader
.
read_ptr
=
NULL
;
reader
->
eof
=
1
;
reader
.
eof
=
1
;
git_buf_clear
(
&
reader
->
buffer
);
git_buf_clear
(
&
reader
.
buffer
);
}
else
if
(
result
==
0
)
{
}
else
if
(
result
==
0
)
{
reader
->
read_ptr
=
reader
->
buffer
.
ptr
;
reader
.
read_ptr
=
reader
.
buffer
.
ptr
;
reader
->
eof
=
0
;
reader
.
eof
=
0
;
}
else
{
}
else
{
git_filebuf_cleanup
(
&
file
);
git_filebuf_cleanup
(
&
file
);
return
-
1
;
/* OS error when reading the file */
return
-
1
;
/* OS error when reading the file */
...
@@ -1939,7 +1962,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
...
@@ -1939,7 +1962,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
write_data
.
preg
=
preg
;
write_data
.
preg
=
preg
;
write_data
.
value
=
value
;
write_data
.
value
=
value
;
result
=
config_parse
(
reader
,
write_on_section
,
write_on_variable
,
write_on_comment
,
write_on_eof
,
&
write_data
);
result
=
config_parse
(
&
reader
,
write_on_section
,
write_on_variable
,
write_on_comment
,
write_on_eof
,
&
write_data
);
git__free
(
section
);
git__free
(
section
);
git_buf_free
(
&
write_data
.
buffered_comment
);
git_buf_free
(
&
write_data
.
buffered_comment
);
...
@@ -1960,6 +1983,6 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
...
@@ -1960,6 +1983,6 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
done:
done:
git_buf_free
(
&
buf
);
git_buf_free
(
&
buf
);
git_buf_free
(
&
reader
->
buffer
);
git_buf_free
(
&
reader
.
buffer
);
return
result
;
return
result
;
}
}
tests/config/include.c
View file @
e0568621
...
@@ -2,25 +2,31 @@
...
@@ -2,25 +2,31 @@
#include "buffer.h"
#include "buffer.h"
#include "fileops.h"
#include "fileops.h"
void
test_config_include__relative
(
void
)
static
git_config
*
cfg
;
static
git_buf
buf
;
void
test_config_include__initialize
(
void
)
{
{
git_config
*
cfg
;
cfg
=
NULL
;
git_buf
buf
=
GIT_BUF_INIT
;
git_buf_init
(
&
buf
,
0
);
}
void
test_config_include__cleanup
(
void
)
{
git_config_free
(
cfg
);
git_buf_free
(
&
buf
);
}
void
test_config_include__relative
(
void
)
{
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
cl_fixture
(
"config/config-include"
)));
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
cl_fixture
(
"config/config-include"
)));
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar.baz"
));
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar.baz"
));
cl_assert_equal_s
(
"huzzah"
,
git_buf_cstr
(
&
buf
));
cl_assert_equal_s
(
"huzzah"
,
git_buf_cstr
(
&
buf
));
git_buf_free
(
&
buf
);
git_config_free
(
cfg
);
}
}
void
test_config_include__absolute
(
void
)
void
test_config_include__absolute
(
void
)
{
{
git_config
*
cfg
;
git_buf
buf
=
GIT_BUF_INIT
;
cl_git_pass
(
git_buf_printf
(
&
buf
,
"[include]
\n
path = %s/config-included"
,
cl_fixture
(
"config"
)));
cl_git_pass
(
git_buf_printf
(
&
buf
,
"[include]
\n
path = %s/config-included"
,
cl_fixture
(
"config"
)));
cl_git_mkfile
(
"config-include-absolute"
,
git_buf_cstr
(
&
buf
));
cl_git_mkfile
(
"config-include-absolute"
,
git_buf_cstr
(
&
buf
));
...
@@ -29,16 +35,10 @@ void test_config_include__absolute(void)
...
@@ -29,16 +35,10 @@ void test_config_include__absolute(void)
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar.baz"
));
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar.baz"
));
cl_assert_equal_s
(
"huzzah"
,
git_buf_cstr
(
&
buf
));
cl_assert_equal_s
(
"huzzah"
,
git_buf_cstr
(
&
buf
));
git_buf_free
(
&
buf
);
git_config_free
(
cfg
);
}
}
void
test_config_include__homedir
(
void
)
void
test_config_include__homedir
(
void
)
{
{
git_config
*
cfg
;
git_buf
buf
=
GIT_BUF_INIT
;
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_SEARCH_PATH
,
GIT_CONFIG_LEVEL_GLOBAL
,
cl_fixture
(
"config"
)));
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_SEARCH_PATH
,
GIT_CONFIG_LEVEL_GLOBAL
,
cl_fixture
(
"config"
)));
cl_git_mkfile
(
"config-include-homedir"
,
"[include]
\n
path = ~/config-included"
);
cl_git_mkfile
(
"config-include-homedir"
,
"[include]
\n
path = ~/config-included"
);
...
@@ -47,18 +47,12 @@ void test_config_include__homedir(void)
...
@@ -47,18 +47,12 @@ void test_config_include__homedir(void)
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar.baz"
));
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar.baz"
));
cl_assert_equal_s
(
"huzzah"
,
git_buf_cstr
(
&
buf
));
cl_assert_equal_s
(
"huzzah"
,
git_buf_cstr
(
&
buf
));
git_buf_free
(
&
buf
);
git_config_free
(
cfg
);
cl_sandbox_set_search_path_defaults
();
cl_sandbox_set_search_path_defaults
();
}
}
/* We need to pretend that the variables were defined where the file was included */
/* We need to pretend that the variables were defined where the file was included */
void
test_config_include__ordering
(
void
)
void
test_config_include__ordering
(
void
)
{
{
git_config
*
cfg
;
git_buf
buf
=
GIT_BUF_INIT
;
cl_git_mkfile
(
"included"
,
"[foo
\"
bar
\"
]
\n
baz = hurrah
\n
frotz = hiya"
);
cl_git_mkfile
(
"included"
,
"[foo
\"
bar
\"
]
\n
baz = hurrah
\n
frotz = hiya"
);
cl_git_mkfile
(
"including"
,
cl_git_mkfile
(
"including"
,
"[foo
\"
bar
\"
]
\n
frotz = hello
\n
"
"[foo
\"
bar
\"
]
\n
frotz = hello
\n
"
...
@@ -72,16 +66,11 @@ void test_config_include__ordering(void)
...
@@ -72,16 +66,11 @@ void test_config_include__ordering(void)
git_buf_clear
(
&
buf
);
git_buf_clear
(
&
buf
);
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar.baz"
));
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar.baz"
));
cl_assert_equal_s
(
"huzzah"
,
git_buf_cstr
(
&
buf
));
cl_assert_equal_s
(
"huzzah"
,
git_buf_cstr
(
&
buf
));
git_buf_free
(
&
buf
);
git_config_free
(
cfg
);
}
}
/* We need to pretend that the variables were defined where the file was included */
/* We need to pretend that the variables were defined where the file was included */
void
test_config_include__depth
(
void
)
void
test_config_include__depth
(
void
)
{
{
git_config
*
cfg
;
cl_git_mkfile
(
"a"
,
"[include]
\n
path = b"
);
cl_git_mkfile
(
"a"
,
"[include]
\n
path = b"
);
cl_git_mkfile
(
"b"
,
"[include]
\n
path = a"
);
cl_git_mkfile
(
"b"
,
"[include]
\n
path = a"
);
...
@@ -93,9 +82,6 @@ void test_config_include__depth(void)
...
@@ -93,9 +82,6 @@ void test_config_include__depth(void)
void
test_config_include__missing
(
void
)
void
test_config_include__missing
(
void
)
{
{
git_config
*
cfg
;
git_buf
buf
=
GIT_BUF_INIT
;
cl_git_mkfile
(
"including"
,
"[include]
\n
path = nonexistentfile
\n
[foo]
\n
bar = baz"
);
cl_git_mkfile
(
"including"
,
"[include]
\n
path = nonexistentfile
\n
[foo]
\n
bar = baz"
);
giterr_clear
();
giterr_clear
();
...
@@ -103,16 +89,10 @@ void test_config_include__missing(void)
...
@@ -103,16 +89,10 @@ void test_config_include__missing(void)
cl_assert
(
giterr_last
()
==
NULL
);
cl_assert
(
giterr_last
()
==
NULL
);
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar"
));
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar"
));
cl_assert_equal_s
(
"baz"
,
git_buf_cstr
(
&
buf
));
cl_assert_equal_s
(
"baz"
,
git_buf_cstr
(
&
buf
));
git_buf_free
(
&
buf
);
git_config_free
(
cfg
);
}
}
void
test_config_include__missing_homedir
(
void
)
void
test_config_include__missing_homedir
(
void
)
{
{
git_config
*
cfg
;
git_buf
buf
=
GIT_BUF_INIT
;
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_SEARCH_PATH
,
GIT_CONFIG_LEVEL_GLOBAL
,
cl_fixture
(
"config"
)));
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_SEARCH_PATH
,
GIT_CONFIG_LEVEL_GLOBAL
,
cl_fixture
(
"config"
)));
cl_git_mkfile
(
"including"
,
"[include]
\n
path = ~/.nonexistentfile
\n
[foo]
\n
bar = baz"
);
cl_git_mkfile
(
"including"
,
"[include]
\n
path = ~/.nonexistentfile
\n
[foo]
\n
bar = baz"
);
...
@@ -122,17 +102,12 @@ void test_config_include__missing_homedir(void)
...
@@ -122,17 +102,12 @@ void test_config_include__missing_homedir(void)
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar"
));
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar"
));
cl_assert_equal_s
(
"baz"
,
git_buf_cstr
(
&
buf
));
cl_assert_equal_s
(
"baz"
,
git_buf_cstr
(
&
buf
));
git_buf_free
(
&
buf
);
git_config_free
(
cfg
);
cl_sandbox_set_search_path_defaults
();
cl_sandbox_set_search_path_defaults
();
}
}
#define replicate10(s) s s s s s s s s s s
#define replicate10(s) s s s s s s s s s s
void
test_config_include__depth2
(
void
)
void
test_config_include__depth2
(
void
)
{
{
git_config
*
cfg
;
git_buf
buf
=
GIT_BUF_INIT
;
const
char
*
content
=
"[include]
\n
"
replicate10
(
replicate10
(
"path=bottom
\n
"
));
const
char
*
content
=
"[include]
\n
"
replicate10
(
replicate10
(
"path=bottom
\n
"
));
cl_git_mkfile
(
"top-level"
,
"[include]
\n
path = middle
\n
[foo]
\n
bar = baz"
);
cl_git_mkfile
(
"top-level"
,
"[include]
\n
path = middle
\n
[foo]
\n
bar = baz"
);
...
@@ -147,7 +122,45 @@ void test_config_include__depth2(void)
...
@@ -147,7 +122,45 @@ void test_config_include__depth2(void)
git_buf_clear
(
&
buf
);
git_buf_clear
(
&
buf
);
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar2"
));
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar2"
));
cl_assert_equal_s
(
"baz2"
,
git_buf_cstr
(
&
buf
));
cl_assert_equal_s
(
"baz2"
,
git_buf_cstr
(
&
buf
));
}
git_buf_free
(
&
buf
);
void
test_config_include__removing_include_removes_values
(
void
)
git_config_free
(
cfg
);
{
cl_git_mkfile
(
"top-level"
,
"[include]
\n
path = included"
);
cl_git_mkfile
(
"included"
,
"[foo]
\n
bar = value"
);
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"top-level"
));
cl_git_mkfile
(
"top-level"
,
""
);
cl_git_fail
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar"
));
}
void
test_config_include__rewriting_include_refreshes_values
(
void
)
{
cl_git_mkfile
(
"top-level"
,
"[include]
\n
path = first
\n
[include]
\n
path = second"
);
cl_git_mkfile
(
"first"
,
"[first]
\n
foo = bar"
);
cl_git_mkfile
(
"second"
,
"[second]
\n
foo = bar"
);
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"top-level"
));
cl_git_mkfile
(
"first"
,
"[first]
\n
other = value"
);
cl_git_fail
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"foo.bar"
));
cl_git_pass
(
git_config_get_string_buf
(
&
buf
,
cfg
,
"first.other"
));
cl_assert_equal_s
(
buf
.
ptr
,
"value"
);
}
void
test_config_include__included_variables_cannot_be_deleted
(
void
)
{
cl_git_mkfile
(
"top-level"
,
"[include]
\n
path = included
\n
"
);
cl_git_mkfile
(
"included"
,
"[foo]
\n
bar = value"
);
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"top-level"
));
cl_git_fail
(
git_config_delete_entry
(
cfg
,
"foo.bar"
));
}
void
test_config_include__included_variables_cannot_be_modified
(
void
)
{
cl_git_mkfile
(
"top-level"
,
"[include]
\n
path = included
\n
"
);
cl_git_mkfile
(
"included"
,
"[foo]
\n
bar = value"
);
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
"top-level"
));
cl_git_fail
(
git_config_set_string
(
cfg
,
"foo.bar"
,
"other-value"
));
}
}
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