Remove submodule from files-backend.c
cover Remove submodule from files-backend.c
This is on top of mh/submodule-hash, it:
- centralizes path manipulation around submodule, $GIT_DIR... in files-backend.c to a new function files_path() with the intention to make it easier to change later. files_path() is destined to become
strbuf_addbuf(&sb, refs->gitdir);
strbuf_complete(&sb, '/');
strbuf_vaddf(&sb, fmt, vap);but that can only be achieved once we get compound ref store.
- removes git_path() and submodule_git_path() from files-backend.c. No more magic path translation as far as ref backend is concerned.
- moves submodule path resolution code outside the backend. files-backend is now oblivious of submodules and in theory a submodule ref-store supports all operations (but I could be wrong, I didn't stare hard)
- exposes get_submodule_ref_store() and get_main_ref_store() as public API. A new set of API around ref-store will be added. And get_worktree_ref_store() of course. The *_submodule() API might be removed, we'll see.
The problem with set_worktree_head_symref() (which peeks into another gitdir) should be solved once we have get_worktree_ref_store(). That's my next step.
Compound ref store will have to wait until I'm done with my gc-in-worktree problem as I think I can live without it for now. I think after compound ref store is in place, adding lmdb backend back should be much cleaner because it does not care about either submodules or worktrees.
Nguyễn Thái Ngọc Duy (11):
refs-internal.c: make files_log_ref_write() static
files-backend: convert git_path() to strbuf_git_path()
files-backend: add files_path()
files-backend: replace *git_path*() with files_path() refs.c: share is_per_worktree_ref() to files-backend.c refs-internal.h: correct is_per_worktree_ref()
files-backend: remove the use of git_path()
refs.c: factor submodule code out of get_ref_store()
refs: move submodule code out of files-backend.c
files-backend: remove submodule_allowed from files_downcast()
refs: split and make get_*_ref_store() public API
refs.c | 125 ++++++++++++------ refs.h | 13 ++ refs/files-backend.c | 350 ++++++++++++++++++++++++++++++--------------------- refs/refs-internal.h | 28 ++--- 4 files changed, 316 insertions(+), 200 deletions(-)
Signature · 1 line
2.11.0.157.gd943d85
PATCH 1/11 refs-internal.c: make files_log_ref_write() static
Created 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
@@ -222,10 +222,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 01/11] refs-internal.c: make files_log_ref_write() static
Quoted 14 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 +0
-0
refs/files-backend.c static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, · line 170
Quoted 6 lines
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);
Why? I don't like adding forward declarations unless it is absolutely necessary (ie mutually recursive functions), and even in the current 'pu' branch (@c04899d50), the definition of this function appears before all uses in this file. (ie, just add static to the definition).
What am I missing?
ATB,
Ramsay Jones
Quoted 19 lines
refs/files-backend.c +0
-0static struct ref_dir *get_ref_dir (struct ref_entry *entry) {refs/refs-internal.h +0
-4@@ -222,10 +222,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
Re: [PATCH 01/11] refs-internal.c: make files_log_ref_write() static
Quoted 30 lines · Ramsay Jones
Quoted 14 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 +0
-0refs/files-backend.c static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, · line 170
Quoted 6 lines
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);Why? I don't like adding forward declarations unless it is absolutely necessary (ie mutually recursive functions), and even in the current 'pu' branch (@c04899d50), the definition of this function appears before all uses in this file. (ie, just add static to the definition).
Quoted 1 line
What am I missing?
It may have been needed at one point. With all the code changes and movements, I guess I forgot to remove it.
Signature · 1 line
Duy
PATCH 2/11 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 | 114 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 24 deletions(-)
refs/files-backend.c +90 -24
@@ -2169,6 +2169,8 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)static int timeout_configured =0 ;static int timeout_value =1000 ;struct packed_ref_cache *packed_ref_cache; +struct strbuf sb =STRBUF_INIT ; +int ret;files_assert_main_repository (refs,"lock_packed_refs" );
@@ -2177,10 +2179,13 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) timeout_configured =1 ; } -if (hold_lock_file_for_update_timeout ( - &packlock,git_path ("packed-refs" ), - flags, timeout_value) <0 ) +strbuf_git_path (&sb,"packed-refs" ); + ret =hold_lock_file_for_update_timeout (&packlock, sb.buf, + flags, timeout_value); +strbuf_release (&sb); +if (ret <0 )return -1 ; +/* * Get the current packed-refs while holding the lock. If the * packed-refs file has been modified since we last read it,
@@ -2335,6 +2340,9 @@ static void try_remove_empty_parents(char *name)for (q = p; *q; q++) ;while (1 ) { +struct strbuf sb =STRBUF_INIT ; +int ret; +while (q > p && *q !='/' ) q--;while (q > p && *(q-1 ) =='/' )
@@ -2342,7 +2350,10 @@ static void try_remove_empty_parents(char *name)if (q == p)break ; *q ='\0' ; -if (rmdir (git_path ("%s" , name))) +strbuf_git_path (&sb,"%s" , name); + ret =rmdir (sb.buf); +strbuf_release (&sb); +if (ret)break ; } }
@@ -2431,7 +2442,11 @@ 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); +struct strbuf sb =STRBUF_INIT ; + +strbuf_git_path (&sb,"packed-refs" ); +unable_to_lock_message (sb.buf, errno, err); +strbuf_release (&sb);return -1 ; } packed =get_packed_refs (refs);
@@ -2529,11 +2544,12 @@ static int rename_tmp_log(const char *newrefname) {int attempts_remaining =4 ;struct strbuf path =STRBUF_INIT ; +struct strbuf tmp_renamed_log =STRBUF_INIT ;int ret =-1 ; - retry: -strbuf_reset (&path);strbuf_git_path (&path,"logs/%s" , newrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + retry:switch (safe_create_leading_directories_const (path.buf)) {case SCLD_OK :break ;/* success */
@@ -2546,7 +2562,7 @@ static int rename_tmp_log(const char *newrefname) goto out; } -if (rename (git_path (TMP_RENAMED_LOG ), path.buf)) { +if (rename (tmp_renamed_log.buf, path.buf)) {if ((errno==EISDIR || errno==ENOTDIR ) && --attempts_remaining >0 ) {/* * rename(a, b) when b is an existing
@@ -2574,6 +2590,7 @@ static int rename_tmp_log(const char *newrefname) ret =0 ; out:strbuf_release (&path); +strbuf_release (&tmp_renamed_log);return ret; }
@@ -2614,9 +2631,15 @@ 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 ; +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); + log = !lstat (sb_oldref.buf, &loginfo); +strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))return error ("reflog for %s is a symlink" , oldrefname);
@@ -2630,7 +2653,12 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log); +if (ret)return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno));
@@ -2709,13 +2737,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))) +strbuf_git_path (&sb_newref,"logs/%s" , newrefname); +strbuf_git_path (&sb_oldref,"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)); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG );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)); +strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log);return 1 ; }
@@ -3111,22 +3145,32 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static 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)
@@ -3181,7 +3225,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 ;
@@ -3287,7 +3333,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 ;
@@ -3369,12 +3417,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; }
@@ -3843,8 +3894,13 @@ static int files_transaction_commit(struct ref_store *ref_store, ret =TRANSACTION_GENERIC_ERROR ; goto cleanup; } -for_each_string_list_item (ref_to_delete, &refs_to_delete) -unlink_or_warn (git_path ("logs/%s" , ref_to_delete->string)); +for_each_string_list_item (ref_to_delete, &refs_to_delete) { +struct strbuf sb =STRBUF_INIT ; + +strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +unlink_or_warn (sb.buf); +strbuf_release (&sb); + }clear_loose_ref_cache (refs); cleanup:
@@ -4098,18 +4154,28 @@ 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_reset (&sb);if (get_shared_repository ()) { -adjust_shared_perm (git_path ("refs/heads" )); -adjust_shared_perm (git_path ("refs/tags" )); +strbuf_git_path (&sb,"refs/heads" ); +adjust_shared_perm (sb.buf); +strbuf_reset (&sb); +strbuf_git_path (&sb,"refs/tags" ); +adjust_shared_perm (sb.buf); } +strbuf_release (&sb);return 0 ; }
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH 02/11] files-backend: convert git_path() to strbuf_git_path()
Quoted 126 lines · Nguyễn Thái Ngọc Duy
git_path()and friends are going to be killed infiles-backend.cin near future. And because there's a risk with overwriting buffer ingit_path(), let's convert them all tostrbuf_git_path(). We'll have easier time killing/convertingstrbuf_git_path()then because we won't have to worry about memory management again.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 114 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 24 deletions(-)refs/files-backend.c +32
-9@@ -2169,6 +2169,8 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)static int timeout_configured =0 ;static int timeout_value =1000 ;struct packed_ref_cache *packed_ref_cache; +struct strbuf sb =STRBUF_INIT ; +int ret;files_assert_main_repository (refs,"lock_packed_refs" );@@ -2177,10 +2179,13 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) timeout_configured =1 ; } -if (hold_lock_file_for_update_timeout ( - &packlock,git_path ("packed-refs" ), - flags, timeout_value) <0 ) +strbuf_git_path (&sb,"packed-refs" ); + ret =hold_lock_file_for_update_timeout (&packlock, sb.buf, + flags, timeout_value); +strbuf_release (&sb); +if (ret <0 )return -1 ; +/* * Get the current packed-refs while holding the lock. If the * packed-refs file has been modified since we last read it, @@ -2335,6 +2340,9 @@ static void try_remove_empty_parents(char *name)for (q = p; *q; q++) ;while (1 ) { +struct strbuf sb =STRBUF_INIT ; +int ret; +while (q > p && *q !='/' ) q--;while (q > p && *(q-1 ) =='/' )@@ -2342,7 +2350,10 @@ static void try_remove_empty_parents(char *name)if (q == p)break ; *q ='\0' ; -if (rmdir (git_path ("%s" , name))) +strbuf_git_path (&sb,"%s" , name); + ret =rmdir (sb.buf); +strbuf_release (&sb); +if (ret)break ; } }@@ -2431,7 +2442,11 @@ 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); +struct strbuf sb =STRBUF_INIT ; + +strbuf_git_path (&sb,"packed-refs" ); +unable_to_lock_message (sb.buf, errno, err); +strbuf_release (&sb);return -1 ; } packed =get_packed_refs (refs);@@ -2529,11 +2544,12 @@ static int rename_tmp_log(const char *newrefname) {int attempts_remaining =4 ;struct strbuf path =STRBUF_INIT ; +struct strbuf tmp_renamed_log =STRBUF_INIT ;int ret =-1 ; - retry: -strbuf_reset (&path);strbuf_git_path (&path,"logs/%s" , newrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + retry:switch (safe_create_leading_directories_const (path.buf)) {case SCLD_OK :break ;/* success */ @@ -2546,7 +2562,7 @@ static int rename_tmp_log(const char *newrefname) goto out; } -if (rename (git_path (TMP_RENAMED_LOG ), path.buf)) { +if (rename (tmp_renamed_log.buf, path.buf)) {if ((errno==EISDIR || errno==ENOTDIR ) && --attempts_remaining >0 ) {/* * rename(a, b) when b is an existing @@ -2574,6 +2590,7 @@ static int rename_tmp_log(const char *newrefname) ret =0 ; out:strbuf_release (&path); +strbuf_release (&tmp_renamed_log);return ret; }@@ -2614,9 +2631,15 @@ 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 ; +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); + log = !lstat (sb_oldref.buf, &loginfo); +strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))return error ("reflog for %s is a symlink" , oldrefname);
refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2658
Quoted 7 lines
refs/files-backend.c +3
-1@@ -2630,7 +2653,12 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf);
It probably won't make too much difference, but the two code sequences above are not similar in terms of side-effects when 'log' is false. In that case, the two calls to git_path() and the call to rename() are not made in the original code. In the new sequence, the two calls to strbuf_git_path() are always made (but rename() is not).
Quoted 7 lines
refs/files-backend.c +3
-0+strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log); +if (ret)return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno));
refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2742
Quoted 7 lines
refs/files-backend.c +3
-1@@ -2709,13 +2737,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))) +strbuf_git_path (&sb_newref,"logs/%s" , newrefname); +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +if (logmoved &&rename (sb_newref.buf, sb_oldref.buf))
ditto
refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2747
Quoted 6 lines
refs/files-backend.c +2
-1error ("unable to restore logfile %s from %s: %s" , oldrefname, newrefname,strerror (errno)); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG );if (!logmoved && log && -rename (git_path (TMP_RENAMED_LOG ),git_path ("logs/%s" , oldrefname))) +rename (tmp_renamed_log.buf, sb_oldref.buf))
similar
refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2755
Quoted 8 lines
refs/files-backend.c +3
-0error ("unable to restore logfile %s from " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno)); +strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log);return 1 ; }
ATB,
Ramsay Jones
PATCH 3/11 files-backend: add files_path()
In reply to Nguyễn Thái Ngọc DuyThis will be the replacement for both git_path() and git_path_submodule() in this file. The idea is backend takes a git path and use that, oblivious of submodule, linked worktrees and such.
This is the middle step towards that. Eventually the "submodule" field in 'struct files_ref_store' should be replace by "gitdir". And a compound ref_store is created to combine two files backends together, one represents the shared refs in $GIT_COMMON_DIR, one per-worktree. At that point, files_path() becomes a wrapper of strbuf_vaddf().
--- refs/files-backend.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
refs/files-backend.c +20 -0
@@ -169,6 +169,9 @@ static int files_log_ref_write(const char *refname, const unsigned char *old_sha const unsigned char *new_sha1, const char *msg, int flags, struct strbuf *err); +void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) __attribute__((format (printf,3 ,4 ))); +static struct ref_dir *get_ref_dir (struct ref_entry *entry) {struct ref_dir *dir;
@@ -930,6 +933,23 @@ struct files_ref_store {/* Lock used for the main packed-refs file: */ static struct lock_file packlock; +void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) +{ +struct strbuf tmp =STRBUF_INIT ; +va_list vap; + +va_start (vap, fmt); +strbuf_vaddf (&tmp, fmt, vap); +va_end (vap); +if (refs->submodule) +strbuf_git_path_submodule (sb, refs->submodule, +"%s" , tmp.buf); +else +strbuf_git_path (sb,"%s" , tmp.buf); +strbuf_release (&tmp); +} +/* * Increment the reference count of *packed_refs. */
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH 03/11] files-backend: add files_path()
Quoted 20 lines · Nguyễn Thái Ngọc Duy
This will be the replacement for both
git_path()andgit_path_submodule()in this file. The idea is backend takes a git path and use that, oblivious of submodule, linked worktrees and such.This is the middle step towards that. Eventually the "submodule" field in 'struct
files_ref_store' should be replace by "gitdir". And a compoundref_storeis created to combine two files backends together, one represents the shared refs in $GIT_COMMON_DIR, one per-worktree. At that point,files_path()becomes a wrapper ofstrbuf_vaddf().Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)refs/files-backend.c +0
-0
refs/files-backend.c static int files_log_ref_write(const char *refname, const unsigned char *old_sha · line 174
Quoted 6 lines
refs/files-backend.c +3
-0@@ -169,6 +169,9 @@ static int files_log_ref_write(const char *refname, const unsigned char *old_sha const unsigned char *new_sha1, const char *msg, int flags, struct strbuf *err); +void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) __attribute__((format (printf,3 ,4 ))); +
Why?
Quoted 18 lines
refs/files-backend.c +10
-0static struct ref_dir *get_ref_dir (struct ref_entry *entry) {struct ref_dir *dir;@@ -930,6 +933,23 @@ struct files_ref_store {/* Lock used for the main packed-refs file: */ static struct lock_file packlock; +void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) +{ +struct strbuf tmp =STRBUF_INIT ; +va_list vap; + +va_start (vap, fmt); +strbuf_vaddf (&tmp, fmt, vap); +va_end (vap); +if (refs->submodule)
refs/files-backend.c struct files_ref_store { · line 955
Quoted 10 lines
refs/files-backend.c +7
-0+strbuf_git_path_submodule (sb, refs->submodule, +"%s" , tmp.buf); + else + strbuf_git_path(sb, "%s", tmp.buf); +strbuf_release (&tmp); +} +/* * Increment the reference count of *packed_refs. */
ATB,
Ramsay Jones
PATCH 4/11 files-backend: replace *git_path*() with files_path()
In reply to Nguyễn Thái Ngọc DuyThis centralizes all path rewriting of files-backend.c in one place so we have easier time removing the path rewriting later. There could be some hidden indirect git_path() though, I didn't audit the code to the bottom.
Side note: set_worktree_head_symref() is a bad boy and should not be in files-backend.c (probably should not exist in the first place). But we'll leave it there until we have better multi-worktree support in refs before we update it.
--- refs/files-backend.c | 193 ++++++++++++++++++++++++++------------------------- 1 file changed, 98 insertions(+), 95 deletions(-)
refs/files-backend.c +98 -95
@@ -165,12 +165,13 @@ 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); -void files_path (struct files_ref_store *refs,struct strbuf *sb, -const char *fmt, ...) __attribute__((format (printf,3 ,4 ))); +static void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) __attribute__((format (printf,3 ,4 )));static struct ref_dir *get_ref_dir (struct ref_entry *entry) {
@@ -933,8 +934,8 @@ struct files_ref_store {/* Lock used for the main packed-refs file: */ static struct lock_file packlock; -void files_path (struct files_ref_store *refs,struct strbuf *sb, -const char *fmt, ...) +static void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) {struct strbuf tmp =STRBUF_INIT ;va_list vap;
@@ -1180,12 +1181,10 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)static struct packed_ref_cache *get_packed_ref_cache (struct files_ref_store *refs) {char *packed_refs_file; +struct strbuf sb =STRBUF_INIT ; -if (refs->submodule) - packed_refs_file =git_pathdup_submodule (refs->submodule, -"packed-refs" ); -else - packed_refs_file =git_pathdup ("packed-refs" ); +files_path (refs, &sb,"packed-refs" ); + packed_refs_file =strbuf_detach (&sb,NULL );if (refs->packed && !stat_validity_check (&refs->packed->validity, packed_refs_file))
@@ -1251,10 +1250,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)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_path (refs, &path,"%s" , dirname); path_baselen = path.len;if (err) {
@@ -1396,10 +1392,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_path (refs, &sb_path,"%s" , refname); path = sb_path.buf;
@@ -1587,7 +1580,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_path (refs, &ref_file,"%s" , refname); retry:switch (safe_create_leading_directories (ref_file.buf)) {
@@ -2054,7 +2047,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_path (refs, &ref_file,"%s" , refname); resolved = !!resolve_ref_unsafe (refname, resolve_flags, lock->old_oid.hash, type);if (!resolved && errno ==EISDIR ) {
@@ -2199,7 +2192,7 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) timeout_configured =1 ; } -strbuf_git_path (&sb,"packed-refs" ); +files_path (refs, &sb,"packed-refs" ); ret =hold_lock_file_for_update_timeout (&packlock, sb.buf, flags, timeout_value);strbuf_release (&sb);
@@ -2345,7 +2338,7 @@ static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data)* Remove empty parents, but spare refs/ and immediate subdirs. * Note: munges *name. */ -static void try_remove_empty_parents (char *name) +static void try_remove_empty_parents (struct files_ref_store *refs,char *name) {char *p, *q;int i;
@@ -2370,7 +2363,7 @@ static void try_remove_empty_parents(char *name)if (q == p)break ; *q ='\0' ; -strbuf_git_path (&sb,"%s" , name); +files_path (refs, &sb,"%s" , name); ret =rmdir (sb.buf);strbuf_release (&sb);if (ret)
@@ -2379,7 +2372,7 @@ static void try_remove_empty_parents(char *name) }/* 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 ;
@@ -2399,13 +2392,13 @@ static void prune_ref(struct ref_to_prune *r) }ref_transaction_free (transaction);strbuf_release (&err); -try_remove_empty_parents (r->name); +try_remove_empty_parents (refs, r->name); } -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; } }
@@ -2428,7 +2421,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 ; }
@@ -2464,7 +2457,7 @@ static int repack_without_refs(struct files_ref_store *refs,if (lock_packed_refs (refs,0 )) {struct strbuf sb =STRBUF_INIT ; -strbuf_git_path (&sb,"packed-refs" ); +files_path (refs, &sb,"packed-refs" );unable_to_lock_message (sb.buf, errno, err);strbuf_release (&sb);return -1 ;
@@ -2560,15 +2553,15 @@ static int files_delete_refs(struct ref_store *ref_store,*/ #define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log" -static int rename_tmp_log (const char *newrefname) +static int rename_tmp_log (struct files_ref_store *refs,const char *newrefname) {int attempts_remaining =4 ;struct strbuf path =STRBUF_INIT ;struct strbuf tmp_renamed_log =STRBUF_INIT ;int ret =-1 ; -strbuf_git_path (&path,"logs/%s" , newrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &path,"logs/%s" , newrefname); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); retry:switch (safe_create_leading_directories_const (path.buf)) {case SCLD_OK :
@@ -2657,7 +2650,7 @@ 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); +files_path (refs, &sb_oldref,"logs/%s" , oldrefname); log = !lstat (sb_oldref.buf, &loginfo);strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))
@@ -2673,8 +2666,8 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &sb_oldref,"logs/%s" , oldrefname); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf);strbuf_release (&sb_oldref);strbuf_release (&tmp_renamed_log);
@@ -2701,7 +2694,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_path (refs, &path,"%s" , newrefname); result =remove_empty_directories (&path);strbuf_release (&path);
@@ -2715,7 +2708,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;
@@ -2757,12 +2750,12 @@ static int files_rename_ref(struct ref_store *ref_store, log_all_ref_updates = flag; rollbacklog: -strbuf_git_path (&sb_newref,"logs/%s" , newrefname); -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +files_path (refs, &sb_newref,"logs/%s" , newrefname); +files_path (refs, &sb_oldref,"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)); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG );if (!logmoved && log &&rename (tmp_renamed_log.buf, sb_oldref.buf)) error("unable to restore logfile %s from "TMP_RENAMED_LOG": %s",
@@ -2818,11 +2811,13 @@ static int commit_ref(struct ref_lock *lock)* should_autocreate_reflog returns non-zero. Otherwise, create it * regardless of the ref name. Fill in *err and return -1 on failure. */ -static int log_ref_setup (const char *refname,struct strbuf *logfile,struct strbuf *err,int force_create) +static int log_ref_setup (struct files_ref_store *refs,const char *refname, +struct strbuf *logfile,struct strbuf *err, +int force_create) {int logfd, oflags =O_APPEND |O_WRONLY ; -strbuf_git_path (logfile,"logs/%s" , refname); +files_path (refs, logfile,"logs/%s" , refname);if (force_create ||should_autocreate_reflog (refname)) {if (safe_create_leading_directories (logfile->buf) <0 ) { strbuf_addf(err, "unable to create directory for '%s': "
@@ -2865,11 +2860,10 @@ static int files_create_reflog(struct ref_store *ref_store, {int ret;struct strbuf sb =STRBUF_INIT ; +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"create_reflog" ); -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"create_reflog" ); - - ret =log_ref_setup (refname, &sb, err, force_create); + ret =log_ref_setup (refs, refname, &sb, err, force_create);strbuf_release (&sb);return ret; }
@@ -2900,7 +2894,8 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,return 0 ; } -static int log_ref_write_1 (const char *refname,const unsigned char *old_sha1, +static int log_ref_write_1 (struct files_ref_store *refs, +const char *refname,const unsigned char *old_sha1,const unsigned char *new_sha1,const char *msg,struct strbuf *logfile,int flags,struct strbuf *err)
@@ -2910,7 +2905,7 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,if (log_all_ref_updates <0 ) log_all_ref_updates = !is_bare_repository (); - result =log_ref_setup (refname, logfile, err, flags &REF_FORCE_CREATE_REFLOG ); + result =log_ref_setup (refs, refname, logfile, err, flags &REF_FORCE_CREATE_REFLOG );if (result)return result;
@@ -2934,21 +2929,23 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,return 0 ; } -static int log_ref_write (const char *refname,const unsigned char *old_sha1, +static int 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) { -return files_log_ref_write (refname, old_sha1, new_sha1, msg, flags, - err); +return files_log_ref_write (refs, refname, old_sha1, new_sha1, + msg, flags, err); } -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) {struct strbuf sb =STRBUF_INIT ; -int ret =log_ref_write_1 (refname, old_sha1, new_sha1, msg, &sb, flags, - err); +int ret =log_ref_write_1 (refs, refname, old_sha1, new_sha1, msg, + &sb, flags, err);strbuf_release (&sb);return ret; }
@@ -3005,7 +3002,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 (log_ref_write (lock->ref_name, lock->old_oid.hash, sha1, logmsg,0 , err)) { +if (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" , lock->ref_name, old_msg);
@@ -3036,8 +3034,8 @@ 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 (log_ref_write ("HEAD" , lock->old_oid.hash, sha1, - logmsg,0 , &log_err)) { +if (log_ref_write (refs,"HEAD" , lock->old_oid.hash, + sha1, logmsg,0 , &log_err)) {error ("%s" , log_err.buf);strbuf_release (&log_err); }
@@ -3069,23 +3067,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) && -log_ref_write (refname, lock->old_oid.hash, new_sha1, logmsg,0 , &err)) { +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 ; }
@@ -3093,7 +3094,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);
@@ -3122,13 +3123,19 @@ 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) { +/* +* 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 ;
@@ -3155,7 +3162,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target) lock->lk = &head_lock; lock->ref_name =xstrdup (head_rel); - ret =create_symref_locked (lock, head_rel, target,NULL ); + ret =create_symref_locked (refs, lock, head_rel, target,NULL );unlock_ref (lock);/* will free lock */ strbuf_release (&head_path);
@@ -3165,14 +3172,13 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static int files_reflog_exists (struct ref_store *ref_store,const char *refname) { +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"reflog_exists" );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_path (refs, &sb,"logs/%s" , refname); ret = !lstat (sb.buf, &st) &&S_ISREG (st.st_mode);strbuf_release (&sb);return ret;
@@ -3181,13 +3187,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_path (refs, &sb,"logs/%s" , refname); ret =remove_path (sb.buf);strbuf_release (&sb);return ret;
@@ -3237,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_path (refs, &sb,"logs/%s" , refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3346,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_path (refs, &sb,"logs/%s" , refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3435,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_path (refs, &sb,"logs" ); iter->dir_iterator =dir_iterator_begin (sb.buf);strbuf_release (&sb);return ref_iterator;
@@ -3867,8 +3869,8 @@ static int files_transaction_commit(struct ref_store *ref_store,if (update->flags &REF_NEEDS_COMMIT || update->flags &REF_LOG_ONLY ) { -if (log_ref_write (lock->ref_name, lock->old_oid.hash, - update->new_sha1, +if (log_ref_write (refs, lock->ref_name, + lock->old_oid.hash, update->new_sha1, update->msg, update->flags, err)) {char *old_msg =strbuf_detach (err,NULL );
@@ -3917,7 +3919,7 @@ static int files_transaction_commit(struct ref_store *ref_store,for_each_string_list_item (ref_to_delete, &refs_to_delete) {struct strbuf sb =STRBUF_INIT ; -strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +files_path (refs, &sb,"logs/%s" , ref_to_delete->string);unlink_or_warn (sb.buf);strbuf_release (&sb); }
@@ -4079,6 +4081,7 @@ static int files_reflog_expire(struct ref_store *ref_store,int status =0 ;int type;struct strbuf err =STRBUF_INIT ; +struct strbuf sb =STRBUF_INIT ;memset (&cb,0 ,sizeof (cb)); cb.flags = flags;
@@ -4103,7 +4106,8 @@ static int files_reflog_expire(struct ref_store *ref_store,return 0 ; } - log_file =git_pathdup ("logs/%s" , refname); +files_path (refs, &sb,"logs/%s" , refname); + log_file =strbuf_detach (&sb,NULL );if (!(flags &EXPIRE_REFLOGS_DRY_RUN )) {/* * Even though holding $GIT_DIR/logs/$reflog.lock has
@@ -4174,25 +4178,24 @@ 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_path (refs, &sb,"refs/heads" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_path (refs, &sb,"refs/tags" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb);if (get_shared_repository ()) { -strbuf_git_path (&sb,"refs/heads" ); +files_path (refs, &sb,"refs/heads" );adjust_shared_perm (sb.buf);strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_path (refs, &sb,"refs/tags" );adjust_shared_perm (sb.buf); }strbuf_release (&sb);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH 04/11] files-backend: replace *git_path*() with files_path()
Quoted 21 lines · Nguyễn Thái Ngọc Duy
This centralizes all path rewriting of
files-backend.cin one place so we have easier time removing the path rewriting later. There could be some hidden indirectgit_path()though, I didn't audit the code to the bottom.Side note:
set_worktree_head_symref()is a bad boy and should not be infiles-backend.c(probably should not exist in the first place). But we'll leave it there until we have better multi-worktree support in refs before we update it.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 193 ++++++++++++++++++++++++++------------------------- 1 file changed, 98 insertions(+), 95 deletions(-)refs/files-backend.c +0
-0@@ -165,12 +165,13 @@ static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, const char *dirname, size_t len,
refs/files-backend.c static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, · line 173
Quoted 10 lines
refs/files-backend.c +2
-3int 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); -void files_path (struct files_ref_store *refs,struct strbuf *sb, -const char *fmt, ...) __attribute__((format (printf,3 ,4 )));
You only added this in the last commit, so maybe mark it static in the previous patch! Also, just in case you were wondering, the 'Why?' of the previous email was, "Why do you need this forward declaration?" (hint: you don't ;-)
Quoted 6 lines
refs/files-backend.c +2
-0+static void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) __attribute__((format (printf,3 ,4 )));static struct ref_dir *get_ref_dir (struct ref_entry *entry) {
refs/files-backend.c struct files_ref_store { · line 941
Quoted 10 lines
refs/files-backend.c +2
-2@@ -933,8 +934,8 @@ struct files_ref_store {/* Lock used for the main packed-refs file: */ static struct lock_file packlock; -void files_path (struct files_ref_store *refs,struct strbuf *sb, -const char *fmt, ...) +static void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) {struct strbuf tmp =STRBUF_INIT ;va_list vap;
ATB,
Ramsay Jones
Re: [PATCH 04/11] files-backend: replace *git_path*() with files_path()
Quoted 7 lines · Ramsay Jones
refs/files-backend.c static struct ref_entry *create_dir_entry(struct files_ref_store *ref_store, · line 173
Quoted 2 lines
refs/files-backend.c +0
-2-void files_path (struct files_ref_store *refs,struct strbuf *sb, -const char *fmt, ...) __attribute__((format (printf,3 ,4 )));You only added this in the last commit, so maybe mark it static in the previous patch! Also, just in case you were wondering, the 'Why?' of the previous email was, "Why do you need this forward declaration?" (hint: you don't ;-)
Yeah, my compiler considers unused static functions an error. But I guess I should adjust those million compiler flags instead of doing it like this. I'll need to check if it's an error with DEVELOPER_CFLAGS because people may bisect with that.
Signature · 1 line
Duy
PATCH 5/11 refs.c: share is_per_worktree_ref() to files-backend.c
In reply to Nguyễn Thái Ngọc Duy--- refs.c | 6 ------ refs/refs-internal.h | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-)
refs.c +0 -6
@@ -489,12 +489,6 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)return logs_found; } -static int is_per_worktree_ref (const char *refname) -{ -return !strcmp (refname,"HEAD" ) || -starts_with (refname,"refs/bisect/" ); -} -static int is_pseudoref_syntax (const char *refname) {const char *c;
refs/refs-internal.h +6 -0
@@ -651,4 +651,10 @@ const char *resolve_ref_recursively(struct ref_store *refs,int resolve_flags, unsigned char *sha1, int *flags); +static inline int is_per_worktree_ref (const char *refname) +{ +return !strcmp (refname,"HEAD" ) || +starts_with (refname,"refs/bisect/" ); +} +#endif /* REFS_REFS_INTERNAL_H */
Signature · 1 line
2.11.0.157.gd943d85
PATCH 6/11 refs-internal.h: correct is_per_worktree_ref()
In reply to Nguyễn Thái Ngọc DuyAll refs outside refs/ directory is per-worktree, not just HEAD.
--- refs/refs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
refs/refs-internal.h +1 -1
@@ -653,7 +653,7 @@ const char *resolve_ref_recursively(struct ref_store *refs,static inline int is_per_worktree_ref (const char *refname) { -return !strcmp (refname,"HEAD" ) || +return !starts_with (refname,"refs/" ) ||starts_with (refname,"refs/bisect/" ); }
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH 06/11] refs-internal.h: correct is_per_worktree_ref()
Quoted 12 lines · Nguyễn Thái Ngọc Duy
All refs outside refs/ directory is per-worktree, not just HEAD.
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/refs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)refs/refs-internal.h +0
-0
refs/refs-internal.h const char *resolve_ref_recursively(struct ref_store *refs, · line 657
Quoted 6 lines
refs/refs-internal.h +1
-1@@ -653,7 +653,7 @@ const char *resolve_ref_recursively(struct ref_store *refs,static inline int is_per_worktree_ref (const char *refname) { -return !strcmp (refname,"HEAD" ) || +return !starts_with (refname,"refs/" ) ||starts_with (refname,"refs/bisect/" );
you're loosing HEAD here? (assuming we get HEAD in short form here, as well as long form refs/HEAD)
Quoted 5 lines
refs/refs-internal.h +0
-1} --2.11.0.157.gd943d85
Re: [PATCH 06/11] refs-internal.h: correct is_per_worktree_ref()
Quoted 14 lines · Stefan Beller
Quoted 13 lines · Nguyễn Thái Ngọc Duy
All refs outside refs/ directory is per-worktree, not just HEAD.
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/refs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)refs/refs-internal.h +0
-0@@ -653,7 +653,7 @@ const char *resolve_ref_recursively(struct ref_store *refs,
Quoted 8 lines
refs/refs-internal.h const char *resolve_ref_recursively(struct ref_store *refs, · line 657
Quoted 5 lines
refs/refs-internal.h +1
-1static inline int is_per_worktree_ref (const char *refname) { -return !strcmp (refname,"HEAD" ) || +return !starts_with (refname,"refs/" ) ||starts_with (refname,"refs/bisect/" );you're loosing HEAD here? (assuming we get HEAD in short form here, as well as long form refs/HEAD)
I don't understand. if refname is HEAD then both !strcmp(...) and !starts_with(refname, "refs/") return 1. If it's refs/HEAD, both return 0. In other words, there's no functional changes?
Signature · 1 line
Duy
Re: [PATCH 06/11] refs-internal.h: correct is_per_worktree_ref()
Quoted 24 lines · Duy Nguyen
Quoted 14 lines · Stefan Beller
Quoted 13 lines · Nguyễn Thái Ngọc Duy
All refs outside refs/ directory is per-worktree, not just HEAD.
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/refs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)refs/refs-internal.h +0
-0@@ -653,7 +653,7 @@ const char *resolve_ref_recursively(struct ref_store *refs,Quoted 8 lines
refs/refs-internal.h const char *resolve_ref_recursively(struct ref_store *refs, · line 657
Quoted 5 lines
refs/refs-internal.h +1
-1static inline int is_per_worktree_ref (const char *refname) { -return !strcmp (refname,"HEAD" ) || +return !starts_with (refname,"refs/" ) ||starts_with (refname,"refs/bisect/" );you're loosing HEAD here? (assuming we get HEAD in short form here, as well as long form refs/HEAD)
Quoted 3 lines
I don't understand. if refname is HEAD then both !strcmp(...) and !starts_with(refname, "refs/") return 1. If it's refs/HEAD, both return 0. In other words, there's no functional changes?
eh, my bad. You're right.
PATCH 7/11 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 | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
refs/files-backend.c +18 -2
@@ -927,6 +927,9 @@ struct files_ref_store {*/ const char *submodule; +struct strbuf gitdir; +struct strbuf gitcommondir; +struct ref_entry *loose;struct packed_ref_cache *packed; };
@@ -939,6 +942,7 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb, {struct strbuf tmp =STRBUF_INIT ;va_list vap; +const char *ref;va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);
@@ -946,8 +950,12 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb,if (refs->submodule)strbuf_git_path_submodule (sb, refs->submodule,"%s" , tmp.buf); +else if (is_per_worktree_ref (tmp.buf) || + (skip_prefix (tmp.buf,"logs/" , &ref) && +is_per_worktree_ref (ref))) +strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf);else -strbuf_git_path (sb,"%s" , tmp.buf); +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf);strbuf_release (&tmp); }
@@ -1006,7 +1014,15 @@ 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); +strbuf_init (&refs->gitdir,0 ); +strbuf_init (&refs->gitcommondir,0 ); + +if (submodule) { + refs->submodule =xstrdup_or_null (submodule); + }else { +strbuf_addstr (&refs->gitdir,get_git_dir ()); +strbuf_addstr (&refs->gitcommondir,get_git_common_dir ()); + }return ref_store; }
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH 07/11] files-backend: remove the use of git_path()
refs/files-backend.c static struct ref_store *files_ref_store_create(const char *submodule) · line 1021
Quoted 3 lines
refs/files-backend.c +3
-0+ +if (submodule) { + refs->submodule =xstrdup_or_null (submodule);
drop the _or_null here?
So in this patch we have either
* submodule set
* or gitdir/gitcommondir set
which means that we exercise the commondir for regular repos. In the future when we want to be able to have a combination of worktrees and submodules this ought to be possible by setting submodule != NULL and still populating the gitdir/commondir buffers.
Thanks,
Stefan
Re: [PATCH 07/11] files-backend: remove the use of git_path()
Quoted 6 lines · Stefan Beller
refs/files-backend.c static struct ref_store *files_ref_store_create(const char *submodule) · line 1021
Quoted 3 lines
refs/files-backend.c +3
-0+ +if (submodule) { + refs->submodule =xstrdup_or_null (submodule);drop the
_or_nullhere?
Quoted 8 lines
So in this patch we have either
* submodule set
* or gitdir/gitcommondir setwhich means that we exercise the commondir for regular repos. In the future when we want to be able to have a combination of worktrees and submodules this ought to be possible by setting submodule != NULL and still populating the gitdir/commondir buffers.
You probably have seen it by now. In the near future, submodule is completely gone from here. We convert to a .git dir before we pass in here. In a farther future, gitcommondir will be gone too with all the per-worktree logic in this file. A linked worktree consists of two backends actually, one per-worktree (which remains files-based), the other for shared refs, which could be files, lmdb or whatever. Stacking up submodule on top of a linked worktree should not be a problem.
Signature · 1 line
Duy
PATCH 8/11 refs.c: factor submodule code out of get_ref_store()
In reply to Nguyễn Thái Ngọc DuyThis code is going to be expanded a bit soon. Keep it out for better readability later.
--- refs.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
refs.c +14 -8
@@ -1445,6 +1445,18 @@ static struct ref_store *lookup_ref_store(const char *submodule)return entry ? entry->refs :NULL ; } +static struct ref_store *init_submodule_ref_store (const char *submodule) +{ +struct strbuf submodule_sb =STRBUF_INIT ; +struct ref_store *refs =NULL ; + +strbuf_addstr (&submodule_sb, submodule); +if (is_nonbare_repository_dir (&submodule_sb)) + refs =ref_store_init (submodule); +strbuf_release (&submodule_sb); +return refs; +} +struct ref_store *get_ref_store (const char *submodule) {struct ref_store *refs;
@@ -1457,14 +1469,8 @@ struct ref_store *get_ref_store(const char *submodule) }else { refs =lookup_ref_store (submodule); -if (!refs) { -struct strbuf submodule_sb =STRBUF_INIT ; - -strbuf_addstr (&submodule_sb, submodule); -if (is_nonbare_repository_dir (&submodule_sb)) - refs =ref_store_init (submodule); -strbuf_release (&submodule_sb); - } +if (!refs) + refs =init_submodule_ref_store (submodule); }return refs;
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH 08/11] refs.c: factor submodule code out of get_ref_store()
Quoted 5 lines · Nguyễn Thái Ngọc Duy
This code is going to be expanded a bit soon. Keep it out for better readability later.
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>---
Looks good,
Thanks,
Stefan
PATCH 9/11 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().
The new code in init_submodule_ref_store() is basically a copy of strbuf_git_path_submodule().
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() follows shortly. It's separate to keep noises from this patch.
--- refs.c | 48 +++++++++++++++++++++++++++++++++++++++++------- refs/files-backend.c | 25 +++++++------------------ refs/refs-internal.h | 6 +++--- 3 files changed, 51 insertions(+), 28 deletions(-)
refs.c +41 -7
@@ -9,6 +9,7 @@#include "refs/refs-internal.h" #include "object.h" #include "tag.h" +#include "submodule-config.h" /* * List of all available backends
@@ -1410,7 +1411,7 @@ static void register_ref_store(struct ref_store *refs, const char *submodule)* Create, record, and return a ref_store instance for the specified * submodule (or the main repository if submodule is NULL). */ -static struct ref_store *ref_store_init (const char *submodule) +static struct ref_store *ref_store_init (const char *submodule,const char *gitdir) {const char *be_name ="files" ;struct ref_storage_be *be =find_ref_storage_backend (be_name);
@@ -1419,7 +1420,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);register_ref_store (refs, submodule);return refs; }
@@ -1445,15 +1446,48 @@ static struct ref_store *lookup_ref_store(const char *submodule)return entry ? entry->refs :NULL ; } -static struct ref_store *init_submodule_ref_store (const char *submodule) +static struct ref_store *init_submodule_ref_store (const char *path) {struct strbuf submodule_sb =STRBUF_INIT ; +struct strbuf git_submodule_common_dir =STRBUF_INIT ; +struct strbuf git_submodule_dir =STRBUF_INIT ; +struct strbuf buf =STRBUF_INIT ; +const char *git_dir; +const struct submodule *sub;struct ref_store *refs =NULL ; -strbuf_addstr (&submodule_sb, submodule); -if (is_nonbare_repository_dir (&submodule_sb)) - refs =ref_store_init (submodule); +strbuf_addstr (&submodule_sb, path); +if (!is_nonbare_repository_dir (&submodule_sb)) + goto done; + +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) + goto done; +strbuf_reset (&buf); +strbuf_git_path (&buf,"%s/%s" ,"modules" , sub->name); + } +strbuf_addch (&buf,'/' ); +strbuf_addbuf (&git_submodule_dir, &buf); + + refs =ref_store_init (path, git_submodule_dir.buf); + +done: +strbuf_release (&git_submodule_dir); +strbuf_release (&git_submodule_common_dir);strbuf_release (&submodule_sb); +strbuf_release (&buf); +return refs; }
@@ -1465,7 +1499,7 @@ struct ref_store *get_ref_store(const char *submodule) refs =lookup_ref_store (NULL );if (!refs) - refs =ref_store_init (NULL ); + refs =ref_store_init (NULL ,NULL ); }else { refs =lookup_ref_store (submodule);
refs/files-backend.c +7 -18
@@ -920,13 +920,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; -struct strbuf gitdir;struct strbuf gitcommondir;
@@ -947,12 +940,9 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb,va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);va_end (vap); -if (refs->submodule) -strbuf_git_path_submodule (sb, refs->submodule, -"%s" , tmp.buf); -else if (is_per_worktree_ref (tmp.buf) || - (skip_prefix (tmp.buf,"logs/" , &ref) && -is_per_worktree_ref (ref))) +if (is_per_worktree_ref (tmp.buf) || + (skip_prefix (tmp.buf,"logs/" , &ref) && +is_per_worktree_ref (ref)))strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf);else strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf);
@@ -1007,7 +997,7 @@ 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;
@@ -1017,8 +1007,9 @@ static struct ref_store *files_ref_store_create(const char *submodule)strbuf_init (&refs->gitdir,0 );strbuf_init (&refs->gitcommondir,0 ); -if (submodule) { - refs->submodule =xstrdup_or_null (submodule); +if (gitdir) { +strbuf_addstr (&refs->gitdir, gitdir); +get_common_dir_noenv (&refs->gitcommondir, gitdir); }else {strbuf_addstr (&refs->gitdir,get_git_dir ());strbuf_addstr (&refs->gitcommondir,get_git_common_dir ());
@@ -1034,8 +1025,6 @@ 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); }/*
refs/refs-internal.h +3 -3
@@ -476,12 +476,12 @@ 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 +* Initialize the ref_store for the specified gitdir, or for the +* current repository if gitdir == NULL. These functions should call * base_ref_store_init() to initialize the shared part of the * ref_store and to record the ref_store for later lookup. */ -typedef struct ref_store *ref_store_init_fn (const char *submodule); +typedef 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 09/11] refs: move submodule code out of files-backend.c
Quoted 67 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().The new code in
init_submodule_ref_store()is basically a copy ofstrbuf_git_path_submodule().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()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 | 48 +++++++++++++++++++++++++++++++++++++++++------- refs/files-backend.c | 25 +++++++------------------ refs/refs-internal.h | 6 +++--- 3 files changed, 51 insertions(+), 28 deletions(-)refs.c +9
-5@@ -9,6 +9,7 @@#include "refs/refs-internal.h" #include "object.h" #include "tag.h" +#include "submodule-config.h" /* * List of all available backends @@ -1410,7 +1411,7 @@ static void register_ref_store(struct ref_store *refs, const char *submodule)* Create, record, and return a ref_store instance for the specified * submodule (or the main repository if submodule is NULL). */ -static struct ref_store *ref_store_init (const char *submodule) +static struct ref_store *ref_store_init (const char *submodule,const char *gitdir) {const char *be_name ="files" ;struct ref_storage_be *be =find_ref_storage_backend (be_name);@@ -1419,7 +1420,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);register_ref_store (refs, submodule);return refs; }@@ -1445,15 +1446,48 @@ static struct ref_store *lookup_ref_store(const char *submodule)return entry ? entry->refs :NULL ; } -static struct ref_store *init_submodule_ref_store (const char *submodule) +static struct ref_store *init_submodule_ref_store (const char *path) {struct strbuf submodule_sb =STRBUF_INIT ; +struct strbuf git_submodule_common_dir =STRBUF_INIT ; +struct strbuf git_submodule_dir =STRBUF_INIT ; +struct strbuf buf =STRBUF_INIT ; +const char *git_dir; +const struct submodule *sub;struct ref_store *refs =NULL ; -strbuf_addstr (&submodule_sb, submodule); -if (is_nonbare_repository_dir (&submodule_sb))
refs.c static struct ref_store *lookup_ref_store(const char *submodule) · line 1467
Quoted 10 lines
refs.c +9
-1- refs =ref_store_init (submodule); +strbuf_addstr (&submodule_sb, path); +if (!is_nonbare_repository_dir (&submodule_sb)) + goto done; + +strbuf_addstr (&buf, path); +strbuf_complete (&buf,'/' ); +strbuf_addstr (&buf,".git" ); + + git_dir =read_gitfile (buf.buf);
if buf.buf is a (git) directory as opposed to a git file, we error out in read_gitfile. Did you mean to use read_gitfile_gently here or rather even resolve_gitdir_gently ?
refs.c static struct ref_store *lookup_ref_store(const char *submodule) · line 1468
Quoted 1 line
refs.c +1
-0+if (git_dir) {
when not using the _gently version git_dir is always non NULL here (or we're dead)?
refs.c static struct ref_store *lookup_ref_store(const char *submodule) · line 1478
Quoted 10 lines
refs.c +10
-0+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) + goto done; +strbuf_reset (&buf); +strbuf_git_path (&buf,"%s/%s" ,"modules" , sub->name);
You can inline "modules" into the format string?
refs.c static struct ref_store *lookup_ref_store(const char *submodule) · line 1483
Quoted 5 lines
refs.c +5
-0+ } +strbuf_addch (&buf,'/' ); +strbuf_addbuf (&git_submodule_dir, &buf); + + refs =ref_store_init (path, git_submodule_dir.buf);
strbuf_detach (git_submodule_dir) here, such that we keep the string alive despite the release of the strbuf below?
so essentially this function
* takes a submodule path
* checks if there is a repo at the given path in the working tree
* resolves the gitfile if any
* if the gitfile could not resolve to a valid repo just make up the location to be $GIT_DIR/modules/<name>
sounds confusing to me. I need to reread it later.
refs.c static struct ref_store *lookup_ref_store(const char *submodule) · line 1486
Quoted 6 lines
refs.c +3
-2-if (submodule) { - refs->submodule =xstrdup_or_null (submodule); +if (gitdir) { +strbuf_addstr (&refs->gitdir, gitdir); +get_common_dir_noenv (&refs->gitcommondir, gitdir);
Oh I see. we loose the _or_null here, so my remark on the previous patch might be just unneeded work.
refs.c static struct ref_store *files_ref_store_create(const char *submodule) · line 1028
Quoted 10 lines
refs.c +0
-2}else {strbuf_addstr (&refs->gitdir,get_git_dir ());strbuf_addstr (&refs->gitcommondir,get_git_common_dir ());@@ -1034,8 +1025,6 @@ 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); }
In a followup we'd get rid of files_assert_main_repository presumably?
Thanks,
Stefan
Re: [PATCH 09/11] refs: move submodule code out of files-backend.c
Quoted 5 lines · Stefan Beller
Quoted 1 line
+
git_dir=read_gitfile(buf.buf);if buf.buf is a (git) directory as opposed to a git file, we error out in
read_gitfile. Did you mean to useread_gitfile_gentlyhere or rather evenresolve_gitdir_gently?
This is what strbuf_git_path_submodule() does. I don't know the backstory so I'm going to keep it as it is to keep the behavior exactly (or very close) as before. We can replace it with a better version (with explanation and all).
Quoted 16 lines
Quoted 1 line
+ if (
git_dir) {when not using the
_gentlyversiongit_diris always non NULL here (or we're dead)?refs.c static struct ref_store *lookup_ref_store(const char *submodule) · line 1478
Quoted 10 lines
refs.c +10
-0+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) + goto done; +strbuf_reset (&buf); +strbuf_git_path (&buf,"%s/%s" ,"modules" , sub->name);
Quoted 1 line
You can inline "modules" into the format string?
Hm.. because this is strbuf_git_path_submodule() code. Perhaps it's better to split it to a separate function and call it from here? Then you can make more improvements on top that benefit everybody.
Quoted 5 lines
Quoted 5 lines
} else { strbuf_addstr(&refs->gitdir, get_git_dir()); strbuf_addstr(&refs->gitcommondir, get_git_common_dir());refs/files-backend.c +0
-0@@ -1034,8 +1025,6 @@ static struct ref_store *files_ref_store_create(const char *submodule) static void files_assert_main_repository(struct files_ref_store *refs,
Quoted 8 lines
refs/files-backend.c static struct ref_store *files_ref_store_create(const char *submodule) · line 1028
Quoted 5 lines
refs/files-backend.c +0
-2const char *caller) { -if (refs->submodule) -die ("BUG: %s called for a submodule" , caller); }In a followup we'd get rid of
files_assert_main_repositorypresumably?
Yes. Can't delete it now because I would need to touch all callers.
Signature · 1 line
Duy
PATCH 10/11 files-backend: remove submodule_allowed from files_downcast()
In reply to Nguyễn Thái Ngọc DuySince submodule or not is irrelevant to files-backend after the last patch, remove the parameter from files_downcast() and kill files_assert_main_repository().
PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
--- refs/files-backend.c | 69 ++++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 48 deletions(-)
refs/files-backend.c +21 -48
@@ -1019,23 +1019,13 @@ 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. -*/ -static void files_assert_main_repository (struct files_ref_store *refs, -const char *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. */ -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, +const char *caller) {struct files_ref_store *refs;
@@ -1045,9 +1035,6 @@ static struct files_ref_store *files_downcast( refs = (struct files_ref_store *)ref_store; -if (!submodule_allowed) -files_assert_main_repository (refs, caller); -return refs; }
@@ -1383,7 +1370,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, struct strbuf *referent, unsigned int *type) { struct files_ref_store *refs = -files_downcast (ref_store,1 ,"read_raw_ref" ); +files_downcast (ref_store,"read_raw_ref" );struct strbuf sb_contents =STRBUF_INIT ;struct strbuf sb_path =STRBUF_INIT ;const char *path;
@@ -1576,7 +1563,6 @@ static int lock_raw_ref(struct files_ref_store *refs,int ret =TRANSACTION_GENERIC_ERROR ;assert (err); -files_assert_main_repository (refs,"lock_raw_ref" ); *type =0 ;
@@ -1800,7 +1786,7 @@ static enum peel_status peel_entry(struct ref_entry *entry, int repeel)static int files_peel_ref (struct ref_store *ref_store,const char *refname,unsigned char *sha1) { -struct files_ref_store *refs =files_downcast (ref_store,0 ,"peel_ref" ); +struct files_ref_store *refs =files_downcast (ref_store,"peel_ref" );int flag;unsigned char base[20 ];
@@ -1909,7 +1895,7 @@ static struct ref_iterator *files_ref_iterator_begin( const char *prefix, unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,1 ,"ref_iterator_begin" ); +files_downcast (ref_store,"ref_iterator_begin" );struct ref_dir *loose_dir, *packed_dir;struct ref_iterator *loose_iter, *packed_iter;struct files_ref_iterator *iter;
@@ -2042,7 +2028,6 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,int attempts_remaining =3 ;int resolved; -files_assert_main_repository (refs,"lock_ref_sha1_basic" );assert (err); lock =xcalloc (1 ,sizeof (struct ref_lock ));
@@ -2190,8 +2175,6 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)struct strbuf sb =STRBUF_INIT ;int ret; -files_assert_main_repository (refs,"lock_packed_refs" ); -if (!timeout_configured) {git_config_get_int ("core.packedrefstimeout" , &timeout_value); timeout_configured =1 ;
@@ -2231,8 +2214,6 @@ static int commit_packed_refs(struct files_ref_store *refs)int save_errno =0 ;FILE *out; -files_assert_main_repository (refs,"commit_packed_refs" ); -if (!packed_ref_cache->lock)die ("internal error: packed-refs not locked" );
@@ -2264,8 +2245,6 @@ static void rollback_packed_refs(struct files_ref_store *refs)struct packed_ref_cache *packed_ref_cache =get_packed_ref_cache (refs); -files_assert_main_repository (refs,"rollback_packed_refs" ); -if (!packed_ref_cache->lock)die ("internal error: packed-refs not locked" );rollback_lock_file (packed_ref_cache->lock);
@@ -2411,7 +2390,7 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune *r)static int files_pack_refs (struct ref_store *ref_store,unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"pack_refs" ); +files_downcast (ref_store,"pack_refs" );struct pack_refs_cb_data cbdata;memset (&cbdata,0 ,sizeof (cbdata));
@@ -2444,7 +2423,6 @@ static int repack_without_refs(struct files_ref_store *refs,struct string_list_item *refname;int ret, needs_repacking =0 , removed =0 ; -files_assert_main_repository (refs,"repack_without_refs" );assert (err);/* Look for a packed ref */
@@ -2512,7 +2490,7 @@ static int files_delete_refs(struct ref_store *ref_store, struct string_list *refnames, unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"delete_refs" ); +files_downcast (ref_store,"delete_refs" );struct strbuf err =STRBUF_INIT ;int i, result =0 ;
@@ -2619,7 +2597,7 @@ static int files_verify_refname_available(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,1 ,"verify_refname_available" ); +files_downcast (ref_store,"verify_refname_available" );struct ref_dir *packed_refs =get_packed_refs (refs);struct ref_dir *loose_refs =get_loose_refs (refs);
@@ -2644,7 +2622,7 @@ static int files_rename_ref(struct ref_store *ref_store, const char *logmsg) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"rename_ref" ); +files_downcast (ref_store,"rename_ref" );unsigned char sha1[20 ], orig_sha1[20 ];int flag =0 , logmoved =0 ;struct ref_lock *lock;
@@ -2866,7 +2844,7 @@ static int files_create_reflog(struct ref_store *ref_store,int ret;struct strbuf sb =STRBUF_INIT ;struct files_ref_store *refs = -files_downcast (ref_store,0 ,"create_reflog" ); +files_downcast (ref_store,"create_reflog" ); ret =log_ref_setup (refs, refname, &sb, err, force_create);strbuf_release (&sb);
@@ -3004,8 +2982,6 @@ static int commit_ref_update(struct files_ref_store *refs, const unsigned char *sha1, const char *logmsg, struct strbuf *err) { - files_assert_main_repository(refs, "commit_ref_update"); -clear_loose_ref_cache (refs );if (log_ref_write (refs, lock->ref_name, lock->old_oid.hash, sha1, logmsg,0 , err)) {
@@ -3114,7 +3090,7 @@ static int files_create_symref(struct ref_store *ref_store, const char *logmsg) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"create_symref" ); +files_downcast (ref_store,"create_symref" );struct strbuf err =STRBUF_INIT ;struct ref_lock *lock;int ret;
@@ -3140,7 +3116,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_ref_store (NULL ),"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
@@ -3178,7 +3154,7 @@ static int files_reflog_exists(struct ref_store *ref_store, const char *refname) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_exists" ); +files_downcast (ref_store,"reflog_exists" );struct strbuf sb =STRBUF_INIT ;struct stat st;int ret;
@@ -3193,7 +3169,7 @@ static int files_delete_reflog(struct ref_store *ref_store, const char *refname) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"delete_reflog" ); +files_downcast (ref_store,"delete_reflog" );struct strbuf sb =STRBUF_INIT ;int ret;
@@ -3248,7 +3224,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store, void *cb_data) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"for_each_reflog_ent_reverse" ); +files_downcast (ref_store,"for_each_reflog_ent_reverse" );struct strbuf sb =STRBUF_INIT ;FILE *logfp;long pos;
@@ -3356,7 +3332,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store, each_reflog_ent_fn fn, void *cb_data) { struct files_ref_store *refs = -files_downcast (ref_store,0 ,"for_each_reflog_ent" ); +files_downcast (ref_store,"for_each_reflog_ent" );FILE *logfp;struct strbuf sb =STRBUF_INIT ;int ret =0 ;
@@ -3444,7 +3420,7 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {static struct ref_iterator *files_reflog_iterator_begin (struct ref_store *ref_store) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_iterator_begin" ); +files_downcast (ref_store,"reflog_iterator_begin" );struct files_reflog_iterator *iter =xcalloc (1 ,sizeof (*iter));struct ref_iterator *ref_iterator = &iter->base;struct strbuf sb =STRBUF_INIT ;
@@ -3656,8 +3632,6 @@ static int lock_ref_for_update(struct files_ref_store *refs,int ret;struct ref_lock *lock; -files_assert_main_repository (refs,"lock_ref_for_update" ); -if ((update->flags &REF_HAVE_NEW ) &&is_null_sha1 (update->new_sha1)) update->flags |=REF_DELETING ;
@@ -3782,7 +3756,7 @@ static int files_transaction_commit(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"ref_transaction_commit" ); +files_downcast (ref_store,"ref_transaction_commit" );int ret =0 , i;struct string_list refs_to_delete =STRING_LIST_INIT_NODUP ;struct string_list_item *ref_to_delete;
@@ -3956,7 +3930,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"initial_ref_transaction_commit" ); +files_downcast (ref_store,"initial_ref_transaction_commit" );int ret =0 , i;struct string_list affected_refnames =STRING_LIST_INIT_NODUP ;
@@ -4078,7 +4052,7 @@ static int files_reflog_expire(struct ref_store *ref_store, void *policy_cb_data) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_expire" ); +files_downcast (ref_store,"reflog_expire" );static struct lock_file reflog_lock;struct expire_reflog_cb cb;struct ref_lock *lock;
@@ -4183,8 +4157,7 @@ static int files_reflog_expire(struct ref_store *ref_store,static int files_init_db (struct ref_store *ref_store,struct strbuf *err) { -struct files_ref_store *refs = -files_downcast (ref_store,0 ,"init_db" ); +struct files_ref_store *refs =files_downcast (ref_store,"init_db" );struct strbuf sb =STRBUF_INIT ;/*
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH 10/11] files-backend: remove submodule_allowed from files_downcast()
Quoted 9 lines · Nguyễn Thái Ngọc Duy
Since submodule or not is irrelevant to files-backend after the last patch, remove the parameter from
files_downcast()and killfiles_assert_main_repository().PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>---
Looks good,
Stefan
PATCH 11/11 refs: split and make get_*_ref_store() public API
In reply to Nguyễn Thái Ngọc Duy--- refs.c | 59 ++++++++++++++++++++++++++++++---------------------- refs.h | 13 ++++++++++++ refs/files-backend.c | 2 +- refs/refs-internal.h | 12 ----------- 4 files changed, 48 insertions(+), 38 deletions(-)
refs.c +34 -25
@@ -1160,7 +1160,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)
@@ -1304,7 +1304,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); }
@@ -1312,7 +1312,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); }
@@ -1333,10 +1333,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)
@@ -1491,15 +1491,24 @@ static struct ref_store *init_submodule_ref_store(const char *path)return refs; } -struct ref_store *get_ref_store (const char *submodule) +struct ref_store *get_main_ref_store (void ) {struct ref_store *refs; -if (!submodule || !*submodule) { - refs =lookup_ref_store (NULL ); + refs =lookup_ref_store (NULL ); -if (!refs) - refs =ref_store_init (NULL ,NULL ); +if (!refs) + refs =ref_store_init (NULL ,NULL ); + +return refs; +} + +struct ref_store *get_submodule_ref_store (const char *submodule) +{ +struct ref_store *refs; + +if (!submodule || !*submodule) { +return get_main_ref_store (); }else { refs =lookup_ref_store (submodule);
@@ -1519,14 +1528,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); }
@@ -1534,7 +1543,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);
@@ -1543,7 +1552,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); }
@@ -1553,14 +1562,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);
@@ -1571,7 +1580,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);
@@ -1580,14 +1589,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); }
@@ -1595,14 +1604,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); }
@@ -1614,7 +1623,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,
@@ -1624,21 +1633,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 +13 -0
@@ -553,4 +553,17 @@ int reflog_expire(const char *refname, const unsigned char *sha1,int ref_storage_backend_exists (const char *name); +/* +* 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); +struct ref_store *get_main_ref_store (void ); +#endif /* REFS_H */
refs/files-backend.c +1 -1
@@ -3116,7 +3116,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 ),"set_head_symref" ); +files_downcast (get_main_ref_store (),"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
refs/refs-internal.h +0 -12
@@ -634,18 +634,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
Re: [PATCH 11/11] refs: split and make get_*_ref_store() public API
Quoted 4 lines
+/*
+ * Return theref_storeinstance for the specified submodule. For the
+ * main repository, use submodule==NULL; such a call cannot fail.
So now we have both a get_main as well as a get_submodule function, but the submodule function can return the main as well?
I'd rather see this as a BUG; or asking another way:
What is the difference between get_submodule_ref_store(NULL) and get_main_ref_store() ?
As you went through all call sites (by renaming the function), we'd be able to tell that there is no caller with NULL, or is it?
Stefan
Quoted 10 lines
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.
+ */refs.h +2
-0+struct ref_store *get_submodule_ref_store (const char *submodule); +struct ref_store *get_main_ref_store (void );
Re: [PATCH 11/11] refs: split and make get_*_ref_store() public API
Quoted 11 lines · Stefan Beller
Quoted 4 lines
+/*
+ * Return theref_storeinstance for the specified submodule. For the
+ * main repository, use submodule==NULL; such a call cannot fail.So now we have both a
get_mainas well as aget_submodulefunction, but the submodule function can return the main as well?I'd rather see this as a BUG; or asking another way:
What is the difference betweenget_submodule_ref_store(NULL)andget_main_ref_store()?
Technical debts :) In order to do that, we need to make sure _submodule() never takes NULL as main repo. But current code does. On example is revision.c where submodule==NULL is the main repo. In the end, I agree that get_submodule_ref_store(NULL) should be a bug.
Quoted 2 lines
As you went through all call sites (by renaming the function), we'd be able to tell that there is no caller with NULL, or is it?
Direct call sites are just middle men though, e.g. for_each_ref_submodule(). I'll attempt to clean this up at some point in future (probably at the same time I attempt to kill *_submodule ref api). But I think for now I'll just put a TODO or FIXME comment here.
Signature · 1 line
Duy
Re: [PATCH 11/11] refs: split and make get_*_ref_store() public API
Quoted 4 lines · Duy Nguyen
Direct call sites are just middle men though, e.g.
for_each_ref_submodule(). I'll attempt to clean this up at some point in future (probably at the same time I attempt to kill*_submoduleref api). But I think for now I'll just put a TODO or FIXME comment here.
So we'd have get_*_ref_store() for various cases and then will have a unifying for_each_ref_in_refstore() that takes a ref-store, which supersedes all the ad-hoc iterators like for_each_ref_submodule(), for_each_namespaced_ref(), etc?
That's a very sensible longer-term goal, methinks.
I am wondering what we should do to for_each_{tag,branch,...}_ref(). Would that become
ref_store = get_ref_main_store(); tag_ref_store = filter_ref_store(ref_store, "refs/tags/"); for_each_ref_in_refstore(tag_ref_store, ...);
or do you plan to have some other pattern?
Re: [PATCH 11/11] refs: split and make get_*_ref_store() public API
Quoted 7 lines · Junio C Hamano
Quoted 4 lines · Duy Nguyen
Direct call sites are just middle men though, e.g.
for_each_ref_submodule(). I'll attempt to clean this up at some point in future (probably at the same time I attempt to kill*_submoduleref api). But I think for now I'll just put a TODO or FIXME comment here.
Quoted 6 lines
So we'd have get_*_ref_store() for various cases and then will have a unifying
for_each_ref_in_refstore()that takes a ref-store, which supersedes all the ad-hoc iterators likefor_each_ref_submodule(),for_each_namespaced_ref(), etc?That's a very sensible longer-term goal, methinks.
Ah I forgot about ref namespace. I'll need to try something out in that area.
Quoted 8 lines
I am wondering what we should do to for_each_{tag,branch,...}_ref(). Would that become
ref_store = get_ref_main_store(); tag_ref_store = filter_ref_store(ref_store, "refs/tags/"); for_each_ref_in_refstore(tag_ref_store, ...);or do you plan to have some other pattern?
Long term, I think that's what Mike wants. Though the filter_ref_store might return an (opaque) iterator instead of a ref store and for_each_refstore() becomes a thin wrapper around the iterator interface.
Signature · 1 line
Duy
Re: [PATCH 11/11] refs: split and make get_*_ref_store() public API
Quoted 4 lines · Duy Nguyen
Long term, I think that's what Mike wants. Though the
filter_ref_storemight return an (opaque) iterator instead of a ref store andfor_each_refstore()becomes a thin wrapper around the iterator interface.
Ah, yes, an iterator would be a lot more suitable abstraction there.
Thanks.
Re: [PATCH 11/11] refs: split and make get_*_ref_store() public API
In reply to Duy NguyenQuoted 18 lines · Duy Nguyen
Quoted 11 lines · Stefan Beller
Quoted 4 lines
+/*
+ * Return theref_storeinstance for the specified submodule. For the
+ * main repository, use submodule==NULL; such a call cannot fail.So now we have both a
get_mainas well as aget_submodulefunction, but the submodule function can return the main as well?I'd rather see this as a BUG; or asking another way:
What is the difference betweenget_submodule_ref_store(NULL)andget_main_ref_store()?Technical debts :) In order to do that, we need to make sure
_submodule()never takes NULL as main repo. But current code does. On example isrevision.cwhere submodule==NULL is the main repo. In the end, I agree thatget_submodule_ref_store(NULL)should be a bug.
Quoted 7 lines
Quoted 2 lines
As you went through all call sites (by renaming the function), we'd be able to tell that there is no caller with NULL, or is it?
Direct call sites are just middle men though, e.g.
for_each_ref_submodule(). I'll attempt to clean this up at some point in future (probably at the same time I attempt to kill*_submoduleref api). But I think for now I'll just put a TODO or FIXME comment here.
ok, fine with me.
My line of thinking when originally responding was to put the FIXME comment at the caller site, and there we'd differentiate between the two cases and call the appropriate function.
Quoted 2 lines
--
Duy
v2 cover Remove submodule from files-backend.c
In reply to Nguyễn Thái Ngọc DuyPATCH v2 1/16 refs-internal.c: make files_log_ref_write() static
Created 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
@@ -222,10 +222,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 v2 2/16 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 | 111 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 22 deletions(-)
refs/files-backend.c +89 -22
@@ -2169,6 +2169,8 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)static int timeout_configured =0 ;static int timeout_value =1000 ;struct packed_ref_cache *packed_ref_cache; +struct strbuf sb =STRBUF_INIT ; +int ret;files_assert_main_repository (refs,"lock_packed_refs" );
@@ -2177,10 +2179,13 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) timeout_configured =1 ; } -if (hold_lock_file_for_update_timeout ( - &packlock,git_path ("packed-refs" ), - flags, timeout_value) <0 ) +strbuf_git_path (&sb,"packed-refs" ); + ret =hold_lock_file_for_update_timeout (&packlock, sb.buf, + flags, timeout_value); +strbuf_release (&sb); +if (ret <0 )return -1 ; +/* * Get the current packed-refs while holding the lock. If the * packed-refs file has been modified since we last read it,
@@ -2335,6 +2340,9 @@ static void try_remove_empty_parents(char *name)for (q = p; *q; q++) ;while (1 ) { +struct strbuf sb =STRBUF_INIT ; +int ret; +while (q > p && *q !='/' ) q--;while (q > p && *(q-1 ) =='/' )
@@ -2342,7 +2350,10 @@ static void try_remove_empty_parents(char *name)if (q == p)break ; *q ='\0' ; -if (rmdir (git_path ("%s" , name))) +strbuf_git_path (&sb,"%s" , name); + ret =rmdir (sb.buf); +strbuf_release (&sb); +if (ret)break ; } }
@@ -2431,7 +2442,11 @@ 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); +struct strbuf sb =STRBUF_INIT ; + +strbuf_git_path (&sb,"packed-refs" ); +unable_to_lock_message (sb.buf, errno, err); +strbuf_release (&sb);return -1 ; } packed =get_packed_refs (refs);
@@ -2529,8 +2544,10 @@ static int rename_tmp_log(const char *newrefname) {int attempts_remaining =4 ;struct strbuf path =STRBUF_INIT ; +struct strbuf tmp_renamed_log =STRBUF_INIT ;int ret =-1 ; +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); retry:strbuf_reset (&path);strbuf_git_path (&path,"logs/%s" , newrefname);
@@ -2546,7 +2563,7 @@ static int rename_tmp_log(const char *newrefname) goto out; } -if (rename (git_path (TMP_RENAMED_LOG ), path.buf)) { +if (rename (tmp_renamed_log.buf, path.buf)) {if ((errno==EISDIR || errno==ENOTDIR ) && --attempts_remaining >0 ) {/* * rename(a, b) when b is an existing
@@ -2574,6 +2591,7 @@ static int rename_tmp_log(const char *newrefname) ret =0 ; out:strbuf_release (&path); +strbuf_release (&tmp_renamed_log);return ret; }
@@ -2614,9 +2632,15 @@ 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 ; +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); + log = !lstat (sb_oldref.buf, &loginfo); +strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))return error ("reflog for %s is a symlink" , oldrefname);
@@ -2630,7 +2654,12 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log); +if (ret)return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno));
@@ -2709,13 +2738,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))) +strbuf_git_path (&sb_newref,"logs/%s" , newrefname); +strbuf_git_path (&sb_oldref,"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)); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG );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)); +strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log);return 1 ; }
@@ -3111,22 +3146,32 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static 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)
@@ -3181,7 +3226,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 ;
@@ -3287,7 +3334,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 ;
@@ -3369,12 +3418,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; }
@@ -3843,8 +3895,13 @@ static int files_transaction_commit(struct ref_store *ref_store, ret =TRANSACTION_GENERIC_ERROR ; goto cleanup; } -for_each_string_list_item (ref_to_delete, &refs_to_delete) -unlink_or_warn (git_path ("logs/%s" , ref_to_delete->string)); +for_each_string_list_item (ref_to_delete, &refs_to_delete) { +struct strbuf sb =STRBUF_INIT ; + +strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +unlink_or_warn (sb.buf); +strbuf_release (&sb); + }clear_loose_ref_cache (refs); cleanup:
@@ -4098,18 +4155,28 @@ 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_reset (&sb);if (get_shared_repository ()) { -adjust_shared_perm (git_path ("refs/heads" )); -adjust_shared_perm (git_path ("refs/tags" )); +strbuf_git_path (&sb,"refs/heads" ); +adjust_shared_perm (sb.buf); +strbuf_reset (&sb); +strbuf_git_path (&sb,"refs/tags" ); +adjust_shared_perm (sb.buf); } +strbuf_release (&sb);return 0 ; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v2 3/16 files-backend: add files_path()
In reply to Nguyễn Thái Ngọc DuyThis will be the replacement for both git_path() and git_path_submodule() in this file. The idea is backend takes a git path and use that, oblivious of submodule, linked worktrees and such.
This is the middle step towards that. Eventually the "submodule" field in 'struct files_ref_store' should be replace by "gitdir". And a compound ref_store is created to combine two files backends together, one represents the shared refs in $GIT_COMMON_DIR, one per-worktree. At that point, files_path() becomes a wrapper of strbuf_vaddf().
--- refs/files-backend.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
refs/files-backend.c +18 -0
@@ -930,6 +930,24 @@ struct files_ref_store {/* Lock used for the main packed-refs file: */ static struct lock_file packlock; +__attribute__((format (printf,3 ,4 ))) +static void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) +{ +struct strbuf tmp =STRBUF_INIT ; +va_list vap; + +va_start (vap, fmt); +strbuf_vaddf (&tmp, fmt, vap); +va_end (vap); +if (refs->submodule) +strbuf_git_path_submodule (sb, refs->submodule, +"%s" , tmp.buf); +else +strbuf_git_path (sb,"%s" , tmp.buf); +strbuf_release (&tmp); +} +/* * Increment the reference count of *packed_refs. */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v2 4/16 files-backend: replace *git_path*() with files_path()
In reply to Nguyễn Thái Ngọc DuyThis centralizes all path rewriting of files-backend.c in one place so we have easier time removing the path rewriting later. There could be some hidden indirect git_path() though, I didn't audit the code to the bottom.
Side note: set_worktree_head_symref() is a bad boy and should not be in files-backend.c (probably should not exist in the first place). But we'll leave it there until we have better multi-worktree support in refs before we update it.
--- refs/files-backend.c | 185 ++++++++++++++++++++++++++------------------------- 1 file changed, 94 insertions(+), 91 deletions(-)
refs/files-backend.c +94 -91
@@ -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);
@@ -1178,12 +1179,10 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)static struct packed_ref_cache *get_packed_ref_cache (struct files_ref_store *refs) {char *packed_refs_file; +struct strbuf sb =STRBUF_INIT ; -if (refs->submodule) - packed_refs_file =git_pathdup_submodule (refs->submodule, -"packed-refs" ); -else - packed_refs_file =git_pathdup ("packed-refs" ); +files_path (refs, &sb,"packed-refs" ); + packed_refs_file =strbuf_detach (&sb,NULL );if (refs->packed && !stat_validity_check (&refs->packed->validity, packed_refs_file))
@@ -1249,10 +1248,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)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_path (refs, &path,"%s" , dirname); path_baselen = path.len;if (err) {
@@ -1394,10 +1390,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_path (refs, &sb_path,"%s" , refname); path = sb_path.buf;
@@ -1585,7 +1578,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_path (refs, &ref_file,"%s" , refname); retry:switch (safe_create_leading_directories (ref_file.buf)) {
@@ -2052,7 +2045,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_path (refs, &ref_file,"%s" , refname); resolved = !!resolve_ref_unsafe (refname, resolve_flags, lock->old_oid.hash, type);if (!resolved && errno ==EISDIR ) {
@@ -2197,7 +2190,7 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) timeout_configured =1 ; } -strbuf_git_path (&sb,"packed-refs" ); +files_path (refs, &sb,"packed-refs" ); ret =hold_lock_file_for_update_timeout (&packlock, sb.buf, flags, timeout_value);strbuf_release (&sb);
@@ -2343,7 +2336,7 @@ static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data)* Remove empty parents, but spare refs/ and immediate subdirs. * Note: munges *name. */ -static void try_remove_empty_parents (char *name) +static void try_remove_empty_parents (struct files_ref_store *refs,char *name) {char *p, *q;int i;
@@ -2368,7 +2361,7 @@ static void try_remove_empty_parents(char *name)if (q == p)break ; *q ='\0' ; -strbuf_git_path (&sb,"%s" , name); +files_path (refs, &sb,"%s" , name); ret =rmdir (sb.buf);strbuf_release (&sb);if (ret)
@@ -2377,7 +2370,7 @@ static void try_remove_empty_parents(char *name) }/* 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 ;
@@ -2397,13 +2390,13 @@ static void prune_ref(struct ref_to_prune *r) }ref_transaction_free (transaction);strbuf_release (&err); -try_remove_empty_parents (r->name); +try_remove_empty_parents (refs, r->name); } -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; } }
@@ -2426,7 +2419,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 ; }
@@ -2462,7 +2455,7 @@ static int repack_without_refs(struct files_ref_store *refs,if (lock_packed_refs (refs,0 )) {struct strbuf sb =STRBUF_INIT ; -strbuf_git_path (&sb,"packed-refs" ); +files_path (refs, &sb,"packed-refs" );unable_to_lock_message (sb.buf, errno, err);strbuf_release (&sb);return -1 ;
@@ -2558,17 +2551,17 @@ static int files_delete_refs(struct ref_store *ref_store,*/ #define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log" -static int rename_tmp_log (const char *newrefname) +static int rename_tmp_log (struct files_ref_store *refs,const char *newrefname) {int attempts_remaining =4 ;struct strbuf path =STRBUF_INIT ;struct strbuf tmp_renamed_log =STRBUF_INIT ;int ret =-1 ; -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); retry:strbuf_reset (&path); -strbuf_git_path (&path,"logs/%s" , newrefname); +files_path (refs, &path,"logs/%s" , newrefname);switch (safe_create_leading_directories_const (path.buf)) {case SCLD_OK :break ;/* success */
@@ -2656,7 +2649,7 @@ 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); +files_path (refs, &sb_oldref,"logs/%s" , oldrefname); log = !lstat (sb_oldref.buf, &loginfo);strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))
@@ -2672,8 +2665,8 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &sb_oldref,"logs/%s" , oldrefname); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf);strbuf_release (&sb_oldref);strbuf_release (&tmp_renamed_log);
@@ -2700,7 +2693,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_path (refs, &path,"%s" , newrefname); result =remove_empty_directories (&path);strbuf_release (&path);
@@ -2714,7 +2707,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;
@@ -2756,12 +2749,12 @@ static int files_rename_ref(struct ref_store *ref_store, log_all_ref_updates = flag; rollbacklog: -strbuf_git_path (&sb_newref,"logs/%s" , newrefname); -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +files_path (refs, &sb_newref,"logs/%s" , newrefname); +files_path (refs, &sb_oldref,"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)); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG );if (!logmoved && log &&rename (tmp_renamed_log.buf, sb_oldref.buf)) error("unable to restore logfile %s from "TMP_RENAMED_LOG": %s",
@@ -2817,11 +2810,13 @@ static int commit_ref(struct ref_lock *lock)* should_autocreate_reflog returns non-zero. Otherwise, create it * regardless of the ref name. Fill in *err and return -1 on failure. */ -static int log_ref_setup (const char *refname,struct strbuf *logfile,struct strbuf *err,int force_create) +static int log_ref_setup (struct files_ref_store *refs,const char *refname, +struct strbuf *logfile,struct strbuf *err, +int force_create) {int logfd, oflags =O_APPEND |O_WRONLY ; -strbuf_git_path (logfile,"logs/%s" , refname); +files_path (refs, logfile,"logs/%s" , refname);if (force_create ||should_autocreate_reflog (refname)) {if (safe_create_leading_directories (logfile->buf) <0 ) { strbuf_addf(err, "unable to create directory for '%s': "
@@ -2864,11 +2859,10 @@ static int files_create_reflog(struct ref_store *ref_store, {int ret;struct strbuf sb =STRBUF_INIT ; +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"create_reflog" ); -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"create_reflog" ); - - ret =log_ref_setup (refname, &sb, err, force_create); + ret =log_ref_setup (refs, refname, &sb, err, force_create);strbuf_release (&sb);return ret; }
@@ -2899,7 +2893,8 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,return 0 ; } -static int log_ref_write_1 (const char *refname,const unsigned char *old_sha1, +static int log_ref_write_1 (struct files_ref_store *refs, +const char *refname,const unsigned char *old_sha1,const unsigned char *new_sha1,const char *msg,struct strbuf *logfile,int flags,struct strbuf *err)
@@ -2909,7 +2904,7 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,if (log_all_ref_updates <0 ) log_all_ref_updates = !is_bare_repository (); - result =log_ref_setup (refname, logfile, err, flags &REF_FORCE_CREATE_REFLOG ); + result =log_ref_setup (refs, refname, logfile, err, flags &REF_FORCE_CREATE_REFLOG );if (result)return result;
@@ -2933,21 +2928,23 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,return 0 ; } -static int log_ref_write (const char *refname,const unsigned char *old_sha1, +static int 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) { -return files_log_ref_write (refname, old_sha1, new_sha1, msg, flags, - err); +return files_log_ref_write (refs, refname, old_sha1, new_sha1, + msg, flags, err); } -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) {struct strbuf sb =STRBUF_INIT ; -int ret =log_ref_write_1 (refname, old_sha1, new_sha1, msg, &sb, flags, - err); +int ret =log_ref_write_1 (refs, refname, old_sha1, new_sha1, msg, + &sb, flags, err);strbuf_release (&sb);return ret; }
@@ -3004,7 +3001,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 (log_ref_write (lock->ref_name, lock->old_oid.hash, sha1, logmsg,0 , err)) { +if (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" , lock->ref_name, old_msg);
@@ -3035,8 +3033,8 @@ 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 (log_ref_write ("HEAD" , lock->old_oid.hash, sha1, - logmsg,0 , &log_err)) { +if (log_ref_write (refs,"HEAD" , lock->old_oid.hash, + sha1, logmsg,0 , &log_err)) {error ("%s" , log_err.buf);strbuf_release (&log_err); }
@@ -3068,23 +3066,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) && -log_ref_write (refname, lock->old_oid.hash, new_sha1, logmsg,0 , &err)) { +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 ; }
@@ -3092,7 +3093,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);
@@ -3121,13 +3122,19 @@ 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) { +/* +* 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 ;
@@ -3154,7 +3161,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target) lock->lk = &head_lock; lock->ref_name =xstrdup (head_rel); - ret =create_symref_locked (lock, head_rel, target,NULL ); + ret =create_symref_locked (refs, lock, head_rel, target,NULL );unlock_ref (lock);/* will free lock */ strbuf_release (&head_path);
@@ -3164,14 +3171,13 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static int files_reflog_exists (struct ref_store *ref_store,const char *refname) { +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"reflog_exists" );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_path (refs, &sb,"logs/%s" , refname); ret = !lstat (sb.buf, &st) &&S_ISREG (st.st_mode);strbuf_release (&sb);return ret;
@@ -3180,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_path (refs, &sb,"logs/%s" , refname); ret =remove_path (sb.buf);strbuf_release (&sb);return ret;
@@ -3236,15 +3241,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_path (refs, &sb,"logs/%s" , refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3345,14 +3349,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_path (refs, &sb,"logs/%s" , refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3434,15 +3437,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_path (refs, &sb,"logs" ); iter->dir_iterator =dir_iterator_begin (sb.buf);strbuf_release (&sb);return ref_iterator;
@@ -3866,8 +3868,8 @@ static int files_transaction_commit(struct ref_store *ref_store,if (update->flags &REF_NEEDS_COMMIT || update->flags &REF_LOG_ONLY ) { -if (log_ref_write (lock->ref_name, lock->old_oid.hash, - update->new_sha1, +if (log_ref_write (refs, lock->ref_name, + lock->old_oid.hash, update->new_sha1, update->msg, update->flags, err)) {char *old_msg =strbuf_detach (err,NULL );
@@ -3916,7 +3918,7 @@ static int files_transaction_commit(struct ref_store *ref_store,for_each_string_list_item (ref_to_delete, &refs_to_delete) {struct strbuf sb =STRBUF_INIT ; -strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +files_path (refs, &sb,"logs/%s" , ref_to_delete->string);unlink_or_warn (sb.buf);strbuf_release (&sb); }
@@ -4078,6 +4080,7 @@ static int files_reflog_expire(struct ref_store *ref_store,int status =0 ;int type;struct strbuf err =STRBUF_INIT ; +struct strbuf sb =STRBUF_INIT ;memset (&cb,0 ,sizeof (cb)); cb.flags = flags;
@@ -4102,7 +4105,8 @@ static int files_reflog_expire(struct ref_store *ref_store,return 0 ; } - log_file =git_pathdup ("logs/%s" , refname); +files_path (refs, &sb,"logs/%s" , refname); + log_file =strbuf_detach (&sb,NULL );if (!(flags &EXPIRE_REFLOGS_DRY_RUN )) {/* * Even though holding $GIT_DIR/logs/$reflog.lock has
@@ -4173,25 +4177,24 @@ 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_path (refs, &sb,"refs/heads" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_path (refs, &sb,"refs/tags" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb);if (get_shared_repository ()) { -strbuf_git_path (&sb,"refs/heads" ); +files_path (refs, &sb,"refs/heads" );adjust_shared_perm (sb.buf);strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_path (refs, &sb,"refs/tags" );adjust_shared_perm (sb.buf); }strbuf_release (&sb);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v2 04/16] files-backend: replace *git_path*() with files_path()
Quoted 4 lines · Nguyễn Thái Ngọc Duy
This centralizes all path rewriting of
files-backend.cin one place so we have easier time removing the path rewriting later. There could be some hidden indirectgit_path()though, I didn't audit the code to the bottom.
Almost all of the calls to files_path() [1] take one of the following forms:
* files_path(refs, &sb, "packed-refs")
* files_path(refs, &sb, "%s", refname)
* files_path(refs, &sb, "logs/%s", refname)
(though sometimes refname is not the name of a reference but rather the name of a directory containing references, like "refs/heads").
This suggests to me that it would be more natural to have three functions, files_packed_refs_path(), files_loose_ref_path(), and files_reflog_path(), with no fmt arguments. Aside from making the callers a bit simpler and the implementation of each of the three functions simpler (they wouldn't have to deal with variable argument lists), at the cost of needing three similar functions.
But I think the split would also be advantageous from a design point of view. The relative path locations of loose reference files, reflog files, and the packed-refs file is kind of a coincidence, and it would be advantageous to encode that policy in three functions rather than continuing to spread knowledge of those assumptions around.
It would also make it easier to switch to a new system of encoding reference names, for example so that reference names that differ only in case can be stored on a case-insensitive filesystem, or to store reflogs using a naming scheme that is not susceptible to D/F conflicts so that we can retain reflogs for deleted references.
Michael
[1] The only exception I see is one call files_path(refs, &sb, "logs"), which is a prelude to iterating over the reflog files. This is actually an example of the code giving us a hint that the design is
wrong: if you iterate only over the directories under git_path(logs), you miss the reflogs for worktree references.
Re: [PATCH v2 04/16] files-backend: replace *git_path*() with files_path()
Quoted 29 lines · Michael Haggerty
Quoted 4 lines · Nguyễn Thái Ngọc Duy
This centralizes all path rewriting of
files-backend.cin one place so we have easier time removing the path rewriting later. There could be some hidden indirectgit_path()though, I didn't audit the code to the bottom.Almost all of the calls to
files_path()[1] take one of the following forms:*
files_path(refs, &sb, "packed-refs")
*files_path(refs, &sb, "%s", refname)
*files_path(refs, &sb, "logs/%s", refname)(though sometimes
refnameis not the name of a reference but rather the name of a directory containing references, like "refs/heads").This suggests to me that it would be more natural to have three functions,
files_packed_refs_path(),files_loose_ref_path(), andfiles_reflog_path(), with nofmtarguments. Aside from making the callers a bit simpler and the implementation of each of the three functions simpler (they wouldn't have to deal with variable argument lists), at the cost of needing three similar functions.But I think the split would also be advantageous from a design point of view. The relative path locations of loose reference files, reflog files, and the packed-refs file is kind of a coincidence, and it would be advantageous to encode that policy in three functions rather than continuing to spread knowledge of those assumptions around.
Quoted 5 lines
It would also make it easier to switch to a new system of encoding reference names, for example so that reference names that differ only in case can be stored on a case-insensitive filesystem, or to store reflogs using a naming scheme that is not susceptible to D/F conflicts so that we can retain reflogs for deleted references.
I agree. I didn't see it clearly at the beginning (and made several mistakes in earlier iterations) but as you have seen files_path() the separation is pretty clear there. I was going to do it when introducing the "linked worktree" backend. But since you pointed it out, I'll update it in this series too.
Quoted 7 lines
Michael
[1] The only exception I see is one call
files_path(refs, &sb, "logs"), which is a prelude to iterating over the reflog files. This is actually an example of the code giving us a hint that the design is
wrong: if you iterate only over the directories undergit_path(logs), you miss the reflogs for worktree references.
Oh yes, I had to fix the reflog iterator [1] exactly for that :)
[1] https://public-inbox.org/git/[email protected]/T/#u
Signature · 1 line
Duy
PATCH v2 5/16 refs.c: share is_per_worktree_ref() to files-backend.c
In reply to Nguyễn Thái Ngọc Duy--- refs.c | 6 ------ refs/refs-internal.h | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-)
refs.c +0 -6
@@ -489,12 +489,6 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)return logs_found; } -static int is_per_worktree_ref (const char *refname) -{ -return !strcmp (refname,"HEAD" ) || -starts_with (refname,"refs/bisect/" ); -} -static int is_pseudoref_syntax (const char *refname) {const char *c;
refs/refs-internal.h +6 -0
@@ -651,4 +651,10 @@ const char *resolve_ref_recursively(struct ref_store *refs,int resolve_flags, unsigned char *sha1, int *flags); +static inline int is_per_worktree_ref (const char *refname) +{ +return !strcmp (refname,"HEAD" ) || +starts_with (refname,"refs/bisect/" ); +} +#endif /* REFS_REFS_INTERNAL_H */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v2 6/16 refs-internal.h: correct is_per_worktree_ref()
In reply to Nguyễn Thái Ngọc DuyAll refs outside refs/ directory is per-worktree, not just HEAD.
--- refs/refs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
refs/refs-internal.h +1 -1
@@ -653,7 +653,7 @@ const char *resolve_ref_recursively(struct ref_store *refs,static inline int is_per_worktree_ref (const char *refname) { -return !strcmp (refname,"HEAD" ) || +return !starts_with (refname,"refs/" ) ||starts_with (refname,"refs/bisect/" ); }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v2 7/16 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 | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
refs/files-backend.c +18 -2
@@ -924,6 +924,9 @@ struct files_ref_store {*/ const char *submodule; +struct strbuf gitdir; +struct strbuf gitcommondir; +struct ref_entry *loose;struct packed_ref_cache *packed; };
@@ -937,6 +940,7 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb, {struct strbuf tmp =STRBUF_INIT ;va_list vap; +const char *ref;va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);
@@ -944,8 +948,12 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb,if (refs->submodule)strbuf_git_path_submodule (sb, refs->submodule,"%s" , tmp.buf); +else if (is_per_worktree_ref (tmp.buf) || + (skip_prefix (tmp.buf,"logs/" , &ref) && +is_per_worktree_ref (ref))) +strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf);else -strbuf_git_path (sb,"%s" , tmp.buf); +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf);strbuf_release (&tmp); }
@@ -1004,7 +1012,15 @@ 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); +strbuf_init (&refs->gitdir,0 ); +strbuf_init (&refs->gitcommondir,0 ); + +if (submodule) { + refs->submodule =xstrdup (submodule); + }else { +strbuf_addstr (&refs->gitdir,get_git_dir ()); +strbuf_addstr (&refs->gitcommondir,get_git_common_dir ()); + }return ref_store; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v2 8/16 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
@@ -1445,15 +1445,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
PATCH v2 9/16 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
@@ -1384,17 +1384,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 ;
@@ -1463,7 +1459,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 ;
@@ -1474,7 +1470,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 v2 10/16 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 | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
refs.c +9 -10
@@ -1454,22 +1454,21 @@ 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;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); +if (is_nonbare_repository_dir (&submodule_sb)) + refs =ref_store_init (submodule); +strbuf_release (&submodule_sb);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v2 11/16 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 | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-)
refs.c +19 -17
@@ -1402,25 +1402,19 @@ 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. +* for submodule. 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) +static void register_submodule_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 (!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); - } +if (hashmap_put (&submodule_ref_stores, +alloc_submodule_hash_entry (submodule, refs))) +die ("BUG: ref_store for submodule '%s' initialized twice" , + submodule); }/*
@@ -1437,7 +1431,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; }
@@ -1449,6 +1442,12 @@ 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; }
@@ -1469,6 +1468,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) +register_submodule_ref_store (refs, submodule);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v2 12/16 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 | 2 ++ 2 files changed, 20 insertions(+), 18 deletions(-)
refs.c +18 -18
@@ -1303,7 +1303,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); }
@@ -1311,7 +1311,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); }
@@ -1434,7 +1434,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;
@@ -1483,14 +1483,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); }
@@ -1498,7 +1498,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);
@@ -1507,7 +1507,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); }
@@ -1517,14 +1517,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);
@@ -1535,7 +1535,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);
@@ -1544,14 +1544,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); }
@@ -1559,14 +1559,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); }
@@ -1578,7 +1578,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,
@@ -1588,21 +1588,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 +2 -0
@@ -553,4 +553,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 */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v2 13/16 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
@@ -1335,3 +1335,34 @@ void prepare_submodule_repo_env(struct argv_array *out) }argv_array_push (out,"GIT_DIR=.git" ); } + +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
@@ -70,6 +70,7 @@ extern int push_unpushed_submodules(struct sha1_array *commits, int dry_run);void connect_work_tree_and_git_dir (const char *work_tree,const char *git_dir);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
PATCH v2 14/16 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().
The new code in init_submodule_ref_store() is basically a copy of strbuf_git_path_submodule().
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() follows shortly. It's separate to keep noises from this patch.
--- refs.c | 18 +++++++++++++----- refs/files-backend.c | 26 ++++++++------------------ refs/refs-internal.h | 6 +++--- 3 files changed, 24 insertions(+), 26 deletions(-)
refs.c +13 -5
@@ -9,6 +9,7 @@#include "refs/refs-internal.h" #include "object.h" #include "tag.h" +#include "submodule.h" /* * List of all available backends
@@ -1419,9 +1420,9 @@ static void register_submodule_ref_store(struct ref_store *refs,/* * Create, record, and return a ref_store instance for the specified -* submodule (or the main repository if submodule is NULL). +* gitdir (or the main repository if gitdir is NULL). */ -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);
@@ -1430,7 +1431,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; }
@@ -1455,6 +1456,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 ();
@@ -1465,8 +1467,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 +8 -18
@@ -917,13 +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; -struct strbuf gitdir;struct strbuf gitcommondir;
@@ -945,12 +938,9 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb,va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);va_end (vap); -if (refs->submodule) -strbuf_git_path_submodule (sb, refs->submodule, -"%s" , tmp.buf); -else if (is_per_worktree_ref (tmp.buf) || - (skip_prefix (tmp.buf,"logs/" , &ref) && -is_per_worktree_ref (ref))) +if (is_per_worktree_ref (tmp.buf) || + (skip_prefix (tmp.buf,"logs/" , &ref) && +is_per_worktree_ref (ref)))strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf);else strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf);
@@ -1005,7 +995,7 @@ 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;
@@ -1015,8 +1005,9 @@ static struct ref_store *files_ref_store_create(const char *submodule)strbuf_init (&refs->gitdir,0 );strbuf_init (&refs->gitcommondir,0 ); -if (submodule) { - refs->submodule =xstrdup (submodule); +if (gitdir) { +strbuf_addstr (&refs->gitdir, gitdir); +get_common_dir_noenv (&refs->gitcommondir, gitdir); }else {strbuf_addstr (&refs->gitdir,get_git_dir ());strbuf_addstr (&refs->gitcommondir,get_git_common_dir ());
@@ -1032,8 +1023,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 */ }/*
refs/refs-internal.h +3 -3
@@ -476,12 +476,12 @@ 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 +* Initialize the ref_store for the specified gitdir, or for the +* current repository if gitdir == NULL. These functions should call * base_ref_store_init() to initialize the shared part of the * ref_store and to record the ref_store for later lookup. */ -typedef struct ref_store *ref_store_init_fn (const char *submodule); +typedef 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 v2 15/16 files-backend: remove submodule_allowed from files_downcast()
In reply to Nguyễn Thái Ngọc DuySince submodule or not is irrelevant to files-backend after the last patch, remove the parameter from files_downcast() and kill files_assert_main_repository().
PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
--- refs/files-backend.c | 70 ++++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 49 deletions(-)
refs/files-backend.c +21 -49
@@ -1017,24 +1017,13 @@ 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. -*/ -static void files_assert_main_repository (struct files_ref_store *refs, -const char *caller) -{ -/* This function is to be deleted in the next patch */ -} - -/* * 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. */ -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, +const char *caller) {struct files_ref_store *refs;
@@ -1044,9 +1033,6 @@ static struct files_ref_store *files_downcast( refs = (struct files_ref_store *)ref_store; -if (!submodule_allowed) -files_assert_main_repository (refs, caller); -return refs; }
@@ -1382,7 +1368,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, struct strbuf *referent, unsigned int *type) { struct files_ref_store *refs = -files_downcast (ref_store,1 ,"read_raw_ref" ); +files_downcast (ref_store,"read_raw_ref" );struct strbuf sb_contents =STRBUF_INIT ;struct strbuf sb_path =STRBUF_INIT ;const char *path;
@@ -1575,7 +1561,6 @@ static int lock_raw_ref(struct files_ref_store *refs,int ret =TRANSACTION_GENERIC_ERROR ;assert (err); -files_assert_main_repository (refs,"lock_raw_ref" ); *type =0 ;
@@ -1799,7 +1784,7 @@ static enum peel_status peel_entry(struct ref_entry *entry, int repeel)static int files_peel_ref (struct ref_store *ref_store,const char *refname,unsigned char *sha1) { -struct files_ref_store *refs =files_downcast (ref_store,0 ,"peel_ref" ); +struct files_ref_store *refs =files_downcast (ref_store,"peel_ref" );int flag;unsigned char base[20 ];
@@ -1908,7 +1893,7 @@ static struct ref_iterator *files_ref_iterator_begin( const char *prefix, unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,1 ,"ref_iterator_begin" ); +files_downcast (ref_store,"ref_iterator_begin" );struct ref_dir *loose_dir, *packed_dir;struct ref_iterator *loose_iter, *packed_iter;struct files_ref_iterator *iter;
@@ -2041,7 +2026,6 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,int attempts_remaining =3 ;int resolved; -files_assert_main_repository (refs,"lock_ref_sha1_basic" );assert (err); lock =xcalloc (1 ,sizeof (struct ref_lock ));
@@ -2189,8 +2173,6 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)struct strbuf sb =STRBUF_INIT ;int ret; -files_assert_main_repository (refs,"lock_packed_refs" ); -if (!timeout_configured) {git_config_get_int ("core.packedrefstimeout" , &timeout_value); timeout_configured =1 ;
@@ -2230,8 +2212,6 @@ static int commit_packed_refs(struct files_ref_store *refs)int save_errno =0 ;FILE *out; -files_assert_main_repository (refs,"commit_packed_refs" ); -if (!packed_ref_cache->lock)die ("internal error: packed-refs not locked" );
@@ -2263,8 +2243,6 @@ static void rollback_packed_refs(struct files_ref_store *refs)struct packed_ref_cache *packed_ref_cache =get_packed_ref_cache (refs); -files_assert_main_repository (refs,"rollback_packed_refs" ); -if (!packed_ref_cache->lock)die ("internal error: packed-refs not locked" );rollback_lock_file (packed_ref_cache->lock);
@@ -2410,7 +2388,7 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune *r)static int files_pack_refs (struct ref_store *ref_store,unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"pack_refs" ); +files_downcast (ref_store,"pack_refs" );struct pack_refs_cb_data cbdata;memset (&cbdata,0 ,sizeof (cbdata));
@@ -2443,7 +2421,6 @@ static int repack_without_refs(struct files_ref_store *refs,struct string_list_item *refname;int ret, needs_repacking =0 , removed =0 ; -files_assert_main_repository (refs,"repack_without_refs" );assert (err);/* Look for a packed ref */
@@ -2511,7 +2488,7 @@ static int files_delete_refs(struct ref_store *ref_store, struct string_list *refnames, unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"delete_refs" ); +files_downcast (ref_store,"delete_refs" );struct strbuf err =STRBUF_INIT ;int i, result =0 ;
@@ -2619,7 +2596,7 @@ static int files_verify_refname_available(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,1 ,"verify_refname_available" ); +files_downcast (ref_store,"verify_refname_available" );struct ref_dir *packed_refs =get_packed_refs (refs);struct ref_dir *loose_refs =get_loose_refs (refs);
@@ -2644,7 +2621,7 @@ static int files_rename_ref(struct ref_store *ref_store, const char *logmsg) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"rename_ref" ); +files_downcast (ref_store,"rename_ref" );unsigned char sha1[20 ], orig_sha1[20 ];int flag =0 , logmoved =0 ;struct ref_lock *lock;
@@ -2866,7 +2843,7 @@ static int files_create_reflog(struct ref_store *ref_store,int ret;struct strbuf sb =STRBUF_INIT ;struct files_ref_store *refs = -files_downcast (ref_store,0 ,"create_reflog" ); +files_downcast (ref_store,"create_reflog" ); ret =log_ref_setup (refs, refname, &sb, err, force_create);strbuf_release (&sb);
@@ -3004,8 +2981,6 @@ static int commit_ref_update(struct files_ref_store *refs, const unsigned char *sha1, const char *logmsg, struct strbuf *err) { - files_assert_main_repository(refs, "commit_ref_update"); -clear_loose_ref_cache (refs );if (log_ref_write (refs, lock->ref_name, lock->old_oid.hash, sha1, logmsg,0 , err)) {
@@ -3114,7 +3089,7 @@ static int files_create_symref(struct ref_store *ref_store, const char *logmsg) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"create_symref" ); +files_downcast (ref_store,"create_symref" );struct strbuf err =STRBUF_INIT ;struct ref_lock *lock;int ret;
@@ -3140,7 +3115,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_ref_store (NULL ),"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
@@ -3178,7 +3153,7 @@ static int files_reflog_exists(struct ref_store *ref_store, const char *refname) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_exists" ); +files_downcast (ref_store,"reflog_exists" );struct strbuf sb =STRBUF_INIT ;struct stat st;int ret;
@@ -3193,7 +3168,7 @@ static int files_delete_reflog(struct ref_store *ref_store, const char *refname) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"delete_reflog" ); +files_downcast (ref_store,"delete_reflog" );struct strbuf sb =STRBUF_INIT ;int ret;
@@ -3248,7 +3223,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store, void *cb_data) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"for_each_reflog_ent_reverse" ); +files_downcast (ref_store,"for_each_reflog_ent_reverse" );struct strbuf sb =STRBUF_INIT ;FILE *logfp;long pos;
@@ -3356,7 +3331,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store, each_reflog_ent_fn fn, void *cb_data) { struct files_ref_store *refs = -files_downcast (ref_store,0 ,"for_each_reflog_ent" ); +files_downcast (ref_store,"for_each_reflog_ent" );FILE *logfp;struct strbuf sb =STRBUF_INIT ;int ret =0 ;
@@ -3444,7 +3419,7 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {static struct ref_iterator *files_reflog_iterator_begin (struct ref_store *ref_store) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_iterator_begin" ); +files_downcast (ref_store,"reflog_iterator_begin" );struct files_reflog_iterator *iter =xcalloc (1 ,sizeof (*iter));struct ref_iterator *ref_iterator = &iter->base;struct strbuf sb =STRBUF_INIT ;
@@ -3656,8 +3631,6 @@ static int lock_ref_for_update(struct files_ref_store *refs,int ret;struct ref_lock *lock; -files_assert_main_repository (refs,"lock_ref_for_update" ); -if ((update->flags &REF_HAVE_NEW ) &&is_null_sha1 (update->new_sha1)) update->flags |=REF_DELETING ;
@@ -3782,7 +3755,7 @@ static int files_transaction_commit(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"ref_transaction_commit" ); +files_downcast (ref_store,"ref_transaction_commit" );int ret =0 , i;struct string_list refs_to_delete =STRING_LIST_INIT_NODUP ;struct string_list_item *ref_to_delete;
@@ -3956,7 +3929,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"initial_ref_transaction_commit" ); +files_downcast (ref_store,"initial_ref_transaction_commit" );int ret =0 , i;struct string_list affected_refnames =STRING_LIST_INIT_NODUP ;
@@ -4078,7 +4051,7 @@ static int files_reflog_expire(struct ref_store *ref_store, void *policy_cb_data) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_expire" ); +files_downcast (ref_store,"reflog_expire" );static struct lock_file reflog_lock;struct expire_reflog_cb cb;struct ref_lock *lock;
@@ -4183,8 +4156,7 @@ static int files_reflog_expire(struct ref_store *ref_store,static int files_init_db (struct ref_store *ref_store,struct strbuf *err) { -struct files_ref_store *refs = -files_downcast (ref_store,0 ,"init_db" ); +struct files_ref_store *refs =files_downcast (ref_store,"init_db" );struct strbuf sb =STRBUF_INIT ;/*
Signature · 1 line
2.11.0.157.gd943d85
PATCH v2 16/16 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/files-backend.c | 2 +- refs/refs-internal.h | 12 ------------ 4 files changed, 20 insertions(+), 17 deletions(-)
refs.c +8 -4
@@ -1160,7 +1160,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)
@@ -1333,10 +1333,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)
@@ -1452,13 +1452,17 @@ struct ref_store *get_main_ref_store(void)return refs; } -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
@@ -554,5 +554,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/files-backend.c +1 -1
@@ -3115,7 +3115,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 ),"set_head_symref" ); +files_downcast (get_main_ref_store (),"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
refs/refs-internal.h +0 -12
@@ -634,18 +634,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
This series looks good to me.
Thanks,
Stefan
v3 cover Remove submodule from files-backend.c
In reply to Nguyễn Thái Ngọc Duyv3 only changes 07/16 but it's kinda important because I broke packed-refs. packed-refs' path became $GIT_DIR/packed-refs instead of $GIT_COMMON_DIR/packed-refs and as a result the majority of refs will disappear in linked worktrees. Interdiff
refs/files-backend.c +5 -3
@@ -938,9 +938,11 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb,va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);va_end (vap); -if (is_per_worktree_ref (tmp.buf) || - (skip_prefix (tmp.buf,"logs/" , &ref) && -is_per_worktree_ref (ref))) +if (!strcmp (tmp.buf,"packed-refs" ) || !strcmp (tmp.buf,"logs" )) +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf); +else if (is_per_worktree_ref (tmp.buf) || + (skip_prefix (tmp.buf,"logs/" , &ref) && +is_per_worktree_ref (ref)))strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf);else strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf);
Nguyễn Thái Ngọc Duy (16):
refs-internal.c: make files_log_ref_write() static
files-backend: convert git_path() to strbuf_git_path()
files-backend: add files_path()
files-backend: replace *git_path*() with files_path()
refs.c: share is_per_worktree_ref() to files-backend.c refs-internal.h: correct is_per_worktree_ref()
files-backend: remove the use of git_path()
refs.c: introduce get_main_ref_store()
refs: rename lookup_ref_store() to lookup_submodule_ref_store() refs.c: flatten get_ref_store() a bit
refs.c: kill register_ref_store(), add register_submodule_ref_store() refs.c: make get_main_ref_store() public and use it
path.c: move some code out of strbuf_git_path_submodule()
refs: move submodule code out of files-backend.c
files-backend: remove submodule_allowed from files_downcast()
refs: rename get_ref_store() to get_submodule_ref_store() and make it public
path.c | 34 ++--- refs.c | 144 +++++++++++---------- refs.h | 13 ++ refs/files-backend.c | 349 +++++++++++++++++++++++++++++++-------------------- refs/refs-internal.h | 28 ++--- submodule.c | 31 +++++ submodule.h | 1 + 7 files changed, 348 insertions(+), 252 deletions(-)
Signature · 1 line
2.11.0.157.gd943d85
PATCH v3 1/16 refs-internal.c: make files_log_ref_write() static
Created 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
@@ -222,10 +222,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 v3 2/16 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 | 111 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 22 deletions(-)
refs/files-backend.c +89 -22
@@ -2169,6 +2169,8 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)static int timeout_configured =0 ;static int timeout_value =1000 ;struct packed_ref_cache *packed_ref_cache; +struct strbuf sb =STRBUF_INIT ; +int ret;files_assert_main_repository (refs,"lock_packed_refs" );
@@ -2177,10 +2179,13 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) timeout_configured =1 ; } -if (hold_lock_file_for_update_timeout ( - &packlock,git_path ("packed-refs" ), - flags, timeout_value) <0 ) +strbuf_git_path (&sb,"packed-refs" ); + ret =hold_lock_file_for_update_timeout (&packlock, sb.buf, + flags, timeout_value); +strbuf_release (&sb); +if (ret <0 )return -1 ; +/* * Get the current packed-refs while holding the lock. If the * packed-refs file has been modified since we last read it,
@@ -2335,6 +2340,9 @@ static void try_remove_empty_parents(char *name)for (q = p; *q; q++) ;while (1 ) { +struct strbuf sb =STRBUF_INIT ; +int ret; +while (q > p && *q !='/' ) q--;while (q > p && *(q-1 ) =='/' )
@@ -2342,7 +2350,10 @@ static void try_remove_empty_parents(char *name)if (q == p)break ; *q ='\0' ; -if (rmdir (git_path ("%s" , name))) +strbuf_git_path (&sb,"%s" , name); + ret =rmdir (sb.buf); +strbuf_release (&sb); +if (ret)break ; } }
@@ -2431,7 +2442,11 @@ 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); +struct strbuf sb =STRBUF_INIT ; + +strbuf_git_path (&sb,"packed-refs" ); +unable_to_lock_message (sb.buf, errno, err); +strbuf_release (&sb);return -1 ; } packed =get_packed_refs (refs);
@@ -2529,8 +2544,10 @@ static int rename_tmp_log(const char *newrefname) {int attempts_remaining =4 ;struct strbuf path =STRBUF_INIT ; +struct strbuf tmp_renamed_log =STRBUF_INIT ;int ret =-1 ; +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); retry:strbuf_reset (&path);strbuf_git_path (&path,"logs/%s" , newrefname);
@@ -2546,7 +2563,7 @@ static int rename_tmp_log(const char *newrefname) goto out; } -if (rename (git_path (TMP_RENAMED_LOG ), path.buf)) { +if (rename (tmp_renamed_log.buf, path.buf)) {if ((errno==EISDIR || errno==ENOTDIR ) && --attempts_remaining >0 ) {/* * rename(a, b) when b is an existing
@@ -2574,6 +2591,7 @@ static int rename_tmp_log(const char *newrefname) ret =0 ; out:strbuf_release (&path); +strbuf_release (&tmp_renamed_log);return ret; }
@@ -2614,9 +2632,15 @@ 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 ; +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); + log = !lstat (sb_oldref.buf, &loginfo); +strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))return error ("reflog for %s is a symlink" , oldrefname);
@@ -2630,7 +2654,12 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log); +if (ret)return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno));
@@ -2709,13 +2738,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))) +strbuf_git_path (&sb_newref,"logs/%s" , newrefname); +strbuf_git_path (&sb_oldref,"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)); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG );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)); +strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log);return 1 ; }
@@ -3111,22 +3146,32 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static 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)
@@ -3181,7 +3226,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 ;
@@ -3287,7 +3334,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 ;
@@ -3369,12 +3418,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; }
@@ -3843,8 +3895,13 @@ static int files_transaction_commit(struct ref_store *ref_store, ret =TRANSACTION_GENERIC_ERROR ; goto cleanup; } -for_each_string_list_item (ref_to_delete, &refs_to_delete) -unlink_or_warn (git_path ("logs/%s" , ref_to_delete->string)); +for_each_string_list_item (ref_to_delete, &refs_to_delete) { +struct strbuf sb =STRBUF_INIT ; + +strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +unlink_or_warn (sb.buf); +strbuf_release (&sb); + }clear_loose_ref_cache (refs); cleanup:
@@ -4098,18 +4155,28 @@ 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_reset (&sb);if (get_shared_repository ()) { -adjust_shared_perm (git_path ("refs/heads" )); -adjust_shared_perm (git_path ("refs/tags" )); +strbuf_git_path (&sb,"refs/heads" ); +adjust_shared_perm (sb.buf); +strbuf_reset (&sb); +strbuf_git_path (&sb,"refs/tags" ); +adjust_shared_perm (sb.buf); } +strbuf_release (&sb);return 0 ; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v3 3/16 files-backend: add files_path()
In reply to Nguyễn Thái Ngọc DuyThis will be the replacement for both git_path() and git_path_submodule() in this file. The idea is backend takes a git path and use that, oblivious of submodule, linked worktrees and such.
This is the middle step towards that. Eventually the "submodule" field in 'struct files_ref_store' should be replace by "gitdir". And a compound ref_store is created to combine two files backends together, one represents the shared refs in $GIT_COMMON_DIR, one per-worktree. At that point, files_path() becomes a wrapper of strbuf_vaddf().
--- refs/files-backend.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
refs/files-backend.c +18 -0
@@ -930,6 +930,24 @@ struct files_ref_store {/* Lock used for the main packed-refs file: */ static struct lock_file packlock; +__attribute__((format (printf,3 ,4 ))) +static void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) +{ +struct strbuf tmp =STRBUF_INIT ; +va_list vap; + +va_start (vap, fmt); +strbuf_vaddf (&tmp, fmt, vap); +va_end (vap); +if (refs->submodule) +strbuf_git_path_submodule (sb, refs->submodule, +"%s" , tmp.buf); +else +strbuf_git_path (sb,"%s" , tmp.buf); +strbuf_release (&tmp); +} +/* * Increment the reference count of *packed_refs. */
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v3 03/16] files-backend: add files_path()
Quoted 6 lines · Nguyễn Thái Ngọc Duy
This will be the replacement for both
git_path()andgit_path_submodule()in this file. The idea is backend takes a git path and use that, oblivious of submodule, linked worktrees and such.This is the middle step towards that. Eventually the "submodule" field in 'struct
files_ref_store' should be replace by "gitdir". And a
s/replace/&d/;
Quoted 3 lines
compound
ref_storeis created to combine two files backends together, one represents the shared refs in $GIT_COMMON_DIR, one per-worktree. At that point,files_path()becomes a wrapper ofstrbuf_vaddf().
I like the general direction, obviously ;-)
Quoted 35 lines
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)refs/files-backend.c +18
-0@@ -930,6 +930,24 @@ struct files_ref_store {/* Lock used for the main packed-refs file: */ static struct lock_file packlock; +__attribute__((format (printf,3 ,4 ))) +static void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) +{ +struct strbuf tmp =STRBUF_INIT ; +va_list vap; + +va_start (vap, fmt); +strbuf_vaddf (&tmp, fmt, vap); +va_end (vap); +if (refs->submodule) +strbuf_git_path_submodule (sb, refs->submodule, +"%s" , tmp.buf); +else +strbuf_git_path (sb,"%s" , tmp.buf); +strbuf_release (&tmp); +} +/* * Increment the reference count of *packed_refs. */
PATCH v3 4/16 files-backend: replace *git_path*() with files_path()
In reply to Nguyễn Thái Ngọc DuyThis centralizes all path rewriting of files-backend.c in one place so we have easier time removing the path rewriting later. There could be some hidden indirect git_path() though, I didn't audit the code to the bottom.
Side note: set_worktree_head_symref() is a bad boy and should not be in files-backend.c (probably should not exist in the first place). But we'll leave it there until we have better multi-worktree support in refs before we update it.
--- refs/files-backend.c | 185 ++++++++++++++++++++++++++------------------------- 1 file changed, 94 insertions(+), 91 deletions(-)
refs/files-backend.c +94 -91
@@ -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);
@@ -1178,12 +1179,10 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)static struct packed_ref_cache *get_packed_ref_cache (struct files_ref_store *refs) {char *packed_refs_file; +struct strbuf sb =STRBUF_INIT ; -if (refs->submodule) - packed_refs_file =git_pathdup_submodule (refs->submodule, -"packed-refs" ); -else - packed_refs_file =git_pathdup ("packed-refs" ); +files_path (refs, &sb,"packed-refs" ); + packed_refs_file =strbuf_detach (&sb,NULL );if (refs->packed && !stat_validity_check (&refs->packed->validity, packed_refs_file))
@@ -1249,10 +1248,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)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_path (refs, &path,"%s" , dirname); path_baselen = path.len;if (err) {
@@ -1394,10 +1390,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_path (refs, &sb_path,"%s" , refname); path = sb_path.buf;
@@ -1585,7 +1578,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_path (refs, &ref_file,"%s" , refname); retry:switch (safe_create_leading_directories (ref_file.buf)) {
@@ -2052,7 +2045,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_path (refs, &ref_file,"%s" , refname); resolved = !!resolve_ref_unsafe (refname, resolve_flags, lock->old_oid.hash, type);if (!resolved && errno ==EISDIR ) {
@@ -2197,7 +2190,7 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) timeout_configured =1 ; } -strbuf_git_path (&sb,"packed-refs" ); +files_path (refs, &sb,"packed-refs" ); ret =hold_lock_file_for_update_timeout (&packlock, sb.buf, flags, timeout_value);strbuf_release (&sb);
@@ -2343,7 +2336,7 @@ static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data)* Remove empty parents, but spare refs/ and immediate subdirs. * Note: munges *name. */ -static void try_remove_empty_parents (char *name) +static void try_remove_empty_parents (struct files_ref_store *refs,char *name) {char *p, *q;int i;
@@ -2368,7 +2361,7 @@ static void try_remove_empty_parents(char *name)if (q == p)break ; *q ='\0' ; -strbuf_git_path (&sb,"%s" , name); +files_path (refs, &sb,"%s" , name); ret =rmdir (sb.buf);strbuf_release (&sb);if (ret)
@@ -2377,7 +2370,7 @@ static void try_remove_empty_parents(char *name) }/* 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 ;
@@ -2397,13 +2390,13 @@ static void prune_ref(struct ref_to_prune *r) }ref_transaction_free (transaction);strbuf_release (&err); -try_remove_empty_parents (r->name); +try_remove_empty_parents (refs, r->name); } -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; } }
@@ -2426,7 +2419,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 ; }
@@ -2462,7 +2455,7 @@ static int repack_without_refs(struct files_ref_store *refs,if (lock_packed_refs (refs,0 )) {struct strbuf sb =STRBUF_INIT ; -strbuf_git_path (&sb,"packed-refs" ); +files_path (refs, &sb,"packed-refs" );unable_to_lock_message (sb.buf, errno, err);strbuf_release (&sb);return -1 ;
@@ -2558,17 +2551,17 @@ static int files_delete_refs(struct ref_store *ref_store,*/ #define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log" -static int rename_tmp_log (const char *newrefname) +static int rename_tmp_log (struct files_ref_store *refs,const char *newrefname) {int attempts_remaining =4 ;struct strbuf path =STRBUF_INIT ;struct strbuf tmp_renamed_log =STRBUF_INIT ;int ret =-1 ; -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); retry:strbuf_reset (&path); -strbuf_git_path (&path,"logs/%s" , newrefname); +files_path (refs, &path,"logs/%s" , newrefname);switch (safe_create_leading_directories_const (path.buf)) {case SCLD_OK :break ;/* success */
@@ -2656,7 +2649,7 @@ 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); +files_path (refs, &sb_oldref,"logs/%s" , oldrefname); log = !lstat (sb_oldref.buf, &loginfo);strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))
@@ -2672,8 +2665,8 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &sb_oldref,"logs/%s" , oldrefname); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf);strbuf_release (&sb_oldref);strbuf_release (&tmp_renamed_log);
@@ -2700,7 +2693,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_path (refs, &path,"%s" , newrefname); result =remove_empty_directories (&path);strbuf_release (&path);
@@ -2714,7 +2707,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;
@@ -2756,12 +2749,12 @@ static int files_rename_ref(struct ref_store *ref_store, log_all_ref_updates = flag; rollbacklog: -strbuf_git_path (&sb_newref,"logs/%s" , newrefname); -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +files_path (refs, &sb_newref,"logs/%s" , newrefname); +files_path (refs, &sb_oldref,"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)); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG );if (!logmoved && log &&rename (tmp_renamed_log.buf, sb_oldref.buf)) error("unable to restore logfile %s from "TMP_RENAMED_LOG": %s",
@@ -2817,11 +2810,13 @@ static int commit_ref(struct ref_lock *lock)* should_autocreate_reflog returns non-zero. Otherwise, create it * regardless of the ref name. Fill in *err and return -1 on failure. */ -static int log_ref_setup (const char *refname,struct strbuf *logfile,struct strbuf *err,int force_create) +static int log_ref_setup (struct files_ref_store *refs,const char *refname, +struct strbuf *logfile,struct strbuf *err, +int force_create) {int logfd, oflags =O_APPEND |O_WRONLY ; -strbuf_git_path (logfile,"logs/%s" , refname); +files_path (refs, logfile,"logs/%s" , refname);if (force_create ||should_autocreate_reflog (refname)) {if (safe_create_leading_directories (logfile->buf) <0 ) { strbuf_addf(err, "unable to create directory for '%s': "
@@ -2864,11 +2859,10 @@ static int files_create_reflog(struct ref_store *ref_store, {int ret;struct strbuf sb =STRBUF_INIT ; +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"create_reflog" ); -/* Check validity (but we don't need the result): */ -files_downcast (ref_store,0 ,"create_reflog" ); - - ret =log_ref_setup (refname, &sb, err, force_create); + ret =log_ref_setup (refs, refname, &sb, err, force_create);strbuf_release (&sb);return ret; }
@@ -2899,7 +2893,8 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,return 0 ; } -static int log_ref_write_1 (const char *refname,const unsigned char *old_sha1, +static int log_ref_write_1 (struct files_ref_store *refs, +const char *refname,const unsigned char *old_sha1,const unsigned char *new_sha1,const char *msg,struct strbuf *logfile,int flags,struct strbuf *err)
@@ -2909,7 +2904,7 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,if (log_all_ref_updates <0 ) log_all_ref_updates = !is_bare_repository (); - result =log_ref_setup (refname, logfile, err, flags &REF_FORCE_CREATE_REFLOG ); + result =log_ref_setup (refs, refname, logfile, err, flags &REF_FORCE_CREATE_REFLOG );if (result)return result;
@@ -2933,21 +2928,23 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,return 0 ; } -static int log_ref_write (const char *refname,const unsigned char *old_sha1, +static int 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) { -return files_log_ref_write (refname, old_sha1, new_sha1, msg, flags, - err); +return files_log_ref_write (refs, refname, old_sha1, new_sha1, + msg, flags, err); } -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) {struct strbuf sb =STRBUF_INIT ; -int ret =log_ref_write_1 (refname, old_sha1, new_sha1, msg, &sb, flags, - err); +int ret =log_ref_write_1 (refs, refname, old_sha1, new_sha1, msg, + &sb, flags, err);strbuf_release (&sb);return ret; }
@@ -3004,7 +3001,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 (log_ref_write (lock->ref_name, lock->old_oid.hash, sha1, logmsg,0 , err)) { +if (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" , lock->ref_name, old_msg);
@@ -3035,8 +3033,8 @@ 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 (log_ref_write ("HEAD" , lock->old_oid.hash, sha1, - logmsg,0 , &log_err)) { +if (log_ref_write (refs,"HEAD" , lock->old_oid.hash, + sha1, logmsg,0 , &log_err)) {error ("%s" , log_err.buf);strbuf_release (&log_err); }
@@ -3068,23 +3066,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) && -log_ref_write (refname, lock->old_oid.hash, new_sha1, logmsg,0 , &err)) { +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 ; }
@@ -3092,7 +3093,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);
@@ -3121,13 +3122,19 @@ 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) { +/* +* 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 ;
@@ -3154,7 +3161,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target) lock->lk = &head_lock; lock->ref_name =xstrdup (head_rel); - ret =create_symref_locked (lock, head_rel, target,NULL ); + ret =create_symref_locked (refs, lock, head_rel, target,NULL );unlock_ref (lock);/* will free lock */ strbuf_release (&head_path);
@@ -3164,14 +3171,13 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static int files_reflog_exists (struct ref_store *ref_store,const char *refname) { +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"reflog_exists" );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_path (refs, &sb,"logs/%s" , refname); ret = !lstat (sb.buf, &st) &&S_ISREG (st.st_mode);strbuf_release (&sb);return ret;
@@ -3180,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_path (refs, &sb,"logs/%s" , refname); ret =remove_path (sb.buf);strbuf_release (&sb);return ret;
@@ -3236,15 +3241,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_path (refs, &sb,"logs/%s" , refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3345,14 +3349,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_path (refs, &sb,"logs/%s" , refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3434,15 +3437,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_path (refs, &sb,"logs" ); iter->dir_iterator =dir_iterator_begin (sb.buf);strbuf_release (&sb);return ref_iterator;
@@ -3866,8 +3868,8 @@ static int files_transaction_commit(struct ref_store *ref_store,if (update->flags &REF_NEEDS_COMMIT || update->flags &REF_LOG_ONLY ) { -if (log_ref_write (lock->ref_name, lock->old_oid.hash, - update->new_sha1, +if (log_ref_write (refs, lock->ref_name, + lock->old_oid.hash, update->new_sha1, update->msg, update->flags, err)) {char *old_msg =strbuf_detach (err,NULL );
@@ -3916,7 +3918,7 @@ static int files_transaction_commit(struct ref_store *ref_store,for_each_string_list_item (ref_to_delete, &refs_to_delete) {struct strbuf sb =STRBUF_INIT ; -strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +files_path (refs, &sb,"logs/%s" , ref_to_delete->string);unlink_or_warn (sb.buf);strbuf_release (&sb); }
@@ -4078,6 +4080,7 @@ static int files_reflog_expire(struct ref_store *ref_store,int status =0 ;int type;struct strbuf err =STRBUF_INIT ; +struct strbuf sb =STRBUF_INIT ;memset (&cb,0 ,sizeof (cb)); cb.flags = flags;
@@ -4102,7 +4105,8 @@ static int files_reflog_expire(struct ref_store *ref_store,return 0 ; } - log_file =git_pathdup ("logs/%s" , refname); +files_path (refs, &sb,"logs/%s" , refname); + log_file =strbuf_detach (&sb,NULL );if (!(flags &EXPIRE_REFLOGS_DRY_RUN )) {/* * Even though holding $GIT_DIR/logs/$reflog.lock has
@@ -4173,25 +4177,24 @@ 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_path (refs, &sb,"refs/heads" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_path (refs, &sb,"refs/tags" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb);if (get_shared_repository ()) { -strbuf_git_path (&sb,"refs/heads" ); +files_path (refs, &sb,"refs/heads" );adjust_shared_perm (sb.buf);strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_path (refs, &sb,"refs/tags" );adjust_shared_perm (sb.buf); }strbuf_release (&sb);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v3 04/16] files-backend: replace *git_path*() with files_path()
Quoted 10 lines · Nguyễn Thái Ngọc Duy
This centralizes all path rewriting of
files-backend.cin one place so we have easier time removing the path rewriting later. There could be some hidden indirectgit_path()though, I didn't audit the code to the bottom.Side note:
set_worktree_head_symref()is a bad boy and should not be infiles-backend.c(probably should not exist in the first place). But we'll leave it there until we have better multi-worktree support in refs before we update it.
Quoted 4 lines
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 185 ++++++++++++++++++++++++++------------------------- 1 file changed, 94 insertions(+), 91 deletions(-)
In this step, files_path() is still "if refs->submodule field is there, then use that to call strbuf_git_path_submodule() and otherwise call strbuf_git_path()." That is a very sensible refactoring for things like packed-refs-file in this hunk:
refs/files-backend.c static void read_packed_refs(FILE *f, struct ref_dir *dir) · line 1185
Quoted 12 lines
static struct
packed_ref_cache*get_packed_ref_cache(structfiles_ref_store*refs) {refs/files-backend.c +3
-5char *packed_refs_file; +struct strbuf sb =STRBUF_INIT ; -if (refs->submodule) - packed_refs_file =git_pathdup_submodule (refs->submodule, -"packed-refs" ); -else - packed_refs_file =git_pathdup ("packed-refs" ); +files_path (refs, &sb,"packed-refs" ); + packed_refs_file =strbuf_detach (&sb,NULL );
But the original code of some other changes do not follow that pattern, e.g.
refs/files-backend.c static int lock_raw_ref(struct files_ref_store *refs, · line 1581
Quoted 6 lines
refs/files-backend.c +1
-1@@ -1585,7 +1578,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_path (refs, &ref_file,"%s" , refname);
Is it the right way to review these changes to make sure that a conversion from the original that is an unconditional strbuf_git_path() to files_path() happens only if the function is "files-assert-main-repository" clean? lock_raw_ref() certainly is one of those functions where the caller should not have a non-empty submodule field in refs.
refs/files-backend.c static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs, · line 2048
Quoted 6 lines
refs/files-backend.c +1
-1@@ -2052,7 +2045,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_path (refs, &ref_file,"%s" , refname);
So is this one; lock_ref_sha1_basic() is protected with assert-main-repo.
Quoted 10 lines
refs/files-backend.c +1
-1@@ -2343,7 +2336,7 @@ static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data)* Remove empty parents, but spare refs/ and immediate subdirs. * Note: munges *name. */ -static void try_remove_empty_parents (char *name) +static void try_remove_empty_parents (struct files_ref_store *refs,char *name) {char *p, *q;int i;
refs/files-backend.c static void try_remove_empty_parents(char *name) · line 2364
Quoted 5 lines
refs/files-backend.c +1
-1@@ -2368,7 +2361,7 @@ static void try_remove_empty_parents(char *name)if (q == p)break ; *q ='\0' ; -strbuf_git_path (&sb,"%s" , name); +files_path (refs, &sb,"%s" , name);
But here it gets iffy. try_remove_empty_parents() itself does not assert, and its sole caller prune_ref() does not, either. The sole caller of prune_ref() which is prune_refs() does not. As we climb the call chain up, we reach files_pack_refs(). Am I confused to doubt that the method is inherently main-repo only?
... ah, OK, files_downcast() at the beginning of pack_refs forbids submodule. So this is safe.
refs/files-backend.c static int repack_without_refs(struct files_ref_store *refs, · line 2458
Quoted 6 lines
refs/files-backend.c +1
-1@@ -2462,7 +2455,7 @@ static int repack_without_refs(struct files_ref_store *refs,if (lock_packed_refs (refs,0 )) {struct strbuf sb =STRBUF_INIT ; -strbuf_git_path (&sb,"packed-refs" ); +files_path (refs, &sb,"packed-refs" );
This is safe, as repack_without_refs() asserts that it is main-repo only.
refs/files-backend.c static int files_delete_refs(struct ref_store *ref_store, · line 2555
Quoted 7 lines
refs/files-backend.c +1
-1@@ -2558,17 +2551,17 @@ static int files_delete_refs(struct ref_store *ref_store,*/ #define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log" -static int rename_tmp_log (const char *newrefname) +static int rename_tmp_log (struct files_ref_store *refs,const char *newrefname) {
The sole caller files_rename_ref() is main-repo only and that is guaranteed when downcast is done.
refs/files-backend.c static int commit_ref(struct ref_lock *lock) · line 2819
Quoted 9 lines
refs/files-backend.c +4
-2-static int log_ref_setup (const char *refname,struct strbuf *logfile,struct strbuf *err,int force_create) +static int log_ref_setup (struct files_ref_store *refs,const char *refname, +struct strbuf *logfile,struct strbuf *err, +int force_create) {int logfd, oflags =O_APPEND |O_WRONLY ; -strbuf_git_path (logfile,"logs/%s" , refname); +files_path (refs, logfile,"logs/%s" , refname);
This and friends of log_ref_write() eventually rolls up to commit_ref_update() that has the main-repo only assertion, so they should be safe.
Another entry point files_create_symref() via create_symref_locked() also reaches log_ref_write() and friends but the safety is guaranteed via the downcast that asserts.
OK, overall I really like the loss of "Check the validity but we do not need the result" with this step. The same checks are still done but the code looks much less hacky.
PATCH v3 5/16 refs.c: share is_per_worktree_ref() to files-backend.c
In reply to Nguyễn Thái Ngọc Duy--- refs.c | 6 ------ refs/refs-internal.h | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-)
refs.c +0 -6
@@ -489,12 +489,6 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)return logs_found; } -static int is_per_worktree_ref (const char *refname) -{ -return !strcmp (refname,"HEAD" ) || -starts_with (refname,"refs/bisect/" ); -} -static int is_pseudoref_syntax (const char *refname) {const char *c;
refs/refs-internal.h +6 -0
@@ -651,4 +651,10 @@ const char *resolve_ref_recursively(struct ref_store *refs,int resolve_flags, unsigned char *sha1, int *flags); +static inline int is_per_worktree_ref (const char *refname) +{ +return !strcmp (refname,"HEAD" ) || +starts_with (refname,"refs/bisect/" ); +} +#endif /* REFS_REFS_INTERNAL_H */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v3 6/16 refs-internal.h: correct is_per_worktree_ref()
In reply to Nguyễn Thái Ngọc DuyAll refs outside refs/ directory is per-worktree, not just HEAD.
--- refs/refs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
refs/refs-internal.h +1 -1
@@ -653,7 +653,7 @@ const char *resolve_ref_recursively(struct ref_store *refs,static inline int is_per_worktree_ref (const char *refname) { -return !strcmp (refname,"HEAD" ) || +return !starts_with (refname,"refs/" ) ||starts_with (refname,"refs/bisect/" ); }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v3 7/16 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 | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
refs/files-backend.c +20 -2
@@ -924,6 +924,9 @@ struct files_ref_store {*/ const char *submodule; +struct strbuf gitdir; +struct strbuf gitcommondir; +struct ref_entry *loose;struct packed_ref_cache *packed; };
@@ -937,6 +940,7 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb, {struct strbuf tmp =STRBUF_INIT ;va_list vap; +const char *ref;va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);
@@ -944,8 +948,14 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb,if (refs->submodule)strbuf_git_path_submodule (sb, refs->submodule,"%s" , tmp.buf); +else if (!strcmp (tmp.buf,"packed-refs" ) || !strcmp (tmp.buf,"logs" )) +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf); +else if (is_per_worktree_ref (tmp.buf) || + (skip_prefix (tmp.buf,"logs/" , &ref) && +is_per_worktree_ref (ref))) +strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf);else -strbuf_git_path (sb,"%s" , tmp.buf); +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf);strbuf_release (&tmp); }
@@ -1004,7 +1014,15 @@ 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); +strbuf_init (&refs->gitdir,0 ); +strbuf_init (&refs->gitcommondir,0 ); + +if (submodule) { + refs->submodule =xstrdup (submodule); + }else { +strbuf_addstr (&refs->gitdir,get_git_dir ()); +strbuf_addstr (&refs->gitcommondir,get_git_common_dir ()); + }return ref_store; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v3 8/16 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
@@ -1445,15 +1445,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
PATCH v3 9/16 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
@@ -1384,17 +1384,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 ;
@@ -1463,7 +1459,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 ;
@@ -1474,7 +1470,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 v3 10/16 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 | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
refs.c +9 -10
@@ -1454,22 +1454,21 @@ 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;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); +if (is_nonbare_repository_dir (&submodule_sb)) + refs =ref_store_init (submodule); +strbuf_release (&submodule_sb);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v3 11/16 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 | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-)
refs.c +19 -17
@@ -1402,25 +1402,19 @@ 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. +* for submodule. 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) +static void register_submodule_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 (!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); - } +if (hashmap_put (&submodule_ref_stores, +alloc_submodule_hash_entry (submodule, refs))) +die ("BUG: ref_store for submodule '%s' initialized twice" , + submodule); }/*
@@ -1437,7 +1431,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; }
@@ -1449,6 +1442,12 @@ 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; }
@@ -1469,6 +1468,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) +register_submodule_ref_store (refs, submodule);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v3 11/16] refs.c: kill register_ref_store(), add register_submodule_ref_store()
Quoted 4 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().
Very nice.
PATCH v3 12/16 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 | 2 ++ 2 files changed, 20 insertions(+), 18 deletions(-)
refs.c +18 -18
@@ -1303,7 +1303,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); }
@@ -1311,7 +1311,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); }
@@ -1434,7 +1434,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;
@@ -1483,14 +1483,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); }
@@ -1498,7 +1498,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);
@@ -1507,7 +1507,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); }
@@ -1517,14 +1517,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);
@@ -1535,7 +1535,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);
@@ -1544,14 +1544,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); }
@@ -1559,14 +1559,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); }
@@ -1578,7 +1578,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,
@@ -1588,21 +1588,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 +2 -0
@@ -553,4 +553,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 */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v3 13/16 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
@@ -1335,3 +1335,34 @@ void prepare_submodule_repo_env(struct argv_array *out) }argv_array_push (out,"GIT_DIR=.git" ); } + +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
@@ -70,6 +70,7 @@ extern int push_unpushed_submodules(struct sha1_array *commits, int dry_run);void connect_work_tree_and_git_dir (const char *work_tree,const char *git_dir);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
PATCH v3 14/16 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().
The new code in init_submodule_ref_store() is basically a copy of strbuf_git_path_submodule().
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() follows shortly. It's separate to keep noises from this patch.
--- refs.c | 18 +++++++++++++----- refs/files-backend.c | 22 ++++++---------------- refs/refs-internal.h | 6 +++--- 3 files changed, 22 insertions(+), 24 deletions(-)
refs.c +13 -5
@@ -9,6 +9,7 @@#include "refs/refs-internal.h" #include "object.h" #include "tag.h" +#include "submodule.h" /* * List of all available backends
@@ -1419,9 +1420,9 @@ static void register_submodule_ref_store(struct ref_store *refs,/* * Create, record, and return a ref_store instance for the specified -* submodule (or the main repository if submodule is NULL). +* gitdir (or the main repository if gitdir is NULL). */ -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);
@@ -1430,7 +1431,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; }
@@ -1455,6 +1456,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 ();
@@ -1465,8 +1467,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 +6 -16
@@ -917,13 +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; -struct strbuf gitdir;struct strbuf gitcommondir;
@@ -945,10 +938,7 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb,va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);va_end (vap); -if (refs->submodule) -strbuf_git_path_submodule (sb, refs->submodule, -"%s" , tmp.buf); -else if (!strcmp (tmp.buf,"packed-refs" ) || !strcmp (tmp.buf,"logs" )) +if (!strcmp (tmp.buf,"packed-refs" ) || !strcmp (tmp.buf,"logs" ))strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf); else if (is_per_worktree_ref(tmp.buf) || (skip_prefix(tmp.buf, "logs/", &ref) &&
@@ -1007,7 +997,7 @@ 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;
@@ -1017,8 +1007,9 @@ static struct ref_store *files_ref_store_create(const char *submodule)strbuf_init (&refs->gitdir,0 );strbuf_init (&refs->gitcommondir,0 ); -if (submodule) { - refs->submodule =xstrdup (submodule); +if (gitdir) { +strbuf_addstr (&refs->gitdir, gitdir); +get_common_dir_noenv (&refs->gitcommondir, gitdir); }else {strbuf_addstr (&refs->gitdir,get_git_dir ());strbuf_addstr (&refs->gitcommondir,get_git_common_dir ());
@@ -1034,8 +1025,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 */ }/*
refs/refs-internal.h +3 -3
@@ -476,12 +476,12 @@ 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 +* Initialize the ref_store for the specified gitdir, or for the +* current repository if gitdir == NULL. These functions should call * base_ref_store_init() to initialize the shared part of the * ref_store and to record the ref_store for later lookup. */ -typedef struct ref_store *ref_store_init_fn (const char *submodule); +typedef 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 v3 15/16 files-backend: remove submodule_allowed from files_downcast()
In reply to Nguyễn Thái Ngọc DuySince submodule or not is irrelevant to files-backend after the last patch, remove the parameter from files_downcast() and kill files_assert_main_repository().
PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
--- refs/files-backend.c | 70 ++++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 49 deletions(-)
refs/files-backend.c +21 -49
@@ -1019,24 +1019,13 @@ 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. -*/ -static void files_assert_main_repository (struct files_ref_store *refs, -const char *caller) -{ -/* This function is to be deleted in the next patch */ -} - -/* * 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. */ -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, +const char *caller) {struct files_ref_store *refs;
@@ -1046,9 +1035,6 @@ static struct files_ref_store *files_downcast( refs = (struct files_ref_store *)ref_store; -if (!submodule_allowed) -files_assert_main_repository (refs, caller); -return refs; }
@@ -1384,7 +1370,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, struct strbuf *referent, unsigned int *type) { struct files_ref_store *refs = -files_downcast (ref_store,1 ,"read_raw_ref" ); +files_downcast (ref_store,"read_raw_ref" );struct strbuf sb_contents =STRBUF_INIT ;struct strbuf sb_path =STRBUF_INIT ;const char *path;
@@ -1577,7 +1563,6 @@ static int lock_raw_ref(struct files_ref_store *refs,int ret =TRANSACTION_GENERIC_ERROR ;assert (err); -files_assert_main_repository (refs,"lock_raw_ref" ); *type =0 ;
@@ -1801,7 +1786,7 @@ static enum peel_status peel_entry(struct ref_entry *entry, int repeel)static int files_peel_ref (struct ref_store *ref_store,const char *refname,unsigned char *sha1) { -struct files_ref_store *refs =files_downcast (ref_store,0 ,"peel_ref" ); +struct files_ref_store *refs =files_downcast (ref_store,"peel_ref" );int flag;unsigned char base[20 ];
@@ -1910,7 +1895,7 @@ static struct ref_iterator *files_ref_iterator_begin( const char *prefix, unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,1 ,"ref_iterator_begin" ); +files_downcast (ref_store,"ref_iterator_begin" );struct ref_dir *loose_dir, *packed_dir;struct ref_iterator *loose_iter, *packed_iter;struct files_ref_iterator *iter;
@@ -2043,7 +2028,6 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,int attempts_remaining =3 ;int resolved; -files_assert_main_repository (refs,"lock_ref_sha1_basic" );assert (err); lock =xcalloc (1 ,sizeof (struct ref_lock ));
@@ -2191,8 +2175,6 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)struct strbuf sb =STRBUF_INIT ;int ret; -files_assert_main_repository (refs,"lock_packed_refs" ); -if (!timeout_configured) {git_config_get_int ("core.packedrefstimeout" , &timeout_value); timeout_configured =1 ;
@@ -2232,8 +2214,6 @@ static int commit_packed_refs(struct files_ref_store *refs)int save_errno =0 ;FILE *out; -files_assert_main_repository (refs,"commit_packed_refs" ); -if (!packed_ref_cache->lock)die ("internal error: packed-refs not locked" );
@@ -2265,8 +2245,6 @@ static void rollback_packed_refs(struct files_ref_store *refs)struct packed_ref_cache *packed_ref_cache =get_packed_ref_cache (refs); -files_assert_main_repository (refs,"rollback_packed_refs" ); -if (!packed_ref_cache->lock)die ("internal error: packed-refs not locked" );rollback_lock_file (packed_ref_cache->lock);
@@ -2412,7 +2390,7 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune *r)static int files_pack_refs (struct ref_store *ref_store,unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"pack_refs" ); +files_downcast (ref_store,"pack_refs" );struct pack_refs_cb_data cbdata;memset (&cbdata,0 ,sizeof (cbdata));
@@ -2445,7 +2423,6 @@ static int repack_without_refs(struct files_ref_store *refs,struct string_list_item *refname;int ret, needs_repacking =0 , removed =0 ; -files_assert_main_repository (refs,"repack_without_refs" );assert (err);/* Look for a packed ref */
@@ -2513,7 +2490,7 @@ static int files_delete_refs(struct ref_store *ref_store, struct string_list *refnames, unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"delete_refs" ); +files_downcast (ref_store,"delete_refs" );struct strbuf err =STRBUF_INIT ;int i, result =0 ;
@@ -2621,7 +2598,7 @@ static int files_verify_refname_available(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,1 ,"verify_refname_available" ); +files_downcast (ref_store,"verify_refname_available" );struct ref_dir *packed_refs =get_packed_refs (refs);struct ref_dir *loose_refs =get_loose_refs (refs);
@@ -2646,7 +2623,7 @@ static int files_rename_ref(struct ref_store *ref_store, const char *logmsg) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"rename_ref" ); +files_downcast (ref_store,"rename_ref" );unsigned char sha1[20 ], orig_sha1[20 ];int flag =0 , logmoved =0 ;struct ref_lock *lock;
@@ -2868,7 +2845,7 @@ static int files_create_reflog(struct ref_store *ref_store,int ret;struct strbuf sb =STRBUF_INIT ;struct files_ref_store *refs = -files_downcast (ref_store,0 ,"create_reflog" ); +files_downcast (ref_store,"create_reflog" ); ret =log_ref_setup (refs, refname, &sb, err, force_create);strbuf_release (&sb);
@@ -3006,8 +2983,6 @@ static int commit_ref_update(struct files_ref_store *refs, const unsigned char *sha1, const char *logmsg, struct strbuf *err) { - files_assert_main_repository(refs, "commit_ref_update"); -clear_loose_ref_cache (refs );if (log_ref_write (refs, lock->ref_name, lock->old_oid.hash, sha1, logmsg,0 , err)) {
@@ -3116,7 +3091,7 @@ static int files_create_symref(struct ref_store *ref_store, const char *logmsg) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"create_symref" ); +files_downcast (ref_store,"create_symref" );struct strbuf err =STRBUF_INIT ;struct ref_lock *lock;int ret;
@@ -3142,7 +3117,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_ref_store (NULL ),"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
@@ -3180,7 +3155,7 @@ static int files_reflog_exists(struct ref_store *ref_store, const char *refname) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_exists" ); +files_downcast (ref_store,"reflog_exists" );struct strbuf sb =STRBUF_INIT ;struct stat st;int ret;
@@ -3195,7 +3170,7 @@ static int files_delete_reflog(struct ref_store *ref_store, const char *refname) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"delete_reflog" ); +files_downcast (ref_store,"delete_reflog" );struct strbuf sb =STRBUF_INIT ;int ret;
@@ -3250,7 +3225,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store, void *cb_data) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"for_each_reflog_ent_reverse" ); +files_downcast (ref_store,"for_each_reflog_ent_reverse" );struct strbuf sb =STRBUF_INIT ;FILE *logfp;long pos;
@@ -3358,7 +3333,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store, each_reflog_ent_fn fn, void *cb_data) { struct files_ref_store *refs = -files_downcast (ref_store,0 ,"for_each_reflog_ent" ); +files_downcast (ref_store,"for_each_reflog_ent" );FILE *logfp;struct strbuf sb =STRBUF_INIT ;int ret =0 ;
@@ -3446,7 +3421,7 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {static struct ref_iterator *files_reflog_iterator_begin (struct ref_store *ref_store) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_iterator_begin" ); +files_downcast (ref_store,"reflog_iterator_begin" );struct files_reflog_iterator *iter =xcalloc (1 ,sizeof (*iter));struct ref_iterator *ref_iterator = &iter->base;struct strbuf sb =STRBUF_INIT ;
@@ -3658,8 +3633,6 @@ static int lock_ref_for_update(struct files_ref_store *refs,int ret;struct ref_lock *lock; -files_assert_main_repository (refs,"lock_ref_for_update" ); -if ((update->flags &REF_HAVE_NEW ) &&is_null_sha1 (update->new_sha1)) update->flags |=REF_DELETING ;
@@ -3784,7 +3757,7 @@ static int files_transaction_commit(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"ref_transaction_commit" ); +files_downcast (ref_store,"ref_transaction_commit" );int ret =0 , i;struct string_list refs_to_delete =STRING_LIST_INIT_NODUP ;struct string_list_item *ref_to_delete;
@@ -3958,7 +3931,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"initial_ref_transaction_commit" ); +files_downcast (ref_store,"initial_ref_transaction_commit" );int ret =0 , i;struct string_list affected_refnames =STRING_LIST_INIT_NODUP ;
@@ -4080,7 +4053,7 @@ static int files_reflog_expire(struct ref_store *ref_store, void *policy_cb_data) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_expire" ); +files_downcast (ref_store,"reflog_expire" );static struct lock_file reflog_lock;struct expire_reflog_cb cb;struct ref_lock *lock;
@@ -4185,8 +4158,7 @@ static int files_reflog_expire(struct ref_store *ref_store,static int files_init_db (struct ref_store *ref_store,struct strbuf *err) { -struct files_ref_store *refs = -files_downcast (ref_store,0 ,"init_db" ); +struct files_ref_store *refs =files_downcast (ref_store,"init_db" );struct strbuf sb =STRBUF_INIT ;/*
Signature · 1 line
2.11.0.157.gd943d85
PATCH v3 16/16 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/files-backend.c | 2 +- refs/refs-internal.h | 12 ------------ 4 files changed, 20 insertions(+), 17 deletions(-)
refs.c +8 -4
@@ -1160,7 +1160,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)
@@ -1333,10 +1333,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)
@@ -1452,13 +1452,17 @@ struct ref_store *get_main_ref_store(void)return refs; } -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
@@ -554,5 +554,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/files-backend.c +1 -1
@@ -3117,7 +3117,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 ),"set_head_symref" ); +files_downcast (get_main_ref_store (),"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
refs/refs-internal.h +0 -12
@@ -634,18 +634,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
v4 cover Remove submodule from files-backend.c
In reply to Nguyễn Thái Ngọc Duyv4:
- is based on master+mh/ref-remove-empty-directory+mh/submodule-hash instead of mh/submodule-hash alone. It could merge with pu cleanly.
- 06/16 from v5, "correct is_per_worktree_ref", is removed. The "remove the use of git_path" patch is updated to handle it correctly even without that patch. More on this later.
- update "replace" typo in a commit message
The story behind the 06/16 removal is, in my simple view, there are per-repo and per-worktree refs. But refs.c and backends see them as three types: per-worktree, pseudo and normal/per-repo. Refs like ORIG_HEAD are _both_ per-worktree and pseudo.
06/16 reclassifies ORIG_HEAD from pseudo to per-worktree, which triggers a failure in t1400 because as pseudo refs, reflog will not be created while it will be for per-worktree. This new test is on master, not maint. I now fall back to treating both per-worktree and pseudo as per-worktree in files_path() only and keep classification unchanged.
Side note, my other two series seem to apply cleanly on top of this v3, so no resend.
Nguyễn Thái Ngọc Duy (15):
refs-internal.c: make files_log_ref_write() static
files-backend: convert git_path() to strbuf_git_path()
files-backend: add files_path()
files-backend: replace *git_path*() with files_path()
refs.c: share is_per_worktree_ref() to files-backend.c
files-backend: remove the use of git_path()
refs.c: introduce get_main_ref_store()
refs: rename lookup_ref_store() to lookup_submodule_ref_store() refs.c: flatten get_ref_store() a bit
refs.c: kill register_ref_store(), add register_submodule_ref_store() refs.c: make get_main_ref_store() public and use it
path.c: move some code out of strbuf_git_path_submodule()
refs: move submodule code out of files-backend.c
files-backend: remove submodule_allowed from files_downcast()
refs: rename get_ref_store() to get_submodule_ref_store() and make it public
path.c | 34 +---- refs.c | 144 +++++++++--------- refs.h | 13 ++ refs/files-backend.c | 406 ++++++++++++++++++++++++++++++++------------------- refs/refs-internal.h | 28 ++-- submodule.c | 31 ++++ submodule.h | 1 + 7 files changed, 396 insertions(+), 261 deletions(-)
Signature · 1 line
2.11.0.157.gd943d85
PATCH v4 1/15 refs-internal.c: make files_log_ref_write() static
Created 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
PATCH v4 2/15 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 | 146 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 31 deletions(-)
refs/files-backend.c +115 -31
@@ -2151,6 +2151,8 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)static int timeout_configured =0 ;static int timeout_value =1000 ;struct packed_ref_cache *packed_ref_cache; +struct strbuf sb =STRBUF_INIT ; +int ret;files_assert_main_repository (refs,"lock_packed_refs" );
@@ -2159,10 +2161,13 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) timeout_configured =1 ; } -if (hold_lock_file_for_update_timeout ( - &packlock,git_path ("packed-refs" ), - flags, timeout_value) <0 ) +strbuf_git_path (&sb,"packed-refs" ); + ret =hold_lock_file_for_update_timeout (&packlock, sb.buf, + flags, timeout_value); +strbuf_release (&sb); +if (ret <0 )return -1 ; +/* * Get the current packed-refs while holding the lock. If the * packed-refs file has been modified since we last read it,
@@ -2312,6 +2317,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;
@@ -2333,14 +2339,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 */
@@ -2426,7 +2437,11 @@ 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); +struct strbuf sb =STRBUF_INIT ; + +strbuf_git_path (&sb,"packed-refs" ); +unable_to_lock_message (sb.buf, errno, err); +strbuf_release (&sb);return -1 ; } packed =get_packed_refs (refs);
@@ -2504,9 +2519,11 @@ static int files_delete_refs(struct ref_store *ref_store,static int rename_tmp_log_callback (const char *path,void *cb) { +struct strbuf sb =STRBUF_INIT ;int *true_errno = cb; -if (rename (git_path (TMP_RENAMED_LOG ), path)) { +strbuf_git_path (&sb,TMP_RENAMED_LOG ); +if (rename (sb.buf, path)) {/* * rename(a, b) when b is an existing directory ought * to result in ISDIR, but Solaris 5.8 gives ENOTDIR.
@@ -2515,30 +2532,40 @@ static int rename_tmp_log_callback(const char *path, void *cb)* that it knows to retry. */ *true_errno = errno; +strbuf_release (&sb);if (errno ==ENOTDIR ) errno =EISDIR ;return -1 ; }else { +strbuf_release (&sb);return 0 ; } }static int rename_tmp_log (const char *newrefname) { -char *path =git_pathdup ("logs/%s" , newrefname); +struct strbuf sb =STRBUF_INIT ; +const char *path;int ret, true_errno; +strbuf_git_path (&sb,"logs/%s" , newrefname); + path = sb.buf; ret =raceproof_create_file (path, rename_tmp_log_callback, &true_errno);if (ret) {if (errno ==EISDIR )error ("directory not empty: %s" , path); -else +else { +struct strbuf tmp_renamed =STRBUF_INIT ; + +strbuf_git_path (&tmp_renamed,TMP_RENAMED_LOG );error ("unable to move logfile %s to %s: %s" , -git_path (TMP_RENAMED_LOG ), path, + tmp_renamed.buf, path,strerror (true_errno)); +strbuf_release (&tmp_renamed); + } } -free (path); +strbuf_release (&sb);return ret; }
@@ -2579,9 +2606,15 @@ 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 ; +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); + log = !lstat (sb_oldref.buf, &loginfo); +strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))return error ("reflog for %s is a symlink" , oldrefname);
@@ -2595,7 +2628,12 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log); +if (ret)return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno));
@@ -2674,13 +2712,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))) +strbuf_git_path (&sb_newref,"logs/%s" , newrefname); +strbuf_git_path (&sb_oldref,"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)); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG );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)); +strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log);return 1 ; }
@@ -2854,18 +2898,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 ;
@@ -3085,22 +3135,32 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static 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)
@@ -3155,7 +3215,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 ;
@@ -3261,7 +3323,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 ;
@@ -3343,12 +3407,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; }
@@ -3686,6 +3753,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);
@@ -3807,7 +3875,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; }
@@ -3827,9 +3897,13 @@ 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))) +struct strbuf sb =STRBUF_INIT ; + +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 ); +strbuf_release (&sb); }clear_loose_ref_cache (refs);
@@ -4101,18 +4175,28 @@ 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_reset (&sb);if (get_shared_repository ()) { -adjust_shared_perm (git_path ("refs/heads" )); -adjust_shared_perm (git_path ("refs/tags" )); +strbuf_git_path (&sb,"refs/heads" ); +adjust_shared_perm (sb.buf); +strbuf_reset (&sb); +strbuf_git_path (&sb,"refs/tags" ); +adjust_shared_perm (sb.buf); } +strbuf_release (&sb);return 0 ; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v4 3/15 files-backend: add files_path()
In reply to Nguyễn Thái Ngọc DuyThis will be the replacement for both git_path() and git_path_submodule() in this file. The idea is backend takes a git path and use that, oblivious of submodule, linked worktrees and such.
This is the middle step towards that. Eventually the "submodule" field in 'struct files_ref_store' should be replaced by "gitdir". And a compound ref_store is created to combine two files backends together, one represents the shared refs in $GIT_COMMON_DIR, one per-worktree. At that point, files_path() becomes a wrapper of strbuf_vaddf().
--- refs/files-backend.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
refs/files-backend.c +18 -0
@@ -930,6 +930,24 @@ struct files_ref_store {/* Lock used for the main packed-refs file: */ static struct lock_file packlock; +__attribute__((format (printf,3 ,4 ))) +static void files_path (struct files_ref_store *refs,struct strbuf *sb, +const char *fmt, ...) +{ +struct strbuf tmp =STRBUF_INIT ; +va_list vap; + +va_start (vap, fmt); +strbuf_vaddf (&tmp, fmt, vap); +va_end (vap); +if (refs->submodule) +strbuf_git_path_submodule (sb, refs->submodule, +"%s" , tmp.buf); +else +strbuf_git_path (sb,"%s" , tmp.buf); +strbuf_release (&tmp); +} +/* * Increment the reference count of *packed_refs. */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v4 4/15 files-backend: replace *git_path*() with files_path()
In reply to Nguyễn Thái Ngọc DuyThis centralizes all path rewriting of files-backend.c in one place so we have easier time removing the path rewriting later. There could be some hidden indirect git_path() though, I didn't audit the code to the bottom.
Side note: set_worktree_head_symref() is a bad boy and should not be in files-backend.c (probably should not exist in the first place). But we'll leave it there until we have better multi-worktree support in refs before we update it.
--- refs/files-backend.c | 208 +++++++++++++++++++++++++++------------------------ 1 file changed, 111 insertions(+), 97 deletions(-)
refs/files-backend.c +111 -97
@@ -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);
@@ -1178,12 +1179,10 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)static struct packed_ref_cache *get_packed_ref_cache (struct files_ref_store *refs) {char *packed_refs_file; +struct strbuf sb =STRBUF_INIT ; -if (refs->submodule) - packed_refs_file =git_pathdup_submodule (refs->submodule, -"packed-refs" ); -else - packed_refs_file =git_pathdup ("packed-refs" ); +files_path (refs, &sb,"packed-refs" ); + packed_refs_file =strbuf_detach (&sb,NULL );if (refs->packed && !stat_validity_check (&refs->packed->validity, packed_refs_file))
@@ -1249,10 +1248,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)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_path (refs, &path,"%s" , dirname); path_baselen = path.len;if (err) {
@@ -1394,10 +1390,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_path (refs, &sb_path,"%s" , refname); path = sb_path.buf;
@@ -1585,7 +1578,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_path (refs, &ref_file,"%s" , refname); retry:switch (safe_create_leading_directories (ref_file.buf)) {
@@ -2057,7 +2050,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_path (refs, &ref_file,"%s" , refname); resolved = !!resolve_ref_unsafe (refname, resolve_flags, lock->old_oid.hash, type);if (!resolved && errno ==EISDIR ) {
@@ -2179,7 +2172,7 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags) timeout_configured =1 ; } -strbuf_git_path (&sb,"packed-refs" ); +files_path (refs, &sb,"packed-refs" ); ret =hold_lock_file_for_update_timeout (&packlock, sb.buf, flags, timeout_value);strbuf_release (&sb);
@@ -2332,7 +2325,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 ;
@@ -2359,12 +2354,12 @@ static void try_remove_empty_parents(const char *refname, unsigned int flags)strbuf_setlen (&buf, q - buf.buf);strbuf_reset (&sb); -strbuf_git_path (&sb,"%s" , buf.buf); +files_path (refs, &sb,"%s" , buf.buf);if ((flags &REMOVE_EMPTY_PARENTS_REF ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REF ;strbuf_reset (&sb); -strbuf_git_path (&sb,"logs/%s" , buf.buf); +files_path (refs, &sb,"logs/%s" , buf.buf);if ((flags &REMOVE_EMPTY_PARENTS_REFLOG ) &&rmdir (sb.buf)) flags &= ~REMOVE_EMPTY_PARENTS_REFLOG ; }
@@ -2373,7 +2368,7 @@ static void try_remove_empty_parents(const char *refname, unsigned int flags) }/* 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 ;
@@ -2395,10 +2390,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; } }
@@ -2421,7 +2416,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 ; }
@@ -2457,7 +2452,7 @@ static int repack_without_refs(struct files_ref_store *refs,if (lock_packed_refs (refs,0 )) {struct strbuf sb =STRBUF_INIT ; -strbuf_git_path (&sb,"packed-refs" ); +files_path (refs, &sb,"packed-refs" );unable_to_lock_message (sb.buf, errno, err);strbuf_release (&sb);return -1 ;
@@ -2535,12 +2530,17 @@ 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_tmp_log_cb { +struct files_ref_store *refs; +int true_errno; +}; + +static int rename_tmp_log_callback (const char *path,void *cb_) {struct strbuf sb =STRBUF_INIT ; -int *true_errno = cb; +struct rename_tmp_log_cb *cb = cb_; -strbuf_git_path (&sb,TMP_RENAMED_LOG ); +files_path (cb->refs, &sb,TMP_RENAMED_LOG );if (rename (sb.buf, path)) {/* * rename(a, b) when b is an existing directory ought
@@ -2549,7 +2549,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;strbuf_release (&sb);if (errno ==ENOTDIR ) errno =EISDIR ;
@@ -2560,25 +2560,27 @@ static int rename_tmp_log_callback(const char *path, void *cb) } } -static int rename_tmp_log (const char *newrefname) +static int rename_tmp_log (struct files_ref_store *refs,const char *newrefname) {struct strbuf sb =STRBUF_INIT ; +struct rename_tmp_log_cb cb;const char *path; -int ret, true_errno; +int ret; -strbuf_git_path (&sb,"logs/%s" , newrefname); +files_path (refs, &sb,"logs/%s" , newrefname); path = sb.buf; - ret =raceproof_create_file (path, rename_tmp_log_callback, &true_errno); + cb.refs = refs; + ret =raceproof_create_file (path, rename_tmp_log_callback, &cb);if (ret) {if (errno ==EISDIR )error ("directory not empty: %s" , path);else {struct strbuf tmp_renamed =STRBUF_INIT ; -strbuf_git_path (&tmp_renamed,TMP_RENAMED_LOG ); +files_path (refs, &tmp_renamed,TMP_RENAMED_LOG );error ("unable to move logfile %s to %s: %s" , tmp_renamed.buf, path, -strerror (true_errno)); +strerror (cb.true_errno));strbuf_release (&tmp_renamed); } }
@@ -2630,7 +2632,7 @@ 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); +files_path (refs, &sb_oldref,"logs/%s" , oldrefname); log = !lstat (sb_oldref.buf, &loginfo);strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))
@@ -2646,8 +2648,8 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &sb_oldref,"logs/%s" , oldrefname); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf);strbuf_release (&sb_oldref);strbuf_release (&tmp_renamed_log);
@@ -2674,7 +2676,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_path (refs, &path,"%s" , newrefname); result =remove_empty_directories (&path);strbuf_release (&path);
@@ -2688,7 +2690,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;
@@ -2730,12 +2732,12 @@ static int files_rename_ref(struct ref_store *ref_store, log_all_ref_updates = flag; rollbacklog: -strbuf_git_path (&sb_newref,"logs/%s" , newrefname); -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +files_path (refs, &sb_newref,"logs/%s" , newrefname); +files_path (refs, &sb_oldref,"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)); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +files_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG );if (!logmoved && log &&rename (tmp_renamed_log.buf, sb_oldref.buf)) error("unable to restore logfile %s from "TMP_RENAMED_LOG": %s",
@@ -2803,10 +2805,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 sb =STRBUF_INIT ; +char *logfile; + +files_path (refs, &sb,"logs/%s" , refname); + logfile =strbuf_detach (&sb,NULL );if (force_create ||should_autocreate_reflog (refname)) {if (raceproof_create_file (logfile, open_or_create_logfile, logfd)) {
@@ -2856,12 +2863,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 )
@@ -2896,7 +2902,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) {
@@ -2905,7 +2912,7 @@ 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)
@@ -2919,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_path (refs, &sb,"logs/%s" , refname);strbuf_addf (err,"unable to append to '%s': %s" , sb.buf,strerror (save_errno));strbuf_release (&sb);
@@ -2930,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_path (refs, &sb,"logs/%s" , refname);strbuf_addf (err,"unable to append to '%s': %s" , sb.buf,strerror (save_errno));strbuf_release (&sb);
@@ -2991,8 +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, - logmsg,0 , err)) { +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" , lock->ref_name, old_msg);
@@ -3023,8 +3030,8 @@ 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); }
@@ -3056,24 +3063,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, +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 ; }
@@ -3081,7 +3090,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);
@@ -3110,13 +3119,19 @@ 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) { +/* +* 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 ;
@@ -3143,7 +3158,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target) lock->lk = &head_lock; lock->ref_name =xstrdup (head_rel); - ret =create_symref_locked (lock, head_rel, target,NULL ); + ret =create_symref_locked (refs, lock, head_rel, target,NULL );unlock_ref (lock);/* will free lock */ strbuf_release (&head_path);
@@ -3153,14 +3168,13 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static int files_reflog_exists (struct ref_store *ref_store,const char *refname) { +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"reflog_exists" );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_path (refs, &sb,"logs/%s" , refname); ret = !lstat (sb.buf, &st) &&S_ISREG (st.st_mode);strbuf_release (&sb);return ret;
@@ -3169,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_path (refs, &sb,"logs/%s" , refname); ret =remove_path (sb.buf);strbuf_release (&sb);return ret;
@@ -3225,15 +3238,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_path (refs, &sb,"logs/%s" , refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3334,14 +3346,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_path (refs, &sb,"logs/%s" , refname); logfp =fopen (sb.buf,"r" );strbuf_release (&sb);if (!logfp)
@@ -3423,15 +3434,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_path (refs, &sb,"logs" ); iter->dir_iterator =dir_iterator_begin (sb.buf);strbuf_release (&sb);return ref_iterator;
@@ -3856,7 +3866,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,
@@ -3894,7 +3905,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_path (refs, &sb,"%s" , lock->ref_name);if (unlink_or_msg (sb.buf, err)) { ret =TRANSACTION_GENERIC_ERROR ; goto cleanup;
@@ -3917,9 +3928,10 @@ static int files_transaction_commit(struct ref_store *ref_store,for_each_string_list_item (ref_to_delete, &refs_to_delete) {struct strbuf sb =STRBUF_INIT ; -strbuf_git_path (&sb,"logs/%s" , ref_to_delete->string); +files_path (refs, &sb,"logs/%s" , 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 );strbuf_release (&sb); }
@@ -3943,7 +3955,8 @@ 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 ); } }
@@ -4098,6 +4111,7 @@ static int files_reflog_expire(struct ref_store *ref_store,int status =0 ;int type;struct strbuf err =STRBUF_INIT ; +struct strbuf sb =STRBUF_INIT ;memset (&cb,0 ,sizeof (cb)); cb.flags = flags;
@@ -4122,7 +4136,8 @@ static int files_reflog_expire(struct ref_store *ref_store,return 0 ; } - log_file =git_pathdup ("logs/%s" , refname); +files_path (refs, &sb,"logs/%s" , refname); + log_file =strbuf_detach (&sb,NULL );if (!(flags &EXPIRE_REFLOGS_DRY_RUN )) {/* * Even though holding $GIT_DIR/logs/$reflog.lock has
@@ -4193,25 +4208,24 @@ 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_path (refs, &sb,"refs/heads" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_path (refs, &sb,"refs/tags" );safe_create_dir (sb.buf,1 );strbuf_reset (&sb);if (get_shared_repository ()) { -strbuf_git_path (&sb,"refs/heads" ); +files_path (refs, &sb,"refs/heads" );adjust_shared_perm (sb.buf);strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_path (refs, &sb,"refs/tags" );adjust_shared_perm (sb.buf); }strbuf_release (&sb);
Signature · 1 line
2.11.0.157.gd943d85
PATCH v4 5/15 refs.c: share is_per_worktree_ref() to files-backend.c
In reply to Nguyễn Thái Ngọc Duy--- refs.c | 6 ------ refs/refs-internal.h | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-)
refs.c +0 -6
@@ -489,12 +489,6 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)return logs_found; } -static int is_per_worktree_ref (const char *refname) -{ -return !strcmp (refname,"HEAD" ) || -starts_with (refname,"refs/bisect/" ); -} -static int is_pseudoref_syntax (const char *refname) {const char *c;
refs/refs-internal.h +6 -0
@@ -657,4 +657,10 @@ const char *resolve_ref_recursively(struct ref_store *refs,int resolve_flags, unsigned char *sha1, int *flags); +static inline int is_per_worktree_ref (const char *refname) +{ +return !strcmp (refname,"HEAD" ) || +starts_with (refname,"refs/bisect/" ); +} +#endif /* REFS_REFS_INTERNAL_H */
Signature · 1 line
2.11.0.157.gd943d85
PATCH v4 6/15 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 | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-)
refs/files-backend.c +33 -4
@@ -924,6 +924,9 @@ struct files_ref_store {*/ const char *submodule; +struct strbuf gitdir; +struct strbuf gitcommondir; +struct ref_entry *loose;struct packed_ref_cache *packed; };
@@ -937,15 +940,33 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb, {struct strbuf tmp =STRBUF_INIT ;va_list vap; +const char *ref;va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);va_end (vap); -if (refs->submodule) +if (refs->submodule) {strbuf_git_path_submodule (sb, refs->submodule,"%s" , tmp.buf); -else -strbuf_git_path (sb,"%s" , tmp.buf); + }else if (!strcmp (tmp.buf,"packed-refs" ) || + !strcmp (tmp.buf,"logs" )) {/* non refname path */ +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf); + }else if (skip_prefix (tmp.buf,"logs/" , &ref)) {/* reflog */ +if (is_per_worktree_ref (ref)) +strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf); +else +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf); + }else {/* refname */ +switch (ref_type (tmp.buf)) { +case REF_TYPE_PER_WORKTREE : +case REF_TYPE_PSEUDOREF : +strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf); +break ; +case REF_TYPE_NORMAL : +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf); +break ; + } + }strbuf_release (&tmp); }
@@ -1004,7 +1025,15 @@ 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); +strbuf_init (&refs->gitdir,0 ); +strbuf_init (&refs->gitcommondir,0 ); + +if (submodule) { + refs->submodule =xstrdup (submodule); + }else { +strbuf_addstr (&refs->gitdir,get_git_dir ()); +strbuf_addstr (&refs->gitcommondir,get_git_common_dir ()); + }return ref_store; }
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v4 06/15] files-backend: remove the use of git_path()
Quoted 18 lines · Nguyễn Thái Ngọc Duy
Given $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.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-)refs/files-backend.c +0
-0
refs/files-backend.c struct files_ref_store { · line 928
Quoted 5 lines
refs/files-backend.c +2
-0@@ -924,6 +924,9 @@ struct files_ref_store {*/ const char *submodule; +struct strbuf gitdir; +struct strbuf gitcommondir;
Is there a reason for these to be strbufs rather than const char *? (One reason would be if you planned to use the len field, but I don't think you do so.)
Quoted 13 lines
refs/files-backend.c +2
-1@@ -937,15 +940,33 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb, {struct strbuf tmp =STRBUF_INIT ;va_list vap; +const char *ref;va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);va_end (vap); -if (refs->submodule) +if (refs->submodule) {strbuf_git_path_submodule (sb, refs->submodule,"%s" , tmp.buf);
refs/files-backend.c static void files_path(struct files_ref_store *refs, struct strbuf *sb, · line 958
Quoted 10 lines
refs/files-backend.c +8
-2-else -strbuf_git_path (sb,"%s" , tmp.buf); + }else if (!strcmp (tmp.buf,"packed-refs" ) || + !strcmp (tmp.buf,"logs" )) {/* non refname path */ +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf); + }else if (skip_prefix (tmp.buf,"logs/" , &ref)) {/* reflog */ +if (is_per_worktree_ref (ref)) +strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf); +else +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf);
This code would also be simpler if there were separate functions for packed-refs, loose references, and reflogs.
Quoted 1 line
[...]
Michael
Re: [PATCH v4 06/15] files-backend: remove the use of git_path()
Quoted 22 lines · Michael Haggerty
Quoted 21 lines · Nguyễn Thái Ngọc Duy
Given $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.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-)refs/files-backend.c +0
-0@@ -924,6 +924,9 @@ struct files_ref_store {*/ const char *submodule;
Quoted 6 lines
refs/files-backend.c struct files_ref_store { · line 928
Quoted 2 lines
refs/files-backend.c +2
-0+struct strbuf gitdir; +struct strbuf gitcommondir;Is there a reason for these to be
strbufs rather thanconst char *? (One reason would be if you planned to use thelenfield, but I don't think you do so.)
Nope. I just didn't think about char *. It may have to lose "const" though because in submodule case we may need a new allocation.
Quoted 19 lines
Quoted 19 lines
refs/files-backend.c +5
-3@@ -937,15 +940,33 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb, {struct strbuf tmp =STRBUF_INIT ;va_list vap; +const char *ref;va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);va_end (vap); -if (refs->submodule) +if (refs->submodule) {strbuf_git_path_submodule (sb, refs->submodule,"%s" , tmp.buf); -else -strbuf_git_path (sb,"%s" , tmp.buf); + }else if (!strcmp (tmp.buf,"packed-refs" ) || + !strcmp (tmp.buf,"logs" )) {/* non refname path */ +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf);
Quoted 8 lines
refs/files-backend.c static void files_path(struct files_ref_store *refs, struct strbuf *sb, · line 958
Quoted 5 lines
refs/files-backend.c +5
-0+ }else if (skip_prefix (tmp.buf,"logs/" , &ref)) {/* reflog */ +if (is_per_worktree_ref (ref)) +strbuf_addf (sb,"%s/%s" , refs->gitdir.buf, tmp.buf); +else +strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf);This code would also be simpler if there were separate functions for packed-refs, loose references, and reflogs.
And maybe keep the path to packed-refs, the base path up to "logs" in struct files_ref_store too (they will be calculated at ref store init)? That way the files_packed_refs_path() does no calculation. files_reflog_path() and files_ref_path() will just do string concatenation, no fancy addf.
Signature · 1 line
Duy
PATCH v4 7/15 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
@@ -1450,15 +1450,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
PATCH v4 8/15 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
@@ -1389,17 +1389,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 ;
@@ -1468,7 +1464,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 ;
@@ -1479,7 +1475,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 v4 9/15 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 | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
refs.c +9 -10
@@ -1459,22 +1459,21 @@ 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;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); +if (is_nonbare_repository_dir (&submodule_sb)) + refs =ref_store_init (submodule); +strbuf_release (&submodule_sb);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v4 10/15 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 | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-)
refs.c +19 -17
@@ -1407,25 +1407,19 @@ 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. +* for submodule. 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) +static void register_submodule_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 (!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); - } +if (hashmap_put (&submodule_ref_stores, +alloc_submodule_hash_entry (submodule, refs))) +die ("BUG: ref_store for submodule '%s' initialized twice" , + submodule); }/*
@@ -1442,7 +1436,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; }
@@ -1454,6 +1447,12 @@ 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; }
@@ -1474,6 +1473,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) +register_submodule_ref_store (refs, submodule);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v4 11/15 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 | 2 ++ 2 files changed, 20 insertions(+), 18 deletions(-)
refs.c +18 -18
@@ -1308,7 +1308,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); }
@@ -1316,7 +1316,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); }
@@ -1439,7 +1439,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;
@@ -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 +2 -0
@@ -555,4 +555,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 */
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v4 11/15] 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.
I see where you're going with this, but as of the end of this patch series, there is still nothing that a caller outside of the refs module can do with a struct ref_store *. This means that it would be enough to put this declaration (and that of get_submodule_ref_store(), added in a later patch) in refs/refs-internal.h for now.
If you want to move the declarations straight to refs.h now to avoid code churn in some later patch series, then please mention that fact in the commit message.
Michael
PATCH v4 12/15 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
PATCH v4 13/15 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().
The new code in init_submodule_ref_store() is basically a copy of strbuf_git_path_submodule().
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() follows shortly. It's separate to keep noises from this patch.
--- refs.c | 18 +++++++++++++----- refs/files-backend.c | 24 +++++++----------------- refs/refs-internal.h | 6 +++--- 3 files changed, 23 insertions(+), 25 deletions(-)
refs.c +13 -5
@@ -9,6 +9,7 @@#include "refs/refs-internal.h" #include "object.h" #include "tag.h" +#include "submodule.h" /* * List of all available backends
@@ -1424,9 +1425,9 @@ static void register_submodule_ref_store(struct ref_store *refs,/* * Create, record, and return a ref_store instance for the specified -* submodule (or the main repository if submodule is NULL). +* gitdir (or the main repository if gitdir is NULL). */ -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);
@@ -1435,7 +1436,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; }
@@ -1460,6 +1461,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 ();
@@ -1470,8 +1472,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 +7 -17
@@ -917,13 +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; -struct strbuf gitdir;struct strbuf gitcommondir;
@@ -945,11 +938,8 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb,va_start (vap, fmt);strbuf_vaddf (&tmp, fmt, vap);va_end (vap); -if (refs->submodule) { -strbuf_git_path_submodule (sb, refs->submodule, -"%s" , tmp.buf); - }else if (!strcmp (tmp.buf,"packed-refs" ) || - !strcmp (tmp.buf,"logs" )) {/* non refname path */ +if (!strcmp (tmp.buf,"packed-refs" ) || !strcmp (tmp.buf,"logs" )) { +/* non refname path */ strbuf_addf (sb,"%s/%s" , refs->gitcommondir.buf, tmp.buf); }else if (skip_prefix (tmp.buf,"logs/" , &ref)) {/* reflog */ if (is_per_worktree_ref (ref))
@@ -1018,7 +1008,7 @@ 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;
@@ -1028,8 +1018,9 @@ static struct ref_store *files_ref_store_create(const char *submodule)strbuf_init (&refs->gitdir,0 );strbuf_init (&refs->gitcommondir,0 ); -if (submodule) { - refs->submodule =xstrdup (submodule); +if (gitdir) { +strbuf_addstr (&refs->gitdir, gitdir); +get_common_dir_noenv (&refs->gitcommondir, gitdir); }else {strbuf_addstr (&refs->gitdir,get_git_dir ());strbuf_addstr (&refs->gitcommondir,get_git_common_dir ());
@@ -1045,8 +1036,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 */ }/*
refs/refs-internal.h +3 -3
@@ -482,12 +482,12 @@ 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 +* Initialize the ref_store for the specified gitdir, or for the +* current repository if gitdir == NULL. These functions should call * base_ref_store_init() to initialize the shared part of the * ref_store and to record the ref_store for later lookup. */ -typedef struct ref_store *ref_store_init_fn (const char *submodule); +typedef 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 v4 14/15 files-backend: remove submodule_allowed from files_downcast()
In reply to Nguyễn Thái Ngọc DuySince submodule or not is irrelevant to files-backend after the last patch, remove the parameter from files_downcast() and kill files_assert_main_repository().
PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
--- refs/files-backend.c | 70 ++++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 49 deletions(-)
refs/files-backend.c +21 -49
@@ -1030,24 +1030,13 @@ 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. -*/ -static void files_assert_main_repository (struct files_ref_store *refs, -const char *caller) -{ -/* This function is to be deleted in the next patch */ -} - -/* * 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. */ -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, +const char *caller) {struct files_ref_store *refs;
@@ -1057,9 +1046,6 @@ static struct files_ref_store *files_downcast( refs = (struct files_ref_store *)ref_store; -if (!submodule_allowed) -files_assert_main_repository (refs, caller); -return refs; }
@@ -1395,7 +1381,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, struct strbuf *referent, unsigned int *type) { struct files_ref_store *refs = -files_downcast (ref_store,1 ,"read_raw_ref" ); +files_downcast (ref_store,"read_raw_ref" );struct strbuf sb_contents =STRBUF_INIT ;struct strbuf sb_path =STRBUF_INIT ;const char *path;
@@ -1588,7 +1574,6 @@ static int lock_raw_ref(struct files_ref_store *refs,int ret =TRANSACTION_GENERIC_ERROR ;assert (err); -files_assert_main_repository (refs,"lock_raw_ref" ); *type =0 ;
@@ -1812,7 +1797,7 @@ static enum peel_status peel_entry(struct ref_entry *entry, int repeel)static int files_peel_ref (struct ref_store *ref_store,const char *refname,unsigned char *sha1) { -struct files_ref_store *refs =files_downcast (ref_store,0 ,"peel_ref" ); +struct files_ref_store *refs =files_downcast (ref_store,"peel_ref" );int flag;unsigned char base[20 ];
@@ -1921,7 +1906,7 @@ static struct ref_iterator *files_ref_iterator_begin( const char *prefix, unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,1 ,"ref_iterator_begin" ); +files_downcast (ref_store,"ref_iterator_begin" );struct ref_dir *loose_dir, *packed_dir;struct ref_iterator *loose_iter, *packed_iter;struct files_ref_iterator *iter;
@@ -2059,7 +2044,6 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,int resolve_flags =RESOLVE_REF_NO_RECURSE ;int resolved; -files_assert_main_repository (refs,"lock_ref_sha1_basic" );assert (err); lock =xcalloc (1 ,sizeof (struct ref_lock ));
@@ -2184,8 +2168,6 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)struct strbuf sb =STRBUF_INIT ;int ret; -files_assert_main_repository (refs,"lock_packed_refs" ); -if (!timeout_configured) {git_config_get_int ("core.packedrefstimeout" , &timeout_value); timeout_configured =1 ;
@@ -2225,8 +2207,6 @@ static int commit_packed_refs(struct files_ref_store *refs)int save_errno =0 ;FILE *out; -files_assert_main_repository (refs,"commit_packed_refs" ); -if (!packed_ref_cache->lock)die ("internal error: packed-refs not locked" );
@@ -2258,8 +2238,6 @@ static void rollback_packed_refs(struct files_ref_store *refs)struct packed_ref_cache *packed_ref_cache =get_packed_ref_cache (refs); -files_assert_main_repository (refs,"rollback_packed_refs" ); -if (!packed_ref_cache->lock)die ("internal error: packed-refs not locked" );rollback_lock_file (packed_ref_cache->lock);
@@ -2420,7 +2398,7 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune *r)static int files_pack_refs (struct ref_store *ref_store,unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"pack_refs" ); +files_downcast (ref_store,"pack_refs" );struct pack_refs_cb_data cbdata;memset (&cbdata,0 ,sizeof (cbdata));
@@ -2453,7 +2431,6 @@ static int repack_without_refs(struct files_ref_store *refs,struct string_list_item *refname;int ret, needs_repacking =0 , removed =0 ; -files_assert_main_repository (refs,"repack_without_refs" );assert (err);/* Look for a packed ref */
@@ -2503,7 +2480,7 @@ static int files_delete_refs(struct ref_store *ref_store, struct string_list *refnames, unsigned int flags) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"delete_refs" ); +files_downcast (ref_store,"delete_refs" );struct strbuf err =STRBUF_INIT ;int i, result =0 ;
@@ -2615,7 +2592,7 @@ static int files_verify_refname_available(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,1 ,"verify_refname_available" ); +files_downcast (ref_store,"verify_refname_available" );struct ref_dir *packed_refs =get_packed_refs (refs);struct ref_dir *loose_refs =get_loose_refs (refs);
@@ -2640,7 +2617,7 @@ static int files_rename_ref(struct ref_store *ref_store, const char *logmsg) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"rename_ref" ); +files_downcast (ref_store,"rename_ref" );unsigned char sha1[20 ], orig_sha1[20 ];int flag =0 , logmoved =0 ;struct ref_lock *lock;
@@ -2883,7 +2860,7 @@ static int files_create_reflog(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"create_reflog" ); +files_downcast (ref_store,"create_reflog" );int fd;if (log_ref_setup (refs, refname, force_create, &fd, err))
@@ -3014,8 +2991,6 @@ static int commit_ref_update(struct files_ref_store *refs, const unsigned char *sha1, const char *logmsg, struct strbuf *err) { - files_assert_main_repository(refs, "commit_ref_update"); -clear_loose_ref_cache (refs );if (files_log_ref_write (refs, lock->ref_name, lock->old_oid.hash, sha1, logmsg,0 , err)) {
@@ -3124,7 +3099,7 @@ static int files_create_symref(struct ref_store *ref_store, const char *logmsg) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"create_symref" ); +files_downcast (ref_store,"create_symref" );struct strbuf err =STRBUF_INIT ;struct ref_lock *lock;int ret;
@@ -3150,7 +3125,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_ref_store (NULL ),"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
@@ -3188,7 +3163,7 @@ static int files_reflog_exists(struct ref_store *ref_store, const char *refname) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_exists" ); +files_downcast (ref_store,"reflog_exists" );struct strbuf sb =STRBUF_INIT ;struct stat st;int ret;
@@ -3203,7 +3178,7 @@ static int files_delete_reflog(struct ref_store *ref_store, const char *refname) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"delete_reflog" ); +files_downcast (ref_store,"delete_reflog" );struct strbuf sb =STRBUF_INIT ;int ret;
@@ -3258,7 +3233,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store, void *cb_data) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"for_each_reflog_ent_reverse" ); +files_downcast (ref_store,"for_each_reflog_ent_reverse" );struct strbuf sb =STRBUF_INIT ;FILE *logfp;long pos;
@@ -3366,7 +3341,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store, each_reflog_ent_fn fn, void *cb_data) { struct files_ref_store *refs = -files_downcast (ref_store,0 ,"for_each_reflog_ent" ); +files_downcast (ref_store,"for_each_reflog_ent" );FILE *logfp;struct strbuf sb =STRBUF_INIT ;int ret =0 ;
@@ -3454,7 +3429,7 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {static struct ref_iterator *files_reflog_iterator_begin (struct ref_store *ref_store) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_iterator_begin" ); +files_downcast (ref_store,"reflog_iterator_begin" );struct files_reflog_iterator *iter =xcalloc (1 ,sizeof (*iter));struct ref_iterator *ref_iterator = &iter->base;struct strbuf sb =STRBUF_INIT ;
@@ -3666,8 +3641,6 @@ static int lock_ref_for_update(struct files_ref_store *refs,int ret;struct ref_lock *lock; -files_assert_main_repository (refs,"lock_ref_for_update" ); -if ((update->flags &REF_HAVE_NEW ) &&is_null_sha1 (update->new_sha1)) update->flags |=REF_DELETING ;
@@ -3792,7 +3765,7 @@ static int files_transaction_commit(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"ref_transaction_commit" ); +files_downcast (ref_store,"ref_transaction_commit" );int ret =0 , i;struct string_list refs_to_delete =STRING_LIST_INIT_NODUP ;struct string_list_item *ref_to_delete;
@@ -4000,7 +3973,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store, struct strbuf *err) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"initial_ref_transaction_commit" ); +files_downcast (ref_store,"initial_ref_transaction_commit" );int ret =0 , i;struct string_list affected_refnames =STRING_LIST_INIT_NODUP ;
@@ -4122,7 +4095,7 @@ static int files_reflog_expire(struct ref_store *ref_store, void *policy_cb_data) {struct files_ref_store *refs = -files_downcast (ref_store,0 ,"reflog_expire" ); +files_downcast (ref_store,"reflog_expire" );static struct lock_file reflog_lock;struct expire_reflog_cb cb;struct ref_lock *lock;
@@ -4227,8 +4200,7 @@ static int files_reflog_expire(struct ref_store *ref_store,static int files_init_db (struct ref_store *ref_store,struct strbuf *err) { -struct files_ref_store *refs = -files_downcast (ref_store,0 ,"init_db" ); +struct files_ref_store *refs =files_downcast (ref_store,"init_db" );struct strbuf sb =STRBUF_INIT ;/*
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v4 14/15] files-backend: remove submodule_allowed from files_downcast()
Quoted 6 lines · Nguyễn Thái Ngọc Duy
Since submodule or not is irrelevant to files-backend after the last patch, remove the parameter from
files_downcast()and killfiles_assert_main_repository().PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
I think you are jumping the gun here.
Even after your changes, there is still a significant difference between the main repository and submodules: we have access to the object database for the main repository, but not for submodules.
So, for example, the following don't work for submodules:
* parse_object() is used to ensure that references are only pointed at valid objects, and that branches are only pointed at commit objects.
* peel_object() is used to write the peeled version of references in packed-refs, and to peel references while they are being iterated over. Since this doesn't work, I think you can't write packed-refs in a submodule.
These limitations, I think, imply that submodule references have to be treated as read-only.
When I was working on a patch series similar to yours, I introduced a boolean "main_repository" flag in struct ref_store, and use that member to implement files_assert_main_repository(). That way files_ref_store::submodule can still be removed, which is the more important goal from a design standpoint.
Michael
Re: [PATCH v4 14/15] files-backend: remove submodule_allowed from files_downcast()
Quoted 19 lines · Michael Haggerty
Quoted 6 lines · Nguyễn Thái Ngọc Duy
Since submodule or not is irrelevant to files-backend after the last patch, remove the parameter from
files_downcast()and killfiles_assert_main_repository().PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
I think you are jumping the gun here.
Even after your changes, there is still a significant difference between the main repository and submodules: we have access to the object database for the main repository, but not for submodules.
So, for example, the following don't work for submodules:
*
parse_object()is used to ensure that references are only pointed at valid objects, and that branches are only pointed at commit objects.
Quoted 7 lines
*
peel_object()is used to write the peeled version of references inpacked-refs, and to peel references while they are being iterated over. Since this doesn't work, I think you can't writepacked-refsin a submodule.These limitations, I think, imply that submodule references have to be treated as read-only.
Behind the scene submodule does add_submodule_odb(), which basically makes the submodule's odb an alternate of in-core odb. So odb access works. I was puzzled how submodules could by pass odb access at the beginning only to find that out. technical/api-ref-iteration.txt also mentions that you need to add_submodule_odb(), so I think it's deliberate (albeit hacky) design.
Quoted 5 lines
When I was working on a patch series similar to yours, I introduced a boolean "
main_repository" flag instruct ref_store, and use that member to implementfiles_assert_main_repository(). That wayfiles_ref_store::submodulecan still be removed, which is the more important goal from a design standpoint.
I could keep the submodule check back (and replace the submodule string in files_ref_store with just a flag). But I really think all backend functions work with submodule. Perhaps add some tests to exercise/verify that files-backend-on-submodule works?
Signature · 1 line
Duy
Re: [PATCH v4 14/15] files-backend: remove submodule_allowed from files_downcast()
Quoted 28 lines · Duy Nguyen
Quoted 19 lines · Michael Haggerty
Quoted 6 lines · Nguyễn Thái Ngọc Duy
Since submodule or not is irrelevant to files-backend after the last patch, remove the parameter from
files_downcast()and killfiles_assert_main_repository().PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
I think you are jumping the gun here.
Even after your changes, there is still a significant difference between the main repository and submodules: we have access to the object database for the main repository, but not for submodules.
So, for example, the following don't work for submodules:
*
parse_object()is used to ensure that references are only pointed at valid objects, and that branches are only pointed at commit objects.Quoted 7 lines
*
peel_object()is used to write the peeled version of references inpacked-refs, and to peel references while they are being iterated over. Since this doesn't work, I think you can't writepacked-refsin a submodule.These limitations, I think, imply that submodule references have to be treated as read-only.
Quoted 6 lines
Behind the scene submodule does
add_submodule_odb(), which basically makes the submodule's odb an alternate of in-core odb. So odb access works. I was puzzled how submodules could by pass odb access at the beginning only to find that out.technical/api-ref-iteration.txtalso mentions that you need toadd_submodule_odb(), so I think it's deliberate (albeit hacky) design.
That's interesting. I didn't know it before.
But I still don't think that means that reference writing can work correctly. If I try to set a submodule branch to an SHA-1 and I verify that the SHA-1 points to a valid commit, how do I know that the commit is in the same submodule that holds the reference?
Quoted 1 line
[...]
Michael
Re: [PATCH v4 14/15] files-backend: remove submodule_allowed from files_downcast()
Quoted 36 lines · Michael Haggerty
Quoted 28 lines · Duy Nguyen
Quoted 19 lines · Michael Haggerty
Quoted 6 lines · Nguyễn Thái Ngọc Duy
Since submodule or not is irrelevant to files-backend after the last patch, remove the parameter from
files_downcast()and killfiles_assert_main_repository().PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
I think you are jumping the gun here.
Even after your changes, there is still a significant difference between the main repository and submodules: we have access to the object database for the main repository, but not for submodules.
So, for example, the following don't work for submodules:
*
parse_object()is used to ensure that references are only pointed at valid objects, and that branches are only pointed at commit objects.Quoted 7 lines
*
peel_object()is used to write the peeled version of references inpacked-refs, and to peel references while they are being iterated over. Since this doesn't work, I think you can't writepacked-refsin a submodule.These limitations, I think, imply that submodule references have to be treated as read-only.
Quoted 6 lines
Behind the scene submodule does
add_submodule_odb(), which basically makes the submodule's odb an alternate of in-core odb. So odb access works. I was puzzled how submodules could by pass odb access at the beginning only to find that out.technical/api-ref-iteration.txtalso mentions that you need toadd_submodule_odb(), so I think it's deliberate (albeit hacky) design.
Quoted 6 lines
That's interesting. I didn't know it before.
But I still don't think that means that reference writing can work correctly. If I try to set a submodule branch to an SHA-1 and I verify that the SHA-1 points to a valid commit, how do I know that the commit is in the same submodule that holds the reference?
Good point. So will the new flag be "read_only" (no reference to submodule), or "submodule"? This flag will be passed in at ref-store init time and kept in files_ref_store.
Signature · 1 line
Duy
Re: [PATCH v4 14/15] files-backend: remove submodule_allowed from files_downcast()
Quoted 16 lines · Duy Nguyen
Quoted 15 lines · Michael Haggerty
Quoted 11 lines · Duy Nguyen
Quoted 3 lines · Michael Haggerty
[...]
These limitations, I think, imply that submodule references have to be treated as read-only.Behind the scene submodule does
add_submodule_odb(), which basically makes the submodule's odb an alternate of in-core odb. So odb access works. I was puzzled how submodules could by pass odb access at the beginning only to find that out.technical/api-ref-iteration.txtalso mentions that you need toadd_submodule_odb(), so I think it's deliberate (albeit hacky) design.That's interesting. I didn't know it before.
Quoted 8 lines
Quoted 4 lines
But I still don't think that means that reference writing can work correctly. If I try to set a submodule branch to an SHA-1 and I verify that the SHA-1 points to a valid commit, how do I know that the commit is in the same submodule that holds the reference?
Good point. So will the new flag be "
read_only" (no reference to submodule), or "submodule"? This flag will be passed in at ref-store init time and kept infiles_ref_store.
I haven't checked carefully whether there are other operations that don't work and/or don't make sense for submodules. If not, then read_only would also be a fine name for the flag.
Michael
Re: [PATCH v4 14/15] files-backend: remove submodule_allowed from files_downcast()
In reply to Michael HaggertyQuoted 5 lines · Michael Haggerty
Quoted 4 lines · Nguyễn Thái Ngọc Duy
Since submodule or not is irrelevant to files-backend after the last patch, remove the parameter from
files_downcast()and killfiles_assert_main_repository().
Quoted 8 lines
Quoted 2 lines
PS. This implies that all ref operations are allowed for submodules. But we may need to look more closely to see if that's really true...
I think you are jumping the gun here.
Even after your changes, there is still a significant difference between the main repository and submodules: we have access to the object database for the main repository, but not for submodules.
I did jump the gun for another reason: files-backend makes function calls to the frontend, which unconditionally target the main ref store (e.g. resolve_ref_unsafe, delete_ref...). Of course, because store-aware api does not exist. My decision (off-list) to add test-ref-store was the right call. I would not have seen these because I was not (and still am not) familiar with files-backend.c enough to see its dark corners.
files-backend.c is not all unicorn and rainbow :(
Signature · 1 line
Duy
PATCH v4 15/15 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/files-backend.c | 2 +- refs/refs-internal.h | 12 ------------ 4 files changed, 20 insertions(+), 17 deletions(-)
refs.c +8 -4
@@ -1165,7 +1165,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)
@@ -1338,10 +1338,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)
@@ -1457,13 +1457,17 @@ struct ref_store *get_main_ref_store(void)return refs; } -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
@@ -556,5 +556,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/files-backend.c +1 -1
@@ -3125,7 +3125,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 ),"set_head_symref" ); +files_downcast (get_main_ref_store (),"set_head_symref" );static struct lock_file head_lock;struct ref_lock *lock;struct strbuf head_path =STRBUF_INIT ;
refs/refs-internal.h +0 -12
@@ -640,18 +640,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
Quoted 1 line · Nguyễn Thái Ngọc Duy
v4:
I very much like the direction of this patch series. I reviewed the design pretty carefully and left some comments about it, and skimmed through the code changes. But I haven't yet reviewed the code in detail. I'll wait for your reaction to my design comments before doing so.
Thanks,
Michael
Quoted 7 lines · Michael Haggerty
Quoted 1 line · Nguyễn Thái Ngọc Duy
v4:
I very much like the direction of this patch series. I reviewed the design pretty carefully and left some comments about it, and skimmed through the code changes. But I haven't yet reviewed the code in detail. I'll wait for your reaction to my design comments before doing so.
Unless there are some mails in transit, thanks for the review. The comments I haven't replied to usually mean "I agree" (but not writing unless I could add anything after).
Signature · 1 line
Duy
v5 cover Remove submodule from files-backend.c
In reply to Nguyễn Thái Ngọc Duyv5 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.c is 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, like open(). Operations are allowed or forbidden based on this flag. The submodule_allowed flag is killed. files_assert_main.. remains.
- get_*_ref_store() remain public api because it's used by test-ref-store.c and pack-refs.c.
- files-backend.c should 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.
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.
This series is also available on my github repo. branch files-backend-git-dir-2.
Nguyễn Thái Ngọc Duy (24):
refs.h: add forward declaration for structs used in this file
files-backend: make files_log_ref_write() static
files-backend: add and use files_packed_refs_path()
files-backend: convert git_path() to strbuf_git_path()
files-backend: move "logs/" out of TMP_RENAMED_LOG
files-backend: add and use files_reflog_path()
files-backend: add and use files_refname_path()
files-backend: remove the use of git_path()
refs.c: introduce get_main_ref_store()
refs: rename lookup_ref_store() to lookup_submodule_ref_store() refs.c: flatten get_ref_store() a bit
refs.c: kill register_ref_store(), add register_submodule_ref_store() refs.c: make get_main_ref_store() public and use it
path.c: move some code out of strbuf_git_path_submodule()
refs: move submodule code out of files-backend.c
files-backend: replace submodule_allowed check in files_downcast()
refs: rename get_ref_store() to get_submodule_ref_store() and make it public
refs: add new ref-store api
refs: new transaction related ref-store api
files-backend: avoid ref api targetting main ref store
refs: delete pack_refs() in favor of refs_pack_refs()
t/helper: add test-ref-store to test ref-store functions
t1405: some basic tests on main ref store
t1406: new tests for submodule ref store
Makefile | 1 + builtin/pack-refs.c | 2 +- path.c | 34 +-- refs.c | 411 ++++++++++++++++++-------- refs.h | 100 ++++++- refs/files-backend.c | 509 +++++++++++++++++++++----------- refs/refs-internal.h | 64 +--- submodule.c | 31 ++ submodule.h | 1 + t/helper/.gitignore | 1 + t/helper/test-ref-store.c (new) | 274 +++++++++++++++++ t/t1405-main-ref-store.sh (new +x) | 123 ++++++++ t/t1406-submodule-ref-store.sh (new +x) | 95 ++++++ 13 files changed, 1269 insertions(+), 377 deletions(-) create mode 100644 t/helper/test-ref-store.c create mode 100755 t/t1405-main-ref-store.sh create mode 100755 t/t1406-submodule-ref-store.sh
Signature · 1 line
2.11.0.157.gd943d85
PATCH v5 1/24 refs.h: add forward declaration for structs used in this file
--- refs.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
refs.h +5 -1
@@ -1,6 +1,11 @@#ifndef REFS_H #define REFS_H +struct object_id ; +struct ref_transaction ; +struct strbuf ; +struct string_list ; +/* * Resolve a reference, recursively following symbolic refererences. *
@@ -144,7 +149,6 @@ 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
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 01/24] refs.h: add forward declaration for structs used in this file
Quoted 22 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)refs.h +5
-0@@ -1,6 +1,11 @@#ifndef REFS_H #define REFS_H +struct object_id ; +struct ref_transaction ; +struct strbuf ; +struct string_list ; +/* * Resolve a reference, recursively following symbolic refererences. *
refs.h int dwim_log(const char *str, int len, unsigned char *sha1, char **ref); · line 147
Quoted 4 lines
refs.h +0
-1@@ -144,7 +149,6 @@ 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 ;
Leaving the detailed comment about ref_transaction dangling? I can understand if you don't want to move it with the declaration, as you want all declarations terse in a few lines.
Maybe move the comment to be part of the first large comment (The one that you can see in the first hunk, starting with " * Resolve a reference, recursively following")
Maybe Michael has a better idea how to make this comment more accessible to the casual refs-reader.
Thanks,
Stefan
Re: [PATCH v5 01/24] refs.h: add forward declaration for structs used in this file
Quoted 26 lines · Stefan Beller
Quoted 25 lines · Nguyễn Thái Ngọc Duy
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)refs.h +5
-0@@ -1,6 +1,11 @@#ifndef REFS_H #define REFS_H +struct object_id ; +struct ref_transaction ; +struct strbuf ; +struct string_list ; +/* * Resolve a reference, recursively following symbolic refererences. * @@ -144,7 +149,6 @@ 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. */
Quoted 8 lines
refs.h int dwim_log(const char *str, int len, unsigned char *sha1, char **ref); · line 147
Quoted 1 line
refs.h +0
-1-struct ref_transaction ;Leaving the detailed comment about
ref_transactiondangling? I can understand if you don't want to move it with the declaration, as you want all declarations terse in a few lines.
Maybe move the comment to be part of the first large comment (The one that you can see in the first hunk, starting with " * Resolve a reference, recursively following")
I thought the comment block covered the following declarations too, not just ref_transaction. But on second read it's not that. Transaction functions are way down below. I'll probably move ref_transaction back where it was.
Signature · 1 line
Duy
PATCH v5 2/24 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
PATCH v5 3/24 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 v5 4/24 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 | 139 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 106 insertions(+), 33 deletions(-)
refs/files-backend.c +106 -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,9 +2603,15 @@ 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 ; +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); + log = !lstat (sb_oldref.buf, &loginfo); +strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))return error ("reflog for %s is a symlink" , oldrefname);
@@ -2602,7 +2625,12 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log); +if (ret)return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno));
@@ -2681,13 +2709,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))) +strbuf_git_path (&sb_newref,"logs/%s" , newrefname); +strbuf_git_path (&sb_oldref,"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)); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG );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)); +strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log);return 1 ; }
@@ -2861,18 +2895,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 ;
@@ -3092,22 +3132,32 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static 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)
@@ -3162,7 +3212,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 ;
@@ -3268,7 +3320,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 ;
@@ -3350,12 +3404,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; }
@@ -3693,6 +3750,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);
@@ -3814,7 +3872,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; }
@@ -3834,7 +3894,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 ); }
@@ -3842,6 +3904,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++) {
@@ -4108,18 +4171,28 @@ 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_reset (&sb);if (get_shared_repository ()) { -adjust_shared_perm (git_path ("refs/heads" )); -adjust_shared_perm (git_path ("refs/tags" )); +strbuf_git_path (&sb,"refs/heads" ); +adjust_shared_perm (sb.buf); +strbuf_reset (&sb); +strbuf_git_path (&sb,"refs/tags" ); +adjust_shared_perm (sb.buf); } +strbuf_release (&sb);return 0 ; }
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 04/24] files-backend: convert git_path() to strbuf_git_path()
Quoted 53 lines · Nguyễn Thái Ngọc Duy
git_path()and friends are going to be killed infiles-backend.cin near future. And because there's a risk with overwriting buffer ingit_path(), let's convert them all tostrbuf_git_path(). We'll have easier time killing/convertingstrbuf_git_path()then because we won't have to worry about memory management again.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 139 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 106 insertions(+), 33 deletions(-)refs/files-backend.c +14
-3@@ -2586,9 +2603,15 @@ 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 ; +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); + log = !lstat (sb_oldref.buf, &loginfo); +strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))return error ("reflog for %s is a symlink" , oldrefname);@@ -2602,7 +2625,12 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -if (log &&rename (git_path ("logs/%s" , oldrefname),git_path (TMP_RENAMED_LOG ))) +strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); + ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log); +if (ret)return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno));@@ -2681,13 +2709,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))) +strbuf_git_path (&sb_newref,"logs/%s" , newrefname);
refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2721
Quoted 10 lines
refs/files-backend.c +4
-1+strbuf_git_path (&sb_oldref,"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)); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG );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));
It feels like you're writing, releasing, re-writing these strbufs more than necessary. Maybe it would be clearer to set them once, and on errors set ret = error() then jump to a label here...
refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2725
Quoted 4 lines
refs/files-backend.c +3
-0+strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log);
...and change this to return ret?
Quoted 25 lines
refs/files-backend.c +8
-3return 1 ; }@@ -4108,18 +4171,28 @@ 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_reset (&sb);if (get_shared_repository ()) { -adjust_shared_perm (git_path ("refs/heads" ));
refs/files-backend.c static int files_reflog_expire(struct ref_store *ref_store, · line 4197
Quoted 10 lines
refs/files-backend.c +6
-1-adjust_shared_perm (git_path ("refs/tags" )); +strbuf_git_path (&sb,"refs/heads" ); +adjust_shared_perm (sb.buf); +strbuf_reset (&sb); +strbuf_git_path (&sb,"refs/tags" ); +adjust_shared_perm (sb.buf); } +strbuf_release (&sb);return 0 ; }
It looks to me like safe_create_dir() already has the ability to adjust_shared_perm(), or am I missing something? (I realize that this is preexisting code.)
Michael
Re: [PATCH v5 04/24] files-backend: convert git_path() to strbuf_git_path()
Quoted 21 lines · Michael Haggerty
Quoted 6 lines
refs/files-backend.c +1
-1@@ -2681,13 +2709,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))) +strbuf_git_path (&sb_newref,"logs/%s" , newrefname);refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2721
Quoted 10 lines
refs/files-backend.c +4
-1+strbuf_git_path (&sb_oldref,"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)); +strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG );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));It feels like you're writing, releasing, re-writing these strbufs more than necessary. Maybe it would be clearer to set them once, and on errors set
ret = error()then jump to a label here...
Quoted 6 lines
refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2725
Quoted 4 lines
refs/files-backend.c +3
-0+strbuf_release (&sb_newref); +strbuf_release (&sb_oldref); +strbuf_release (&tmp_renamed_log);...and change this to
return ret?
If that's ok with you, will do. I kept the patch dumb so the reader does not have to keep track of many things when they check if there are any behavior changes.
Quoted 31 lines
Quoted 20 lines
refs/files-backend.c +8
-3static 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_reset (&sb);if (get_shared_repository ()) { -adjust_shared_perm (git_path ("refs/heads" ));refs/files-backend.c static int files_reflog_expire(struct ref_store *ref_store, · line 4197
Quoted 10 lines
refs/files-backend.c +6
-1-adjust_shared_perm (git_path ("refs/tags" )); +strbuf_git_path (&sb,"refs/heads" ); +adjust_shared_perm (sb.buf); +strbuf_reset (&sb); +strbuf_git_path (&sb,"refs/tags" ); +adjust_shared_perm (sb.buf); } +strbuf_release (&sb);return 0 ; }
Quoted 3 lines
It looks to me like
safe_create_dir()already has the ability toadjust_shared_perm(), or am I missing something? (I realize that this is preexisting code.)
Yeah you're right. I guess this code was written when safe_create_dir() didn't do that. That certainly shortens this patch.
Signature · 1 line
Duy
PATCH v5 5/24 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 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
refs/files-backend.c +6 -6
@@ -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) {
@@ -2626,12 +2626,12 @@ static int files_rename_ref(struct ref_store *ref_store,return 1 ;strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG ); ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf);strbuf_release (&sb_oldref);strbuf_release (&tmp_renamed_log);if (ret) -return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , +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 )) {
@@ -2714,10 +2714,10 @@ static int files_rename_ref(struct ref_store *ref_store,if (logmoved &&rename (sb_newref.buf, sb_oldref.buf))error ("unable to restore logfile %s from %s: %s" , oldrefname, newrefname,strerror (errno)); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG );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));strbuf_release (&sb_newref);strbuf_release (&sb_oldref);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 05/24] files-backend: move "logs/" out of TMP_RENAMED_LOG
Quoted 17 lines · Nguyễn Thái Ngọc Duy
This 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.
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)refs/files-backend.c +0
-0
refs/files-backend.c static int files_delete_refs(struct ref_store *ref_store, · line 2516
Quoted 5 lines
refs/files-backend.c +1
-1@@ -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"
The constant name feels a little bit misleading now that it is not the name of a logfile but rather a reference name. OTOH "tmp-renamed-log" is *in* the reference name so I guess it's not really wrong.
Quoted 14 lines
refs/files-backend.c +1
-1struct 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) {@@ -2626,12 +2626,12 @@ static int files_rename_ref(struct ref_store *ref_store,return 1 ;
refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2635
Quoted 10 lines
refs/files-backend.c +2
-2strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG ); ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf);strbuf_release (&sb_oldref);strbuf_release (&tmp_renamed_log);if (ret) -return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , +return error ("unable to move logfile logs/%s to logs/" TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno));
It seems like it would be preferable to use sb_oldref.buf and tmp.buf when building the error message. But I guess that tmp.buf might include some path preceding "logs/" that is unwanted in the error message? But it's a shame to hardcode the file naming scheme here again.
Maybe we *do* want the path in the error message?
It just occurred to me: this temporary logfile lives in the main repository, right? What if a worktree reference is being renamed? Part of the advertised use of worktrees is that the worktree might live far from the main directory, or even on removable media. But it's not possible to rename files across partitions. Maybe this will come out in the wash once worktrees are ref_stores themselves.
For that matter, what if a user tries to rename a worktree ref into a common ref or vice versa?
refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2637
Quoted 2 lines
refs/files-backend.c +0
-0if (delete_ref (oldrefname, orig_sha1,REF_NODEREF )) {
Michael
Re: [PATCH v5 05/24] files-backend: move "logs/" out of TMP_RENAMED_LOG
Quoted 10 lines · Michael Haggerty
refs/files-backend.c static int files_delete_refs(struct ref_store *ref_store, · line 2516
Quoted 6 lines
refs/files-backend.c +1
-1@@ -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"The constant name feels a little bit misleading now that it is not the name of a logfile but rather a reference name. OTOH "tmp-renamed-log" is *in* the reference name so I guess it's not really wrong.
Heh.. I had a similar internal debate and almost renamed it to tmp_renamed_refname. But then it's technically not a valid ref name either (starting with a leading dot). My lazy side came in and declared that doing nothing was always the right way.
Quoted 30 lines
Quoted 14 lines
refs/files-backend.c +1
-1struct 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) {@@ -2626,12 +2626,12 @@ static int files_rename_ref(struct ref_store *ref_store,return 1 ;refs/files-backend.c static int files_rename_ref(struct ref_store *ref_store, · line 2635
Quoted 10 lines
refs/files-backend.c +2
-2strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&tmp_renamed_log,TMP_RENAMED_LOG ); +strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG ); ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf);strbuf_release (&sb_oldref);strbuf_release (&tmp_renamed_log);if (ret) -return error ("unable to move logfile logs/%s to " TMP_RENAMED_LOG ": %s" , +return error ("unable to move logfile logs/%s to logs/" TMP_RENAMED_LOG ": %s" , oldrefname,strerror (errno));It seems like it would be preferable to use
sb_oldref.bufandtmp.bufwhen building the error message. But I guess thattmp.bufmight include some path preceding "logs/" that is unwanted in the error message? But it's a shame to hardcode the file naming scheme here again.
Quoted 1 line
Maybe we *do* want the path in the error message?
It's an error, every piece of details matters. So yeah I'm inclined we should print full path.
Quoted 6 lines
It just occurred to me: this temporary logfile lives in the main repository, right? What if a worktree reference is being renamed? Part of the advertised use of worktrees is that the worktree might live far from the main directory, or even on removable media. But it's not possible to rename files across partitions. Maybe this will come out in the wash once worktrees are
ref_storesthemselves.
The actual working directory may be separated, but all the things that belong to .git (even of a linked worktree) stay in the main worktree's .git directory. And I don't think we ever support having a .git directory on multiple partitions. You can rename refs freely even when the worktree is on a detached removable drive.
Quoted 2 lines
For that matter, what if a user tries to rename a worktree ref into a common ref or vice versa?
Interesting. It should work, it's just a rename(".git/worktrees/blah/refs/bisect/good", ".git/refs/heads/saved") after the path translation done by git_path().
Signature · 1 line
Duy
PATCH v5 6/24 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 | 148 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 59 deletions(-)
refs/files-backend.c +89 -59
@@ -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,7 +2624,7 @@ 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); +files_reflog_path (refs, &sb_oldref, oldrefname); log = !lstat (sb_oldref.buf, &loginfo);strbuf_release (&sb_oldref);if (log &&S_ISLNK (loginfo.st_mode))
@@ -2625,8 +2640,8 @@ static int files_rename_ref(struct ref_store *ref_store,if (!rename_ref_available (oldrefname, newrefname))return 1 ; -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); -strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG ); +files_reflog_path (refs, &sb_oldref, oldrefname); +files_reflog_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG ); ret = log &&rename (sb_oldref.buf, tmp_renamed_log.buf);strbuf_release (&sb_oldref);strbuf_release (&tmp_renamed_log);
@@ -2667,7 +2682,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;
@@ -2709,12 +2724,12 @@ static int files_rename_ref(struct ref_store *ref_store, log_all_ref_updates = flag; rollbacklog: -strbuf_git_path (&sb_newref,"logs/%s" , newrefname); -strbuf_git_path (&sb_oldref,"logs/%s" , oldrefname); +files_reflog_path (refs, &sb_newref, newrefname); +files_reflog_path (refs, &sb_oldref, oldrefname);if (logmoved &&rename (sb_newref.buf, sb_oldref.buf))error ("unable to restore logfile %s from %s: %s" , oldrefname, newrefname,strerror (errno)); -strbuf_git_path (&tmp_renamed_log,"logs/%s" ,TMP_RENAMED_LOG ); +files_reflog_path (refs, &tmp_renamed_log,TMP_RENAMED_LOG );if (!logmoved && log &&rename (tmp_renamed_log.buf, sb_oldref.buf)) error("unable to restore logfile %s from logs/"TMP_RENAMED_LOG": %s",
@@ -2782,10 +2797,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)) {
@@ -2835,12 +2855,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 )
@@ -2875,7 +2894,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) {
@@ -2884,7 +2904,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)
@@ -2898,7 +2919,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);
@@ -2909,7 +2930,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);
@@ -2970,7 +2991,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",
@@ -3002,8 +3024,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); }
@@ -3035,24 +3058,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 ; }
@@ -3060,7 +3085,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);
@@ -3089,13 +3114,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) { +/* +* 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 ;
@@ -3122,7 +3154,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target) lock->lk = &head_lock; lock->ref_name =xstrdup (head_rel); - ret =create_symref_locked (lock, head_rel, target,NULL ); + ret =create_symref_locked (refs, lock, head_rel, target,NULL );unlock_ref (lock);/* will free lock */ strbuf_release (&head_path);
@@ -3132,14 +3164,13 @@ int set_worktree_head_symref(const char *gitdir, const char *target)static int files_reflog_exists (struct ref_store *ref_store,const char *refname) { +struct files_ref_store *refs = +files_downcast (ref_store,0 ,"reflog_exists" );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;
@@ -3148,13 +3179,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;
@@ -3204,15 +3234,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)
@@ -3313,14 +3342,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)
@@ -3402,15 +3430,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;
@@ -3835,7 +3862,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,
@@ -3895,9 +3923,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 ); }
@@ -3921,7 +3949,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 ); } }
@@ -4072,6 +4100,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;
@@ -4100,7 +4129,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 v5 7/24 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 sumodule-ready. Not yet.
--- refs/files-backend.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-)
refs/files-backend.c +25 -20
@@ -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.
@@ -1251,10 +1263,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)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) {
@@ -1396,10 +1405,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 +1593,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 +2065,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 +2364,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 ;
@@ -2668,7 +2674,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);
@@ -3901,7 +3907,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;
@@ -4201,25 +4207,24 @@ 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_reset (&sb);if (get_shared_repository ()) { -strbuf_git_path (&sb,"refs/heads" ); +files_refname_path (refs, &sb,"refs/heads" );adjust_shared_perm (sb.buf);strbuf_reset (&sb); -strbuf_git_path (&sb,"refs/tags" ); +files_refname_path (refs, &sb,"refs/tags" );adjust_shared_perm (sb.buf); }strbuf_release (&sb);
Signature · 1 line
2.11.0.157.gd943d85
Re: [PATCH v5 07/24] 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 sumodule-ready. Not yet.
s/sumodule/submodule/
Quoted 14 lines
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-)refs/files-backend.c +1
-0@@ -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,
refs/files-backend.c static void files_reflog_path(struct files_ref_store *refs, · line 1193
Quoted 10 lines
refs/files-backend.c +10
-0+ 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); +}
Maybe it's just me, but I find it odd to exit early here when the first exit isn't due to an error. For me, structuring this like if () call1(); else call2(); would make it clearer that the two code paths are equally-valid alternatives, and either one or the other will be executed.
I had the same feeling when I read files_reflog_path()
refs/files-backend.c static void read_loose_refs(const char *dirname, struct ref_dir *dir) · line 1266
Quoted 12 lines
refs/files-backend.c +1
-4/* * Get the packed_ref_cache for the specified files_ref_store, * creating it if necessary. @@ -1251,10 +1263,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)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);
It's so nice to see these ugly if (refs->submodule) code blocks disappearing!
Quoted 1 line
[...]
Michael
Re: [PATCH v5 07/24] files-backend: add and use files_refname_path()
Quoted 32 lines · Michael Haggerty
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 sumodule-ready. Not yet.s/sumodule/submodule/
Quoted 22 lines
Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-)refs/files-backend.c +9
-0@@ -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 ; + } +
Quoted 8 lines
refs/files-backend.c static void files_reflog_path(struct files_ref_store *refs, · line 1193
Quoted 2 lines
refs/files-backend.c +2
-0+strbuf_git_path (sb,"%s" , refname); +}Maybe it's just me, but I find it odd to exit early here when the first exit isn't due to an error. For me, structuring this like
if () call1(); else call2();would make it clearer that the two code paths are equally-valid alternatives, and either one or the other will be executed.
Its original version probably looked better. This is another case of future patches influencing back the past ones: I structure the patch so that in future we mostly add lines, or delete whole (in this case, I believe), not modify a lot of lines. I think the readability does not degrade too much though, so it's probably ok.
Signature · 1 line
Duy
Re: [PATCH v5 07/24] files-backend: add and use files_refname_path()
In reply to Nguyễn Thái Ngọc DuyQuoted 19 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 sumodule-ready. Not yet.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-)refs/files-backend.c +0
-0@@ -1251,10 +1263,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)size_t path_baselen;
refs/files-backend.c static void read_loose_refs(const char *dirname, struct ref_dir *dir) · line 1269
Quoted 10 lines
refs/files-backend.c +1
-4int 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) {
I just noticed another thing. After this change, err is never set, so the if (err) block (and err itself) can be deleted.
Quoted 1 line
[...]
Michael
PATCH v5 8/24 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
Re: [PATCH v5 08/24] files-backend: remove the use of git_path()
Quoted 37 lines · Nguyễn Thái Ngọc Duy
Given $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.Signed-off-by Nguyễn Thái Ngọc Duy <[email protected]>--- refs/files-backend.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-)refs/files-backend.c +4
-1@@ -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);
refs/files-backend.c static struct ref_store *files_ref_store_create(const char *submodule) · line 1005
Quoted 9 lines
refs/files-backend.c +5
-1@@ -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 );
git_path() and friends avoid adding an extra / if git_dir() already ends in a slash or if it is the empty string. Here you don't have that functionality. Is that intentional?
Same thing below, too.
Quoted 43 lines
refs/files-backend.c +22
-3return 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 ;
refs/files-backend.c static void files_refname_path(struct files_ref_store *refs, · line 1228
Quoted 10 lines
refs/files-backend.c +7
-0+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); + } }/*
Michael
Re: [PATCH v5 08/24] files-backend: remove the use of git_path()
Quoted 4 lines · Michael Haggerty
Quoted 4 lines
refs/files-backend.c +0
-0@@ -995,7 +998,11 @@ static struct ref_store *files_ref_store_create(const char *submodule)return ref_store; }
Quoted 10 lines
refs/files-backend.c static struct ref_store *files_ref_store_create(const char *submodule) · line 1005
Quoted 6 lines
refs/files-backend.c +5
-1- 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 );
git_path()and friends avoid adding an extra/ifgit_dir()already ends in a slash or if it is the empty string. Here you don't have that functionality. Is that intentional?
Kind of. I noticed that behavior but the thinking was, this $GIT_DIR thing is going to get replaced soon anyway, and because the the uses of these paths are very clear (in three groups) that avoiding redundant slashes does not buy us anything extra, it's just more code.
Signature · 1 line
Duy
PATCH v5 9/24 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 v5 09/24] refs.c: introduce get_main_ref_store()
Quoted 12 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 +0
-0@@ -1456,15 +1456,23 @@ static struct ref_store *ref_store_init(const char *submodule)return refs; }
refs.c static struct ref_store *ref_store_init(const char *submodule) · line 1467
Quoted 10 lines
refs.c +9
-0+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;
Unnecessary temporary variable?
Quoted 1 line
[...]
Michael
Re: [PATCH v5 09/24] refs.c: introduce get_main_ref_store()
Quoted 14 lines · Michael Haggerty
Quoted 13 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 +0
-0@@ -1456,15 +1456,23 @@ static struct ref_store *ref_store_init(const char *submodule)return refs; }
Quoted 11 lines
refs.c static struct ref_store *ref_store_init(const char *submodule) · line 1467
Quoted 9 lines
refs.c +9
-0+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;Unnecessary temporary variable?
That's the price for doing too much mechanical conversion :-P On second read, I think I did that on purpose (or by luck) because the "kill register_ref_store" patch needs this intermediate "refs" so we can save it to main_ref_store. Cleaner future patch for the minor uncleanliness in the current one.
Signature · 1 line
Duy
PATCH v5 10/24 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 v5 11/24 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 | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
refs.c +9 -10
@@ -1465,22 +1465,21 @@ 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;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); +if (is_nonbare_repository_dir (&submodule_sb)) + refs =ref_store_init (submodule); +strbuf_release (&submodule_sb);return refs; }
Signature · 1 line
2.11.0.157.gd943d85
PATCH v5 12/24 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 | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-)
refs.c +26 -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,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; } +/* +* 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 ;
@@ -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) +register_submodule_ref_store (refs, submodule);return refs; }
Signature · 1 line
2.11.0.157.gd943d85