From 11f8457fb9b787f350e176fd28ee8c01fd2b82d5 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 26 Mar 2017 09:42:15 +0700 Subject: files-backend: make files_log_ref_write() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created in 5f3c3a4e6f (files_log_ref_write: new function - 2015-11-10) but probably never used outside refs-internal.c Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- refs/refs-internal.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'refs/refs-internal.h') diff --git a/refs/refs-internal.h b/refs/refs-internal.h index fa93c9a32e..f732473e1d 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -228,10 +228,6 @@ struct ref_transaction { 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 -- cgit v1.3 From 5d0bc90e5de37c708f0856aef2c7b353a9d5030b Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 26 Mar 2017 09:42:31 +0700 Subject: refs: move submodule code out of files-backend.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit files-backend is now initialized with a $GIT_DIR. Converting a submodule path to where real submodule gitdir is located is done in get_ref_store(). This gives a slight performance improvement for submodules since we don't convert submodule path to gitdir at every backend call like before. We pay that once at ref-store creation. More cleanup in files_downcast() and files_assert_main_repository() follows shortly. It's separate to keep noises from this patch. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- refs.c | 19 ++++++++++++++----- refs/files-backend.c | 24 ++---------------------- refs/refs-internal.h | 9 ++++----- 3 files changed, 20 insertions(+), 32 deletions(-) (limited to 'refs/refs-internal.h') diff --git a/refs.c b/refs.c index 1f4c1a2347..d72b48a430 100644 --- a/refs.c +++ b/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 @@ -1413,9 +1414,9 @@ static struct ref_store *lookup_submodule_ref_store(const char *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) { const char *be_name = "files"; struct ref_storage_be *be = find_ref_storage_backend(be_name); @@ -1424,7 +1425,7 @@ 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); + refs = be->init(gitdir); return refs; } @@ -1433,7 +1434,7 @@ struct ref_store *get_main_ref_store(void) if (main_ref_store) return main_ref_store; - main_ref_store = ref_store_init(NULL); + main_ref_store = ref_store_init(get_git_dir()); return main_ref_store; } @@ -1474,8 +1475,16 @@ struct ref_store *get_ref_store(const char *submodule) if (!ret) return NULL; - refs = ref_store_init(submodule); + ret = submodule_to_gitdir(&submodule_sb, submodule); + if (ret) { + strbuf_release(&submodule_sb); + return NULL; + } + + refs = ref_store_init(submodule_sb.buf); register_submodule_ref_store(refs, submodule); + + strbuf_release(&submodule_sb); return refs; } diff --git a/refs/files-backend.c b/refs/files-backend.c index b62f374f9c..490f05a6f4 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -917,12 +917,6 @@ struct packed_ref_cache { struct files_ref_store { struct ref_store base; - /* - * The name of the submodule represented by this object, or - * NULL if it represents the main repository's reference - * store: - */ - const char *submodule; char *gitdir; char *gitcommondir; char *packed_refs_path; @@ -982,22 +976,14 @@ static void clear_loose_ref_cache(struct files_ref_store *refs) * Create a new submodule ref cache and add it to the internal * set of caches. */ -static struct ref_store *files_ref_store_create(const char *submodule) +static struct ref_store *files_ref_store_create(const char *gitdir) { struct files_ref_store *refs = xcalloc(1, sizeof(*refs)); struct ref_store *ref_store = (struct ref_store *)refs; struct strbuf sb = STRBUF_INIT; - const char *gitdir = get_git_dir(); base_ref_store_init(ref_store, &refs_be_files); - if (submodule) { - refs->submodule = xstrdup(submodule); - refs->packed_refs_path = git_pathdup_submodule( - refs->submodule, "packed-refs"); - return ref_store; - } - refs->gitdir = xstrdup(gitdir); get_common_dir_noenv(&sb, gitdir); refs->gitcommondir = strbuf_detach(&sb, NULL); @@ -1014,8 +1000,7 @@ static struct ref_store *files_ref_store_create(const char *submodule) static void files_assert_main_repository(struct files_ref_store *refs, const char *caller) { - if (refs->submodule) - die("BUG: %s called for a submodule", caller); + /* This function is to be fixed up in the next patch */ } /* @@ -1206,11 +1191,6 @@ static void files_ref_path(struct files_ref_store *refs, struct strbuf *sb, const char *refname) { - if (refs->submodule) { - strbuf_git_path_submodule(sb, refs->submodule, "%s", refname); - return; - } - switch (ref_type(refname)) { case REF_TYPE_PER_WORKTREE: case REF_TYPE_PSEUDOREF: diff --git a/refs/refs-internal.h b/refs/refs-internal.h index f732473e1d..dfa1817929 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -482,12 +482,11 @@ 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. + * 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); typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err); -- cgit v1.3 From 9e7ec634a130535982e9bc63d65c2fe8c076a662 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 26 Mar 2017 09:42:32 +0700 Subject: files-backend: replace submodule_allowed check in files_downcast() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit files-backend.c is unlearning submodules. Instead of having a specific check for submodules to see what operation is allowed, files backend now takes a set of flags at init. Each operation will check if the required flags is present before performing. For now we have four flags: read, write and odb access. Main ref store has all flags, obviously, while submodule stores are read-only and have access to odb (*). The "main" flag stays because many functions in the backend calls frontend ones without a ref store, so these functions always target the main ref store. Ideally the flag should be gone after ref-store-aware api is in place and used by backends. (*) Submodule code needs for_each_ref. Try take REF_STORE_ODB flag out. At least t3404 would fail. The "have access to odb" in submodule is a bit hacky since we don't know from he whether add_submodule_odb() has been called. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- refs.c | 15 ++++++--- refs/files-backend.c | 86 +++++++++++++++++++++++++++++++++------------------- refs/refs-internal.h | 9 +++++- 3 files changed, 73 insertions(+), 37 deletions(-) (limited to 'refs/refs-internal.h') diff --git a/refs.c b/refs.c index d72b48a430..c7bffac06d 100644 --- a/refs.c +++ b/refs.c @@ -1416,7 +1416,8 @@ static struct ref_store *lookup_submodule_ref_store(const char *submodule) * Create, record, and return a ref_store instance for the specified * gitdir. */ -static struct ref_store *ref_store_init(const char *gitdir) +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); @@ -1425,7 +1426,7 @@ static struct ref_store *ref_store_init(const char *gitdir) if (!be) die("BUG: reference backend %s is unknown", be_name); - refs = be->init(gitdir); + refs = be->init(gitdir, flags); return refs; } @@ -1434,7 +1435,11 @@ 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()); + 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; } @@ -1481,7 +1486,9 @@ struct ref_store *get_ref_store(const char *submodule) return NULL; } - refs = ref_store_init(submodule_sb.buf); + /* 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); diff --git a/refs/files-backend.c b/refs/files-backend.c index 490f05a6f4..c90b47232e 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -916,6 +916,7 @@ struct packed_ref_cache { */ struct files_ref_store { struct ref_store base; + unsigned int store_flags; char *gitdir; char *gitcommondir; @@ -976,13 +977,15 @@ static void clear_loose_ref_cache(struct files_ref_store *refs) * Create a new submodule ref cache and add it to the internal * set of caches. */ -static struct ref_store *files_ref_store_create(const char *gitdir) +static struct ref_store *files_ref_store_create(const char *gitdir, + unsigned int flags) { struct files_ref_store *refs = xcalloc(1, sizeof(*refs)); struct ref_store *ref_store = (struct ref_store *)refs; struct strbuf sb = STRBUF_INIT; base_ref_store_init(ref_store, &refs_be_files); + refs->store_flags = flags; refs->gitdir = xstrdup(gitdir); get_common_dir_noenv(&sb, gitdir); @@ -994,24 +997,27 @@ static struct ref_store *files_ref_store_create(const char *gitdir) } /* - * Die if refs is for a submodule (i.e., not for the main repository). - * caller is used in any necessary error messages. + * Die if refs is not the main ref store. caller is used in any + * necessary error messages. */ static void files_assert_main_repository(struct files_ref_store *refs, const char *caller) { - /* This function is to be fixed up in the next patch */ + if (refs->store_flags & REF_STORE_MAIN) + return; + + die("BUG: operation %s only allowed for main ref store", caller); } /* * Downcast ref_store to files_ref_store. Die if ref_store is not a - * files_ref_store. If submodule_allowed is not true, then also die if - * files_ref_store is for a submodule (i.e., not for the main - * repository). caller is used in any necessary error messages. + * files_ref_store. required_flags is compared with ref_store's + * store_flags to ensure the ref_store has all required capabilities. + * "caller" is used in any necessary error messages. */ -static struct files_ref_store *files_downcast( - struct ref_store *ref_store, int submodule_allowed, - const char *caller) +static struct files_ref_store *files_downcast(struct ref_store *ref_store, + unsigned int required_flags, + const char *caller) { struct files_ref_store *refs; @@ -1021,8 +1027,9 @@ static struct files_ref_store *files_downcast( refs = (struct files_ref_store *)ref_store; - if (!submodule_allowed) - files_assert_main_repository(refs, caller); + if ((refs->store_flags & required_flags) != required_flags) + die("BUG: operation %s requires abilities 0x%x, but only have 0x%x", + caller, required_flags, refs->store_flags); return refs; } @@ -1398,7 +1405,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, struct strbuf *referent, unsigned int *type) { struct files_ref_store *refs = - files_downcast(ref_store, 1, "read_raw_ref"); + files_downcast(ref_store, REF_STORE_READ, "read_raw_ref"); struct strbuf sb_contents = STRBUF_INIT; struct strbuf sb_path = STRBUF_INIT; const char *path; @@ -1815,10 +1822,14 @@ static enum peel_status peel_entry(struct ref_entry *entry, int repeel) static int files_peel_ref(struct ref_store *ref_store, const char *refname, unsigned char *sha1) { - struct files_ref_store *refs = files_downcast(ref_store, 0, "peel_ref"); + struct files_ref_store *refs = + files_downcast(ref_store, REF_STORE_READ | REF_STORE_ODB, + "peel_ref"); int flag; unsigned char base[20]; + files_assert_main_repository(refs, "peel_ref"); + if (current_ref_iter && current_ref_iter->refname == refname) { struct object_id peeled; @@ -1923,8 +1934,7 @@ static struct ref_iterator *files_ref_iterator_begin( struct ref_store *ref_store, const char *prefix, unsigned int flags) { - struct files_ref_store *refs = - files_downcast(ref_store, 1, "ref_iterator_begin"); + struct files_ref_store *refs; struct ref_dir *loose_dir, *packed_dir; struct ref_iterator *loose_iter, *packed_iter; struct files_ref_iterator *iter; @@ -1935,6 +1945,10 @@ static struct ref_iterator *files_ref_iterator_begin( if (ref_paranoia) flags |= DO_FOR_EACH_INCLUDE_BROKEN; + refs = files_downcast(ref_store, + REF_STORE_READ | (ref_paranoia ? 0 : REF_STORE_ODB), + "ref_iterator_begin"); + iter = xcalloc(1, sizeof(*iter)); ref_iterator = &iter->base; base_ref_iterator_init(ref_iterator, &files_ref_iterator_vtable); @@ -2415,7 +2429,8 @@ static void prune_refs(struct ref_to_prune *r) static int files_pack_refs(struct ref_store *ref_store, unsigned int flags) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "pack_refs"); + files_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB, + "pack_refs"); struct pack_refs_cb_data cbdata; memset(&cbdata, 0, sizeof(cbdata)); @@ -2494,7 +2509,7 @@ static int files_delete_refs(struct ref_store *ref_store, struct string_list *refnames, unsigned int flags) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "delete_refs"); + files_downcast(ref_store, REF_STORE_WRITE, "delete_refs"); struct strbuf err = STRBUF_INIT; int i, result = 0; @@ -2598,7 +2613,7 @@ static int files_verify_refname_available(struct ref_store *ref_store, struct strbuf *err) { struct files_ref_store *refs = - files_downcast(ref_store, 1, "verify_refname_available"); + files_downcast(ref_store, REF_STORE_READ, "verify_refname_available"); struct ref_dir *packed_refs = get_packed_refs(refs); struct ref_dir *loose_refs = get_loose_refs(refs); @@ -2623,7 +2638,7 @@ static int files_rename_ref(struct ref_store *ref_store, const char *logmsg) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "rename_ref"); + files_downcast(ref_store, REF_STORE_WRITE, "rename_ref"); unsigned char sha1[20], orig_sha1[20]; int flag = 0, logmoved = 0; struct ref_lock *lock; @@ -2873,7 +2888,7 @@ static int files_create_reflog(struct ref_store *ref_store, struct strbuf *err) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "create_reflog"); + files_downcast(ref_store, REF_STORE_WRITE, "create_reflog"); int fd; if (log_ref_setup(refs, refname, force_create, &fd, err)) @@ -3117,7 +3132,7 @@ static int files_create_symref(struct ref_store *ref_store, const char *logmsg) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "create_symref"); + files_downcast(ref_store, REF_STORE_WRITE, "create_symref"); struct strbuf err = STRBUF_INIT; struct ref_lock *lock; int ret; @@ -3143,7 +3158,9 @@ int set_worktree_head_symref(const char *gitdir, const char *target, const char * backends. This function needs to die. */ struct files_ref_store *refs = - files_downcast(get_main_ref_store(), 0, "set_head_symref"); + files_downcast(get_main_ref_store(), + REF_STORE_WRITE, + "set_head_symref"); static struct lock_file head_lock; struct ref_lock *lock; @@ -3182,7 +3199,7 @@ static int files_reflog_exists(struct ref_store *ref_store, const char *refname) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "reflog_exists"); + files_downcast(ref_store, REF_STORE_READ, "reflog_exists"); struct strbuf sb = STRBUF_INIT; struct stat st; int ret; @@ -3197,7 +3214,7 @@ static int files_delete_reflog(struct ref_store *ref_store, const char *refname) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "delete_reflog"); + files_downcast(ref_store, REF_STORE_WRITE, "delete_reflog"); struct strbuf sb = STRBUF_INIT; int ret; @@ -3253,7 +3270,8 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store, void *cb_data) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "for_each_reflog_ent_reverse"); + files_downcast(ref_store, REF_STORE_READ, + "for_each_reflog_ent_reverse"); struct strbuf sb = STRBUF_INIT; FILE *logfp; long pos; @@ -3361,7 +3379,8 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store, each_reflog_ent_fn fn, void *cb_data) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "for_each_reflog_ent"); + files_downcast(ref_store, REF_STORE_READ, + "for_each_reflog_ent"); FILE *logfp; struct strbuf sb = STRBUF_INIT; int ret = 0; @@ -3449,7 +3468,8 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = { static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "reflog_iterator_begin"); + files_downcast(ref_store, REF_STORE_READ, + "reflog_iterator_begin"); struct files_reflog_iterator *iter = xcalloc(1, sizeof(*iter)); struct ref_iterator *ref_iterator = &iter->base; struct strbuf sb = STRBUF_INIT; @@ -3787,7 +3807,8 @@ static int files_transaction_commit(struct ref_store *ref_store, struct strbuf *err) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "ref_transaction_commit"); + files_downcast(ref_store, REF_STORE_WRITE, + "ref_transaction_commit"); int ret = 0, i; struct string_list refs_to_delete = STRING_LIST_INIT_NODUP; struct string_list_item *ref_to_delete; @@ -3992,7 +4013,8 @@ static int files_initial_transaction_commit(struct ref_store *ref_store, struct strbuf *err) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "initial_ref_transaction_commit"); + files_downcast(ref_store, REF_STORE_WRITE, + "initial_ref_transaction_commit"); int ret = 0, i; struct string_list affected_refnames = STRING_LIST_INIT_NODUP; @@ -4114,7 +4136,7 @@ static int files_reflog_expire(struct ref_store *ref_store, void *policy_cb_data) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "reflog_expire"); + files_downcast(ref_store, REF_STORE_WRITE, "reflog_expire"); static struct lock_file reflog_lock; struct expire_reflog_cb cb; struct ref_lock *lock; @@ -4220,7 +4242,7 @@ static int files_reflog_expire(struct ref_store *ref_store, static int files_init_db(struct ref_store *ref_store, struct strbuf *err) { struct files_ref_store *refs = - files_downcast(ref_store, 0, "init_db"); + files_downcast(ref_store, REF_STORE_WRITE, "init_db"); struct strbuf sb = STRBUF_INIT; /* diff --git a/refs/refs-internal.h b/refs/refs-internal.h index dfa1817929..0cca280b5c 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -481,12 +481,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 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 *gitdir); +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); -- cgit v1.3 From 18d0002d6ddc191454b6b4a99cdac65fc7ff9ece Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 26 Mar 2017 09:42:33 +0700 Subject: refs: rename get_ref_store() to get_submodule_ref_store() and make it public MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function is intended to replace *_submodule() refs API. It provides a ref store for a specific submodule, which can be operated on by a new set of refs API. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- refs.c | 12 ++++++++---- refs.h | 11 +++++++++++ refs/refs-internal.h | 12 ------------ 3 files changed, 19 insertions(+), 16 deletions(-) (limited to 'refs/refs-internal.h') diff --git a/refs.c b/refs.c index c7bffac06d..fbbd9e1f63 100644 --- a/refs.c +++ b/refs.c @@ -1171,7 +1171,7 @@ int head_ref(each_ref_fn fn, void *cb_data) static int do_for_each_ref(const char *submodule, const char *prefix, each_ref_fn fn, int trim, int flags, void *cb_data) { - struct ref_store *refs = get_ref_store(submodule); + struct ref_store *refs = get_submodule_ref_store(submodule); struct ref_iterator *iter; if (!refs) @@ -1344,10 +1344,10 @@ 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) @@ -1460,13 +1460,17 @@ static void register_submodule_ref_store(struct ref_store *refs, submodule); } -struct ref_store *get_ref_store(const char *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) { + /* + * FIXME: This case is ideally not allowed. But that + * can't happen until we clean up all the callers. + */ return get_main_ref_store(); } diff --git a/refs.h b/refs.h index a6cd12267f..e6d8f67895 100644 --- a/refs.h +++ b/refs.h @@ -562,5 +562,16 @@ 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 */ diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 0cca280b5c..f20dde39ee 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -646,18 +646,6 @@ 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, -- cgit v1.3 From 7d2df051d05bc65a0a540ba080f07b421b4d99d7 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 26 Mar 2017 09:42:34 +0700 Subject: refs: add new ref-store api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not meant to cover all existing API. It adds enough to test ref stores with the new test program test-ref-store, coming soon and to be used by files-backend.c. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- refs.c | 251 ++++++++++++++++++++++++++++++++++++++------------- refs.h | 74 +++++++++++++++ refs/files-backend.c | 13 +-- refs/refs-internal.h | 31 +------ 4 files changed, 270 insertions(+), 99 deletions(-) (limited to 'refs/refs-internal.h') diff --git a/refs.c b/refs.c index fbbd9e1f63..c1cb0b6908 100644 --- a/refs.c +++ b/refs.c @@ -171,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 */ @@ -185,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); @@ -286,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) @@ -1120,14 +1157,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); @@ -1168,10 +1208,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_submodule_ref_store(submodule); struct ref_iterator *iter; if (!refs) @@ -1183,19 +1222,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) @@ -1204,19 +1254,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) @@ -1224,19 +1278,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) @@ -1323,7 +1383,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_main_ref_store(), refname, + return refs_resolve_ref_unsafe(get_main_ref_store(), refname, resolve_flags, sha1, flags); } @@ -1353,7 +1413,7 @@ int resolve_gitlink_ref(const char *submodule, const char *refname, 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; @@ -1506,27 +1566,42 @@ void base_ref_store_init(struct ref_store *refs, } /* backend functions */ +int refs_pack_refs(struct ref_store *refs, unsigned int flags) +{ + return refs->be->pack_refs(refs, flags); +} + int pack_refs(unsigned int flags) { - struct ref_store *refs = get_main_ref_store(); + return refs_pack_refs(get_main_ref_store(), flags); +} - 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_main_ref_store(); + 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_main_ref_store(); - - 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, @@ -1537,19 +1612,17 @@ int ref_transaction_commit(struct ref_transaction *transaction, 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_main_ref_store(); - 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_main_ref_store(); struct ref_iterator *iter; iter = refs->be->reflog_iterator_begin(refs); @@ -1557,43 +1630,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_ent_reverse(const char *refname, each_reflog_ent_fn fn, - void *cb_data) +int for_each_reflog(each_ref_fn fn, void *cb_data) { - struct ref_store *refs = get_main_ref_store(); + 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) +{ + return refs_for_each_reflog_ent_reverse(get_main_ref_store(), + 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_main_ref_store(); + 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_main_ref_store(); + 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_main_ref_store(); + 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_main_ref_store(); + 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, @@ -1603,11 +1717,10 @@ 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_main_ref_store(); - - 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, @@ -1618,16 +1731,24 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction, return refs->be->initial_transaction_commit(refs, transaction, err); } -int delete_refs(struct string_list *refnames, unsigned int flags) +int refs_delete_refs(struct ref_store *refs, struct string_list *refnames, + unsigned int flags) { - struct ref_store *refs = get_main_ref_store(); - return refs->be->delete_refs(refs, refnames, flags); } -int rename_ref(const char *oldref, const char *newref, const char *logmsg) +int delete_refs(struct string_list *refnames, unsigned int flags) { - struct ref_store *refs = get_main_ref_store(); + return refs_delete_refs(get_main_ref_store(), 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) +{ + return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg); +} diff --git a/refs.h b/refs.h index e6d8f67895..eaa31e8193 100644 --- a/refs.h +++ b/refs.h @@ -57,16 +57,50 @@ struct string_list; #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); @@ -83,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); /** @@ -196,6 +232,17 @@ typedef int each_ref_fn(const char *refname, * modifies the reference also returns a nonzero value to immediately * stop the iteration. */ +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); @@ -225,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) @@ -248,6 +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 refs_pack_refs(struct ref_store *refs, unsigned int flags); int pack_refs(unsigned int flags); /* @@ -263,6 +312,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. **/ @@ -272,6 +323,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); /* @@ -290,9 +342,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 */ @@ -301,6 +356,12 @@ 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); @@ -308,6 +369,7 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void * Calls the specified function for each reflog file until it returns nonzero, * and returns the value */ +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 @@ -328,8 +390,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); /* @@ -552,6 +618,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, diff --git a/refs/files-backend.c b/refs/files-backend.c index c90b47232e..f3ebdb279d 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1313,7 +1313,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir) create_dir_entry(refs, refname.buf, refname.len, 1)); } else { - if (!resolve_ref_recursively(&refs->base, + if (!refs_resolve_ref_unsafe(&refs->base, refname.buf, RESOLVE_REF_READING, sha1, &flag)) { @@ -1622,7 +1622,8 @@ retry: * another reference such as "refs/foo". There is no * reason to expect this error to be transitory. */ - if (verify_refname_available(refname, extras, skip, err)) { + if (refs_verify_refname_available(&refs->base, refname, + extras, skip, err)) { if (mustexist) { /* * To the user the relevant error is @@ -2670,7 +2671,7 @@ static int files_rename_ref(struct ref_store *ref_store, oldrefname); goto out; } - if (!rename_ref_available(oldrefname, newrefname)) { + if (!refs_rename_ref_available(&refs->base, oldrefname, newrefname)) { ret = 1; goto out; } @@ -4054,9 +4055,9 @@ static int files_initial_transaction_commit(struct ref_store *ref_store, if ((update->flags & REF_HAVE_OLD) && !is_null_sha1(update->old_sha1)) die("BUG: initial ref transaction with old_sha1 set"); - if (verify_refname_available(update->refname, - &affected_refnames, NULL, - err)) { + if (refs_verify_refname_available(&refs->base, update->refname, + &affected_refnames, NULL, + err)) { ret = TRANSACTION_NAME_CONFLICT; goto cleanup; } diff --git a/refs/refs-internal.h b/refs/refs-internal.h index f20dde39ee..5f26208c2c 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -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, @@ -252,7 +230,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 @@ -646,9 +626,4 @@ struct ref_store { void base_ref_store_init(struct ref_store *refs, const struct ref_storage_be *be); -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 */ -- cgit v1.3 From c0fe4e8ba3db828079f1288169a94294e713b3d8 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 26 Mar 2017 09:42:35 +0700 Subject: refs: new transaction related ref-store api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The transaction struct now takes a ref store at creation and will operate on that ref store alone. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- refs.c | 55 ++++++++++++++++++++++++++++++++++++++++------------ refs.h | 9 +++++++++ refs/refs-internal.h | 1 + 3 files changed, 53 insertions(+), 12 deletions(-) (limited to 'refs/refs-internal.h') diff --git a/refs.c b/refs.c index c1cb0b6908..ca1d100551 100644 --- a/refs.c +++ b/refs.c @@ -630,16 +630,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) || @@ -654,6 +658,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; @@ -813,11 +824,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) @@ -934,18 +954,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) || @@ -976,6 +998,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; @@ -1607,7 +1638,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master, int ref_transaction_commit(struct ref_transaction *transaction, struct strbuf *err) { - struct ref_store *refs = get_main_ref_store(); + struct ref_store *refs = transaction->ref_store; return refs->be->transaction_commit(refs, transaction, err); } @@ -1726,7 +1757,7 @@ int reflog_expire(const char *refname, const unsigned char *sha1, int initial_ref_transaction_commit(struct ref_transaction *transaction, struct strbuf *err) { - struct ref_store *refs = get_main_ref_store(); + struct ref_store *refs = transaction->ref_store; return refs->be->initial_transaction_commit(refs, transaction, err); } diff --git a/refs.h b/refs.h index eaa31e8193..37f4aa8bd5 100644 --- a/refs.h +++ b/refs.h @@ -333,6 +333,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); @@ -418,6 +422,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); /* @@ -552,6 +558,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); diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 5f26208c2c..690498698e 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -200,6 +200,7 @@ 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; -- cgit v1.3