From patchwork Mon Dec 6 00:36:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Neeraj Singh (WINDOWS-SFS)" X-Patchwork-Id: 12657483 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AFE6BC433F5 for ; Mon, 6 Dec 2021 00:36:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241732AbhLFAjl (ORCPT ); Sun, 5 Dec 2021 19:39:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54566 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229567AbhLFAjh (ORCPT ); Sun, 5 Dec 2021 19:39:37 -0500 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 07B3CC061751 for ; Sun, 5 Dec 2021 16:36:10 -0800 (PST) Received: by mail-wr1-x431.google.com with SMTP id v11so18821406wrw.10 for ; Sun, 05 Dec 2021 16:36:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=l/lrBGwDNIW3/tOARoA5pUzl7te/Ab3jRbNpD85IwE0=; b=Celid59d9j90FbFhoUsUDbE1LXSpFP84s3AXzlbl/3kEgq3bgbYaBSBW0ZxYujRgNY O5cQzz3qC7MKI5Ad06U87ZR6JW95PYITcPJcFm/c8OD323sahIv1VKbAcSDrE461DAN0 QpmEioKS+h58X/M2/Imact9vrDUMyV35C89KSwY0l/e5kX8QVTdDNqXBIzCd9XswAvRR hpGzAjyorTp3fDQpeaDLuaUqs+XJywH/46JhcpM0tq3YqiZbCid2X5cFMATSgbi80WkB ShgV+WIe+KIJ6t0u9Gzi/OdG8Ym9jNfr+oQUO8BFzYcC22jRf3jG9YIrq1p2ygQKyPsU areg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=l/lrBGwDNIW3/tOARoA5pUzl7te/Ab3jRbNpD85IwE0=; b=7ms/0GA4PJq3DCa8Va0SoEElAhUPc48Dtpc/LPIKATU1Dm02/HG0LU124eOe1eN1Pk FU9q5Zc66BZM99El4UZOpEf3WZwxMUS/PMRltmp7TnjmRnopTvljxaJmaPqLhuloiEn6 IJ501+W+dXMPNrVYPq8WxRDHNpFgUJz4OvJznS7RVOtqcJNB876jJFJTdtfSEDqzzZY3 4W5mEBab/ffTcXi6HXoIZWeVRPiwzpB08lZzXp1KDUEYt/JQNslILipESg+0eqO+65OM denncF8Uf4kHoLe/npNi6R7sVZMJ7IUKx7MgkTsEPzzdUde65+FkTBT90biPbGK9mYQJ TX8Q== X-Gm-Message-State: AOAM532WaH/ZFCFfNaHYZFiRRPBgKjOiS7fOoj+ROWhQmcrs7GgcTNIl sMn2r1+A1Ikd3NHTeVvQZmn2oK6JzvM= X-Google-Smtp-Source: ABdhPJyFtx8rpzYAwMgjOXb8R6jxjnt0l6WgRVGcO2c/MhjCqHqi9UU4yvNahcGQuNvp8cEUAvXdJw== X-Received: by 2002:adf:d1c1:: with SMTP id b1mr1781493wrd.296.1638750968182; Sun, 05 Dec 2021 16:36:08 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a10sm12226473wmq.27.2021.12.05.16.36.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 Dec 2021 16:36:07 -0800 (PST) Message-Id: <36c00613d9a6ad4fc768e15b9ec23f9af520338a.1638750965.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Mon, 06 Dec 2021 00:36:04 +0000 Subject: [PATCH v2 1/2] tmp-objdir: new API for creating temporary writable databases Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Neeraj Singh , "Neeraj K. Singh" , Neeraj Singh Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Neeraj Singh From: Neeraj Singh The tmp_objdir API provides the ability to create temporary object directories, but was designed with the goal of having subprocesses access these object stores, followed by the main process migrating objects from it to the main object store or just deleting it. The subprocesses would view it as their primary datastore and write to it. Here we add the tmp_objdir_replace_primary_odb function that replaces the current process's writable "main" object directory with the specified one. The previous main object directory is restored in either tmp_objdir_migrate or tmp_objdir_destroy. For the --remerge-diff usecase, add a new `will_destroy` flag in `struct object_database` to mark ephemeral object databases that do not require fsync durability. Add 'git prune' support for removing temporary object databases, and make sure that they have a name starting with tmp_ and containing an operation-specific name. Based-on-patch-by: Elijah Newren Signed-off-by: Neeraj Singh Signed-off-by: Junio C Hamano --- builtin/prune.c | 20 ++++++++++++--- builtin/receive-pack.c | 2 +- environment.c | 5 ++++ object-file.c | 44 +++++++++++++++++++++++++++++++-- object-store.h | 19 +++++++++++++++ object.c | 2 +- tmp-objdir.c | 55 +++++++++++++++++++++++++++++++++++++++--- tmp-objdir.h | 29 +++++++++++++++++++--- 8 files changed, 162 insertions(+), 14 deletions(-) diff --git a/builtin/prune.c b/builtin/prune.c index 485c9a3c56f..c2bcdc07db4 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -26,10 +26,22 @@ static int prune_tmp_file(const char *fullpath) return error("Could not stat '%s'", fullpath); if (st.st_mtime > expire) return 0; - if (show_only || verbose) - printf("Removing stale temporary file %s\n", fullpath); - if (!show_only) - unlink_or_warn(fullpath); + if (S_ISDIR(st.st_mode)) { + if (show_only || verbose) + printf("Removing stale temporary directory %s\n", fullpath); + if (!show_only) { + struct strbuf remove_dir_buf = STRBUF_INIT; + + strbuf_addstr(&remove_dir_buf, fullpath); + remove_dir_recursively(&remove_dir_buf, 0); + strbuf_release(&remove_dir_buf); + } + } else { + if (show_only || verbose) + printf("Removing stale temporary file %s\n", fullpath); + if (!show_only) + unlink_or_warn(fullpath); + } return 0; } diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 49b846d9605..8815e24cde5 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -2213,7 +2213,7 @@ static const char *unpack(int err_fd, struct shallow_info *si) strvec_push(&child.args, alt_shallow_file); } - tmp_objdir = tmp_objdir_create(); + tmp_objdir = tmp_objdir_create("incoming"); if (!tmp_objdir) { if (err_fd > 0) close(err_fd); diff --git a/environment.c b/environment.c index 9da7f3c1a19..342400fcaad 100644 --- a/environment.c +++ b/environment.c @@ -17,6 +17,7 @@ #include "commit.h" #include "strvec.h" #include "object-store.h" +#include "tmp-objdir.h" #include "chdir-notify.h" #include "shallow.h" @@ -331,10 +332,14 @@ static void update_relative_gitdir(const char *name, void *data) { char *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir()); + struct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb(); trace_printf_key(&trace_setup_key, "setup: move $GIT_DIR to '%s'", path); + set_git_dir_1(path); + if (tmp_objdir) + tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd); free(path); } diff --git a/object-file.c b/object-file.c index c3d866a287e..0b6a61aeaff 100644 --- a/object-file.c +++ b/object-file.c @@ -683,6 +683,43 @@ void add_to_alternates_memory(const char *reference) '\n', NULL, 0); } +struct object_directory *set_temporary_primary_odb(const char *dir, int will_destroy) +{ + struct object_directory *new_odb; + + /* + * Make sure alternates are initialized, or else our entry may be + * overwritten when they are. + */ + prepare_alt_odb(the_repository); + + /* + * Make a new primary odb and link the old primary ODB in as an + * alternate + */ + new_odb = xcalloc(1, sizeof(*new_odb)); + new_odb->path = xstrdup(dir); + new_odb->will_destroy = will_destroy; + new_odb->next = the_repository->objects->odb; + the_repository->objects->odb = new_odb; + return new_odb->next; +} + +void restore_primary_odb(struct object_directory *restore_odb, const char *old_path) +{ + struct object_directory *cur_odb = the_repository->objects->odb; + + if (strcmp(old_path, cur_odb->path)) + BUG("expected %s as primary object store; found %s", + old_path, cur_odb->path); + + if (cur_odb->next != restore_odb) + BUG("we expect the old primary object store to be the first alternate"); + + the_repository->objects->odb = restore_odb; + free_object_directory(cur_odb); +} + /* * Compute the exact path an alternate is at and returns it. In case of * error NULL is returned and the human readable error is added to `err` @@ -1809,8 +1846,11 @@ int hash_object_file(const struct git_hash_algo *algo, const void *buf, /* Finalize a file on disk, and close it. */ static void close_loose_object(int fd) { - if (fsync_object_files) - fsync_or_die(fd, "loose object file"); + if (!the_repository->objects->odb->will_destroy) { + if (fsync_object_files) + fsync_or_die(fd, "loose object file"); + } + if (close(fd) != 0) die_errno(_("error when closing loose object file")); } diff --git a/object-store.h b/object-store.h index 952efb6a4be..82cf13f1054 100644 --- a/object-store.h +++ b/object-store.h @@ -27,6 +27,11 @@ struct object_directory { uint32_t loose_objects_subdir_seen[8]; /* 256 bits */ struct oidtree *loose_objects_cache; + /* + * This object store is ephemeral, so there is no need to fsync. + */ + unsigned int will_destroy : 1; + /* * Path to the alternative object store. If this is a relative path, * it is relative to the current working directory. @@ -58,6 +63,17 @@ void add_to_alternates_file(const char *dir); */ void add_to_alternates_memory(const char *dir); +/* + * Replace the current writable object directory with the specified temporary + * object directory; returns the former primary object directory. + */ +struct object_directory *set_temporary_primary_odb(const char *dir, int will_destroy); + +/* + * Restore a previous ODB replaced by set_temporary_main_odb. + */ +void restore_primary_odb(struct object_directory *restore_odb, const char *old_path); + /* * Populate and return the loose object cache array corresponding to the * given object ID. @@ -68,6 +84,9 @@ struct oidtree *odb_loose_cache(struct object_directory *odb, /* Empty the loose object cache for the specified object directory. */ void odb_clear_loose_cache(struct object_directory *odb); +/* Clear and free the specified object directory */ +void free_object_directory(struct object_directory *odb); + struct packed_git { struct hashmap_entry packmap_ent; struct packed_git *next; diff --git a/object.c b/object.c index 23a24e678a8..048f96a260e 100644 --- a/object.c +++ b/object.c @@ -513,7 +513,7 @@ struct raw_object_store *raw_object_store_new(void) return o; } -static void free_object_directory(struct object_directory *odb) +void free_object_directory(struct object_directory *odb) { free(odb->path); odb_clear_loose_cache(odb); diff --git a/tmp-objdir.c b/tmp-objdir.c index b8d880e3626..3d38eeab66b 100644 --- a/tmp-objdir.c +++ b/tmp-objdir.c @@ -1,5 +1,6 @@ #include "cache.h" #include "tmp-objdir.h" +#include "chdir-notify.h" #include "dir.h" #include "sigchain.h" #include "string-list.h" @@ -11,6 +12,8 @@ struct tmp_objdir { struct strbuf path; struct strvec env; + struct object_directory *prev_odb; + int will_destroy; }; /* @@ -38,6 +41,9 @@ static int tmp_objdir_destroy_1(struct tmp_objdir *t, int on_signal) if (t == the_tmp_objdir) the_tmp_objdir = NULL; + if (!on_signal && t->prev_odb) + restore_primary_odb(t->prev_odb, t->path.buf); + /* * This may use malloc via strbuf_grow(), but we should * have pre-grown t->path sufficiently so that this @@ -52,6 +58,7 @@ static int tmp_objdir_destroy_1(struct tmp_objdir *t, int on_signal) */ if (!on_signal) tmp_objdir_free(t); + return err; } @@ -121,7 +128,7 @@ static int setup_tmp_objdir(const char *root) return ret; } -struct tmp_objdir *tmp_objdir_create(void) +struct tmp_objdir *tmp_objdir_create(const char *prefix) { static int installed_handlers; struct tmp_objdir *t; @@ -129,11 +136,16 @@ struct tmp_objdir *tmp_objdir_create(void) if (the_tmp_objdir) BUG("only one tmp_objdir can be used at a time"); - t = xmalloc(sizeof(*t)); + t = xcalloc(1, sizeof(*t)); strbuf_init(&t->path, 0); strvec_init(&t->env); - strbuf_addf(&t->path, "%s/incoming-XXXXXX", get_object_directory()); + /* + * Use a string starting with tmp_ so that the builtin/prune.c code + * can recognize any stale objdirs left behind by a crash and delete + * them. + */ + strbuf_addf(&t->path, "%s/tmp_objdir-%s-XXXXXX", get_object_directory(), prefix); /* * Grow the strbuf beyond any filename we expect to be placed in it. @@ -269,6 +281,13 @@ int tmp_objdir_migrate(struct tmp_objdir *t) if (!t) return 0; + if (t->prev_odb) { + if (the_repository->objects->odb->will_destroy) + BUG("migrating an ODB that was marked for destruction"); + restore_primary_odb(t->prev_odb, t->path.buf); + t->prev_odb = NULL; + } + strbuf_addbuf(&src, &t->path); strbuf_addstr(&dst, get_object_directory()); @@ -292,3 +311,33 @@ void tmp_objdir_add_as_alternate(const struct tmp_objdir *t) { add_to_alternates_memory(t->path.buf); } + +void tmp_objdir_replace_primary_odb(struct tmp_objdir *t, int will_destroy) +{ + if (t->prev_odb) + BUG("the primary object database is already replaced"); + t->prev_odb = set_temporary_primary_odb(t->path.buf, will_destroy); + t->will_destroy = will_destroy; +} + +struct tmp_objdir *tmp_objdir_unapply_primary_odb(void) +{ + if (!the_tmp_objdir || !the_tmp_objdir->prev_odb) + return NULL; + + restore_primary_odb(the_tmp_objdir->prev_odb, the_tmp_objdir->path.buf); + the_tmp_objdir->prev_odb = NULL; + return the_tmp_objdir; +} + +void tmp_objdir_reapply_primary_odb(struct tmp_objdir *t, const char *old_cwd, + const char *new_cwd) +{ + char *path; + + path = reparent_relative_path(old_cwd, new_cwd, t->path.buf); + strbuf_reset(&t->path); + strbuf_addstr(&t->path, path); + free(path); + tmp_objdir_replace_primary_odb(t, t->will_destroy); +} diff --git a/tmp-objdir.h b/tmp-objdir.h index b1e45b4c75d..a3145051f25 100644 --- a/tmp-objdir.h +++ b/tmp-objdir.h @@ -10,7 +10,7 @@ * * Example: * - * struct tmp_objdir *t = tmp_objdir_create(); + * struct tmp_objdir *t = tmp_objdir_create("incoming"); * if (!run_command_v_opt_cd_env(cmd, 0, NULL, tmp_objdir_env(t)) && * !tmp_objdir_migrate(t)) * printf("success!\n"); @@ -22,9 +22,10 @@ struct tmp_objdir; /* - * Create a new temporary object directory; returns NULL on failure. + * Create a new temporary object directory with the specified prefix; + * returns NULL on failure. */ -struct tmp_objdir *tmp_objdir_create(void); +struct tmp_objdir *tmp_objdir_create(const char *prefix); /* * Return a list of environment strings, suitable for use with @@ -51,4 +52,26 @@ int tmp_objdir_destroy(struct tmp_objdir *); */ void tmp_objdir_add_as_alternate(const struct tmp_objdir *); +/* + * Replaces the main object store in the current process with the temporary + * object directory and makes the former main object store an alternate. + * If will_destroy is nonzero, the object directory may not be migrated. + */ +void tmp_objdir_replace_primary_odb(struct tmp_objdir *, int will_destroy); + +/* + * If the primary object database was replaced by a temporary object directory, + * restore it to its original value while keeping the directory contents around. + * Returns NULL if the primary object database was not replaced. + */ +struct tmp_objdir *tmp_objdir_unapply_primary_odb(void); + +/* + * Reapplies the former primary temporary object database, after protentially + * changing its relative path. + */ +void tmp_objdir_reapply_primary_odb(struct tmp_objdir *, const char *old_cwd, + const char *new_cwd); + + #endif /* TMP_OBJDIR_H */ From patchwork Mon Dec 6 00:36:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Neeraj Singh (WINDOWS-SFS)" X-Patchwork-Id: 12657481 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A719C433FE for ; Mon, 6 Dec 2021 00:36:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241737AbhLFAjm (ORCPT ); Sun, 5 Dec 2021 19:39:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54568 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241692AbhLFAji (ORCPT ); Sun, 5 Dec 2021 19:39:38 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C29D2C061751 for ; Sun, 5 Dec 2021 16:36:10 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id q3so18855066wru.5 for ; Sun, 05 Dec 2021 16:36:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=aBUPWg290Pm6pLig53PzPZ68pgytiSx64oEFtcO6jpE=; b=d18OLtfX1itzd419OF6lpeO5lw5weeijweztlVCT4M6ePSqujpSgLMHkmoRFEjpRW2 hhEPgWfPc2E2aOXU5ZIG6rilqYhQYKgoeO+Cc8+0XbjfyLiVLgW1lknoFrsLEVlBWkPy Rx5BZBphe52JQzOWpGPPnz1CwfPNbc9COmOmZNXLVoEojohjAPk2MpDkiQQY82iZjsrt uVeY5ITzqIGTDDNNA2Fmo4JE3rixawASjK9ZsL6js70WSJW0qZt/Dk4T5Nq6hrVYMM2L 2DyZK/D0LIXOSp72Cw4zdM5PwqCl+A7V+uoUD50yqBDfV2GRO8SZ4EHf4oDvRIzscNE2 SqDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=aBUPWg290Pm6pLig53PzPZ68pgytiSx64oEFtcO6jpE=; b=zFt3QE60GSKQjU6pLPXNHg2OPB/3CuSKS2RQxuoKWkOPvi9+ox/aUiFWZi7QQ4RKxa wL39HVuzY96kfWFGLeK1zmbFVux29FV2K0XDnBQJtsRyp+/rx0WlCNvMKnWaxPT+0JZ5 zrVdA5CZWtztq3YFcwvd2OlZtNDeGlnhMsAz4JlbLdLfShHjZhVREjA02eENKknhaA0E /s8g3FHhe92k05M1aGcLvJmWXXc4HJDlZtgk9qsfmUnYtBT0CGRWAI8z/WAnv8QRV3fB NrqT4L06Erd1ideRdeJpc2ATDdOmH12fLA7D0rCFPsi+hv6iG+D2Q7/5e6CkcZmMnzlv PEMA== X-Gm-Message-State: AOAM532SphTTopIpYVxYwu9sjOSyl+0QZgEy9zsbGybdqZWwnTvRWwGy Sr+H6mIyhVeGfBx7R6DIbmyYBgw7Ibs= X-Google-Smtp-Source: ABdhPJzn9D2FFkYUOdLHFxCMufxUhPgPJ/vnfKMh3wCkVvc73kx0nYCZx1Pahvkv6CBsUcv8GTdObw== X-Received: by 2002:a5d:6d88:: with SMTP id l8mr39086901wrs.270.1638750968992; Sun, 05 Dec 2021 16:36:08 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id d7sm9444232wrw.87.2021.12.05.16.36.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 Dec 2021 16:36:08 -0800 (PST) Message-Id: In-Reply-To: References: Date: Mon, 06 Dec 2021 00:36:05 +0000 Subject: [PATCH v2 2/2] tmp-objdir: disable ref updates when replacing the primary odb Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Neeraj Singh , "Neeraj K. Singh" , Neeraj Singh Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Neeraj Singh From: Neeraj Singh When creating a subprocess with a temporary ODB, we set the GIT_QUARANTINE_ENVIRONMENT env var to tell child Git processes not to update refs, since the tmp-objdir may go away. Introduce a similar mechanism for in-process temporary ODBs when we call tmp_objdir_replace_primary_odb. Now both mechanisms set the disable_ref_updates flag on the odb, which is queried by the ref_transaction_prepare function. Note: This change adds an assumption that the state of the_repository is relevant for any ref transaction that might be initiated. Unwinding this assumption should be straightforward by saving the relevant repository to query in the transaction or the ref_store. Peff's test case was invoking ref updates via the cachetextconv setting. That particular code silently does nothing when a ref update is forbidden. See the call to notes_cache_put in fill_textconv where errors are ignored. Reported-by: Jeff King Signed-off-by: Neeraj Singh Signed-off-by: Junio C Hamano --- environment.c | 4 ++++ object-file.c | 6 ++++++ object-store.h | 7 +++++++ refs.c | 2 +- repository.c | 2 ++ repository.h | 1 + 6 files changed, 21 insertions(+), 1 deletion(-) diff --git a/environment.c b/environment.c index 342400fcaad..2701dfeeec8 100644 --- a/environment.c +++ b/environment.c @@ -169,6 +169,10 @@ void setup_git_env(const char *git_dir) args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT); args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT); args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT); + if (getenv(GIT_QUARANTINE_ENVIRONMENT)) { + args.disable_ref_updates = 1; + } + repo_set_gitdir(the_repository, git_dir, &args); strvec_clear(&to_free); diff --git a/object-file.c b/object-file.c index 0b6a61aeaff..659ef7623ff 100644 --- a/object-file.c +++ b/object-file.c @@ -699,6 +699,12 @@ struct object_directory *set_temporary_primary_odb(const char *dir, int will_des */ new_odb = xcalloc(1, sizeof(*new_odb)); new_odb->path = xstrdup(dir); + + /* + * Disable ref updates while a temporary odb is active, since + * the objects in the database may roll back. + */ + new_odb->disable_ref_updates = 1; new_odb->will_destroy = will_destroy; new_odb->next = the_repository->objects->odb; the_repository->objects->odb = new_odb; diff --git a/object-store.h b/object-store.h index 82cf13f1054..9ae9262c340 100644 --- a/object-store.h +++ b/object-store.h @@ -27,6 +27,13 @@ struct object_directory { uint32_t loose_objects_subdir_seen[8]; /* 256 bits */ struct oidtree *loose_objects_cache; + /* + * This is a temporary object store created by the tmp_objdir + * facility. Disable ref updates since the objects in the store + * might be discarded on rollback. + */ + unsigned int disable_ref_updates : 1; + /* * This object store is ephemeral, so there is no need to fsync. */ diff --git a/refs.c b/refs.c index d7cc0a23a3b..ac744e85f5f 100644 --- a/refs.c +++ b/refs.c @@ -2137,7 +2137,7 @@ int ref_transaction_prepare(struct ref_transaction *transaction, break; } - if (getenv(GIT_QUARANTINE_ENVIRONMENT)) { + if (refs->repo->objects->odb->disable_ref_updates) { strbuf_addstr(err, _("ref updates forbidden inside quarantine environment")); return -1; diff --git a/repository.c b/repository.c index c5b90ba93ea..dce8e35ac20 100644 --- a/repository.c +++ b/repository.c @@ -80,6 +80,8 @@ void repo_set_gitdir(struct repository *repo, expand_base_dir(&repo->objects->odb->path, o->object_dir, repo->commondir, "objects"); + repo->objects->odb->disable_ref_updates = o->disable_ref_updates; + free(repo->objects->alternate_db); repo->objects->alternate_db = xstrdup_or_null(o->alternate_db); expand_base_dir(&repo->graft_file, o->graft_file, diff --git a/repository.h b/repository.h index a057653981c..7c04e99ac5c 100644 --- a/repository.h +++ b/repository.h @@ -158,6 +158,7 @@ struct set_gitdir_args { const char *graft_file; const char *index_file; const char *alternate_db; + int disable_ref_updates; }; void repo_set_gitdir(struct repository *repo, const char *root,