refs: introduce a "ref paranoia" flag
authorJeff King <peff@peff.net>
Fri, 20 Mar 2015 18:43:06 +0000 (14:43 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 20 Mar 2015 19:40:49 +0000 (12:40 -0700)
Most operations that iterate over refs are happy to ignore
broken cruft. However, some operations should be performed
with knowledge of these broken refs, because it is better
for the operation to choke on a missing object than it is to
silently pretend that the ref did not exist (e.g., if we are
computing the set of reachable tips in order to prune
objects).

These processes could just call for_each_rawref, except that
ref iteration is often hidden behind other interfaces. For
instance, for a destructive "repack -ad", we would have to
inform "pack-objects" that we are destructive, and then it
would in turn have to tell the revision code that our
"--all" should include broken refs.

It's much simpler to just set a global for "dangerous"
operations that includes broken refs in all iterations.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git.txt
cache.h
environment.c
refs.c
index af306209e936e0387e08d779815f995988565cc4..8da85a604ea8464f6a5c6c9da944335381f69853 100644 (file)
@@ -1026,6 +1026,17 @@ GIT_ICASE_PATHSPECS::
        variable when it is invoked as the top level command by the
        end user, to be recorded in the body of the reflog.
 
+`GIT_REF_PARANOIA`::
+       If set to `1`, include broken or badly named refs when iterating
+       over lists of refs. In a normal, non-corrupted repository, this
+       does nothing. However, enabling it may help git to detect and
+       abort some operations in the presence of broken refs. Git sets
+       this variable automatically when performing destructive
+       operations like linkgit:git-prune[1]. You should not need to set
+       it yourself unless you want to be paranoid about making sure
+       an operation has touched every ref (e.g., because you are
+       cloning a repository to make a backup).
+
 
 Discussion[[Discussion]]
 ------------------------
diff --git a/cache.h b/cache.h
index 4d02efc905456e61ce841ec1db2cc19491346257..23806394eb5089f480d5300ac23e616eccd604db 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -613,6 +613,14 @@ extern int precomposed_unicode;
 extern int protect_hfs;
 extern int protect_ntfs;
 
+/*
+ * Include broken refs in all ref iterations, which will
+ * generally choke dangerous operations rather than letting
+ * them silently proceed without taking the broken ref into
+ * account.
+ */
+extern int ref_paranoia;
+
 /*
  * The character that begins a commented line in user-editable file
  * that is subject to stripspace.
index 1ade5c9684a9f901db7d0b3fff04d0cad443caf7..a40044c3bf8040a36ddfb5c260b389ec63683abd 100644 (file)
@@ -24,6 +24,7 @@ int is_bare_repository_cfg = -1; /* unspecified */
 int log_all_ref_updates = -1; /* unspecified */
 int warn_ambiguous_refs = 1;
 int warn_on_object_refname_ambiguity = 1;
+int ref_paranoia = -1;
 int repository_format_version;
 const char *git_commit_encoding;
 const char *git_log_output_encoding;
diff --git a/refs.c b/refs.c
index 9edf18b04e7e29b12fa3808aab2239efcc404dca..6c788814200fbb10f2bcf2cbe3f2b2b057ecf6c2 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1907,6 +1907,11 @@ static int do_for_each_ref(struct ref_cache *refs, const char *base,
        data.fn = fn;
        data.cb_data = cb_data;
 
+       if (ref_paranoia < 0)
+               ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 0);
+       if (ref_paranoia)
+               data.flags |= DO_FOR_EACH_INCLUDE_BROKEN;
+
        return do_for_each_entry(refs, base, do_one_ref, &data);
 }