Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/config_file.c')
-rw-r--r--src/config_file.c109
1 files changed, 91 insertions, 18 deletions
diff --git a/src/config_file.c b/src/config_file.c
index 52a5376bd..a3fec1b34 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -105,6 +105,10 @@ typedef struct {
git_array_t(struct reader) readers;
+ bool locked;
+ git_filebuf locked_buf;
+ git_buf locked_content;
+
char *file_path;
} diskfile_backend;
@@ -685,6 +689,42 @@ static int config_snapshot(git_config_backend **out, git_config_backend *in)
return git_config_file__snapshot(out, b);
}
+static int config_lock(git_config_backend *_cfg)
+{
+ diskfile_backend *cfg = (diskfile_backend *) _cfg;
+ int error;
+
+ if ((error = git_filebuf_open(&cfg->locked_buf, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0)
+ return error;
+
+ error = git_futils_readbuffer(&cfg->locked_content, cfg->file_path);
+ if (error < 0 && error != GIT_ENOTFOUND) {
+ git_filebuf_cleanup(&cfg->locked_buf);
+ return error;
+ }
+
+ cfg->locked = true;
+ return 0;
+
+}
+
+static int config_unlock(git_config_backend *_cfg, int success)
+{
+ diskfile_backend *cfg = (diskfile_backend *) _cfg;
+ int error = 0;
+
+ if (success) {
+ git_filebuf_write(&cfg->locked_buf, cfg->locked_content.ptr, cfg->locked_content.size);
+ error = git_filebuf_commit(&cfg->locked_buf);
+ }
+
+ git_filebuf_cleanup(&cfg->locked_buf);
+ git_buf_free(&cfg->locked_content);
+ cfg->locked = false;
+
+ return error;
+}
+
int git_config_file__ondisk(git_config_backend **out, const char *path)
{
diskfile_backend *backend;
@@ -706,6 +746,8 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
backend->header.parent.del_multivar = config_delete_multivar;
backend->header.parent.iterator = config_iterator_new;
backend->header.parent.snapshot = config_snapshot;
+ backend->header.parent.lock = config_lock;
+ backend->header.parent.unlock = config_unlock;
backend->header.parent.free = backend_free;
*out = (git_config_backend *)backend;
@@ -750,6 +792,21 @@ static int config_delete_readonly(git_config_backend *cfg, const char *name)
return config_error_readonly();
}
+static int config_lock_readonly(git_config_backend *_cfg)
+{
+ GIT_UNUSED(_cfg);
+
+ return config_error_readonly();
+}
+
+static int config_unlock_readonly(git_config_backend *_cfg, int success)
+{
+ GIT_UNUSED(_cfg);
+ GIT_UNUSED(success);
+
+ return config_error_readonly();
+}
+
static void backend_readonly_free(git_config_backend *_backend)
{
diskfile_backend *backend = (diskfile_backend *)_backend;
@@ -803,6 +860,8 @@ int git_config_file__snapshot(git_config_backend **out, diskfile_backend *in)
backend->header.parent.del = config_delete_readonly;
backend->header.parent.del_multivar = config_delete_multivar_readonly;
backend->header.parent.iterator = config_iterator_new;
+ backend->header.parent.lock = config_lock_readonly;
+ backend->header.parent.unlock = config_unlock_readonly;
backend->header.parent.free = backend_readonly_free;
*out = (git_config_backend *)backend;
@@ -1602,7 +1661,7 @@ static int config_read(git_strmap *values, diskfile_backend *cfg_file, struct re
return config_parse(reader, NULL, read_on_variable, NULL, NULL, &parse_data);
}
-static int write_section(git_filebuf *file, const char *key)
+static int write_section(git_buf *fbuf, const char *key)
{
int result;
const char *dot;
@@ -1626,7 +1685,7 @@ static int write_section(git_filebuf *file, const char *key)
if (git_buf_oom(&buf))
return -1;
- result = git_filebuf_write(file, git_buf_cstr(&buf), buf.size);
+ result = git_buf_put(fbuf, git_buf_cstr(&buf), buf.size);
git_buf_free(&buf);
return result;
@@ -1651,7 +1710,7 @@ static const char *quotes_for_value(const char *value)
}
struct write_data {
- git_filebuf *file;
+ git_buf *buf;
unsigned int in_section : 1,
preg_replaced : 1;
const char *section;
@@ -1662,10 +1721,10 @@ struct write_data {
static int write_line(struct write_data *write_data, const char *line, size_t line_len)
{
- int result = git_filebuf_write(write_data->file, line, line_len);
+ int result = git_buf_put(write_data->buf, line, line_len);
if (!result && line_len && line[line_len-1] != '\n')
- result = git_filebuf_printf(write_data->file, "\n");
+ result = git_buf_printf(write_data->buf, "\n");
return result;
}
@@ -1676,7 +1735,7 @@ static int write_value(struct write_data *write_data)
int result;
q = quotes_for_value(write_data->value);
- result = git_filebuf_printf(write_data->file,
+ result = git_buf_printf(write_data->buf,
"\t%s = %s%s%s\n", write_data->name, q, write_data->value, q);
/* If we are updating a single name/value, we're done. Setting `value`
@@ -1782,7 +1841,7 @@ static int write_on_eof(struct reader **reader, void *data)
* value.
*/
if ((!write_data->preg || !write_data->preg_replaced) && write_data->value) {
- if ((result = write_section(write_data->file, write_data->section)) == 0)
+ if ((result = write_section(write_data->buf, write_data->section)) == 0)
result = write_value(write_data);
}
@@ -1797,18 +1856,23 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
int result;
char *section, *name, *ldot;
git_filebuf file = GIT_FILEBUF_INIT;
+ git_buf buf = GIT_BUF_INIT;
struct reader *reader = git_array_get(cfg->readers, 0);
struct write_data write_data;
- /* Lock the file */
- if ((result = git_filebuf_open(
- &file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0) {
+ if (cfg->locked) {
+ result = git_buf_puts(&reader->buffer, git_buf_cstr(&cfg->locked_content));
+ } else {
+ /* Lock the file */
+ if ((result = git_filebuf_open(
+ &file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0) {
git_buf_free(&reader->buffer);
return result;
- }
+ }
- /* We need to read in our own config file */
- result = git_futils_readbuffer(&reader->buffer, cfg->file_path);
+ /* We need to read in our own config file */
+ result = git_futils_readbuffer(&reader->buffer, cfg->file_path);
+ }
/* Initialise the reading position */
if (result == GIT_ENOTFOUND) {
@@ -1827,7 +1891,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
name = ldot + 1;
section = git__strndup(key, ldot - key);
- write_data.file = &file;
+ write_data.buf = &buf;
write_data.section = section;
write_data.in_section = 0;
write_data.preg_replaced = 0;
@@ -1843,13 +1907,22 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
goto done;
}
- /* refresh stats - if this errors, then commit will error too */
- (void)git_filebuf_stats(&reader->file_mtime, &reader->file_size, &file);
+ if (cfg->locked) {
+ size_t len = buf.asize;
+ /* Update our copy with the modified contents */
+ git_buf_free(&cfg->locked_content);
+ git_buf_attach(&cfg->locked_content, git_buf_detach(&buf), len);
+ } else {
+ git_filebuf_write(&file, git_buf_cstr(&buf), git_buf_len(&buf));
- result = git_filebuf_commit(&file);
- git_buf_free(&reader->buffer);
+ /* refresh stats - if this errors, then commit will error too */
+ (void)git_filebuf_stats(&reader->file_mtime, &reader->file_size, &file);
+
+ result = git_filebuf_commit(&file);
+ }
done:
+ git_buf_free(&buf);
git_buf_free(&reader->buffer);
return result;
}