mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-12 10:05:57 +00:00
config: keep a list of included files
When refreshing we need to refresh if any of the files have been touched, so we need to keep the list.
This commit is contained in:
parent
d8d25acb9a
commit
19be0692b4
@ -15,6 +15,7 @@
|
|||||||
#include "git2/sys/config.h"
|
#include "git2/sys/config.h"
|
||||||
#include "git2/types.h"
|
#include "git2/types.h"
|
||||||
#include "strmap.h"
|
#include "strmap.h"
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -90,7 +91,7 @@ typedef struct {
|
|||||||
|
|
||||||
git_strmap *values;
|
git_strmap *values;
|
||||||
|
|
||||||
struct reader reader;
|
git_array_t(struct reader) readers;
|
||||||
|
|
||||||
char *file_path;
|
char *file_path;
|
||||||
|
|
||||||
@ -162,6 +163,7 @@ static void free_vars(git_strmap *values)
|
|||||||
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;
|
||||||
@ -169,20 +171,27 @@ static int config_open(git_config_backend *cfg, git_config_level_t level)
|
|||||||
b->values = git_strmap_alloc();
|
b->values = git_strmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(b->values);
|
GITERR_CHECK_ALLOC(b->values);
|
||||||
|
|
||||||
git_buf_init(&b->reader.buffer, 0);
|
git_array_init(b->readers);
|
||||||
|
reader = git_array_alloc(b->readers);
|
||||||
|
memset(reader, 0, sizeof(struct reader));
|
||||||
|
|
||||||
|
reader->file_path = git__strdup(b->file_path);
|
||||||
|
GITERR_CHECK_ALLOC(reader->file_path);
|
||||||
|
|
||||||
|
git_buf_init(&reader->buffer, 0);
|
||||||
res = git_futils_readbuffer_updated(
|
res = git_futils_readbuffer_updated(
|
||||||
&b->reader.buffer, b->file_path, &b->reader.file_mtime, &b->reader.file_size, NULL);
|
&reader->buffer, b->file_path, &reader->file_mtime, &reader->file_size, NULL);
|
||||||
|
|
||||||
/* It's fine if the file doesn't exist */
|
/* It's fine if the file doesn't exist */
|
||||||
if (res == GIT_ENOTFOUND)
|
if (res == GIT_ENOTFOUND)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (res < 0 || (res = config_parse(b, &b->reader, level, 0)) < 0) {
|
if (res < 0 || (res = config_parse(b, reader, level, 0)) < 0) {
|
||||||
free_vars(b->values);
|
free_vars(b->values);
|
||||||
b->values = NULL;
|
b->values = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
git_buf_free(&b->reader.buffer);
|
git_buf_free(&reader->buffer);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,9 +200,10 @@ static int config_refresh(git_config_backend *cfg)
|
|||||||
int res, updated = 0;
|
int res, updated = 0;
|
||||||
diskfile_backend *b = (diskfile_backend *)cfg;
|
diskfile_backend *b = (diskfile_backend *)cfg;
|
||||||
git_strmap *old_values;
|
git_strmap *old_values;
|
||||||
|
struct reader *reader = git_array_get(b->readers, 0);
|
||||||
|
|
||||||
res = git_futils_readbuffer_updated(
|
res = git_futils_readbuffer_updated(
|
||||||
&b->reader.buffer, b->file_path, &b->reader.file_mtime, &b->reader.file_size, &updated);
|
&reader->buffer, b->file_path, &reader->file_mtime, &reader->file_size, &updated);
|
||||||
if (res < 0 || !updated)
|
if (res < 0 || !updated)
|
||||||
return (res == GIT_ENOTFOUND) ? 0 : res;
|
return (res == GIT_ENOTFOUND) ? 0 : res;
|
||||||
|
|
||||||
@ -202,25 +212,31 @@ static int config_refresh(git_config_backend *cfg)
|
|||||||
b->values = git_strmap_alloc();
|
b->values = git_strmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(b->values);
|
GITERR_CHECK_ALLOC(b->values);
|
||||||
|
|
||||||
if ((res = config_parse(b, &b->reader, b->level, 0)) < 0) {
|
if ((res = config_parse(b, reader, b->level, 0)) < 0) {
|
||||||
free_vars(b->values);
|
free_vars(b->values);
|
||||||
b->values = old_values;
|
b->values = old_values;
|
||||||
} else {
|
} else {
|
||||||
free_vars(old_values);
|
free_vars(old_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
git_buf_free(&b->reader.buffer);
|
git_buf_free(&reader->buffer);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
git__free(backend->reader.file_path);
|
for (i = 0; i < git_array_size(backend->readers); i++) {
|
||||||
|
struct reader *r = git_array_get(backend->readers, i);
|
||||||
|
git__free(r->file_path);
|
||||||
|
}
|
||||||
|
git_array_clear(backend->readers);
|
||||||
|
|
||||||
git__free(backend->file_path);
|
git__free(backend->file_path);
|
||||||
free_vars(backend->values);
|
free_vars(backend->values);
|
||||||
git__free(backend);
|
git__free(backend);
|
||||||
@ -508,10 +524,6 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
|
|||||||
backend->file_path = git__strdup(path);
|
backend->file_path = git__strdup(path);
|
||||||
GITERR_CHECK_ALLOC(backend->file_path);
|
GITERR_CHECK_ALLOC(backend->file_path);
|
||||||
|
|
||||||
/* the reader needs its own copy */
|
|
||||||
backend->reader.file_path = git__strdup(path);
|
|
||||||
GITERR_CHECK_ALLOC(backend->reader.file_path);
|
|
||||||
|
|
||||||
backend->parent.open = config_open;
|
backend->parent.open = config_open;
|
||||||
backend->parent.get = config_get;
|
backend->parent.get = config_get;
|
||||||
backend->parent.set = config_set;
|
backend->parent.set = config_set;
|
||||||
@ -995,11 +1007,12 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!git__strcmp(var->entry->name, "include.path")) {
|
if (!git__strcmp(var->entry->name, "include.path")) {
|
||||||
struct reader r;
|
struct reader *r;
|
||||||
git_buf path = GIT_BUF_INIT;
|
git_buf path = GIT_BUF_INIT;
|
||||||
char *dir;
|
char *dir;
|
||||||
|
|
||||||
memset(&r, 0, sizeof(r));
|
r = git_array_alloc(cfg_file->readers);
|
||||||
|
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)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1010,17 +1023,14 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c
|
|||||||
if (result < 0)
|
if (result < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
r.file_path = git_buf_detach(&path);
|
r->file_path = git_buf_detach(&path);
|
||||||
git_buf_init(&r.buffer, 0);
|
git_buf_init(&r->buffer, 0);
|
||||||
if ((result = git_futils_readbuffer_updated(&r.buffer, r.file_path, &r.file_mtime,
|
if ((result = git_futils_readbuffer_updated(&r->buffer, r->file_path, &r->file_mtime,
|
||||||
&r.file_size, NULL)) < 0) {
|
&r->file_size, NULL)) < 0)
|
||||||
git__free(r.file_path);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
result = config_parse(cfg_file, &r, level, depth+1);
|
result = config_parse(cfg_file, r, level, depth+1);
|
||||||
git__free(r.file_path);
|
git_buf_free(&r->buffer);
|
||||||
git_buf_free(&r.buffer);
|
|
||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
break;
|
break;
|
||||||
@ -1074,20 +1084,21 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
|||||||
const char *pre_end = NULL, *post_start = NULL, *data_start;
|
const char *pre_end = NULL, *post_start = NULL, *data_start;
|
||||||
char *current_section = NULL, *section, *name, *ldot;
|
char *current_section = NULL, *section, *name, *ldot;
|
||||||
git_filebuf file = GIT_FILEBUF_INIT;
|
git_filebuf file = GIT_FILEBUF_INIT;
|
||||||
|
struct reader *reader = git_array_get(cfg->readers, 0);
|
||||||
|
|
||||||
/* We need to read in our own config file */
|
/* We need to read in our own config file */
|
||||||
result = git_futils_readbuffer(&cfg->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) {
|
||||||
cfg->reader.read_ptr = NULL;
|
reader->read_ptr = NULL;
|
||||||
cfg->reader.eof = 1;
|
reader->eof = 1;
|
||||||
data_start = NULL;
|
data_start = NULL;
|
||||||
git_buf_clear(&cfg->reader.buffer);
|
git_buf_clear(&reader->buffer);
|
||||||
} else if (result == 0) {
|
} else if (result == 0) {
|
||||||
cfg->reader.read_ptr = cfg->reader.buffer.ptr;
|
reader->read_ptr = reader->buffer.ptr;
|
||||||
cfg->reader.eof = 0;
|
reader->eof = 0;
|
||||||
data_start = cfg->reader.read_ptr;
|
data_start = reader->read_ptr;
|
||||||
} else {
|
} else {
|
||||||
return -1; /* OS error when reading the file */
|
return -1; /* OS error when reading the file */
|
||||||
}
|
}
|
||||||
@ -1096,13 +1107,13 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
|||||||
if (git_filebuf_open(&file, cfg->file_path, 0) < 0)
|
if (git_filebuf_open(&file, cfg->file_path, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
skip_bom(&cfg->reader);
|
skip_bom(reader);
|
||||||
ldot = strrchr(key, '.');
|
ldot = strrchr(key, '.');
|
||||||
name = ldot + 1;
|
name = ldot + 1;
|
||||||
section = git__strndup(key, ldot - key);
|
section = git__strndup(key, ldot - key);
|
||||||
|
|
||||||
while (!cfg->reader.eof) {
|
while (!reader->eof) {
|
||||||
c = reader_peek(&cfg->reader, SKIP_WHITESPACE);
|
c = reader_peek(reader, SKIP_WHITESPACE);
|
||||||
|
|
||||||
if (c == '\0') { /* We've arrived at the end of the file */
|
if (c == '\0') { /* We've arrived at the end of the file */
|
||||||
break;
|
break;
|
||||||
@ -1115,11 +1126,11 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
|||||||
* new section. If we actually want to replace it, the
|
* new section. If we actually want to replace it, the
|
||||||
* default case will take care of updating them.
|
* default case will take care of updating them.
|
||||||
*/
|
*/
|
||||||
pre_end = post_start = cfg->reader.read_ptr;
|
pre_end = post_start = reader->read_ptr;
|
||||||
|
|
||||||
git__free(current_section);
|
git__free(current_section);
|
||||||
current_section = NULL;
|
current_section = NULL;
|
||||||
if (parse_section_header(&cfg->reader, ¤t_section) < 0)
|
if (parse_section_header(reader, ¤t_section) < 0)
|
||||||
goto rewrite_fail;
|
goto rewrite_fail;
|
||||||
|
|
||||||
/* Keep track of when it stops matching */
|
/* Keep track of when it stops matching */
|
||||||
@ -1128,7 +1139,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (c == ';' || c == '#') {
|
else if (c == ';' || c == '#') {
|
||||||
reader_consume_line(&cfg->reader);
|
reader_consume_line(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
@ -1144,15 +1155,15 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
|||||||
*/
|
*/
|
||||||
if (!section_matches) {
|
if (!section_matches) {
|
||||||
if (!last_section_matched) {
|
if (!last_section_matched) {
|
||||||
reader_consume_line(&cfg->reader);
|
reader_consume_line(reader);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int has_matched = 0;
|
int has_matched = 0;
|
||||||
char *var_name, *var_value;
|
char *var_name, *var_value;
|
||||||
|
|
||||||
pre_end = cfg->reader.read_ptr;
|
pre_end = reader->read_ptr;
|
||||||
if (parse_variable(&cfg->reader, &var_name, &var_value) < 0)
|
if (parse_variable(reader, &var_name, &var_value) < 0)
|
||||||
goto rewrite_fail;
|
goto rewrite_fail;
|
||||||
|
|
||||||
/* First try to match the name of the variable */
|
/* First try to match the name of the variable */
|
||||||
@ -1171,7 +1182,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
|||||||
if (!has_matched)
|
if (!has_matched)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
post_start = cfg->reader.read_ptr;
|
post_start = reader->read_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We've found the variable we wanted to change, so
|
/* We've found the variable we wanted to change, so
|
||||||
@ -1214,12 +1225,12 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
|||||||
*/
|
*/
|
||||||
if (write_trailer) {
|
if (write_trailer) {
|
||||||
/* Write out rest of the file */
|
/* Write out rest of the file */
|
||||||
git_filebuf_write(&file, post_start, cfg->reader.buffer.size - (post_start - data_start));
|
git_filebuf_write(&file, post_start, reader->buffer.size - (post_start - data_start));
|
||||||
} else {
|
} else {
|
||||||
if (preg_replaced) {
|
if (preg_replaced) {
|
||||||
git_filebuf_printf(&file, "\n%s", data_start);
|
git_filebuf_printf(&file, "\n%s", data_start);
|
||||||
} else {
|
} else {
|
||||||
git_filebuf_write(&file, cfg->reader.buffer.ptr, cfg->reader.buffer.size);
|
git_filebuf_write(&file, reader->buffer.ptr, reader->buffer.size);
|
||||||
|
|
||||||
/* And now if we just need to add a variable */
|
/* And now if we just need to add a variable */
|
||||||
if (!section_matches && write_section(&file, section) < 0)
|
if (!section_matches && write_section(&file, section) < 0)
|
||||||
@ -1235,7 +1246,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If we are here, there is at least a section line */
|
/* If we are here, there is at least a section line */
|
||||||
if (cfg->reader.buffer.size > 0 && *(cfg->reader.buffer.ptr + cfg->reader.buffer.size - 1) != '\n')
|
if (reader->buffer.size > 0 && *(reader->buffer.ptr + reader->buffer.size - 1) != '\n')
|
||||||
git_filebuf_write(&file, "\n", 1);
|
git_filebuf_write(&file, "\n", 1);
|
||||||
|
|
||||||
git_filebuf_printf(&file, "\t%s = %s\n", name, value);
|
git_filebuf_printf(&file, "\t%s = %s\n", name, value);
|
||||||
@ -1246,10 +1257,10 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
|||||||
git__free(current_section);
|
git__free(current_section);
|
||||||
|
|
||||||
/* refresh stats - if this errors, then commit will error too */
|
/* refresh stats - if this errors, then commit will error too */
|
||||||
(void)git_filebuf_stats(&cfg->reader.file_mtime, &cfg->reader.file_size, &file);
|
(void)git_filebuf_stats(&reader->file_mtime, &reader->file_size, &file);
|
||||||
|
|
||||||
result = git_filebuf_commit(&file, GIT_CONFIG_FILE_MODE);
|
result = git_filebuf_commit(&file, GIT_CONFIG_FILE_MODE);
|
||||||
git_buf_free(&cfg->reader.buffer);
|
git_buf_free(&reader->buffer);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -1258,7 +1269,7 @@ rewrite_fail:
|
|||||||
git__free(current_section);
|
git__free(current_section);
|
||||||
|
|
||||||
git_filebuf_cleanup(&file);
|
git_filebuf_cleanup(&file);
|
||||||
git_buf_free(&cfg->reader.buffer);
|
git_buf_free(&reader->buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user