int git_config(config_fn_t fn, void *data) { int ret = 0, found = 0; char *repo_config = NULL; const char *home = NULL; /* Setting $GIT_CONFIG makes git read _only_ the given config file. */ if (config_exclusive_filename) return git_config_from_file(fn, config_exclusive_filename, data); if (git_config_system() && !access(git_etc_gitconfig(), R_OK)) { ret += git_config_from_file(fn, git_etc_gitconfig(), data); found += 1; } home = getenv("HOME"); if (git_config_global() && home) { char *user_config = xstrdup(mkpath("%s/.gitconfig", home)); if (!access(user_config, R_OK)) { ret += git_config_from_file(fn, user_config, data); found += 1; } free(user_config); } repo_config = git_pathdup("config"); if (!access(repo_config, R_OK)) { ret += git_config_from_file(fn, repo_config, data); found += 1; } free(repo_config); if (found == 0) return -1; return ret; }
int git_get_config(const char *key, char *buffer, int size, char *git_path) { char *local, *global; const char *home, *system; struct config_buf buf; buf.buf=buffer; buf.size=size; buf.seen = 0; buf.key = key; local=global=system=NULL; home = get_windows_home_directory(); if (home) global = xstrdup(mkpath("%s/.gitconfig", home)); system = git_etc_gitconfig(); local = git_pathdup("config"); if ( !buf.seen) git_config_from_file(get_config, local, &buf); if (!buf.seen && global) git_config_from_file(get_config, global, &buf); if (!buf.seen && system) git_config_from_file(get_config, system, &buf); if(local) free(local); if(global) free(global); return !buf.seen; }
int git_config(config_fn_t fn) { int ret = 0; char *repo_config = NULL; const char *home = NULL, *filename; /* $GIT_CONFIG makes git read _only_ the given config file, * $GIT_CONFIG_LOCAL will make it process it in addition to the * global config file, the same way it would the per-repository * config file otherwise. */ filename = getenv(CONFIG_ENVIRONMENT); if (!filename) { if (git_config_system() && !access(git_etc_gitconfig(), R_OK)) ret += git_config_from_file(fn, git_etc_gitconfig()); home = getenv("HOME"); filename = getenv(CONFIG_LOCAL_ENVIRONMENT); if (!filename) filename = repo_config = xstrdup(git_path("config")); } if (git_config_global() && home) { char *user_config = xstrdup(mkpath("%s/.gitconfig", home)); if (!access(user_config, R_OK)) ret = git_config_from_file(fn, user_config); free(user_config); } ret += git_config_from_file(fn, filename); free(repo_config); return ret; }
static int read_populate_opts(struct replay_opts *opts) { if (is_rebase_i(opts)) { struct strbuf buf = STRBUF_INIT; if (read_oneliner(&buf, rebase_path_gpg_sign_opt(), 1)) { if (!starts_with(buf.buf, "-S")) strbuf_reset(&buf); else { free(opts->gpg_sign); opts->gpg_sign = xstrdup(buf.buf + 2); } } strbuf_release(&buf); return 0; } if (!file_exists(git_path_opts_file())) return 0; /* * The function git_parse_source(), called from git_config_from_file(), * may die() in case of a syntactically incorrect file. We do not care * about this case, though, because we wrote that file ourselves, so we * are pretty certain that it is syntactically correct. */ if (git_config_from_file(populate_opts_cb, git_path_opts_file(), opts) < 0) return error(_("malformed options sheet: '%s'"), git_path_opts_file()); return 0; }
void gitmodules_config(void) { const char *work_tree = get_git_work_tree(); if (work_tree) { struct strbuf gitmodules_path = STRBUF_INIT; int pos; strbuf_addstr(&gitmodules_path, work_tree); strbuf_addstr(&gitmodules_path, "/.gitmodules"); if (read_cache() < 0) die("index file corrupt"); pos = cache_name_pos(".gitmodules", 11); if (pos < 0) { /* .gitmodules not found or isn't merged */ pos = -1 - pos; if (active_nr > pos) { /* there is a .gitmodules */ const struct cache_entry *ce = active_cache[pos]; if (ce_namelen(ce) == 11 && !memcmp(ce->name, ".gitmodules", 11)) gitmodules_is_unmerged = 1; } } if (!gitmodules_is_unmerged) git_config_from_file(submodule_config, gitmodules_path.buf, NULL); strbuf_release(&gitmodules_path); } }
static void read_populate_opts(struct replay_opts **opts_ptr) { if (!file_exists(git_path_opts_file())) return; if (git_config_from_file(populate_opts_cb, git_path_opts_file(), *opts_ptr) < 0) die(_("Malformed options sheet: %s"), git_path_opts_file()); }
int read_repository_format(struct repository_format *format, const char *path) { memset(format, 0, sizeof(*format)); format->version = -1; format->is_bare = -1; string_list_init(&format->unknown_extensions, 1); git_config_from_file(check_repo_format, path, format); return format->version; }
static void read_populate_opts(struct replay_opts **opts_ptr) { const char *opts_file = git_path(SEQ_OPTS_FILE); if (!file_exists(opts_file)) return; if (git_config_from_file(populate_opts_cb, opts_file, *opts_ptr) < 0) die(_("Malformed options sheet: %s"), opts_file); }
int git_get_config(const char *key, char *buffer, int size, char *git_path) { char *local,*global,*system_wide,*p; struct config_buf buf; buf.buf=buffer; buf.size=size; buf.seen = 0; buf.key = key; local=global=system_wide=NULL; //local = config_exclusive_filename; if (!local) { const char *home = get_windows_home_directory(); local=p= git_pathdup("config"); if(git_path&&strlen(git_path)) { local=xstrdup(mkpath("%s/%s", git_path, p)); free(p); } if (git_config_global() && home) global = xstrdup(mkpath("%s/.gitconfig", home)); if (git_config_system()) system_wide = git_etc_gitconfig(); } if ( !buf.seen) git_config_from_file(get_config, local, &buf); if (!buf.seen && global) git_config_from_file(get_config, global, &buf); if (!buf.seen && system_wide) git_config_from_file(get_config, system_wide, &buf); if(local) free(local); if(global) free(global); //if(system_wide) // free(system_wide); return !buf.seen; }
int git_config_early(config_fn_t fn, void *data, const char *repo_config) { int ret = 0, found = 0; const char *home = NULL; /* Setting $GIT_CONFIG makes git read _only_ the given config file. */ if (config_exclusive_filename) return git_config_from_file(fn, config_exclusive_filename, data); if (git_config_system() && !access(git_etc_gitconfig(), R_OK)) { ret += git_config_from_file(fn, git_etc_gitconfig(), data); found += 1; } home = getenv("HOME"); if (home) { char *user_config = xstrdup(mkpath("%s/.gitconfig", home)); if (!access(user_config, R_OK)) { ret += git_config_from_file(fn, user_config, data); found += 1; } free(user_config); } if (repo_config && !access(repo_config, R_OK)) { ret += git_config_from_file(fn, repo_config, data); found += 1; } switch (git_config_from_parameters(fn, data)) { case -1: /* error */ die("unable to parse command-line config"); break; case 0: /* found nothing */ break; default: /* found at least one item */ found++; break; } return ret == 0 ? found : ret; }
void gitmodules_config(void) { const char *work_tree = get_git_work_tree(); if (work_tree) { struct strbuf gitmodules_path = STRBUF_INIT; strbuf_addstr(&gitmodules_path, work_tree); strbuf_addstr(&gitmodules_path, "/.gitmodules"); git_config_from_file(submodule_config, gitmodules_path.buf, NULL); strbuf_release(&gitmodules_path); } }
static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) { struct stat st; struct passwd *pwd; size_t pathlen; struct strbuf rel = STRBUF_INIT; char *p, *slash; int n; size_t size; if (stat(path->buf, &st)) { fprintf(stderr, "Error accessing %s: %s (%d)\n", path->buf, strerror(errno), errno); return; } strbuf_addch(path, '/'); pathlen = path->len; if (ctx.cfg.strict_export) { strbuf_addstr(path, ctx.cfg.strict_export); if(stat(path->buf, &st)) return; strbuf_setlen(path, pathlen); } strbuf_addstr(path, "noweb"); if (!stat(path->buf, &st)) return; strbuf_setlen(path, pathlen); if (!starts_with(path->buf, base)) strbuf_addbuf(&rel, path); else strbuf_addstr(&rel, path->buf + strlen(base) + 1); if (!strcmp(rel.buf + rel.len - 5, "/.git")) strbuf_setlen(&rel, rel.len - 5); else if (rel.len && rel.buf[rel.len - 1] == '/') strbuf_setlen(&rel, rel.len - 1); repo = cgit_add_repo(rel.buf); config_fn = fn; if (ctx.cfg.enable_git_config) { strbuf_addstr(path, "config"); git_config_from_file(gitconfig_config, path->buf, NULL); strbuf_setlen(path, pathlen); } if (ctx.cfg.remove_suffix) { size_t urllen; strip_suffix(repo->url, ".git", &urllen); strip_suffix_mem(repo->url, &urllen, "/"); repo->url[urllen] = '\0'; } repo->path = xstrdup(path->buf); while (!repo->owner) { if ((pwd = getpwuid(st.st_uid)) == NULL) { fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", path->buf, strerror(errno), errno); break; } if (pwd->pw_gecos) if ((p = strchr(pwd->pw_gecos, ','))) *p = '\0'; repo->owner = xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name); } if (repo->desc == cgit_default_repo_desc || !repo->desc) { strbuf_addstr(path, "description"); if (!stat(path->buf, &st)) readfile(path->buf, &repo->desc, &size); strbuf_setlen(path, pathlen); } if (ctx.cfg.section_from_path) { n = ctx.cfg.section_from_path; if (n > 0) { slash = rel.buf - 1; while (slash && n && (slash = strchr(slash + 1, '/'))) n--; } else { slash = rel.buf + rel.len; while (slash && n && (slash = xstrrchr(rel.buf, slash - 1, '/'))) n++; } if (slash && !n) { *slash = '\0'; repo->section = xstrdup(rel.buf); *slash = '/'; if (starts_with(repo->name, repo->section)) { repo->name += strlen(repo->section); if (*repo->name == '/') repo->name++; } } } strbuf_addstr(path, "cgitrc"); if (!stat(path->buf, &st)) parse_configfile(path->buf, &repo_config); strbuf_release(&rel); }
/* * If value==NULL, unset in (remove from) config, * if value_regex!=NULL, disregard key/value pairs where value does not match. * if multi_replace==0, nothing, or only one matching key/value is replaced, * else all matching key/values (regardless how many) are removed, * before the new pair is written. * * Returns 0 on success. * * This function does this: * * - it locks the config file by creating ".git/config.lock" * * - it then parses the config using store_aux() as validator to find * the position on the key/value pair to replace. If it is to be unset, * it must be found exactly once. * * - the config file is mmap()ed and the part before the match (if any) is * written to the lock file, then the changed part and the rest. * * - the config file is removed and the lock file rename()d to it. * */ int git_config_set_multivar(const char* key, const char* value, const char* value_regex, int multi_replace) { int i, dot; int fd = -1, in_fd; int ret; char* config_filename; struct lock_file *lock = NULL; const char* last_dot = strrchr(key, '.'); if (config_exclusive_filename) config_filename = xstrdup(config_exclusive_filename); else config_filename = git_pathdup("config"); /* * Since "key" actually contains the section name and the real * key name separated by a dot, we have to know where the dot is. */ if (last_dot == NULL) { error("key does not contain a section: %s", key); ret = 2; goto out_free; } store.baselen = last_dot - key; store.multi_replace = multi_replace; /* * Validate the key and while at it, lower case it for matching. */ store.key = xmalloc(strlen(key) + 1); dot = 0; for (i = 0; key[i]; i++) { unsigned char c = key[i]; if (c == '.') dot = 1; /* Leave the extended basename untouched.. */ if (!dot || i > store.baselen) { if (!iskeychar(c) || (i == store.baselen+1 && !isalpha(c))) { error("invalid key: %s", key); free(store.key); ret = 1; goto out_free; } c = tolower(c); } else if (c == '\n') { error("invalid key (newline): %s", key); free(store.key); ret = 1; goto out_free; } store.key[i] = c; } store.key[i] = 0; /* * The lock serves a purpose in addition to locking: the new * contents of .git/config will be written into it. */ lock = xcalloc(sizeof(struct lock_file), 1); fd = hold_lock_file_for_update(lock, config_filename, 0); if (fd < 0) { error("could not lock config file %s", config_filename); free(store.key); ret = -1; goto out_free; } /* * If .git/config does not exist yet, write a minimal version. */ in_fd = open(config_filename, O_RDONLY); if ( in_fd < 0 ) { free(store.key); if ( ENOENT != errno ) { error("opening %s: %s", config_filename, strerror(errno)); ret = 3; /* same as "invalid config file" */ goto out_free; } /* if nothing to unset, error out */ if (value == NULL) { ret = 5; goto out_free; } store.key = (char*)key; if (!store_write_section(fd, key) || !store_write_pair(fd, key, value)) goto write_err_out; } else { struct stat st; char* contents; size_t contents_sz, copy_begin, copy_end; int i, new_line = 0; if (value_regex == NULL) store.value_regex = NULL; else { if (value_regex[0] == '!') { store.do_not_match = 1; value_regex++; } else store.do_not_match = 0; store.value_regex = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(store.value_regex, value_regex, REG_EXTENDED)) { error("invalid pattern: %s", value_regex); free(store.value_regex); ret = 6; goto out_free; } } store.offset[0] = 0; store.state = START; store.seen = 0; /* * After this, store.offset will contain the *end* offset * of the last match, or remain at 0 if no match was found. * As a side effect, we make sure to transform only a valid * existing config file. */ if (git_config_from_file(store_aux, config_filename, NULL)) { error("invalid config file %s", config_filename); free(store.key); if (store.value_regex != NULL) { regfree(store.value_regex); free(store.value_regex); } ret = 3; goto out_free; } free(store.key); if (store.value_regex != NULL) { regfree(store.value_regex); free(store.value_regex); } /* if nothing to unset, or too many matches, error out */ if ((store.seen == 0 && value == NULL) || (store.seen > 1 && multi_replace == 0)) { ret = 5; goto out_free; } fstat(in_fd, &st); contents_sz = xsize_t(st.st_size); contents = xmmap(NULL, contents_sz, PROT_READ, MAP_PRIVATE, in_fd, 0); close(in_fd); if (store.seen == 0) store.seen = 1; for (i = 0, copy_begin = 0; i < store.seen; i++) { if (store.offset[i] == 0) { store.offset[i] = copy_end = contents_sz; } else if (store.state != KEY_SEEN) { copy_end = store.offset[i]; } else copy_end = find_beginning_of_line( contents, contents_sz, store.offset[i]-2, &new_line); if (copy_end > 0 && contents[copy_end-1] != '\n') new_line = 1; /* write the first part of the config */ if (copy_end > copy_begin) { if (write_in_full(fd, contents + copy_begin, copy_end - copy_begin) < copy_end - copy_begin) goto write_err_out; if (new_line && write_in_full(fd, "\n", 1) != 1) goto write_err_out; } copy_begin = store.offset[i]; } /* write the pair (value == NULL means unset) */ if (value != NULL) { if (store.state == START) { if (!store_write_section(fd, key)) goto write_err_out; } if (!store_write_pair(fd, key, value)) goto write_err_out; } /* write the rest of the config */ if (copy_begin < contents_sz) if (write_in_full(fd, contents + copy_begin, contents_sz - copy_begin) < contents_sz - copy_begin) goto write_err_out; munmap(contents, contents_sz); } if (commit_lock_file(lock) < 0) { error("could not commit config file %s", config_filename); ret = 4; goto out_free; } /* * lock is committed, so don't try to roll it back below. * NOTE: Since lockfile.c keeps a linked list of all created * lock_file structures, it isn't safe to free(lock). It's * better to just leave it hanging around. */ lock = NULL; ret = 0; out_free: if (lock) rollback_lock_file(lock); free(config_filename); return ret; write_err_out: ret = write_error(lock->filename); goto out_free; }
static int get_value(const char* key_, const char* regex_) { int ret = -1; char *tl; char *global = NULL, *repo_config = NULL; const char *system_wide = NULL, *local; local = getenv(CONFIG_ENVIRONMENT); if (!local) { const char *home = getenv("HOME"); local = getenv(CONFIG_LOCAL_ENVIRONMENT); if (!local) local = repo_config = xstrdup(git_path("config")); if (git_config_global() && home) global = xstrdup(mkpath("%s/.gitconfig", home)); if (git_config_system()) system_wide = git_etc_gitconfig(); } key = xstrdup(key_); for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl) *tl = tolower(*tl); for (tl=key; *tl && *tl != '.'; ++tl) *tl = tolower(*tl); if (use_key_regexp) { key_regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(key_regexp, key, REG_EXTENDED)) { fprintf(stderr, "Invalid key pattern: %s\n", key_); goto free_strings; } } if (regex_) { if (regex_[0] == '!') { do_not_match = 1; regex_++; } regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(regexp, regex_, REG_EXTENDED)) { fprintf(stderr, "Invalid pattern: %s\n", regex_); goto free_strings; } } if (do_all && system_wide) git_config_from_file(show_config, system_wide); if (do_all && global) git_config_from_file(show_config, global); git_config_from_file(show_config, local); if (!do_all && !seen && global) git_config_from_file(show_config, global); if (!do_all && !seen && system_wide) git_config_from_file(show_config, system_wide); free(key); if (regexp) { regfree(regexp); free(regexp); } if (do_all) ret = !seen; else ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1; free_strings: free(repo_config); free(global); return ret; }
/* * If value==NULL, unset in (remove from) config, * if value_regex!=NULL, disregard key/value pairs where value does not match. * if multi_replace==0, nothing, or only one matching key/value is replaced, * else all matching key/values (regardless how many) are removed, * before the new pair is written. * * Returns 0 on success. * * This function does this: * * - it locks the config file by creating ".git/config.lock" * * - it then parses the config using store_aux() as validator to find * the position on the key/value pair to replace. If it is to be unset, * it must be found exactly once. * * - the config file is mmap()ed and the part before the match (if any) is * written to the lock file, then the changed part and the rest. * * - the config file is removed and the lock file rename()d to it. * */ int git_config_set_multivar(const char *key, const char *value, const char *value_regex, int multi_replace) { int fd = -1, in_fd; int ret; char *config_filename; struct lock_file *lock = NULL; if (config_exclusive_filename) config_filename = xstrdup(config_exclusive_filename); else config_filename = git_pathdup("config"); /* parse-key returns negative; flip the sign to feed exit(3) */ ret = 0 - git_config_parse_key(key, &store.key, &store.baselen); if (ret) goto out_free; store.multi_replace = multi_replace; /* * The lock serves a purpose in addition to locking: the new * contents of .git/config will be written into it. */ lock = xcalloc(sizeof(struct lock_file), 1); fd = hold_lock_file_for_update(lock, config_filename, 0); if (fd < 0) { error("could not lock config file %s: %s", config_filename, strerror(errno)); free(store.key); ret = CONFIG_NO_LOCK; goto out_free; } /* * If .git/config does not exist yet, write a minimal version. */ in_fd = open(config_filename, O_RDONLY); if ( in_fd < 0 ) { free(store.key); if ( ENOENT != errno ) { error("opening %s: %s", config_filename, strerror(errno)); ret = CONFIG_INVALID_FILE; /* same as "invalid config file" */ goto out_free; } /* if nothing to unset, error out */ if (value == NULL) { ret = CONFIG_NOTHING_SET; goto out_free; } store.key = (char *)key; if (!store_write_section(fd, key) || !store_write_pair(fd, key, value)) goto write_err_out; } else { struct stat st; char *contents; size_t contents_sz, copy_begin, copy_end; int i, new_line = 0; if (value_regex == NULL) store.value_regex = NULL; else { if (value_regex[0] == '!') { store.do_not_match = 1; value_regex++; } else store.do_not_match = 0; store.value_regex = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(store.value_regex, value_regex, REG_EXTENDED)) { error("invalid pattern: %s", value_regex); free(store.value_regex); ret = CONFIG_INVALID_PATTERN; goto out_free; } } store.offset[0] = 0; store.state = START; store.seen = 0; /* * After this, store.offset will contain the *end* offset * of the last match, or remain at 0 if no match was found. * As a side effect, we make sure to transform only a valid * existing config file. */ if (git_config_from_file(store_aux, config_filename, NULL)) { error("invalid config file %s", config_filename); free(store.key); if (store.value_regex != NULL) { regfree(store.value_regex); free(store.value_regex); } ret = CONFIG_INVALID_FILE; goto out_free; } free(store.key); if (store.value_regex != NULL) { regfree(store.value_regex); free(store.value_regex); } /* if nothing to unset, or too many matches, error out */ if ((store.seen == 0 && value == NULL) || (store.seen > 1 && multi_replace == 0)) { ret = CONFIG_NOTHING_SET; goto out_free; } fstat(in_fd, &st); contents_sz = xsize_t(st.st_size); contents = xmmap(NULL, contents_sz, PROT_READ, MAP_PRIVATE, in_fd, 0); close(in_fd); if (store.seen == 0) store.seen = 1; for (i = 0, copy_begin = 0; i < store.seen; i++) { if (store.offset[i] == 0) { store.offset[i] = copy_end = contents_sz; } else if (store.state != KEY_SEEN) { copy_end = store.offset[i]; } else copy_end = find_beginning_of_line( contents, contents_sz, store.offset[i]-2, &new_line); if (copy_end > 0 && contents[copy_end-1] != '\n') new_line = 1; /* write the first part of the config */ if (copy_end > copy_begin) { if (write_in_full(fd, contents + copy_begin, copy_end - copy_begin) < copy_end - copy_begin) goto write_err_out; if (new_line && write_str_in_full(fd, "\n") != 1) goto write_err_out; } copy_begin = store.offset[i]; } /* write the pair (value == NULL means unset) */ if (value != NULL) { if (store.state == START) { if (!store_write_section(fd, key)) goto write_err_out; } if (!store_write_pair(fd, key, value)) goto write_err_out; } /* write the rest of the config */ if (copy_begin < contents_sz) if (write_in_full(fd, contents + copy_begin, contents_sz - copy_begin) < contents_sz - copy_begin) goto write_err_out; munmap(contents, contents_sz); } if (commit_lock_file(lock) < 0) { error("could not commit config file %s", config_filename); ret = CONFIG_NO_WRITE; goto out_free; } /* * lock is committed, so don't try to roll it back below. * NOTE: Since lockfile.c keeps a linked list of all created * lock_file structures, it isn't safe to free(lock). It's * better to just leave it hanging around. */ lock = NULL; ret = 0; out_free: if (lock) rollback_lock_file(lock); free(config_filename); return ret; write_err_out: ret = write_error(lock->filename); goto out_free; }
int git_config(config_fn_t fn) { return git_config_from_file(fn, git_path("config")); }
static int get_value(const char *key_, const char *regex_) { int ret = -1; char *global = NULL, *xdg = NULL, *repo_config = NULL; const char *system_wide = NULL, *local; struct config_include_data inc = CONFIG_INCLUDE_INIT; config_fn_t fn; void *data; local = given_config_file; if (!local) { local = repo_config = git_pathdup("config"); if (git_config_system()) system_wide = git_etc_gitconfig(); home_config_paths(&global, &xdg, "config"); } if (use_key_regexp) { char *tl; /* * NEEDSWORK: this naive pattern lowercasing obviously does not * work for more complex patterns like "^[^.]*Foo.*bar". * Perhaps we should deprecate this altogether someday. */ key = xstrdup(key_); for (tl = key + strlen(key) - 1; tl >= key && *tl != '.'; tl--) *tl = tolower(*tl); for (tl = key; *tl && *tl != '.'; tl++) *tl = tolower(*tl); key_regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(key_regexp, key, REG_EXTENDED)) { fprintf(stderr, "Invalid key pattern: %s\n", key_); free(key); goto free_strings; } } else { if (git_config_parse_key(key_, &key, NULL)) goto free_strings; } if (regex_) { if (regex_[0] == '!') { do_not_match = 1; regex_++; } regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(regexp, regex_, REG_EXTENDED)) { fprintf(stderr, "Invalid pattern: %s\n", regex_); goto free_strings; } } fn = show_config; data = NULL; if (respect_includes) { inc.fn = fn; inc.data = data; fn = git_config_include; data = &inc; } if (do_all && system_wide) git_config_from_file(fn, system_wide, data); if (do_all && xdg) git_config_from_file(fn, xdg, data); if (do_all && global) git_config_from_file(fn, global, data); if (do_all) git_config_from_file(fn, local, data); git_config_from_parameters(fn, data); if (!do_all && !seen) git_config_from_file(fn, local, data); if (!do_all && !seen && global) git_config_from_file(fn, global, data); if (!do_all && !seen && xdg) git_config_from_file(fn, xdg, data); if (!do_all && !seen && system_wide) git_config_from_file(fn, system_wide, data); free(key); if (regexp) { regfree(regexp); free(regexp); } if (do_all) ret = !seen; else ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1; free_strings: free(repo_config); free(global); free(xdg); return ret; }
static void add_repo(const char *base, const char *path, repo_config_fn fn) { struct stat st; struct passwd *pwd; char *rel, *p, *slash; int n; size_t size; if (stat(path, &st)) { fprintf(stderr, "Error accessing %s: %s (%d)\n", path, strerror(errno), errno); return; } if (ctx.cfg.strict_export && stat(fmt("%s/%s", path, ctx.cfg.strict_export), &st)) return; if (!stat(fmt("%s/noweb", path), &st)) return; if (base == path) rel = xstrdup(fmt("%s", path)); else rel = xstrdup(fmt("%s", path + strlen(base) + 1)); if (!strcmp(rel + strlen(rel) - 5, "/.git")) rel[strlen(rel) - 5] = '\0'; repo = cgit_add_repo(rel); config_fn = fn; if (ctx.cfg.enable_git_config) git_config_from_file(gitconfig_config, fmt("%s/config", path), NULL); if (ctx.cfg.remove_suffix) if ((p = strrchr(repo->url, '.')) && !strcmp(p, ".git")) *p = '\0'; repo->path = xstrdup(path); while (!repo->owner) { if ((pwd = getpwuid(st.st_uid)) == NULL) { fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", path, strerror(errno), errno); break; } if (pwd->pw_gecos) if ((p = strchr(pwd->pw_gecos, ','))) *p = '\0'; repo->owner = xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name); } if (repo->desc == cgit_default_repo_desc || !repo->desc) { p = fmt("%s/description", path); if (!stat(p, &st)) readfile(p, &repo->desc, &size); } if (!repo->readme) { p = fmt("%s/README.html", path); if (!stat(p, &st)) repo->readme = "README.html"; } if (ctx.cfg.section_from_path) { n = ctx.cfg.section_from_path; if (n > 0) { slash = rel; while (slash && n && (slash = strchr(slash, '/'))) n--; } else { slash = rel + strlen(rel); while (slash && n && (slash = xstrrchr(rel, slash, '/'))) n++; } if (slash && !n) { *slash = '\0'; repo->section = xstrdup(rel); *slash = '/'; if (!prefixcmp(repo->name, repo->section)) { repo->name += strlen(repo->section); if (*repo->name == '/') repo->name++; } } } p = fmt("%s/cgitrc", path); if (!stat(p, &st)) parse_configfile(xstrdup(p), &repo_config); free(rel); }
static int get_value(const char *key_, const char *regex_) { int ret = -1; char *global = NULL, *repo_config = NULL; const char *system_wide = NULL, *local; local = config_exclusive_filename; if (!local) { const char *home = getenv("HOME"); local = repo_config = git_pathdup("config"); if (home) global = xstrdup(mkpath("%s/.gitconfig", home)); if (git_config_system()) system_wide = git_etc_gitconfig(); } if (use_key_regexp) { char *tl; /* * NEEDSWORK: this naive pattern lowercasing obviously does not * work for more complex patterns like "^[^.]*Foo.*bar". * Perhaps we should deprecate this altogether someday. */ key = xstrdup(key_); for (tl = key + strlen(key) - 1; tl >= key && *tl != '.'; tl--) *tl = tolower(*tl); for (tl = key; *tl && *tl != '.'; tl++) *tl = tolower(*tl); key_regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(key_regexp, key, REG_EXTENDED)) { fprintf(stderr, "Invalid key pattern: %s\n", key_); free(key); goto free_strings; } } else { if (git_config_parse_key(key_, &key, NULL)) goto free_strings; } if (regex_) { if (regex_[0] == '!') { do_not_match = 1; regex_++; } regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(regexp, regex_, REG_EXTENDED)) { fprintf(stderr, "Invalid pattern: %s\n", regex_); goto free_strings; } } if (do_all && system_wide) git_config_from_file(show_config, system_wide, NULL); if (do_all && global) git_config_from_file(show_config, global, NULL); if (do_all) git_config_from_file(show_config, local, NULL); git_config_from_parameters(show_config, NULL); if (!do_all && !seen) git_config_from_file(show_config, local, NULL); if (!do_all && !seen && global) git_config_from_file(show_config, global, NULL); if (!do_all && !seen && system_wide) git_config_from_file(show_config, system_wide, NULL); free(key); if (regexp) { regfree(regexp); free(regexp); } if (do_all) ret = !seen; else ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1; free_strings: free(repo_config); free(global); return ret; }