Skip to content

Commit 95f29fb

Browse files
committed
config: skip r/o backends when writing
Configuration backends have a readonly-flag which is currently used to distinguish configuration snapshots. But somewhat unexpectedly, we do not use the flag to prevent writing to a readonly backend but happily proceed to do so. This commit modifies logic to also honor the readonly flag for configuration setters. We will now traverse through all backends and pick the first one which is not marked as read-only whenever we want to write new configuration.
1 parent 6424413 commit 95f29fb

File tree

1 file changed

+41
-22
lines changed

1 file changed

+41
-22
lines changed

src/config.c

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -576,22 +576,50 @@ int git_config_foreach_match(
576576
* Setters
577577
**************/
578578

579-
static int config_error_nofiles(const char *name)
579+
typedef enum {
580+
BACKEND_USE_SET,
581+
BACKEND_USE_DELETE
582+
} backend_use;
583+
584+
static const char *uses[] = {
585+
"set",
586+
"delete"
587+
};
588+
589+
static int get_backend_for_use(git_config_backend **out,
590+
git_config *cfg, const char *name, backend_use use)
580591
{
592+
size_t i;
593+
file_internal *f;
594+
595+
*out = NULL;
596+
597+
if (git_vector_length(&cfg->files) == 0) {
598+
giterr_set(GITERR_CONFIG,
599+
"cannot %s value for '%s' when no config files exist",
600+
uses[use], name);
601+
return GIT_ENOTFOUND;
602+
}
603+
604+
git_vector_foreach(&cfg->files, i, f) {
605+
if (!f->file->readonly) {
606+
*out = f->file;
607+
return 0;
608+
}
609+
}
610+
581611
giterr_set(GITERR_CONFIG,
582-
"cannot set value for '%s' when no config files exist", name);
612+
"cannot %s value for '%s' when all config files are readonly",
613+
uses[use], name);
583614
return GIT_ENOTFOUND;
584615
}
585616

586617
int git_config_delete_entry(git_config *cfg, const char *name)
587618
{
588619
git_config_backend *file;
589-
file_internal *internal;
590620

591-
internal = git_vector_get(&cfg->files, 0);
592-
if (!internal || !internal->file)
593-
return config_error_nofiles(name);
594-
file = internal->file;
621+
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
622+
return GIT_ENOTFOUND;
595623

596624
return file->del(file, name);
597625
}
@@ -617,17 +645,14 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
617645
{
618646
int error;
619647
git_config_backend *file;
620-
file_internal *internal;
621648

622649
if (!value) {
623650
giterr_set(GITERR_CONFIG, "the value to set cannot be NULL");
624651
return -1;
625652
}
626653

627-
internal = git_vector_get(&cfg->files, 0);
628-
if (!internal || !internal->file)
629-
return config_error_nofiles(name);
630-
file = internal->file;
654+
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_SET) < 0)
655+
return GIT_ENOTFOUND;
631656

632657
error = file->set(file, name, value);
633658

@@ -1032,25 +1057,19 @@ int git_config_multivar_iterator_new(git_config_iterator **out, const git_config
10321057
int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
10331058
{
10341059
git_config_backend *file;
1035-
file_internal *internal;
10361060

1037-
internal = git_vector_get(&cfg->files, 0);
1038-
if (!internal || !internal->file)
1039-
return config_error_nofiles(name);
1040-
file = internal->file;
1061+
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
1062+
return GIT_ENOTFOUND;
10411063

10421064
return file->set_multivar(file, name, regexp, value);
10431065
}
10441066

10451067
int git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp)
10461068
{
10471069
git_config_backend *file;
1048-
file_internal *internal;
10491070

1050-
internal = git_vector_get(&cfg->files, 0);
1051-
if (!internal || !internal->file)
1052-
return config_error_nofiles(name);
1053-
file = internal->file;
1071+
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
1072+
return GIT_ENOTFOUND;
10541073

10551074
return file->del_multivar(file, name, regexp);
10561075
}

0 commit comments

Comments
 (0)