Skip to content

Commit

Permalink
refs: make refs/bisect/* per-worktree
Browse files Browse the repository at this point in the history
We need the place we stick refs for bisects in progress to not be
shared between worktrees.  So we make the refs/bisect/ hierarchy
per-worktree.

The is_per_worktree_ref function and associated docs learn that
refs/bisect/ is per-worktree, as does the git_path code in path.c

The ref-packing functions learn that per-worktree refs should not be
packed (since packed-refs is common rather than per-worktree).

Since refs/bisect is per-worktree, logs/refs/bisect should be too.

Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
David Turner authored and Junio C Hamano committed Sep 1, 2015
1 parent 4e09cf2 commit ce414b3
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 3 deletions.
5 changes: 3 additions & 2 deletions Documentation/glossary-content.txt
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,9 @@ exclude;;

[[def_per_worktree_ref]]per-worktree ref::
Refs that are per-<<def_working_tree,worktree>>, rather than
global. This is presently only <<def_HEAD,HEAD>>, but might
later include other unusual refs.
global. This is presently only <<def_HEAD,HEAD>> and any refs
that start with `refs/bisect/`, but might later include other
unusual refs.

[[def_pseudoref]]pseudoref::
Pseudorefs are a class of files under `$GIT_DIR` which behave
Expand Down
2 changes: 2 additions & 0 deletions path.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,11 @@ static struct common_dir common_list[] = {
{ 0, 0, 1, "info/sparse-checkout" },
{ 1, 1, 0, "logs" },
{ 1, 1, 1, "logs/HEAD" },
{ 0, 1, 1, "logs/refs/bisect" },
{ 0, 1, 0, "lost-found" },
{ 0, 1, 0, "objects" },
{ 0, 1, 0, "refs" },
{ 0, 1, 1, "refs/bisect" },
{ 0, 1, 0, "remotes" },
{ 0, 1, 0, "worktrees" },
{ 0, 1, 0, "rr-cache" },
Expand Down
32 changes: 31 additions & 1 deletion refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ struct ref_entry {
};

static void read_loose_refs(const char *dirname, struct ref_dir *dir);
static int search_ref_dir(struct ref_dir *dir, const char *refname, size_t len);
static struct ref_entry *create_dir_entry(struct ref_cache *ref_cache,
const char *dirname, size_t len,
int incomplete);
static void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry);

static struct ref_dir *get_ref_dir(struct ref_entry *entry)
{
Expand All @@ -312,6 +317,24 @@ static struct ref_dir *get_ref_dir(struct ref_entry *entry)
dir = &entry->u.subdir;
if (entry->flag & REF_INCOMPLETE) {
read_loose_refs(entry->name, dir);

/*
* Manually add refs/bisect, which, being
* per-worktree, might not appear in the directory
* listing for refs/ in the main repo.
*/
if (!strcmp(entry->name, "refs/")) {
int pos = search_ref_dir(dir, "refs/bisect/", 12);
if (pos < 0) {
struct ref_entry *child_entry;
child_entry = create_dir_entry(dir->ref_cache,
"refs/bisect/",
12, 1);
add_entry_to_dir(dir, child_entry);
read_loose_refs("refs/bisect",
&child_entry->u.subdir);
}
}
entry->flag &= ~REF_INCOMPLETE;
}
return dir;
Expand Down Expand Up @@ -2649,6 +2672,8 @@ struct pack_refs_cb_data {
struct ref_to_prune *ref_to_prune;
};

static int is_per_worktree_ref(const char *refname);

/*
* An each_ref_entry_fn that is run over loose references only. If
* the loose reference can be packed, add an entry in the packed ref
Expand All @@ -2662,6 +2687,10 @@ static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data)
struct ref_entry *packed_entry;
int is_tag_ref = starts_with(entry->name, "refs/tags/");

/* Do not pack per-worktree refs: */
if (is_per_worktree_ref(entry->name))
return 0;

/* ALWAYS pack tags */
if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref)
return 0;
Expand Down Expand Up @@ -2856,7 +2885,8 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)

static int is_per_worktree_ref(const char *refname)
{
return !strcmp(refname, "HEAD");
return !strcmp(refname, "HEAD") ||
starts_with(refname, "refs/bisect/");
}

static int is_pseudoref_syntax(const char *refname)
Expand Down
5 changes: 5 additions & 0 deletions t/t0060-path-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ test_expect_success 'setup common repository' 'git --git-dir=bar init'
test_git_path GIT_COMMON_DIR=bar index .git/index
test_git_path GIT_COMMON_DIR=bar HEAD .git/HEAD
test_git_path GIT_COMMON_DIR=bar logs/HEAD .git/logs/HEAD
test_git_path GIT_COMMON_DIR=bar logs/refs/bisect/foo .git/logs/refs/bisect/foo
test_git_path GIT_COMMON_DIR=bar logs/refs/bisec/foo bar/logs/refs/bisec/foo
test_git_path GIT_COMMON_DIR=bar logs/refs/bisec bar/logs/refs/bisec
test_git_path GIT_COMMON_DIR=bar logs/refs/bisectfoo bar/logs/refs/bisectfoo
test_git_path GIT_COMMON_DIR=bar objects bar/objects
test_git_path GIT_COMMON_DIR=bar objects/bar bar/objects/bar
test_git_path GIT_COMMON_DIR=bar info/exclude bar/info/exclude
Expand All @@ -276,6 +280,7 @@ test_git_path GIT_COMMON_DIR=bar remotes/bar bar/remotes/bar
test_git_path GIT_COMMON_DIR=bar branches/bar bar/branches/bar
test_git_path GIT_COMMON_DIR=bar logs/refs/heads/master bar/logs/refs/heads/master
test_git_path GIT_COMMON_DIR=bar refs/heads/master bar/refs/heads/master
test_git_path GIT_COMMON_DIR=bar refs/bisect/foo .git/refs/bisect/foo
test_git_path GIT_COMMON_DIR=bar hooks/me bar/hooks/me
test_git_path GIT_COMMON_DIR=bar config bar/config
test_git_path GIT_COMMON_DIR=bar packed-refs bar/packed-refs
Expand Down
19 changes: 19 additions & 0 deletions t/t1400-update-ref.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1130,4 +1130,23 @@ test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction deleting branches
)
'

test_expect_success 'handle per-worktree refs in refs/bisect' '
git commit --allow-empty -m "initial commit" &&
git worktree add -b branch worktree &&
(
cd worktree &&
git commit --allow-empty -m "test commit" &&
git for-each-ref >for-each-ref.out &&
! grep refs/bisect for-each-ref.out &&
git update-ref refs/bisect/something HEAD &&
git rev-parse refs/bisect/something >../worktree-head &&
git for-each-ref | grep refs/bisect/something
) &&
test_path_is_missing .git/refs/bisect &&
test_must_fail git rev-parse refs/bisect/something &&
git update-ref refs/bisect/something HEAD &&
git rev-parse refs/bisect/something >main-head &&
! test_cmp main-head worktree-head
'

test_done
7 changes: 7 additions & 0 deletions t/t3210-pack-refs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ test_expect_success 'pack ref directly below refs/' '
test_path_is_missing .git/refs/top
'

test_expect_success 'do not pack ref in refs/bisect' '
git update-ref refs/bisect/local HEAD &&
git pack-refs --all --prune &&
! grep refs/bisect/local .git/packed-refs >/dev/null &&
test_path_is_file .git/refs/bisect/local
'

test_expect_success 'disable reflogs' '
git config core.logallrefupdates false &&
rm -rf .git/logs
Expand Down

0 comments on commit ce414b3

Please sign in to comment.