mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-22 06:26:26 +00:00
Merge pull request #6756 from libgit2/ethomson/worktree-config
Separate config reader and writer backend priorities (for worktree configs)
This commit is contained in:
@@ -22,8 +22,19 @@ GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* Priority level of a config file.
|
||||
*
|
||||
* These priority levels correspond to the natural escalation logic
|
||||
* (from higher to lower) when searching for config entries in git.git.
|
||||
* (from higher to lower) when reading or searching for config entries
|
||||
* in git.git. Meaning that for the same key, the configuration in
|
||||
* the local configuration is preferred over the configuration in
|
||||
* the system configuration file.
|
||||
*
|
||||
* Callers can add their own custom configuration, beginning at the
|
||||
* `GIT_CONFIG_LEVEL_APP` level.
|
||||
*
|
||||
* Writes, by default, occur in the highest priority level backend
|
||||
* that is writable. This ordering can be overridden with
|
||||
* `git_config_set_writeorder`.
|
||||
*
|
||||
* git_config_open_default() and git_repository_config() honor those
|
||||
* priority levels as well.
|
||||
@@ -48,9 +59,13 @@ typedef enum {
|
||||
*/
|
||||
GIT_CONFIG_LEVEL_LOCAL = 5,
|
||||
|
||||
/** Worktree specific configuration file; $GIT_DIR/config.worktree
|
||||
*/
|
||||
GIT_CONFIG_LEVEL_WORKTREE = 6,
|
||||
|
||||
/** Application specific configuration file; freely defined by applications
|
||||
*/
|
||||
GIT_CONFIG_LEVEL_APP = 6,
|
||||
GIT_CONFIG_LEVEL_APP = 7,
|
||||
|
||||
/** Represents the highest level available config file (i.e. the most
|
||||
* specific config file available that actually is loaded)
|
||||
@@ -296,6 +311,11 @@ GIT_EXTERN(int) git_config_open_level(
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_open_global(git_config **out, git_config *config);
|
||||
|
||||
GIT_EXTERN(int) git_config_set_writeorder(
|
||||
git_config *cfg,
|
||||
git_config_level_t *levels,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* Create a snapshot of the configuration
|
||||
*
|
||||
|
||||
@@ -19,20 +19,20 @@ GIT_BEGIN_DECL
|
||||
|
||||
/** Generic return codes */
|
||||
typedef enum {
|
||||
GIT_OK = 0, /**< No error */
|
||||
GIT_OK = 0, /**< No error */
|
||||
|
||||
GIT_ERROR = -1, /**< Generic error */
|
||||
GIT_ENOTFOUND = -3, /**< Requested object could not be found */
|
||||
GIT_EEXISTS = -4, /**< Object exists preventing operation */
|
||||
GIT_EAMBIGUOUS = -5, /**< More than one object matches */
|
||||
GIT_EBUFS = -6, /**< Output buffer too short to hold data */
|
||||
GIT_ERROR = -1, /**< Generic error */
|
||||
GIT_ENOTFOUND = -3, /**< Requested object could not be found */
|
||||
GIT_EEXISTS = -4, /**< Object exists preventing operation */
|
||||
GIT_EAMBIGUOUS = -5, /**< More than one object matches */
|
||||
GIT_EBUFS = -6, /**< Output buffer too short to hold data */
|
||||
|
||||
/**
|
||||
* GIT_EUSER is a special error that is never generated by libgit2
|
||||
* code. You can return it from a callback (e.g to stop an iteration)
|
||||
* to know that it was generated by the callback and not by libgit2.
|
||||
*/
|
||||
GIT_EUSER = -7,
|
||||
GIT_EUSER = -7,
|
||||
|
||||
GIT_EBAREREPO = -8, /**< Operation not allowed on bare repository */
|
||||
GIT_EUNBORNBRANCH = -9, /**< HEAD refers to branch with no commits */
|
||||
@@ -61,7 +61,8 @@ typedef enum {
|
||||
GIT_EOWNER = -36, /**< The object is not owned by the current user */
|
||||
GIT_TIMEOUT = -37, /**< The operation timed out */
|
||||
GIT_EUNCHANGED = -38, /**< There were no changes */
|
||||
GIT_ENOTSUPPORTED = -39 /**< An option is not supported */
|
||||
GIT_ENOTSUPPORTED = -39, /**< An option is not supported */
|
||||
GIT_EREADONLY = -40 /**< The subject is read-only */
|
||||
} git_error_code;
|
||||
|
||||
/**
|
||||
|
||||
@@ -499,6 +499,7 @@ typedef enum {
|
||||
GIT_REPOSITORY_ITEM_PACKED_REFS,
|
||||
GIT_REPOSITORY_ITEM_REMOTES,
|
||||
GIT_REPOSITORY_ITEM_CONFIG,
|
||||
GIT_REPOSITORY_ITEM_WORKTREE_CONFIG,
|
||||
GIT_REPOSITORY_ITEM_INFO,
|
||||
GIT_REPOSITORY_ITEM_HOOKS,
|
||||
GIT_REPOSITORY_ITEM_LOGS,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,8 @@
|
||||
|
||||
struct git_config {
|
||||
git_refcount rc;
|
||||
git_vector backends;
|
||||
git_vector readers;
|
||||
git_vector writers;
|
||||
};
|
||||
|
||||
extern int git_config__global_location(git_str *buf);
|
||||
@@ -94,17 +95,21 @@ int git_config_lookup_map_enum(git_configmap_t *type_out,
|
||||
size_t map_n, int enum_val);
|
||||
|
||||
/**
|
||||
* Unlock the backend with the highest priority
|
||||
* Unlock the given backend that was previously locked.
|
||||
*
|
||||
* Unlocking will allow other writers to update the configuration
|
||||
* file. Optionally, any changes performed since the lock will be
|
||||
* applied to the configuration.
|
||||
*
|
||||
* @param cfg the configuration
|
||||
* @param config the config instance
|
||||
* @param data the config data passed to git_transaction_new
|
||||
* @param commit boolean which indicates whether to commit any changes
|
||||
* done since locking
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_unlock(git_config *cfg, int commit);
|
||||
GIT_EXTERN(int) git_config_unlock(
|
||||
git_config *config,
|
||||
void *data,
|
||||
int commit);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -58,6 +58,7 @@ static const struct {
|
||||
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "packed-refs", false },
|
||||
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "remotes", true },
|
||||
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "config", false },
|
||||
{ GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM_GITDIR, "config.worktree", false },
|
||||
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "info", true },
|
||||
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "hooks", true },
|
||||
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "logs", true },
|
||||
@@ -1273,6 +1274,24 @@ int git_repository_discover(
|
||||
return error;
|
||||
}
|
||||
|
||||
static int has_config_worktree(bool *out, git_config *cfg)
|
||||
{
|
||||
int worktreeconfig = 0, error;
|
||||
|
||||
*out = false;
|
||||
|
||||
error = git_config_get_bool(&worktreeconfig, cfg, "extensions.worktreeconfig");
|
||||
|
||||
if (error == 0)
|
||||
*out = worktreeconfig;
|
||||
else if (error == GIT_ENOTFOUND)
|
||||
*out = false;
|
||||
else
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_config(
|
||||
git_config **out,
|
||||
git_repository *repo,
|
||||
@@ -1281,9 +1300,11 @@ static int load_config(
|
||||
const char *system_config_path,
|
||||
const char *programdata_path)
|
||||
{
|
||||
int error;
|
||||
git_str config_path = GIT_STR_INIT;
|
||||
git_config *cfg = NULL;
|
||||
git_config_level_t write_order;
|
||||
bool has_worktree;
|
||||
int error;
|
||||
|
||||
GIT_ASSERT_ARG(out);
|
||||
|
||||
@@ -1297,6 +1318,14 @@ static int load_config(
|
||||
if (error && error != GIT_ENOTFOUND)
|
||||
goto on_error;
|
||||
|
||||
if ((error = has_config_worktree(&has_worktree, cfg)) == 0 &&
|
||||
has_worktree &&
|
||||
(error = git_repository__item_path(&config_path, repo, GIT_REPOSITORY_ITEM_WORKTREE_CONFIG)) == 0)
|
||||
error = git_config_add_file_ondisk(cfg, config_path.ptr, GIT_CONFIG_LEVEL_WORKTREE, repo, 0);
|
||||
|
||||
if (error && error != GIT_ENOTFOUND)
|
||||
goto on_error;
|
||||
|
||||
git_str_dispose(&config_path);
|
||||
}
|
||||
|
||||
@@ -1326,6 +1355,11 @@ static int load_config(
|
||||
|
||||
git_error_clear(); /* clear any lingering ENOTFOUND errors */
|
||||
|
||||
write_order = GIT_CONFIG_LEVEL_LOCAL;
|
||||
|
||||
if ((error = git_config_set_writeorder(cfg, &write_order, 1)) < 0)
|
||||
goto on_error;
|
||||
|
||||
*out = cfg;
|
||||
return 0;
|
||||
|
||||
@@ -1845,7 +1879,8 @@ static int check_repositoryformatversion(int *version, git_config *config)
|
||||
|
||||
static const char *builtin_extensions[] = {
|
||||
"noop",
|
||||
"objectformat"
|
||||
"objectformat",
|
||||
"worktreeconfig",
|
||||
};
|
||||
|
||||
static git_vector user_extensions = { 0, git__strcmp_cb };
|
||||
|
||||
@@ -49,12 +49,16 @@ struct git_transaction {
|
||||
git_repository *repo;
|
||||
git_refdb *db;
|
||||
git_config *cfg;
|
||||
void *cfg_data;
|
||||
|
||||
git_strmap *locks;
|
||||
git_pool pool;
|
||||
};
|
||||
|
||||
int git_transaction_config_new(git_transaction **out, git_config *cfg)
|
||||
int git_transaction_config_new(
|
||||
git_transaction **out,
|
||||
git_config *cfg,
|
||||
void *data)
|
||||
{
|
||||
git_transaction *tx;
|
||||
|
||||
@@ -66,6 +70,8 @@ int git_transaction_config_new(git_transaction **out, git_config *cfg)
|
||||
|
||||
tx->type = TRANSACTION_CONFIG;
|
||||
tx->cfg = cfg;
|
||||
tx->cfg_data = data;
|
||||
|
||||
*out = tx;
|
||||
return 0;
|
||||
}
|
||||
@@ -333,8 +339,9 @@ int git_transaction_commit(git_transaction *tx)
|
||||
GIT_ASSERT_ARG(tx);
|
||||
|
||||
if (tx->type == TRANSACTION_CONFIG) {
|
||||
error = git_config_unlock(tx->cfg, true);
|
||||
error = git_config_unlock(tx->cfg, tx->cfg_data, true);
|
||||
tx->cfg = NULL;
|
||||
tx->cfg_data = NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -369,10 +376,8 @@ void git_transaction_free(git_transaction *tx)
|
||||
return;
|
||||
|
||||
if (tx->type == TRANSACTION_CONFIG) {
|
||||
if (tx->cfg) {
|
||||
git_config_unlock(tx->cfg, false);
|
||||
git_config_free(tx->cfg);
|
||||
}
|
||||
if (tx->cfg)
|
||||
git_config_unlock(tx->cfg, tx->cfg_data, false);
|
||||
|
||||
git__free(tx);
|
||||
return;
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int git_transaction_config_new(git_transaction **out, git_config *cfg);
|
||||
int git_transaction_config_new(
|
||||
git_transaction **out,
|
||||
git_config *cfg,
|
||||
void *data);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,3 +71,21 @@ void test_config_configlevel__fetching_a_level_from_an_empty_compound_config_ret
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_configlevel__can_override_local_with_worktree(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
cl_git_pass(git_config_new(&cfg));
|
||||
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"),
|
||||
GIT_CONFIG_LEVEL_WORKTREE, NULL, 1));
|
||||
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"),
|
||||
GIT_CONFIG_LEVEL_LOCAL, NULL, 1));
|
||||
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.stringglobal"));
|
||||
cl_assert_equal_s("don't find me!", buf.ptr);
|
||||
|
||||
git_buf_dispose(&buf);
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ void test_config_readonly__writing_to_readonly_fails(void)
|
||||
backend->readonly = 1;
|
||||
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
|
||||
|
||||
cl_git_fail_with(GIT_ENOTFOUND, git_config_set_string(cfg, "foo.bar", "baz"));
|
||||
cl_git_fail_with(GIT_EREADONLY, git_config_set_string(cfg, "foo.bar", "baz"));
|
||||
cl_assert(!git_fs_path_exists("global"));
|
||||
}
|
||||
|
||||
|
||||
@@ -696,6 +696,36 @@ void test_config_write__locking(void)
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_write__abort_lock(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
git_config_entry *entry;
|
||||
git_transaction *tx;
|
||||
const char *filename = "locked-file";
|
||||
|
||||
/* Open the config and lock it */
|
||||
cl_git_mkfile(filename, "[section]\n\tname = value\n");
|
||||
cl_git_pass(git_config_open_ondisk(&cfg, filename));
|
||||
cl_git_pass(git_config_get_entry(&entry, cfg, "section.name"));
|
||||
cl_assert_equal_s("value", entry->value);
|
||||
git_config_entry_free(entry);
|
||||
cl_git_pass(git_config_lock(&tx, cfg));
|
||||
|
||||
/* Change entries in the locked backend */
|
||||
cl_git_pass(git_config_set_string(cfg, "section.name", "other value"));
|
||||
cl_git_pass(git_config_set_string(cfg, "section2.name3", "more value"));
|
||||
|
||||
git_transaction_free(tx);
|
||||
|
||||
/* Now that we've unlocked it, we should see no changes */
|
||||
cl_git_pass(git_config_get_entry(&entry, cfg, "section.name"));
|
||||
cl_assert_equal_s("value", entry->value);
|
||||
git_config_entry_free(entry);
|
||||
cl_git_fail_with(GIT_ENOTFOUND, git_config_get_entry(&entry, cfg, "section2.name3"));
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_write__repeated(void)
|
||||
{
|
||||
const char *filename = "config-repeated";
|
||||
|
||||
@@ -34,9 +34,10 @@ void test_core_opts__extensions_query(void)
|
||||
|
||||
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
|
||||
|
||||
cl_assert_equal_sz(out.count, 2);
|
||||
cl_assert_equal_sz(out.count, 3);
|
||||
cl_assert_equal_s("noop", out.strings[0]);
|
||||
cl_assert_equal_s("objectformat", out.strings[1]);
|
||||
cl_assert_equal_s("worktreeconfig", out.strings[2]);
|
||||
|
||||
git_strarray_dispose(&out);
|
||||
}
|
||||
@@ -49,10 +50,11 @@ void test_core_opts__extensions_add(void)
|
||||
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
|
||||
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
|
||||
|
||||
cl_assert_equal_sz(out.count, 3);
|
||||
cl_assert_equal_sz(out.count, 4);
|
||||
cl_assert_equal_s("foo", out.strings[0]);
|
||||
cl_assert_equal_s("noop", out.strings[1]);
|
||||
cl_assert_equal_s("objectformat", out.strings[2]);
|
||||
cl_assert_equal_s("worktreeconfig", out.strings[3]);
|
||||
|
||||
git_strarray_dispose(&out);
|
||||
}
|
||||
@@ -65,10 +67,11 @@ void test_core_opts__extensions_remove(void)
|
||||
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
|
||||
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
|
||||
|
||||
cl_assert_equal_sz(out.count, 3);
|
||||
cl_assert_equal_sz(out.count, 4);
|
||||
cl_assert_equal_s("bar", out.strings[0]);
|
||||
cl_assert_equal_s("baz", out.strings[1]);
|
||||
cl_assert_equal_s("objectformat", out.strings[2]);
|
||||
cl_assert_equal_s("worktreeconfig", out.strings[3]);
|
||||
|
||||
git_strarray_dispose(&out);
|
||||
}
|
||||
@@ -81,11 +84,12 @@ void test_core_opts__extensions_uniq(void)
|
||||
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
|
||||
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
|
||||
|
||||
cl_assert_equal_sz(out.count, 4);
|
||||
cl_assert_equal_sz(out.count, 5);
|
||||
cl_assert_equal_s("bar", out.strings[0]);
|
||||
cl_assert_equal_s("foo", out.strings[1]);
|
||||
cl_assert_equal_s("noop", out.strings[2]);
|
||||
cl_assert_equal_s("objectformat", out.strings[3]);
|
||||
cl_assert_equal_s("worktreeconfig", out.strings[4]);
|
||||
|
||||
git_strarray_dispose(&out);
|
||||
}
|
||||
|
||||
@@ -6,15 +6,19 @@
|
||||
|
||||
static worktree_fixture fixture =
|
||||
WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
|
||||
static worktree_fixture submodule =
|
||||
WORKTREE_FIXTURE_INIT("submodules", "submodules-worktree-parent");
|
||||
|
||||
void test_worktree_config__initialize(void)
|
||||
{
|
||||
setup_fixture_worktree(&fixture);
|
||||
setup_fixture_worktree(&submodule);
|
||||
}
|
||||
|
||||
void test_worktree_config__cleanup(void)
|
||||
{
|
||||
cleanup_fixture_worktree(&fixture);
|
||||
cleanup_fixture_worktree(&submodule);
|
||||
}
|
||||
|
||||
void test_worktree_config__open(void)
|
||||
@@ -27,7 +31,7 @@ void test_worktree_config__open(void)
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_worktree_config__set(void)
|
||||
void test_worktree_config__set_level_local(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
int32_t val;
|
||||
@@ -45,3 +49,78 @@ void test_worktree_config__set(void)
|
||||
cl_assert_equal_i(val, 5);
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_worktree_config__requires_extension(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
git_config *wtcfg;
|
||||
int extension = 0;
|
||||
|
||||
/*
|
||||
* the "submodules" repo does not have extensions.worktreeconfig
|
||||
* set, the worktree configuration should not be available.
|
||||
*/
|
||||
cl_git_pass(git_repository_config(&cfg, submodule.repo));
|
||||
cl_git_fail_with(GIT_ENOTFOUND, git_config_get_bool(&extension, cfg, "extensions.worktreeconfig"));
|
||||
cl_assert_equal_i(0, extension);
|
||||
cl_git_fail_with(GIT_ENOTFOUND, git_config_open_level(&wtcfg, cfg, GIT_CONFIG_LEVEL_WORKTREE));
|
||||
git_config_free(cfg);
|
||||
|
||||
/* the "testrepo" repo does have the configuration set. */
|
||||
cl_git_pass(git_repository_config(&cfg, fixture.repo));
|
||||
cl_git_pass(git_config_get_bool(&extension, cfg, "extensions.worktreeconfig"));
|
||||
cl_assert_equal_i(1, extension);
|
||||
cl_git_pass(git_config_open_level(&wtcfg, cfg, GIT_CONFIG_LEVEL_WORKTREE));
|
||||
git_config_free(wtcfg);
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_worktree_config__exists(void)
|
||||
{
|
||||
git_config *cfg, *wtcfg, *snap;
|
||||
const char *str;
|
||||
|
||||
cl_git_pass(git_repository_config(&cfg, fixture.repo));
|
||||
cl_git_pass(git_repository_config(&wtcfg, fixture.worktree));
|
||||
|
||||
cl_git_pass(git_config_snapshot(&snap, cfg));
|
||||
cl_git_pass(git_config_get_string(&str, snap, "worktreetest.config"));
|
||||
cl_assert_equal_s("mainrepo", str);
|
||||
git_config_free(snap);
|
||||
|
||||
cl_git_pass(git_config_snapshot(&snap, wtcfg));
|
||||
cl_git_pass(git_config_get_string(&str, snap, "worktreetest.config"));
|
||||
cl_assert_equal_s("worktreerepo", str);
|
||||
git_config_free(snap);
|
||||
|
||||
git_config_free(cfg);
|
||||
git_config_free(wtcfg);
|
||||
}
|
||||
|
||||
void test_worktree_config__set_level_worktree(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
git_config *wtcfg;
|
||||
int32_t val;
|
||||
|
||||
cl_git_pass(git_repository_config(&cfg, fixture.repo));
|
||||
cl_git_pass(git_config_open_level(&wtcfg, cfg, GIT_CONFIG_LEVEL_WORKTREE));
|
||||
cl_git_pass(git_config_set_int32(wtcfg, "worktree.specific", 42));
|
||||
|
||||
cl_git_pass(git_config_get_int32(&val, cfg, "worktree.specific"));
|
||||
cl_assert_equal_i(val, 42);
|
||||
|
||||
/* reopen to verify config has been set */
|
||||
git_config_free(cfg);
|
||||
cl_git_pass(git_repository_config(&cfg, fixture.repo));
|
||||
cl_git_pass(git_config_get_int32(&val, cfg, "worktree.specific"));
|
||||
cl_assert_equal_i(val, 42);
|
||||
|
||||
cl_git_fail_with(GIT_ENOTFOUND, git_config_delete_entry(cfg, "worktree.specific"));
|
||||
|
||||
cl_git_pass(git_config_delete_entry(wtcfg, "worktree.specific"));
|
||||
cl_git_fail_with(GIT_ENOTFOUND, git_config_get_int32(&val, cfg, "worktree.specific"));
|
||||
|
||||
git_config_free(cfg);
|
||||
git_config_free(wtcfg);
|
||||
}
|
||||
|
||||
2
tests/resources/testrepo/.gitted/config
vendored
2
tests/resources/testrepo/.gitted/config
vendored
@@ -3,6 +3,8 @@
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
[extensions]
|
||||
worktreeconfig = true
|
||||
[remote "test"]
|
||||
url = git://github.com/libgit2/libgit2
|
||||
fetch = +refs/heads/*:refs/remotes/test/*
|
||||
|
||||
2
tests/resources/testrepo/.gitted/config.worktree
vendored
Normal file
2
tests/resources/testrepo/.gitted/config.worktree
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
[worktreetest]
|
||||
config = mainrepo
|
||||
2
tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/config.worktree
vendored
Normal file
2
tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/config.worktree
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
[worktreetest]
|
||||
config = worktreerepo
|
||||
Reference in New Issue
Block a user