summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2017-06-26 14:09:29 -0700
committerJunio C Hamano <gitster@pobox.com>2017-06-26 14:09:29 -0700
commit5c83d850d076ebc00b149975981703a6a664892b (patch)
treead73b67921955035e55321ade766f28cbc9cc048
parent849b44cdf193908dfe1cadc731fb23019b53a211 (diff)
parent03df567fbf6afeca32f6a27d04656c1a3a162453 (diff)
downloadgit-5c83d850d076ebc00b149975981703a6a664892b.tar.gz
Merge branch 'mh/packed-ref-store-prep'
Bugfix for a topic that is (only) in 'master'. * mh/packed-ref-store-prep: for_each_bisect_ref(): don't trim refnames lock_packed_refs(): fix cache validity check
-rw-r--r--refs.c12
-rw-r--r--refs.h5
-rw-r--r--refs/files-backend.c32
-rw-r--r--revision.c2
-rwxr-xr-xt/t6002-rev-list-bisect.sh14
5 files changed, 54 insertions, 11 deletions
diff --git a/refs.c b/refs.c
index 84112c88ee..88658ba769 100644
--- a/refs.c
+++ b/refs.c
@@ -1342,6 +1342,18 @@ int for_each_ref_in_submodule(const char *submodule, const char *prefix,
prefix, fn, cb_data);
}
+int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
+ each_ref_fn fn, void *cb_data,
+ unsigned int broken)
+{
+ unsigned int flag = 0;
+
+ if (broken)
+ flag = DO_FOR_EACH_INCLUDE_BROKEN;
+ return do_for_each_ref(get_submodule_ref_store(submodule),
+ prefix, fn, 0, flag, cb_data);
+}
+
int for_each_replace_ref(each_ref_fn fn, void *cb_data)
{
return do_for_each_ref(get_main_ref_store(),
diff --git a/refs.h b/refs.h
index 4be14c4b3c..aa4ecc83d0 100644
--- a/refs.h
+++ b/refs.h
@@ -303,7 +303,10 @@ int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data);
int for_each_ref_submodule(const char *submodule,
each_ref_fn fn, void *cb_data);
int for_each_ref_in_submodule(const char *submodule, const char *prefix,
- each_ref_fn fn, void *cb_data);
+ each_ref_fn fn, void *cb_data);
+int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
+ each_ref_fn fn, void *cb_data,
+ unsigned int broken);
int for_each_tag_ref_submodule(const char *submodule,
each_ref_fn fn, void *cb_data);
int for_each_branch_ref_submodule(const char *submodule,
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 5ef88eda8b..0404f2c233 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -371,6 +371,18 @@ static void files_ref_path(struct files_ref_store *refs,
}
/*
+ * Check that the packed refs cache (if any) still reflects the
+ * contents of the file. If not, clear the cache.
+ */
+static void validate_packed_ref_cache(struct files_ref_store *refs)
+{
+ if (refs->packed &&
+ !stat_validity_check(&refs->packed->validity,
+ files_packed_refs_path(refs)))
+ clear_packed_ref_cache(refs);
+}
+
+/*
* Get the packed_ref_cache for the specified files_ref_store,
* creating and populating it if it hasn't been read before or if the
* file has been changed (according to its `validity` field) since it
@@ -382,10 +394,8 @@ static struct packed_ref_cache *get_packed_ref_cache(struct files_ref_store *ref
{
const char *packed_refs_file = files_packed_refs_path(refs);
- if (refs->packed &&
- !is_lock_file_locked(&refs->packed_refs_lock) &&
- !stat_validity_check(&refs->packed->validity, packed_refs_file))
- clear_packed_ref_cache(refs);
+ if (!is_lock_file_locked(&refs->packed_refs_lock))
+ validate_packed_ref_cache(refs);
if (!refs->packed)
refs->packed = read_packed_refs(packed_refs_file);
@@ -1312,13 +1322,17 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)
&refs->packed_refs_lock, files_packed_refs_path(refs),
flags, timeout_value) < 0)
return -1;
+
/*
- * Get the current packed-refs while holding the lock. It is
- * important that we call `get_packed_ref_cache()` before
- * setting `packed_ref_cache->lock`, because otherwise the
- * former will see that the file is locked and assume that the
- * cache can't be stale.
+ * Now that we hold the `packed-refs` lock, make sure that our
+ * cache matches the current version of the file. Normally
+ * `get_packed_ref_cache()` does that for us, but that
+ * function assumes that when the file is locked, any existing
+ * cache is still valid. We've just locked the file, but it
+ * might have changed the moment *before* we locked it.
*/
+ validate_packed_ref_cache(refs);
+
packed_ref_cache = get_packed_ref_cache(refs);
/* Increment the reference count to prevent it from being freed: */
acquire_packed_ref_cache(packed_ref_cache);
diff --git a/revision.c b/revision.c
index d81c08a1de..e181ad1b70 100644
--- a/revision.c
+++ b/revision.c
@@ -2075,7 +2075,7 @@ static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_d
struct strbuf bisect_refs = STRBUF_INIT;
int status;
strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
- status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data);
+ status = for_each_fullref_in_submodule(submodule, bisect_refs.buf, fn, cb_data, 0);
strbuf_release(&bisect_refs);
return status;
}
diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh
index 3bf2759eae..534903bbd2 100755
--- a/t/t6002-rev-list-bisect.sh
+++ b/t/t6002-rev-list-bisect.sh
@@ -235,4 +235,18 @@ test_sequence "--bisect"
#
#
+
+test_expect_success '--bisect can default to good/bad refs' '
+ git update-ref refs/bisect/bad c3 &&
+ good=$(git rev-parse b1) &&
+ git update-ref refs/bisect/good-$good $good &&
+ good=$(git rev-parse c1) &&
+ git update-ref refs/bisect/good-$good $good &&
+
+ # the only thing between c3 and c1 is c2
+ git rev-parse c2 >expect &&
+ git rev-list --bisect >actual &&
+ test_cmp expect actual
+'
+
test_done