Merge branch 'nd/files-backend-git-dir'
The "submodule" specific field in the ref_store structure is replaced with a more generic "gitdir" that can later be used also when dealing with ref_store that represents the set of refs visible from the other worktrees. * nd/files-backend-git-dir: (28 commits) refs.h: add a note about sorting order of for_each_ref_* t1406: new tests for submodule ref store t1405: some basic tests on main ref store t/helper: add test-ref-store to test ref-store functions refs: delete pack_refs() in favor of refs_pack_refs() files-backend: avoid ref api targeting main ref store refs: new transaction related ref-store api refs: add new ref-store api refs: rename get_ref_store() to get_submodule_ref_store() and make it public files-backend: replace submodule_allowed check in files_downcast() refs: move submodule code out of files-backend.c path.c: move some code out of strbuf_git_path_submodule() refs.c: make get_main_ref_store() public and use it refs.c: kill register_ref_store(), add register_submodule_ref_store() refs.c: flatten get_ref_store() a bit refs: rename lookup_ref_store() to lookup_submodule_ref_store() refs.c: introduce get_main_ref_store() files-backend: remove the use of git_path() files-backend: add and use files_ref_path() files-backend: add and use files_reflog_path() ...
This commit is contained in:
commit
5ab8f2261f
1
Makefile
1
Makefile
@ -630,6 +630,7 @@ TEST_PROGRAMS_NEED_X += test-parse-options
|
||||
TEST_PROGRAMS_NEED_X += test-path-utils
|
||||
TEST_PROGRAMS_NEED_X += test-prio-queue
|
||||
TEST_PROGRAMS_NEED_X += test-read-cache
|
||||
TEST_PROGRAMS_NEED_X += test-ref-store
|
||||
TEST_PROGRAMS_NEED_X += test-regex
|
||||
TEST_PROGRAMS_NEED_X += test-revision-walking
|
||||
TEST_PROGRAMS_NEED_X += test-run-command
|
||||
|
@ -17,5 +17,5 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
|
||||
usage_with_options(pack_refs_usage, opts);
|
||||
return pack_refs(flags);
|
||||
return refs_pack_refs(get_main_ref_store(), flags);
|
||||
}
|
||||
|
35
path.c
35
path.c
@ -471,39 +471,19 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
|
||||
}
|
||||
|
||||
/* Returns 0 on success, negative on failure. */
|
||||
#define SUBMODULE_PATH_ERR_NOT_CONFIGURED -1
|
||||
static int do_submodule_path(struct strbuf *buf, const char *path,
|
||||
const char *fmt, va_list args)
|
||||
{
|
||||
const char *git_dir;
|
||||
struct strbuf git_submodule_common_dir = STRBUF_INIT;
|
||||
struct strbuf git_submodule_dir = STRBUF_INIT;
|
||||
const struct submodule *sub;
|
||||
int err = 0;
|
||||
int ret;
|
||||
|
||||
strbuf_addstr(buf, path);
|
||||
strbuf_complete(buf, '/');
|
||||
strbuf_addstr(buf, ".git");
|
||||
|
||||
git_dir = read_gitfile(buf->buf);
|
||||
if (git_dir) {
|
||||
strbuf_reset(buf);
|
||||
strbuf_addstr(buf, git_dir);
|
||||
}
|
||||
if (!is_git_directory(buf->buf)) {
|
||||
gitmodules_config();
|
||||
sub = submodule_from_path(null_sha1, path);
|
||||
if (!sub) {
|
||||
err = SUBMODULE_PATH_ERR_NOT_CONFIGURED;
|
||||
goto cleanup;
|
||||
}
|
||||
strbuf_reset(buf);
|
||||
strbuf_git_path(buf, "%s/%s", "modules", sub->name);
|
||||
}
|
||||
|
||||
strbuf_addch(buf, '/');
|
||||
strbuf_addbuf(&git_submodule_dir, buf);
|
||||
ret = submodule_to_gitdir(&git_submodule_dir, path);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
strbuf_complete(&git_submodule_dir, '/');
|
||||
strbuf_addbuf(buf, &git_submodule_dir);
|
||||
strbuf_vaddf(buf, fmt, args);
|
||||
|
||||
if (get_common_dir_noenv(&git_submodule_common_dir, git_submodule_dir.buf))
|
||||
@ -514,8 +494,7 @@ static int do_submodule_path(struct strbuf *buf, const char *path,
|
||||
cleanup:
|
||||
strbuf_release(&git_submodule_dir);
|
||||
strbuf_release(&git_submodule_common_dir);
|
||||
|
||||
return err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *git_pathdup_submodule(const char *path, const char *fmt, ...)
|
||||
|
427
refs.c
427
refs.c
@ -9,6 +9,7 @@
|
||||
#include "refs/refs-internal.h"
|
||||
#include "object.h"
|
||||
#include "tag.h"
|
||||
#include "submodule.h"
|
||||
|
||||
/*
|
||||
* List of all available backends
|
||||
@ -170,11 +171,23 @@ int refname_is_safe(const char *refname)
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *refs_resolve_refdup(struct ref_store *refs,
|
||||
const char *refname, int resolve_flags,
|
||||
unsigned char *sha1, int *flags)
|
||||
{
|
||||
const char *result;
|
||||
|
||||
result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
|
||||
sha1, flags);
|
||||
return xstrdup_or_null(result);
|
||||
}
|
||||
|
||||
char *resolve_refdup(const char *refname, int resolve_flags,
|
||||
unsigned char *sha1, int *flags)
|
||||
{
|
||||
return xstrdup_or_null(resolve_ref_unsafe(refname, resolve_flags,
|
||||
sha1, flags));
|
||||
return refs_resolve_refdup(get_main_ref_store(),
|
||||
refname, resolve_flags,
|
||||
sha1, flags);
|
||||
}
|
||||
|
||||
/* The argument to filter_refs */
|
||||
@ -184,13 +197,20 @@ struct ref_filter {
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
int read_ref_full(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
|
||||
int refs_read_ref_full(struct ref_store *refs, const char *refname,
|
||||
int resolve_flags, unsigned char *sha1, int *flags)
|
||||
{
|
||||
if (resolve_ref_unsafe(refname, resolve_flags, sha1, flags))
|
||||
if (refs_resolve_ref_unsafe(refs, refname, resolve_flags, sha1, flags))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int read_ref_full(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
|
||||
{
|
||||
return refs_read_ref_full(get_main_ref_store(), refname,
|
||||
resolve_flags, sha1, flags);
|
||||
}
|
||||
|
||||
int read_ref(const char *refname, unsigned char *sha1)
|
||||
{
|
||||
return read_ref_full(refname, RESOLVE_REF_READING, sha1, NULL);
|
||||
@ -285,34 +305,52 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_li
|
||||
for_each_rawref(warn_if_dangling_symref, &data);
|
||||
}
|
||||
|
||||
int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return refs_for_each_ref_in(refs, "refs/tags/", fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_tag_ref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return for_each_ref_in("refs/tags/", fn, cb_data);
|
||||
return refs_for_each_tag_ref(get_main_ref_store(), fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return for_each_ref_in_submodule(submodule, "refs/tags/", fn, cb_data);
|
||||
return refs_for_each_tag_ref(get_submodule_ref_store(submodule),
|
||||
fn, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_branch_ref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return for_each_ref_in("refs/heads/", fn, cb_data);
|
||||
return refs_for_each_branch_ref(get_main_ref_store(), fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return for_each_ref_in_submodule(submodule, "refs/heads/", fn, cb_data);
|
||||
return refs_for_each_branch_ref(get_submodule_ref_store(submodule),
|
||||
fn, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_remote_ref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return for_each_ref_in("refs/remotes/", fn, cb_data);
|
||||
return refs_for_each_remote_ref(get_main_ref_store(), fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return for_each_ref_in_submodule(submodule, "refs/remotes/", fn, cb_data);
|
||||
return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
|
||||
fn, cb_data);
|
||||
}
|
||||
|
||||
int head_ref_namespaced(each_ref_fn fn, void *cb_data)
|
||||
@ -596,16 +634,20 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1
|
||||
return 0;
|
||||
}
|
||||
|
||||
int delete_ref(const char *msg, const char *refname,
|
||||
const unsigned char *old_sha1, unsigned int flags)
|
||||
int refs_delete_ref(struct ref_store *refs, const char *msg,
|
||||
const char *refname,
|
||||
const unsigned char *old_sha1,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct ref_transaction *transaction;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
|
||||
if (ref_type(refname) == REF_TYPE_PSEUDOREF)
|
||||
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
|
||||
assert(refs == get_main_ref_store());
|
||||
return delete_pseudoref(refname, old_sha1);
|
||||
}
|
||||
|
||||
transaction = ref_transaction_begin(&err);
|
||||
transaction = ref_store_transaction_begin(refs, &err);
|
||||
if (!transaction ||
|
||||
ref_transaction_delete(transaction, refname, old_sha1,
|
||||
flags, msg, &err) ||
|
||||
@ -620,6 +662,13 @@ int delete_ref(const char *msg, const char *refname,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int delete_ref(const char *msg, const char *refname,
|
||||
const unsigned char *old_sha1, unsigned int flags)
|
||||
{
|
||||
return refs_delete_ref(get_main_ref_store(), msg, refname,
|
||||
old_sha1, flags);
|
||||
}
|
||||
|
||||
int copy_reflog_msg(char *buf, const char *msg)
|
||||
{
|
||||
char *cp = buf;
|
||||
@ -779,11 +828,20 @@ int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time,
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct ref_transaction *ref_transaction_begin(struct strbuf *err)
|
||||
struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
|
||||
struct strbuf *err)
|
||||
{
|
||||
struct ref_transaction *tr;
|
||||
assert(err);
|
||||
|
||||
return xcalloc(1, sizeof(struct ref_transaction));
|
||||
tr = xcalloc(1, sizeof(struct ref_transaction));
|
||||
tr->ref_store = refs;
|
||||
return tr;
|
||||
}
|
||||
|
||||
struct ref_transaction *ref_transaction_begin(struct strbuf *err)
|
||||
{
|
||||
return ref_store_transaction_begin(get_main_ref_store(), err);
|
||||
}
|
||||
|
||||
void ref_transaction_free(struct ref_transaction *transaction)
|
||||
@ -900,18 +958,20 @@ int update_ref_oid(const char *msg, const char *refname,
|
||||
old_oid ? old_oid->hash : NULL, flags, onerr);
|
||||
}
|
||||
|
||||
int update_ref(const char *msg, const char *refname,
|
||||
const unsigned char *new_sha1, const unsigned char *old_sha1,
|
||||
unsigned int flags, enum action_on_err onerr)
|
||||
int refs_update_ref(struct ref_store *refs, const char *msg,
|
||||
const char *refname, const unsigned char *new_sha1,
|
||||
const unsigned char *old_sha1, unsigned int flags,
|
||||
enum action_on_err onerr)
|
||||
{
|
||||
struct ref_transaction *t = NULL;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
int ret = 0;
|
||||
|
||||
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
|
||||
assert(refs == get_main_ref_store());
|
||||
ret = write_pseudoref(refname, new_sha1, old_sha1, &err);
|
||||
} else {
|
||||
t = ref_transaction_begin(&err);
|
||||
t = ref_store_transaction_begin(refs, &err);
|
||||
if (!t ||
|
||||
ref_transaction_update(t, refname, new_sha1, old_sha1,
|
||||
flags, msg, &err) ||
|
||||
@ -942,6 +1002,15 @@ int update_ref(const char *msg, const char *refname,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int update_ref(const char *msg, const char *refname,
|
||||
const unsigned char *new_sha1,
|
||||
const unsigned char *old_sha1,
|
||||
unsigned int flags, enum action_on_err onerr)
|
||||
{
|
||||
return refs_update_ref(get_main_ref_store(), msg, refname, new_sha1,
|
||||
old_sha1, flags, onerr);
|
||||
}
|
||||
|
||||
char *shorten_unambiguous_ref(const char *refname, int strict)
|
||||
{
|
||||
int i;
|
||||
@ -1127,14 +1196,17 @@ const char *find_descendant_ref(const char *dirname,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rename_ref_available(const char *old_refname, const char *new_refname)
|
||||
int refs_rename_ref_available(struct ref_store *refs,
|
||||
const char *old_refname,
|
||||
const char *new_refname)
|
||||
{
|
||||
struct string_list skip = STRING_LIST_INIT_NODUP;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
int ok;
|
||||
|
||||
string_list_insert(&skip, old_refname);
|
||||
ok = !verify_refname_available(new_refname, NULL, &skip, &err);
|
||||
ok = !refs_verify_refname_available(refs, new_refname,
|
||||
NULL, &skip, &err);
|
||||
if (!ok)
|
||||
error("%s", err.buf);
|
||||
|
||||
@ -1175,10 +1247,9 @@ int head_ref(each_ref_fn fn, void *cb_data)
|
||||
* non-zero value, stop the iteration and return that value;
|
||||
* otherwise, return 0.
|
||||
*/
|
||||
static int do_for_each_ref(const char *submodule, const char *prefix,
|
||||
static int do_for_each_ref(struct ref_store *refs, const char *prefix,
|
||||
each_ref_fn fn, int trim, int flags, void *cb_data)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(submodule);
|
||||
struct ref_iterator *iter;
|
||||
|
||||
if (!refs)
|
||||
@ -1190,19 +1261,30 @@ static int do_for_each_ref(const char *submodule, const char *prefix,
|
||||
return do_for_each_ref_iterator(iter, fn, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(refs, "", fn, 0, 0, cb_data);
|
||||
}
|
||||
|
||||
int for_each_ref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(NULL, "", fn, 0, 0, cb_data);
|
||||
return refs_for_each_ref(get_main_ref_store(), fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(submodule, "", fn, 0, 0, cb_data);
|
||||
return refs_for_each_ref(get_submodule_ref_store(submodule), fn, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(refs, prefix, fn, strlen(prefix), 0, cb_data);
|
||||
}
|
||||
|
||||
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(NULL, prefix, fn, strlen(prefix), 0, cb_data);
|
||||
return refs_for_each_ref_in(get_main_ref_store(), prefix, fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsigned int broken)
|
||||
@ -1211,19 +1293,23 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsig
|
||||
|
||||
if (broken)
|
||||
flag = DO_FOR_EACH_INCLUDE_BROKEN;
|
||||
return do_for_each_ref(NULL, prefix, fn, 0, flag, cb_data);
|
||||
return do_for_each_ref(get_main_ref_store(),
|
||||
prefix, fn, 0, flag, cb_data);
|
||||
}
|
||||
|
||||
int for_each_ref_in_submodule(const char *submodule, const char *prefix,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(submodule, prefix, fn, strlen(prefix), 0, cb_data);
|
||||
return refs_for_each_ref_in(get_submodule_ref_store(submodule),
|
||||
prefix, fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_replace_ref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(NULL, git_replace_ref_base, fn,
|
||||
strlen(git_replace_ref_base), 0, cb_data);
|
||||
return do_for_each_ref(get_main_ref_store(),
|
||||
git_replace_ref_base, fn,
|
||||
strlen(git_replace_ref_base),
|
||||
0, cb_data);
|
||||
}
|
||||
|
||||
int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
|
||||
@ -1231,19 +1317,25 @@ int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int ret;
|
||||
strbuf_addf(&buf, "%srefs/", get_git_namespace());
|
||||
ret = do_for_each_ref(NULL, buf.buf, fn, 0, 0, cb_data);
|
||||
ret = do_for_each_ref(get_main_ref_store(),
|
||||
buf.buf, fn, 0, 0, cb_data);
|
||||
strbuf_release(&buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int for_each_rawref(each_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(NULL, "", fn, 0,
|
||||
return do_for_each_ref(refs, "", fn, 0,
|
||||
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
|
||||
}
|
||||
|
||||
int for_each_rawref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return refs_for_each_rawref(get_main_ref_store(), fn, cb_data);
|
||||
}
|
||||
|
||||
/* This function needs to return a meaningful errno on failure */
|
||||
const char *resolve_ref_recursively(struct ref_store *refs,
|
||||
const char *refs_resolve_ref_unsafe(struct ref_store *refs,
|
||||
const char *refname,
|
||||
int resolve_flags,
|
||||
unsigned char *sha1, int *flags)
|
||||
@ -1322,7 +1414,7 @@ const char *resolve_ref_recursively(struct ref_store *refs,
|
||||
/* backend functions */
|
||||
int refs_init_db(struct strbuf *err)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
struct ref_store *refs = get_main_ref_store();
|
||||
|
||||
return refs->be->init_db(refs, err);
|
||||
}
|
||||
@ -1330,7 +1422,7 @@ int refs_init_db(struct strbuf *err)
|
||||
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
|
||||
unsigned char *sha1, int *flags)
|
||||
{
|
||||
return resolve_ref_recursively(get_ref_store(NULL), refname,
|
||||
return refs_resolve_ref_unsafe(get_main_ref_store(), refname,
|
||||
resolve_flags, sha1, flags);
|
||||
}
|
||||
|
||||
@ -1351,16 +1443,16 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
|
||||
/* We need to strip off one or more trailing slashes */
|
||||
char *stripped = xmemdupz(submodule, len);
|
||||
|
||||
refs = get_ref_store(stripped);
|
||||
refs = get_submodule_ref_store(stripped);
|
||||
free(stripped);
|
||||
} else {
|
||||
refs = get_ref_store(submodule);
|
||||
refs = get_submodule_ref_store(submodule);
|
||||
}
|
||||
|
||||
if (!refs)
|
||||
return -1;
|
||||
|
||||
if (!resolve_ref_recursively(refs, refname, 0, sha1, &flags) ||
|
||||
if (!refs_resolve_ref_unsafe(refs, refname, 0, sha1, &flags) ||
|
||||
is_null_sha1(sha1))
|
||||
return -1;
|
||||
return 0;
|
||||
@ -1403,17 +1495,13 @@ static struct ref_store *main_ref_store;
|
||||
static struct hashmap submodule_ref_stores;
|
||||
|
||||
/*
|
||||
* Return the ref_store instance for the specified submodule (or the
|
||||
* main repository if submodule is NULL). If that ref_store hasn't
|
||||
* been initialized yet, return NULL.
|
||||
* Return the ref_store instance for the specified submodule. If that
|
||||
* ref_store hasn't been initialized yet, return NULL.
|
||||
*/
|
||||
static struct ref_store *lookup_ref_store(const char *submodule)
|
||||
static struct ref_store *lookup_submodule_ref_store(const char *submodule)
|
||||
{
|
||||
struct submodule_hash_entry *entry;
|
||||
|
||||
if (!submodule)
|
||||
return main_ref_store;
|
||||
|
||||
if (!submodule_ref_stores.tablesize)
|
||||
/* It's initialized on demand in register_ref_store(). */
|
||||
return NULL;
|
||||
@ -1423,34 +1511,12 @@ static struct ref_store *lookup_ref_store(const char *submodule)
|
||||
return entry ? entry->refs : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the specified ref_store to be the one that should be used
|
||||
* for submodule (or the main repository if submodule is NULL). It is
|
||||
* a fatal error to call this function twice for the same submodule.
|
||||
*/
|
||||
static void register_ref_store(struct ref_store *refs, const char *submodule)
|
||||
{
|
||||
if (!submodule) {
|
||||
if (main_ref_store)
|
||||
die("BUG: main_ref_store initialized twice");
|
||||
|
||||
main_ref_store = refs;
|
||||
} else {
|
||||
if (!submodule_ref_stores.tablesize)
|
||||
hashmap_init(&submodule_ref_stores, submodule_hash_cmp, 0);
|
||||
|
||||
if (hashmap_put(&submodule_ref_stores,
|
||||
alloc_submodule_hash_entry(submodule, refs)))
|
||||
die("BUG: ref_store for submodule '%s' initialized twice",
|
||||
submodule);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create, record, and return a ref_store instance for the specified
|
||||
* submodule (or the main repository if submodule is NULL).
|
||||
* gitdir.
|
||||
*/
|
||||
static struct ref_store *ref_store_init(const char *submodule)
|
||||
static struct ref_store *ref_store_init(const char *gitdir,
|
||||
unsigned int flags)
|
||||
{
|
||||
const char *be_name = "files";
|
||||
struct ref_storage_be *be = find_ref_storage_backend(be_name);
|
||||
@ -1459,33 +1525,76 @@ static struct ref_store *ref_store_init(const char *submodule)
|
||||
if (!be)
|
||||
die("BUG: reference backend %s is unknown", be_name);
|
||||
|
||||
refs = be->init(submodule);
|
||||
register_ref_store(refs, submodule);
|
||||
refs = be->init(gitdir, flags);
|
||||
return refs;
|
||||
}
|
||||
|
||||
struct ref_store *get_ref_store(const char *submodule)
|
||||
struct ref_store *get_main_ref_store(void)
|
||||
{
|
||||
if (main_ref_store)
|
||||
return main_ref_store;
|
||||
|
||||
main_ref_store = ref_store_init(get_git_dir(),
|
||||
(REF_STORE_READ |
|
||||
REF_STORE_WRITE |
|
||||
REF_STORE_ODB |
|
||||
REF_STORE_MAIN));
|
||||
return main_ref_store;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the specified ref_store to be the one that should be used
|
||||
* for submodule. It is a fatal error to call this function twice for
|
||||
* the same submodule.
|
||||
*/
|
||||
static void register_submodule_ref_store(struct ref_store *refs,
|
||||
const char *submodule)
|
||||
{
|
||||
if (!submodule_ref_stores.tablesize)
|
||||
hashmap_init(&submodule_ref_stores, submodule_hash_cmp, 0);
|
||||
|
||||
if (hashmap_put(&submodule_ref_stores,
|
||||
alloc_submodule_hash_entry(submodule, refs)))
|
||||
die("BUG: ref_store for submodule '%s' initialized twice",
|
||||
submodule);
|
||||
}
|
||||
|
||||
struct ref_store *get_submodule_ref_store(const char *submodule)
|
||||
{
|
||||
struct strbuf submodule_sb = STRBUF_INIT;
|
||||
struct ref_store *refs;
|
||||
int ret;
|
||||
|
||||
if (!submodule || !*submodule) {
|
||||
refs = lookup_ref_store(NULL);
|
||||
|
||||
if (!refs)
|
||||
refs = ref_store_init(NULL);
|
||||
} else {
|
||||
refs = lookup_ref_store(submodule);
|
||||
|
||||
if (!refs) {
|
||||
struct strbuf submodule_sb = STRBUF_INIT;
|
||||
|
||||
strbuf_addstr(&submodule_sb, submodule);
|
||||
if (is_nonbare_repository_dir(&submodule_sb))
|
||||
refs = ref_store_init(submodule);
|
||||
strbuf_release(&submodule_sb);
|
||||
}
|
||||
/*
|
||||
* FIXME: This case is ideally not allowed. But that
|
||||
* can't happen until we clean up all the callers.
|
||||
*/
|
||||
return get_main_ref_store();
|
||||
}
|
||||
|
||||
refs = lookup_submodule_ref_store(submodule);
|
||||
if (refs)
|
||||
return refs;
|
||||
|
||||
strbuf_addstr(&submodule_sb, submodule);
|
||||
ret = is_nonbare_repository_dir(&submodule_sb);
|
||||
strbuf_release(&submodule_sb);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
ret = submodule_to_gitdir(&submodule_sb, submodule);
|
||||
if (ret) {
|
||||
strbuf_release(&submodule_sb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* assume that add_submodule_odb() has been called */
|
||||
refs = ref_store_init(submodule_sb.buf,
|
||||
REF_STORE_READ | REF_STORE_ODB);
|
||||
register_submodule_ref_store(refs, submodule);
|
||||
|
||||
strbuf_release(&submodule_sb);
|
||||
return refs;
|
||||
}
|
||||
|
||||
@ -1496,50 +1605,58 @@ void base_ref_store_init(struct ref_store *refs,
|
||||
}
|
||||
|
||||
/* backend functions */
|
||||
int pack_refs(unsigned int flags)
|
||||
int refs_pack_refs(struct ref_store *refs, unsigned int flags)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->pack_refs(refs, flags);
|
||||
}
|
||||
|
||||
int refs_peel_ref(struct ref_store *refs, const char *refname,
|
||||
unsigned char *sha1)
|
||||
{
|
||||
return refs->be->peel_ref(refs, refname, sha1);
|
||||
}
|
||||
|
||||
int peel_ref(const char *refname, unsigned char *sha1)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
return refs_peel_ref(get_main_ref_store(), refname, sha1);
|
||||
}
|
||||
|
||||
return refs->be->peel_ref(refs, refname, sha1);
|
||||
int refs_create_symref(struct ref_store *refs,
|
||||
const char *ref_target,
|
||||
const char *refs_heads_master,
|
||||
const char *logmsg)
|
||||
{
|
||||
return refs->be->create_symref(refs, ref_target,
|
||||
refs_heads_master,
|
||||
logmsg);
|
||||
}
|
||||
|
||||
int create_symref(const char *ref_target, const char *refs_heads_master,
|
||||
const char *logmsg)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->create_symref(refs, ref_target, refs_heads_master,
|
||||
logmsg);
|
||||
return refs_create_symref(get_main_ref_store(), ref_target,
|
||||
refs_heads_master, logmsg);
|
||||
}
|
||||
|
||||
int ref_transaction_commit(struct ref_transaction *transaction,
|
||||
struct strbuf *err)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
struct ref_store *refs = transaction->ref_store;
|
||||
|
||||
return refs->be->transaction_commit(refs, transaction, err);
|
||||
}
|
||||
|
||||
int verify_refname_available(const char *refname,
|
||||
const struct string_list *extra,
|
||||
const struct string_list *skip,
|
||||
struct strbuf *err)
|
||||
int refs_verify_refname_available(struct ref_store *refs,
|
||||
const char *refname,
|
||||
const struct string_list *extra,
|
||||
const struct string_list *skip,
|
||||
struct strbuf *err)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->verify_refname_available(refs, refname, extra, skip, err);
|
||||
}
|
||||
|
||||
int for_each_reflog(each_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
struct ref_iterator *iter;
|
||||
|
||||
iter = refs->be->reflog_iterator_begin(refs);
|
||||
@ -1547,43 +1664,84 @@ int for_each_reflog(each_ref_fn fn, void *cb_data)
|
||||
return do_for_each_ref_iterator(iter, fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_reflog(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return refs_for_each_reflog(get_main_ref_store(), fn, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
|
||||
const char *refname,
|
||||
each_reflog_ent_fn fn,
|
||||
void *cb_data)
|
||||
{
|
||||
return refs->be->for_each_reflog_ent_reverse(refs, refname,
|
||||
fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
|
||||
void *cb_data)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
return refs_for_each_reflog_ent_reverse(get_main_ref_store(),
|
||||
refname, fn, cb_data);
|
||||
}
|
||||
|
||||
return refs->be->for_each_reflog_ent_reverse(refs, refname,
|
||||
fn, cb_data);
|
||||
int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname,
|
||||
each_reflog_ent_fn fn, void *cb_data)
|
||||
{
|
||||
return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
|
||||
}
|
||||
|
||||
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
|
||||
void *cb_data)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
return refs_for_each_reflog_ent(get_main_ref_store(), refname,
|
||||
fn, cb_data);
|
||||
}
|
||||
|
||||
return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
|
||||
int refs_reflog_exists(struct ref_store *refs, const char *refname)
|
||||
{
|
||||
return refs->be->reflog_exists(refs, refname);
|
||||
}
|
||||
|
||||
int reflog_exists(const char *refname)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
return refs_reflog_exists(get_main_ref_store(), refname);
|
||||
}
|
||||
|
||||
return refs->be->reflog_exists(refs, refname);
|
||||
int refs_create_reflog(struct ref_store *refs, const char *refname,
|
||||
int force_create, struct strbuf *err)
|
||||
{
|
||||
return refs->be->create_reflog(refs, refname, force_create, err);
|
||||
}
|
||||
|
||||
int safe_create_reflog(const char *refname, int force_create,
|
||||
struct strbuf *err)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
return refs_create_reflog(get_main_ref_store(), refname,
|
||||
force_create, err);
|
||||
}
|
||||
|
||||
return refs->be->create_reflog(refs, refname, force_create, err);
|
||||
int refs_delete_reflog(struct ref_store *refs, const char *refname)
|
||||
{
|
||||
return refs->be->delete_reflog(refs, refname);
|
||||
}
|
||||
|
||||
int delete_reflog(const char *refname)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
return refs_delete_reflog(get_main_ref_store(), refname);
|
||||
}
|
||||
|
||||
return refs->be->delete_reflog(refs, refname);
|
||||
int refs_reflog_expire(struct ref_store *refs,
|
||||
const char *refname, const unsigned char *sha1,
|
||||
unsigned int flags,
|
||||
reflog_expiry_prepare_fn prepare_fn,
|
||||
reflog_expiry_should_prune_fn should_prune_fn,
|
||||
reflog_expiry_cleanup_fn cleanup_fn,
|
||||
void *policy_cb_data)
|
||||
{
|
||||
return refs->be->reflog_expire(refs, refname, sha1, flags,
|
||||
prepare_fn, should_prune_fn,
|
||||
cleanup_fn, policy_cb_data);
|
||||
}
|
||||
|
||||
int reflog_expire(const char *refname, const unsigned char *sha1,
|
||||
@ -1593,31 +1751,38 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
|
||||
reflog_expiry_cleanup_fn cleanup_fn,
|
||||
void *policy_cb_data)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->reflog_expire(refs, refname, sha1, flags,
|
||||
prepare_fn, should_prune_fn,
|
||||
cleanup_fn, policy_cb_data);
|
||||
return refs_reflog_expire(get_main_ref_store(),
|
||||
refname, sha1, flags,
|
||||
prepare_fn, should_prune_fn,
|
||||
cleanup_fn, policy_cb_data);
|
||||
}
|
||||
|
||||
int initial_ref_transaction_commit(struct ref_transaction *transaction,
|
||||
struct strbuf *err)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
struct ref_store *refs = transaction->ref_store;
|
||||
|
||||
return refs->be->initial_transaction_commit(refs, transaction, err);
|
||||
}
|
||||
|
||||
int refs_delete_refs(struct ref_store *refs, struct string_list *refnames,
|
||||
unsigned int flags)
|
||||
{
|
||||
return refs->be->delete_refs(refs, refnames, flags);
|
||||
}
|
||||
|
||||
int delete_refs(struct string_list *refnames, unsigned int flags)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
return refs_delete_refs(get_main_ref_store(), refnames, flags);
|
||||
}
|
||||
|
||||
return refs->be->delete_refs(refs, refnames, flags);
|
||||
int refs_rename_ref(struct ref_store *refs, const char *oldref,
|
||||
const char *newref, const char *logmsg)
|
||||
{
|
||||
return refs->be->rename_ref(refs, oldref, newref, logmsg);
|
||||
}
|
||||
|
||||
int rename_ref(const char *oldref, const char *newref, const char *logmsg)
|
||||
{
|
||||
struct ref_store *refs = get_ref_store(NULL);
|
||||
|
||||
return refs->be->rename_ref(refs, oldref, newref, logmsg);
|
||||
return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg);
|
||||
}
|
||||
|
106
refs.h
106
refs.h
@ -1,6 +1,11 @@
|
||||
#ifndef REFS_H
|
||||
#define REFS_H
|
||||
|
||||
struct object_id;
|
||||
struct ref_store;
|
||||
struct strbuf;
|
||||
struct string_list;
|
||||
|
||||
/*
|
||||
* Resolve a reference, recursively following symbolic refererences.
|
||||
*
|
||||
@ -52,16 +57,50 @@
|
||||
#define RESOLVE_REF_NO_RECURSE 0x02
|
||||
#define RESOLVE_REF_ALLOW_BAD_NAME 0x04
|
||||
|
||||
const char *refs_resolve_ref_unsafe(struct ref_store *refs,
|
||||
const char *refname,
|
||||
int resolve_flags,
|
||||
unsigned char *sha1,
|
||||
int *flags);
|
||||
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
|
||||
unsigned char *sha1, int *flags);
|
||||
|
||||
char *refs_resolve_refdup(struct ref_store *refs,
|
||||
const char *refname, int resolve_flags,
|
||||
unsigned char *sha1, int *flags);
|
||||
char *resolve_refdup(const char *refname, int resolve_flags,
|
||||
unsigned char *sha1, int *flags);
|
||||
|
||||
int refs_read_ref_full(struct ref_store *refs, const char *refname,
|
||||
int resolve_flags, unsigned char *sha1, int *flags);
|
||||
int read_ref_full(const char *refname, int resolve_flags,
|
||||
unsigned char *sha1, int *flags);
|
||||
int read_ref(const char *refname, unsigned char *sha1);
|
||||
|
||||
/*
|
||||
* Return 0 if a reference named refname could be created without
|
||||
* conflicting with the name of an existing reference. Otherwise,
|
||||
* return a negative value and write an explanation to err. If extras
|
||||
* is non-NULL, it is a list of additional refnames with which refname
|
||||
* is not allowed to conflict. If skip is non-NULL, ignore potential
|
||||
* conflicts with refs in skip (e.g., because they are scheduled for
|
||||
* deletion in the same operation). Behavior is undefined if the same
|
||||
* name is listed in both extras and skip.
|
||||
*
|
||||
* Two reference names conflict if one of them exactly matches the
|
||||
* leading components of the other; e.g., "foo/bar" conflicts with
|
||||
* both "foo" and with "foo/bar/baz" but not with "foo/bar" or
|
||||
* "foo/barbados".
|
||||
*
|
||||
* extras and skip must be sorted.
|
||||
*/
|
||||
|
||||
int refs_verify_refname_available(struct ref_store *refs,
|
||||
const char *refname,
|
||||
const struct string_list *extra,
|
||||
const struct string_list *skip,
|
||||
struct strbuf *err);
|
||||
|
||||
int ref_exists(const char *refname);
|
||||
|
||||
int should_autocreate_reflog(const char *refname);
|
||||
@ -78,6 +117,8 @@ extern int refs_init_db(struct strbuf *err);
|
||||
* Symbolic references are considered unpeelable, even if they
|
||||
* ultimately resolve to a peelable tag.
|
||||
*/
|
||||
int refs_peel_ref(struct ref_store *refs, const char *refname,
|
||||
unsigned char *sha1);
|
||||
int peel_ref(const char *refname, unsigned char *sha1);
|
||||
|
||||
/**
|
||||
@ -189,8 +230,19 @@ typedef int each_ref_fn(const char *refname,
|
||||
* it is not safe to modify references while an iteration is in
|
||||
* progress, unless the same callback function invocation that
|
||||
* modifies the reference also returns a nonzero value to immediately
|
||||
* stop the iteration.
|
||||
* stop the iteration. Returned references are sorted.
|
||||
*/
|
||||
int refs_for_each_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_tag_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_branch_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_remote_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
|
||||
int head_ref(each_ref_fn fn, void *cb_data);
|
||||
int for_each_ref(each_ref_fn fn, void *cb_data);
|
||||
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
|
||||
@ -220,6 +272,7 @@ int head_ref_namespaced(each_ref_fn fn, void *cb_data);
|
||||
int for_each_namespaced_ref(each_ref_fn fn, void *cb_data);
|
||||
|
||||
/* can be used to learn about broken ref and symref */
|
||||
int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data);
|
||||
int for_each_rawref(each_ref_fn fn, void *cb_data);
|
||||
|
||||
static inline const char *has_glob_specials(const char *pattern)
|
||||
@ -243,7 +296,7 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt,
|
||||
* Write a packed-refs file for the current repository.
|
||||
* flags: Combination of the above PACK_REFS_* flags.
|
||||
*/
|
||||
int pack_refs(unsigned int flags);
|
||||
int refs_pack_refs(struct ref_store *refs, unsigned int flags);
|
||||
|
||||
/*
|
||||
* Flags controlling ref_transaction_update(), ref_transaction_create(), etc.
|
||||
@ -258,6 +311,8 @@ int pack_refs(unsigned int flags);
|
||||
/*
|
||||
* Setup reflog before using. Fill in err and return -1 on failure.
|
||||
*/
|
||||
int refs_create_reflog(struct ref_store *refs, const char *refname,
|
||||
int force_create, struct strbuf *err);
|
||||
int safe_create_reflog(const char *refname, int force_create, struct strbuf *err);
|
||||
|
||||
/** Reads log for the value of ref during at_time. **/
|
||||
@ -267,6 +322,7 @@ int read_ref_at(const char *refname, unsigned int flags,
|
||||
unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
|
||||
|
||||
/** Check if a particular reflog exists */
|
||||
int refs_reflog_exists(struct ref_store *refs, const char *refname);
|
||||
int reflog_exists(const char *refname);
|
||||
|
||||
/*
|
||||
@ -276,6 +332,10 @@ int reflog_exists(const char *refname);
|
||||
* exists, regardless of its old value. It is an error for old_sha1 to
|
||||
* be NULL_SHA1. flags is passed through to ref_transaction_delete().
|
||||
*/
|
||||
int refs_delete_ref(struct ref_store *refs, const char *msg,
|
||||
const char *refname,
|
||||
const unsigned char *old_sha1,
|
||||
unsigned int flags);
|
||||
int delete_ref(const char *msg, const char *refname,
|
||||
const unsigned char *old_sha1, unsigned int flags);
|
||||
|
||||
@ -285,9 +345,12 @@ int delete_ref(const char *msg, const char *refname,
|
||||
* an all-or-nothing transaction). flags is passed through to
|
||||
* ref_transaction_delete().
|
||||
*/
|
||||
int refs_delete_refs(struct ref_store *refs, struct string_list *refnames,
|
||||
unsigned int flags);
|
||||
int delete_refs(struct string_list *refnames, unsigned int flags);
|
||||
|
||||
/** Delete a reflog */
|
||||
int refs_delete_reflog(struct ref_store *refs, const char *refname);
|
||||
int delete_reflog(const char *refname);
|
||||
|
||||
/* iterate over reflog entries */
|
||||
@ -296,13 +359,20 @@ typedef int each_reflog_ent_fn(
|
||||
const char *committer, unsigned long timestamp,
|
||||
int tz, const char *msg, void *cb_data);
|
||||
|
||||
int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname,
|
||||
each_reflog_ent_fn fn, void *cb_data);
|
||||
int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
|
||||
const char *refname,
|
||||
each_reflog_ent_fn fn,
|
||||
void *cb_data);
|
||||
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data);
|
||||
int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data);
|
||||
|
||||
/*
|
||||
* Calls the specified function for each reflog file until it returns nonzero,
|
||||
* and returns the value
|
||||
* and returns the value. Reflog file order is unspecified.
|
||||
*/
|
||||
int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data);
|
||||
int for_each_reflog(each_ref_fn fn, void *cb_data);
|
||||
|
||||
#define REFNAME_ALLOW_ONELEVEL 1
|
||||
@ -323,8 +393,12 @@ const char *prettify_refname(const char *refname);
|
||||
char *shorten_unambiguous_ref(const char *refname, int strict);
|
||||
|
||||
/** rename ref, return 0 on success **/
|
||||
int refs_rename_ref(struct ref_store *refs, const char *oldref,
|
||||
const char *newref, const char *logmsg);
|
||||
int rename_ref(const char *oldref, const char *newref, const char *logmsg);
|
||||
|
||||
int refs_create_symref(struct ref_store *refs, const char *refname,
|
||||
const char *target, const char *logmsg);
|
||||
int create_symref(const char *refname, const char *target, const char *logmsg);
|
||||
|
||||
/*
|
||||
@ -347,6 +421,8 @@ enum action_on_err {
|
||||
* Begin a reference transaction. The reference transaction must
|
||||
* be freed by calling ref_transaction_free().
|
||||
*/
|
||||
struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
|
||||
struct strbuf *err);
|
||||
struct ref_transaction *ref_transaction_begin(struct strbuf *err);
|
||||
|
||||
/*
|
||||
@ -481,6 +557,9 @@ void ref_transaction_free(struct ref_transaction *transaction);
|
||||
* ref_transaction_update(). Handle errors as requested by the `onerr`
|
||||
* argument.
|
||||
*/
|
||||
int refs_update_ref(struct ref_store *refs, const char *msg, const char *refname,
|
||||
const unsigned char *new_sha1, const unsigned char *old_sha1,
|
||||
unsigned int flags, enum action_on_err onerr);
|
||||
int update_ref(const char *msg, const char *refname,
|
||||
const unsigned char *new_sha1, const unsigned char *old_sha1,
|
||||
unsigned int flags, enum action_on_err onerr);
|
||||
@ -547,6 +626,14 @@ typedef void reflog_expiry_cleanup_fn(void *cb_data);
|
||||
* enum expire_reflog_flags. The three function pointers are described
|
||||
* above. On success, return zero.
|
||||
*/
|
||||
int refs_reflog_expire(struct ref_store *refs,
|
||||
const char *refname,
|
||||
const unsigned char *sha1,
|
||||
unsigned int flags,
|
||||
reflog_expiry_prepare_fn prepare_fn,
|
||||
reflog_expiry_should_prune_fn should_prune_fn,
|
||||
reflog_expiry_cleanup_fn cleanup_fn,
|
||||
void *policy_cb_data);
|
||||
int reflog_expire(const char *refname, const unsigned char *sha1,
|
||||
unsigned int flags,
|
||||
reflog_expiry_prepare_fn prepare_fn,
|
||||
@ -556,4 +643,17 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
|
||||
|
||||
int ref_storage_backend_exists(const char *name);
|
||||
|
||||
struct ref_store *get_main_ref_store(void);
|
||||
/*
|
||||
* Return the ref_store instance for the specified submodule. For the
|
||||
* main repository, use submodule==NULL; such a call cannot fail. For
|
||||
* a submodule, the submodule must exist and be a nonbare repository,
|
||||
* otherwise return NULL. If the requested reference store has not yet
|
||||
* been initialized, initialize it first.
|
||||
*
|
||||
* For backwards compatibility, submodule=="" is treated the same as
|
||||
* submodule==NULL.
|
||||
*/
|
||||
struct ref_store *get_submodule_ref_store(const char *submodule);
|
||||
|
||||
#endif /* REFS_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -111,28 +111,6 @@ enum peel_status {
|
||||
*/
|
||||
enum peel_status peel_object(const unsigned char *name, unsigned char *sha1);
|
||||
|
||||
/*
|
||||
* Return 0 if a reference named refname could be created without
|
||||
* conflicting with the name of an existing reference. Otherwise,
|
||||
* return a negative value and write an explanation to err. If extras
|
||||
* is non-NULL, it is a list of additional refnames with which refname
|
||||
* is not allowed to conflict. If skip is non-NULL, ignore potential
|
||||
* conflicts with refs in skip (e.g., because they are scheduled for
|
||||
* deletion in the same operation). Behavior is undefined if the same
|
||||
* name is listed in both extras and skip.
|
||||
*
|
||||
* Two reference names conflict if one of them exactly matches the
|
||||
* leading components of the other; e.g., "foo/bar" conflicts with
|
||||
* both "foo" and with "foo/bar/baz" but not with "foo/bar" or
|
||||
* "foo/barbados".
|
||||
*
|
||||
* extras and skip must be sorted.
|
||||
*/
|
||||
int verify_refname_available(const char *newname,
|
||||
const struct string_list *extras,
|
||||
const struct string_list *skip,
|
||||
struct strbuf *err);
|
||||
|
||||
/*
|
||||
* Copy the reflog message msg to buf, which has been allocated sufficiently
|
||||
* large, while cleaning up the whitespaces. Especially, convert LF to space,
|
||||
@ -222,16 +200,13 @@ enum ref_transaction_state {
|
||||
* as atomically as possible. This structure is opaque to callers.
|
||||
*/
|
||||
struct ref_transaction {
|
||||
struct ref_store *ref_store;
|
||||
struct ref_update **updates;
|
||||
size_t alloc;
|
||||
size_t nr;
|
||||
enum ref_transaction_state state;
|
||||
};
|
||||
|
||||
int files_log_ref_write(const char *refname, const unsigned char *old_sha1,
|
||||
const unsigned char *new_sha1, const char *msg,
|
||||
int flags, struct strbuf *err);
|
||||
|
||||
/*
|
||||
* Check for entries in extras that are within the specified
|
||||
* directory, where dirname is a reference directory name including
|
||||
@ -256,7 +231,9 @@ const char *find_descendant_ref(const char *dirname,
|
||||
* processes (though rename_ref() catches some races that might get by
|
||||
* this check).
|
||||
*/
|
||||
int rename_ref_available(const char *old_refname, const char *new_refname);
|
||||
int refs_rename_ref_available(struct ref_store *refs,
|
||||
const char *old_refname,
|
||||
const char *new_refname);
|
||||
|
||||
/* We allow "recursive" symbolic refs. Only within reason, though */
|
||||
#define SYMREF_MAXDEPTH 5
|
||||
@ -485,13 +462,19 @@ struct ref_store;
|
||||
|
||||
/* refs backends */
|
||||
|
||||
/* ref_store_init flags */
|
||||
#define REF_STORE_READ (1 << 0)
|
||||
#define REF_STORE_WRITE (1 << 1) /* can perform update operations */
|
||||
#define REF_STORE_ODB (1 << 2) /* has access to object database */
|
||||
#define REF_STORE_MAIN (1 << 3)
|
||||
|
||||
/*
|
||||
* Initialize the ref_store for the specified submodule, or for the
|
||||
* main repository if submodule == NULL. These functions should call
|
||||
* base_ref_store_init() to initialize the shared part of the
|
||||
* ref_store and to record the ref_store for later lookup.
|
||||
* Initialize the ref_store for the specified gitdir. These functions
|
||||
* should call base_ref_store_init() to initialize the shared part of
|
||||
* the ref_store and to record the ref_store for later lookup.
|
||||
*/
|
||||
typedef struct ref_store *ref_store_init_fn(const char *submodule);
|
||||
typedef struct ref_store *ref_store_init_fn(const char *gitdir,
|
||||
unsigned int flags);
|
||||
|
||||
typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err);
|
||||
|
||||
@ -644,21 +627,4 @@ struct ref_store {
|
||||
void base_ref_store_init(struct ref_store *refs,
|
||||
const struct ref_storage_be *be);
|
||||
|
||||
/*
|
||||
* Return the ref_store instance for the specified submodule. For the
|
||||
* main repository, use submodule==NULL; such a call cannot fail. For
|
||||
* a submodule, the submodule must exist and be a nonbare repository,
|
||||
* otherwise return NULL. If the requested reference store has not yet
|
||||
* been initialized, initialize it first.
|
||||
*
|
||||
* For backwards compatibility, submodule=="" is treated the same as
|
||||
* submodule==NULL.
|
||||
*/
|
||||
struct ref_store *get_ref_store(const char *submodule);
|
||||
|
||||
const char *resolve_ref_recursively(struct ref_store *refs,
|
||||
const char *refname,
|
||||
int resolve_flags,
|
||||
unsigned char *sha1, int *flags);
|
||||
|
||||
#endif /* REFS_REFS_INTERNAL_H */
|
||||
|
31
submodule.c
31
submodule.c
@ -1866,3 +1866,34 @@ const char *get_superproject_working_tree(void)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int submodule_to_gitdir(struct strbuf *buf, const char *submodule)
|
||||
{
|
||||
const struct submodule *sub;
|
||||
const char *git_dir;
|
||||
int ret = 0;
|
||||
|
||||
strbuf_reset(buf);
|
||||
strbuf_addstr(buf, submodule);
|
||||
strbuf_complete(buf, '/');
|
||||
strbuf_addstr(buf, ".git");
|
||||
|
||||
git_dir = read_gitfile(buf->buf);
|
||||
if (git_dir) {
|
||||
strbuf_reset(buf);
|
||||
strbuf_addstr(buf, git_dir);
|
||||
}
|
||||
if (!is_git_directory(buf->buf)) {
|
||||
gitmodules_config();
|
||||
sub = submodule_from_path(null_sha1, submodule);
|
||||
if (!sub) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
strbuf_reset(buf);
|
||||
strbuf_git_path(buf, "%s/%s", "modules", sub->name);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
@ -98,6 +98,12 @@ extern int push_unpushed_submodules(struct oid_array *commits,
|
||||
int dry_run);
|
||||
extern void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
|
||||
extern int parallel_submodules(void);
|
||||
/*
|
||||
* Given a submodule path (as in the index), return the repository
|
||||
* path of that submodule in 'buf'. Return -1 on error or when the
|
||||
* submodule is not initialized.
|
||||
*/
|
||||
int submodule_to_gitdir(struct strbuf *buf, const char *submodule);
|
||||
|
||||
#define SUBMODULE_MOVE_HEAD_DRY_RUN (1<<0)
|
||||
#define SUBMODULE_MOVE_HEAD_FORCE (1<<1)
|
||||
|
1
t/helper/.gitignore
vendored
1
t/helper/.gitignore
vendored
@ -20,6 +20,7 @@
|
||||
/test-path-utils
|
||||
/test-prio-queue
|
||||
/test-read-cache
|
||||
/test-ref-store
|
||||
/test-regex
|
||||
/test-revision-walking
|
||||
/test-run-command
|
||||
|
277
t/helper/test-ref-store.c
Normal file
277
t/helper/test-ref-store.c
Normal file
@ -0,0 +1,277 @@
|
||||
#include "cache.h"
|
||||
#include "refs.h"
|
||||
|
||||
static const char *notnull(const char *arg, const char *name)
|
||||
{
|
||||
if (!arg)
|
||||
die("%s required", name);
|
||||
return arg;
|
||||
}
|
||||
|
||||
static unsigned int arg_flags(const char *arg, const char *name)
|
||||
{
|
||||
return atoi(notnull(arg, name));
|
||||
}
|
||||
|
||||
static const char **get_store(const char **argv, struct ref_store **refs)
|
||||
{
|
||||
const char *gitdir;
|
||||
|
||||
if (!argv[0]) {
|
||||
die("ref store required");
|
||||
} else if (!strcmp(argv[0], "main")) {
|
||||
*refs = get_main_ref_store();
|
||||
} else if (skip_prefix(argv[0], "submodule:", &gitdir)) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
int ret;
|
||||
|
||||
ret = strbuf_git_path_submodule(&sb, gitdir, "objects/");
|
||||
if (ret)
|
||||
die("strbuf_git_path_submodule failed: %d", ret);
|
||||
add_to_alternates_memory(sb.buf);
|
||||
strbuf_release(&sb);
|
||||
|
||||
*refs = get_submodule_ref_store(gitdir);
|
||||
} else
|
||||
die("unknown backend %s", argv[0]);
|
||||
|
||||
if (!*refs)
|
||||
die("no ref store");
|
||||
|
||||
/* consume store-specific optional arguments if needed */
|
||||
|
||||
return argv + 1;
|
||||
}
|
||||
|
||||
|
||||
static int cmd_pack_refs(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
unsigned int flags = arg_flags(*argv++, "flags");
|
||||
|
||||
return refs_pack_refs(refs, flags);
|
||||
}
|
||||
|
||||
static int cmd_peel_ref(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
unsigned char sha1[20];
|
||||
int ret;
|
||||
|
||||
ret = refs_peel_ref(refs, refname, sha1);
|
||||
if (!ret)
|
||||
puts(sha1_to_hex(sha1));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cmd_create_symref(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
const char *target = notnull(*argv++, "target");
|
||||
const char *logmsg = *argv++;
|
||||
|
||||
return refs_create_symref(refs, refname, target, logmsg);
|
||||
}
|
||||
|
||||
static int cmd_delete_refs(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
unsigned int flags = arg_flags(*argv++, "flags");
|
||||
struct string_list refnames = STRING_LIST_INIT_NODUP;
|
||||
|
||||
while (*argv)
|
||||
string_list_append(&refnames, *argv++);
|
||||
|
||||
return refs_delete_refs(refs, &refnames, flags);
|
||||
}
|
||||
|
||||
static int cmd_rename_ref(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *oldref = notnull(*argv++, "oldref");
|
||||
const char *newref = notnull(*argv++, "newref");
|
||||
const char *logmsg = *argv++;
|
||||
|
||||
return refs_rename_ref(refs, oldref, newref, logmsg);
|
||||
}
|
||||
|
||||
static int each_ref(const char *refname, const struct object_id *oid,
|
||||
int flags, void *cb_data)
|
||||
{
|
||||
printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_for_each_ref(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *prefix = notnull(*argv++, "prefix");
|
||||
|
||||
return refs_for_each_ref_in(refs, prefix, each_ref, NULL);
|
||||
}
|
||||
|
||||
static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
unsigned char sha1[20];
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
int resolve_flags = arg_flags(*argv++, "resolve-flags");
|
||||
int flags;
|
||||
const char *ref;
|
||||
|
||||
ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
|
||||
sha1, &flags);
|
||||
printf("%s %s 0x%x\n", sha1_to_hex(sha1), ref, flags);
|
||||
return ref ? 0 : 1;
|
||||
}
|
||||
|
||||
static int cmd_verify_ref(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
int ret;
|
||||
|
||||
ret = refs_verify_refname_available(refs, refname, NULL, NULL, &err);
|
||||
if (err.len)
|
||||
puts(err.buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cmd_for_each_reflog(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
return refs_for_each_reflog(refs, each_ref, NULL);
|
||||
}
|
||||
|
||||
static int each_reflog(struct object_id *old_oid, struct object_id *new_oid,
|
||||
const char *committer, unsigned long timestamp,
|
||||
int tz, const char *msg, void *cb_data)
|
||||
{
|
||||
printf("%s %s %s %lu %d %s\n",
|
||||
oid_to_hex(old_oid), oid_to_hex(new_oid),
|
||||
committer, timestamp, tz, msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_for_each_reflog_ent(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
|
||||
return refs_for_each_reflog_ent(refs, refname, each_reflog, refs);
|
||||
}
|
||||
|
||||
static int cmd_for_each_reflog_ent_reverse(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
|
||||
return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog, refs);
|
||||
}
|
||||
|
||||
static int cmd_reflog_exists(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
|
||||
return !refs_reflog_exists(refs, refname);
|
||||
}
|
||||
|
||||
static int cmd_create_reflog(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
int force_create = arg_flags(*argv++, "force-create");
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
int ret;
|
||||
|
||||
ret = refs_create_reflog(refs, refname, force_create, &err);
|
||||
if (err.len)
|
||||
puts(err.buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cmd_delete_reflog(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
|
||||
return refs_delete_reflog(refs, refname);
|
||||
}
|
||||
|
||||
static int cmd_reflog_expire(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
die("not supported yet");
|
||||
}
|
||||
|
||||
static int cmd_delete_ref(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *msg = notnull(*argv++, "msg");
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
const char *sha1_buf = notnull(*argv++, "old-sha1");
|
||||
unsigned int flags = arg_flags(*argv++, "flags");
|
||||
unsigned char old_sha1[20];
|
||||
|
||||
if (get_sha1_hex(sha1_buf, old_sha1))
|
||||
die("not sha-1");
|
||||
|
||||
return refs_delete_ref(refs, msg, refname, old_sha1, flags);
|
||||
}
|
||||
|
||||
static int cmd_update_ref(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *msg = notnull(*argv++, "msg");
|
||||
const char *refname = notnull(*argv++, "refname");
|
||||
const char *new_sha1_buf = notnull(*argv++, "old-sha1");
|
||||
const char *old_sha1_buf = notnull(*argv++, "old-sha1");
|
||||
unsigned int flags = arg_flags(*argv++, "flags");
|
||||
unsigned char old_sha1[20];
|
||||
unsigned char new_sha1[20];
|
||||
|
||||
if (get_sha1_hex(old_sha1_buf, old_sha1) ||
|
||||
get_sha1_hex(new_sha1_buf, new_sha1))
|
||||
die("not sha-1");
|
||||
|
||||
return refs_update_ref(refs, msg, refname,
|
||||
new_sha1, old_sha1,
|
||||
flags, UPDATE_REFS_DIE_ON_ERR);
|
||||
}
|
||||
|
||||
struct command {
|
||||
const char *name;
|
||||
int (*func)(struct ref_store *refs, const char **argv);
|
||||
};
|
||||
|
||||
static struct command commands[] = {
|
||||
{ "pack-refs", cmd_pack_refs },
|
||||
{ "peel-ref", cmd_peel_ref },
|
||||
{ "create-symref", cmd_create_symref },
|
||||
{ "delete-refs", cmd_delete_refs },
|
||||
{ "rename-ref", cmd_rename_ref },
|
||||
{ "for-each-ref", cmd_for_each_ref },
|
||||
{ "resolve-ref", cmd_resolve_ref },
|
||||
{ "verify-ref", cmd_verify_ref },
|
||||
{ "for-each-reflog", cmd_for_each_reflog },
|
||||
{ "for-each-reflog-ent", cmd_for_each_reflog_ent },
|
||||
{ "for-each-reflog-ent-reverse", cmd_for_each_reflog_ent_reverse },
|
||||
{ "reflog-exists", cmd_reflog_exists },
|
||||
{ "create-reflog", cmd_create_reflog },
|
||||
{ "delete-reflog", cmd_delete_reflog },
|
||||
{ "reflog-expire", cmd_reflog_expire },
|
||||
/*
|
||||
* backend transaction functions can't be tested separately
|
||||
*/
|
||||
{ "delete-ref", cmd_delete_ref },
|
||||
{ "update-ref", cmd_update_ref },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int cmd_main(int argc, const char **argv)
|
||||
{
|
||||
struct ref_store *refs;
|
||||
const char *func;
|
||||
struct command *cmd;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
argv = get_store(argv + 1, &refs);
|
||||
|
||||
func = *argv++;
|
||||
if (!func)
|
||||
die("ref function required");
|
||||
for (cmd = commands; cmd->name; cmd++) {
|
||||
if (!strcmp(func, cmd->name))
|
||||
return cmd->func(refs, argv);
|
||||
}
|
||||
die("unknown function %s", func);
|
||||
return 0;
|
||||
}
|
129
t/t1405-main-ref-store.sh
Executable file
129
t/t1405-main-ref-store.sh
Executable file
@ -0,0 +1,129 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test main ref store api'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
RUN="test-ref-store main"
|
||||
|
||||
test_expect_success 'pack_refs(PACK_REFS_ALL | PACK_REFS_PRUNE)' '
|
||||
test_commit one &&
|
||||
N=`find .git/refs -type f | wc -l` &&
|
||||
test "$N" != 0 &&
|
||||
$RUN pack-refs 3 &&
|
||||
N=`find .git/refs -type f | wc -l`
|
||||
'
|
||||
|
||||
test_expect_success 'peel_ref(new-tag)' '
|
||||
git rev-parse HEAD >expected &&
|
||||
git tag -a -m new-tag new-tag HEAD &&
|
||||
$RUN peel-ref refs/tags/new-tag >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'create_symref(FOO, refs/heads/master)' '
|
||||
$RUN create-symref FOO refs/heads/master nothing &&
|
||||
echo refs/heads/master >expected &&
|
||||
git symbolic-ref FOO >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' '
|
||||
git rev-parse FOO -- &&
|
||||
git rev-parse refs/tags/new-tag -- &&
|
||||
$RUN delete-refs 0 FOO refs/tags/new-tag &&
|
||||
test_must_fail git rev-parse FOO -- &&
|
||||
test_must_fail git rev-parse refs/tags/new-tag --
|
||||
'
|
||||
|
||||
test_expect_success 'rename_refs(master, new-master)' '
|
||||
git rev-parse master >expected &&
|
||||
$RUN rename-ref refs/heads/master refs/heads/new-master &&
|
||||
git rev-parse new-master >actual &&
|
||||
test_cmp expected actual &&
|
||||
test_commit recreate-master
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_ref(refs/heads/)' '
|
||||
$RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
|
||||
cat >expected <<-\EOF &&
|
||||
master 0x0
|
||||
new-master 0x0
|
||||
EOF
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_ref() is sorted' '
|
||||
$RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
|
||||
sort actual > expected &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'resolve_ref(new-master)' '
|
||||
SHA1=`git rev-parse new-master` &&
|
||||
echo "$SHA1 refs/heads/new-master 0x0" >expected &&
|
||||
$RUN resolve-ref refs/heads/new-master 0 >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'verify_ref(new-master)' '
|
||||
$RUN verify-ref refs/heads/new-master
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_reflog()' '
|
||||
$RUN for-each-reflog | sort | cut -c 42- >actual &&
|
||||
cat >expected <<-\EOF &&
|
||||
HEAD 0x1
|
||||
refs/heads/master 0x0
|
||||
refs/heads/new-master 0x0
|
||||
EOF
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_reflog_ent()' '
|
||||
$RUN for-each-reflog-ent HEAD >actual &&
|
||||
head -n1 actual | grep one &&
|
||||
tail -n2 actual | head -n1 | grep recreate-master
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_reflog_ent_reverse()' '
|
||||
$RUN for-each-reflog-ent-reverse HEAD >actual &&
|
||||
head -n1 actual | grep recreate-master &&
|
||||
tail -n2 actual | head -n1 | grep one
|
||||
'
|
||||
|
||||
test_expect_success 'reflog_exists(HEAD)' '
|
||||
$RUN reflog-exists HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'delete_reflog(HEAD)' '
|
||||
$RUN delete-reflog HEAD &&
|
||||
! test -f .git/logs/HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'create-reflog(HEAD)' '
|
||||
$RUN create-reflog HEAD 1 &&
|
||||
test -f .git/logs/HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'delete_ref(refs/heads/foo)' '
|
||||
git checkout -b foo &&
|
||||
FOO_SHA1=`git rev-parse foo` &&
|
||||
git checkout --detach &&
|
||||
test_commit bar-commit &&
|
||||
git checkout -b bar &&
|
||||
BAR_SHA1=`git rev-parse bar` &&
|
||||
$RUN update-ref updating refs/heads/foo $BAR_SHA1 $FOO_SHA1 0 &&
|
||||
echo $BAR_SHA1 >expected &&
|
||||
git rev-parse refs/heads/foo >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'delete_ref(refs/heads/foo)' '
|
||||
SHA1=`git rev-parse foo` &&
|
||||
git checkout --detach &&
|
||||
$RUN delete-ref msg refs/heads/foo $SHA1 0 &&
|
||||
test_must_fail git rev-parse refs/heads/foo --
|
||||
'
|
||||
|
||||
test_done
|
101
t/t1406-submodule-ref-store.sh
Executable file
101
t/t1406-submodule-ref-store.sh
Executable file
@ -0,0 +1,101 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test submodule ref store api'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
RUN="test-ref-store submodule:sub"
|
||||
|
||||
test_expect_success 'setup' '
|
||||
git init sub &&
|
||||
(
|
||||
cd sub &&
|
||||
test_commit first &&
|
||||
git checkout -b new-master
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'pack_refs() not allowed' '
|
||||
test_must_fail $RUN pack-refs 3
|
||||
'
|
||||
|
||||
test_expect_success 'peel_ref(new-tag)' '
|
||||
git -C sub rev-parse HEAD >expected &&
|
||||
git -C sub tag -a -m new-tag new-tag HEAD &&
|
||||
$RUN peel-ref refs/tags/new-tag >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'create_symref() not allowed' '
|
||||
test_must_fail $RUN create-symref FOO refs/heads/master nothing
|
||||
'
|
||||
|
||||
test_expect_success 'delete_refs() not allowed' '
|
||||
test_must_fail $RUN delete-refs 0 FOO refs/tags/new-tag
|
||||
'
|
||||
|
||||
test_expect_success 'rename_refs() not allowed' '
|
||||
test_must_fail $RUN rename-ref refs/heads/master refs/heads/new-master
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_ref(refs/heads/)' '
|
||||
$RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
|
||||
cat >expected <<-\EOF &&
|
||||
master 0x0
|
||||
new-master 0x0
|
||||
EOF
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_ref() is sorted' '
|
||||
$RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
|
||||
sort actual > expected &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'resolve_ref(master)' '
|
||||
SHA1=`git -C sub rev-parse master` &&
|
||||
echo "$SHA1 refs/heads/master 0x0" >expected &&
|
||||
$RUN resolve-ref refs/heads/master 0 >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'verify_ref(new-master)' '
|
||||
$RUN verify-ref refs/heads/new-master
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_reflog()' '
|
||||
$RUN for-each-reflog | sort | cut -c 42- >actual &&
|
||||
cat >expected <<-\EOF &&
|
||||
HEAD 0x1
|
||||
refs/heads/master 0x0
|
||||
refs/heads/new-master 0x0
|
||||
EOF
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_reflog_ent()' '
|
||||
$RUN for-each-reflog-ent HEAD >actual && cat actual &&
|
||||
head -n1 actual | grep first &&
|
||||
tail -n2 actual | head -n1 | grep master.to.new
|
||||
'
|
||||
|
||||
test_expect_success 'for_each_reflog_ent_reverse()' '
|
||||
$RUN for-each-reflog-ent-reverse HEAD >actual &&
|
||||
head -n1 actual | grep master.to.new &&
|
||||
tail -n2 actual | head -n1 | grep first
|
||||
'
|
||||
|
||||
test_expect_success 'reflog_exists(HEAD)' '
|
||||
$RUN reflog-exists HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'delete_reflog() not allowed' '
|
||||
test_must_fail $RUN delete-reflog HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'create-reflog() not allowed' '
|
||||
test_must_fail $RUN create-reflog HEAD 1
|
||||
'
|
||||
|
||||
test_done
|
Loading…
Reference in New Issue
Block a user