Remove submodule from files-backend.c
Re: [PATCH v5 12/24] refs.c: kill register_ref_store(), add register_submodule_ref_store()
In reply to Nguyễn Thái Ngọc DuyQuoted 53 lines · Nguyễn Thái Ngọc Duy
This is the last function in this code (besides public API) that takes submodule argument and handles both main/submodule cases. Break it down, move main store registration in
get_main_ref_store()and keep the rest inregister_submodule_ref_store().Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.c | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-)refs.c +0
-24@@ -1412,29 +1412,6 @@ static struct ref_store *lookup_submodule_ref_store(const char *submodule) }/* -* 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). */ @@ -1448,7 +1425,6 @@ static struct ref_store *ref_store_init(const char *submodule)die ("BUG: reference backend %s is unknown" , be_name); refs = be->init (submodule); -register_ref_store (refs, submodule);return refs; }
refs.c static struct ref_store *get_main_ref_store(void) · line 1445
Quoted 10 lines
refs.c +6
-0@@ -1460,9 +1436,32 @@ static struct ref_store *get_main_ref_store(void)return main_ref_store; refs =ref_store_init (NULL ); +if (refs) { +if (main_ref_store) +die ("BUG: main_ref_store initialized twice" ); + + main_ref_store = refs; + }return refs;
Superfluous test: I don't think ref_store_init() ever returns NULL. This also implies that you could check main_ref_store before calling ref_store_init(), and eliminate a temporary.
Quoted 23 lines
refs.c +17
-0} +/* +* 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_ref_store (const char *submodule) {struct strbuf submodule_sb =STRBUF_INIT ;
refs.c struct ref_store *get_ref_store(const char *submodule) · line 1483
Quoted 5 lines
refs.c +2
-0@@ -1480,6 +1479,9 @@ struct ref_store *get_ref_store(const char *submodule)if (is_nonbare_repository_dir (&submodule_sb)) refs =ref_store_init (submodule);strbuf_release (&submodule_sb); + +if (refs)
I think refs should always be non-NULL here for the same reason.
refs.c struct ref_store *get_ref_store(const char *submodule) · line 1486
Quoted 3 lines
refs.c +1
-0+register_submodule_ref_store (refs, submodule);return refs; }
Michael
Re: [PATCH v5 12/24] refs.c: kill register_ref_store(), add register_submodule_ref_store()
Quoted 11 lines · Michael Haggerty
refs.c struct ref_store *get_ref_store(const char *submodule) · line 1483
Quoted 9 lines
struct
ref_store*get_ref_store(const char *submodule){ struct strbuf submodule_sb = STRBUF_INIT;refs.c +2
-0@@ -1480,6 +1479,9 @@ struct ref_store *get_ref_store(const char *submodule)if (is_nonbare_repository_dir (&submodule_sb)) refs =ref_store_init (submodule);strbuf_release (&submodule_sb); + +if (refs)I think
refsshould always be non-NULL here for the same reason.
That's true if is_nonbar_repo... returns true. If it's false (e.g. uninitialized submodule) then refs remains NULL from before (I didn't know about this until I hit a segfault in rev-list in another series)
Signature · 1 line
Duy
Re: [PATCH v5 12/24] refs.c: kill register_ref_store(), add register_submodule_ref_store()
Quoted 13 lines · Duy Nguyen
Quoted 11 lines · Michael Haggerty
refs.c struct ref_store *get_ref_store(const char *submodule) · line 1483
Quoted 9 lines
struct
ref_store*get_ref_store(const char *submodule){ struct strbuf submodule_sb = STRBUF_INIT;refs.c +2
-0@@ -1480,6 +1479,9 @@ struct ref_store *get_ref_store(const char *submodule)if (is_nonbare_repository_dir (&submodule_sb)) refs =ref_store_init (submodule);strbuf_release (&submodule_sb); + +if (refs)I think
refsshould always be non-NULL here for the same reason.
Quoted 3 lines
That's true if
is_nonbar_repo... returns true. If it's false (e.g. uninitialized submodule) then refs remains NULL from before (I didn't know about this until I hit a segfault in rev-list in another series)
Oh, yes, true.
But given that, I think the code would be clearer if the two calls were in the same if; i.e.,
refs = lookup_submodule_ref_store(submodule); if (refs)
return refs;
strbuf_addstr(&submodule_sb, submodule); if (is_nonbare_repository_dir(&submodule_sb)) {
refs = ref_store_init(submodule); register_submodule_ref_store(refs, submodule); }
strbuf_release(&submodule_sb);
return refs;
or even the if (!is_nonbare_repository_dir(...)) goto cleanup; pattern to make it clearer that this is an error return.
Michael
PATCH v5 13/24 refs.c: make get_main_ref_store() public and use it
In reply to Nguyễn Thái Ngọc Duyget_ref_store() will soon be renamed to get_submodule_ref_store(). Together with future get_worktree_ref_store(), the three functions provide an appropriate ref store for different operation modes. New APIs will be added to operate directly on ref stores.
--- refs.c | 36 ++++++++++++++++++------------------ refs.h | 3 +++ refs/files-backend.c | 2 +- 3 files changed, 22 insertions(+), 19 deletions(-)
refs.c +18 -18
@@ -1314,7 +1314,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); }
@@ -1322,7 +1322,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 resolve_ref_recursively (get_main_ref_store (), refname, resolve_flags, sha1, flags); }
@@ -1428,7 +1428,7 @@ static struct ref_store *ref_store_init(const char *submodule)return refs; } -static struct ref_store *get_main_ref_store (void ) +struct ref_store *get_main_ref_store (void ) {struct ref_store *refs;
@@ -1494,14 +1494,14 @@ void base_ref_store_init(struct ref_store *refs,/* backend functions */ int pack_refs (unsigned int flags) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->pack_refs (refs, flags); }int peel_ref (const char *refname,unsigned char *sha1) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->peel_ref (refs, refname, sha1); }
@@ -1509,7 +1509,7 @@ int peel_ref(const char *refname, unsigned char *sha1)int create_symref (const char *ref_target,const char *refs_heads_master,const char *logmsg) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->create_symref (refs, ref_target, refs_heads_master, logmsg);
@@ -1518,7 +1518,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_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->transaction_commit (refs, transaction, err); }
@@ -1528,14 +1528,14 @@ int verify_refname_available(const char *refname,const struct string_list *skip, struct strbuf *err) { - struct ref_store *refs = get_ref_store(NULL); + 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) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();struct ref_iterator *iter; iter = refs->be->reflog_iterator_begin (refs);
@@ -1546,7 +1546,7 @@ int for_each_reflog(each_ref_fn fn, void *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 ); +struct ref_store *refs =get_main_ref_store ();return refs->be->for_each_reflog_ent_reverse (refs, refname, fn, cb_data);
@@ -1555,14 +1555,14 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,int for_each_reflog_ent (const char *refname,each_reflog_ent_fn fn,void *cb_data) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();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 ); +struct ref_store *refs =get_main_ref_store ();return refs->be->reflog_exists (refs, refname); }
@@ -1570,14 +1570,14 @@ int reflog_exists(const char *refname)int safe_create_reflog (const char *refname,int force_create,struct strbuf *err) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->create_reflog (refs, refname, force_create, err); }int delete_reflog (const char *refname) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->delete_reflog (refs, refname); }
@@ -1589,7 +1589,7 @@ 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); + struct ref_store *refs = get_main_ref_store(); return refs->be->reflog_expire(refs, refname, sha1, flags, prepare_fn, should_prune_fn,
@@ -1599,21 +1599,21 @@ 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_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();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 ); +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) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->rename_ref (refs, oldref, newref, logmsg); }
refs.h +3 -0
@@ -2,6 +2,7 @@#define REFS_H struct object_id ; +struct ref_store ;struct ref_transaction ;struct strbuf ;struct string_list ;
@@ -559,4 +560,6 @@ 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 ); +#endif /* REFS_H */
refs/files-backend.c +1 -1
@@ -3165,7 +3165,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target)* backends. This function needs to die. */ struct files_ref_store *refs = -files_downcast (get_ref_store (NULL ),0 ,"set_head_symref" ); +files_downcast (get_main_ref_store (),0 ,"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 13/24] refs.c: make get_main_ref_store() public and use it
Quoted 4 lines · Nguyễn Thái Ngọc Duy
get_ref_store()will soon be renamed toget_submodule_ref_store(). Together with futureget_worktree_ref_store(), the three functions provide an appropriate ref store for different operation modes. New APIs will be added to operate directly on ref stores.
Nice.
Michael
PATCH v5 14/24 path.c: move some code out of strbuf_git_path_submodule()
In reply to Nguyễn Thái Ngọc Duyrefs is learning to avoid path rewriting that is done by strbuf_git_path_submodule(). Factor out this code so it could be reused by refs*
--- path.c | 34 +++++++--------------------------- submodule.c | 31 +++++++++++++++++++++++++++++++ submodule.h | 1 + 3 files changed, 39 insertions(+), 27 deletions(-)
path.c +7 -27
@@ -475,35 +475,16 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)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 +495,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, ...)
submodule.c +31 -0
@@ -1514,3 +1514,34 @@ void absorb_git_dir_into_superproject(const char *prefix,strbuf_release (&sb); } } + +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; +}
submodule.h +1 -0
@@ -81,6 +81,7 @@ extern int push_unpushed_submodules(struct sha1_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 ); +int submodule_to_gitdir (struct strbuf *buf,const char *submodule);/* * Prepare the "env_array" parameter of a "struct child_process" for executing
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 14/24] path.c: move some code out of strbuf_git_path_submodule()
Quoted 30 lines · Nguyễn Thái Ngọc Duy
refs is learning to avoid path rewriting that is done by
strbuf_git_path_submodule(). Factor out this code so it could be reused by refs*Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- path.c | 34 +++++++--------------------------- submodule.c | 31 +++++++++++++++++++++++++++++++ submodule.h | 1 + 3 files changed, 39 insertions(+), 27 deletions(-)path.c +1
-7@@ -475,35 +475,16 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)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" ); -
path.c const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...) · line 497
Quoted 10 lines
path.c +0
-10- 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 ;
I didn't read this patch too carefully, but where the old code used the constant SUBMODULE_PATH_ERR_NOT_CONFIGURED, the new code returns -1. In fact, now the constant is totally unused. It looks like there's some more cleanup that could happen.
Quoted 71 lines
path.c +6
-10- 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 +495,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, ...)submodule.c +31
-0@@ -1514,3 +1514,34 @@ void absorb_git_dir_into_superproject(const char *prefix,strbuf_release (&sb); } } + +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; +}submodule.h +0
-0
submodule.h extern int push_unpushed_submodules(struct sha1_array *commits, · line 84
Quoted 4 lines
submodule.h +1
-0@@ -81,6 +81,7 @@ extern int push_unpushed_submodules(struct sha1_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 ); +int submodule_to_gitdir (struct strbuf *buf,const char *submodule);
A docstring is always nice :-)
submodule.h extern int push_unpushed_submodules(struct sha1_array *commits,
Quoted 4 lines
submodule.h +0
-0/* * Prepare the "env_array" parameter of a "struct child_process" for executing
Michael
PATCH v5 15/24 refs: move submodule code out of files-backend.c
In reply to Nguyễn Thái Ngọc Duyfiles-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.
--- refs.c | 20 ++++++++++++++------ refs/files-backend.c | 24 ++---------------------- refs/refs-internal.h | 9 ++++----- 3 files changed, 20 insertions(+), 33 deletions(-)
refs.c +14 -6
@@ -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; }
@@ -1435,7 +1436,7 @@ struct ref_store *get_main_ref_store(void)if (main_ref_store)return main_ref_store; - refs =ref_store_init (NULL ); + refs =ref_store_init (get_git_dir ());if (refs) {if (main_ref_store)die ("BUG: main_ref_store initialized twice" );
@@ -1466,6 +1467,7 @@ struct ref_store *get_ref_store(const char *submodule) {struct strbuf submodule_sb =STRBUF_INIT ;struct ref_store *refs; +int ret;if (!submodule || !*submodule) {return get_main_ref_store ();
@@ -1476,8 +1478,14 @@ struct ref_store *get_ref_store(const char *submodule)return refs;strbuf_addstr (&submodule_sb, submodule); -if (is_nonbare_repository_dir (&submodule_sb)) - refs =ref_store_init (submodule); + ret =is_nonbare_repository_dir (&submodule_sb); +strbuf_release (&submodule_sb); +if (!ret) +return refs; + + ret =submodule_to_gitdir (&submodule_sb, submodule); +if (!ret) + refs =ref_store_init (submodule_sb.buf);strbuf_release (&submodule_sb);if (refs)
refs/files-backend.c +2 -22
@@ -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 deleted in the next patch */ }/*
@@ -1206,11 +1191,6 @@ static void files_refname_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:
refs/refs-internal.h +4 -5
@@ -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);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 15/24] refs: move submodule code out of files-backend.c
Quoted 68 lines · Nguyễn Thái Ngọc Duy
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()andfiles_assert_main_repository()follows shortly. It's separate to keep noises from this patch.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.c | 20 ++++++++++++++------ refs/files-backend.c | 24 ++---------------------- refs/refs-internal.h | 9 ++++----- 3 files changed, 20 insertions(+), 33 deletions(-)refs.c +6
-4@@ -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; }@@ -1435,7 +1436,7 @@ struct ref_store *get_main_ref_store(void)if (main_ref_store)return main_ref_store; - refs =ref_store_init (NULL ); + refs =ref_store_init (get_git_dir ());if (refs) {if (main_ref_store)die ("BUG: main_ref_store initialized twice" );@@ -1466,6 +1467,7 @@ struct ref_store *get_ref_store(const char *submodule) {struct strbuf submodule_sb =STRBUF_INIT ;struct ref_store *refs; +int ret;if (!submodule || !*submodule) {return get_main_ref_store ();
refs.c struct ref_store *get_ref_store(const char *submodule) · line 1484
Quoted 9 lines
refs.c +4
-2@@ -1476,8 +1478,14 @@ struct ref_store *get_ref_store(const char *submodule)return refs;strbuf_addstr (&submodule_sb, submodule); -if (is_nonbare_repository_dir (&submodule_sb)) - refs =ref_store_init (submodule); + ret =is_nonbare_repository_dir (&submodule_sb); +strbuf_release (&submodule_sb); +if (!ret) +return refs;
refs is always NULL here, right? Then it would be more transparent to return NULL. Or maybe use the goto cleanup pattern, which makes it clearer which are error-handling paths (and lets you get avoid the temporary variable ret)).
Quoted 49 lines
refs.c +4
-0+ + ret =submodule_to_gitdir (&submodule_sb, submodule); +if (!ret) + refs =ref_store_init (submodule_sb.buf);strbuf_release (&submodule_sb);if (refs)refs/files-backend.c +1
-15@@ -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 );
refs/files-backend.c static struct ref_store *files_ref_store_create(const char *submodule) · line 1003
Quoted 6 lines
refs/files-backend.c +1
-2@@ -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 deleted in the next patch */
I don't think the above comment is correct anymore. Possibly the commit log message is also out of date too, but I haven't read far enough ahead to know.
Quoted 1 line
[...]
Michael
PATCH v5 16/24 files-backend: replace submodule_allowed check in files_downcast()
In reply to Nguyễn Thái Ngọc Duyfiles-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.
--- refs.c | 15 ++++++--- refs/files-backend.c | 86 +++++++++++++++++++++++++++++++++------------------- refs/refs-internal.h | 9 +++++- 3 files changed, 73 insertions(+), 37 deletions(-)
refs.c +11 -4
@@ -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; }
@@ -1436,7 +1437,11 @@ struct ref_store *get_main_ref_store(void)if (main_ref_store)return main_ref_store; - refs =ref_store_init (get_git_dir ()); + refs =ref_store_init (get_git_dir (), + (REF_STORE_READ | +REF_STORE_WRITE | +REF_STORE_ODB | +REF_STORE_MAIN ));if (refs) {if (main_ref_store)die ("BUG: main_ref_store initialized twice" );
@@ -1485,7 +1490,9 @@ struct ref_store *get_ref_store(const char *submodule) ret =submodule_to_gitdir (&submodule_sb, submodule);if (!ret) - refs =ref_store_init (submodule_sb.buf); +/* pretend that add_submodule_odb() has been called */ + refs =ref_store_init (submodule_sb.buf, +REF_STORE_READ |REF_STORE_ODB );strbuf_release (&submodule_sb);if (refs)
refs/files-backend.c +54 -32
253 lines not on this page · raw message
refs/refs-internal.h +8 -1
@@ -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);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 16/24] files-backend: replace submodule_allowed check in files_downcast()
Quoted 8 lines · Nguyễn Thái Ngọc Duy
files-backend.cis 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 (*).
I'm surprised that you have implemented a "read" flag. Do you expect ever to support ref-stores that are unreadable? In other words, couldn't "read" just be assumed for any ref store?
Quoted 24 lines
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 takeREF_STORE_ODBflag out. At least t3404 would fail. The "have access to odb" in submodule is a bit hacky since we don't know from he whetheradd_submodule_odb()has been called.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.c | 15 ++++++--- refs/files-backend.c | 86 +++++++++++++++++++++++++++++++++------------------- refs/refs-internal.h | 9 +++++- 3 files changed, 73 insertions(+), 37 deletions(-)refs.c +0
-0@@ -1821,10 +1829,14 @@ static enum peel_status peel_entry(struct ref_entry *entry, int repeel) static int files_peel_ref(struct ref_store *ref_store,
refs.c static enum peel_status peel_entry(struct ref_entry *entry, int repeel) · line 1838
Quoted 10 lines
refs.c +4
-1const 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" );
Instead of this call, couldn't you add REF_STORE_MAIN to the flags passed to files_downcase()?
refs.c static enum peel_status peel_entry(struct ref_entry *entry, int repeel) · line 1842
Quoted 5 lines
refs.c +1
-0+if (current_ref_iter && current_ref_iter->refname == refname) {struct object_id peeled;
Michael
PATCH v5 17/24 refs: rename get_ref_store() to get_submodule_ref_store() and make it public
In reply to Nguyễn Thái Ngọc DuyThis 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.
--- refs.c | 12 ++++++++---- refs.h | 11 +++++++++++ refs/refs-internal.h | 12 ------------ 3 files changed, 19 insertions(+), 16 deletions(-)
refs.c +8 -4
@@ -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)
@@ -1468,13 +1468,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 (); }
refs.h +11 -0
@@ -561,5 +561,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 */
refs/refs-internal.h +0 -12
@@ -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,
Signature · 1 line
2.11.0.157.gd943d85
PATCH v5 18/24 refs: add new ref-store api
In reply to Nguyễn Thái Ngọc DuyThis 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.
--- refs.c | 235 +++++++++++++++++++++++++++++++++++++-------------- refs.h | 71 ++++++++++++++++ refs/files-backend.c | 13 +-- refs/refs-internal.h | 31 +------ 4 files changed, 253 insertions(+), 97 deletions(-)
refs.c +172 -63
@@ -185,13 +185,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 +293,52 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_lifor_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 +1145,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 +1196,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 +1210,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 +1242,23 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsigif (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 +1266,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 +1371,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 +1401,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 ;
@@ -1511,27 +1559,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,
@@ -1542,19 +1605,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);
@@ -1562,43 +1623,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,
@@ -1608,11 +1710,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,
@@ -1623,16 +1724,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); +}
refs.h +71 -0
158 lines not on this page · raw message
refs/files-backend.c +7 -6
@@ -1320,7 +1320,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)) {
@@ -1629,7 +1629,8 @@ static int lock_raw_ref(struct files_ref_store *refs,* 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
@@ -2671,7 +2672,7 @@ static int files_rename_ref(struct ref_store *ref_store,if (flag &REF_ISSYMREF )return error ("refname %s is a symbolic ref, renaming it is not supported" , oldrefname); -if (!rename_ref_available (oldrefname, newrefname)) +if (!refs_rename_ref_available (&refs->base, oldrefname, newrefname))return 1 ;files_reflog_path (refs, &sb_oldref, oldrefname);
@@ -4055,9 +4056,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; }
refs/refs-internal.h +3 -28
@@ -112,28 +112,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, * because reflog file is one line per entry.
@@ -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 */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v5 19/24 refs: new transaction related ref-store api
In reply to Nguyễn Thái Ngọc DuyThe transaction struct now takes a ref store at creation and will operate on that ref store alone.
--- refs.c | 54 ++++++++++++++++++++++++++++++++++++++++------------ refs.h | 8 ++++++++ refs/refs-internal.h | 1 + 3 files changed, 51 insertions(+), 12 deletions(-)
refs.c +42 -12
@@ -618,16 +618,19 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1return 0 ; } -int delete_ref (const char *refname,const unsigned char *old_sha1, -unsigned int flags) +int refs_delete_ref (struct ref_store *refs,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, NULL, &err) ||
@@ -642,6 +645,13 @@ int delete_ref(const char *refname, const unsigned char *old_sha1,return 0 ; } +int delete_ref (const char *refname,const unsigned char *old_sha1, +unsigned int flags) +{ +return refs_delete_ref (get_main_ref_store (), refname, + old_sha1, flags); +} +int copy_reflog_msg (char *buf,const char *msg) {char *cp = buf;
@@ -801,11 +811,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)
@@ -922,18 +941,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) ||
@@ -964,6 +985,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;
@@ -1600,7 +1630,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); }
@@ -1719,7 +1749,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); }
refs.h +8 -0
@@ -330,6 +330,9 @@ 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 *refname, +const unsigned char *old_sha1, +unsigned int flags);int delete_ref (const char *refname,const unsigned char *old_sha1,unsigned int flags);
@@ -414,6 +417,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);/*
@@ -548,6 +553,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);
refs/refs-internal.h +1 -0
@@ -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;
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 19/24] refs: new transaction related ref-store api
Quoted 20 lines · Nguyễn Thái Ngọc Duy
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 <[email protected]>--- refs.c | 54 ++++++++++++++++++++++++++++++++++++++++------------ refs.h | 8 ++++++++ refs/refs-internal.h | 1 + 3 files changed, 51 insertions(+), 12 deletions(-)refs.c +0
-2@@ -618,16 +618,19 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1return 0 ; } -int delete_ref (const char *refname,const unsigned char *old_sha1, -unsigned int flags)
refs.c static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1 · line 629
Quoted 10 lines
refs.c +5
-1+int refs_delete_ref (struct ref_store *refs,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 ());
Hmmm, I would have expected this to be checked via (refs.flags & REF_STORE_MAIN). I guess this is temporary; once we have compound ref stores either version will need to be changed again. So I don't see a strong argument for one vs. the other.
It might be more natural to make delete_pseudoref() take a refs argument and do the check internally.
(Same comments below where write_pseudoref() is called.)
Michael
Quoted 150 lines
refs.c +37
-9return 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, NULL, &err) ||@@ -642,6 +645,13 @@ int delete_ref(const char *refname, const unsigned char *old_sha1,return 0 ; } +int delete_ref (const char *refname,const unsigned char *old_sha1, +unsigned int flags) +{ +return refs_delete_ref (get_main_ref_store (), refname, + old_sha1, flags); +} +int copy_reflog_msg (char *buf,const char *msg) {char *cp = buf;@@ -801,11 +811,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)@@ -922,18 +941,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) ||@@ -964,6 +985,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;@@ -1600,7 +1630,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); }@@ -1719,7 +1749,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); }refs.h +8
-0@@ -330,6 +330,9 @@ 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 *refname, +const unsigned char *old_sha1, +unsigned int flags);int delete_ref (const char *refname,const unsigned char *old_sha1,unsigned int flags);@@ -414,6 +417,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);/* @@ -548,6 +553,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);refs/refs-internal.h +1
-0@@ -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;
PATCH v5 20/24 files-backend: avoid ref api targetting main ref store
In reply to Nguyễn Thái Ngọc DuyA small step towards making files-backend works as a non-main ref store using the newly added store-aware API.
For the record, join and nm on refs.o and files-backend.o tell me that files-backend no longer uses functions that defaults to get_main_ref_store().
I'm not yet comfortable at the idea of removing files_assert_main_repository() (or converting REF_STORE_MAIN to REF_STORE_WRITE). More staring and testing is required before that can happen. Well, except peel_ref(). I'm pretty sure that function is safe.
--- refs/files-backend.c | 85 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 36 deletions(-)
refs/files-backend.c +49 -36
@@ -1836,8 +1836,6 @@ static int files_peel_ref(struct ref_store *ref_store,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;
@@ -1847,7 +1845,8 @@ static int files_peel_ref(struct ref_store *ref_store,return 0 ; } -if (read_ref_full (refname,RESOLVE_REF_READING , base, &flag)) +if (refs_read_ref_full (ref_store, refname, +RESOLVE_REF_READING , base, &flag))return -1 ;/*
@@ -2017,15 +2016,15 @@ static struct ref_iterator *files_ref_iterator_begin(* on success. On error, write an error message to err, set errno, and * return a negative value. */ -static int verify_lock (struct ref_lock *lock, +static int verify_lock (struct ref_store *ref_store,struct ref_lock *lock,const unsigned char *old_sha1,int mustexist,struct strbuf *err) {assert (err); -if (read_ref_full (lock->ref_name, - mustexist ?RESOLVE_REF_READING :0 , - lock->old_oid.hash,NULL )) { +if (refs_read_ref_full (ref_store, lock->ref_name, + mustexist ?RESOLVE_REF_READING :0 , + lock->old_oid.hash,NULL )) {if (old_sha1) {int save_errno = errno;strbuf_addf (err,"can't verify ref '%s'" , lock->ref_name);
@@ -2094,8 +2093,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, resolve_flags |=RESOLVE_REF_ALLOW_BAD_NAME ;files_refname_path (refs, &ref_file, refname); - resolved = !!resolve_ref_unsafe (refname, resolve_flags, - lock->old_oid.hash, type); + resolved = !!refs_resolve_ref_unsafe (&refs->base, + refname, resolve_flags, + lock->old_oid.hash, type);if (!resolved && errno ==EISDIR ) {/* * we are trying to lock foo but we used to
@@ -2112,8 +2112,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, refname); goto error_return; } - resolved = !!resolve_ref_unsafe (refname, resolve_flags, - lock->old_oid.hash, type); + resolved = !!refs_resolve_ref_unsafe (&refs->base, + refname, resolve_flags, + lock->old_oid.hash, type); }if (!resolved) { last_errno = errno;
@@ -2151,7 +2152,7 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, goto error_return; } -if (verify_lock (lock, old_sha1, mustexist, err)) { +if (verify_lock (&refs->base, lock, old_sha1, mustexist, err)) { last_errno = errno; goto error_return; }
@@ -2406,7 +2407,7 @@ static void try_remove_empty_parents(struct files_ref_store *refs, }/* make sure nobody touched the ref, and unlink */ -static void prune_ref (struct ref_to_prune *r) +static void prune_ref (struct files_ref_store *refs,struct ref_to_prune *r) {struct ref_transaction *transaction;struct strbuf err =STRBUF_INIT ;
@@ -2414,7 +2415,7 @@ static void prune_ref(struct ref_to_prune *r)if (check_refname_format (r->name,0 ))return ; - transaction =ref_transaction_begin (&err); + transaction =ref_store_transaction_begin (&refs->base, &err); if (!transaction || ref_transaction_delete(transaction, r->name, r->sha1, REF_ISPRUNING | REF_NODEREF, NULL, &err) ||
@@ -2428,10 +2429,10 @@ static void prune_ref(struct ref_to_prune *r)strbuf_release (&err); } -static void prune_refs (struct ref_to_prune *r) +static void prune_refs (struct files_ref_store *refs,struct ref_to_prune *r) {while (r) { -prune_ref (r); +prune_ref (refs, r); r = r->next; } }
@@ -2455,7 +2456,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)if (commit_packed_refs (refs))die_errno ("unable to overwrite old ref-pack file" ); -prune_refs (cbdata.ref_to_prune); +prune_refs (refs, cbdata.ref_to_prune);return 0 ; }
@@ -2547,7 +2548,7 @@ static int files_delete_refs(struct ref_store *ref_store,for (i =0 ; i < refnames->nr; i++) {const char *refname = refnames->items[i].string; -if (delete_ref (refname,NULL , flags)) +if (refs_delete_ref (&refs->base, refname,NULL , flags)) result |=error (_ ("could not remove reference %s" ), refname); }
@@ -2665,8 +2666,9 @@ static int files_rename_ref(struct ref_store *ref_store,if (log &&S_ISLNK (loginfo.st_mode))return error ("reflog for %s is a symlink" , oldrefname); -if (!resolve_ref_unsafe (oldrefname,RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , - orig_sha1, &flag)) +if (!refs_resolve_ref_unsafe (&refs->base, oldrefname, +RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , + orig_sha1, &flag))return error ("refname %s not found" , oldrefname);if (flag &REF_ISSYMREF )
@@ -2684,7 +2686,7 @@ static int files_rename_ref(struct ref_store *ref_store,return error ("unable to move logfile logs/%s to logs/" TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); -if (delete_ref (oldrefname, orig_sha1,REF_NODEREF )) { +if (refs_delete_ref (&refs->base, oldrefname, orig_sha1,REF_NODEREF )) {error ("unable to delete old %s" , oldrefname); goto rollback; }
@@ -2696,9 +2698,10 @@ static int files_rename_ref(struct ref_store *ref_store,* the safety anyway; we want to delete the reference whatever * its current value. */ -if (!read_ref_full (newrefname,RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , - sha1,NULL ) && -delete_ref (newrefname,NULL ,REF_NODEREF )) { +if (!refs_read_ref_full (&refs->base, newrefname, +RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , + sha1,NULL ) && +refs_delete_ref (&refs->base, newrefname,NULL ,REF_NODEREF )) {if (errno ==EISDIR ) {struct strbuf path =STRBUF_INIT ;int result;
@@ -3054,8 +3057,9 @@ static int commit_ref_update(struct files_ref_store *refs,int head_flag;const char *head_ref; - head_ref =resolve_ref_unsafe ("HEAD" ,RESOLVE_REF_READING , - head_sha1, &head_flag); + head_ref =refs_resolve_ref_unsafe (&refs->base,"HEAD" , +RESOLVE_REF_READING , + head_sha1, &head_flag);if (head_ref && (head_flag &REF_ISSYMREF ) && !strcmp (head_ref, lock->ref_name)) {struct strbuf log_err =STRBUF_INIT ;
@@ -3099,7 +3103,9 @@ static void update_symref_reflog(struct files_ref_store *refs, {struct strbuf err =STRBUF_INIT ;unsigned char new_sha1[20 ]; -if (logmsg && !read_ref (target, new_sha1) && +if (logmsg && + !refs_read_ref_full (&refs->base, target, +RESOLVE_REF_READING , new_sha1,NULL ) &&files_log_ref_write (refs, refname, lock->old_oid.hash, new_sha1, logmsg,0 , &err)) {error ("%s" , err.buf);
@@ -3403,6 +3409,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,struct files_reflog_iterator {struct ref_iterator base; +struct ref_store *ref_store;struct dir_iterator *dir_iterator;struct object_id oid; };
@@ -3424,8 +3431,9 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)if (ends_with (diter->basename,".lock" ))continue ; -if (read_ref_full (diter->relative_path,0 , - iter->oid.hash, &flags)) { +if (refs_read_ref_full (iter->ref_store, + diter->relative_path,0 , + iter->oid.hash, &flags)) {error ("bad ref for %s" , diter->path.buf);continue ; }
@@ -3479,6 +3487,7 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_stbase_ref_iterator_init (ref_iterator, &files_reflog_iterator_vtable);files_reflog_path (refs, &sb,NULL ); iter->dir_iterator =dir_iterator_begin (sb.buf); + iter->ref_store = ref_store;strbuf_release (&sb);return ref_iterator; }
@@ -3718,8 +3727,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,* the transaction, so we have to read it here * to record and possibly check old_sha1: */ -if (read_ref_full (referent.buf,0 , - lock->old_oid.hash,NULL )) { +if (refs_read_ref_full (&refs->base, + referent.buf,0 , + lock->old_oid.hash,NULL )) {if (update->flags &REF_HAVE_OLD ) { strbuf_addf(err, "cannot lock ref '%s': " "error reading reference",
@@ -3873,8 +3883,10 @@ static int files_transaction_commit(struct ref_store *ref_store,* head_ref within the transaction, then split_head_update() * arranges for the reflog of HEAD to be updated, too. */ - head_ref =resolve_refdup ("HEAD" ,RESOLVE_REF_NO_RECURSE , - head_oid.hash, &head_type); + head_ref = (char *)refs_resolve_ref_unsafe (ref_store,"HEAD" , +RESOLVE_REF_NO_RECURSE , + head_oid.hash, &head_type); + head_ref =xstrdup_or_null (head_ref);if (head_ref && !(head_type &REF_ISSYMREF )) {free (head_ref);
@@ -4047,7 +4059,8 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,* so here we really only check that none of the references * that we are creating already exists. */ -if (for_each_rawref (ref_present, &affected_refnames)) +if (refs_for_each_rawref (&refs->base, ref_present, + &affected_refnames))die ("BUG: initial ref transaction called with existing refs" );for (i =0 ; i < transaction->nr; i++) {
@@ -4166,7 +4179,7 @@ static int files_reflog_expire(struct ref_store *ref_store,strbuf_release (&err);return -1 ; } -if (!reflog_exists (refname)) { +if (!refs_reflog_exists (ref_store, refname)) {unlock_ref (lock);return 0 ; }
@@ -4197,7 +4210,7 @@ static int files_reflog_expire(struct ref_store *ref_store, } (*prepare_fn)(refname, sha1, cb.policy_cb); -for_each_reflog_ent (refname, expire_reflog_ent, &cb); +refs_for_each_reflog_ent (ref_store, refname, expire_reflog_ent, &cb); (*cleanup_fn)(cb.policy_cb);if (!(flags &EXPIRE_REFLOGS_DRY_RUN )) {
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 20/24] files-backend: avoid ref api targetting main ref store
Quoted 6 lines · Nguyễn Thái Ngọc Duy
A small step towards making files-backend works as a non-main ref store using the newly added store-aware API.
For the record,
joinandnmon refs.o and files-backend.o tell me that files-backend no longer uses functions that defaults toget_main_ref_store().
Nice!
Quoted 16 lines
I'm not yet comfortable at the idea of removing
files_assert_main_repository()(or convertingREF_STORE_MAINtoREF_STORE_WRITE). More staring and testing is required before that can happen. Well, exceptpeel_ref(). I'm pretty sure that function is safe.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 85 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 36 deletions(-)refs/files-backend.c +0
-0
refs/files-backend.c static int files_transaction_commit(struct ref_store *ref_store, · line 3889
Quoted 9 lines
refs/files-backend.c +4
-2@@ -3873,8 +3883,10 @@ static int files_transaction_commit(struct ref_store *ref_store,* head_ref within the transaction, then split_head_update() * arranges for the reflog of HEAD to be updated, too. */ - head_ref =resolve_refdup ("HEAD" ,RESOLVE_REF_NO_RECURSE , - head_oid.hash, &head_type); + head_ref = (char *)refs_resolve_ref_unsafe (ref_store,"HEAD" , +RESOLVE_REF_NO_RECURSE , + head_oid.hash, &head_type); + head_ref =xstrdup_or_null (head_ref);
If you combine the last two statements, you can avoid the ugly cast.
Quoted 1 line
[...]
Michael
PATCH v5 21/24 refs: delete pack_refs() in favor of refs_pack_refs()
In reply to Nguyễn Thái Ngọc DuyIt only has one caller, not worth keeping just for convenience.
--- builtin/pack-refs.c | 2 +- refs.c | 5 ----- refs.h | 1 - 3 files changed, 1 insertion(+), 7 deletions(-)
builtin/pack-refs.c +1 -1
@@ -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); }
refs.c +0 -5
@@ -1594,11 +1594,6 @@ int refs_pack_refs(struct ref_store *refs, unsigned int flags)return refs->be->pack_refs (refs, flags); } -int pack_refs (unsigned int flags) -{ -return refs_pack_refs (get_main_ref_store (), flags); -} -int refs_peel_ref (struct ref_store *refs,const char *refname,unsigned char *sha1) {
refs.h +0 -1
@@ -294,7 +294,6 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt,* 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);/* * Flags controlling ref_transaction_update(), ref_transaction_create(), etc.
Signature · 1 line
2.11.0.157.gd943d85
PATCH v5 22/24 t/helper: add test-ref-store to test ref-store functions
In reply to Nguyễn Thái Ngọc Duy--- Makefile | 1 + t/helper/.gitignore | 1 + t/helper/test-ref-store.c (new) | 274 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+) create mode 100644 t/helper/test-ref-store.c
Makefile +1 -0
@@ -624,6 +624,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
t/helper/.gitignore +1 -0
@@ -19,6 +19,7 @@ /test-path-utils /test-prio-queue /test-read-cache +/test-ref-store /test-regex /test-revision-walking /test-run-command
t/helper/test-ref-store.c new file +274 -0
274 lines not on this page · raw message
Signature · 1 line
2.11.0.157.gd943d85
PATCH v5 23/24 t1405: some basic tests on main ref store
In reply to Nguyễn Thái Ngọc Duy--- t/t1405-main-ref-store.sh (new +x) | 123 +++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100755 t/t1405-main-ref-store.sh
t/t1405-main-ref-store.sh new file +123 -0
@@ -0,0 +1,123 @@ +#!/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 '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 | cut -c 42- >actual && + cat >expected <<-\EOF && + refs/heads/master 0x0 + refs/heads/new-master 0x0 + HEAD 0x1 + 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 refs/heads/foo $SHA1 0 && + test_must_fail git rev-parse refs/heads/foo -- +' + +test_done
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 23/24] t1405: some basic tests on main ref store
Quoted 13 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- t/t1405-main-ref-store.sh (new +x) | 123 +++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100755 t/t1405-main-ref-store.sht/t1405-main-ref-store.sh new file +1
-0@@ -0,0 +1,123 @@ +#!/bin/sh
t/t1405-main-ref-store.sh line 11
Quoted 10 lines
t/t1405-main-ref-store.sh new file +10
-0+ +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` &&
I think we prefer $() to ``. (Same throughout this file and also t1406 in the next commit.)
It's notable that these tests grep around the filesystem, so they won't be applicable to future refs backends. Of course, "pack-refs" is intrinsically only applicable to the files backend, so for this test it's not surprising. But some tests could conceivably be written in a generic way, so that they should pass for any refs backend.
Just food for thought; no need to change anything now.
t/t1405-main-ref-store.sh line 14
Quoted 3 lines
t/t1405-main-ref-store.sh new file +3
-0+ test "$N" != 0 && + $RUN pack-refs 3 && + N=`find .git/refs -type f | wc -l`
Didn't you mean to test the final $N?
Quoted 21 lines
t/t1405-main-ref-store.sh new file +21
-0+' + +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 -- &&
t/t1405-main-ref-store.sh line 45
Quoted 10 lines
t/t1405-main-ref-store.sh new file +10
-0+ 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 +'
Isn't HEAD set to refs/heads/master prior to this test? If so, then I think it should become detached when you rename refs/heads/master. Or maybe it should be changed to point at refs/heads/new-master, I can't remember. In either case, it might be useful for the test to check that the behavior matches the status quo, so we notice if the behavior ever changes inadvertently.
Quoted 40 lines
t/t1405-main-ref-store.sh new file +40
-0+ +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 '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 | cut -c 42- >actual && + cat >expected <<-\EOF && + refs/heads/master 0x0 + refs/heads/new-master 0x0 + HEAD 0x1 + 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 &&
t/t1405-main-ref-store.sh line 95
Quoted 10 lines
t/t1405-main-ref-store.sh new file +10
-0+ 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
Maybe also test the final state using reflog-exists to make sure that function can also return false?
Quoted 16 lines
t/t1405-main-ref-store.sh new file +16
-0+' + +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 &&
t/t1405-main-ref-store.sh line 121
Quoted 10 lines
t/t1405-main-ref-store.sh new file +10
-0+ 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 refs/heads/foo $SHA1 0 && + test_must_fail git rev-parse refs/heads/foo -- +'
The last two tests have the same name.
You might also want to test these functions when the old oid is incorrect or when the reference is missing.
t/t1405-main-ref-store.sh line 123
Quoted 1 line
t/t1405-main-ref-store.sh new file +1
-0+test_done
Thanks for all the new tests!
Michael
Re: [PATCH v5 23/24] t1405: some basic tests on main ref store
Quoted 7 lines · Michael Haggerty
It's notable that these tests grep around the filesystem, so they won't be applicable to future refs backends. Of course, "pack-refs" is intrinsically only applicable to the files backend, so for this test it's not surprising. But some tests could conceivably be written in a generic way, so that they should pass for any refs backend.
Just food for thought; no need to change anything now.
I'm a bit on the fence about this. On one hand I think there is room to backend-specific tests (and this one is more about files backend, we just don't have any direct way of getting the backend except through get_main_ref_store()).
On the other hand, I can see a need for verifying refs behavior across backends. Submodule backend is unfortunately a bad fit (and probably worktree backend too in early phase) because it cannot fully replace files backend. lmdb does. I guess these tests will have some more restructuring when lmdb joins the party.
I imagine we could have something like "ref_expect_success [backend,[backend..]] <title> <body>", which makes it easier to exercise a new backend with the same test, or we could add backend-specific tests as well. Not sure how to do it yet (the devil will be in the body, I think, like dealing with "git -C sub" for submodules). Probably won't do in this series anyway.
Quoted 8 lines
t/t1405-main-ref-store.sh line 45
Quoted 7 lines
t/t1405-main-ref-store.sh new file +7
-0+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 +'
Quoted 6 lines
Isn't HEAD set to
refs/heads/masterprior to this test? If so, then I think it should become detached when you renamerefs/heads/master. Or maybe it should be changed to point atrefs/heads/new-master, I can't remember. In either case, it might be useful for the test to check that the behavior matches the status quo, so we notice if the behavior ever changes inadvertently.
You had me worried a bit there, that I broke something. Yes we rename HEAD too. No it's not the backend's job. It's done separately by builtin/branch.c. Probably a good thing because I don't the backend should know about HEAD's special semantics. Front-end might though.
Quoted 11 lines
t/t1405-main-ref-store.sh line 121
Quoted 6 lines
t/t1405-main-ref-store.sh new file +6
-0+test_expect_success 'delete_ref(refs/heads/foo)' ' + SHA1=`git rev-parse foo` && + git checkout --detach && + $RUN delete-ref refs/heads/foo $SHA1 0 && + test_must_fail git rev-parse refs/heads/foo -- +'The last two tests have the same name.
You might also want to test these functions when the old oid is incorrect or when the reference is missing.
I will. But you probably noticed that I didn't cover refs behavior extensively. I don't know this area well enough to write a conformant test suite. But I think that's ok. We have something to start improving now.
Signature · 1 line
Duy
PATCH v5 24/24 t1406: new tests for submodule ref store
In reply to Nguyễn Thái Ngọc Duy--- t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 t/t1406-submodule-ref-store.sh
t/t1406-submodule-ref-store.sh new file +95 -0
@@ -0,0 +1,95 @@ +#!/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 '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 | cut -c 42- >actual && + cat >expected <<-\EOF && + refs/heads/master 0x0 + refs/heads/new-master 0x0 + HEAD 0x1 + 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
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 24/24] t1406: new tests for submodule ref store
t/t1406-submodule-ref-store.sh
Quoted 12 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 t/t1406-submodule-ref-store.sht/t1406-submodule-ref-store.sh new file +0
-0
I haven't actually read this far in the patch series, but I noticed that a test in this file fails:
t1406-submodule-ref-store.sh (Wstat: 256 Tests: 15
Failed: 1)
Failed test: 10
Non-zero exit status: 1
I didn't have time to look into it more; let me know if you can't reproduce it.
Michael
Re: [PATCH v5 24/24] t1406: new tests for submodule ref store
Quoted 18 lines · Michael Haggerty
t/t1406-submodule-ref-store.sh
Quoted 12 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 t/t1406-submodule-ref-store.sht/t1406-submodule-ref-store.sh new file +0
-0I haven't actually read this far in the patch series, but I noticed that a test in this file fails:
Quoted 7 lines
t1406-submodule-ref-store.sh(Wstat: 256 Tests: 15
Failed: 1)
Failed test: 10
Non-zero exit status: 1I didn't have time to look into it more; let me know if you can't reproduce it.
Fantastic. No I couldn't reproduce it, even --valgrind did not complain. First step maybe just pushing your branch somewhere so I can try out if you're applying the patches via mail (maybe there's some changes in the base that affect this). .Otherwise /t1406-* -v -i might be enough clue for me to dig in, I hope.
Signature · 1 line
Duy
Re: [PATCH v5 24/24] t1406: new tests for submodule ref store
Quoted 24 lines · Duy Nguyen
Quoted 23 lines · Michael Haggerty
t/t1406-submodule-ref-store.sh
Quoted 12 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 t/t1406-submodule-ref-store.sht/t1406-submodule-ref-store.sh new file +0
-0I haven't actually read this far in the patch series, but I noticed that a test in this file fails:
t1406-submodule-ref-store.sh(Wstat: 256 Tests: 15
Failed: 1)
Failed test: 10
Non-zero exit status: 1
Quoted 8 lines
Quoted 2 lines
I didn't have time to look into it more; let me know if you can't reproduce it.
Fantastic. No I couldn't reproduce it, even --valgrind did not complain. First step maybe just pushing your branch somewhere so I can try out if you're applying the patches via mail (maybe there's some changes in the base that affect this). .Otherwise /t1406-* -v -i might be enough clue for me to dig in, I hope.
I'm testing c5302654930070135eec9bc1b4ef99b14e0f28ee from Junio's GitHub fork.
Unfortunately, the test succeeds (every time) when I run just t1406-* or with -d or -i options, but fails (every time) when run as part of the whole test suite, so it's a bit tricky to dig deeper.
By trial and error, I found that the test succeeds if I comment out the "for_each_reflog()" test. By having that test write its results to /tmp where they won't be deleted, I found that the problem is that the actual results are not sorted correctly:
refs/heads/new-master 0x0
refs/heads/master 0x0
HEAD 0x1I don't know why it's so Heisenbergish.
Michael
Re: [PATCH v5 24/24] t1406: new tests for submodule ref store
Quoted 10 lines · Michael Haggerty
By trial and error, I found that the test succeeds if I comment out the "
for_each_reflog()" test. By having that test write its results to/tmpwhere they won't be deleted, I found that the problem is that theactualresults are not sorted correctly:refs/heads/new-master 0x0 refs/heads/master 0x0 HEAD 0x1I don't know why it's so Heisenbergish.
It happens consistently on my other laptop. And yes it looks like sorting order problem, probably because of the underlying file system. I did wonder about that at some point but never asked. We do not guarantee any sorting order in the for-each api, do we?
Signature · 1 line
Duy
Re: [PATCH v5 24/24] t1406: new tests for submodule ref store
Quoted 10 lines · Duy Nguyen
Quoted 9 lines · Michael Haggerty
By trial and error, I found that the test succeeds if I comment out the "
for_each_reflog()" test. By having that test write its results to/tmpwhere they won't be deleted, I found that the problem is that theactualresults are not sorted correctly:refs/heads/new-master 0x0 refs/heads/master 0x0 HEAD 0x1
Quoted 6 lines
Quoted 1 line
I don't know why it's so Heisenbergish.
It happens consistently on my other laptop. And yes it looks like sorting order problem, probably because of the underlying file system. I did wonder about that at some point but never asked. We do not guarantee any sorting order in the for-each api, do we?
The for-each-ref iteration is defined to be sorted by refname, but it's true that the for-each-reflog order is undefined. So it was wrong for me to say that the results are not sorted correctly. The problem is that the actual output is ordered differently than the "expected" results, which the test incorrectly considers to be an error.
Michael
Re: [PATCH v5 24/24] t1406: new tests for submodule ref store
Quoted 2 lines · Michael Haggerty
The for-each-ref iteration is defined to be sorted by refname, but it's true that the for-each-reflog order is undefined.
Thanks. I'm going to add a few lines about this near for_each_ref and for_each_reflog() then, assuming that this is the desired behavior, not a bug. (Another patch, because I'm not happy until it gets 30+)
Signature · 1 line
Duy
Re: [PATCH v5 24/24] t1406: new tests for submodule ref store
In reply to Nguyễn Thái Ngọc DuyQuoted 5 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 t/t1406-submodule-ref-store.sh
I wonder if you could reduce some of the repetition between this test file and t1405, at least for the functions that should work for both the main repository and for submodules? For example, if you were to define
GIT='git'
in one case and
GIT='git -C sub'
in the other, then maybe some of the setup code could be made to look alike? Then the division could be one test file for the functions that work for both main and submodules, and a second for the functions that only work for main. Just a thought...
Michael
Quoted 15 lines · Nguyễn Thái Ngọc Duy
v5 goes a bit longer than v4, basically:
-
files_path()is broken down into three smaller functions, files_{packed_refs,reflog,refname}_path().- most of store-based api is added because..
-
test-ref-store.cis added with t1405 and t1406 for some basic tests I'm not aimimg for complete ref store coverage. But we can continue to improve from there.-
refs_store_init()now takes a "permission" flag, likeopen(). Operations are allowed or forbidden based on this flag. Thesubmodule_allowedflag is killed.files_assert_main.. remains.
Quoted 6 lines
- get_*_ref_store() remain public api because it's used by
test-ref-store.candpack-refs.c.-
files-backend.cshould now make no function calls that implicitly target the main store. But this will have to be tested more to be sure. I'm tempted to add a tracing backend just for this purpose.
OK.
Quoted 4 lines
Junio, if you take this on 'pu', you'll have to kick my other two series out (they should not even compile). I'm not resending them until I get a "looks mostly ok" from Michael. No point in updating them when this series keeps moving.
Thanks for a note.
Quoted 24 lines · Junio C Hamano
Quoted 15 lines · Nguyễn Thái Ngọc Duy
v5 goes a bit longer than v4, basically:
-
files_path()is broken down into three smaller functions, files_{packed_refs,reflog,refname}_path().- most of store-based api is added because..
-
test-ref-store.cis added with t1405 and t1406 for some basic tests I'm not aimimg for complete ref store coverage. But we can continue to improve from there.-
refs_store_init()now takes a "permission" flag, likeopen(). Operations are allowed or forbidden based on this flag. Thesubmodule_allowedflag is killed.files_assert_main.. remains.Quoted 6 lines
- get_*_ref_store() remain public api because it's used by
test-ref-store.candpack-refs.c.-
files-backend.cshould now make no function calls that implicitly target the main store. But this will have to be tested more to be sure. I'm tempted to add a tracing backend just for this purpose.
Quoted 8 lines
OK.
Quoted 4 lines
Junio, if you take this on 'pu', you'll have to kick my other two series out (they should not even compile). I'm not resending them until I get a "looks mostly ok" from Michael. No point in updating them when this series keeps moving.
Thanks for a note.
As this round seems to have added conflicts with another topic that is already in flight that the previous round did not conflict with, I'll eject all three for now until this one solidifies a bit more.
Quoted 1 line · Nguyễn Thái Ngọc Duy
v5 goes a bit longer than v4, basically:
I've read through patch 14/24 so far, and they all look good except for the mostly superficial comments that I have sent so far. I like the way this is heading!
I'll try to continue tomorrow.
Michael
Quoted 10 lines · Michael Haggerty
Quoted 1 line · Nguyễn Thái Ngọc Duy
v5 goes a bit longer than v4, basically:
I've read through patch 14/24 so far, and they all look good except for the mostly superficial comments that I have sent so far. I like the way this is heading!
I'll try to continue tomorrow.
Michael
Thanks.
Quoted 1 line · Nguyễn Thái Ngọc Duy
v5 goes a bit longer than v4, basically:
I've reviewed all of the patches and left a bunch of comments, mostly superficial. I'm very happy about the way it's going, and especially want to say how much I appreciate that you've done so much legwork and added so many tests.
Michael
v6 cover Remove submodule from files-backend.c
In reply to Nguyễn Thái Ngọc Duyv6 should address all Micheal's comments in v5, except a few that I replied back. The interdiff looks a bit messy due to some new refactoring (05/27) in files_rename_ref(), but it makes the final output easier to read.
03/27 and 27/27 are also new patches that are not really necessary but nice to have.
The series is rebased on latest master and does not depend on any other topics, since they all have graduated to master.
path.c +0 -1
@@ -471,7 +471,6 @@ 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 -1static int do_submodule_path (struct strbuf *buf,const char *path,const char *fmt,va_list args) {
refs.c +26 -16
66 lines not on this page · raw message
refs.h +6 -3
@@ -3,7 +3,6 @@struct object_id ;struct ref_store ; -struct ref_transaction ;struct strbuf ;struct string_list ;
@@ -66,6 +65,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,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);
@@ -183,6 +185,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);* `ref_transaction_commit` is called. So `ref_transaction_verify` * won't report a verification failure until the commit is attempted. */ +struct ref_transaction ;/* * Bit values set in the flags argument passed to each_ref_fn() and
@@ -227,7 +230,7 @@ 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);
@@ -367,7 +370,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 +* 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);
refs/files-backend.c +35 -41
136 lines not on this page · raw message
submodule.c +5 -0
@@ -1515,6 +1515,11 @@ void absorb_git_dir_into_superproject(const char *prefix, } } +/* +* 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) {const struct submodule *sub;
t/helper/test-ref-store.c +2 -1
@@ -195,6 +195,7 @@ static int cmd_reflog_expire(struct ref_store *refs, const char **argv)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" );
@@ -203,7 +204,7 @@ static int cmd_delete_ref(struct ref_store *refs, const char **argv)if (get_sha1_hex (sha1_buf, old_sha1))die ("not sha-1" ); -return refs_delete_ref (refs, refname, old_sha1, flags); +return refs_delete_ref (refs, msg, refname, old_sha1, flags); }static int cmd_update_ref (struct ref_store *refs,const char **argv)
t/t1405-main-ref-store.sh +9 -3
@@ -53,6 +53,12 @@ test_expect_success 'for_each_ref(refs/heads/)' ' 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 &&
@@ -65,11 +71,11 @@ test_expect_success 'verify_ref(new-master)' ' ' test_expect_success 'for_each_reflog()' ' - $RUN for-each-reflog | cut -c 42- >actual && + $RUN for-each-reflog | sort | cut -c 42- >actual && cat >expected <<-\EOF && + HEAD 0x1 refs/heads/master 0x0 refs/heads/new-master 0x0 - HEAD 0x1 EOF test_cmp expected actual '
@@ -116,7 +122,7 @@ test_expect_success 'delete_ref(refs/heads/foo)' ' test_expect_success 'delete_ref(refs/heads/foo)' ' SHA1=`git rev-parse foo` && git checkout --detach && - $RUN delete-ref refs/heads/foo $SHA1 0 && + $RUN delete-ref msg refs/heads/foo $SHA1 0 && test_must_fail git rev-parse refs/heads/foo -- '
t/t1406-submodule-ref-store.sh +8 -2
@@ -47,6 +47,12 @@ test_expect_success 'for_each_ref(refs/heads/)' ' 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 &&
@@ -59,11 +65,11 @@ test_expect_success 'verify_ref(new-master)' ' ' test_expect_success 'for_each_reflog()' ' - $RUN for-each-reflog | cut -c 42- >actual && + $RUN for-each-reflog | sort | cut -c 42- >actual && cat >expected <<-\EOF && + HEAD 0x1 refs/heads/master 0x0 refs/heads/new-master 0x0 - HEAD 0x1 EOF test_cmp expected actual '
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 1/27 refs.h: add forward declaration for structs used in this file
--- refs.h | 4 ++++ 1 file changed, 4 insertions(+)
refs.h +4 -0
@@ -1,6 +1,10 @@#ifndef REFS_H #define REFS_H +struct object_id ; +struct strbuf ; +struct string_list ; +/* * Resolve a reference, recursively following symbolic refererences. *
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 2/27 files-backend: make files_log_ref_write() static
In reply to Nguyễn Thái Ngọc DuyCreated in 5f3c3a4e6f (files_log_ref_write: new function - 2015-11-10) but probably never used outside refs-internal.c
--- refs/files-backend.c | 3 +++ refs/refs-internal.h | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-)
refs/files-backend.c +3 -0
@@ -165,6 +165,9 @@ static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, const char *dirname, size_t len, int incomplete);static void add_entry_to_dir (struct ref_dir *dir,struct ref_entry *entry); +static 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);static struct ref_dir *get_ref_dir (struct ref_entry *entry) {
refs/refs-internal.h +0 -4
@@ -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
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v6 02/27] files-backend: make files_log_ref_write() static
Quoted 29 lines · Nguyễn Thái Ngọc Duy
Created in
5f3c3a4e6f(files_log_ref_write: new function - 2015-11-10) but probably never used outsiderefs-internal.cSigned-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 3 +++ refs/refs-internal.h | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-)refs/files-backend.c +3
-0@@ -165,6 +165,9 @@ static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, const char *dirname, size_t len, int incomplete);static void add_entry_to_dir (struct ref_dir *dir,struct ref_entry *entry); +static 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);static struct ref_dir *get_ref_dir (struct ref_entry *entry) {refs/refs-internal.h +0
-0
refs/refs-internal.h struct ref_transaction { · line 233
Quoted 10 lines
refs/refs-internal.h +0
-4@@ -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
You changed the declaration, but the definition still makes the function non-static.
Michael
Re: [PATCH v6 02/27] files-backend: make files_log_ref_write() static
Quoted 32 lines · Michael Haggerty
Quoted 31 lines · Nguyễn Thái Ngọc Duy
Created in
5f3c3a4e6f(files_log_ref_write: new function - 2015-11-10) but probably never used outsiderefs-internal.cSigned-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 3 +++ refs/refs-internal.h | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-)refs/files-backend.c +3
-0@@ -165,6 +165,9 @@ static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, const char *dirname, size_t len, int incomplete);static void add_entry_to_dir (struct ref_dir *dir,struct ref_entry *entry); +static 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);static struct ref_dir *get_ref_dir (struct ref_entry *entry) {refs/refs-internal.h +0
-0@@ -228,10 +228,6 @@ struct ref_transaction {enum ref_transaction_state state; };
Quoted 11 lines
refs/refs-internal.h struct ref_transaction { · line 233
Quoted 8 lines
refs/refs-internal.h +0
-4-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 You changed the declaration, but the definition still makes the function non-static.
Actually, this is a static symbol, since it's 'static-ness' derives from the above forward declaration.
However, as I said in a previous email, this tickles sparse to issue a warning. In addition, simply adding 'static' to the definition (ie simply _don't_ do the forward declaration) is less work! :-D
ATB,
Ramsay Jones
PATCH v6 3/27 files-backend: delete dead code in files_init_db()
In reply to Nguyễn Thái Ngọc Duysafe_create_dir() can do adjust_shared_perm() internally, and init-db has always created 'refs' in shared mode since the beginning, af6e277c5e (git-init-db: initialize shared repositories with --shared - 2005-12-22). So this code looks like extra adjust_shared_perm calls are unnecessary.
And they are. But let's see why there are here in the first place.
This code was added in 6fb5acfd8f (refs: add methods to init refs db - 2016-09-04). From the diff alone this looks like a faithful refactored code from init-db.c. But there is a subtle difference:
Between the safe_create_dir() block and adjust_shared_perm() block in the old init-db.c, we may copy/recreate directories from the repo template. So it makes sense that adjust_shared_perm() is re-executed then to fix potential permission screwups.
After 6fb5acfd8f, refs dirs are created after template is copied. Nobody will change directory permission again. So the extra adjust_shared_perm() is redudant. Delete them.
--- refs/files-backend.c | 4 ---- 1 file changed, 4 deletions(-)
refs/files-backend.c +0 -4
@@ -4110,10 +4110,6 @@ static int files_init_db(struct ref_store *ref_store, struct strbuf *err)*/ safe_create_dir (git_path ("refs/heads" ),1 );safe_create_dir (git_path ("refs/tags" ),1 ); -if (get_shared_repository ()) { -adjust_shared_perm (git_path ("refs/heads" )); -adjust_shared_perm (git_path ("refs/tags" )); - }return 0 ; }
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v6 03/27] files-backend: delete dead code in files_init_db()
Quoted 12 lines · Nguyễn Thái Ngọc Duy
safe_create_dir()can doadjust_shared_perm()internally, and init-db has always created 'refs' in shared mode since the beginning,af6e277c5e(git-init-db: initialize shared repositories with --shared - 2005-12-22). So this code looks like extraadjust_shared_permcalls are unnecessary.And they are. But let's see why there are here in the first place.
This code was added in
6fb5acfd8f(refs: add methods to init refs db - 2016-09-04). From the diff alone this looks like a faithful refactored code frominit-db.c. But there is a subtle difference:
Quoted 8 lines
Between the
safe_create_dir()block andadjust_shared_perm()block in the oldinit-db.c, we may copy/recreate directories from the repo template. So it makes sense thatadjust_shared_perm()is re-executed then to fix potential permission screwups.After
6fb5acfd8f, refs dirs are created after template is copied. Nobody will change directory permission again. So the extraadjust_shared_perm()is redudant. Delete them.
LGTM. Thanks for the careful research.
Michael
PATCH v6 4/27 files-backend: add and use files_packed_refs_path()
In reply to Nguyễn Thái Ngọc DuyKeep repo-related path handling in one place. This will make it easier to add submodule/multiworktree support later.
--- refs/files-backend.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)
refs/files-backend.c +18 -11
@@ -923,6 +923,8 @@ struct files_ref_store {*/ const char *submodule; +char *packed_refs_path; +struct ref_entry *loose;struct packed_ref_cache *packed; };
@@ -985,7 +987,14 @@ static struct ref_store *files_ref_store_create(const char *submodule)base_ref_store_init (ref_store, &refs_be_files); - refs->submodule =xstrdup_or_null (submodule); +if (submodule) { + refs->submodule =xstrdup (submodule); + refs->packed_refs_path =git_pathdup_submodule ( + refs->submodule,"packed-refs" ); +return ref_store; + } + + refs->packed_refs_path =git_pathdup ("packed-refs" );return ref_store; }
@@ -1153,19 +1162,18 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)strbuf_release (&line); } +static const char *files_packed_refs_path (struct files_ref_store *refs) +{ +return refs->packed_refs_path; +} +/* * Get the packed_ref_cache for the specified files_ref_store, * creating it if necessary. */ static struct packed_ref_cache *get_packed_ref_cache (struct files_ref_store *refs) { -char *packed_refs_file; - -if (refs->submodule) - packed_refs_file =git_pathdup_submodule (refs->submodule, -"packed-refs" ); -else - packed_refs_file =git_pathdup ("packed-refs" ); +const char *packed_refs_file =files_packed_refs_path (refs);if (refs->packed && !stat_validity_check (&refs->packed->validity, packed_refs_file))
@@ -1184,7 +1192,6 @@ static struct packed_ref_cache *get_packed_ref_cache(struct files_ref_store *reffclose (f); } } -free (packed_refs_file);return refs->packed; }
@@ -2160,7 +2167,7 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) }if (hold_lock_file_for_update_timeout ( - &packlock,git_path ("packed-refs" ), + &packlock,files_packed_refs_path (refs), flags, timeout_value) <0 )return -1 ;/*
@@ -2426,7 +2433,7 @@ static int repack_without_refs(struct files_ref_store *refs,return 0 ;/* no refname exists in packed refs */ if (lock_packed_refs (refs,0 )) { -unable_to_lock_message (git_path ("packed-refs" ), errno, err); +unable_to_lock_message (files_packed_refs_path (refs), errno, err);return -1 ; } packed =get_packed_refs (refs);
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 5/27 files-backend: make sure files_rename_ref() always reach the end
In reply to Nguyễn Thái Ngọc DuyThis is a no-op patch. It prepares the function so that we can release resources (to be added later in this function) before we return.
--- refs/files-backend.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-)
refs/files-backend.c +28 -14
@@ -2588,23 +2588,34 @@ static int files_rename_ref(struct ref_store *ref_store,struct stat loginfo;int log = !lstat (git_path ("logs/%s" , oldrefname), &loginfo);struct strbuf err =STRBUF_INIT ; +int ret; -if (log &&S_ISLNK (loginfo.st_mode)) -return error ("reflog for %s is a symlink" , oldrefname); +if (log &&S_ISLNK (loginfo.st_mode)) { + ret =error ("reflog for %s is a symlink" , oldrefname); + goto out; + }if (!resolve_ref_unsafe (oldrefname,RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , - orig_sha1, &flag)) -return error ("refname %s not found" , oldrefname); + orig_sha1, &flag)) { + ret =error ("refname %s not found" , oldrefname); + goto out; + } -if (flag &REF_ISSYMREF ) -return error ("refname %s is a symbolic ref, renaming it is not supported" , - oldrefname); -if (!rename_ref_available (oldrefname, newrefname)) -return 1 ; +if (flag &REF_ISSYMREF ) { + ret =error ("refname %s is a symbolic ref, renaming it is not supported" , + oldrefname); + goto out; + } +if (!rename_ref_available (oldrefname, newrefname)) { + ret =1 ; + goto out; + } -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) -return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , - oldrefname,strerror (errno)); +if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) { + ret =error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , + oldrefname,strerror (errno)); + goto out; + }if (delete_ref (logmsg, oldrefname, orig_sha1,REF_NODEREF )) {error ("unable to delete old %s" , oldrefname);
@@ -2660,7 +2671,8 @@ static int files_rename_ref(struct ref_store *ref_store, goto rollback; } -return 0 ; + ret =0 ; + goto out; rollback: lock = lock_ref_sha1_basic(refs, oldrefname, NULL, NULL, NULL,
@@ -2689,7 +2701,9 @@ static int files_rename_ref(struct ref_store *ref_store,error ("unable to restore logfile %s from " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); -return 1 ; + ret =1 ; + out: +return ret; }static int close_ref (struct ref_lock *lock)
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 6/27 files-backend: convert git_path() to strbuf_git_path()
In reply to Nguyễn Thái Ngọc Duygit_path() and friends are going to be killed in files-backend.c in near future. And because there's a risk with overwriting buffer in git_path(), let's convert them all to strbuf_git_path(). We'll have easier time killing/converting strbuf_git_path() then because we won't have to worry about memory management again.
--- refs/files-backend.c | 130 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 97 insertions(+), 33 deletions(-)
refs/files-backend.c +97 -33
@@ -2319,6 +2319,7 @@ enum {static void try_remove_empty_parents (const char *refname,unsigned int flags) {struct strbuf buf =STRBUF_INIT ; +struct strbuf sb =STRBUF_INIT ;char *p, *q;int i;
@@ -2340,14 +2341,19 @@ static void try_remove_empty_parents(const char *refname, unsigned int flags)if (q == p)break ;strbuf_setlen (&buf, q - buf.buf); -if ((flags &REMOVE_EMPTY_PARENTS_REF ) && -rmdir (git_path ("%s" , buf.buf))) + +strbuf_reset (&sb); +strbuf_git_path (&sb,"%s" , buf.buf); +if ((flags &REMOVE_EMPTY_PARENTS_REF ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REF ; -if ((flags &REMOVE_EMPTY_PARENTS_REFLOG ) && -rmdir (git_path ("logs/%s" , buf.buf))) + +strbuf_reset (&sb); +strbuf_git_path (&sb,"logs/%s" , buf.buf); +if ((flags &REMOVE_EMPTY_PARENTS_REFLOG ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REFLOG ; }strbuf_release (&buf); +strbuf_release (&sb); }/* make sure nobody touched the ref, and unlink */
@@ -2509,11 +2515,16 @@ static int files_delete_refs(struct ref_store *ref_store,*/ #define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log" -static int rename_tmp_log_callback (const char *path,void *cb) +struct rename_cb { +const char *tmp_renamed_log; +int true_errno; +}; + +static int rename_tmp_log_callback (const char *path,void *cb_data) { -int *true_errno = cb; +struct rename_cb *cb = cb_data; -if (rename (git_path (TMP_RENAMED_LOG ), path)) { +if (rename (cb->tmp_renamed_log, path)) {/* * rename(a, b) when b is an existing directory ought * to result in ISDIR, but Solaris 5.8 gives ENOTDIR.
@@ -2521,7 +2532,7 @@ static int rename_tmp_log_callback(const char *path, void *cb)* but report EISDIR to raceproof_create_file() so * that it knows to retry. */ - *true_errno = errno; + cb->true_errno = errno;if (errno ==ENOTDIR ) errno =EISDIR ;return -1 ;
@@ -2532,20 +2543,26 @@ static int rename_tmp_log_callback(const char *path, void *cb)static int rename_tmp_log (const char *newrefname) { -char *path =git_pathdup ("logs/%s" , newrefname); -int ret, true_errno; +struct strbuf path =STRBUF_INIT ; +struct strbuf tmp =STRBUF_INIT ; +struct rename_cb cb; +int ret; - ret =raceproof_create_file (path, rename_tmp_log_callback, &true_errno); +strbuf_git_path (&path,"logs/%s" , newrefname); +strbuf_git_path (&tmp,TMP_RENAMED_LOG ); + cb.tmp_renamed_log = tmp.buf; + ret =raceproof_create_file (path.buf, rename_tmp_log_callback, &cb);if (ret) {if (errno ==EISDIR ) -error ("directory not empty: %s" , path); +error ("directory not empty: %s" , path.buf);else error ("unable to move logfile %s to %s: %s" , -git_path (TMP_RENAMED_LOG ), path, -strerror (true_errno)); + tmp.buf, path.buf, +strerror (cb.true_errno)); } -free (path); +strbuf_release (&path); +strbuf_release (&tmp);return ret; }
@@ -2586,10 +2603,17 @@ static int files_rename_ref(struct ref_store *ref_store,int flag =0 , logmoved =0 ;struct ref_lock *lock;struct stat loginfo; -int log = !lstat (git_path ("logs/%s" , oldrefname), &loginfo); +struct strbuf sb_oldref =STRBUF_INIT ; +struct strbuf sb_newref =STRBUF_INIT ; +struct strbuf tmp_renamed_log =STRBUF_INIT ; +int log, ret;struct strbuf err =STRBUF_INIT ; -int ret; +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +strbuf_git_path (&sb_newref,"logs/%s" , newrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + + log = !lstat (sb_oldref.buf, &loginfo);if (log &&S_ISLNK (loginfo.st_mode)) { ret =error ("reflog for %s is a symlink" , oldrefname); goto out;
@@ -2611,7 +2635,7 @@ static int files_rename_ref(struct ref_store *ref_store, goto out; } -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) { +if (log &&rename (sb_oldref.buf, tmp_renamed_log.buf)) { ret =error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); goto out;
@@ -2693,16 +2717,19 @@ static int files_rename_ref(struct ref_store *ref_store, log_all_ref_updates = flag; rollbacklog: -if (logmoved &&rename (git_path ("logs/%s" , newrefname),git_path ("logs/%s" , oldrefname))) +if (logmoved &&rename (sb_newref.buf, sb_oldref.buf))error ("unable to restore logfile %s from %s: %s" , oldrefname, newrefname,strerror (errno));if (!logmoved && log && -rename (git_path (TMP_RENAMED_LOG ),git_path ("logs/%s" , oldrefname))) +rename (tmp_renamed_log.buf, sb_oldref.buf))error ("unable to restore logfile %s from " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); - ret =1 ; out: +strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log); +return ret; }
@@ -2875,18 +2902,24 @@ int files_log_ref_write(const char *refname, const unsigned char *old_sha1, result =log_ref_write_fd (logfd, old_sha1, new_sha1,git_committer_info (0 ), msg);if (result) { +struct strbuf sb =STRBUF_INIT ;int save_errno = errno; +strbuf_git_path (&sb,"logs/%s" , refname);strbuf_addf (err,"unable to append to '%s': %s" , -git_path ("logs/%s" , refname),strerror (save_errno)); + sb.buf,strerror (save_errno)); +strbuf_release (&sb);close (logfd);return -1 ; }if (close (logfd)) { +struct strbuf sb =STRBUF_INIT ;int save_errno = errno; +strbuf_git_path (&sb,"logs/%s" , refname);strbuf_addf (err,"unable to append to '%s': %s" , -git_path ("logs/%s" , refname),strerror (save_errno)); + sb.buf,strerror (save_errno)); +strbuf_release (&sb);return -1 ; }return 0 ;
@@ -3106,22 +3139,32 @@ int set_worktree_head_symref(const char *gitdir, const char *target, const charstatic int files_reflog_exists (struct ref_store *ref_store,const char *refname) { +struct strbuf sb =STRBUF_INIT ;struct stat st; +int ret;/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"reflog_exists" ); -return !lstat (git_path ("logs/%s" , refname), &st) && -S_ISREG (st.st_mode); +strbuf_git_path (&sb,"logs/%s" , refname); + ret = !lstat (sb.buf, &st) &&S_ISREG (st.st_mode); +strbuf_release (&sb); +return ret; }static int files_delete_reflog (struct ref_store *ref_store,const char *refname) { +struct strbuf sb =STRBUF_INIT ; +int ret; +/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"delete_reflog" ); -return remove_path (git_path ("logs/%s" , refname)); +strbuf_git_path (&sb,"logs/%s" , refname); + ret =remove_path (sb.buf); +strbuf_release (&sb); +return ret; }static int show_one_reflog_ent (struct strbuf *sb,each_reflog_ent_fn fn,void *cb_data)
@@ -3177,7 +3220,9 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"for_each_reflog_ent_reverse" ); - logfp =fopen (git_path ("logs/%s" , refname),"r" ); +strbuf_git_path (&sb,"logs/%s" , refname); + logfp =fopen (sb.buf,"r" ); +strbuf_release (&sb);if (!logfp)return -1 ;
@@ -3283,7 +3328,9 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"for_each_reflog_ent" ); - logfp =fopen (git_path ("logs/%s" , refname),"r" ); +strbuf_git_path (&sb,"logs/%s" , refname); + logfp =fopen (sb.buf,"r" ); +strbuf_release (&sb);if (!logfp)return -1 ;
@@ -3365,12 +3412,15 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st {struct files_reflog_iterator *iter =xcalloc (1 ,sizeof (*iter));struct ref_iterator *ref_iterator = &iter->base; +struct strbuf sb =STRBUF_INIT ;/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"reflog_iterator_begin" );base_ref_iterator_init (ref_iterator, &files_reflog_iterator_vtable); - iter->dir_iterator =dir_iterator_begin (git_path ("logs" )); +strbuf_git_path (&sb,"logs" ); + iter->dir_iterator =dir_iterator_begin (sb.buf); +strbuf_release (&sb);return ref_iterator; }
@@ -3708,6 +3758,7 @@ static int files_transaction_commit(struct ref_store *ref_store,char *head_ref =NULL ;int head_type;struct object_id head_oid; +struct strbuf sb =STRBUF_INIT ;assert (err);
@@ -3829,7 +3880,9 @@ static int files_transaction_commit(struct ref_store *ref_store,if (!(update->type &REF_ISPACKED ) || update->type &REF_ISSYMREF ) {/* It is a loose reference. */ -if (unlink_or_msg (git_path ("%s" , lock->ref_name), err)) { +strbuf_reset (&sb); +strbuf_git_path (&sb,"%s" , lock->ref_name); +if (unlink_or_msg (sb.buf, err)) { ret =TRANSACTION_GENERIC_ERROR ; goto cleanup; }
@@ -3849,7 +3902,9 @@ static int files_transaction_commit(struct ref_store *ref_store,/* Delete the reflogs of any references that were deleted: */ for_each_string_list_item (ref_to_delete, &refs_to_delete) { -if (!unlink_or_warn (git_path ("logs/%s" , ref_to_delete->string))) +strbuf_reset (&sb); +strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +if (!unlink_or_warn (sb.buf))try_remove_empty_parents (ref_to_delete->string,REMOVE_EMPTY_PARENTS_REFLOG ); }
@@ -3857,6 +3912,7 @@ static int files_transaction_commit(struct ref_store *ref_store,clear_loose_ref_cache (refs); cleanup: +strbuf_release (&sb); transaction->state =REF_TRANSACTION_CLOSED ;for (i =0 ; i < transaction->nr; i++) {
@@ -4123,14 +4179,22 @@ static int files_reflog_expire(struct ref_store *ref_store,static int files_init_db (struct ref_store *ref_store,struct strbuf *err) { +struct strbuf sb =STRBUF_INIT ; +/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"init_db" );/* * Create .git/refs/{heads,tags} */ -safe_create_dir (git_path ("refs/heads" ),1 ); -safe_create_dir (git_path ("refs/tags" ),1 ); +strbuf_git_path (&sb,"refs/heads" ); +safe_create_dir (sb.buf,1 ); + +strbuf_reset (&sb); +strbuf_git_path (&sb,"refs/tags" ); +safe_create_dir (sb.buf,1 ); + +strbuf_release (&sb);return 0 ; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 7/27 files-backend: move "logs/" out of TMP_RENAMED_LOG
In reply to Nguyễn Thái Ngọc DuyThis makes reflog path building consistent, always in the form of
strbuf_git_path(sb, "logs/%s", refname);
It reduces the mental workload a bit in the next patch when that function call is converted.
--- refs/files-backend.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
refs/files-backend.c +5 -5
@@ -2513,7 +2513,7 @@ static int files_delete_refs(struct ref_store *ref_store,* IOW, to avoid cross device rename errors, the temporary renamed log must * live into logs/refs. */ -#define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log" +#define TMP_RENAMED_LOG "refs/.tmp-renamed-log"struct rename_cb {const char *tmp_renamed_log;
@@ -2549,7 +2549,7 @@ static int rename_tmp_log(const char *newrefname)int ret;strbuf_git_path (&path,"logs/%s" , newrefname); -strbuf_git_path (&tmp,TMP_RENAMED_LOG ); +strbuf_git_path (&tmp,"logs/%s" ,TMP_RENAMED_LOG ); cb.tmp_renamed_log = tmp.buf; ret =raceproof_create_file (path.buf, rename_tmp_log_callback, &cb);if (ret) {
@@ -2611,7 +2611,7 @@ static int files_rename_ref(struct ref_store *ref_store,strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname);strbuf_git_path (&sb_newref,"logs/%s" , newrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG ); log = !lstat (sb_oldref.buf, &loginfo);if (log &&S_ISLNK (loginfo.st_mode)) {
@@ -2636,7 +2636,7 @@ static int files_rename_ref(struct ref_store *ref_store, }if (log &&rename (sb_oldref.buf, tmp_renamed_log.buf)) { - ret =error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , + ret =error ("unable to move logfile logs/%s to logs/" TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); goto out; }
@@ -2722,7 +2722,7 @@ static int files_rename_ref(struct ref_store *ref_store, oldrefname, newrefname, strerror(errno));if (!logmoved && log &&rename (tmp_renamed_log.buf, sb_oldref.buf)) -error ("unable to restore logfile %s from " TMP_RENAMED_LOG ": %s" , +error ("unable to restore logfile %s from logs/" TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); ret =1 ; out:
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 8/27 files-backend: add and use files_reflog_path()
In reply to Nguyễn Thái Ngọc DuyKeep repo-related path handling in one place. This will make it easier to add submodule/multiworktree support later.
--- refs/files-backend.c | 142 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 56 deletions(-)
refs/files-backend.c +86 -56
@@ -165,7 +165,8 @@ static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, const char *dirname, size_t len, int incomplete);static void add_entry_to_dir (struct ref_dir *dir,struct ref_entry *entry); -static int files_log_ref_write (const char *refname,const unsigned char *old_sha1, +static int files_log_ref_write (struct files_ref_store *refs, +const char *refname,const unsigned char *old_sha1,const unsigned char *new_sha1,const char *msg,int flags,struct strbuf *err);
@@ -1167,6 +1168,18 @@ static const char *files_packed_refs_path(struct files_ref_store *refs)return refs->packed_refs_path; } +static void files_reflog_path (struct files_ref_store *refs, +struct strbuf *sb, +const char *refname) +{ +if (!refname) { +strbuf_git_path (sb,"logs" ); +return ; + } + +strbuf_git_path (sb,"logs/%s" , refname); +} +/* * Get the packed_ref_cache for the specified files_ref_store, * creating it if necessary.
@@ -2316,7 +2329,9 @@ enum {* subdirs. flags is a combination of REMOVE_EMPTY_PARENTS_REF and/or * REMOVE_EMPTY_PARENTS_REFLOG. */ -static void try_remove_empty_parents (const char *refname,unsigned int flags) +static void try_remove_empty_parents (struct files_ref_store *refs, +const char *refname, +unsigned int flags) {struct strbuf buf =STRBUF_INIT ;struct strbuf sb =STRBUF_INIT ;
@@ -2348,7 +2363,7 @@ static void try_remove_empty_parents(const char *refname, unsigned int flags) flags &= ~REMOVE_EMPTY_PARENTS_REF ;strbuf_reset (&sb); -strbuf_git_path (&sb,"logs/%s" , buf.buf); +files_reflog_path (refs, &sb, buf.buf);if ((flags &REMOVE_EMPTY_PARENTS_REFLOG ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REFLOG ; }
@@ -2541,15 +2556,15 @@ static int rename_tmp_log_callback(const char *path, void *cb_data) } } -static int rename_tmp_log (const char *newrefname) +static int rename_tmp_log (struct files_ref_store *refs,const char *newrefname) {struct strbuf path =STRBUF_INIT ;struct strbuf tmp =STRBUF_INIT ;struct rename_cb cb;int ret; -strbuf_git_path (&path,"logs/%s" , newrefname); -strbuf_git_path (&tmp,"logs/%s" ,TMP_RENAMED_LOG ); +files_reflog_path (refs, &path, newrefname); +files_reflog_path (refs, &tmp,TMP_RENAMED_LOG ); cb.tmp_renamed_log = tmp.buf; ret =raceproof_create_file (path.buf, rename_tmp_log_callback, &cb);if (ret) {
@@ -2609,9 +2624,9 @@ static int files_rename_ref(struct ref_store *ref_store,int log, ret;struct strbuf err =STRBUF_INIT ; -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&sb_newref,"logs/%s" , newrefname); -strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG ); +files_reflog_path (refs, &sb_oldref, oldrefname); +files_reflog_path (refs, &sb_newref, newrefname); +files_reflog_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); log = !lstat (sb_oldref.buf, &loginfo);if (log &&S_ISLNK (loginfo.st_mode)) {
@@ -2674,7 +2689,7 @@ static int files_rename_ref(struct ref_store *ref_store, } } -if (log &&rename_tmp_log (newrefname)) +if (log &&rename_tmp_log (refs, newrefname)) goto rollback; logmoved = log;
@@ -2789,10 +2804,15 @@ static int open_or_create_logfile(const char *path, void *cb)* set *logfd to -1. On failure, fill in *err, set *logfd to -1, and * return -1. */ -static int log_ref_setup (const char *refname,int force_create, +static int log_ref_setup (struct files_ref_store *refs, +const char *refname,int force_create,int *logfd,struct strbuf *err) { -char *logfile =git_pathdup ("logs/%s" , refname); +struct strbuf logfile_sb =STRBUF_INIT ; +char *logfile; + +files_reflog_path (refs, &logfile_sb, refname); + logfile =strbuf_detach (&logfile_sb,NULL );if (force_create ||should_autocreate_reflog (refname)) {if (raceproof_create_file (logfile, open_or_create_logfile, logfd)) {
@@ -2842,12 +2862,11 @@ static int files_create_reflog(struct ref_store *ref_store, const char *refname, int force_create, struct strbuf *err) { + struct files_ref_store *refs = +files_downcast (ref_store,0 ,"create_reflog" );int fd; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"create_reflog" ); - -if (log_ref_setup (refname, force_create, &fd, err)) +if (log_ref_setup (refs, refname, force_create, &fd, err))return -1 ;if (fd >=0 )
@@ -2882,7 +2901,8 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,return 0 ; } -int files_log_ref_write (const char *refname,const unsigned char *old_sha1, +int files_log_ref_write (struct files_ref_store *refs, +const char *refname,const unsigned char *old_sha1,const unsigned char *new_sha1,const char *msg,int flags,struct strbuf *err) {
@@ -2891,7 +2911,8 @@ int files_log_ref_write(const char *refname, const unsigned char *old_sha1,if (log_all_ref_updates ==LOG_REFS_UNSET ) log_all_ref_updates =is_bare_repository () ?LOG_REFS_NONE :LOG_REFS_NORMAL ; - result =log_ref_setup (refname, flags &REF_FORCE_CREATE_REFLOG , + result =log_ref_setup (refs, refname, + flags &REF_FORCE_CREATE_REFLOG , &logfd, err);if (result)
@@ -2905,7 +2926,7 @@ int files_log_ref_write(const char *refname, const unsigned char *old_sha1,struct strbuf sb =STRBUF_INIT ;int save_errno = errno; -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname);strbuf_addf (err,"unable to append to '%s': %s" , sb.buf,strerror (save_errno));strbuf_release (&sb);
@@ -2916,7 +2937,7 @@ int files_log_ref_write(const char *refname, const unsigned char *old_sha1,struct strbuf sb =STRBUF_INIT ;int save_errno = errno; -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname);strbuf_addf (err,"unable to append to '%s': %s" , sb.buf,strerror (save_errno));strbuf_release (&sb);
@@ -2977,7 +2998,8 @@ static int commit_ref_update(struct files_ref_store *refs,files_assert_main_repository (refs,"commit_ref_update" );clear_loose_ref_cache (refs); -if (files_log_ref_write (lock->ref_name, lock->old_oid.hash, sha1, +if (files_log_ref_write (refs, lock->ref_name, + lock->old_oid.hash, sha1, logmsg,0 , err)) {char *old_msg =strbuf_detach (err,NULL ); strbuf_addf(err, "cannot update the ref '%s': %s",
@@ -3009,8 +3031,9 @@ static int commit_ref_update(struct files_ref_store *refs,if (head_ref && (head_flag &REF_ISSYMREF ) && !strcmp (head_ref, lock->ref_name)) {struct strbuf log_err =STRBUF_INIT ; -if (files_log_ref_write ("HEAD" , lock->old_oid.hash, sha1, - logmsg,0 , &log_err)) { +if (files_log_ref_write (refs,"HEAD" , + lock->old_oid.hash, sha1, + logmsg,0 , &log_err)) {error ("%s" , log_err.buf);strbuf_release (&log_err); }
@@ -3042,24 +3065,26 @@ static int create_ref_symlink(struct ref_lock *lock, const char *target)return ret; } -static void update_symref_reflog (struct ref_lock *lock,const char *refname, +static void update_symref_reflog (struct files_ref_store *refs, +struct ref_lock *lock,const char *refname,const char *target,const char *logmsg) {struct strbuf err =STRBUF_INIT ;unsigned char new_sha1[20 ];if (logmsg && !read_ref (target, new_sha1) && -files_log_ref_write (refname, lock->old_oid.hash, new_sha1, - logmsg,0 , &err)) { +files_log_ref_write (refs, refname, lock->old_oid.hash, + new_sha1, logmsg,0 , &err)) {error ("%s" , err.buf);strbuf_release (&err); } } -static int create_symref_locked (struct ref_lock *lock,const char *refname, +static int create_symref_locked (struct files_ref_store *refs, +struct ref_lock *lock,const char *refname,const char *target,const char *logmsg) {if (prefer_symlink_refs && !create_ref_symlink (lock, target)) { -update_symref_reflog (lock, refname, target, logmsg); +update_symref_reflog (refs, lock, refname, target, logmsg);return 0 ; }
@@ -3067,7 +3092,7 @@ static int create_symref_locked(struct ref_lock *lock, const char *refname,return error ("unable to fdopen %s: %s" , lock->lk->tempfile.filename.buf,strerror (errno)); -update_symref_reflog (lock, refname, target, logmsg); +update_symref_reflog (refs, lock, refname, target, logmsg);/* no error check; commit_ref will check ferror */ fprintf (lock->lk->tempfile.fp,"ref: %s\n" , target);
@@ -3096,13 +3121,20 @@ static int files_create_symref(struct ref_store *ref_store,return -1 ; } - ret =create_symref_locked (lock, refname, target, logmsg); + ret =create_symref_locked (refs, lock, refname, target, logmsg);unlock_ref (lock);return ret; }int set_worktree_head_symref (const char *gitdir,const char *target,const char *logmsg) { +/* +* FIXME: this obviously will not work well for future refs +* backends. This function needs to die. +*/ +struct files_ref_store *refs = +files_downcast (get_ref_store (NULL ),0 ,"set_head_symref" ); +static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
@@ -3129,7 +3161,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target, const char lock->lk = &head_lock; lock->ref_name =xstrdup (head_rel); - ret =create_symref_locked (lock, head_rel, target, logmsg); + ret =create_symref_locked (refs, lock, head_rel, target, logmsg);unlock_ref (lock);/* will free lock */ strbuf_release (&head_path);
@@ -3139,14 +3171,13 @@ int set_worktree_head_symref(const char *gitdir, const char *target, const charstatic int files_reflog_exists (struct ref_store *ref_store,const char *refname) { +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"reflog_exists" );struct strbuf sb =STRBUF_INIT ;struct stat st;int ret; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"reflog_exists" ); - -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname); ret = !lstat (sb.buf, &st) &&S_ISREG (st.st_mode);strbuf_release (&sb);return ret;
@@ -3155,13 +3186,12 @@ static int files_reflog_exists(struct ref_store *ref_store,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" );struct strbuf sb =STRBUF_INIT ;int ret; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"delete_reflog" ); - -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname); ret =remove_path (sb.buf);strbuf_release (&sb);return ret;
@@ -3212,15 +3242,14 @@ static int files_for_each_reflog_ent_reverse(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_reverse" );struct strbuf sb =STRBUF_INIT ;FILE *logfp;long pos;int ret =0 , at_tail =1 ; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"for_each_reflog_ent_reverse" ); - -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3321,14 +3350,13 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,const char *refname, each_reflog_ent_fn fn, void *cb_data) { + struct files_ref_store *refs = +files_downcast (ref_store,0 ,"for_each_reflog_ent" );FILE *logfp;struct strbuf sb =STRBUF_INIT ;int ret =0 ; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"for_each_reflog_ent" ); - -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3410,15 +3438,14 @@ 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" );struct files_reflog_iterator *iter =xcalloc (1 ,sizeof (*iter));struct ref_iterator *ref_iterator = &iter->base;struct strbuf sb =STRBUF_INIT ; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"reflog_iterator_begin" ); -base_ref_iterator_init (ref_iterator, &files_reflog_iterator_vtable); -strbuf_git_path (&sb,"logs" ); +files_reflog_path (refs, &sb,NULL ); iter->dir_iterator =dir_iterator_begin (sb.buf);strbuf_release (&sb);return ref_iterator;
@@ -3843,7 +3870,8 @@ static int files_transaction_commit(struct ref_store *ref_store,if (update->flags &REF_NEEDS_COMMIT || update->flags &REF_LOG_ONLY ) { - if (files_log_ref_write(lock->ref_name, + if (files_log_ref_write(refs, + lock->ref_name, lock->old_oid.hash, update->new_sha1, update->msg, update->flags,
@@ -3903,9 +3931,9 @@ static int files_transaction_commit(struct ref_store *ref_store,/* Delete the reflogs of any references that were deleted: */ for_each_string_list_item (ref_to_delete, &refs_to_delete) {strbuf_reset (&sb); -strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +files_reflog_path (refs, &sb, ref_to_delete->string);if (!unlink_or_warn (sb.buf)) -try_remove_empty_parents (ref_to_delete->string, +try_remove_empty_parents (refs, ref_to_delete->string,REMOVE_EMPTY_PARENTS_REFLOG ); }
@@ -3929,7 +3957,7 @@ static int files_transaction_commit(struct ref_store *ref_store,* can only work because we have already * removed the lockfile.) */ -try_remove_empty_parents (update->refname, +try_remove_empty_parents (refs, update->refname,REMOVE_EMPTY_PARENTS_REF ); } }
@@ -4080,6 +4108,7 @@ static int files_reflog_expire(struct ref_store *ref_store,static struct lock_file reflog_lock;struct expire_reflog_cb cb;struct ref_lock *lock; +struct strbuf log_file_sb =STRBUF_INIT ;char *log_file;int status =0 ;int type;
@@ -4108,7 +4137,8 @@ static int files_reflog_expire(struct ref_store *ref_store,return 0 ; } - log_file =git_pathdup ("logs/%s" , refname); +files_reflog_path (refs, &log_file_sb, refname); + log_file =strbuf_detach (&log_file_sb,NULL );if (!(flags &EXPIRE_REFLOGS_DRY_RUN )) {/* * Even though holding $GIT_DIR/logs/$reflog.lock has
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 9/27 files-backend: add and use files_refname_path()
In reply to Nguyễn Thái Ngọc DuyKeep repo-related path handling in one place. This will make it easier to add submodule/multiworktree support later.
This automatically adds the "if submodule then use the submodule version of git_path" to other call sites too. But it does not mean those operations are submodule-ready. Not yet.
--- refs/files-backend.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-)
refs/files-backend.c +23 -24
@@ -1180,6 +1180,18 @@ static void files_reflog_path(struct files_ref_store *refs,strbuf_git_path (sb,"logs/%s" , refname); } +static void files_refname_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 ; + } + +strbuf_git_path (sb,"%s" , refname); +} +/* * Get the packed_ref_cache for the specified files_ref_store, * creating it if necessary.
@@ -1249,19 +1261,10 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)struct strbuf refname;struct strbuf path =STRBUF_INIT ;size_t path_baselen; -int err =0 ; -if (refs->submodule) - err =strbuf_git_path_submodule (&path, refs->submodule,"%s" , dirname); -else -strbuf_git_path (&path,"%s" , dirname); +files_refname_path (refs, &path, dirname); path_baselen = path.len; -if (err) { -strbuf_release (&path); -return ; - } - d =opendir (path.buf);if (!d) {strbuf_release (&path);
@@ -1396,10 +1399,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, *type =0 ;strbuf_reset (&sb_path); -if (refs->submodule) -strbuf_git_path_submodule (&sb_path, refs->submodule,"%s" , refname); -else -strbuf_git_path (&sb_path,"%s" , refname); +files_refname_path (refs, &sb_path, refname); path = sb_path.buf;
@@ -1587,7 +1587,7 @@ static int lock_raw_ref(struct files_ref_store *refs, *lock_p = lock =xcalloc (1 ,sizeof (*lock)); lock->ref_name =xstrdup (refname); -strbuf_git_path (&ref_file,"%s" , refname); +files_refname_path (refs, &ref_file, refname); retry:switch (safe_create_leading_directories (ref_file.buf)) {
@@ -2059,7 +2059,7 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,if (flags &REF_DELETING ) resolve_flags |=RESOLVE_REF_ALLOW_BAD_NAME ; -strbuf_git_path (&ref_file,"%s" , refname); +files_refname_path (refs, &ref_file, refname); resolved = !!resolve_ref_unsafe (refname, resolve_flags, lock->old_oid.hash, type);if (!resolved && errno ==EISDIR ) {
@@ -2358,7 +2358,7 @@ static void try_remove_empty_parents(struct files_ref_store *refs,strbuf_setlen (&buf, q - buf.buf);strbuf_reset (&sb); -strbuf_git_path (&sb,"%s" , buf.buf); +files_refname_path (refs, &sb, buf.buf);if ((flags &REMOVE_EMPTY_PARENTS_REF ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REF ;
@@ -2675,7 +2675,7 @@ static int files_rename_ref(struct ref_store *ref_store,struct strbuf path =STRBUF_INIT ;int result; -strbuf_git_path (&path,"%s" , newrefname); +files_refname_path (refs, &path, newrefname); result =remove_empty_directories (&path);strbuf_release (&path);
@@ -3909,7 +3909,7 @@ static int files_transaction_commit(struct ref_store *ref_store, update->type & REF_ISSYMREF) {/* It is a loose reference. */ strbuf_reset (&sb); -strbuf_git_path (&sb,"%s" , lock->ref_name); +files_refname_path (refs, &sb, lock->ref_name);if (unlink_or_msg (sb.buf, err)) { ret =TRANSACTION_GENERIC_ERROR ; goto cleanup;
@@ -4209,19 +4209,18 @@ 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" );struct strbuf sb =STRBUF_INIT ; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"init_db" ); -/* * Create .git/refs/{heads,tags} */ -strbuf_git_path (&sb,"refs/heads" ); +files_refname_path (refs, &sb,"refs/heads" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_refname_path (refs, &sb,"refs/tags" );safe_create_dir (sb.buf,1 );strbuf_release (&sb);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v6 09/27] files-backend: add and use files_refname_path()
Quoted 6 lines · Nguyễn Thái Ngọc Duy
Keep repo-related path handling in one place. This will make it easier to add submodule/multiworktree support later.
This automatically adds the "if submodule then use the submodule version of
git_path" to other call sites too. But it does not mean those operations are submodule-ready. Not yet.
Maybe files_loose_ref_path() would be a more descriptive name for the new function. But I can live with it either way.
Quoted 39 lines
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-)refs/files-backend.c +13
-5@@ -1180,6 +1180,18 @@ static void files_reflog_path(struct files_ref_store *refs,strbuf_git_path (sb,"logs/%s" , refname); } +static void files_refname_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 ; + } + +strbuf_git_path (sb,"%s" , refname); +} +/* * Get the packed_ref_cache for the specified files_ref_store, * creating it if necessary. @@ -1249,19 +1261,10 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)struct strbuf refname;struct strbuf path =STRBUF_INIT ;size_t path_baselen; -int err =0 ; -if (refs->submodule) - err =strbuf_git_path_submodule (&path, refs->submodule,"%s" , dirname); -else -strbuf_git_path (&path,"%s" , dirname); +files_refname_path (refs, &path, dirname);
refs/files-backend.c static void read_loose_refs(const char *dirname, struct ref_dir *dir) · line 1270
Quoted 10 lines
refs/files-backend.c +0
-5path_baselen = path.len; -if (err) { -strbuf_release (&path); -return ; - } - d =opendir (path.buf);if (!d) {strbuf_release (&path);
The old code in the hunk above went to the trouble of handling errors from strbuf_git_path_submodule(), which I think can happen if the submodule path doesn't actually point at a directory that looks like a Git repository. Your new code doesn't handle such an error.
It seems clear that read_loose_refs() is to late a place to be dealing with such errors, and indeed it seems like the check is_nonbare_repository_dir() in get_ref_store() should make such errors impossible, so I think your change is OK. If you agree, it might be appropriate to mention that reasoning in the commit message.
Quoted 1 line
[...]
Michael
PATCH v6 10/27 files-backend: remove the use of git_path()
In reply to Nguyễn Thái Ngọc DuyGiven $GIT_DIR and $GIT_COMMON_DIR, files-backend is now in charge of deciding what goes where (*). The end goal is to pass $GIT_DIR only. A refs "view" of a linked worktree is a logical ref store that combines two files backends together.
(*) Not entirely true since strbuf_git_path_submodule() still does path translation underneath. But that's for another patch.
--- refs/files-backend.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-)
refs/files-backend.c +38 -5
@@ -923,7 +923,8 @@ struct files_ref_store {* store: */ const char *submodule; - +char *gitdir; +char *gitcommondir;char *packed_refs_path;struct ref_entry *loose;
@@ -985,6 +986,8 @@ static struct ref_store *files_ref_store_create(const char *submodule) {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);
@@ -995,7 +998,11 @@ static struct ref_store *files_ref_store_create(const char *submodule)return ref_store; } - refs->packed_refs_path =git_pathdup ("packed-refs" ); + refs->gitdir =xstrdup (gitdir); +get_common_dir_noenv (&sb, gitdir); + refs->gitcommondir =strbuf_detach (&sb,NULL ); +strbuf_addf (&sb,"%s/packed-refs" , refs->gitcommondir); + refs->packed_refs_path =strbuf_detach (&sb,NULL );return ref_store; }
@@ -1173,11 +1180,26 @@ static void files_reflog_path(struct files_ref_store *refs, const char *refname) {if (!refname) { -strbuf_git_path (sb,"logs" ); +/* +* FIXME: of course this is wrong in multi worktree +* setting. To be fixed real soon. +*/ +strbuf_addf (sb,"%s/logs" , refs->gitcommondir);return ; } -strbuf_git_path (sb,"logs/%s" , refname); +switch (ref_type (refname)) { +case REF_TYPE_PER_WORKTREE : +case REF_TYPE_PSEUDOREF : +strbuf_addf (sb,"%s/logs/%s" , refs->gitdir, refname); +break ; +case REF_TYPE_NORMAL : +strbuf_addf (sb,"%s/logs/%s" , refs->gitcommondir, refname); +break ; +default : +die ("BUG: unknown ref type %d of ref %s" , +ref_type (refname), refname); + } } static void files_refname_path(struct files_ref_store *refs,
@@ -1189,7 +1211,18 @@ static void files_refname_path(struct files_ref_store *refs,return ; } -strbuf_git_path (sb,"%s" , refname); +switch (ref_type (refname)) { +case REF_TYPE_PER_WORKTREE : +case REF_TYPE_PSEUDOREF : +strbuf_addf (sb,"%s/%s" , refs->gitdir, refname); +break ; +case REF_TYPE_NORMAL : +strbuf_addf (sb,"%s/%s" , refs->gitcommondir, refname); +break ; +default : +die ("BUG: unknown ref type %d of ref %s" , +ref_type (refname), refname); + } }/*
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 11/27 refs.c: introduce get_main_ref_store()
In reply to Nguyễn Thái Ngọc Duy--- refs.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
refs.c +12 -4
@@ -1456,15 +1456,23 @@ static struct ref_store *ref_store_init(const char *submodule)return refs; } +static struct ref_store *get_main_ref_store (void ) +{ +struct ref_store *refs; + +if (main_ref_store) +return main_ref_store; + + refs =ref_store_init (NULL ); +return refs; +} +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 ); +return get_main_ref_store (); }else { refs =lookup_ref_store (submodule);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v6 11/27] refs.c: introduce get_main_ref_store()
Quoted 14 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)refs.c +1
-0@@ -1456,15 +1456,23 @@ static struct ref_store *ref_store_init(const char *submodule)return refs; } +static struct ref_store *get_main_ref_store (void )
refs.c static struct ref_store *ref_store_init(const char *submodule) · line 1469
Quoted 10 lines
refs.c +10
-0+{ +struct ref_store *refs; + +if (main_ref_store) +return main_ref_store; + + refs =ref_store_init (NULL ); +return refs; +} +
I still [1] think that refs here is an unnecessary temporary variable. And even after your "kill register_ref_store" patch I think it is superfluous and the function could look like
static struct ref_store *get_main_ref_store(void)
{
if (!main_ref_store)
main_ref_store = ref_store_init(NULL);
return main_ref_store;
}Quoted 1 line
[...]
Michael
PATCH v6 12/27 refs: rename lookup_ref_store() to lookup_submodule_ref_store()
In reply to Nguyễn Thái Ngọc DuyWith get_main_ref_store() being used inside get_ref_store(), lookup_ref_store() is only used for submodule code path. Rename to reflect that and delete dead code.
--- refs.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)
refs.c +4 -9
@@ -1395,17 +1395,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 ;
@@ -1474,7 +1470,7 @@ struct ref_store *get_ref_store(const char *submodule)if (!submodule || !*submodule) {return get_main_ref_store (); }else { - refs =lookup_ref_store (submodule); + refs =lookup_submodule_ref_store (submodule);if (!refs) {struct strbuf submodule_sb =STRBUF_INIT ;
@@ -1485,7 +1481,6 @@ struct ref_store *get_ref_store(const char *submodule)strbuf_release (&submodule_sb); } } -return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 13/27 refs.c: flatten get_ref_store() a bit
In reply to Nguyễn Thái Ngọc DuyThis helps the future changes in this code. And because get_ref_store() is destined to become get_submodule_ref_store(), the "get main store" code path will be removed eventually. After this the patch to delete that code will be cleaner.
--- refs.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
refs.c +13 -10
@@ -1465,22 +1465,25 @@ static struct ref_store *get_main_ref_store(void)struct ref_store *get_ref_store (const char *submodule) { +struct strbuf submodule_sb =STRBUF_INIT ;struct ref_store *refs; +int ret;if (!submodule || !*submodule) {return get_main_ref_store (); - }else { - refs =lookup_submodule_ref_store (submodule); + } -if (!refs) { -struct strbuf submodule_sb =STRBUF_INIT ; + refs =lookup_submodule_ref_store (submodule); +if (refs) +return refs; -strbuf_addstr (&submodule_sb, submodule); -if (is_nonbare_repository_dir (&submodule_sb)) - refs =ref_store_init (submodule); -strbuf_release (&submodule_sb); - } - } +strbuf_addstr (&submodule_sb, submodule); + ret =is_nonbare_repository_dir (&submodule_sb); +strbuf_release (&submodule_sb); +if (!ret) +return NULL ; + + refs =ref_store_init (submodule);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 14/27 refs.c: kill register_ref_store(), add register_submodule_ref_store()
In reply to Nguyễn Thái Ngọc DuyThis is the last function in this code (besides public API) that takes submodule argument and handles both main/submodule cases. Break it down, move main store registration in get_main_ref_store() and keep the rest in register_submodule_ref_store().
--- refs.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-)
refs.c +19 -24
@@ -1412,29 +1412,6 @@ static struct ref_store *lookup_submodule_ref_store(const char *submodule) }/* -* 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). */
@@ -1448,7 +1425,6 @@ static struct ref_store *ref_store_init(const char *submodule)die ("BUG: reference backend %s is unknown" , be_name); refs = be->init (submodule); -register_ref_store (refs, submodule);return refs; }
@@ -1460,9 +1436,27 @@ static struct ref_store *get_main_ref_store(void)return main_ref_store; refs =ref_store_init (NULL ); + main_ref_store = refs;return refs; } +/* +* 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_ref_store (const char *submodule) {struct strbuf submodule_sb =STRBUF_INIT ;
@@ -1484,6 +1478,7 @@ struct ref_store *get_ref_store(const char *submodule)return NULL ; refs =ref_store_init (submodule); +register_submodule_ref_store (refs, submodule);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 15/27 refs.c: make get_main_ref_store() public and use it
In reply to Nguyễn Thái Ngọc Duyget_ref_store() will soon be renamed to get_submodule_ref_store(). Together with future get_worktree_ref_store(), the three functions provide an appropriate ref store for different operation modes. New APIs will be added to operate directly on ref stores.
--- refs.c | 36 ++++++++++++++++++------------------ refs.h | 3 +++ refs/files-backend.c | 2 +- 3 files changed, 22 insertions(+), 19 deletions(-)
refs.c +18 -18
@@ -1314,7 +1314,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); }
@@ -1322,7 +1322,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 resolve_ref_recursively (get_main_ref_store (), refname, resolve_flags, sha1, flags); }
@@ -1428,7 +1428,7 @@ static struct ref_store *ref_store_init(const char *submodule)return refs; } -static struct ref_store *get_main_ref_store (void ) +struct ref_store *get_main_ref_store (void ) {struct ref_store *refs;
@@ -1491,14 +1491,14 @@ void base_ref_store_init(struct ref_store *refs,/* backend functions */ int pack_refs (unsigned int flags) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->pack_refs (refs, flags); }int peel_ref (const char *refname,unsigned char *sha1) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->peel_ref (refs, refname, sha1); }
@@ -1506,7 +1506,7 @@ int peel_ref(const char *refname, unsigned char *sha1)int create_symref (const char *ref_target,const char *refs_heads_master,const char *logmsg) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->create_symref (refs, ref_target, refs_heads_master, logmsg);
@@ -1515,7 +1515,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_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->transaction_commit (refs, transaction, err); }
@@ -1525,14 +1525,14 @@ int verify_refname_available(const char *refname,const struct string_list *skip, struct strbuf *err) { - struct ref_store *refs = get_ref_store(NULL); + 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) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();struct ref_iterator *iter; iter = refs->be->reflog_iterator_begin (refs);
@@ -1543,7 +1543,7 @@ int for_each_reflog(each_ref_fn fn, void *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 ); +struct ref_store *refs =get_main_ref_store ();return refs->be->for_each_reflog_ent_reverse (refs, refname, fn, cb_data);
@@ -1552,14 +1552,14 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,int for_each_reflog_ent (const char *refname,each_reflog_ent_fn fn,void *cb_data) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();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 ); +struct ref_store *refs =get_main_ref_store ();return refs->be->reflog_exists (refs, refname); }
@@ -1567,14 +1567,14 @@ int reflog_exists(const char *refname)int safe_create_reflog (const char *refname,int force_create,struct strbuf *err) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->create_reflog (refs, refname, force_create, err); }int delete_reflog (const char *refname) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->delete_reflog (refs, refname); }
@@ -1586,7 +1586,7 @@ 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); + struct ref_store *refs = get_main_ref_store(); return refs->be->reflog_expire(refs, refname, sha1, flags, prepare_fn, should_prune_fn,
@@ -1596,21 +1596,21 @@ 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_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();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 ); +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) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->rename_ref (refs, oldref, newref, logmsg); }
refs.h +3 -0
@@ -2,6 +2,7 @@#define REFS_H struct object_id ; +struct ref_store ;struct strbuf ;struct string_list ;
@@ -560,4 +561,6 @@ 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 ); +#endif /* REFS_H */
refs/files-backend.c +1 -1
@@ -3166,7 +3166,7 @@ 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_ref_store (NULL ),0 ,"set_head_symref" ); +files_downcast (get_main_ref_store (),0 ,"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 16/27 path.c: move some code out of strbuf_git_path_submodule()
In reply to Nguyễn Thái Ngọc Duyrefs is learning to avoid path rewriting that is done by strbuf_git_path_submodule(). Factor out this code so it could be reused by refs*
--- path.c | 35 +++++++---------------------------- submodule.c | 36 ++++++++++++++++++++++++++++++++++++ submodule.h | 1 + 3 files changed, 44 insertions(+), 28 deletions(-)
path.c +7 -28
@@ -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 -1static 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, ...)
submodule.c +36 -0
@@ -1596,3 +1596,39 @@ const char *get_superproject_working_tree(void)return ret; } + +/* +* 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) +{ +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; +}
submodule.h +1 -0
@@ -81,6 +81,7 @@ extern int push_unpushed_submodules(struct sha1_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 ); +int submodule_to_gitdir (struct strbuf *buf,const char *submodule);/* * Prepare the "env_array" parameter of a "struct child_process" for executing
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v6 16/27] path.c: move some code out of strbuf_git_path_submodule()
Quoted 3 lines · Nguyễn Thái Ngọc Duy
refs is learning to avoid path rewriting that is done by
strbuf_git_path_submodule(). Factor out this code so it could be reused by refs*
Is the "*" on the previous line is a typo, or did you want to add a footnote, or ...?
Quoted 13 lines
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- path.c | 35 +++++++---------------------------- submodule.c | 36 ++++++++++++++++++++++++++++++++++++ submodule.h | 1 + 3 files changed, 44 insertions(+), 28 deletions(-)[...]
submodule.c +0
-0
submodule.c const char *get_superproject_working_tree(void) · line 1604
Quoted 9 lines
submodule.c +6
-0@@ -1596,3 +1596,39 @@ const char *get_superproject_working_tree(void)return ret; } + +/* +* 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. +*/
Thanks for writing a docstring, but given that this is a public function, I think it is preferred to put the docstring in the header file.
Quoted 1 line
[...]
Michael
Re: [PATCH v6 16/27] path.c: move some code out of strbuf_git_path_submodule()
Quoted 7 lines · Michael Haggerty
Quoted 3 lines · Nguyễn Thái Ngọc Duy
refs is learning to avoid path rewriting that is done by
strbuf_git_path_submodule(). Factor out this code so it could be reused by refs*Is the "*" on the previous line is a typo, or did you want to add a footnote, or ...?
It's a wildcard for "all refs functions" :D Will rephrase.
Signature · 1 line
Duy
PATCH v6 17/27 refs: move submodule code out of files-backend.c
In reply to Nguyễn Thái Ngọc Duyfiles-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.
--- refs.c | 19 ++++++++++++++----- refs/files-backend.c | 24 ++---------------------- refs/refs-internal.h | 9 ++++----- 3 files changed, 20 insertions(+), 32 deletions(-)
refs.c +14 -5
@@ -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; }
@@ -1435,7 +1436,7 @@ struct ref_store *get_main_ref_store(void)if (main_ref_store)return main_ref_store; - refs =ref_store_init (NULL ); + refs =ref_store_init (get_git_dir ()); main_ref_store = refs;return refs; }
@@ -1477,8 +1478,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; }
refs/files-backend.c +2 -22
@@ -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 deleted in the next patch */ }/*
@@ -1206,11 +1191,6 @@ static void files_refname_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:
refs/refs-internal.h +4 -5
@@ -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);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v6 17/27] refs: move submodule code out of files-backend.c
Quoted 24 lines · Nguyễn Thái Ngọc Duy
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()andfiles_assert_main_repository()follows shortly. It's separate to keep noises from this patch.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.c | 19 ++++++++++++++----- refs/files-backend.c | 24 ++---------------------- refs/refs-internal.h | 9 ++++----- 3 files changed, 20 insertions(+), 32 deletions(-)[...]
refs/files-backend.c +0
-0
refs/files-backend.c static struct ref_store *files_ref_store_create(const char *submodule) · line 1003
Quoted 6 lines
refs/files-backend.c +1
-2@@ -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 deleted in the next patch */
Actually, the function survives the next patch. But the incorrect comment doesn't ;-)
Ideally, the following patch would precede this one; then this function wouldn't have to be disabled between the two patches.
But given that it's only a consistency check, I suppose that we can live with the disappearance of this check for one commit. The comment could maybe be corrected, though.
Quoted 6 lines
[...]
refs/refs-internal.h +0
-0
refs/refs-internal.h struct ref_store; · line 487
Quoted 10 lines
refs/refs-internal.h +3
-4@@ -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.
Maybe mention that the function will make its own copy of gitdir?
refs/refs-internal.h struct ref_store; · line 491
Quoted 5 lines
refs/refs-internal.h +1
-1*/ -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);
Michael
Re: [PATCH v6 17/27] refs: move submodule code out of files-backend.c
Quoted 8 lines · Michael Haggerty
Quoted 8 lines
[...]
refs/refs-internal.h +0
-0@@ -482,12 +482,11 @@ struct ref_store;/* refs backends */
Quoted 10 lines
refs/refs-internal.h struct ref_store; · line 487
Quoted 8 lines
refs/refs-internal.h +3
-4/* -* 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. Maybe mention that the function will make its own copy of
gitdir?
I would think that's the default/sane behavior and not need to be mentioned? A function that keeps a pointer even after it exits, now that's something that must be documented.
Signature · 1 line
Duy
Re: [PATCH v6 17/27] refs: move submodule code out of files-backend.c
Quoted 20 lines · Duy Nguyen
Quoted 8 lines · Michael Haggerty
Quoted 8 lines
[...]
refs/refs-internal.h +0
-0@@ -482,12 +482,11 @@ struct ref_store;/* refs backends */ Quoted 10 lines
refs/refs-internal.h struct ref_store; · line 487
Quoted 8 lines
refs/refs-internal.h +3
-4/* -* 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. Maybe mention that the function will make its own copy of
gitdir?
Quoted 3 lines
I would think that's the default/sane behavior and not need to be mentioned? A function that keeps a pointer even after it exits, now that's something that must be documented.
I guess you're right, and I hope that everybody really documents such cases.
Michael
PATCH v6 18/27 files-backend: replace submodule_allowed check in files_downcast()
In reply to Nguyễn Thái Ngọc Duyfiles-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.
--- refs.c | 15 ++++++--- refs/files-backend.c | 86 +++++++++++++++++++++++++++++++++------------------- refs/refs-internal.h | 9 +++++- 3 files changed, 73 insertions(+), 37 deletions(-)
refs.c +11 -4
@@ -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; }
@@ -1436,7 +1437,11 @@ struct ref_store *get_main_ref_store(void)if (main_ref_store)return main_ref_store; - refs =ref_store_init (get_git_dir ()); + refs =ref_store_init (get_git_dir (), + (REF_STORE_READ | +REF_STORE_WRITE | +REF_STORE_ODB | +REF_STORE_MAIN )); main_ref_store = refs;return refs; }
@@ -1484,7 +1489,9 @@ struct ref_store *get_ref_store(const char *submodule)return NULL ; } - refs =ref_store_init (submodule_sb.buf); +/* pretend 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);
refs/files-backend.c +54 -32
253 lines not on this page · raw message
refs/refs-internal.h +8 -1
@@ -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);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v6 18/27] files-backend: replace submodule_allowed check in files_downcast()
Quoted 48 lines · Nguyễn Thái Ngọc Duy
files-backend.cis 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 takeREF_STORE_ODBflag out. At least t3404 would fail. The "have access to odb" in submodule is a bit hacky since we don't know from he whetheradd_submodule_odb()has been called.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.c | 15 ++++++--- refs/files-backend.c | 86 +++++++++++++++++++++++++++++++++------------------- refs/refs-internal.h | 9 +++++- 3 files changed, 73 insertions(+), 37 deletions(-)[...]
refs/files-backend.c +1
-5@@ -1923,21 +1935,23 @@ 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;struct ref_iterator *ref_iterator; -if (!refs) -return empty_ref_iterator_begin (); -if (ref_paranoia <0 )
refs/files-backend.c static struct ref_iterator *files_ref_iterator_begin( · line 1954
Quoted 10 lines
refs/files-backend.c +6
-0ref_paranoia =git_env_bool ("GIT_REF_PARANOIA" ,0 );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" ); +if (!refs) +return empty_ref_iterator_begin (); +
I realize that this if (!refs) check existed in the old code, but isn't it pointless? If refs were NULL, files_downcast() would have already segfaulted, I think.
refs/refs-internal.h struct ref_store; · line 485
Quoted 11 lines
[...]
refs/refs-internal.h +2
-0@@ -481,12 +481,19 @@ struct ref_store;/* refs backends */ +/* ref_store_init flags */ +#define REF_STORE_READ (1 << 0)
I asked [1] in reply to v5 whether REF_STORE_READ is really necessary but I don't think you replied. Surely a reference store that we can't read would be useless? Can't we just assume that any ref_store is readable and drop this constant?
Quoted 4 lines
refs/refs-internal.h +4
-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) +
refs/refs-internal.h struct ref_store; · line 498
Quoted 10 lines
refs/refs-internal.h +2
-1/* * 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);
Michael
Re: [PATCH v6 18/27] files-backend: replace submodule_allowed check in files_downcast()
Quoted 7 lines · Michael Haggerty
refs/refs-internal.h struct ref_store; · line 485
Quoted 2 lines
refs/refs-internal.h +2
-0+/* ref_store_init flags */ +#define REF_STORE_READ (1 << 0)I asked [1] in reply to v5 whether
REF_STORE_READis really necessary but I don't think you replied. Surely a reference store that we can't read would be useless? Can't we just assume that anyref_storeis readable and drop this constant?
I deleted it then I realized many lines like these
files_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
would become
files_downcast(ref_store, 0, "read_raw_ref");
I think for newcomers, the former gives a better hint what the second argument is than a plain zero in the latter, so I'm inclined to keep it.
Signature · 1 line
Duy
Re: [PATCH v6 18/27] files-backend: replace submodule_allowed check in files_downcast()
Quoted 13 lines · Duy Nguyen
Quoted 7 lines · Michael Haggerty
refs/refs-internal.h struct ref_store; · line 485
Quoted 2 lines
refs/refs-internal.h +2
-0+/* ref_store_init flags */ +#define REF_STORE_READ (1 << 0)I asked [1] in reply to v5 whether
REF_STORE_READis really necessary but I don't think you replied. Surely a reference store that we can't read would be useless? Can't we just assume that anyref_storeis readable and drop this constant?I deleted it then I realized many lines like these
files_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
Quoted 7 lines
would become
files_downcast(ref_store, 0, "read_raw_ref");I think for newcomers, the former gives a better hint what the second argument is than a plain zero in the latter, so I'm inclined to keep it.
That's OK with me; I don't feel strongly about it.
Michael
PATCH v6 19/27 refs: rename get_ref_store() to get_submodule_ref_store() and make it public
In reply to Nguyễn Thái Ngọc DuyThis 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.
--- refs.c | 12 ++++++++---- refs.h | 11 +++++++++++ refs/refs-internal.h | 12 ------------ 3 files changed, 19 insertions(+), 16 deletions(-)
refs.c +8 -4
@@ -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)
@@ -1463,13 +1463,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 (); }
refs.h +11 -0
@@ -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 */
refs/refs-internal.h +0 -12
@@ -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,
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 20/27 refs: add new ref-store api
In reply to Nguyễn Thái Ngọc DuyThis 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.
--- refs.c | 251 ++++++++++++++++++++++++++++++++++++++------------- refs.h | 74 +++++++++++++++ refs/files-backend.c | 13 +-- refs/refs-internal.h | 31 +------ 4 files changed, 270 insertions(+), 99 deletions(-)
refs.c +186 -65
@@ -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_lifor_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, unsigif (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 ;
@@ -1509,27 +1569,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,
@@ -1540,19 +1615,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);
@@ -1560,43 +1633,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,
@@ -1606,11 +1720,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,
@@ -1621,16 +1734,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); +}
refs.h +74 -0
161 lines not on this page · raw message
refs/files-backend.c +7 -6
@@ -1314,7 +1314,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)) {
@@ -1623,7 +1623,8 @@ static int lock_raw_ref(struct files_ref_store *refs,* 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
@@ -2673,7 +2674,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; }
@@ -4057,9 +4058,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; }
refs/refs-internal.h +3 -28
@@ -112,28 +112,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, * because reflog file is one line per entry.
@@ -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 */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 21/27 refs: new transaction related ref-store api
In reply to Nguyễn Thái Ngọc DuyThe transaction struct now takes a ref store at creation and will operate on that ref store alone.
--- refs.c | 55 ++++++++++++++++++++++++++++++++++++++++------------ refs.h | 9 +++++++++ refs/refs-internal.h | 1 + 3 files changed, 53 insertions(+), 12 deletions(-)
refs.c +43 -12
@@ -630,16 +630,20 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1return 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;
@@ -1610,7 +1641,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); }
@@ -1729,7 +1760,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); }
refs.h +9 -0
@@ -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);
refs/refs-internal.h +1 -0
@@ -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;
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 22/27 files-backend: avoid ref api targetting main ref store
In reply to Nguyễn Thái Ngọc DuyA small step towards making files-backend works as a non-main ref store using the newly added store-aware API.
For the record, join and nm on refs.o and files-backend.o tell me that files-backend no longer uses functions that defaults to get_main_ref_store().
I'm not yet comfortable at the idea of removing files_assert_main_repository() (or converting REF_STORE_MAIN to REF_STORE_WRITE). More staring and testing is required before that can happen. Well, except peel_ref(). I'm pretty sure that function is safe.
--- refs/files-backend.c | 84 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 35 deletions(-)
refs/files-backend.c +49 -35
@@ -1830,8 +1830,6 @@ static int files_peel_ref(struct ref_store *ref_store,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;
@@ -1841,7 +1839,8 @@ static int files_peel_ref(struct ref_store *ref_store,return 0 ; } -if (read_ref_full (refname,RESOLVE_REF_READING , base, &flag)) +if (refs_read_ref_full (ref_store, refname, +RESOLVE_REF_READING , base, &flag))return -1 ;/*
@@ -2011,15 +2010,15 @@ static struct ref_iterator *files_ref_iterator_begin(* on success. On error, write an error message to err, set errno, and * return a negative value. */ -static int verify_lock (struct ref_lock *lock, +static int verify_lock (struct ref_store *ref_store,struct ref_lock *lock,const unsigned char *old_sha1,int mustexist,struct strbuf *err) {assert (err); -if (read_ref_full (lock->ref_name, - mustexist ?RESOLVE_REF_READING :0 , - lock->old_oid.hash,NULL )) { +if (refs_read_ref_full (ref_store, lock->ref_name, + mustexist ?RESOLVE_REF_READING :0 , + lock->old_oid.hash,NULL )) {if (old_sha1) {int save_errno = errno;strbuf_addf (err,"can't verify ref '%s'" , lock->ref_name);
@@ -2088,8 +2087,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, resolve_flags |=RESOLVE_REF_ALLOW_BAD_NAME ;files_refname_path (refs, &ref_file, refname); - resolved = !!resolve_ref_unsafe (refname, resolve_flags, - lock->old_oid.hash, type); + resolved = !!refs_resolve_ref_unsafe (&refs->base, + refname, resolve_flags, + lock->old_oid.hash, type);if (!resolved && errno ==EISDIR ) {/* * we are trying to lock foo but we used to
@@ -2106,8 +2106,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, refname); goto error_return; } - resolved = !!resolve_ref_unsafe (refname, resolve_flags, - lock->old_oid.hash, type); + resolved = !!refs_resolve_ref_unsafe (&refs->base, + refname, resolve_flags, + lock->old_oid.hash, type); }if (!resolved) { last_errno = errno;
@@ -2145,7 +2146,7 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, goto error_return; } -if (verify_lock (lock, old_sha1, mustexist, err)) { +if (verify_lock (&refs->base, lock, old_sha1, mustexist, err)) { last_errno = errno; goto error_return; }
@@ -2400,7 +2401,7 @@ static void try_remove_empty_parents(struct files_ref_store *refs, }/* make sure nobody touched the ref, and unlink */ -static void prune_ref (struct ref_to_prune *r) +static void prune_ref (struct files_ref_store *refs,struct ref_to_prune *r) {struct ref_transaction *transaction;struct strbuf err =STRBUF_INIT ;
@@ -2408,7 +2409,7 @@ static void prune_ref(struct ref_to_prune *r)if (check_refname_format (r->name,0 ))return ; - transaction =ref_transaction_begin (&err); + transaction =ref_store_transaction_begin (&refs->base, &err); if (!transaction || ref_transaction_delete(transaction, r->name, r->sha1, REF_ISPRUNING | REF_NODEREF, NULL, &err) ||
@@ -2422,10 +2423,10 @@ static void prune_ref(struct ref_to_prune *r)strbuf_release (&err); } -static void prune_refs (struct ref_to_prune *r) +static void prune_refs (struct files_ref_store *refs,struct ref_to_prune *r) {while (r) { -prune_ref (r); +prune_ref (refs, r); r = r->next; } }
@@ -2449,7 +2450,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)if (commit_packed_refs (refs))die_errno ("unable to overwrite old ref-pack file" ); -prune_refs (cbdata.ref_to_prune); +prune_refs (refs, cbdata.ref_to_prune);return 0 ; }
@@ -2541,7 +2542,7 @@ static int files_delete_refs(struct ref_store *ref_store,for (i =0 ; i < refnames->nr; i++) {const char *refname = refnames->items[i].string; -if (delete_ref (NULL , refname,NULL , flags)) +if (refs_delete_ref (&refs->base,NULL , refname,NULL , flags)) result |=error (_ ("could not remove reference %s" ), refname); }
@@ -2663,7 +2664,8 @@ static int files_rename_ref(struct ref_store *ref_store, goto out; } -if (!resolve_ref_unsafe (oldrefname,RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , +if (!refs_resolve_ref_unsafe (&refs->base, oldrefname, +RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , orig_sha1, &flag)) { ret =error ("refname %s not found" , oldrefname); goto out;
@@ -2685,7 +2687,8 @@ static int files_rename_ref(struct ref_store *ref_store, goto out; } -if (delete_ref (logmsg, oldrefname, orig_sha1,REF_NODEREF )) { +if (refs_delete_ref (&refs->base, logmsg, oldrefname, + orig_sha1,REF_NODEREF )) {error ("unable to delete old %s" , oldrefname); goto rollback; }
@@ -2697,9 +2700,11 @@ static int files_rename_ref(struct ref_store *ref_store,* the safety anyway; we want to delete the reference whatever * its current value. */ -if (!read_ref_full (newrefname,RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , - sha1,NULL ) && -delete_ref (NULL , newrefname,NULL ,REF_NODEREF )) { +if (!refs_read_ref_full (&refs->base, newrefname, +RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , + sha1,NULL ) && +refs_delete_ref (&refs->base,NULL , newrefname, +NULL ,REF_NODEREF )) {if (errno ==EISDIR ) {struct strbuf path =STRBUF_INIT ;int result;
@@ -3055,8 +3060,9 @@ static int commit_ref_update(struct files_ref_store *refs,int head_flag;const char *head_ref; - head_ref =resolve_ref_unsafe ("HEAD" ,RESOLVE_REF_READING , - head_sha1, &head_flag); + head_ref =refs_resolve_ref_unsafe (&refs->base,"HEAD" , +RESOLVE_REF_READING , + head_sha1, &head_flag);if (head_ref && (head_flag &REF_ISSYMREF ) && !strcmp (head_ref, lock->ref_name)) {struct strbuf log_err =STRBUF_INIT ;
@@ -3100,7 +3106,9 @@ static void update_symref_reflog(struct files_ref_store *refs, {struct strbuf err =STRBUF_INIT ;unsigned char new_sha1[20 ]; -if (logmsg && !read_ref (target, new_sha1) && +if (logmsg && + !refs_read_ref_full (&refs->base, target, +RESOLVE_REF_READING , new_sha1,NULL ) &&files_log_ref_write (refs, refname, lock->old_oid.hash, new_sha1, logmsg,0 , &err)) {error ("%s" , err.buf);
@@ -3405,6 +3413,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,struct files_reflog_iterator {struct ref_iterator base; +struct ref_store *ref_store;struct dir_iterator *dir_iterator;struct object_id oid; };
@@ -3426,8 +3435,9 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)if (ends_with (diter->basename,".lock" ))continue ; -if (read_ref_full (diter->relative_path,0 , - iter->oid.hash, &flags)) { +if (refs_read_ref_full (iter->ref_store, + diter->relative_path,0 , + iter->oid.hash, &flags)) {error ("bad ref for %s" , diter->path.buf);continue ; }
@@ -3481,6 +3491,7 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_stbase_ref_iterator_init (ref_iterator, &files_reflog_iterator_vtable);files_reflog_path (refs, &sb,NULL ); iter->dir_iterator =dir_iterator_begin (sb.buf); + iter->ref_store = ref_store;strbuf_release (&sb);return ref_iterator; }
@@ -3720,8 +3731,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,* the transaction, so we have to read it here * to record and possibly check old_sha1: */ -if (read_ref_full (referent.buf,0 , - lock->old_oid.hash,NULL )) { +if (refs_read_ref_full (&refs->base, + referent.buf,0 , + lock->old_oid.hash,NULL )) {if (update->flags &REF_HAVE_OLD ) { strbuf_addf(err, "cannot lock ref '%s': " "error reading reference",
@@ -3875,8 +3887,9 @@ static int files_transaction_commit(struct ref_store *ref_store,* head_ref within the transaction, then split_head_update() * arranges for the reflog of HEAD to be updated, too. */ - head_ref =resolve_refdup ("HEAD" ,RESOLVE_REF_NO_RECURSE , - head_oid.hash, &head_type); + head_ref =refs_resolve_refdup (ref_store,"HEAD" , +RESOLVE_REF_NO_RECURSE , + head_oid.hash, &head_type);if (head_ref && !(head_type &REF_ISSYMREF )) {free (head_ref);
@@ -4049,7 +4062,8 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,* so here we really only check that none of the references * that we are creating already exists. */ -if (for_each_rawref (ref_present, &affected_refnames)) +if (refs_for_each_rawref (&refs->base, ref_present, + &affected_refnames))die ("BUG: initial ref transaction called with existing refs" );for (i =0 ; i < transaction->nr; i++) {
@@ -4168,7 +4182,7 @@ static int files_reflog_expire(struct ref_store *ref_store,strbuf_release (&err);return -1 ; } -if (!reflog_exists (refname)) { +if (!refs_reflog_exists (ref_store, refname)) {unlock_ref (lock);return 0 ; }
@@ -4199,7 +4213,7 @@ static int files_reflog_expire(struct ref_store *ref_store, } (*prepare_fn)(refname, sha1, cb.policy_cb); -for_each_reflog_ent (refname, expire_reflog_ent, &cb); +refs_for_each_reflog_ent (ref_store, refname, expire_reflog_ent, &cb); (*cleanup_fn)(cb.policy_cb);if (!(flags &EXPIRE_REFLOGS_DRY_RUN )) {
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 23/27 refs: delete pack_refs() in favor of refs_pack_refs()
In reply to Nguyễn Thái Ngọc DuyIt only has one caller, not worth keeping just for convenience.
--- builtin/pack-refs.c | 2 +- refs.c | 5 ----- refs.h | 1 - 3 files changed, 1 insertion(+), 7 deletions(-)
builtin/pack-refs.c +1 -1
@@ -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); }
refs.c +0 -5
@@ -1605,11 +1605,6 @@ int refs_pack_refs(struct ref_store *refs, unsigned int flags)return refs->be->pack_refs (refs, flags); } -int pack_refs (unsigned int flags) -{ -return refs_pack_refs (get_main_ref_store (), flags); -} -int refs_peel_ref (struct ref_store *refs,const char *refname,unsigned char *sha1) {
refs.h +0 -1
@@ -297,7 +297,6 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt,* 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);/* * Flags controlling ref_transaction_update(), ref_transaction_create(), etc.
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 24/27 t/helper: add test-ref-store to test ref-store functions
In reply to Nguyễn Thái Ngọc Duy--- Makefile | 1 + t/helper/.gitignore | 1 + t/helper/test-ref-store.c (new) | 275 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 277 insertions(+) create mode 100644 t/helper/test-ref-store.c
Makefile +1 -0
@@ -622,6 +622,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
t/helper/.gitignore +1 -0
@@ -19,6 +19,7 @@ /test-path-utils /test-prio-queue /test-read-cache +/test-ref-store /test-regex /test-revision-walking /test-run-command
t/helper/test-ref-store.c new file +275 -0
275 lines not on this page · raw message
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v6 24/27] t/helper: add test-ref-store to test ref-store functions
t/helper/test-ref-store.c
Quoted 2 lines · Nguyễn Thái Ngọc Duy
t/helper/test-ref-store.c new file +0
-0
When nd/files-backend-git-dir is merged to 'next', the new tests in t1405/t1406 break. They need this on top (which should probably just be squashed into this commit when you re-roll).
-- >8 --
Subject: [PATCH] test-ref-store: setup git directory
Without setting up the git directory, we rely on the ".git" fallback in setup_git_env(). This will cause us to abort once b1ef400ee (setup_git_env: avoid blind fall-back to ".git", 2016-10-20) is merged.
--- t/helper/test-ref-store.c | 2 ++ 1 file changed, 2 insertions(+)
t/helper/test-ref-store.c +2 -0
@@ -261,6 +261,8 @@ int cmd_main(int argc, const char **argv)const char *func;struct command *cmd; +setup_git_directory (); + argv =get_store (argv +1 , &refs); func = *argv++;
Signature · 1 line
2.12.1.788.g3cf5b5ec6
Re: [PATCH v6 24/27] t/helper: add test-ref-store to test ref-store functions
Quoted 9 lines · Jeff King
t/helper/test-ref-store.c
Quoted 2 lines · Nguyễn Thái Ngọc Duy
t/helper/test-ref-store.c new file +0
-0When nd/files-backend-git-dir is merged to 'next', the new tests in t1405/t1406 break. They need this on top (which should probably just be squashed into this commit when you re-roll).
Quoted 7 lines
-- >8 --
Subject: [PATCH] test-ref-store: setup git directoryWithout setting up the git directory, we rely on the ".git" fallback in
setup_git_env(). This will cause us to abort onceb1ef400ee(setup_git_env: avoid blind fall-back to ".git", 2016-10-20) is merged.
After posting this, it occurred to me that "pu" should be showing the same failure, but it doesn't. The reason is that e9e167145 (worktree.c:
kill parse_ref() in favor of refs_resolve_ref_unsafe(), 2017-03-18) from nd/worktree-kill-parse-ref sneaks in the setup call.
We should move it back to the addition of test-ref-store, though, since nd/files-backend-git-dir may graduate separately.
-Peff
Re: [PATCH v6 24/27] t/helper: add test-ref-store to test ref-store functions
Quoted 19 lines · Jeff King
Quoted 9 lines · Jeff King
t/helper/test-ref-store.c
Quoted 2 lines · Nguyễn Thái Ngọc Duy
t/helper/test-ref-store.c new file +0
-0When nd/files-backend-git-dir is merged to 'next', the new tests in t1405/t1406 break. They need this on top (which should probably just be squashed into this commit when you re-roll).
Quoted 7 lines
-- >8 --
Subject: [PATCH] test-ref-store: setup git directoryWithout setting up the git directory, we rely on the ".git" fallback in
setup_git_env(). This will cause us to abort onceb1ef400ee(setup_git_env: avoid blind fall-back to ".git", 2016-10-20) is merged.
Quoted 7 lines
After posting this, it occurred to me that "pu" should be showing the same failure, but it doesn't. The reason is that
e9e167145(worktree.c:
killparse_ref()in favor ofrefs_resolve_ref_unsafe(), 2017-03-18) from nd/worktree-kill-parse-ref sneaks in the setup call.We should move it back to the addition of test-ref-store, though, since nd/files-backend-git-dir may graduate separately.
Right. I needed that setup_git_directory() for the third ref store. But now that I think about it, I need it for the first two as well because git_path() is always involved. Will fix (since it looks like files-backend-git-dir is not merged to next yet).
Signature · 1 line
Duy
PATCH v6 25/27 t1405: some basic tests on main ref store
In reply to Nguyễn Thái Ngọc Duy--- t/t1405-main-ref-store.sh (new +x) | 123 +++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100755 t/t1405-main-ref-store.sh
t/t1405-main-ref-store.sh new file +123 -0
@@ -0,0 +1,123 @@ +#!/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 '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
Signature · 1 line
2.11.0.157.gd943d85
PATCH v6 26/27 t1406: new tests for submodule ref store
In reply to Nguyễn Thái Ngọc Duy--- t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 t/t1406-submodule-ref-store.sh
t/t1406-submodule-ref-store.sh new file +95 -0
@@ -0,0 +1,95 @@ +#!/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 '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
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v6 26/27] t1406: new tests for submodule ref store
Quoted 22 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 t/t1406-submodule-ref-store.sht/t1406-submodule-ref-store.sh new file +10
-0@@ -0,0 +1,95 @@ +#!/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 &&
t/t1406-submodule-ref-store.sh line 20
Quoted 10 lines
t/t1406-submodule-ref-store.sh new file +10
-0+ ( + cd sub && + test_commit first && + git checkout -b new-master + ) +' + +test_expect_success 'pack_refs() not allowed' ' + test_must_fail $RUN pack-refs 3 +'
It's a little bit unfortunate but probably OK that this test and its analog in t1405 hard-code internal numerical constants. At least in t1405 the names of the constants appear in the test name, meaning that anybody changing the constants' values in the future will probably find the "3" in that file. Would you do the same here, please, or at least mention the constant names in a comment here?
Quoted 1 line
[...]
Michael
Re: [PATCH v6 26/27] t1406: new tests for submodule ref store
Quoted 31 lines · Michael Haggerty
Quoted 30 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 t/t1406-submodule-ref-store.sht/t1406-submodule-ref-store.sh new file +18
-0@@ -0,0 +1,95 @@ +#!/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' '
Quoted 8 lines
t/t1406-submodule-ref-store.sh line 20
Quoted 2 lines
t/t1406-submodule-ref-store.sh new file +2
-0+ test_must_fail $RUN pack-refs 3 +'It's a little bit unfortunate but probably OK that this test and its analog in t1405 hard-code internal numerical constants. At least in t1405 the names of the constants appear in the test name, meaning that anybody changing the constants' values in the future will probably find the "3" in that file.
I noticed that too, but was not motivated enough to do actual enum/define <-> string mapping in test-ref-store.
Quoted 2 lines
Would you do the same here, please, or at least
mention the constant names in a comment here?
Will do (and hopefully will make test-ref-store take names instead of numbers at a later point, or you'll get annoyed faster and do it ;-)
Signature · 1 line
Duy
PATCH v6 27/27 refs.h: add a note about sorting order of for_each_ref_*
In reply to Nguyễn Thái Ngọc Duy--- refs.h | 4 ++-- t/t1405-main-ref-store.sh | 6 ++++++ t/t1406-submodule-ref-store.sh | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-)
refs.h +2 -2
@@ -230,7 +230,7 @@ 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);
@@ -370,7 +370,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 +* 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);
t/t1405-main-ref-store.sh +6 -0
@@ -53,6 +53,12 @@ test_expect_success 'for_each_ref(refs/heads/)' ' 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 &&
t/t1406-submodule-ref-store.sh +6 -0
@@ -47,6 +47,12 @@ test_expect_success 'for_each_ref(refs/heads/)' ' 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 &&
Signature · 1 line
2.11.0.157.gd943d85
Quoted 10 lines · Nguyễn Thái Ngọc Duy
v6 should address all Micheal's comments in v5, except a few that I replied back. The interdiff looks a bit messy due to some new refactoring (05/27) in
files_rename_ref(), but it makes the final output easier to read.03/27 and 27/27 are also new patches that are not really necessary but nice to have.
The series is rebased on latest master and does not depend on any other topics, since they all have graduated to master.
Thanks for the new version of this patch series. I left a few optional comments, but nothing serious. With or without the suggested changes, I think it's ready to go. Thanks for working on this!
Michael
Quoted 5 lines · Michael Haggerty
Thanks for the new version of this patch series. I left a few optional comments, but nothing serious. With or without the suggested changes, I think it's ready to go. Thanks for working on this!
Reviewed-by Michael Haggerty <[email protected]>
Thanks for reviewing. Judging from the exchanges between you two, it appears that the final reroll would mostly be uncontroversial kind that we can finally merge down to 'next' and then to 'master' fairly quickly ;-)
Thanks, Duy, for working on this. The end-result looks much nicer.
v7 cover Remove submodule from files-backend.c
In reply to Nguyễn Thái Ngọc Duyv7 is mostly about style changes except the one bug in test-ref-store.c, missing setup_git_directory().
There's one new patch, 03/28, which maps to the "if (!refs)" deletion in the interdiff.
The one comment from v6 I haven't addressed in v7 is whether to delete REF_STORE_READ. But if it is deleted, I think I'm doing it in nd/worktree-kill-parse-ref, which is partly about cleanup refs code anyway, to avoid another re-roll in this series.
refs.c +6 -9
@@ -1523,18 +1523,15 @@ static struct ref_store *ref_store_init(const char *gitdir,struct ref_store *get_main_ref_store (void ) { -struct ref_store *refs; -if (main_ref_store)return main_ref_store; - refs =ref_store_init (get_git_dir (), - (REF_STORE_READ | -REF_STORE_WRITE | -REF_STORE_ODB | -REF_STORE_MAIN )); - main_ref_store = refs; -return refs; + 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; }/*
refs/files-backend.c +16 -18
@@ -1195,9 +1195,9 @@ static void files_reflog_path(struct files_ref_store *refs, } } -static void files_refname_path (struct files_ref_store *refs, -struct strbuf *sb, -const char *refname) +static void files_ref_path (struct files_ref_store *refs, +struct strbuf *sb, +const char *refname) {switch (ref_type (refname)) {case REF_TYPE_PER_WORKTREE :
@@ -1283,7 +1283,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)struct strbuf path =STRBUF_INIT ;size_t path_baselen; -files_refname_path (refs, &path, dirname); +files_ref_path (refs, &path, dirname); path_baselen = path.len; d =opendir (path.buf);
@@ -1420,7 +1420,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, *type =0 ;strbuf_reset (&sb_path); -files_refname_path (refs, &sb_path, refname); +files_ref_path (refs, &sb_path, refname); path = sb_path.buf;
@@ -1608,7 +1608,7 @@ static int lock_raw_ref(struct files_ref_store *refs, *lock_p = lock =xcalloc (1 ,sizeof (*lock)); lock->ref_name =xstrdup (refname); -files_refname_path (refs, &ref_file, refname); +files_ref_path (refs, &ref_file, refname); retry:switch (safe_create_leading_directories (ref_file.buf)) {
@@ -1949,8 +1949,6 @@ static struct ref_iterator *files_ref_iterator_begin( refs =files_downcast (ref_store,REF_STORE_READ | (ref_paranoia ?0 :REF_STORE_ODB ),"ref_iterator_begin" ); -if (!refs) -return empty_ref_iterator_begin (); iter =xcalloc (1 ,sizeof (*iter)); ref_iterator = &iter->base;
@@ -2086,7 +2084,7 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,if (flags &REF_DELETING ) resolve_flags |=RESOLVE_REF_ALLOW_BAD_NAME ; -files_refname_path (refs, &ref_file, refname); +files_ref_path (refs, &ref_file, refname); resolved = !!refs_resolve_ref_unsafe (&refs->base, refname, resolve_flags, lock->old_oid.hash, type);
@@ -2387,7 +2385,7 @@ static void try_remove_empty_parents(struct files_ref_store *refs,strbuf_setlen (&buf, q - buf.buf);strbuf_reset (&sb); -files_refname_path (refs, &sb, buf.buf); +files_ref_path (refs, &sb, buf.buf);if ((flags &REMOVE_EMPTY_PARENTS_REF ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REF ;
@@ -2709,7 +2707,7 @@ static int files_rename_ref(struct ref_store *ref_store,struct strbuf path =STRBUF_INIT ;int result; -files_refname_path (refs, &path, newrefname); +files_ref_path (refs, &path, newrefname); result =remove_empty_directories (&path);strbuf_release (&path);
@@ -2935,10 +2933,10 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,return 0 ; } -int files_log_ref_write (struct files_ref_store *refs, -const char *refname,const unsigned char *old_sha1, -const unsigned char *new_sha1,const char *msg, -int flags,struct strbuf *err) +static int files_log_ref_write (struct files_ref_store *refs, +const char *refname,const unsigned char *old_sha1, +const unsigned char *new_sha1,const char *msg, +int flags,struct strbuf *err) {int logfd, result;
@@ -3957,7 +3955,7 @@ static int files_transaction_commit(struct ref_store *ref_store, update->type & REF_ISSYMREF) {/* It is a loose reference. */ strbuf_reset (&sb); -files_refname_path (refs, &sb, lock->ref_name); +files_ref_path (refs, &sb, lock->ref_name);if (unlink_or_msg (sb.buf, err)) { ret =TRANSACTION_GENERIC_ERROR ; goto cleanup;
@@ -4266,11 +4264,11 @@ static int files_init_db(struct ref_store *ref_store, struct strbuf *err)/* * Create .git/refs/{heads,tags} */ -files_refname_path (refs, &sb,"refs/heads" ); +files_ref_path (refs, &sb,"refs/heads" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb); -files_refname_path (refs, &sb,"refs/tags" ); +files_ref_path (refs, &sb,"refs/tags" );safe_create_dir (sb.buf,1 );strbuf_release (&sb);
submodule.c +0 -5
@@ -1597,11 +1597,6 @@ const char *get_superproject_working_tree(void)return ret; } -/* -* 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) {const struct submodule *sub;
submodule.h +5 -0
@@ -81,6 +81,11 @@ extern int push_unpushed_submodules(struct sha1_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);/*
t/helper/test-ref-store.c +2 -0
@@ -261,6 +261,8 @@ int cmd_main(int argc, const char **argv)const char *func;struct command *cmd; +setup_git_directory (); + argv =get_store (argv +1 , &refs); func = *argv++;
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 1/28 refs.h: add forward declaration for structs used in this file
--- refs.h | 4 ++++ 1 file changed, 4 insertions(+)
refs.h +4 -0
@@ -1,6 +1,10 @@#ifndef REFS_H #define REFS_H +struct object_id ; +struct strbuf ; +struct string_list ; +/* * Resolve a reference, recursively following symbolic refererences. *
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 2/28 files-backend: make files_log_ref_write() static
In reply to Nguyễn Thái Ngọc DuyCreated in 5f3c3a4e6f (files_log_ref_write: new function - 2015-11-10) but probably never used outside refs-internal.c
--- refs/files-backend.c | 9 ++++++--- refs/refs-internal.h | 4 ---- 2 files changed, 6 insertions(+), 7 deletions(-)
refs/files-backend.c +6 -3
@@ -165,6 +165,9 @@ static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, const char *dirname, size_t len, int incomplete);static void add_entry_to_dir (struct ref_dir *dir,struct ref_entry *entry); +static 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);static struct ref_dir *get_ref_dir (struct ref_entry *entry) {
@@ -2831,9 +2834,9 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,return 0 ; } -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) +static 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) {int logfd, result;
refs/refs-internal.h +0 -4
@@ -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
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 3/28 files-backend.c: delete dead code in files_ref_iterator_begin()
In reply to Nguyễn Thái Ngọc DuyIt's not in the diff context, but files_downcast() is called before this check. If "refs" is NULL, we would have segfaulted before reaching the check here. And we should never see NULL refs in backend code (frontend should have caught it).
--- refs/files-backend.c | 3 --- 1 file changed, 3 deletions(-)
refs/files-backend.c +0 -3
@@ -1897,9 +1897,6 @@ static struct ref_iterator *files_ref_iterator_begin(struct files_ref_iterator *iter;struct ref_iterator *ref_iterator; -if (!refs) -return empty_ref_iterator_begin (); -if (ref_paranoia <0 ) ref_paranoia =git_env_bool ("GIT_REF_PARANOIA" ,0 );if (ref_paranoia)
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 4/28 files-backend: delete dead code in files_init_db()
In reply to Nguyễn Thái Ngọc Duysafe_create_dir() can do adjust_shared_perm() internally, and init-db has always created 'refs' in shared mode since the beginning, af6e277c5e (git-init-db: initialize shared repositories with --shared - 2005-12-22). So this code looks like extra adjust_shared_perm calls are unnecessary.
And they are. But let's see why there are here in the first place.
This code was added in 6fb5acfd8f (refs: add methods to init refs db - 2016-09-04). From the diff alone this looks like a faithful refactored code from init-db.c. But there is a subtle difference:
Between the safe_create_dir() block and adjust_shared_perm() block in the old init-db.c, we may copy/recreate directories from the repo template. So it makes sense that adjust_shared_perm() is re-executed then to fix potential permission screwups.
After 6fb5acfd8f, refs dirs are created after template is copied. Nobody will change directory permission again. So the extra adjust_shared_perm() is redudant. Delete them.
--- refs/files-backend.c | 4 ---- 1 file changed, 4 deletions(-)
refs/files-backend.c +0 -4
@@ -4107,10 +4107,6 @@ static int files_init_db(struct ref_store *ref_store, struct strbuf *err)*/ safe_create_dir (git_path ("refs/heads" ),1 );safe_create_dir (git_path ("refs/tags" ),1 ); -if (get_shared_repository ()) { -adjust_shared_perm (git_path ("refs/heads" )); -adjust_shared_perm (git_path ("refs/tags" )); - }return 0 ; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 5/28 files-backend: add and use files_packed_refs_path()
In reply to Nguyễn Thái Ngọc DuyKeep repo-related path handling in one place. This will make it easier to add submodule/multiworktree support later.
--- refs/files-backend.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)
refs/files-backend.c +18 -11
@@ -923,6 +923,8 @@ struct files_ref_store {*/ const char *submodule; +char *packed_refs_path; +struct ref_entry *loose;struct packed_ref_cache *packed; };
@@ -985,7 +987,14 @@ static struct ref_store *files_ref_store_create(const char *submodule)base_ref_store_init (ref_store, &refs_be_files); - refs->submodule =xstrdup_or_null (submodule); +if (submodule) { + refs->submodule =xstrdup (submodule); + refs->packed_refs_path =git_pathdup_submodule ( + refs->submodule,"packed-refs" ); +return ref_store; + } + + refs->packed_refs_path =git_pathdup ("packed-refs" );return ref_store; }
@@ -1153,19 +1162,18 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)strbuf_release (&line); } +static const char *files_packed_refs_path (struct files_ref_store *refs) +{ +return refs->packed_refs_path; +} +/* * Get the packed_ref_cache for the specified files_ref_store, * creating it if necessary. */ static struct packed_ref_cache *get_packed_ref_cache (struct files_ref_store *refs) { -char *packed_refs_file; - -if (refs->submodule) - packed_refs_file =git_pathdup_submodule (refs->submodule, -"packed-refs" ); -else - packed_refs_file =git_pathdup ("packed-refs" ); +const char *packed_refs_file =files_packed_refs_path (refs);if (refs->packed && !stat_validity_check (&refs->packed->validity, packed_refs_file))
@@ -1184,7 +1192,6 @@ static struct packed_ref_cache *get_packed_ref_cache(struct files_ref_store *reffclose (f); } } -free (packed_refs_file);return refs->packed; }
@@ -2157,7 +2164,7 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) }if (hold_lock_file_for_update_timeout ( - &packlock,git_path ("packed-refs" ), + &packlock,files_packed_refs_path (refs), flags, timeout_value) <0 )return -1 ;/*
@@ -2423,7 +2430,7 @@ static int repack_without_refs(struct files_ref_store *refs,return 0 ;/* no refname exists in packed refs */ if (lock_packed_refs (refs,0 )) { -unable_to_lock_message (git_path ("packed-refs" ), errno, err); +unable_to_lock_message (files_packed_refs_path (refs), errno, err);return -1 ; } packed =get_packed_refs (refs);
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 6/28 files-backend: make sure files_rename_ref() always reach the end
In reply to Nguyễn Thái Ngọc DuyThis is a no-op patch. It prepares the function so that we can release resources (to be added later in this function) before we return.
--- refs/files-backend.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-)
refs/files-backend.c +28 -14
@@ -2585,23 +2585,34 @@ static int files_rename_ref(struct ref_store *ref_store,struct stat loginfo;int log = !lstat (git_path ("logs/%s" , oldrefname), &loginfo);struct strbuf err =STRBUF_INIT ; +int ret; -if (log &&S_ISLNK (loginfo.st_mode)) -return error ("reflog for %s is a symlink" , oldrefname); +if (log &&S_ISLNK (loginfo.st_mode)) { + ret =error ("reflog for %s is a symlink" , oldrefname); + goto out; + }if (!resolve_ref_unsafe (oldrefname,RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , - orig_sha1, &flag)) -return error ("refname %s not found" , oldrefname); + orig_sha1, &flag)) { + ret =error ("refname %s not found" , oldrefname); + goto out; + } -if (flag &REF_ISSYMREF ) -return error ("refname %s is a symbolic ref, renaming it is not supported" , - oldrefname); -if (!rename_ref_available (oldrefname, newrefname)) -return 1 ; +if (flag &REF_ISSYMREF ) { + ret =error ("refname %s is a symbolic ref, renaming it is not supported" , + oldrefname); + goto out; + } +if (!rename_ref_available (oldrefname, newrefname)) { + ret =1 ; + goto out; + } -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) -return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , - oldrefname,strerror (errno)); +if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) { + ret =error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , + oldrefname,strerror (errno)); + goto out; + }if (delete_ref (logmsg, oldrefname, orig_sha1,REF_NODEREF )) {error ("unable to delete old %s" , oldrefname);
@@ -2657,7 +2668,8 @@ static int files_rename_ref(struct ref_store *ref_store, goto rollback; } -return 0 ; + ret =0 ; + goto out; rollback: lock = lock_ref_sha1_basic(refs, oldrefname, NULL, NULL, NULL,
@@ -2686,7 +2698,9 @@ static int files_rename_ref(struct ref_store *ref_store,error ("unable to restore logfile %s from " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); -return 1 ; + ret =1 ; + out: +return ret; }static int close_ref (struct ref_lock *lock)
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 7/28 files-backend: convert git_path() to strbuf_git_path()
In reply to Nguyễn Thái Ngọc Duygit_path() and friends are going to be killed in files-backend.c in near future. And because there's a risk with overwriting buffer in git_path(), let's convert them all to strbuf_git_path(). We'll have easier time killing/converting strbuf_git_path() then because we won't have to worry about memory management again.
--- refs/files-backend.c | 130 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 97 insertions(+), 33 deletions(-)
refs/files-backend.c +97 -33
@@ -2316,6 +2316,7 @@ enum {static void try_remove_empty_parents (const char *refname,unsigned int flags) {struct strbuf buf =STRBUF_INIT ; +struct strbuf sb =STRBUF_INIT ;char *p, *q;int i;
@@ -2337,14 +2338,19 @@ static void try_remove_empty_parents(const char *refname, unsigned int flags)if (q == p)break ;strbuf_setlen (&buf, q - buf.buf); -if ((flags &REMOVE_EMPTY_PARENTS_REF ) && -rmdir (git_path ("%s" , buf.buf))) + +strbuf_reset (&sb); +strbuf_git_path (&sb,"%s" , buf.buf); +if ((flags &REMOVE_EMPTY_PARENTS_REF ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REF ; -if ((flags &REMOVE_EMPTY_PARENTS_REFLOG ) && -rmdir (git_path ("logs/%s" , buf.buf))) + +strbuf_reset (&sb); +strbuf_git_path (&sb,"logs/%s" , buf.buf); +if ((flags &REMOVE_EMPTY_PARENTS_REFLOG ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REFLOG ; }strbuf_release (&buf); +strbuf_release (&sb); }/* make sure nobody touched the ref, and unlink */
@@ -2506,11 +2512,16 @@ static int files_delete_refs(struct ref_store *ref_store,*/ #define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log" -static int rename_tmp_log_callback (const char *path,void *cb) +struct rename_cb { +const char *tmp_renamed_log; +int true_errno; +}; + +static int rename_tmp_log_callback (const char *path,void *cb_data) { -int *true_errno = cb; +struct rename_cb *cb = cb_data; -if (rename (git_path (TMP_RENAMED_LOG ), path)) { +if (rename (cb->tmp_renamed_log, path)) {/* * rename(a, b) when b is an existing directory ought * to result in ISDIR, but Solaris 5.8 gives ENOTDIR.
@@ -2518,7 +2529,7 @@ static int rename_tmp_log_callback(const char *path, void *cb)* but report EISDIR to raceproof_create_file() so * that it knows to retry. */ - *true_errno = errno; + cb->true_errno = errno;if (errno ==ENOTDIR ) errno =EISDIR ;return -1 ;
@@ -2529,20 +2540,26 @@ static int rename_tmp_log_callback(const char *path, void *cb)static int rename_tmp_log (const char *newrefname) { -char *path =git_pathdup ("logs/%s" , newrefname); -int ret, true_errno; +struct strbuf path =STRBUF_INIT ; +struct strbuf tmp =STRBUF_INIT ; +struct rename_cb cb; +int ret; - ret =raceproof_create_file (path, rename_tmp_log_callback, &true_errno); +strbuf_git_path (&path,"logs/%s" , newrefname); +strbuf_git_path (&tmp,TMP_RENAMED_LOG ); + cb.tmp_renamed_log = tmp.buf; + ret =raceproof_create_file (path.buf, rename_tmp_log_callback, &cb);if (ret) {if (errno ==EISDIR ) -error ("directory not empty: %s" , path); +error ("directory not empty: %s" , path.buf);else error ("unable to move logfile %s to %s: %s" , -git_path (TMP_RENAMED_LOG ), path, -strerror (true_errno)); + tmp.buf, path.buf, +strerror (cb.true_errno)); } -free (path); +strbuf_release (&path); +strbuf_release (&tmp);return ret; }
@@ -2583,10 +2600,17 @@ static int files_rename_ref(struct ref_store *ref_store,int flag =0 , logmoved =0 ;struct ref_lock *lock;struct stat loginfo; -int log = !lstat (git_path ("logs/%s" , oldrefname), &loginfo); +struct strbuf sb_oldref =STRBUF_INIT ; +struct strbuf sb_newref =STRBUF_INIT ; +struct strbuf tmp_renamed_log =STRBUF_INIT ; +int log, ret;struct strbuf err =STRBUF_INIT ; -int ret; +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +strbuf_git_path (&sb_newref,"logs/%s" , newrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + + log = !lstat (sb_oldref.buf, &loginfo);if (log &&S_ISLNK (loginfo.st_mode)) { ret =error ("reflog for %s is a symlink" , oldrefname); goto out;
@@ -2608,7 +2632,7 @@ static int files_rename_ref(struct ref_store *ref_store, goto out; } -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) { +if (log &&rename (sb_oldref.buf, tmp_renamed_log.buf)) { ret =error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); goto out;
@@ -2690,16 +2714,19 @@ static int files_rename_ref(struct ref_store *ref_store, log_all_ref_updates = flag; rollbacklog: -if (logmoved &&rename (git_path ("logs/%s" , newrefname),git_path ("logs/%s" , oldrefname))) +if (logmoved &&rename (sb_newref.buf, sb_oldref.buf))error ("unable to restore logfile %s from %s: %s" , oldrefname, newrefname,strerror (errno));if (!logmoved && log && -rename (git_path (TMP_RENAMED_LOG ),git_path ("logs/%s" , oldrefname))) +rename (tmp_renamed_log.buf, sb_oldref.buf))error ("unable to restore logfile %s from " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); - ret =1 ; out: +strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log); +return ret; }
@@ -2872,18 +2899,24 @@ static int files_log_ref_write(const char *refname, const unsigned char *old_sha result =log_ref_write_fd (logfd, old_sha1, new_sha1,git_committer_info (0 ), msg);if (result) { +struct strbuf sb =STRBUF_INIT ;int save_errno = errno; +strbuf_git_path (&sb,"logs/%s" , refname);strbuf_addf (err,"unable to append to '%s': %s" , -git_path ("logs/%s" , refname),strerror (save_errno)); + sb.buf,strerror (save_errno)); +strbuf_release (&sb);close (logfd);return -1 ; }if (close (logfd)) { +struct strbuf sb =STRBUF_INIT ;int save_errno = errno; +strbuf_git_path (&sb,"logs/%s" , refname);strbuf_addf (err,"unable to append to '%s': %s" , -git_path ("logs/%s" , refname),strerror (save_errno)); + sb.buf,strerror (save_errno)); +strbuf_release (&sb);return -1 ; }return 0 ;
@@ -3103,22 +3136,32 @@ int set_worktree_head_symref(const char *gitdir, const char *target, const charstatic int files_reflog_exists (struct ref_store *ref_store,const char *refname) { +struct strbuf sb =STRBUF_INIT ;struct stat st; +int ret;/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"reflog_exists" ); -return !lstat (git_path ("logs/%s" , refname), &st) && -S_ISREG (st.st_mode); +strbuf_git_path (&sb,"logs/%s" , refname); + ret = !lstat (sb.buf, &st) &&S_ISREG (st.st_mode); +strbuf_release (&sb); +return ret; }static int files_delete_reflog (struct ref_store *ref_store,const char *refname) { +struct strbuf sb =STRBUF_INIT ; +int ret; +/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"delete_reflog" ); -return remove_path (git_path ("logs/%s" , refname)); +strbuf_git_path (&sb,"logs/%s" , refname); + ret =remove_path (sb.buf); +strbuf_release (&sb); +return ret; }static int show_one_reflog_ent (struct strbuf *sb,each_reflog_ent_fn fn,void *cb_data)
@@ -3174,7 +3217,9 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"for_each_reflog_ent_reverse" ); - logfp =fopen (git_path ("logs/%s" , refname),"r" ); +strbuf_git_path (&sb,"logs/%s" , refname); + logfp =fopen (sb.buf,"r" ); +strbuf_release (&sb);if (!logfp)return -1 ;
@@ -3280,7 +3325,9 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"for_each_reflog_ent" ); - logfp =fopen (git_path ("logs/%s" , refname),"r" ); +strbuf_git_path (&sb,"logs/%s" , refname); + logfp =fopen (sb.buf,"r" ); +strbuf_release (&sb);if (!logfp)return -1 ;
@@ -3362,12 +3409,15 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st {struct files_reflog_iterator *iter =xcalloc (1 ,sizeof (*iter));struct ref_iterator *ref_iterator = &iter->base; +struct strbuf sb =STRBUF_INIT ;/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"reflog_iterator_begin" );base_ref_iterator_init (ref_iterator, &files_reflog_iterator_vtable); - iter->dir_iterator =dir_iterator_begin (git_path ("logs" )); +strbuf_git_path (&sb,"logs" ); + iter->dir_iterator =dir_iterator_begin (sb.buf); +strbuf_release (&sb);return ref_iterator; }
@@ -3705,6 +3755,7 @@ static int files_transaction_commit(struct ref_store *ref_store,char *head_ref =NULL ;int head_type;struct object_id head_oid; +struct strbuf sb =STRBUF_INIT ;assert (err);
@@ -3826,7 +3877,9 @@ static int files_transaction_commit(struct ref_store *ref_store,if (!(update->type &REF_ISPACKED ) || update->type &REF_ISSYMREF ) {/* It is a loose reference. */ -if (unlink_or_msg (git_path ("%s" , lock->ref_name), err)) { +strbuf_reset (&sb); +strbuf_git_path (&sb,"%s" , lock->ref_name); +if (unlink_or_msg (sb.buf, err)) { ret =TRANSACTION_GENERIC_ERROR ; goto cleanup; }
@@ -3846,7 +3899,9 @@ static int files_transaction_commit(struct ref_store *ref_store,/* Delete the reflogs of any references that were deleted: */ for_each_string_list_item (ref_to_delete, &refs_to_delete) { -if (!unlink_or_warn (git_path ("logs/%s" , ref_to_delete->string))) +strbuf_reset (&sb); +strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +if (!unlink_or_warn (sb.buf))try_remove_empty_parents (ref_to_delete->string,REMOVE_EMPTY_PARENTS_REFLOG ); }
@@ -3854,6 +3909,7 @@ static int files_transaction_commit(struct ref_store *ref_store,clear_loose_ref_cache (refs); cleanup: +strbuf_release (&sb); transaction->state =REF_TRANSACTION_CLOSED ;for (i =0 ; i < transaction->nr; i++) {
@@ -4120,14 +4176,22 @@ static int files_reflog_expire(struct ref_store *ref_store,static int files_init_db (struct ref_store *ref_store,struct strbuf *err) { +struct strbuf sb =STRBUF_INIT ; +/* Check validity (but we don't need the result): */ files_downcast (ref_store,0 ,"init_db" );/* * Create .git/refs/{heads,tags} */ -safe_create_dir (git_path ("refs/heads" ),1 ); -safe_create_dir (git_path ("refs/tags" ),1 ); +strbuf_git_path (&sb,"refs/heads" ); +safe_create_dir (sb.buf,1 ); + +strbuf_reset (&sb); +strbuf_git_path (&sb,"refs/tags" ); +safe_create_dir (sb.buf,1 ); + +strbuf_release (&sb);return 0 ; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 8/28 files-backend: move "logs/" out of TMP_RENAMED_LOG
In reply to Nguyễn Thái Ngọc DuyThis makes reflog path building consistent, always in the form of
strbuf_git_path(sb, "logs/%s", refname);
It reduces the mental workload a bit in the next patch when that function call is converted.
--- refs/files-backend.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
refs/files-backend.c +5 -5
@@ -2510,7 +2510,7 @@ static int files_delete_refs(struct ref_store *ref_store,* IOW, to avoid cross device rename errors, the temporary renamed log must * live into logs/refs. */ -#define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log" +#define TMP_RENAMED_LOG "refs/.tmp-renamed-log"struct rename_cb {const char *tmp_renamed_log;
@@ -2546,7 +2546,7 @@ static int rename_tmp_log(const char *newrefname)int ret;strbuf_git_path (&path,"logs/%s" , newrefname); -strbuf_git_path (&tmp,TMP_RENAMED_LOG ); +strbuf_git_path (&tmp,"logs/%s" ,TMP_RENAMED_LOG ); cb.tmp_renamed_log = tmp.buf; ret =raceproof_create_file (path.buf, rename_tmp_log_callback, &cb);if (ret) {
@@ -2608,7 +2608,7 @@ static int files_rename_ref(struct ref_store *ref_store,strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname);strbuf_git_path (&sb_newref,"logs/%s" , newrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG ); log = !lstat (sb_oldref.buf, &loginfo);if (log &&S_ISLNK (loginfo.st_mode)) {
@@ -2633,7 +2633,7 @@ static int files_rename_ref(struct ref_store *ref_store, }if (log &&rename (sb_oldref.buf, tmp_renamed_log.buf)) { - ret =error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , + ret =error ("unable to move logfile logs/%s to logs/" TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); goto out; }
@@ -2719,7 +2719,7 @@ static int files_rename_ref(struct ref_store *ref_store, oldrefname, newrefname, strerror(errno));if (!logmoved && log &&rename (tmp_renamed_log.buf, sb_oldref.buf)) -error ("unable to restore logfile %s from " TMP_RENAMED_LOG ": %s" , +error ("unable to restore logfile %s from logs/" TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); ret =1 ; out:
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 9/28 files-backend: add and use files_reflog_path()
In reply to Nguyễn Thái Ngọc DuyKeep repo-related path handling in one place. This will make it easier to add submodule/multiworktree support later.
--- refs/files-backend.c | 142 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 56 deletions(-)
refs/files-backend.c +86 -56
@@ -165,7 +165,8 @@ static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, const char *dirname, size_t len, int incomplete);static void add_entry_to_dir (struct ref_dir *dir,struct ref_entry *entry); -static int files_log_ref_write (const char *refname,const unsigned char *old_sha1, +static int files_log_ref_write (struct files_ref_store *refs, +const char *refname,const unsigned char *old_sha1,const unsigned char *new_sha1,const char *msg,int flags,struct strbuf *err);
@@ -1167,6 +1168,18 @@ static const char *files_packed_refs_path(struct files_ref_store *refs)return refs->packed_refs_path; } +static void files_reflog_path (struct files_ref_store *refs, +struct strbuf *sb, +const char *refname) +{ +if (!refname) { +strbuf_git_path (sb,"logs" ); +return ; + } + +strbuf_git_path (sb,"logs/%s" , refname); +} +/* * Get the packed_ref_cache for the specified files_ref_store, * creating it if necessary.
@@ -2313,7 +2326,9 @@ enum {* subdirs. flags is a combination of REMOVE_EMPTY_PARENTS_REF and/or * REMOVE_EMPTY_PARENTS_REFLOG. */ -static void try_remove_empty_parents (const char *refname,unsigned int flags) +static void try_remove_empty_parents (struct files_ref_store *refs, +const char *refname, +unsigned int flags) {struct strbuf buf =STRBUF_INIT ;struct strbuf sb =STRBUF_INIT ;
@@ -2345,7 +2360,7 @@ static void try_remove_empty_parents(const char *refname, unsigned int flags) flags &= ~REMOVE_EMPTY_PARENTS_REF ;strbuf_reset (&sb); -strbuf_git_path (&sb,"logs/%s" , buf.buf); +files_reflog_path (refs, &sb, buf.buf);if ((flags &REMOVE_EMPTY_PARENTS_REFLOG ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REFLOG ; }
@@ -2538,15 +2553,15 @@ static int rename_tmp_log_callback(const char *path, void *cb_data) } } -static int rename_tmp_log (const char *newrefname) +static int rename_tmp_log (struct files_ref_store *refs,const char *newrefname) {struct strbuf path =STRBUF_INIT ;struct strbuf tmp =STRBUF_INIT ;struct rename_cb cb;int ret; -strbuf_git_path (&path,"logs/%s" , newrefname); -strbuf_git_path (&tmp,"logs/%s" ,TMP_RENAMED_LOG ); +files_reflog_path (refs, &path, newrefname); +files_reflog_path (refs, &tmp,TMP_RENAMED_LOG ); cb.tmp_renamed_log = tmp.buf; ret =raceproof_create_file (path.buf, rename_tmp_log_callback, &cb);if (ret) {
@@ -2606,9 +2621,9 @@ static int files_rename_ref(struct ref_store *ref_store,int log, ret;struct strbuf err =STRBUF_INIT ; -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&sb_newref,"logs/%s" , newrefname); -strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG ); +files_reflog_path (refs, &sb_oldref, oldrefname); +files_reflog_path (refs, &sb_newref, newrefname); +files_reflog_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); log = !lstat (sb_oldref.buf, &loginfo);if (log &&S_ISLNK (loginfo.st_mode)) {
@@ -2671,7 +2686,7 @@ static int files_rename_ref(struct ref_store *ref_store, } } -if (log &&rename_tmp_log (newrefname)) +if (log &&rename_tmp_log (refs, newrefname)) goto rollback; logmoved = log;
@@ -2786,10 +2801,15 @@ static int open_or_create_logfile(const char *path, void *cb)* set *logfd to -1. On failure, fill in *err, set *logfd to -1, and * return -1. */ -static int log_ref_setup (const char *refname,int force_create, +static int log_ref_setup (struct files_ref_store *refs, +const char *refname,int force_create,int *logfd,struct strbuf *err) { -char *logfile =git_pathdup ("logs/%s" , refname); +struct strbuf logfile_sb =STRBUF_INIT ; +char *logfile; + +files_reflog_path (refs, &logfile_sb, refname); + logfile =strbuf_detach (&logfile_sb,NULL );if (force_create ||should_autocreate_reflog (refname)) {if (raceproof_create_file (logfile, open_or_create_logfile, logfd)) {
@@ -2839,12 +2859,11 @@ static int files_create_reflog(struct ref_store *ref_store, const char *refname, int force_create, struct strbuf *err) { + struct files_ref_store *refs = +files_downcast (ref_store,0 ,"create_reflog" );int fd; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"create_reflog" ); - -if (log_ref_setup (refname, force_create, &fd, err)) +if (log_ref_setup (refs, refname, force_create, &fd, err))return -1 ;if (fd >=0 )
@@ -2879,7 +2898,8 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,return 0 ; } -static int files_log_ref_write (const char *refname,const unsigned char *old_sha1, +static int files_log_ref_write (struct files_ref_store *refs, +const char *refname,const unsigned char *old_sha1,const unsigned char *new_sha1,const char *msg,int flags,struct strbuf *err) {
@@ -2888,7 +2908,8 @@ static int files_log_ref_write(const char *refname, const unsigned char *old_shaif (log_all_ref_updates ==LOG_REFS_UNSET ) log_all_ref_updates =is_bare_repository () ?LOG_REFS_NONE :LOG_REFS_NORMAL ; - result =log_ref_setup (refname, flags &REF_FORCE_CREATE_REFLOG , + result =log_ref_setup (refs, refname, + flags &REF_FORCE_CREATE_REFLOG , &logfd, err);if (result)
@@ -2902,7 +2923,7 @@ static int files_log_ref_write(const char *refname, const unsigned char *old_shastruct strbuf sb =STRBUF_INIT ;int save_errno = errno; -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname);strbuf_addf (err,"unable to append to '%s': %s" , sb.buf,strerror (save_errno));strbuf_release (&sb);
@@ -2913,7 +2934,7 @@ static int files_log_ref_write(const char *refname, const unsigned char *old_shastruct strbuf sb =STRBUF_INIT ;int save_errno = errno; -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname);strbuf_addf (err,"unable to append to '%s': %s" , sb.buf,strerror (save_errno));strbuf_release (&sb);
@@ -2974,7 +2995,8 @@ static int commit_ref_update(struct files_ref_store *refs,files_assert_main_repository (refs,"commit_ref_update" );clear_loose_ref_cache (refs); -if (files_log_ref_write (lock->ref_name, lock->old_oid.hash, sha1, +if (files_log_ref_write (refs, lock->ref_name, + lock->old_oid.hash, sha1, logmsg,0 , err)) {char *old_msg =strbuf_detach (err,NULL ); strbuf_addf(err, "cannot update the ref '%s': %s",
@@ -3006,8 +3028,9 @@ static int commit_ref_update(struct files_ref_store *refs,if (head_ref && (head_flag &REF_ISSYMREF ) && !strcmp (head_ref, lock->ref_name)) {struct strbuf log_err =STRBUF_INIT ; -if (files_log_ref_write ("HEAD" , lock->old_oid.hash, sha1, - logmsg,0 , &log_err)) { +if (files_log_ref_write (refs,"HEAD" , + lock->old_oid.hash, sha1, + logmsg,0 , &log_err)) {error ("%s" , log_err.buf);strbuf_release (&log_err); }
@@ -3039,24 +3062,26 @@ static int create_ref_symlink(struct ref_lock *lock, const char *target)return ret; } -static void update_symref_reflog (struct ref_lock *lock,const char *refname, +static void update_symref_reflog (struct files_ref_store *refs, +struct ref_lock *lock,const char *refname,const char *target,const char *logmsg) {struct strbuf err =STRBUF_INIT ;unsigned char new_sha1[20 ];if (logmsg && !read_ref (target, new_sha1) && -files_log_ref_write (refname, lock->old_oid.hash, new_sha1, - logmsg,0 , &err)) { +files_log_ref_write (refs, refname, lock->old_oid.hash, + new_sha1, logmsg,0 , &err)) {error ("%s" , err.buf);strbuf_release (&err); } } -static int create_symref_locked (struct ref_lock *lock,const char *refname, +static int create_symref_locked (struct files_ref_store *refs, +struct ref_lock *lock,const char *refname,const char *target,const char *logmsg) {if (prefer_symlink_refs && !create_ref_symlink (lock, target)) { -update_symref_reflog (lock, refname, target, logmsg); +update_symref_reflog (refs, lock, refname, target, logmsg);return 0 ; }
@@ -3064,7 +3089,7 @@ static int create_symref_locked(struct ref_lock *lock, const char *refname,return error ("unable to fdopen %s: %s" , lock->lk->tempfile.filename.buf,strerror (errno)); -update_symref_reflog (lock, refname, target, logmsg); +update_symref_reflog (refs, lock, refname, target, logmsg);/* no error check; commit_ref will check ferror */ fprintf (lock->lk->tempfile.fp,"ref: %s\n" , target);
@@ -3093,13 +3118,20 @@ static int files_create_symref(struct ref_store *ref_store,return -1 ; } - ret =create_symref_locked (lock, refname, target, logmsg); + ret =create_symref_locked (refs, lock, refname, target, logmsg);unlock_ref (lock);return ret; }int set_worktree_head_symref (const char *gitdir,const char *target,const char *logmsg) { +/* +* FIXME: this obviously will not work well for future refs +* backends. This function needs to die. +*/ +struct files_ref_store *refs = +files_downcast (get_ref_store (NULL ),0 ,"set_head_symref" ); +static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
@@ -3126,7 +3158,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target, const char lock->lk = &head_lock; lock->ref_name =xstrdup (head_rel); - ret =create_symref_locked (lock, head_rel, target, logmsg); + ret =create_symref_locked (refs, lock, head_rel, target, logmsg);unlock_ref (lock);/* will free lock */ strbuf_release (&head_path);
@@ -3136,14 +3168,13 @@ int set_worktree_head_symref(const char *gitdir, const char *target, const charstatic int files_reflog_exists (struct ref_store *ref_store,const char *refname) { +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"reflog_exists" );struct strbuf sb =STRBUF_INIT ;struct stat st;int ret; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"reflog_exists" ); - -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname); ret = !lstat (sb.buf, &st) &&S_ISREG (st.st_mode);strbuf_release (&sb);return ret;
@@ -3152,13 +3183,12 @@ static int files_reflog_exists(struct ref_store *ref_store,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" );struct strbuf sb =STRBUF_INIT ;int ret; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"delete_reflog" ); - -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname); ret =remove_path (sb.buf);strbuf_release (&sb);return ret;
@@ -3209,15 +3239,14 @@ static int files_for_each_reflog_ent_reverse(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_reverse" );struct strbuf sb =STRBUF_INIT ;FILE *logfp;long pos;int ret =0 , at_tail =1 ; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"for_each_reflog_ent_reverse" ); - -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3318,14 +3347,13 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,const char *refname, each_reflog_ent_fn fn, void *cb_data) { + struct files_ref_store *refs = +files_downcast (ref_store,0 ,"for_each_reflog_ent" );FILE *logfp;struct strbuf sb =STRBUF_INIT ;int ret =0 ; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"for_each_reflog_ent" ); - -strbuf_git_path (&sb,"logs/%s" , refname); +files_reflog_path (refs, &sb, refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3407,15 +3435,14 @@ 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" );struct files_reflog_iterator *iter =xcalloc (1 ,sizeof (*iter));struct ref_iterator *ref_iterator = &iter->base;struct strbuf sb =STRBUF_INIT ; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"reflog_iterator_begin" ); -base_ref_iterator_init (ref_iterator, &files_reflog_iterator_vtable); -strbuf_git_path (&sb,"logs" ); +files_reflog_path (refs, &sb,NULL ); iter->dir_iterator =dir_iterator_begin (sb.buf);strbuf_release (&sb);return ref_iterator;
@@ -3840,7 +3867,8 @@ static int files_transaction_commit(struct ref_store *ref_store,if (update->flags &REF_NEEDS_COMMIT || update->flags &REF_LOG_ONLY ) { - if (files_log_ref_write(lock->ref_name, + if (files_log_ref_write(refs, + lock->ref_name, lock->old_oid.hash, update->new_sha1, update->msg, update->flags,
@@ -3900,9 +3928,9 @@ static int files_transaction_commit(struct ref_store *ref_store,/* Delete the reflogs of any references that were deleted: */ for_each_string_list_item (ref_to_delete, &refs_to_delete) {strbuf_reset (&sb); -strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +files_reflog_path (refs, &sb, ref_to_delete->string);if (!unlink_or_warn (sb.buf)) -try_remove_empty_parents (ref_to_delete->string, +try_remove_empty_parents (refs, ref_to_delete->string,REMOVE_EMPTY_PARENTS_REFLOG ); }
@@ -3926,7 +3954,7 @@ static int files_transaction_commit(struct ref_store *ref_store,* can only work because we have already * removed the lockfile.) */ -try_remove_empty_parents (update->refname, +try_remove_empty_parents (refs, update->refname,REMOVE_EMPTY_PARENTS_REF ); } }
@@ -4077,6 +4105,7 @@ static int files_reflog_expire(struct ref_store *ref_store,static struct lock_file reflog_lock;struct expire_reflog_cb cb;struct ref_lock *lock; +struct strbuf log_file_sb =STRBUF_INIT ;char *log_file;int status =0 ;int type;
@@ -4105,7 +4134,8 @@ static int files_reflog_expire(struct ref_store *ref_store,return 0 ; } - log_file =git_pathdup ("logs/%s" , refname); +files_reflog_path (refs, &log_file_sb, refname); + log_file =strbuf_detach (&log_file_sb,NULL );if (!(flags &EXPIRE_REFLOGS_DRY_RUN )) {/* * Even though holding $GIT_DIR/logs/$reflog.lock has
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 10/28 files-backend: add and use files_ref_path()
In reply to Nguyễn Thái Ngọc DuyKeep repo-related path handling in one place. This will make it easier to add submodule/multiworktree support later.
This automatically adds the "if submodule then use the submodule version of git_path" to other call sites too. But it does not mean those operations are submodule-ready. Not yet.
--- refs/files-backend.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-)
refs/files-backend.c +23 -24
@@ -1180,6 +1180,18 @@ static void files_reflog_path(struct files_ref_store *refs,strbuf_git_path (sb,"logs/%s" , refname); } +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 ; + } + +strbuf_git_path (sb,"%s" , refname); +} +/* * Get the packed_ref_cache for the specified files_ref_store, * creating it if necessary.
@@ -1249,19 +1261,10 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)struct strbuf refname;struct strbuf path =STRBUF_INIT ;size_t path_baselen; -int err =0 ; -if (refs->submodule) - err =strbuf_git_path_submodule (&path, refs->submodule,"%s" , dirname); -else -strbuf_git_path (&path,"%s" , dirname); +files_ref_path (refs, &path, dirname); path_baselen = path.len; -if (err) { -strbuf_release (&path); -return ; - } - d =opendir (path.buf);if (!d) {strbuf_release (&path);
@@ -1396,10 +1399,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, *type =0 ;strbuf_reset (&sb_path); -if (refs->submodule) -strbuf_git_path_submodule (&sb_path, refs->submodule,"%s" , refname); -else -strbuf_git_path (&sb_path,"%s" , refname); +files_ref_path (refs, &sb_path, refname); path = sb_path.buf;
@@ -1587,7 +1587,7 @@ static int lock_raw_ref(struct files_ref_store *refs, *lock_p = lock =xcalloc (1 ,sizeof (*lock)); lock->ref_name =xstrdup (refname); -strbuf_git_path (&ref_file,"%s" , refname); +files_ref_path (refs, &ref_file, refname); retry:switch (safe_create_leading_directories (ref_file.buf)) {
@@ -2056,7 +2056,7 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,if (flags &REF_DELETING ) resolve_flags |=RESOLVE_REF_ALLOW_BAD_NAME ; -strbuf_git_path (&ref_file,"%s" , refname); +files_ref_path (refs, &ref_file, refname); resolved = !!resolve_ref_unsafe (refname, resolve_flags, lock->old_oid.hash, type);if (!resolved && errno ==EISDIR ) {
@@ -2355,7 +2355,7 @@ static void try_remove_empty_parents(struct files_ref_store *refs,strbuf_setlen (&buf, q - buf.buf);strbuf_reset (&sb); -strbuf_git_path (&sb,"%s" , buf.buf); +files_ref_path (refs, &sb, buf.buf);if ((flags &REMOVE_EMPTY_PARENTS_REF ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REF ;
@@ -2672,7 +2672,7 @@ static int files_rename_ref(struct ref_store *ref_store,struct strbuf path =STRBUF_INIT ;int result; -strbuf_git_path (&path,"%s" , newrefname); +files_ref_path (refs, &path, newrefname); result =remove_empty_directories (&path);strbuf_release (&path);
@@ -3906,7 +3906,7 @@ static int files_transaction_commit(struct ref_store *ref_store, update->type & REF_ISSYMREF) {/* It is a loose reference. */ strbuf_reset (&sb); -strbuf_git_path (&sb,"%s" , lock->ref_name); +files_ref_path (refs, &sb, lock->ref_name);if (unlink_or_msg (sb.buf, err)) { ret =TRANSACTION_GENERIC_ERROR ; goto cleanup;
@@ -4206,19 +4206,18 @@ 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" );struct strbuf sb =STRBUF_INIT ; -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"init_db" ); -/* * Create .git/refs/{heads,tags} */ -strbuf_git_path (&sb,"refs/heads" ); +files_ref_path (refs, &sb,"refs/heads" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_ref_path (refs, &sb,"refs/tags" );safe_create_dir (sb.buf,1 );strbuf_release (&sb);
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 11/28 files-backend: remove the use of git_path()
In reply to Nguyễn Thái Ngọc DuyGiven $GIT_DIR and $GIT_COMMON_DIR, files-backend is now in charge of deciding what goes where (*). The end goal is to pass $GIT_DIR only. A refs "view" of a linked worktree is a logical ref store that combines two files backends together.
(*) Not entirely true since strbuf_git_path_submodule() still does path translation underneath. But that's for another patch.
--- refs/files-backend.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-)
refs/files-backend.c +38 -5
@@ -923,7 +923,8 @@ struct files_ref_store {* store: */ const char *submodule; - +char *gitdir; +char *gitcommondir;char *packed_refs_path;struct ref_entry *loose;
@@ -985,6 +986,8 @@ static struct ref_store *files_ref_store_create(const char *submodule) {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);
@@ -995,7 +998,11 @@ static struct ref_store *files_ref_store_create(const char *submodule)return ref_store; } - refs->packed_refs_path =git_pathdup ("packed-refs" ); + refs->gitdir =xstrdup (gitdir); +get_common_dir_noenv (&sb, gitdir); + refs->gitcommondir =strbuf_detach (&sb,NULL ); +strbuf_addf (&sb,"%s/packed-refs" , refs->gitcommondir); + refs->packed_refs_path =strbuf_detach (&sb,NULL );return ref_store; }
@@ -1173,11 +1180,26 @@ static void files_reflog_path(struct files_ref_store *refs, const char *refname) {if (!refname) { -strbuf_git_path (sb,"logs" ); +/* +* FIXME: of course this is wrong in multi worktree +* setting. To be fixed real soon. +*/ +strbuf_addf (sb,"%s/logs" , refs->gitcommondir);return ; } -strbuf_git_path (sb,"logs/%s" , refname); +switch (ref_type (refname)) { +case REF_TYPE_PER_WORKTREE : +case REF_TYPE_PSEUDOREF : +strbuf_addf (sb,"%s/logs/%s" , refs->gitdir, refname); +break ; +case REF_TYPE_NORMAL : +strbuf_addf (sb,"%s/logs/%s" , refs->gitcommondir, refname); +break ; +default : +die ("BUG: unknown ref type %d of ref %s" , +ref_type (refname), refname); + } } static void files_ref_path(struct files_ref_store *refs,
@@ -1189,7 +1211,18 @@ static void files_ref_path(struct files_ref_store *refs,return ; } -strbuf_git_path (sb,"%s" , refname); +switch (ref_type (refname)) { +case REF_TYPE_PER_WORKTREE : +case REF_TYPE_PSEUDOREF : +strbuf_addf (sb,"%s/%s" , refs->gitdir, refname); +break ; +case REF_TYPE_NORMAL : +strbuf_addf (sb,"%s/%s" , refs->gitcommondir, refname); +break ; +default : +die ("BUG: unknown ref type %d of ref %s" , +ref_type (refname), refname); + } }/*
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 12/28 refs.c: introduce get_main_ref_store()
In reply to Nguyễn Thái Ngọc Duy--- refs.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
refs.c +9 -4
@@ -1456,15 +1456,20 @@ static struct ref_store *ref_store_init(const char *submodule)return refs; } +static struct ref_store *get_main_ref_store (void ) +{ +if (main_ref_store) +return main_ref_store; + +return ref_store_init (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 ); +return get_main_ref_store (); }else { refs =lookup_ref_store (submodule);
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 13/28 refs: rename lookup_ref_store() to lookup_submodule_ref_store()
In reply to Nguyễn Thái Ngọc DuyWith get_main_ref_store() being used inside get_ref_store(), lookup_ref_store() is only used for submodule code path. Rename to reflect that and delete dead code.
--- refs.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)
refs.c +4 -9
@@ -1395,17 +1395,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 ;
@@ -1471,7 +1467,7 @@ struct ref_store *get_ref_store(const char *submodule)if (!submodule || !*submodule) {return get_main_ref_store (); }else { - refs =lookup_ref_store (submodule); + refs =lookup_submodule_ref_store (submodule);if (!refs) {struct strbuf submodule_sb =STRBUF_INIT ;
@@ -1482,7 +1478,6 @@ struct ref_store *get_ref_store(const char *submodule)strbuf_release (&submodule_sb); } } -return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 14/28 refs.c: flatten get_ref_store() a bit
In reply to Nguyễn Thái Ngọc DuyThis helps the future changes in this code. And because get_ref_store() is destined to become get_submodule_ref_store(), the "get main store" code path will be removed eventually. After this the patch to delete that code will be cleaner.
--- refs.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
refs.c +13 -10
@@ -1462,22 +1462,25 @@ static struct ref_store *get_main_ref_store(void)struct ref_store *get_ref_store (const char *submodule) { +struct strbuf submodule_sb =STRBUF_INIT ;struct ref_store *refs; +int ret;if (!submodule || !*submodule) {return get_main_ref_store (); - }else { - refs =lookup_submodule_ref_store (submodule); + } -if (!refs) { -struct strbuf submodule_sb =STRBUF_INIT ; + refs =lookup_submodule_ref_store (submodule); +if (refs) +return refs; -strbuf_addstr (&submodule_sb, submodule); -if (is_nonbare_repository_dir (&submodule_sb)) - refs =ref_store_init (submodule); -strbuf_release (&submodule_sb); - } - } +strbuf_addstr (&submodule_sb, submodule); + ret =is_nonbare_repository_dir (&submodule_sb); +strbuf_release (&submodule_sb); +if (!ret) +return NULL ; + + refs =ref_store_init (submodule);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 15/28 refs.c: kill register_ref_store(), add register_submodule_ref_store()
In reply to Nguyễn Thái Ngọc DuyThis is the last function in this code (besides public API) that takes submodule argument and handles both main/submodule cases. Break it down, move main store registration in get_main_ref_store() and keep the rest in register_submodule_ref_store().
--- refs.c | 45 ++++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 25 deletions(-)
refs.c +20 -25
@@ -1412,29 +1412,6 @@ static struct ref_store *lookup_submodule_ref_store(const char *submodule) }/* -* 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). */
@@ -1448,7 +1425,6 @@ static struct ref_store *ref_store_init(const char *submodule)die ("BUG: reference backend %s is unknown" , be_name); refs = be->init (submodule); -register_ref_store (refs, submodule);return refs; }
@@ -1457,7 +1433,25 @@ static struct ref_store *get_main_ref_store(void)if (main_ref_store)return main_ref_store; -return ref_store_init (NULL ); + main_ref_store =ref_store_init (NULL ); +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_ref_store (const char *submodule)
@@ -1481,6 +1475,7 @@ struct ref_store *get_ref_store(const char *submodule)return NULL ; refs =ref_store_init (submodule); +register_submodule_ref_store (refs, submodule);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 16/28 refs.c: make get_main_ref_store() public and use it
In reply to Nguyễn Thái Ngọc Duyget_ref_store() will soon be renamed to get_submodule_ref_store(). Together with future get_worktree_ref_store(), the three functions provide an appropriate ref store for different operation modes. New APIs will be added to operate directly on ref stores.
--- refs.c | 36 ++++++++++++++++++------------------ refs.h | 3 +++ refs/files-backend.c | 2 +- 3 files changed, 22 insertions(+), 19 deletions(-)
refs.c +18 -18
@@ -1314,7 +1314,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); }
@@ -1322,7 +1322,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 resolve_ref_recursively (get_main_ref_store (), refname, resolve_flags, sha1, flags); }
@@ -1428,7 +1428,7 @@ static struct ref_store *ref_store_init(const char *submodule)return refs; } -static struct ref_store *get_main_ref_store (void ) +struct ref_store *get_main_ref_store (void ) {if (main_ref_store)return main_ref_store;
@@ -1488,14 +1488,14 @@ void base_ref_store_init(struct ref_store *refs,/* backend functions */ int pack_refs (unsigned int flags) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->pack_refs (refs, flags); }int peel_ref (const char *refname,unsigned char *sha1) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->peel_ref (refs, refname, sha1); }
@@ -1503,7 +1503,7 @@ int peel_ref(const char *refname, unsigned char *sha1)int create_symref (const char *ref_target,const char *refs_heads_master,const char *logmsg) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->create_symref (refs, ref_target, refs_heads_master, logmsg);
@@ -1512,7 +1512,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_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->transaction_commit (refs, transaction, err); }
@@ -1522,14 +1522,14 @@ int verify_refname_available(const char *refname,const struct string_list *skip, struct strbuf *err) { - struct ref_store *refs = get_ref_store(NULL); + 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) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();struct ref_iterator *iter; iter = refs->be->reflog_iterator_begin (refs);
@@ -1540,7 +1540,7 @@ int for_each_reflog(each_ref_fn fn, void *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 ); +struct ref_store *refs =get_main_ref_store ();return refs->be->for_each_reflog_ent_reverse (refs, refname, fn, cb_data);
@@ -1549,14 +1549,14 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,int for_each_reflog_ent (const char *refname,each_reflog_ent_fn fn,void *cb_data) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();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 ); +struct ref_store *refs =get_main_ref_store ();return refs->be->reflog_exists (refs, refname); }
@@ -1564,14 +1564,14 @@ int reflog_exists(const char *refname)int safe_create_reflog (const char *refname,int force_create,struct strbuf *err) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->create_reflog (refs, refname, force_create, err); }int delete_reflog (const char *refname) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->delete_reflog (refs, refname); }
@@ -1583,7 +1583,7 @@ 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); + struct ref_store *refs = get_main_ref_store(); return refs->be->reflog_expire(refs, refname, sha1, flags, prepare_fn, should_prune_fn,
@@ -1593,21 +1593,21 @@ 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_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();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 ); +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) { -struct ref_store *refs =get_ref_store (NULL ); +struct ref_store *refs =get_main_ref_store ();return refs->be->rename_ref (refs, oldref, newref, logmsg); }
refs.h +3 -0
@@ -2,6 +2,7 @@#define REFS_H struct object_id ; +struct ref_store ;struct strbuf ;struct string_list ;
@@ -560,4 +561,6 @@ 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 ); +#endif /* REFS_H */
refs/files-backend.c +1 -1
@@ -3163,7 +3163,7 @@ 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_ref_store (NULL ),0 ,"set_head_symref" ); +files_downcast (get_main_ref_store (),0 ,"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 17/28 path.c: move some code out of strbuf_git_path_submodule()
In reply to Nguyễn Thái Ngọc Duyrefs is learning to avoid path rewriting that is done by strbuf_git_path_submodule(). Factor out this code so it could be reused by refs_* functions.
--- path.c | 35 +++++++---------------------------- submodule.c | 31 +++++++++++++++++++++++++++++++ submodule.h | 6 ++++++ 3 files changed, 44 insertions(+), 28 deletions(-)
path.c +7 -28
@@ -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 -1static 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, ...)
submodule.c +31 -0
@@ -1596,3 +1596,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; +}
submodule.h +6 -0
@@ -81,6 +81,12 @@ extern int push_unpushed_submodules(struct sha1_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);/* * Prepare the "env_array" parameter of a "struct child_process" for executing
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 18/28 refs: move submodule code out of files-backend.c
In reply to Nguyễn Thái Ngọc Duyfiles-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.
--- refs.c | 19 ++++++++++++++----- refs/files-backend.c | 24 ++---------------------- refs/refs-internal.h | 9 ++++----- 3 files changed, 20 insertions(+), 32 deletions(-)
refs.c +14 -5
@@ -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; }
refs/files-backend.c +2 -22
@@ -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:
refs/refs-internal.h +4 -5
@@ -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);
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 19/28 files-backend: replace submodule_allowed check in files_downcast()
In reply to Nguyễn Thái Ngọc Duyfiles-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.
--- refs.c | 15 +++++++--- refs/files-backend.c | 81 +++++++++++++++++++++++++++++++++------------------- refs/refs-internal.h | 9 +++++- 3 files changed, 71 insertions(+), 34 deletions(-)
refs.c +11 -4
@@ -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); +/* pretend 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);
refs/files-backend.c +52 -29
244 lines not on this page · raw message
refs/refs-internal.h +8 -1
@@ -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);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v7 19/28] files-backend: replace submodule_allowed check in files_downcast()
Quoted 32 lines · Nguyễn Thái Ngọc Duy
files-backend.cis 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 takeREF_STORE_ODBflag out. At least t3404 would fail. The "have access to odb" in submodule is a bit hacky since we don't know from he whetheradd_submodule_odb()has been called.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.c | 15 +++++++--- refs/files-backend.c | 81 +++++++++++++++++++++++++++++++++------------------- refs/refs-internal.h | 9 +++++- 3 files changed, 71 insertions(+), 34 deletions(-)refs.c +0
-0
refs.c struct ref_store *get_ref_store(const char *submodule) · line 1489
Quoted 5 lines
refs.c +1
-1@@ -1481,7 +1486,9 @@ struct ref_store *get_ref_store(const char *submodule)return NULL ; } - refs =ref_store_init (submodule_sb.buf); +/* pretend that add_submodule_odb() has been called */
The word "pretend" implies that the thing that follows is not true, whereas we hope that it *is* true. It would be better to say "assume".
Quoted 18 lines
refs.c +2
-0+ refs =ref_store_init (submodule_sb.buf, +REF_STORE_READ |REF_STORE_ODB );register_submodule_ref_store (refs, submodule);strbuf_release (&submodule_sb);refs/files-backend.c +2
-2@@ -994,13 +997,17 @@ 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.
refs/files-backend.c static struct ref_store *files_ref_store_create(const char *gitdir) · line 1010
Quoted 10 lines
refs/files-backend.c +5
-1*/ 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: unallowed operation (%s), only works " +"on main ref store\n" , caller);
"Unallowed" isn't really a word; one would say "disallowed". But it might sound better to say
BUG: operation %s only allowed for main ref store
refs/files-backend.c static void files_assert_main_repository(struct files_ref_store *refs, · line 1021
Quoted 13 lines
refs/files-backend.c +3
-3}/* @@ -1009,9 +1016,9 @@ static void files_assert_main_repository(struct files_ref_store *refs,* files_ref_store is for a submodule (i.e., not for the main * repository). 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)
The docstring for this function needs to be updated; it still talks about the old submodule_allowed parameter.
refs/files-backend.c static struct files_ref_store *files_downcast( · line 1033
Quoted 12 lines
refs/files-backend.c +3
-2{struct files_ref_store *refs;@@ -1021,8 +1028,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: unallowed operation (%s), requires %x, has %x\n" , + caller, required_flags, refs->store_flags);
Same comment about "unallowed". Maybe
BUG: operation %s requires abilities 0x%x but only have 0x%x
refs/files-backend.c static struct files_ref_store *files_downcast( · line 1035
Quoted 4 lines
refs/files-backend.c +0
-0return refs; }
Michael
Re: [PATCH v7 19/28] files-backend: replace submodule_allowed check in files_downcast()
I'll mark this mail and do a follow-up patch once this topic graduates to master. It's less review burden and mail traffic.
Quoted 117 lines · Michael Haggerty
Quoted 32 lines · Nguyễn Thái Ngọc Duy
files-backend.cis 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 takeREF_STORE_ODBflag out. At least t3404 would fail. The "have access to odb" in submodule is a bit hacky since we don't know from he whetheradd_submodule_odb()has been called.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.c | 15 +++++++--- refs/files-backend.c | 81 +++++++++++++++++++++++++++++++++------------------- refs/refs-internal.h | 9 +++++- 3 files changed, 71 insertions(+), 34 deletions(-)refs.c +0
-0refs.c struct ref_store *get_ref_store(const char *submodule) · line 1489
Quoted 5 lines
refs.c +1
-1@@ -1481,7 +1486,9 @@ struct ref_store *get_ref_store(const char *submodule)return NULL ; } - refs =ref_store_init (submodule_sb.buf); +/* pretend that add_submodule_odb() has been called */ The word "pretend" implies that the thing that follows is not true, whereas we hope that it *is* true. It would be better to say "assume".
Quoted 18 lines
refs.c +2
-0+ refs =ref_store_init (submodule_sb.buf, +REF_STORE_READ |REF_STORE_ODB );register_submodule_ref_store (refs, submodule);strbuf_release (&submodule_sb);refs/files-backend.c +2
-2@@ -994,13 +997,17 @@ 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. refs/files-backend.c static struct ref_store *files_ref_store_create(const char *gitdir) · line 1010
Quoted 10 lines
refs/files-backend.c +5
-1*/ 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: unallowed operation (%s), only works " +"on main ref store\n" , caller);"Unallowed" isn't really a word; one would say "disallowed". But it might sound better to say
BUG: operation %s only allowed for main ref storerefs/files-backend.c static void files_assert_main_repository(struct files_ref_store *refs, · line 1021
Quoted 13 lines
refs/files-backend.c +3
-3}/* @@ -1009,9 +1016,9 @@ static void files_assert_main_repository(struct files_ref_store *refs,* files_ref_store is for a submodule (i.e., not for the main * repository). 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)The docstring for this function needs to be updated; it still talks about the old
submodule_allowedparameter.refs/files-backend.c static struct files_ref_store *files_downcast( · line 1033
Quoted 12 lines
refs/files-backend.c +3
-2{struct files_ref_store *refs;@@ -1021,8 +1028,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: unallowed operation (%s), requires %x, has %x\n" , + caller, required_flags, refs->store_flags);Same comment about "unallowed". Maybe
BUG: operation %s requires abilities 0x%x but only have 0x%xrefs/files-backend.c static struct files_ref_store *files_downcast( · line 1035
Quoted 4 lines
refs/files-backend.c +0
-0return refs; }Michael
Signature · 1 line
Duy
Re: [PATCH v7 19/28] files-backend: replace submodule_allowed check in files_downcast()
Quoted 2 lines · Duy Nguyen
I'll mark this mail and do a follow-up patch once this topic graduates to master. It's less review burden and mail traffic.
I actually do not mind a single replacement patch.
Re: [PATCH v7 19/28] files-backend: replace submodule_allowed check in files_downcast()
Quoted 6 lines · Junio C Hamano
Quoted 2 lines · Duy Nguyen
I'll mark this mail and do a follow-up patch once this topic graduates to master. It's less review burden and mail traffic.
I actually do not mind a single replacement patch.
Thanks. Here's the fixup patch
-- 8< --
From c572f11f9c653f6f18d51a56b31cc5d966f9b242 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?=
<[email protected]>
Date: Fri, 14 Apr 2017 19:54:31 +0700
Subject: [PATCH] fixup! files-backend: replace submodule_allowed check in
files_downcast()
--- refs.c | 2 +- refs/files-backend.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-)
refs.c +1 -1
@@ -1486,7 +1486,7 @@ struct ref_store *get_ref_store(const char *submodule)return NULL ; } -/* pretend that add_submodule_odb() has been called */ +/* 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);
refs/files-backend.c +4 -6
@@ -1006,15 +1006,13 @@ static void files_assert_main_repository(struct files_ref_store *refs,if (refs->store_flags &REF_STORE_MAIN )return ; -die ("BUG: unallowed operation (%s), only works " -"on main ref store\n" , caller); +die ("BUG: operation %s is 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. Die if the operation is not allowed on this particular +* store. "caller" is used in any necessary error messages. */ static struct files_ref_store *files_downcast(struct ref_store *ref_store, unsigned int required_flags,
@@ -1029,7 +1027,7 @@ static struct files_ref_store *files_downcast(struct ref_store *ref_store, refs = (struct files_ref_store *)ref_store;if ((refs->store_flags & required_flags) != required_flags) -die ("BUG: unallowed operation (%s), requires %x, has %x\n" , +die ("BUG: operation %s requires abilities 0x%x but have 0x%x" , caller, required_flags, refs->store_flags);return refs;
Signature · 3 lines
2.11.0.157.gd943d85 -- 8< --
PATCH v7 20/28 refs: rename get_ref_store() to get_submodule_ref_store() and make it public
In reply to Nguyễn Thái Ngọc DuyThis 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.
--- refs.c | 12 ++++++++---- refs.h | 11 +++++++++++ refs/refs-internal.h | 12 ------------ 3 files changed, 19 insertions(+), 16 deletions(-)
refs.c +8 -4
@@ -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 (); }
refs.h +11 -0
@@ -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 */
refs/refs-internal.h +0 -12
@@ -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,
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 21/28 refs: add new ref-store api
In reply to Nguyễn Thái Ngọc DuyThis 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.
--- refs.c | 251 ++++++++++++++++++++++++++++++++++++++------------- refs.h | 74 +++++++++++++++ refs/files-backend.c | 13 +-- refs/refs-internal.h | 31 +------ 4 files changed, 270 insertions(+), 99 deletions(-)
refs.c +186 -65
@@ -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_lifor_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, unsigif (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); +}
refs.h +74 -0
161 lines not on this page · raw message
refs/files-backend.c +7 -6
@@ -1314,7 +1314,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)) {
@@ -1623,7 +1623,8 @@ static int lock_raw_ref(struct files_ref_store *refs,* 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
@@ -2671,7 +2672,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; }
@@ -4055,9 +4056,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; }
refs/refs-internal.h +3 -28
@@ -112,28 +112,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, * because reflog file is one line per entry.
@@ -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 */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 22/28 refs: new transaction related ref-store api
In reply to Nguyễn Thái Ngọc DuyThe transaction struct now takes a ref store at creation and will operate on that ref store alone.
--- refs.c | 55 ++++++++++++++++++++++++++++++++++++++++------------ refs.h | 9 +++++++++ refs/refs-internal.h | 1 + 3 files changed, 53 insertions(+), 12 deletions(-)
refs.c +43 -12
@@ -630,16 +630,20 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1return 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); }
refs.h +9 -0
@@ -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);
refs/refs-internal.h +1 -0
@@ -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;
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v7 22/28] refs: new transaction related ref-store api
Quoted 2 lines · Nguyễn Thái Ngọc Duy
The transaction struct now takes a ref store at creation and will operate on that ref store alone.
Having worked downstream of this patch series for a while, I started to wonder why a ref_store has to be baked into a ref_transaction at creation. I haven't noticed any technical reason why it must be so.
If we expected to need to virtualize ref_transaction_begin() sometime, then of course your design would be preferable.
It surprised be, because until now ref_transaction has been a plain old data structure unconnected with a particular ref_store. I would have expected ref_transaction_commit() to gain a more general sibling, refs_ref_transaction_commit() [*], that takes an additional ref_store * object argument, and for ref_transaction_commit() to call that function. It would feel slightly more natural to me, given that transaction_commit is a virtual method of the ref_store class, for refs_ref_transaction_commit() to take an explicit refs pointer rather than having that pointer buried in the ref_transaction.
I think this is mostly an aesthetic issue (about which opinions can legitimately differ) rather than a concrete problem. I haven't yet had any difficulties working with your interface. But I wanted to mention my observation anyway. As far as I'm concerned, you don't need to change it.
Quoted 1 line
[...]
Michael
[*] The name could obviously be improved, but you get the idea.
Re: [PATCH v7 22/28] refs: new transaction related ref-store api
Quoted 11 lines · Michael Haggerty
Quoted 2 lines · Nguyễn Thái Ngọc Duy
The transaction struct now takes a ref store at creation and will operate on that ref store alone.
Having worked downstream of this patch series for a while, I started to wonder why a
ref_storehas to be baked into aref_transactionat creation. I haven't noticed any technical reason why it must be so.If we expected to need to virtualize
ref_transaction_begin()sometime, then of course your design would be preferable.
Quoted 6 lines
It surprised be, because until now
ref_transactionhas been a plain old data structure unconnected with a particularref_store. I would have expectedref_transaction_commit()to gain a more general sibling,refs_ref_transaction_commit()[*], that takes an additionalref_store *object argument, and forref_transaction_commit()to call that function.
I almost went with that, but the question that stopped me was, "what if people do X on ref store A, then Y on ref store B, using the same transaction?". I suppose we could even support that (which basically turns one transaction into two), or check for same ref store and reject. It's too complicated though. So I went a safe way, making sure people won't be able to change ref store half way.
Quoted 16 lines
It would feel slightly more natural to me, given that
transaction_commitis a virtual method of theref_storeclass, forrefs_ref_transaction_commit()to take an explicitrefspointer rather than having that pointer buried in theref_transaction.I think this is mostly an aesthetic issue (about which opinions can legitimately differ) rather than a concrete problem. I haven't yet had any difficulties working with your interface. But I wanted to mention my observation anyway. As far as I'm concerned, you don't need to change it.
Quoted 1 line
[...]
Michael
[*] The name could obviously be improved, but you get the idea.
Signature · 1 line
Duy
PATCH v7 23/28 files-backend: avoid ref api targetting main ref store
In reply to Nguyễn Thái Ngọc DuyA small step towards making files-backend works as a non-main ref store using the newly added store-aware API.
For the record, join and nm on refs.o and files-backend.o tell me that files-backend no longer uses functions that defaults to get_main_ref_store().
I'm not yet comfortable at the idea of removing files_assert_main_repository() (or converting REF_STORE_MAIN to REF_STORE_WRITE). More staring and testing is required before that can happen. Well, except peel_ref(). I'm pretty sure that function is safe.
--- refs/files-backend.c | 84 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 35 deletions(-)
refs/files-backend.c +49 -35
@@ -1830,8 +1830,6 @@ static int files_peel_ref(struct ref_store *ref_store,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;
@@ -1841,7 +1839,8 @@ static int files_peel_ref(struct ref_store *ref_store,return 0 ; } -if (read_ref_full (refname,RESOLVE_REF_READING , base, &flag)) +if (refs_read_ref_full (ref_store, refname, +RESOLVE_REF_READING , base, &flag))return -1 ;/*
@@ -2009,15 +2008,15 @@ static struct ref_iterator *files_ref_iterator_begin(* on success. On error, write an error message to err, set errno, and * return a negative value. */ -static int verify_lock (struct ref_lock *lock, +static int verify_lock (struct ref_store *ref_store,struct ref_lock *lock,const unsigned char *old_sha1,int mustexist,struct strbuf *err) {assert (err); -if (read_ref_full (lock->ref_name, - mustexist ?RESOLVE_REF_READING :0 , - lock->old_oid.hash,NULL )) { +if (refs_read_ref_full (ref_store, lock->ref_name, + mustexist ?RESOLVE_REF_READING :0 , + lock->old_oid.hash,NULL )) {if (old_sha1) {int save_errno = errno;strbuf_addf (err,"can't verify ref '%s'" , lock->ref_name);
@@ -2086,8 +2085,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, resolve_flags |=RESOLVE_REF_ALLOW_BAD_NAME ;files_ref_path (refs, &ref_file, refname); - resolved = !!resolve_ref_unsafe (refname, resolve_flags, - lock->old_oid.hash, type); + resolved = !!refs_resolve_ref_unsafe (&refs->base, + refname, resolve_flags, + lock->old_oid.hash, type);if (!resolved && errno ==EISDIR ) {/* * we are trying to lock foo but we used to
@@ -2104,8 +2104,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, refname); goto error_return; } - resolved = !!resolve_ref_unsafe (refname, resolve_flags, - lock->old_oid.hash, type); + resolved = !!refs_resolve_ref_unsafe (&refs->base, + refname, resolve_flags, + lock->old_oid.hash, type); }if (!resolved) { last_errno = errno;
@@ -2143,7 +2144,7 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, goto error_return; } -if (verify_lock (lock, old_sha1, mustexist, err)) { +if (verify_lock (&refs->base, lock, old_sha1, mustexist, err)) { last_errno = errno; goto error_return; }
@@ -2398,7 +2399,7 @@ static void try_remove_empty_parents(struct files_ref_store *refs, }/* make sure nobody touched the ref, and unlink */ -static void prune_ref (struct ref_to_prune *r) +static void prune_ref (struct files_ref_store *refs,struct ref_to_prune *r) {struct ref_transaction *transaction;struct strbuf err =STRBUF_INIT ;
@@ -2406,7 +2407,7 @@ static void prune_ref(struct ref_to_prune *r)if (check_refname_format (r->name,0 ))return ; - transaction =ref_transaction_begin (&err); + transaction =ref_store_transaction_begin (&refs->base, &err); if (!transaction || ref_transaction_delete(transaction, r->name, r->sha1, REF_ISPRUNING | REF_NODEREF, NULL, &err) ||
@@ -2420,10 +2421,10 @@ static void prune_ref(struct ref_to_prune *r)strbuf_release (&err); } -static void prune_refs (struct ref_to_prune *r) +static void prune_refs (struct files_ref_store *refs,struct ref_to_prune *r) {while (r) { -prune_ref (r); +prune_ref (refs, r); r = r->next; } }
@@ -2447,7 +2448,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)if (commit_packed_refs (refs))die_errno ("unable to overwrite old ref-pack file" ); -prune_refs (cbdata.ref_to_prune); +prune_refs (refs, cbdata.ref_to_prune);return 0 ; }
@@ -2539,7 +2540,7 @@ static int files_delete_refs(struct ref_store *ref_store,for (i =0 ; i < refnames->nr; i++) {const char *refname = refnames->items[i].string; -if (delete_ref (NULL , refname,NULL , flags)) +if (refs_delete_ref (&refs->base,NULL , refname,NULL , flags)) result |=error (_ ("could not remove reference %s" ), refname); }
@@ -2661,7 +2662,8 @@ static int files_rename_ref(struct ref_store *ref_store, goto out; } -if (!resolve_ref_unsafe (oldrefname,RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , +if (!refs_resolve_ref_unsafe (&refs->base, oldrefname, +RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , orig_sha1, &flag)) { ret =error ("refname %s not found" , oldrefname); goto out;
@@ -2683,7 +2685,8 @@ static int files_rename_ref(struct ref_store *ref_store, goto out; } -if (delete_ref (logmsg, oldrefname, orig_sha1,REF_NODEREF )) { +if (refs_delete_ref (&refs->base, logmsg, oldrefname, + orig_sha1,REF_NODEREF )) {error ("unable to delete old %s" , oldrefname); goto rollback; }
@@ -2695,9 +2698,11 @@ static int files_rename_ref(struct ref_store *ref_store,* the safety anyway; we want to delete the reference whatever * its current value. */ -if (!read_ref_full (newrefname,RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , - sha1,NULL ) && -delete_ref (NULL , newrefname,NULL ,REF_NODEREF )) { +if (!refs_read_ref_full (&refs->base, newrefname, +RESOLVE_REF_READING |RESOLVE_REF_NO_RECURSE , + sha1,NULL ) && +refs_delete_ref (&refs->base,NULL , newrefname, +NULL ,REF_NODEREF )) {if (errno ==EISDIR ) {struct strbuf path =STRBUF_INIT ;int result;
@@ -3053,8 +3058,9 @@ static int commit_ref_update(struct files_ref_store *refs,int head_flag;const char *head_ref; - head_ref =resolve_ref_unsafe ("HEAD" ,RESOLVE_REF_READING , - head_sha1, &head_flag); + head_ref =refs_resolve_ref_unsafe (&refs->base,"HEAD" , +RESOLVE_REF_READING , + head_sha1, &head_flag);if (head_ref && (head_flag &REF_ISSYMREF ) && !strcmp (head_ref, lock->ref_name)) {struct strbuf log_err =STRBUF_INIT ;
@@ -3098,7 +3104,9 @@ static void update_symref_reflog(struct files_ref_store *refs, {struct strbuf err =STRBUF_INIT ;unsigned char new_sha1[20 ]; -if (logmsg && !read_ref (target, new_sha1) && +if (logmsg && + !refs_read_ref_full (&refs->base, target, +RESOLVE_REF_READING , new_sha1,NULL ) &&files_log_ref_write (refs, refname, lock->old_oid.hash, new_sha1, logmsg,0 , &err)) {error ("%s" , err.buf);
@@ -3403,6 +3411,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,struct files_reflog_iterator {struct ref_iterator base; +struct ref_store *ref_store;struct dir_iterator *dir_iterator;struct object_id oid; };
@@ -3424,8 +3433,9 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)if (ends_with (diter->basename,".lock" ))continue ; -if (read_ref_full (diter->relative_path,0 , - iter->oid.hash, &flags)) { +if (refs_read_ref_full (iter->ref_store, + diter->relative_path,0 , + iter->oid.hash, &flags)) {error ("bad ref for %s" , diter->path.buf);continue ; }
@@ -3479,6 +3489,7 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_stbase_ref_iterator_init (ref_iterator, &files_reflog_iterator_vtable);files_reflog_path (refs, &sb,NULL ); iter->dir_iterator =dir_iterator_begin (sb.buf); + iter->ref_store = ref_store;strbuf_release (&sb);return ref_iterator; }
@@ -3718,8 +3729,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,* the transaction, so we have to read it here * to record and possibly check old_sha1: */ -if (read_ref_full (referent.buf,0 , - lock->old_oid.hash,NULL )) { +if (refs_read_ref_full (&refs->base, + referent.buf,0 , + lock->old_oid.hash,NULL )) {if (update->flags &REF_HAVE_OLD ) { strbuf_addf(err, "cannot lock ref '%s': " "error reading reference",
@@ -3873,8 +3885,9 @@ static int files_transaction_commit(struct ref_store *ref_store,* head_ref within the transaction, then split_head_update() * arranges for the reflog of HEAD to be updated, too. */ - head_ref =resolve_refdup ("HEAD" ,RESOLVE_REF_NO_RECURSE , - head_oid.hash, &head_type); + head_ref =refs_resolve_refdup (ref_store,"HEAD" , +RESOLVE_REF_NO_RECURSE , + head_oid.hash, &head_type);if (head_ref && !(head_type &REF_ISSYMREF )) {free (head_ref);
@@ -4047,7 +4060,8 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,* so here we really only check that none of the references * that we are creating already exists. */ -if (for_each_rawref (ref_present, &affected_refnames)) +if (refs_for_each_rawref (&refs->base, ref_present, + &affected_refnames))die ("BUG: initial ref transaction called with existing refs" );for (i =0 ; i < transaction->nr; i++) {
@@ -4166,7 +4180,7 @@ static int files_reflog_expire(struct ref_store *ref_store,strbuf_release (&err);return -1 ; } -if (!reflog_exists (refname)) { +if (!refs_reflog_exists (ref_store, refname)) {unlock_ref (lock);return 0 ; }
@@ -4197,7 +4211,7 @@ static int files_reflog_expire(struct ref_store *ref_store, } (*prepare_fn)(refname, sha1, cb.policy_cb); -for_each_reflog_ent (refname, expire_reflog_ent, &cb); +refs_for_each_reflog_ent (ref_store, refname, expire_reflog_ent, &cb); (*cleanup_fn)(cb.policy_cb);if (!(flags &EXPIRE_REFLOGS_DRY_RUN )) {
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v7 23/28] files-backend: avoid ref api targetting main ref store
Nits: s/targetting/targeting/ in the subject line.
Quoted 2 lines · Nguyễn Thái Ngọc Duy
A small step towards making files-backend works as a non-main ref store using the newly added store-aware API.
s/works/work/
Quoted 3 lines
For the record,
joinandnmon refs.o and files-backend.o tell me that files-backend no longer uses functions that defaults toget_main_ref_store().
s/defaults/default/
Quoted 5 lines
I'm not yet comfortable at the idea of removing
files_assert_main_repository()(or convertingREF_STORE_MAINtoREF_STORE_WRITE). More staring and testing is required before that can happen. Well, exceptpeel_ref(). I'm pretty sure that function is safe. [...]
Michael
PATCH v7 24/28 refs: delete pack_refs() in favor of refs_pack_refs()
In reply to Nguyễn Thái Ngọc DuyIt only has one caller, not worth keeping just for convenience.
--- builtin/pack-refs.c | 2 +- refs.c | 5 ----- refs.h | 1 - 3 files changed, 1 insertion(+), 7 deletions(-)
builtin/pack-refs.c +1 -1
@@ -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); }
refs.c +0 -5
@@ -1602,11 +1602,6 @@ int refs_pack_refs(struct ref_store *refs, unsigned int flags)return refs->be->pack_refs (refs, flags); } -int pack_refs (unsigned int flags) -{ -return refs_pack_refs (get_main_ref_store (), flags); -} -int refs_peel_ref (struct ref_store *refs,const char *refname,unsigned char *sha1) {
refs.h +0 -1
@@ -297,7 +297,6 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt,* 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);/* * Flags controlling ref_transaction_update(), ref_transaction_create(), etc.
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 25/28 t/helper: add test-ref-store to test ref-store functions
In reply to Nguyễn Thái Ngọc Duy--- Makefile | 1 + t/helper/.gitignore | 1 + t/helper/test-ref-store.c (new) | 277 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 t/helper/test-ref-store.c
Makefile +1 -0
@@ -622,6 +622,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
t/helper/.gitignore +1 -0
@@ -19,6 +19,7 @@ /test-path-utils /test-prio-queue /test-read-cache +/test-ref-store /test-regex /test-revision-walking /test-run-command
t/helper/test-ref-store.c new file +277 -0
277 lines not on this page · raw message
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 26/28 t1405: some basic tests on main ref store
In reply to Nguyễn Thái Ngọc Duy--- t/t1405-main-ref-store.sh (new +x) | 123 +++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100755 t/t1405-main-ref-store.sh
t/t1405-main-ref-store.sh new file +123 -0
@@ -0,0 +1,123 @@ +#!/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 '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
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 27/28 t1406: new tests for submodule ref store
In reply to Nguyễn Thái Ngọc Duy--- t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 t/t1406-submodule-ref-store.sh
t/t1406-submodule-ref-store.sh new file +95 -0
@@ -0,0 +1,95 @@ +#!/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 '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
Signature · 1 line
2.11.0.157.gd943d85
PATCH v7 28/28 refs.h: add a note about sorting order of for_each_ref_*
In reply to Nguyễn Thái Ngọc Duy--- refs.h | 4 ++-- t/t1405-main-ref-store.sh | 6 ++++++ t/t1406-submodule-ref-store.sh | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-)
refs.h +2 -2
@@ -230,7 +230,7 @@ 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);
@@ -370,7 +370,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 +* 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);
t/t1405-main-ref-store.sh +6 -0
@@ -53,6 +53,12 @@ test_expect_success 'for_each_ref(refs/heads/)' ' 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 &&
t/t1406-submodule-ref-store.sh +6 -0
@@ -47,6 +47,12 @@ test_expect_success 'for_each_ref(refs/heads/)' ' 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 &&
Signature · 1 line
2.11.0.157.gd943d85
Quoted 10 lines · Nguyễn Thái Ngọc Duy
v7 is mostly about style changes except the one bug in
test-ref-store.c, missingsetup_git_directory().There's one new patch, 03/28, which maps to the "if (!refs)" deletion in the interdiff.
The one comment from v6 I haven't addressed in v7 is whether to delete
REF_STORE_READ. But if it is deleted, I think I'm doing it in nd/worktree-kill-parse-ref, which is partly about cleanup refs code anyway, to avoid another re-roll in this series.
I reviewed v7 pretty carefully, and send a couple of minor comments. But with or without changes, it looks good to me and the whole series is
Thanks!
Michael
Quoted 12 lines · Michael Haggerty
Quoted 10 lines · Nguyễn Thái Ngọc Duy
v7 is mostly about style changes except the one bug in
test-ref-store.c, missingsetup_git_directory().There's one new patch, 03/28, which maps to the "if (!refs)" deletion in the interdiff.
The one comment from v6 I haven't addressed in v7 is whether to delete
REF_STORE_READ. But if it is deleted, I think I'm doing it in nd/worktree-kill-parse-ref, which is partly about cleanup refs code anyway, to avoid another re-roll in this series.
Quoted 6 lines
I reviewed v7 pretty carefully, and send a couple of minor comments. But with or without changes, it looks good to me and the whole series is
Reviewed-by Michael Haggerty <[email protected]>Thanks!
Thanks. The "What's cooking" report at the end of the last month marked this topic to wait for a few days for comments before moving to 'next'. Now it has been more than a few days, so I'll move it to the normal "will merge to 'next'" category.
Quoted 8 lines · Nguyễn Thái Ngọc Duy
I'll be sending two more follow-up series, if you are interested, soon:
1) v2 of nd/worktree-gc-protection
which kills
parse_ref()inworktree.c_and_set_worktree_head_symref()infiles-backend.c. Both are bad things that should not have happened. (PS. The topic name is misleading as this is mostly about eliminating warts, unless Junio intended to combine my second series as well)
Your description sounded that these two are just preparatory step for the main one that would soon follow, and that was why these two patches landed on a topic named as such without any of its friends (which were yet to come). If you prefer to keep these a separate preparatory step from the remainder and have them graduate sooner, let's do so, as that is my preference as well.
Rename it "nd/worktree-kill-parse-ref" perhaps?
Quoted 11 lines
This series introduces
get_worktree_ref_store()and adds two new APIsrefs_resolve_ref_unsafe()andrefs_create_symref(). I'm still not sure if therefs_prefix is good naming, but I had to pick something to get things going. Name suggestions are welcome.2) the real worktree-gc-protection
This series adds a bunch of new refs API, enough for
revision.cto traverses all sorts of refs with a ref store instead of "submodule". Many_submoduleAPI are removed as a result because they no longer have any callers (yay!). One of them remains though.
Yay indeed.
Quoted 8 lines · Junio C Hamano
Quoted 6 lines · Nguyễn Thái Ngọc Duy
I'll be sending two more follow-up series, if you are interested, soon:
1) v2 of nd/worktree-gc-protection
...
2) the real worktree-gc-protection
Quoted 6 lines
Quoted 4 lines
This series adds a bunch of new refs API, enough for
revision.cto traverses all sorts of refs with a ref store instead of "submodule". Many_submoduleAPI are removed as a result because they no longer have any callers (yay!). One of them remains though.Yay indeed.
Having said all that, I have a bad news.
I won't be able to queue this as-is, as this heavily conflicts with mh/ref-remove-empty-directory that has already been cooking in 'next' for some time. I started trying conflict resolution myself and it seemed doable, but stopped after finishing perhaps 40% of it, as I cannot afford the same amount of time for conflict resolution every time the series gets rerolled.
If the topic is rebased on the result of doing:
- checking out master^0
- merging mh/ref-remove-empty-directory on it
- mergeing mh/submodule-hash on the result
I suspect that we might be able start cooking it in 'pu' sooner, but I cannot spend any more time on this topic today so I'd stop analyzing the situation for now.
Quoted 11 lines · Junio C Hamano
Quoted 8 lines · Nguyễn Thái Ngọc Duy
I'll be sending two more follow-up series, if you are interested, soon:
1) v2 of nd/worktree-gc-protection
which kills
parse_ref()inworktree.c_and_set_worktree_head_symref()infiles-backend.c. Both are bad things that should not have happened. (PS. The topic name is misleading as this is mostly about eliminating warts, unless Junio intended to combine my second series as well)
Quoted 8 lines
Your description sounded that these two are just preparatory step for the main one that would soon follow, and that was why these two patches landed on a topic named as such without any of its friends (which were yet to come). If you prefer to keep these a separate preparatory step from the remainder and have them graduate sooner, let's do so, as that is my preference as well.
Rename it "nd/worktree-kill-parse-ref" perhaps?
That's exactly my branch name (minus the nd/)
Signature · 1 line
Duy