return 0;
}
+ if (!strcmp(var, "core.deltabasecachelimit")) {
+ delta_base_cache_limit = git_config_int(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "core.autocrlf")) {
if (value && !strcasecmp(value, "input")) {
auto_crlf = -1;
}
if (!strcmp(var, "i18n.commitencoding")) {
- git_commit_encoding = strdup(value);
+ git_commit_encoding = xstrdup(value);
return 0;
}
if (!strcmp(var, "i18n.logoutputencoding")) {
- git_log_output_encoding = strdup(value);
+ git_log_output_encoding = xstrdup(value);
return 0;
}
static int store_aux(const char* key, const char* value)
{
+ const char *ep;
+ size_t section_len;
+
switch (store.state) {
case KEY_SEEN:
if (matches(key, value)) {
}
break;
case SECTION_SEEN:
- if (strncmp(key, store.key, store.baselen+1)) {
+ /*
+ * What we are looking for is in store.key (both
+ * section and var), and its section part is baselen
+ * long. We found key (again, both section and var).
+ * We would want to know if this key is in the same
+ * section as what we are looking for. We already
+ * know we are in the same section as what should
+ * hold store.key.
+ */
+ ep = strrchr(key, '.');
+ section_len = ep - key;
+
+ if ((section_len != store.baselen) ||
+ memcmp(key, store.key, section_len+1)) {
store.state = SECTION_END_SEEN;
break;
- } else
- /* do not increment matches: this is no match */
- store.offset[store.seen] = ftell(config_file);
+ }
+
+ /*
+ * Do not increment matches: this is no match, but we
+ * just made sure we are in the desired section.
+ */
+ store.offset[store.seen] = ftell(config_file);
/* fallthru */
case SECTION_END_SEEN:
case START:
}
+static int section_name_match (const char *buf, const char *name)
+{
+ int i = 0, j = 0, dot = 0;
+ for (; buf[i] && buf[i] != ']'; i++) {
+ if (!dot && isspace(buf[i])) {
+ dot = 1;
+ if (name[j++] != '.')
+ break;
+ for (i++; isspace(buf[i]); i++)
+ ; /* do nothing */
+ if (buf[i] != '"')
+ break;
+ continue;
+ }
+ if (buf[i] == '\\' && dot)
+ i++;
+ else if (buf[i] == '"' && dot) {
+ for (i++; isspace(buf[i]); i++)
+ ; /* do_nothing */
+ break;
+ }
+ if (buf[i] != name[j++])
+ break;
+ }
+ return (buf[i] == ']' && name[j] == 0);
+}
+
+/* if new_name == NULL, the section is removed instead */
int git_config_rename_section(const char *old_name, const char *new_name)
{
- int ret = 0;
+ int ret = 0, remove = 0;
char *config_filename;
struct lock_file *lock = xcalloc(sizeof(struct lock_file), 1);
int out_fd;
}
if (!(config_file = fopen(config_filename, "rb"))) {
- ret = error("Could not open config file!");
- goto out;
+ /* no config file means nothing to rename, no error */
+ goto unlock_and_out;
}
while (fgets(buf, sizeof(buf), config_file)) {
; /* do nothing */
if (buf[i] == '[') {
/* it's a section */
- int j = 0, dot = 0;
- for (i++; buf[i] && buf[i] != ']'; i++) {
- if (!dot && isspace(buf[i])) {
- dot = 1;
- if (old_name[j++] != '.')
- break;
- for (i++; isspace(buf[i]); i++)
- ; /* do nothing */
- if (buf[i] != '"')
- break;
+ if (section_name_match (&buf[i+1], old_name)) {
+ ret++;
+ if (new_name == NULL) {
+ remove = 1;
continue;
}
- if (buf[i] == '\\' && dot)
- i++;
- else if (buf[i] == '"' && dot) {
- for (i++; isspace(buf[i]); i++)
- ; /* do_nothing */
- break;
- }
- if (buf[i] != old_name[j++])
- break;
- }
- if (buf[i] == ']' && old_name[j] == 0) {
- /* old_name matches */
- ret++;
store.baselen = strlen(new_name);
if (!store_write_section(out_fd, new_name)) {
ret = write_error();
}
continue;
}
+ remove = 0;
}
+ if (remove)
+ continue;
length = strlen(buf);
if (write_in_full(out_fd, buf, length) != length) {
ret = write_error();
}
}
fclose(config_file);
+ unlock_and_out:
if (close(out_fd) || commit_lock_file(lock) < 0)
ret = error("Cannot commit config file!");
out: