Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
int git_get_config(const char *key, char *buffer, int size)
{
	char *local, *global, *globalxdg;
	const char *home, *system;
	struct config_buf buf;
	struct git_config_source config_source = { 0 };

	buf.buf=buffer;
	buf.size=size;
	buf.seen = 0;
	buf.key = key;

	home = get_windows_home_directory();
	if (home)
	{
		global = xstrdup(mkpath("%s/.gitconfig", home));
		globalxdg = xstrdup(mkpath("%s/.config/git/config", home));
	}
	else
	{
		global = NULL;
		globalxdg = NULL;
	}

	system = git_etc_gitconfig();

	local = git_pathdup("config");

	if (!buf.seen)
	{
		config_source.file = local;
		git_config_with_options(get_config, &buf, &config_source, 1);
	}
	if (!buf.seen && global)
	{
		config_source.file = global;
		git_config_with_options(get_config, &buf, &config_source, 1);
	}
	if (!buf.seen && globalxdg)
	{
		config_source.file = globalxdg;
		git_config_with_options(get_config, &buf, &config_source, 1);
	}
	if (!buf.seen && system)
	{
		config_source.file = system;
		git_config_with_options(get_config, &buf, &config_source, 1);
	}

	if(local)
		free(local);
	if(global)
		free(global);
	if (globalxdg)
		free(globalxdg);

	return !buf.seen;
}
Пример #5
0
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;
}
Пример #6
0
int get_set_config(const char *key, char *value, CONFIG_TYPE type,char *git_path)
{
	char *local,*global,*system_wide,*p;
	int ret;
	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();
	}

	switch(type)
	{
	case CONFIG_LOCAL:
		config_exclusive_filename  = local;
		break;
	case CONFIG_GLOBAL:
		config_exclusive_filename = global;
		break;
	case CONFIG_SYSTEM:
		config_exclusive_filename = system_wide;
		break;
	default:
		config_exclusive_filename = NULL;
		break;
	}

	if(!config_exclusive_filename)
		return -1;

	ret = git_config_set(key, value);

	if(local)
		free(local);
	if(global)
		free(global);
	//if(system_wide)
	//	free(system_wide);

	return ret;
}
Пример #7
0
// wchar_t wrapper for git_etc_gitconfig()
const wchar_t *wget_msysgit_etc(void)
{
	static const wchar_t *etc_gitconfig = NULL;
	wchar_t wpointer[MAX_PATH];

	if (etc_gitconfig)
		return etc_gitconfig;

	if (xutftowcs_path(wpointer, git_etc_gitconfig()) < 0)
		return NULL;

	etc_gitconfig = _wcsdup(wpointer);

	return etc_gitconfig;
}
Пример #8
0
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;
}
Пример #9
0
int cmd_config(int argc, const char **argv, const char *prefix)
{
    int nongit = !startup_info->have_repository;
    char *value;

    given_config_file = getenv(CONFIG_ENVIRONMENT);

    argc = parse_options(argc, argv, prefix, builtin_config_options,
                         builtin_config_usage,
                         PARSE_OPT_STOP_AT_NON_OPTION);

    if (use_global_config + use_system_config + use_local_config + !!given_config_file > 1) {
        error("only one config file at a time.");
        usage_with_options(builtin_config_usage, builtin_config_options);
    }

    if (use_global_config) {
        char *user_config = NULL;
        char *xdg_config = NULL;

        home_config_paths(&user_config, &xdg_config, "config");

        if (access(user_config, R_OK) && !access(xdg_config, R_OK))
            given_config_file = xdg_config;
        else if (user_config)
            given_config_file = user_config;
        else
            die("$HOME not set");
    }
    else if (use_system_config)
        given_config_file = git_etc_gitconfig();
    else if (use_local_config)
        given_config_file = git_pathdup("config");
    else if (given_config_file) {
        if (!is_absolute_path(given_config_file) && prefix)
            given_config_file =
                xstrdup(prefix_filename(prefix,
                                        strlen(prefix),
                                        given_config_file));
    }

    if (respect_includes == -1)
        respect_includes = !given_config_file;

    if (end_null) {
        term = '\0';
        delim = '\n';
        key_delim = '\n';
    }

    if (HAS_MULTI_BITS(types)) {
        error("only one type at a time.");
        usage_with_options(builtin_config_usage, builtin_config_options);
    }

    if (get_color_slot)
        actions |= ACTION_GET_COLOR;
    if (get_colorbool_slot)
        actions |= ACTION_GET_COLORBOOL;

    if ((get_color_slot || get_colorbool_slot) && types) {
        error("--get-color and variable type are incoherent");
        usage_with_options(builtin_config_usage, builtin_config_options);
    }

    if (HAS_MULTI_BITS(actions)) {
        error("only one action at a time.");
        usage_with_options(builtin_config_usage, builtin_config_options);
    }
    if (actions == 0)
        switch (argc) {
        case 1:
            actions = ACTION_GET;
            break;
        case 2:
            actions = ACTION_SET;
            break;
        case 3:
            actions = ACTION_SET_ALL;
            break;
        default:
            usage_with_options(builtin_config_usage, builtin_config_options);
        }

    if (actions == ACTION_LIST) {
        check_argc(argc, 0, 0);
        if (git_config_with_options(show_all_config, NULL,
                                    given_config_file,
                                    respect_includes) < 0) {
            if (given_config_file)
                die_errno("unable to read config file '%s'",
                          given_config_file);
            else
                die("error processing config file(s)");
        }
    }
    else if (actions == ACTION_EDIT) {
        check_argc(argc, 0, 0);
        if (!given_config_file && nongit)
            die("not in a git directory");
        git_config(git_default_config, NULL);
        launch_editor(given_config_file ?
                      given_config_file : git_path("config"),
                      NULL, NULL);
    }
    else if (actions == ACTION_SET) {
        int ret;
        check_argc(argc, 2, 2);
        value = normalize_value(argv[0], argv[1]);
        ret = git_config_set_in_file(given_config_file, argv[0], value);
        if (ret == CONFIG_NOTHING_SET)
            error("cannot overwrite multiple values with a single value\n"
                  "       Use a regexp, --add or --replace-all to change %s.", argv[0]);
        return ret;
    }
    else if (actions == ACTION_SET_ALL) {
        check_argc(argc, 2, 3);
        value = normalize_value(argv[0], argv[1]);
        return git_config_set_multivar_in_file(given_config_file,
                                               argv[0], value, argv[2], 0);
    }
    else if (actions == ACTION_ADD) {
        check_argc(argc, 2, 2);
        value = normalize_value(argv[0], argv[1]);
        return git_config_set_multivar_in_file(given_config_file,
                                               argv[0], value, "^$", 0);
    }
    else if (actions == ACTION_REPLACE_ALL) {
        check_argc(argc, 2, 3);
        value = normalize_value(argv[0], argv[1]);
        return git_config_set_multivar_in_file(given_config_file,
                                               argv[0], value, argv[2], 1);
    }
    else if (actions == ACTION_GET) {
        check_argc(argc, 1, 2);
        return get_value(argv[0], argv[1]);
    }
    else if (actions == ACTION_GET_ALL) {
        do_all = 1;
        check_argc(argc, 1, 2);
        return get_value(argv[0], argv[1]);
    }
    else if (actions == ACTION_GET_REGEXP) {
        show_keys = 1;
        use_key_regexp = 1;
        do_all = 1;
        check_argc(argc, 1, 2);
        return get_value(argv[0], argv[1]);
    }
    else if (actions == ACTION_UNSET) {
        check_argc(argc, 1, 2);
        if (argc == 2)
            return git_config_set_multivar_in_file(given_config_file,
                                                   argv[0], NULL, argv[1], 0);
        else
            return git_config_set_in_file(given_config_file,
                                          argv[0], NULL);
    }
    else if (actions == ACTION_UNSET_ALL) {
        check_argc(argc, 1, 2);
        return git_config_set_multivar_in_file(given_config_file,
                                               argv[0], NULL, argv[1], 1);
    }
    else if (actions == ACTION_RENAME_SECTION) {
        int ret;
        check_argc(argc, 2, 2);
        ret = git_config_rename_section_in_file(given_config_file,
                                                argv[0], argv[1]);
        if (ret < 0)
            return ret;
        if (ret == 0)
            die("No such section!");
    }
    else if (actions == ACTION_REMOVE_SECTION) {
        int ret;
        check_argc(argc, 1, 1);
        ret = git_config_rename_section_in_file(given_config_file,
                                                argv[0], NULL);
        if (ret < 0)
            return ret;
        if (ret == 0)
            die("No such section!");
    }
    else if (actions == ACTION_GET_COLOR) {
        get_color(argv[0]);
    }
    else if (actions == ACTION_GET_COLORBOOL) {
        if (argc == 1)
            color_stdout_is_tty = git_config_bool("command line", argv[0]);
        return get_colorbool(argc != 0);
    }

    return 0;
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
int git_get_config(const char *key, char *buffer, int size)
{
	const char *home, *system, *programdata;
	struct config_buf buf;
	struct git_config_source config_source = { 0 };

	struct config_options opts = { 0 };
	opts.respect_includes = 1;

	buf.buf=buffer;
	buf.size=size;
	buf.seen = 0;
	buf.key = key;

	if (have_git_dir())
	{
		opts.git_dir = get_git_dir();
		char* local = git_pathdup("config");
		config_source.file = local;
		config_with_options(get_config, &buf, &config_source, &opts);
		free(local);
		if (buf.seen)
			return !buf.seen;
	}

	home = get_windows_home_directory();
	if (home)
	{
		char* global = xstrdup(mkpath("%s/.gitconfig", home));
		if (global)
		{
			config_source.file = global;
			config_with_options(get_config, &buf, &config_source, &opts);
			free(global);
			if (buf.seen)
				return !buf.seen;
		}
		char* globalxdg = xstrdup(mkpath("%s/.config/git/config", home));
		if (globalxdg)
		{
			config_source.file = globalxdg;
			config_with_options(get_config, &buf, &config_source, &opts);
			free(globalxdg);
			if (buf.seen)
				return !buf.seen;
		}
	}

	system = git_etc_gitconfig();
	if (system)
	{
		config_source.file = system;
		config_with_options(get_config, &buf, &config_source, &opts);
		if (buf.seen)
			return !buf.seen;
	}

	programdata = git_program_data_config();
	if (programdata)
	{
		config_source.file = programdata;
		config_with_options(get_config, &buf, &config_source, &opts);
	}

	return !buf.seen;
}
Пример #13
0
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;
}
Пример #14
0
int cmd_config(int argc, const char **argv, const char *prefix)
{
	int nongit;
	char* value;
	const char *file = setup_git_directory_gently(&nongit);

	while (1 < argc) {
		if (!strcmp(argv[1], "--int"))
			type = T_INT;
		else if (!strcmp(argv[1], "--bool"))
			type = T_BOOL;
		else if (!strcmp(argv[1], "--bool-or-int"))
			type = T_BOOL_OR_INT;
		else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) {
			if (argc != 2)
				usage(git_config_set_usage);
			if (git_config(show_all_config) < 0 && file && errno)
				die("unable to read config file %s: %s", file,
				    strerror(errno));
			return 0;
		}
		else if (!strcmp(argv[1], "--global")) {
			char *home = getenv("HOME");
			if (home) {
				char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
				setenv(CONFIG_ENVIRONMENT, user_config, 1);
				free(user_config);
			} else {
				die("$HOME not set");
			}
		}
		else if (!strcmp(argv[1], "--system"))
			setenv(CONFIG_ENVIRONMENT, git_etc_gitconfig(), 1);
		else if (!strcmp(argv[1], "--file") || !strcmp(argv[1], "-f")) {
			if (argc < 3)
				usage(git_config_set_usage);
			if (!is_absolute_path(argv[2]) && file)
				file = prefix_filename(file, strlen(file),
						       argv[2]);
			else
				file = argv[2];
			setenv(CONFIG_ENVIRONMENT, file, 1);
			argc--;
			argv++;
		}
		else if (!strcmp(argv[1], "--null") || !strcmp(argv[1], "-z")) {
			term = '\0';
			delim = '\n';
			key_delim = '\n';
		}
		else if (!strcmp(argv[1], "--rename-section")) {
			int ret;
			if (argc != 4)
				usage(git_config_set_usage);
			ret = git_config_rename_section(argv[2], argv[3]);
			if (ret < 0)
				return ret;
			if (ret == 0) {
				fprintf(stderr, "No such section!\n");
				return 1;
			}
			return 0;
		}
		else if (!strcmp(argv[1], "--remove-section")) {
			int ret;
			if (argc != 3)
				usage(git_config_set_usage);
			ret = git_config_rename_section(argv[2], NULL);
			if (ret < 0)
				return ret;
			if (ret == 0) {
				fprintf(stderr, "No such section!\n");
				return 1;
			}
			return 0;
		} else if (!strcmp(argv[1], "--get-color")) {
			return get_color(argc-2, argv+2);
		} else if (!strcmp(argv[1], "--get-colorbool")) {
			return get_colorbool(argc-2, argv+2);
		} else
			break;
		argc--;
		argv++;
	}

	switch (argc) {
	case 2:
		return get_value(argv[1], NULL);
	case 3:
		if (!strcmp(argv[1], "--unset"))
			return git_config_set(argv[2], NULL);
		else if (!strcmp(argv[1], "--unset-all"))
			return git_config_set_multivar(argv[2], NULL, NULL, 1);
		else if (!strcmp(argv[1], "--get"))
			return get_value(argv[2], NULL);
		else if (!strcmp(argv[1], "--get-all")) {
			do_all = 1;
			return get_value(argv[2], NULL);
		} else if (!strcmp(argv[1], "--get-regexp")) {
			show_keys = 1;
			use_key_regexp = 1;
			do_all = 1;
			return get_value(argv[2], NULL);
		} else {
			value = normalize_value(argv[1], argv[2]);
			return git_config_set(argv[1], value);
		}
	case 4:
		if (!strcmp(argv[1], "--unset"))
			return git_config_set_multivar(argv[2], NULL, argv[3], 0);
		else if (!strcmp(argv[1], "--unset-all"))
			return git_config_set_multivar(argv[2], NULL, argv[3], 1);
		else if (!strcmp(argv[1], "--get"))
			return get_value(argv[2], argv[3]);
		else if (!strcmp(argv[1], "--get-all")) {
			do_all = 1;
			return get_value(argv[2], argv[3]);
		} else if (!strcmp(argv[1], "--get-regexp")) {
			show_keys = 1;
			use_key_regexp = 1;
			do_all = 1;
			return get_value(argv[2], argv[3]);
		} else if (!strcmp(argv[1], "--add")) {
			value = normalize_value(argv[2], argv[3]);
			return git_config_set_multivar(argv[2], value, "^$", 0);
		} else if (!strcmp(argv[1], "--replace-all")) {
			value = normalize_value(argv[2], argv[3]);
			return git_config_set_multivar(argv[2], value, NULL, 1);
		} else {
			value = normalize_value(argv[1], argv[2]);
			return git_config_set_multivar(argv[1], value, argv[3], 0);
		}
	case 5:
		if (!strcmp(argv[1], "--replace-all")) {
			value = normalize_value(argv[2], argv[3]);
			return git_config_set_multivar(argv[2], value, argv[4], 1);
		}
	case 1:
	default:
		usage(git_config_set_usage);
	}
	return 0;
}