#include "../cache.h"
+#include "../config.h"
#include "../refs.h"
#include "refs-internal.h"
#include "ref-cache.h"
oidclr(&oid);
flag |= REF_BAD_NAME | REF_ISBROKEN;
}
- last = create_ref_entry(refname, &oid, flag, 0);
+ last = create_ref_entry(refname, &oid, flag);
if (peeled == PEELED_FULLY ||
(peeled == PEELED_TAGS && starts_with(refname, "refs/tags/")))
last->flag |= REF_KNOWS_PEELED;
}
}
+/*
+ * 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
{
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);
if (!is_lock_file_locked(&refs->packed_refs_lock))
die("BUG: packed refs not locked");
+
+ if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
+ die("Reference has invalid format: '%s'", refname);
+
add_ref_entry(get_packed_ref_dir(packed_ref_cache),
- create_ref_entry(refname, oid, REF_ISPACKED, 1));
+ create_ref_entry(refname, oid, REF_ISPACKED));
}
/*
flag |= REF_BAD_NAME | REF_ISBROKEN;
}
add_entry_to_dir(dir,
- create_ref_entry(refname.buf, &oid, flag, 0));
+ create_ref_entry(refname.buf, &oid, flag));
}
strbuf_setlen(&refname, dirnamelen);
strbuf_setlen(&path, path_baselen);
struct ref_iterator *loose_iter, *packed_iter;
struct files_ref_iterator *iter;
struct ref_iterator *ref_iterator;
+ unsigned int required_flags = REF_STORE_READ;
- if (ref_paranoia < 0)
- ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 0);
- if (ref_paranoia)
- flags |= DO_FOR_EACH_INCLUDE_BROKEN;
+ if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN))
+ required_flags |= REF_STORE_ODB;
- refs = files_downcast(ref_store,
- REF_STORE_READ | (ref_paranoia ? 0 : REF_STORE_ODB),
- "ref_iterator_begin");
+ refs = files_downcast(ref_store, required_flags, "ref_iterator_begin");
iter = xcalloc(1, sizeof(*iter));
ref_iterator = &iter->base;
&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);
oidcpy(&packed_entry->u.value.oid, iter->oid);
} else {
packed_entry = create_ref_entry(iter->refname, iter->oid,
- REF_ISPACKED, 0);
+ REF_ISPACKED);
add_ref_entry(packed_refs, packed_entry);
}
oidclr(&packed_entry->u.value.peeled);
head_oid.hash, &head_type);
if (head_ref && !(head_type & REF_ISSYMREF)) {
- free(head_ref);
- head_ref = NULL;
+ FREE_AND_NULL(head_ref);
}
/*