From: Junio C Hamano Date: Mon, 17 Oct 2016 20:25:20 +0000 (-0700) Subject: Merge branch 'jk/quarantine-received-objects' X-Git-Tag: v2.11.0-rc0~60 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/25ab004c53cdcfea485e5bf437aeaa74df47196d?ds=inline;hp=-c Merge branch 'jk/quarantine-received-objects' In order for the receiving end of "git push" to inspect the received history and decide to reject the push, the objects sent from the sending end need to be made available to the hook and the mechanism for the connectivity check, and this was done traditionally by storing the objects in the receiving repository and letting "git gc" to expire it. Instead, store the newly received objects in a temporary area, and make them available by reusing the alternate object store mechanism to them only while we decide if we accept the check, and once we decide, either migrate them to the repository or purge them immediately. * jk/quarantine-received-objects: tmp-objdir: do not migrate files starting with '.' tmp-objdir: put quarantine information in the environment receive-pack: quarantine objects until pre-receive accepts tmp-objdir: introduce API for temporary object directories check_connected: accept an env argument --- 25ab004c53cdcfea485e5bf437aeaa74df47196d diff --combined Makefile index d15bf8de9d,4e3becb498..9d6c245031 --- a/Makefile +++ b/Makefile @@@ -467,7 -467,6 +467,7 @@@ SPATCH = spatc export TCL_PATH TCLTK_PATH SPARSE_FLAGS = +SPATCH_FLAGS = --all-includes @@@ -832,6 -831,7 +832,7 @@@ LIB_OBJS += submodule-config. LIB_OBJS += symlinks.o LIB_OBJS += tag.o LIB_OBJS += tempfile.o + LIB_OBJS += tmp-objdir.o LIB_OBJS += trace.o LIB_OBJS += trailer.o LIB_OBJS += transport.o @@@ -2315,7 -2315,7 +2316,7 @@@ C_SOURCES = $(patsubst %.o,%.c,$(C_OBJ) %.cocci.patch: %.cocci $(C_SOURCES) @echo ' ' SPATCH $<; \ for f in $(C_SOURCES); do \ - $(SPATCH) --sp-file $< $$f; \ + $(SPATCH) --sp-file $< $$f $(SPATCH_FLAGS); \ done >$@ 2>$@.log; \ if test -s $@; \ then \ diff --combined builtin/receive-pack.c index f7cd180252,267d3204c2..04ed38e17d --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@@ -20,6 -20,7 +20,7 @@@ #include "gpg-interface.h" #include "sigchain.h" #include "fsck.h" + #include "tmp-objdir.h" static const char * const receive_pack_usage[] = { N_("git receive-pack "), @@@ -86,6 -87,8 +87,8 @@@ static enum } use_keepalive; static int keepalive_in_sec = 5; + static struct tmp_objdir *tmp_objdir; + static enum deny_action parse_deny_action(const char *var, const char *value) { if (value) { @@@ -268,10 -271,9 +271,10 @@@ static int show_ref_cb(const char *path return 0; } -static void show_one_alternate_sha1(const unsigned char sha1[20], void *unused) +static int show_one_alternate_sha1(const unsigned char sha1[20], void *unused) { show_ref(".have", sha1); + return 0; } static void collect_one_alternate_ref(const struct ref *ref, void *data) @@@ -664,6 -666,9 +667,9 @@@ static int run_and_feed_hook(const cha } else argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT"); + if (tmp_objdir) + argv_array_pushv(&proc.env_array, tmp_objdir_env(tmp_objdir)); + if (use_sideband) { memset(&muxer, 0, sizeof(muxer)); muxer.proc = copy_to_sideband; @@@ -763,6 -768,7 +769,7 @@@ static int run_update_hook(struct comma proc.stdout_to_stderr = 1; proc.err = use_sideband ? -1 : 0; proc.argv = argv; + proc.env = tmp_objdir_env(tmp_objdir); code = start_command(&proc); if (code) @@@ -834,6 -840,7 +841,7 @@@ static int update_shallow_ref(struct co !delayed_reachability_test(si, i)) sha1_array_append(&extra, si->shallow->sha1[i]); + opt.env = tmp_objdir_env(tmp_objdir); setup_alternate_shallow(&shallow_lock, &opt.shallow_file, &extra); if (check_connected(command_singleton_iterator, cmd, &opt)) { rollback_lock_file(&shallow_lock); @@@ -1241,12 -1248,17 +1249,17 @@@ static void set_connectivity_errors(str for (cmd = commands; cmd; cmd = cmd->next) { struct command *singleton = cmd; + struct check_connected_options opt = CHECK_CONNECTED_INIT; + if (shallow_update && si->shallow_ref[cmd->index]) /* to be checked in update_shallow_ref() */ continue; + + opt.env = tmp_objdir_env(tmp_objdir); if (!check_connected(command_singleton_iterator, &singleton, - NULL)) + &opt)) continue; + cmd->error_string = "missing necessary objects"; } } @@@ -1429,6 -1441,7 +1442,7 @@@ static void execute_commands(struct com data.si = si; opt.err_fd = err_fd; opt.progress = err_fd && !quiet; + opt.env = tmp_objdir_env(tmp_objdir); if (check_connected(iterate_receive_command_list, &data, &opt)) set_connectivity_errors(commands, si); @@@ -1445,6 -1458,19 +1459,19 @@@ return; } + /* + * Now we'll start writing out refs, which means the objects need + * to be in their final positions so that other processes can see them. + */ + if (tmp_objdir_migrate(tmp_objdir) < 0) { + for (cmd = commands; cmd; cmd = cmd->next) { + if (!cmd->error_string) + cmd->error_string = "unable to migrate objects to permanent storage"; + } + return; + } + tmp_objdir = NULL; + check_aliased_updates(commands); free(head_name_to_free); @@@ -1640,6 -1666,18 +1667,18 @@@ static const char *unpack(int err_fd, s argv_array_push(&child.args, alt_shallow_file); } + tmp_objdir = tmp_objdir_create(); + if (!tmp_objdir) + return "unable to create temporary object directory"; + child.env = tmp_objdir_env(tmp_objdir); + + /* + * Normally we just pass the tmp_objdir environment to the child + * processes that do the heavy lifting, but we may need to see these + * objects ourselves to set up shallow information. + */ + tmp_objdir_add_as_alternate(tmp_objdir); + if (ntohl(hdr.hdr_entries) < unpack_limit) { argv_array_pushl(&child.args, "unpack-objects", hdr_arg, NULL); if (quiet) diff --combined cache.h index 0dc39a998c,c898a1dd7d..05ecb889eb --- a/cache.h +++ b/cache.h @@@ -433,6 -433,7 +433,7 @@@ static inline enum object_type object_t #define GIT_GLOB_PATHSPECS_ENVIRONMENT "GIT_GLOB_PATHSPECS" #define GIT_NOGLOB_PATHSPECS_ENVIRONMENT "GIT_NOGLOB_PATHSPECS" #define GIT_ICASE_PATHSPECS_ENVIRONMENT "GIT_ICASE_PATHSPECS" + #define GIT_QUARANTINE_ENVIRONMENT "GIT_QUARANTINE_PATH" /* * This environment variable is expected to contain a boolean indicating @@@ -1206,11 -1207,6 +1207,11 @@@ struct object_context #define GET_SHA1_FOLLOW_SYMLINKS 0100 #define GET_SHA1_ONLY_TO_DIE 04000 +#define GET_SHA1_DISAMBIGUATORS \ + (GET_SHA1_COMMIT | GET_SHA1_COMMITTISH | \ + GET_SHA1_TREE | GET_SHA1_TREEISH | \ + GET_SHA1_BLOB) + extern int get_sha1(const char *str, unsigned char *sha1); extern int get_sha1_commit(const char *str, unsigned char *sha1); extern int get_sha1_committish(const char *str, unsigned char *sha1); @@@ -1225,8 -1221,6 +1226,8 @@@ extern int get_oid(const char *str, str typedef int each_abbrev_fn(const unsigned char *sha1, void *); extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *); +extern int set_disambiguate_hint_config(const char *var, const char *value); + /* * Try to read a SHA1 in hexadecimal format from the 40 characters * starting at hex. Write the 20-byte result to sha1 in binary form. @@@ -1632,15 -1626,7 +1633,15 @@@ struct object_info } packed; } u; }; + +/* + * Initializer for a "struct object_info" that wants no items. You may + * also memset() the memory to all-zeroes. + */ +#define OBJECT_INFO_INIT {NULL} + extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags); +extern int packed_object_info(struct packed_git *pack, off_t offset, struct object_info *); /* Dumb servers support */ extern int update_server_info(int);