mirror of
https://github.com/git/git
synced 2024-10-03 23:29:36 +00:00
Merge branch 'mh/ref-store'
The ref-store abstraction was introduced to the refs API so that we can plug in different backends to store references. * mh/ref-store: (38 commits) refs: implement iteration over only per-worktree refs refs: make lock generic refs: add method to rename refs refs: add methods to init refs db refs: make delete_refs() virtual refs: add method for initial ref transaction commit refs: add methods for reflog refs: add method iterator_begin files_ref_iterator_begin(): take a ref_store argument split_symref_update(): add a files_ref_store argument lock_ref_sha1_basic(): add a files_ref_store argument lock_ref_for_update(): add a files_ref_store argument commit_ref_update(): add a files_ref_store argument lock_raw_ref(): add a files_ref_store argument repack_without_refs(): add a files_ref_store argument refs: make peel_ref() virtual refs: make create_symref() virtual refs: make pack_refs() virtual refs: make verify_refname_available() virtual refs: make read_raw_ref() virtual ...
This commit is contained in:
commit
4322f3848a
|
@ -180,13 +180,7 @@ static int create_default_files(const char *template_path)
|
||||||
char junk[2];
|
char junk[2];
|
||||||
int reinit;
|
int reinit;
|
||||||
int filemode;
|
int filemode;
|
||||||
|
struct strbuf err = STRBUF_INIT;
|
||||||
/*
|
|
||||||
* Create .git/refs/{heads,tags}
|
|
||||||
*/
|
|
||||||
safe_create_dir(git_path_buf(&buf, "refs"), 1);
|
|
||||||
safe_create_dir(git_path_buf(&buf, "refs/heads"), 1);
|
|
||||||
safe_create_dir(git_path_buf(&buf, "refs/tags"), 1);
|
|
||||||
|
|
||||||
/* Just look for `init.templatedir` */
|
/* Just look for `init.templatedir` */
|
||||||
git_config(git_init_db_config, NULL);
|
git_config(git_init_db_config, NULL);
|
||||||
|
@ -210,11 +204,18 @@ static int create_default_files(const char *template_path)
|
||||||
*/
|
*/
|
||||||
if (get_shared_repository()) {
|
if (get_shared_repository()) {
|
||||||
adjust_shared_perm(get_git_dir());
|
adjust_shared_perm(get_git_dir());
|
||||||
adjust_shared_perm(git_path_buf(&buf, "refs"));
|
|
||||||
adjust_shared_perm(git_path_buf(&buf, "refs/heads"));
|
|
||||||
adjust_shared_perm(git_path_buf(&buf, "refs/tags"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to create a "refs" dir in any case so that older
|
||||||
|
* versions of git can tell that this is a repository.
|
||||||
|
*/
|
||||||
|
safe_create_dir(git_path("refs"), 1);
|
||||||
|
adjust_shared_perm(git_path("refs"));
|
||||||
|
|
||||||
|
if (refs_init_db(&err))
|
||||||
|
die("failed to set up refs db: %s", err.buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the default symlink from ".git/HEAD" to the "master"
|
* Create the default symlink from ".git/HEAD" to the "master"
|
||||||
* branch, if it does not exist yet.
|
* branch, if it does not exist yet.
|
||||||
|
|
309
refs.c
309
refs.c
|
@ -9,6 +9,25 @@
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of all available backends
|
||||||
|
*/
|
||||||
|
static struct ref_storage_be *refs_backends = &refs_be_files;
|
||||||
|
|
||||||
|
static struct ref_storage_be *find_ref_storage_backend(const char *name)
|
||||||
|
{
|
||||||
|
struct ref_storage_be *be;
|
||||||
|
for (be = refs_backends; be; be = be->next)
|
||||||
|
if (!strcmp(be->name, name))
|
||||||
|
return be;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ref_storage_backend_exists(const char *name)
|
||||||
|
{
|
||||||
|
return find_ref_storage_backend(name) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* How to handle various characters in refnames:
|
* How to handle various characters in refnames:
|
||||||
* 0: An acceptable character for refs
|
* 0: An acceptable character for refs
|
||||||
|
@ -1081,20 +1100,20 @@ const char *find_descendant_ref(const char *dirname,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rename_ref_available(const char *oldname, const char *newname)
|
int rename_ref_available(const char *old_refname, const char *new_refname)
|
||||||
{
|
{
|
||||||
struct string_list skip = STRING_LIST_INIT_NODUP;
|
struct string_list skip = STRING_LIST_INIT_NODUP;
|
||||||
struct strbuf err = STRBUF_INIT;
|
struct strbuf err = STRBUF_INIT;
|
||||||
int ret;
|
int ok;
|
||||||
|
|
||||||
string_list_insert(&skip, oldname);
|
string_list_insert(&skip, old_refname);
|
||||||
ret = !verify_refname_available(newname, NULL, &skip, &err);
|
ok = !verify_refname_available(new_refname, NULL, &skip, &err);
|
||||||
if (!ret)
|
if (!ok)
|
||||||
error("%s", err.buf);
|
error("%s", err.buf);
|
||||||
|
|
||||||
string_list_clear(&skip, 0);
|
string_list_clear(&skip, 0);
|
||||||
strbuf_release(&err);
|
strbuf_release(&err);
|
||||||
return ret;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
|
int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
|
||||||
|
@ -1132,9 +1151,13 @@ int head_ref(each_ref_fn fn, void *cb_data)
|
||||||
static int do_for_each_ref(const char *submodule, const char *prefix,
|
static int do_for_each_ref(const char *submodule, const char *prefix,
|
||||||
each_ref_fn fn, int trim, int flags, void *cb_data)
|
each_ref_fn fn, int trim, int flags, void *cb_data)
|
||||||
{
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(submodule);
|
||||||
struct ref_iterator *iter;
|
struct ref_iterator *iter;
|
||||||
|
|
||||||
iter = files_ref_iterator_begin(submodule, prefix, flags);
|
if (!refs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
iter = refs->be->iterator_begin(refs, prefix, flags);
|
||||||
iter = prefix_ref_iterator_begin(iter, prefix, trim);
|
iter = prefix_ref_iterator_begin(iter, prefix, trim);
|
||||||
|
|
||||||
return do_for_each_ref_iterator(iter, fn, cb_data);
|
return do_for_each_ref_iterator(iter, fn, cb_data);
|
||||||
|
@ -1193,8 +1216,10 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function needs to return a meaningful errno on failure */
|
/* This function needs to return a meaningful errno on failure */
|
||||||
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
|
static const char *resolve_ref_recursively(struct ref_store *refs,
|
||||||
unsigned char *sha1, int *flags)
|
const char *refname,
|
||||||
|
int resolve_flags,
|
||||||
|
unsigned char *sha1, int *flags)
|
||||||
{
|
{
|
||||||
static struct strbuf sb_refname = STRBUF_INIT;
|
static struct strbuf sb_refname = STRBUF_INIT;
|
||||||
int unused_flags;
|
int unused_flags;
|
||||||
|
@ -1226,7 +1251,8 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
|
||||||
for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
|
for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
|
||||||
unsigned int read_flags = 0;
|
unsigned int read_flags = 0;
|
||||||
|
|
||||||
if (read_raw_ref(refname, sha1, &sb_refname, &read_flags)) {
|
if (refs->be->read_raw_ref(refs, refname,
|
||||||
|
sha1, &sb_refname, &read_flags)) {
|
||||||
*flags |= read_flags;
|
*flags |= read_flags;
|
||||||
if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING))
|
if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1265,3 +1291,266 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
|
||||||
errno = ELOOP;
|
errno = ELOOP;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* backend functions */
|
||||||
|
int refs_init_db(struct strbuf *err)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
|
||||||
|
return refs->be->init_db(refs, 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,
|
||||||
|
resolve_flags, sha1, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolve_gitlink_ref(const char *submodule, const char *refname,
|
||||||
|
unsigned char *sha1)
|
||||||
|
{
|
||||||
|
size_t len = strlen(submodule);
|
||||||
|
struct ref_store *refs;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
while (len && submodule[len - 1] == '/')
|
||||||
|
len--;
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (submodule[len]) {
|
||||||
|
/* We need to strip off one or more trailing slashes */
|
||||||
|
char *stripped = xmemdupz(submodule, len);
|
||||||
|
|
||||||
|
refs = get_ref_store(stripped);
|
||||||
|
free(stripped);
|
||||||
|
} else {
|
||||||
|
refs = get_ref_store(submodule);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!refs)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!resolve_ref_recursively(refs, refname, 0, sha1, &flags) ||
|
||||||
|
is_null_sha1(sha1))
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A pointer to the ref_store for the main repository: */
|
||||||
|
static struct ref_store *main_ref_store;
|
||||||
|
|
||||||
|
/* A linked list of ref_stores for submodules: */
|
||||||
|
static struct ref_store *submodule_ref_stores;
|
||||||
|
|
||||||
|
void base_ref_store_init(struct ref_store *refs,
|
||||||
|
const struct ref_storage_be *be,
|
||||||
|
const char *submodule)
|
||||||
|
{
|
||||||
|
refs->be = be;
|
||||||
|
if (!submodule) {
|
||||||
|
if (main_ref_store)
|
||||||
|
die("BUG: main_ref_store initialized twice");
|
||||||
|
|
||||||
|
refs->submodule = "";
|
||||||
|
refs->next = NULL;
|
||||||
|
main_ref_store = refs;
|
||||||
|
} else {
|
||||||
|
if (lookup_ref_store(submodule))
|
||||||
|
die("BUG: ref_store for submodule '%s' initialized twice",
|
||||||
|
submodule);
|
||||||
|
|
||||||
|
refs->submodule = xstrdup(submodule);
|
||||||
|
refs->next = submodule_ref_stores;
|
||||||
|
submodule_ref_stores = refs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ref_store *ref_store_init(const char *submodule)
|
||||||
|
{
|
||||||
|
const char *be_name = "files";
|
||||||
|
struct ref_storage_be *be = find_ref_storage_backend(be_name);
|
||||||
|
|
||||||
|
if (!be)
|
||||||
|
die("BUG: reference backend %s is unknown", be_name);
|
||||||
|
|
||||||
|
if (!submodule || !*submodule)
|
||||||
|
return be->init(NULL);
|
||||||
|
else
|
||||||
|
return be->init(submodule);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ref_store *lookup_ref_store(const char *submodule)
|
||||||
|
{
|
||||||
|
struct ref_store *refs;
|
||||||
|
|
||||||
|
if (!submodule || !*submodule)
|
||||||
|
return main_ref_store;
|
||||||
|
|
||||||
|
for (refs = submodule_ref_stores; refs; refs = refs->next) {
|
||||||
|
if (!strcmp(submodule, refs->submodule))
|
||||||
|
return refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ref_store *get_ref_store(const char *submodule)
|
||||||
|
{
|
||||||
|
struct ref_store *refs;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assert_main_repository(struct ref_store *refs, const char *caller)
|
||||||
|
{
|
||||||
|
if (*refs->submodule)
|
||||||
|
die("BUG: %s called for a submodule", caller);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* backend functions */
|
||||||
|
int pack_refs(unsigned int flags)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
|
||||||
|
return refs->be->pack_refs(refs, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int peel_ref(const char *refname, unsigned char *sha1)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
|
||||||
|
return refs->be->peel_ref(refs, refname, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ref_transaction_commit(struct ref_transaction *transaction,
|
||||||
|
struct strbuf *err)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
struct ref_iterator *iter;
|
||||||
|
|
||||||
|
iter = refs->be->reflog_iterator_begin(refs);
|
||||||
|
|
||||||
|
return do_for_each_ref_iterator(iter, 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->be->for_each_reflog_ent_reverse(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->be->for_each_reflog_ent(refs, refname, fn, cb_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int reflog_exists(const char *refname)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
|
||||||
|
return refs->be->reflog_exists(refs, refname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int safe_create_reflog(const char *refname, int force_create,
|
||||||
|
struct strbuf *err)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
|
||||||
|
return refs->be->create_reflog(refs, refname, force_create, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int delete_reflog(const char *refname)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
|
||||||
|
return refs->be->delete_reflog(refs, refname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int reflog_expire(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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int initial_ref_transaction_commit(struct ref_transaction *transaction,
|
||||||
|
struct strbuf *err)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
|
||||||
|
return refs->be->initial_transaction_commit(refs, transaction, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int delete_refs(struct string_list *refnames, unsigned int flags)
|
||||||
|
{
|
||||||
|
struct ref_store *refs = get_ref_store(NULL);
|
||||||
|
|
||||||
|
return refs->be->delete_refs(refs, refnames, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
13
refs.h
13
refs.h
|
@ -66,6 +66,8 @@ int ref_exists(const char *refname);
|
||||||
|
|
||||||
int is_branch(const char *refname);
|
int is_branch(const char *refname);
|
||||||
|
|
||||||
|
extern int refs_init_db(struct strbuf *err);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If refname is a non-symbolic reference that refers to a tag object,
|
* If refname is a non-symbolic reference that refers to a tag object,
|
||||||
* and the tag can be (recursively) dereferenced to a non-tag object,
|
* and the tag can be (recursively) dereferenced to a non-tag object,
|
||||||
|
@ -77,11 +79,12 @@ int is_branch(const char *refname);
|
||||||
int peel_ref(const char *refname, unsigned char *sha1);
|
int peel_ref(const char *refname, unsigned char *sha1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve refname in the nested "gitlink" repository that is located
|
* Resolve refname in the nested "gitlink" repository in the specified
|
||||||
* at path. If the resolution is successful, return 0 and set sha1 to
|
* submodule (which must be non-NULL). If the resolution is
|
||||||
* the name of the object; otherwise, return a non-zero value.
|
* successful, return 0 and set sha1 to the name of the object;
|
||||||
|
* otherwise, return a non-zero value.
|
||||||
*/
|
*/
|
||||||
int resolve_gitlink_ref(const char *path, const char *refname,
|
int resolve_gitlink_ref(const char *submodule, const char *refname,
|
||||||
unsigned char *sha1);
|
unsigned char *sha1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -544,4 +547,6 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
|
||||||
reflog_expiry_cleanup_fn cleanup_fn,
|
reflog_expiry_cleanup_fn cleanup_fn,
|
||||||
void *policy_cb_data);
|
void *policy_cb_data);
|
||||||
|
|
||||||
|
int ref_storage_backend_exists(const char *name);
|
||||||
|
|
||||||
#endif /* REFS_H */
|
#endif /* REFS_H */
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -162,7 +162,7 @@ struct ref_update {
|
||||||
*/
|
*/
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
struct ref_lock *lock;
|
void *backend_data;
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
char *msg;
|
char *msg;
|
||||||
|
|
||||||
|
@ -240,7 +240,17 @@ const char *find_descendant_ref(const char *dirname,
|
||||||
const struct string_list *extras,
|
const struct string_list *extras,
|
||||||
const struct string_list *skip);
|
const struct string_list *skip);
|
||||||
|
|
||||||
int rename_ref_available(const char *oldname, const char *newname);
|
/*
|
||||||
|
* Check whether an attempt to rename old_refname to new_refname would
|
||||||
|
* cause a D/F conflict with any existing reference (other than
|
||||||
|
* possibly old_refname). If there would be a conflict, emit an error
|
||||||
|
* message and return false; otherwise, return true.
|
||||||
|
*
|
||||||
|
* Note that this function is not safe against all races with other
|
||||||
|
* 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);
|
||||||
|
|
||||||
/* We allow "recursive" symbolic refs. Only within reason, though */
|
/* We allow "recursive" symbolic refs. Only within reason, though */
|
||||||
#define SYMREF_MAXDEPTH 5
|
#define SYMREF_MAXDEPTH 5
|
||||||
|
@ -394,23 +404,6 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
int trim);
|
int trim);
|
||||||
|
|
||||||
/*
|
|
||||||
* Iterate over the packed and loose references in the specified
|
|
||||||
* submodule that are within find_containing_dir(prefix). If prefix is
|
|
||||||
* NULL or the empty string, iterate over all references in the
|
|
||||||
* submodule.
|
|
||||||
*/
|
|
||||||
struct ref_iterator *files_ref_iterator_begin(const char *submodule,
|
|
||||||
const char *prefix,
|
|
||||||
unsigned int flags);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Iterate over the references in the main ref_store that have a
|
|
||||||
* reflog. The paths within a directory are iterated over in arbitrary
|
|
||||||
* order.
|
|
||||||
*/
|
|
||||||
struct ref_iterator *files_reflog_iterator_begin(void);
|
|
||||||
|
|
||||||
/* Internal implementation of reference iteration: */
|
/* Internal implementation of reference iteration: */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -475,8 +468,85 @@ int do_for_each_ref_iterator(struct ref_iterator *iter,
|
||||||
each_ref_fn fn, void *cb_data);
|
each_ref_fn fn, void *cb_data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the specified reference from the filesystem or packed refs
|
* Only include per-worktree refs in a do_for_each_ref*() iteration.
|
||||||
* file, non-recursively. Set type to describe the reference, and:
|
* Normally this will be used with a files ref_store, since that's
|
||||||
|
* where all reference backends will presumably store their
|
||||||
|
* per-worktree refs.
|
||||||
|
*/
|
||||||
|
#define DO_FOR_EACH_PER_WORKTREE_ONLY 0x02
|
||||||
|
|
||||||
|
struct ref_store;
|
||||||
|
|
||||||
|
/* refs backends */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
typedef struct ref_store *ref_store_init_fn(const char *submodule);
|
||||||
|
|
||||||
|
typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err);
|
||||||
|
|
||||||
|
typedef int ref_transaction_commit_fn(struct ref_store *refs,
|
||||||
|
struct ref_transaction *transaction,
|
||||||
|
struct strbuf *err);
|
||||||
|
|
||||||
|
typedef int pack_refs_fn(struct ref_store *ref_store, unsigned int flags);
|
||||||
|
typedef int peel_ref_fn(struct ref_store *ref_store,
|
||||||
|
const char *refname, unsigned char *sha1);
|
||||||
|
typedef int create_symref_fn(struct ref_store *ref_store,
|
||||||
|
const char *ref_target,
|
||||||
|
const char *refs_heads_master,
|
||||||
|
const char *logmsg);
|
||||||
|
typedef int delete_refs_fn(struct ref_store *ref_store,
|
||||||
|
struct string_list *refnames, unsigned int flags);
|
||||||
|
typedef int rename_ref_fn(struct ref_store *ref_store,
|
||||||
|
const char *oldref, const char *newref,
|
||||||
|
const char *logmsg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate over the references in the specified ref_store that are
|
||||||
|
* within find_containing_dir(prefix). If prefix is NULL or the empty
|
||||||
|
* string, iterate over all references in the submodule.
|
||||||
|
*/
|
||||||
|
typedef struct ref_iterator *ref_iterator_begin_fn(
|
||||||
|
struct ref_store *ref_store,
|
||||||
|
const char *prefix, unsigned int flags);
|
||||||
|
|
||||||
|
/* reflog functions */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate over the references in the specified ref_store that have a
|
||||||
|
* reflog. The refs are iterated over in arbitrary order.
|
||||||
|
*/
|
||||||
|
typedef struct ref_iterator *reflog_iterator_begin_fn(
|
||||||
|
struct ref_store *ref_store);
|
||||||
|
|
||||||
|
typedef int for_each_reflog_ent_fn(struct ref_store *ref_store,
|
||||||
|
const char *refname,
|
||||||
|
each_reflog_ent_fn fn,
|
||||||
|
void *cb_data);
|
||||||
|
typedef int for_each_reflog_ent_reverse_fn(struct ref_store *ref_store,
|
||||||
|
const char *refname,
|
||||||
|
each_reflog_ent_fn fn,
|
||||||
|
void *cb_data);
|
||||||
|
typedef int reflog_exists_fn(struct ref_store *ref_store, const char *refname);
|
||||||
|
typedef int create_reflog_fn(struct ref_store *ref_store, const char *refname,
|
||||||
|
int force_create, struct strbuf *err);
|
||||||
|
typedef int delete_reflog_fn(struct ref_store *ref_store, const char *refname);
|
||||||
|
typedef int reflog_expire_fn(struct ref_store *ref_store,
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a reference from the specified reference store, non-recursively.
|
||||||
|
* Set type to describe the reference, and:
|
||||||
*
|
*
|
||||||
* - If refname is the name of a normal reference, fill in sha1
|
* - If refname is the name of a normal reference, fill in sha1
|
||||||
* (leaving referent unchanged).
|
* (leaving referent unchanged).
|
||||||
|
@ -512,7 +582,111 @@ int do_for_each_ref_iterator(struct ref_iterator *iter,
|
||||||
* - in all other cases, referent will be untouched, and therefore
|
* - in all other cases, referent will be untouched, and therefore
|
||||||
* refname will still be valid and unchanged.
|
* refname will still be valid and unchanged.
|
||||||
*/
|
*/
|
||||||
int read_raw_ref(const char *refname, unsigned char *sha1,
|
typedef int read_raw_ref_fn(struct ref_store *ref_store,
|
||||||
struct strbuf *referent, unsigned int *type);
|
const char *refname, unsigned char *sha1,
|
||||||
|
struct strbuf *referent, unsigned int *type);
|
||||||
|
|
||||||
|
typedef int verify_refname_available_fn(struct ref_store *ref_store,
|
||||||
|
const char *newname,
|
||||||
|
const struct string_list *extras,
|
||||||
|
const struct string_list *skip,
|
||||||
|
struct strbuf *err);
|
||||||
|
|
||||||
|
struct ref_storage_be {
|
||||||
|
struct ref_storage_be *next;
|
||||||
|
const char *name;
|
||||||
|
ref_store_init_fn *init;
|
||||||
|
ref_init_db_fn *init_db;
|
||||||
|
ref_transaction_commit_fn *transaction_commit;
|
||||||
|
ref_transaction_commit_fn *initial_transaction_commit;
|
||||||
|
|
||||||
|
pack_refs_fn *pack_refs;
|
||||||
|
peel_ref_fn *peel_ref;
|
||||||
|
create_symref_fn *create_symref;
|
||||||
|
delete_refs_fn *delete_refs;
|
||||||
|
rename_ref_fn *rename_ref;
|
||||||
|
|
||||||
|
ref_iterator_begin_fn *iterator_begin;
|
||||||
|
read_raw_ref_fn *read_raw_ref;
|
||||||
|
verify_refname_available_fn *verify_refname_available;
|
||||||
|
|
||||||
|
reflog_iterator_begin_fn *reflog_iterator_begin;
|
||||||
|
for_each_reflog_ent_fn *for_each_reflog_ent;
|
||||||
|
for_each_reflog_ent_reverse_fn *for_each_reflog_ent_reverse;
|
||||||
|
reflog_exists_fn *reflog_exists;
|
||||||
|
create_reflog_fn *create_reflog;
|
||||||
|
delete_reflog_fn *delete_reflog;
|
||||||
|
reflog_expire_fn *reflog_expire;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ref_storage_be refs_be_files;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A representation of the reference store for the main repository or
|
||||||
|
* a submodule. The ref_store instances for submodules are kept in a
|
||||||
|
* linked list.
|
||||||
|
*/
|
||||||
|
struct ref_store {
|
||||||
|
/* The backend describing this ref_store's storage scheme: */
|
||||||
|
const struct ref_storage_be *be;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The name of the submodule represented by this object, or
|
||||||
|
* the empty string if it represents the main repository's
|
||||||
|
* reference store:
|
||||||
|
*/
|
||||||
|
const char *submodule;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Submodule reference store instances are stored in a linked
|
||||||
|
* list using this pointer.
|
||||||
|
*/
|
||||||
|
struct ref_store *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill in the generic part of refs for the specified submodule and
|
||||||
|
* add it to our collection of reference stores.
|
||||||
|
*/
|
||||||
|
void base_ref_store_init(struct ref_store *refs,
|
||||||
|
const struct ref_storage_be *be,
|
||||||
|
const char *submodule);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create, record, and return a ref_store instance for the specified
|
||||||
|
* submodule (or the main repository if submodule is NULL).
|
||||||
|
*
|
||||||
|
* For backwards compatibility, submodule=="" is treated the same as
|
||||||
|
* submodule==NULL.
|
||||||
|
*/
|
||||||
|
struct ref_store *ref_store_init(const char *submodule);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* For backwards compatibility, submodule=="" is treated the same as
|
||||||
|
* submodule==NULL.
|
||||||
|
*/
|
||||||
|
struct ref_store *lookup_ref_store(const char *submodule);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Die if refs is for a submodule (i.e., not for the main repository).
|
||||||
|
* caller is used in any necessary error messages.
|
||||||
|
*/
|
||||||
|
void assert_main_repository(struct ref_store *refs, const char *caller);
|
||||||
|
|
||||||
#endif /* REFS_REFS_INTERNAL_H */
|
#endif /* REFS_REFS_INTERNAL_H */
|
||||||
|
|
Loading…
Reference in a new issue