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
003808b3
Commit
003808b3
authored
Oct 31, 2012
by
Vicent Marti
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'config-refresh' into development
parents
a9db123b
c1f61af6
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
273 additions
and
43 deletions
+273
-43
include/git2/config.h
+14
-0
src/attr.c
+14
-22
src/attr_file.h
+2
-7
src/config.c
+14
-0
src/config_file.c
+43
-6
src/filebuf.c
+23
-0
src/filebuf.h
+1
-0
src/fileops.c
+50
-5
src/fileops.h
+42
-1
src/index.c
+1
-1
src/refs.c
+2
-1
tests-clar/config/refresh.c
+67
-0
No files found.
include/git2/config.h
View file @
003808b3
...
...
@@ -56,6 +56,7 @@ struct git_config_file {
int
(
*
set_multivar
)(
git_config_file
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
char
*
value
);
int
(
*
del
)(
struct
git_config_file
*
,
const
char
*
key
);
int
(
*
foreach
)(
struct
git_config_file
*
,
const
char
*
,
int
(
*
fn
)(
const
git_config_entry
*
,
void
*
),
void
*
data
);
int
(
*
refresh
)(
struct
git_config_file
*
);
void
(
*
free
)(
struct
git_config_file
*
);
};
...
...
@@ -243,6 +244,19 @@ GIT_EXTERN(int) git_config_open_level(
unsigned
int
level
);
/**
* Reload changed config files
*
* A config file may be changed on disk out from under the in-memory
* config object. This function causes us to look for files that have
* been modified since we last loaded them and refresh the config with
* the latest information.
*
* @param cfg The configuration to refresh
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_config_refresh
(
git_config
*
cfg
);
/**
* Free the configuration and its associated memory and files
*
* @param cfg the configuration to free
...
...
src/attr.c
View file @
003808b3
...
...
@@ -261,32 +261,26 @@ bool git_attr_cache__is_cached(
static
int
load_attr_file
(
const
char
**
data
,
git_
attr_file_stat_sig
*
sig
,
git_
futils_filestamp
*
stamp
,
const
char
*
filename
)
{
int
error
;
git_buf
content
=
GIT_BUF_INIT
;
struct
stat
st
;
if
(
p_stat
(
filename
,
&
st
)
<
0
)
return
GIT_ENOTFOUND
;
error
=
git_futils_filestamp_check
(
stamp
,
filename
);
if
(
error
<
0
)
return
error
;
if
(
sig
!=
NULL
&&
(
git_time_t
)
st
.
st_mtime
==
sig
->
seconds
&&
(
git_off_t
)
st
.
st_size
==
sig
->
size
&&
(
unsigned
int
)
st
.
st_ino
==
sig
->
ino
)
/* if error == 0, then file is up to date. By returning GIT_ENOTFOUND,
* we tell the caller not to reparse this file...
*/
if
(
!
error
)
return
GIT_ENOTFOUND
;
error
=
git_futils_readbuffer
_updated
(
&
content
,
filename
,
NULL
,
NULL
);
error
=
git_futils_readbuffer
(
&
content
,
filename
);
if
(
error
<
0
)
return
error
;
if
(
sig
!=
NULL
)
{
sig
->
seconds
=
(
git_time_t
)
st
.
st_mtime
;
sig
->
size
=
(
git_off_t
)
st
.
st_size
;
sig
->
ino
=
(
unsigned
int
)
st
.
st_ino
;
}
*
data
=
git_buf_detach
(
&
content
);
return
0
;
...
...
@@ -386,7 +380,7 @@ int git_attr_cache__push_file(
git_attr_cache
*
cache
=
git_repository_attr_cache
(
repo
);
git_attr_file
*
file
=
NULL
;
git_blob
*
blob
=
NULL
;
git_
attr_file_stat_sig
st
;
git_
futils_filestamp
stamp
;
assert
(
filename
&&
stack
);
...
...
@@ -408,12 +402,10 @@ int git_attr_cache__push_file(
/* if not in cache, load data, parse, and cache */
if
(
source
==
GIT_ATTR_FILE_FROM_FILE
)
{
if
(
file
)
memcpy
(
&
st
,
&
file
->
cache_data
.
st
,
sizeof
(
st
));
else
memset
(
&
st
,
0
,
sizeof
(
st
));
git_futils_filestamp_set
(
&
stamp
,
file
?
&
file
->
cache_data
.
stamp
:
NULL
);
error
=
load_attr_file
(
&
content
,
&
st
,
filename
);
error
=
load_attr_file
(
&
content
,
&
st
amp
,
filename
);
}
else
{
error
=
load_attr_blob_from_index
(
&
content
,
&
blob
,
repo
,
file
?
&
file
->
cache_data
.
oid
:
NULL
,
relfile
);
...
...
@@ -448,7 +440,7 @@ int git_attr_cache__push_file(
if
(
blob
)
git_oid_cpy
(
&
file
->
cache_data
.
oid
,
git_object_id
((
git_object
*
)
blob
));
else
memcpy
(
&
file
->
cache_data
.
st
,
&
st
,
sizeof
(
st
)
);
git_futils_filestamp_set
(
&
file
->
cache_data
.
stamp
,
&
stamp
);
finish:
/* push file onto vector if we found one*/
...
...
src/attr_file.h
View file @
003808b3
...
...
@@ -11,6 +11,7 @@
#include "vector.h"
#include "pool.h"
#include "buffer.h"
#include "fileops.h"
#define GIT_ATTR_FILE ".gitattributes"
#define GIT_ATTR_FILE_INREPO "info/attributes"
...
...
@@ -54,19 +55,13 @@ typedef struct {
}
git_attr_assignment
;
typedef
struct
{
git_time_t
seconds
;
git_off_t
size
;
unsigned
int
ino
;
}
git_attr_file_stat_sig
;
typedef
struct
{
char
*
key
;
/* cache "source#path" this was loaded from */
git_vector
rules
;
/* vector of <rule*> or <fnmatch*> */
git_pool
*
pool
;
bool
pool_is_allocated
;
union
{
git_oid
oid
;
git_
attr_file_stat_sig
st
;
git_
futils_filestamp
stamp
;
}
cache_data
;
}
git_attr_file
;
...
...
src/config.c
View file @
003808b3
...
...
@@ -267,6 +267,20 @@ int git_config_add_file(
return
0
;
}
int
git_config_refresh
(
git_config
*
cfg
)
{
int
error
=
0
;
unsigned
int
i
;
for
(
i
=
0
;
i
<
cfg
->
files
.
length
&&
!
error
;
++
i
)
{
file_internal
*
internal
=
git_vector_get
(
&
cfg
->
files
,
i
);
git_config_file
*
file
=
internal
->
file
;
error
=
file
->
refresh
(
file
);
}
return
error
;
}
/*
* Loop over all the variables
*/
...
...
src/config_file.c
View file @
003808b3
...
...
@@ -75,7 +75,11 @@ typedef struct {
int
eof
;
}
reader
;
char
*
file_path
;
char
*
file_path
;
time_t
file_mtime
;
size_t
file_size
;
unsigned
int
level
;
}
diskfile_backend
;
static
int
config_parse
(
diskfile_backend
*
cfg_file
,
unsigned
int
level
);
...
...
@@ -150,25 +154,53 @@ static int config_open(git_config_file *cfg, unsigned int level)
int
res
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
b
->
level
=
level
;
b
->
values
=
git_strmap_alloc
();
GITERR_CHECK_ALLOC
(
b
->
values
);
git_buf_init
(
&
b
->
reader
.
buffer
,
0
);
res
=
git_futils_readbuffer
(
&
b
->
reader
.
buffer
,
b
->
file_path
);
res
=
git_futils_readbuffer_updated
(
&
b
->
reader
.
buffer
,
b
->
file_path
,
&
b
->
file_mtime
,
&
b
->
file_size
,
NULL
);
/* It's fine if the file doesn't exist */
if
(
res
==
GIT_ENOTFOUND
)
return
0
;
if
(
res
<
0
||
config_parse
(
b
,
level
)
<
0
)
{
if
(
res
<
0
||
(
res
=
config_parse
(
b
,
level
))
<
0
)
{
free_vars
(
b
->
values
);
b
->
values
=
NULL
;
git_buf_free
(
&
b
->
reader
.
buffer
);
return
-
1
;
}
git_buf_free
(
&
b
->
reader
.
buffer
);
return
0
;
return
res
;
}
static
int
config_refresh
(
git_config_file
*
cfg
)
{
int
res
,
updated
=
0
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
cfg
;
git_strmap
*
old_values
;
res
=
git_futils_readbuffer_updated
(
&
b
->
reader
.
buffer
,
b
->
file_path
,
&
b
->
file_mtime
,
&
b
->
file_size
,
&
updated
);
if
(
res
<
0
||
!
updated
)
return
(
res
==
GIT_ENOTFOUND
)
?
0
:
res
;
/* need to reload - store old values and prep for reload */
old_values
=
b
->
values
;
b
->
values
=
git_strmap_alloc
();
GITERR_CHECK_ALLOC
(
b
->
values
);
if
((
res
=
config_parse
(
b
,
b
->
level
))
<
0
)
{
free_vars
(
b
->
values
);
b
->
values
=
old_values
;
}
else
{
free_vars
(
old_values
);
}
git_buf_free
(
&
b
->
reader
.
buffer
);
return
res
;
}
static
void
backend_free
(
git_config_file
*
_backend
)
...
...
@@ -527,6 +559,7 @@ int git_config_file__ondisk(git_config_file **out, const char *path)
backend
->
parent
.
set_multivar
=
config_set_multivar
;
backend
->
parent
.
del
=
config_delete
;
backend
->
parent
.
foreach
=
file_foreach
;
backend
->
parent
.
refresh
=
config_refresh
;
backend
->
parent
.
free
=
backend_free
;
*
out
=
(
git_config_file
*
)
backend
;
...
...
@@ -1197,8 +1230,12 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
git__free
(
section
);
git__free
(
current_section
);
/* refresh stats - if this errors, then commit will error too */
(
void
)
git_filebuf_stats
(
&
cfg
->
file_mtime
,
&
cfg
->
file_size
,
&
file
);
result
=
git_filebuf_commit
(
&
file
,
GIT_CONFIG_FILE_MODE
);
git_buf_free
(
&
cfg
->
reader
.
buffer
);
return
result
;
rewrite_fail
:
...
...
src/filebuf.c
View file @
003808b3
...
...
@@ -466,3 +466,26 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...)
return
res
;
}
int
git_filebuf_stats
(
time_t
*
mtime
,
size_t
*
size
,
git_filebuf
*
file
)
{
int
res
;
struct
stat
st
;
if
(
file
->
fd_is_open
)
res
=
p_fstat
(
file
->
fd
,
&
st
);
else
res
=
p_stat
(
file
->
path_original
,
&
st
);
if
(
res
<
0
)
{
giterr_set
(
GITERR_OS
,
"Could not get stat info for '%s'"
,
file
->
path_original
);
return
res
;
}
if
(
mtime
)
*
mtime
=
st
.
st_mtime
;
if
(
size
)
*
size
=
(
size_t
)
st
.
st_size
;
return
0
;
}
src/filebuf.h
View file @
003808b3
...
...
@@ -82,5 +82,6 @@ int git_filebuf_commit_at(git_filebuf *lock, const char *path, mode_t mode);
void
git_filebuf_cleanup
(
git_filebuf
*
lock
);
int
git_filebuf_hash
(
git_oid
*
oid
,
git_filebuf
*
file
);
int
git_filebuf_flush
(
git_filebuf
*
file
);
int
git_filebuf_stats
(
time_t
*
mtime
,
size_t
*
size
,
git_filebuf
*
file
);
#endif
src/fileops.c
View file @
003808b3
...
...
@@ -142,10 +142,11 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
}
int
git_futils_readbuffer_updated
(
git_buf
*
buf
,
const
char
*
path
,
time_t
*
mtime
,
int
*
updated
)
git_buf
*
buf
,
const
char
*
path
,
time_t
*
mtime
,
size_t
*
size
,
int
*
updated
)
{
git_file
fd
;
struct
stat
st
;
bool
changed
=
false
;
assert
(
buf
&&
path
&&
*
path
);
...
...
@@ -162,16 +163,25 @@ int git_futils_readbuffer_updated(
}
/*
* If we were given a time
, we only want to read the file if it
* has been modified.
* If we were given a time
and/or a size, we only want to read the file
*
if it
has been modified.
*/
if
(
mtime
!=
NULL
&&
*
mtime
>=
st
.
st_mtime
)
{
if
(
size
&&
*
size
!=
(
size_t
)
st
.
st_size
)
changed
=
true
;
if
(
mtime
&&
*
mtime
!=
st
.
st_mtime
)
changed
=
true
;
if
(
!
size
&&
!
mtime
)
changed
=
true
;
if
(
!
changed
)
{
p_close
(
fd
);
return
0
;
}
if
(
mtime
!=
NULL
)
*
mtime
=
st
.
st_mtime
;
if
(
size
!=
NULL
)
*
size
=
(
size_t
)
st
.
st_size
;
if
(
git_futils_readbuffer_fd
(
buf
,
fd
,
(
size_t
)
st
.
st_size
)
<
0
)
{
p_close
(
fd
);
...
...
@@ -188,7 +198,7 @@ int git_futils_readbuffer_updated(
int
git_futils_readbuffer
(
git_buf
*
buf
,
const
char
*
path
)
{
return
git_futils_readbuffer_updated
(
buf
,
path
,
NULL
,
NULL
);
return
git_futils_readbuffer_updated
(
buf
,
path
,
NULL
,
NULL
,
NULL
);
}
int
git_futils_mv_withpath
(
const
char
*
from
,
const
char
*
to
,
const
mode_t
dirmode
)
...
...
@@ -660,3 +670,38 @@ int git_futils_cp_r(
return
error
;
}
int
git_futils_filestamp_check
(
git_futils_filestamp
*
stamp
,
const
char
*
path
)
{
struct
stat
st
;
/* if the stamp is NULL, then always reload */
if
(
stamp
==
NULL
)
return
1
;
if
(
p_stat
(
path
,
&
st
)
<
0
)
return
GIT_ENOTFOUND
;
if
(
stamp
->
mtime
==
(
git_time_t
)
st
.
st_mtime
&&
stamp
->
size
==
(
git_off_t
)
st
.
st_size
&&
stamp
->
ino
==
(
unsigned
int
)
st
.
st_ino
)
return
0
;
stamp
->
mtime
=
(
git_time_t
)
st
.
st_mtime
;
stamp
->
size
=
(
git_off_t
)
st
.
st_size
;
stamp
->
ino
=
(
unsigned
int
)
st
.
st_ino
;
return
1
;
}
void
git_futils_filestamp_set
(
git_futils_filestamp
*
target
,
const
git_futils_filestamp
*
source
)
{
assert
(
target
);
if
(
source
)
memcpy
(
target
,
source
,
sizeof
(
*
target
));
else
memset
(
target
,
0
,
sizeof
(
*
target
));
}
src/fileops.h
View file @
003808b3
...
...
@@ -18,7 +18,8 @@
* Read whole files into an in-memory buffer for processing
*/
extern
int
git_futils_readbuffer
(
git_buf
*
obj
,
const
char
*
path
);
extern
int
git_futils_readbuffer_updated
(
git_buf
*
obj
,
const
char
*
path
,
time_t
*
mtime
,
int
*
updated
);
extern
int
git_futils_readbuffer_updated
(
git_buf
*
obj
,
const
char
*
path
,
time_t
*
mtime
,
size_t
*
size
,
int
*
updated
);
extern
int
git_futils_readbuffer_fd
(
git_buf
*
obj
,
git_file
fd
,
size_t
len
);
/**
...
...
@@ -266,4 +267,44 @@ extern int git_futils_find_system_file(git_buf *path, const char *filename);
*/
extern
int
git_futils_fake_symlink
(
const
char
*
new
,
const
char
*
old
);
/**
* A file stamp represents a snapshot of information about a file that can
* be used to test if the file changes. This portable implementation is
* based on stat data about that file, but it is possible that OS specific
* versions could be implemented in the future.
*/
typedef
struct
{
git_time_t
mtime
;
git_off_t
size
;
unsigned
int
ino
;
}
git_futils_filestamp
;
/**
* Compare stat information for file with reference info.
*
* This function updates the file stamp to current data for the given path
* and returns 0 if the file is up-to-date relative to the prior setting or
* 1 if the file has been changed. (This also may return GIT_ENOTFOUND if
* the file doesn't exist.)
*
* @param stamp File stamp to be checked
* @param path Path to stat and check if changed
* @return 0 if up-to-date, 1 if out-of-date, <0 on error
*/
extern
int
git_futils_filestamp_check
(
git_futils_filestamp
*
stamp
,
const
char
*
path
);
/**
* Set or reset file stamp data
*
* This writes the target file stamp. If the source is NULL, this will set
* the target stamp to values that will definitely be out of date. If the
* source is not NULL, this copies the source values to the target.
*
* @param tgt File stamp to write to
* @param src File stamp to copy from or NULL to clear the target
*/
extern
void
git_futils_filestamp_set
(
git_futils_filestamp
*
tgt
,
const
git_futils_filestamp
*
src
);
#endif
/* INCLUDE_fileops_h__ */
src/index.c
View file @
003808b3
...
...
@@ -405,7 +405,7 @@ int git_index_read(git_index *index)
/* We don't want to update the mtime if we fail to parse the index */
mtime
=
index
->
last_modified
;
error
=
git_futils_readbuffer_updated
(
&
buffer
,
index
->
index_file_path
,
&
mtime
,
&
updated
);
&
buffer
,
index
->
index_file_path
,
&
mtime
,
NULL
,
&
updated
);
if
(
error
<
0
)
return
error
;
...
...
src/refs.c
View file @
003808b3
...
...
@@ -123,7 +123,8 @@ static int reference_read(
if
(
git_buf_joinpath
(
&
path
,
repo_path
,
ref_name
)
<
0
)
return
-
1
;
result
=
git_futils_readbuffer_updated
(
file_content
,
path
.
ptr
,
mtime
,
updated
);
result
=
git_futils_readbuffer_updated
(
file_content
,
path
.
ptr
,
mtime
,
NULL
,
updated
);
git_buf_free
(
&
path
);
return
result
;
...
...
tests-clar/config/refresh.c
0 → 100644
View file @
003808b3
#include "clar_libgit2.h"
#define TEST_FILE "config.refresh"
void
test_config_refresh__initialize
(
void
)
{
}
void
test_config_refresh__cleanup
(
void
)
{
cl_fixture_cleanup
(
TEST_FILE
);
}
void
test_config_refresh__update_value
(
void
)
{
git_config
*
cfg
;
int32_t
v
;
cl_git_mkfile
(
TEST_FILE
,
"[section]
\n\t
value = 1
\n\n
"
);
/* By freeing the config, we make sure we flush the values */
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
TEST_FILE
));
cl_git_pass
(
git_config_get_int32
(
&
v
,
cfg
,
"section.value"
));
cl_assert_equal_i
(
1
,
v
);
cl_git_rewritefile
(
TEST_FILE
,
"[section]
\n\t
value = 10
\n\n
"
);
cl_git_pass
(
git_config_get_int32
(
&
v
,
cfg
,
"section.value"
));
cl_assert_equal_i
(
1
,
v
);
cl_git_pass
(
git_config_refresh
(
cfg
));
cl_git_pass
(
git_config_get_int32
(
&
v
,
cfg
,
"section.value"
));
cl_assert_equal_i
(
10
,
v
);
git_config_free
(
cfg
);
}
void
test_config_refresh__delete_value
(
void
)
{
git_config
*
cfg
;
int32_t
v
;
cl_git_mkfile
(
TEST_FILE
,
"[section]
\n\t
value = 1
\n\n
"
);
/* By freeing the config, we make sure we flush the values */
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
TEST_FILE
));
cl_git_pass
(
git_config_get_int32
(
&
v
,
cfg
,
"section.value"
));
cl_assert_equal_i
(
1
,
v
);
cl_git_fail
(
git_config_get_int32
(
&
v
,
cfg
,
"section.newval"
));
cl_git_rewritefile
(
TEST_FILE
,
"[section]
\n\t
newval = 10
\n\n
"
);
cl_git_pass
(
git_config_get_int32
(
&
v
,
cfg
,
"section.value"
));
cl_assert_equal_i
(
1
,
v
);
cl_git_fail
(
git_config_get_int32
(
&
v
,
cfg
,
"section.newval"
));
cl_git_pass
(
git_config_refresh
(
cfg
));
cl_git_fail
(
git_config_get_int32
(
&
v
,
cfg
,
"section.value"
));
cl_git_pass
(
git_config_get_int32
(
&
v
,
cfg
,
"section.newval"
));
cl_assert_equal_i
(
10
,
v
);
git_config_free
(
cfg
);
}
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