Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Beller <sbeller@google.com>2018-04-11 00:26:21 +0300
committerJunio C Hamano <gitster@pobox.com>2018-04-11 12:11:00 +0300
commit11bc058ce66a437499a774e82398c96e1324e2e0 (patch)
tree6ac923d7376c17817799941daedd004cd51f527b /replace-object.c
parentfc1395f4a491a7da46a446233531005634eb979d (diff)
replace_object.c: rename to use dash in file name
This is more consistent with the project style. The majority of Git's source files use dashes in preference to underscores in their file names. Noticed while adding a header corresponding to this file. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Stefan Beller <sbeller@google.com>
Diffstat (limited to 'replace-object.c')
-rw-r--r--replace-object.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/replace-object.c b/replace-object.c
new file mode 100644
index 0000000000..336357394d
--- /dev/null
+++ b/replace-object.c
@@ -0,0 +1,120 @@
+#include "cache.h"
+#include "sha1-lookup.h"
+#include "refs.h"
+#include "commit.h"
+
+/*
+ * An array of replacements. The array is kept sorted by the original
+ * sha1.
+ */
+static struct replace_object {
+ struct object_id original;
+ struct object_id replacement;
+} **replace_object;
+
+static int replace_object_alloc, replace_object_nr;
+
+static const unsigned char *replace_sha1_access(size_t index, void *table)
+{
+ struct replace_object **replace = table;
+ return replace[index]->original.hash;
+}
+
+static int replace_object_pos(const unsigned char *sha1)
+{
+ return sha1_pos(sha1, replace_object, replace_object_nr,
+ replace_sha1_access);
+}
+
+static int register_replace_object(struct replace_object *replace,
+ int ignore_dups)
+{
+ int pos = replace_object_pos(replace->original.hash);
+
+ if (0 <= pos) {
+ if (ignore_dups)
+ free(replace);
+ else {
+ free(replace_object[pos]);
+ replace_object[pos] = replace;
+ }
+ return 1;
+ }
+ pos = -pos - 1;
+ ALLOC_GROW(replace_object, replace_object_nr + 1, replace_object_alloc);
+ replace_object_nr++;
+ if (pos < replace_object_nr)
+ MOVE_ARRAY(replace_object + pos + 1, replace_object + pos,
+ replace_object_nr - pos - 1);
+ replace_object[pos] = replace;
+ return 0;
+}
+
+static int register_replace_ref(const char *refname,
+ const struct object_id *oid,
+ int flag, void *cb_data)
+{
+ /* Get sha1 from refname */
+ const char *slash = strrchr(refname, '/');
+ const char *hash = slash ? slash + 1 : refname;
+ struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
+
+ if (get_oid_hex(hash, &repl_obj->original)) {
+ free(repl_obj);
+ warning("bad replace ref name: %s", refname);
+ return 0;
+ }
+
+ /* Copy sha1 from the read ref */
+ oidcpy(&repl_obj->replacement, oid);
+
+ /* Register new object */
+ if (register_replace_object(repl_obj, 1))
+ die("duplicate replace ref: %s", refname);
+
+ return 0;
+}
+
+static void prepare_replace_object(void)
+{
+ static int replace_object_prepared;
+
+ if (replace_object_prepared)
+ return;
+
+ for_each_replace_ref(register_replace_ref, NULL);
+ replace_object_prepared = 1;
+ if (!replace_object_nr)
+ check_replace_refs = 0;
+}
+
+/* We allow "recursive" replacement. Only within reason, though */
+#define MAXREPLACEDEPTH 5
+
+/*
+ * If a replacement for object oid has been set up, return the
+ * replacement object's name (replaced recursively, if necessary).
+ * The return value is either oid or a pointer to a
+ * permanently-allocated value. This function always respects replace
+ * references, regardless of the value of check_replace_refs.
+ */
+const struct object_id *do_lookup_replace_object(const struct object_id *oid)
+{
+ int pos, depth = MAXREPLACEDEPTH;
+ const struct object_id *cur = oid;
+
+ prepare_replace_object();
+
+ /* Try to recursively replace the object */
+ do {
+ if (--depth < 0)
+ die("replace depth too high for object %s",
+ oid_to_hex(oid));
+
+ pos = replace_object_pos(cur->hash);
+ if (0 <= pos)
+ cur = &replace_object[pos]->replacement;
+ } while (0 <= pos);
+
+ return cur;
+}