diff options
author | Junio C Hamano <gitster@pobox.com> | 2011-05-31 10:57:32 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2011-05-31 10:57:32 -0700 |
commit | 2d11f21c365821ccba1e093f22b99ad71b955f21 (patch) | |
tree | 1ecbe232f12904520838ab4adff6aa70d5ba6e80 /replace_object.c | |
parent | 28b9264dd6cbadcef8b3e48c24ffcb2893b668b3 (diff) | |
parent | 5b42477b59886a85d4b49a60313f9b9d4a0d576f (diff) | |
download | git-2d11f21c365821ccba1e093f22b99ad71b955f21.tar.gz |
Merge remote-tracking branch 'ko/maint' into jc/diff-index-quick-exit-early
* ko/maint: (4352 commits)
git-submodule.sh: separate parens by a space to avoid confusing some shells
Documentation/technical/api-diff.txt: correct name of diff_unmerge()
read_gitfile_gently: use ssize_t to hold read result
remove tests of always-false condition
rerere.c: diagnose a corrupt MERGE_RR when hitting EOF between TAB and '\0'
Git 1.7.5.3
init/clone: remove short option -L and document --separate-git-dir
do not read beyond end of malloc'd buffer
git-svn: Fix git svn log --show-commit
Git 1.7.5.2
provide a copy of the LGPLv2.1
test core.gitproxy configuration
copy_gecos: fix not adding nlen to len when processing "&"
Update draft release notes to 1.7.5.2
Documentation/git-fsck.txt: fix typo: unreadable -> unreachable
send-pack: avoid deadlock on git:// push with failed pack-objects
connect: let callers know if connection is a socket
connect: treat generic proxy processes like ssh processes
sideband_demux(): fix decl-after-stmt
t3503: test cherry picking and reverting root commits
...
Conflicts:
diff.c
Diffstat (limited to 'replace_object.c')
-rw-r--r-- | replace_object.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/replace_object.c b/replace_object.c new file mode 100644 index 0000000000..7c6c7544ad --- /dev/null +++ b/replace_object.c @@ -0,0 +1,115 @@ +#include "cache.h" +#include "sha1-lookup.h" +#include "refs.h" +#include "commit.h" + +static struct replace_object { + unsigned char sha1[2][20]; +} **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]->sha1[0]; +} + +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->sha1[0]); + + if (0 <= pos) { + if (ignore_dups) + free(replace); + else { + free(replace_object[pos]); + replace_object[pos] = replace; + } + return 1; + } + pos = -pos - 1; + if (replace_object_alloc <= ++replace_object_nr) { + replace_object_alloc = alloc_nr(replace_object_alloc); + replace_object = xrealloc(replace_object, + sizeof(*replace_object) * + replace_object_alloc); + } + if (pos < replace_object_nr) + memmove(replace_object + pos + 1, + replace_object + pos, + (replace_object_nr - pos - 1) * + sizeof(*replace_object)); + replace_object[pos] = replace; + return 0; +} + +static int register_replace_ref(const char *refname, + const unsigned char *sha1, + 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 (strlen(hash) != 40 || get_sha1_hex(hash, repl_obj->sha1[0])) { + free(repl_obj); + warning("bad replace ref name: %s", refname); + return 0; + } + + /* Copy sha1 from the read ref */ + hashcpy(repl_obj->sha1[1], sha1); + + /* 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; +} + +/* We allow "recursive" replacement. Only within reason, though */ +#define MAXREPLACEDEPTH 5 + +const unsigned char *lookup_replace_object(const unsigned char *sha1) +{ + int pos, depth = MAXREPLACEDEPTH; + const unsigned char *cur = sha1; + + if (!read_replace_refs) + return sha1; + + prepare_replace_object(); + + /* Try to recursively replace the object */ + do { + if (--depth < 0) + die("replace depth too high for object %s", + sha1_to_hex(sha1)); + + pos = replace_object_pos(cur); + if (0 <= pos) + cur = replace_object[pos]->sha1[1]; + } while (0 <= pos); + + return cur; +} |