From patchwork Fri Jan 31 00:28:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Taylor Blau X-Patchwork-Id: 11358985 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 690D513A4 for ; Fri, 31 Jan 2020 00:28:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 342C2214D8 for ; Fri, 31 Jan 2020 00:28:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=ttaylorr-com.20150623.gappssmtp.com header.i=@ttaylorr-com.20150623.gappssmtp.com header.b="aiPF88Mm" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727731AbgAaA2U (ORCPT ); Thu, 30 Jan 2020 19:28:20 -0500 Received: from mail-pj1-f67.google.com ([209.85.216.67]:35885 "EHLO mail-pj1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727380AbgAaA2T (ORCPT ); Thu, 30 Jan 2020 19:28:19 -0500 Received: by mail-pj1-f67.google.com with SMTP id gv17so2066724pjb.1 for ; Thu, 30 Jan 2020 16:28:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ttaylorr-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=2ce21gkx60g7pVhZdJZGurS9wpav/EZ6A5h6hNOk/X0=; b=aiPF88MmH2GyTe2LIDJbbkC8VNw3L7D4hwO42doKXt19VMwuZ0gQisxWYgDyKxcWK7 ejvfyGZHghX/wbRFb59ttRgUokzDC4yjWQZatogTCwloACYlUM2DZm3uxOCCN+22ZyMC Myj7GKYrmsyhcezPzirmbOFNc8j3FwLb7OB34DDAUHBpEmy0/98BvipkR2/FueX0X1Jz R+caej0Eg5IPxIDEQMmwAzgdH+SxoGlc7bUH8Ddb8dXbeq9SOqJWSHN+/ozF1wzsthv3 msLKoH/3baJ8tXHd12bQBsZeeaUzdR3qHGFeJ0H6M2STNtuGT7xmAP6Ca8v5ucIMavKY KCug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=2ce21gkx60g7pVhZdJZGurS9wpav/EZ6A5h6hNOk/X0=; b=LxBK+lwa1sAd4fuLOdqF9UEE0oO+0CiRedcc+DKDfnRfIRujsH+6fsPM49Lafjo+CU EHgW0+Rzu36MVsgJpZpBdB8/R4qa7GhUBvwD+aBGV8LPhAimlWQw76EtplS9+UC8dk4h 6sE5WexovxMjET3cCL8KKYnSWV079jSCrX/aYlhrBhYC5s3eHLFitzAwxvF0BeSkNmwT vzh9LD5JbA1IqwsUxx6PJWoJMhecTuny/yLBHEH+/gmJxnBtOp2olGgg/JsfeIFWqCQj RWeBtjL1aGEV6AkL5/tzfDJHO8qXAw6o8hRqau0snWdL1yISCYrAXj23Eb5+f5PspLVI VSJA== X-Gm-Message-State: APjAAAXn/BPusKGbulVfU+PWULdalSqbfQ/QWhmA0yq4fHjwb0QQh67B 3ZKFuycqmZfpGee60i5qUuzODxzifo4sKQ== X-Google-Smtp-Source: APXvYqz+ntadsEBm0xe6OBNwErMosOKQ0RXqRLGozLgJ5E7uDEuqU4e4RtgsSGGp3MNBULrjgu9AyA== X-Received: by 2002:a17:902:fe93:: with SMTP id x19mr7458283plm.155.1580430498442; Thu, 30 Jan 2020 16:28:18 -0800 (PST) Received: from localhost ([2601:602:9200:32b0:5c8f:7dac:47b8:95ff]) by smtp.gmail.com with ESMTPSA id c19sm8188178pfc.144.2020.01.30.16.28.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Jan 2020 16:28:18 -0800 (PST) Date: Thu, 30 Jan 2020 16:28:17 -0800 From: Taylor Blau To: git@vger.kernel.org Cc: peff@peff.net, dstolee@microsoft.com, gitster@pobox.com Subject: [PATCH 1/3] builtin/commit-graph.c: support '--split[=]' Message-ID: <4f5bc19903f8a1f5b153b5665de378e743e12744.1580430057.git.me@ttaylorr.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.11.4 (2019-03-13) Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org With '--split', the commit-graph machinery writes new commits in another incremental commit-graph which is part of the existing chain, and optionally decides to condense the chain into a single commit-graph. This is done to ensure that the aysmptotic behavior of looking up a commit in an incremental chain is dominated by the number of incrementals in that chain. It can be controlled by the '--max-commits' and '--size-multiple' options. On occasion, callers may want to ensure that 'git commit-graph write --split' always writes an incremental, and never spends effort condensing the incremental chain [1]. Previously, this was possible by passing '--size-multiple=0', but this no longer the case following 63020f175f (commit-graph: prefer default size_mult when given zero, 2020-01-02). Reintroduce a less-magical variant of the above with a new pair of arguments to '--split': '--split=no-merge' and '--split=merge-all'. When '--split=no-merge' is given, the commit-graph machinery will never condense an existing chain and will always write a new incremental. Conversely, if '--split=merge-all' is given, any invocation including it will always condense a chain if one exists. If '--split' is given with no arguments, it behaves as before and defers to '--size-multiple', and so on. [1]: This might occur when, for example, a server administrator running some program after each push may want to ensure that each job runs proportional in time to the size of the push, and does not "jump" when the commit-graph machinery decides to trigger a merge. Signed-off-by: Taylor Blau --- Documentation/git-commit-graph.txt | 18 +++++++++++----- builtin/commit-graph.c | 33 ++++++++++++++++++++++++++---- commit-graph.c | 19 +++++++++-------- commit-graph.h | 7 +++++++ t/t5324-split-commit-graph.sh | 25 ++++++++++++++++++++++ 5 files changed, 85 insertions(+), 17 deletions(-) diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.txt index 28d1fee505..8d61ba9f56 100644 --- a/Documentation/git-commit-graph.txt +++ b/Documentation/git-commit-graph.txt @@ -57,11 +57,19 @@ or `--stdin-packs`.) With the `--append` option, include all commits that are present in the existing commit-graph file. + -With the `--split` option, write the commit-graph as a chain of multiple -commit-graph files stored in `/info/commit-graphs`. The new commits -not already in the commit-graph are added in a new "tip" file. This file -is merged with the existing file if the following merge conditions are -met: +With the `--split[=]` option, write the commit-graph as a +chain of multiple commit-graph files stored in +`/info/commit-graphs`. Commit-graph layers are merged based on the +strategy and other splitting options. The new commits not already in the +commit-graph are added in a new "tip" file. This file is merged with the +existing file if the following merge conditions are met: +* If `--split=merge-always` is specified, then a merge is always +conducted, and the remaining options are ignored. Conversely, if +`--split=no-merge` is specified, a merge is never performed, and the +remaining options are ignored. A bare `--split` defers to the remaining +options. (Note that merging a chain of commit graphs replaces the +existing chain with a length-1 chain where the first and only +incremental holds the entire graph). + * If `--size-multiple=` is not specified, let `X` equal 2. If the new tip file would have `N` commits and the previous tip has `M` commits and diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index de321c71ad..f03b46d627 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -9,7 +9,9 @@ static char const * const builtin_commit_graph_usage[] = { N_("git commit-graph verify [--object-dir ] [--shallow] [--[no-]progress]"), - N_("git commit-graph write [--object-dir ] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] [--[no-]progress] "), + N_("git commit-graph write [--object-dir ] [--append] " + "[--split[=]] [--reachable|--stdin-packs|--stdin-commits] " + "[--[no-]progress] "), NULL }; @@ -19,7 +21,9 @@ static const char * const builtin_commit_graph_verify_usage[] = { }; static const char * const builtin_commit_graph_write_usage[] = { - N_("git commit-graph write [--object-dir ] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] [--[no-]progress] "), + N_("git commit-graph write [--object-dir ] [--append] " + "[--split[=]] [--reachable|--stdin-packs|--stdin-commits] " + "[--[no-]progress] "), NULL }; @@ -101,6 +105,25 @@ static int graph_verify(int argc, const char **argv) extern int read_replace_refs; static struct split_commit_graph_opts split_opts; +static int write_option_parse_split(const struct option *opt, const char *arg, + int unset) +{ + enum commit_graph_split_flags *flags = opt->value; + + opts.split = 1; + if (!arg) + return 0; + + if (!strcmp(arg, "merge-all")) + *flags = COMMIT_GRAPH_SPLIT_MERGE_REQUIRED; + else if (!strcmp(arg, "no-merge")) + *flags = COMMIT_GRAPH_SPLIT_MERGE_PROHIBITED; + else + die(_("unrecognized --split argument, %s"), arg); + + return 0; +} + static int graph_write(int argc, const char **argv) { struct string_list *pack_indexes = NULL; @@ -123,8 +146,10 @@ static int graph_write(int argc, const char **argv) OPT_BOOL(0, "append", &opts.append, N_("include all commits already in the commit-graph file")), OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")), - OPT_BOOL(0, "split", &opts.split, - N_("allow writing an incremental commit-graph file")), + OPT_CALLBACK_F(0, "split", &split_opts.flags, NULL, + N_("allow writing an incremental commit-graph file"), + PARSE_OPT_OPTARG | PARSE_OPT_NONEG, + write_option_parse_split), OPT_INTEGER(0, "max-commits", &split_opts.max_commits, N_("maximum number of commits in a non-base split commit-graph")), OPT_INTEGER(0, "size-multiple", &split_opts.size_multiple, diff --git a/commit-graph.c b/commit-graph.c index 6d34829f57..02e6ad9d1f 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -1565,15 +1565,18 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx) num_commits = ctx->commits.nr; ctx->num_commit_graphs_after = ctx->num_commit_graphs_before + 1; - while (g && (g->num_commits <= size_mult * num_commits || - (max_commits && num_commits > max_commits))) { - if (g->odb != ctx->odb) - break; + if (ctx->split_opts->flags != COMMIT_GRAPH_SPLIT_MERGE_PROHIBITED) { + while (g && (g->num_commits <= size_mult * num_commits || + (max_commits && num_commits > max_commits) || + (ctx->split_opts->flags == COMMIT_GRAPH_SPLIT_MERGE_REQUIRED))) { + if (g->odb != ctx->odb) + break; - num_commits += g->num_commits; - g = g->base_graph; + num_commits += g->num_commits; + g = g->base_graph; - ctx->num_commit_graphs_after--; + ctx->num_commit_graphs_after--; + } } ctx->new_base_graph = g; @@ -1881,7 +1884,7 @@ int write_commit_graph(struct object_directory *odb, goto cleanup; } - if (!ctx->commits.nr) + if (!ctx->commits.nr && (!ctx->split || ctx->split_opts->flags != COMMIT_GRAPH_SPLIT_MERGE_REQUIRED)) goto cleanup; if (ctx->split) { diff --git a/commit-graph.h b/commit-graph.h index 7d9fc9c16a..dadcc03808 100644 --- a/commit-graph.h +++ b/commit-graph.h @@ -84,10 +84,17 @@ enum commit_graph_write_flags { COMMIT_GRAPH_WRITE_CHECK_OIDS = (1 << 3) }; +enum commit_graph_split_flags { + COMMIT_GRAPH_SPLIT_UNSPECIFIED = 0, + COMMIT_GRAPH_SPLIT_MERGE_REQUIRED = 1, + COMMIT_GRAPH_SPLIT_MERGE_PROHIBITED = 2 +}; + struct split_commit_graph_opts { int size_multiple; int max_commits; timestamp_t expire_time; + enum commit_graph_split_flags flags; }; /* diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index c24823431f..a165b48afe 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -344,4 +344,29 @@ test_expect_success 'split across alternate where alternate is not split' ' test_cmp commit-graph .git/objects/info/commit-graph ' +test_expect_success '--split=merge-all always merges incrementals' ' + test_when_finished rm -rf a b c && + rm -rf $graphdir $infodir/commit-graph && + git reset --hard commits/10 && + git rev-list -3 HEAD~4 >a && + git rev-list -2 HEAD~2 >b && + git rev-list -2 HEAD >c && + git commit-graph write --split=no-merge --stdin-commits a && + git rev-list HEAD >b && + git commit-graph write --split --stdin-commits X-Patchwork-Id: 11358987 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BE3711398 for ; Fri, 31 Jan 2020 00:28:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7E766214D8 for ; Fri, 31 Jan 2020 00:28:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=ttaylorr-com.20150623.gappssmtp.com header.i=@ttaylorr-com.20150623.gappssmtp.com header.b="VTkhEaPN" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727739AbgAaA2W (ORCPT ); Thu, 30 Jan 2020 19:28:22 -0500 Received: from mail-pg1-f193.google.com ([209.85.215.193]:42267 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727380AbgAaA2V (ORCPT ); Thu, 30 Jan 2020 19:28:21 -0500 Received: by mail-pg1-f193.google.com with SMTP id s64so2504882pgb.9 for ; Thu, 30 Jan 2020 16:28:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ttaylorr-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=EVo7eNDEX8Qbmsi6sSdyfKrkD6MOuxr798kJYyE2VfI=; b=VTkhEaPNKWtJ1yyaqeVK1QCW9X1CnPWGgYZzNQtvS4fv3Vmbajg8q4SruEVULcYtY8 L+qNO7tQIundUbwcEmOSF5E5JEkgJWPVOo9Tr8s92bmTN6SfiEyuBznlaCm+gbWTXeN1 oYvcjUSQsEvxgVm2XxzjwC6qTEgmlFG/tPo8Z6yT8mCWLwrLDVBOceOWlZaX8+a8VSaN a8R9+HGuD+MvmfKAwXFGXrNumLkiZh0FgUpK16ahBBLnInWnnc8KJUeE0TvxDNUIznfP 2xreoQa5tZ9AUCpfbD4p1neqrwOIUU+MauXP/iaan9jGIvg+F1anIgKf38wutHyv2yRj WDFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=EVo7eNDEX8Qbmsi6sSdyfKrkD6MOuxr798kJYyE2VfI=; b=JU9n4a7oQVaVipPtkwgCp9Ih2YV2hkxdkYKySAnqnv53Y5173OAuNW9RyWUdBGUMsh vsGar2Yo2cr5vK+6kfFWpU2aUCU++Cb8jd0rQa6XJ8wX8vGU8T41rMiLcUbSFDqCQMV2 ByKnyeVh5zKy6ZyTjxPq678GqvjWKm/6L+7w0qNfHjkvG4a+Nuc6OziBK7NPGknW2QAW a6NdlmI6Z/eRRaxcgtb8E49/SIKdEGO1e0tFMYZ4fgc1XLU8GSFHYYMSnBvur/jIiedL Me/y8zj2BVH91a1sou77Yl5DdV5T1Mc6iCTrcsQUf7EnvWoEUHpeyxs5Knn78SS8nRgR lWXw== X-Gm-Message-State: APjAAAVtaadImHR5L9DnLCSpsNyphq0Ux/cfF4+EBXk/iloVqHLACkXD MT517pd5q0tlaZjRgjfIySr9tRInZKDgsA== X-Google-Smtp-Source: APXvYqyibBPcVbGvfkWsVO9Dj4F2nbDf9uPA736a8S/18DsmkDrW0ihrDVnkfSJ0+HhSkh9CRz2gFg== X-Received: by 2002:a63:3f4f:: with SMTP id m76mr7146538pga.353.1580430500386; Thu, 30 Jan 2020 16:28:20 -0800 (PST) Received: from localhost ([2601:602:9200:32b0:5c8f:7dac:47b8:95ff]) by smtp.gmail.com with ESMTPSA id m101sm7929491pje.13.2020.01.30.16.28.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Jan 2020 16:28:20 -0800 (PST) Date: Thu, 30 Jan 2020 16:28:19 -0800 From: Taylor Blau To: git@vger.kernel.org Cc: peff@peff.net, dstolee@microsoft.com, gitster@pobox.com Subject: [PATCH 2/3] builtin/commit-graph.c: introduce '--input=' Message-ID: <8effe35bcd1dadee3a29d996f269353cf6e4982d.1580430057.git.me@ttaylorr.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.11.4 (2019-03-13) Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The 'write' mode of the 'commit-graph' supports input from a number of different sources: pack indexes over stdin, commits over stdin, commits reachable from all references, and so on. Each of these options are specified with a unique option: '--stdin-packs', '--stdin-commits', etc. Similar to our replacement of 'git config [--]' with 'git config [--type=]' (c.f., fb0dc3bac1 (builtin/config.c: support `--type=` as preferred alias for `--`, 2018-04-18)), softly deprecate '[--]' in favor of '[--input=]'. This makes it more clear to implement new options that are combinations of other options (such as, for example, "none", a combination of the old "--append" and a new sentinel to specify to _not_ look in other packs, which we will implement in a future patch). Unfortunately, the new enumerated type is a bitfield, even though it makes much more sense as '0, 1, 2, ...'. Even though *almost* all options are pairwise exclusive, '--stdin-{packs,commits}' *is* compatible with '--append'. For this reason, use a bitfield. Signed-off-by: Taylor Blau --- Documentation/git-commit-graph.txt | 26 +++++----- builtin/commit-graph.c | 77 ++++++++++++++++++++++-------- t/t5318-commit-graph.sh | 46 +++++++++--------- t/t5324-split-commit-graph.sh | 44 ++++++++--------- 4 files changed, 114 insertions(+), 79 deletions(-) diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.txt index 8d61ba9f56..cbf80226e9 100644 --- a/Documentation/git-commit-graph.txt +++ b/Documentation/git-commit-graph.txt @@ -41,21 +41,21 @@ COMMANDS Write a commit-graph file based on the commits found in packfiles. + -With the `--stdin-packs` option, generate the new commit graph by +With the `--input=stdin-packs` option, generate the new commit graph by walking objects only in the specified pack-indexes. (Cannot be combined -with `--stdin-commits` or `--reachable`.) +with `--input=stdin-commits` or `--input=reachable`.) + -With the `--stdin-commits` option, generate the new commit graph by -walking commits starting at the commits specified in stdin as a list +With the `--input=stdin-commits` option, generate the new commit graph +by walking commits starting at the commits specified in stdin as a list of OIDs in hex, one OID per line. (Cannot be combined with -`--stdin-packs` or `--reachable`.) +`--input=stdin-packs` or `--input=reachable`.) + -With the `--reachable` option, generate the new commit graph by walking -commits starting at all refs. (Cannot be combined with `--stdin-commits` -or `--stdin-packs`.) +With the `--input=reachable` option, generate the new commit graph by +walking commits starting at all refs. (Cannot be combined with +`--input=stdin-commits` or `--input=stdin-packs`.) + -With the `--append` option, include all commits that are present in the -existing commit-graph file. +With the `--input=append` option, include all commits that are present +in the existing commit-graph file. + With the `--split[=]` option, write the commit-graph as a chain of multiple commit-graph files stored in @@ -107,20 +107,20 @@ $ git commit-graph write using commits in ``. + ------------------------------------------------ -$ echo | git commit-graph write --stdin-packs +$ echo | git commit-graph write --input=stdin-packs ------------------------------------------------ * Write a commit-graph file containing all reachable commits. + ------------------------------------------------ -$ git show-ref -s | git commit-graph write --stdin-commits +$ git show-ref -s | git commit-graph write --input=stdin-commits ------------------------------------------------ * Write a commit-graph file containing all commits in the current commit-graph file along with those reachable from `HEAD`. + ------------------------------------------------ -$ git rev-parse HEAD | git commit-graph write --stdin-commits --append +$ git rev-parse HEAD | git commit-graph write --input=stdin-commits --input=append ------------------------------------------------ diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index f03b46d627..03d815e652 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -10,7 +10,7 @@ static char const * const builtin_commit_graph_usage[] = { N_("git commit-graph verify [--object-dir ] [--shallow] [--[no-]progress]"), N_("git commit-graph write [--object-dir ] [--append] " - "[--split[=]] [--reachable|--stdin-packs|--stdin-commits] " + "[--split[=]] [--input=] " "[--[no-]progress] "), NULL }; @@ -22,22 +22,48 @@ static const char * const builtin_commit_graph_verify_usage[] = { static const char * const builtin_commit_graph_write_usage[] = { N_("git commit-graph write [--object-dir ] [--append] " - "[--split[=]] [--reachable|--stdin-packs|--stdin-commits] " + "[--split[=]] [--input=] " "[--[no-]progress] "), NULL }; +enum commit_graph_input { + COMMIT_GRAPH_INPUT_REACHABLE = (1 << 1), + COMMIT_GRAPH_INPUT_STDIN_PACKS = (1 << 2), + COMMIT_GRAPH_INPUT_STDIN_COMMITS = (1 << 3), + COMMIT_GRAPH_INPUT_APPEND = (1 << 4) +}; + static struct opts_commit_graph { const char *obj_dir; - int reachable; - int stdin_packs; - int stdin_commits; - int append; + enum commit_graph_input input; int split; int shallow; int progress; } opts; +static int option_parse_input(const struct option *opt, const char *arg, + int unset) +{ + enum commit_graph_input *to = opt->value; + if (unset || !strcmp(arg, "packs")) { + *to = 0; + return 0; + } + + if (!strcmp(arg, "reachable")) + *to |= COMMIT_GRAPH_INPUT_REACHABLE; + else if (!strcmp(arg, "stdin-packs")) + *to |= COMMIT_GRAPH_INPUT_STDIN_PACKS; + else if (!strcmp(arg, "stdin-commits")) + *to |= COMMIT_GRAPH_INPUT_STDIN_COMMITS; + else if (!strcmp(arg, "append")) + *to |= COMMIT_GRAPH_INPUT_APPEND; + else + die(_("unrecognized --input source, %s"), arg); + return 0; +} + static struct object_directory *find_odb_or_die(struct repository *r, const char *obj_dir) { @@ -137,14 +163,21 @@ static int graph_write(int argc, const char **argv) OPT_STRING(0, "object-dir", &opts.obj_dir, N_("dir"), N_("The object directory to store the graph")), - OPT_BOOL(0, "reachable", &opts.reachable, - N_("start walk at all refs")), - OPT_BOOL(0, "stdin-packs", &opts.stdin_packs, - N_("scan pack-indexes listed by stdin for commits")), - OPT_BOOL(0, "stdin-commits", &opts.stdin_commits, - N_("start walk at commits listed by stdin")), - OPT_BOOL(0, "append", &opts.append, - N_("include all commits already in the commit-graph file")), + OPT_CALLBACK(0, "input", &opts.input, NULL, + N_("include commits from this source in the graph"), + option_parse_input), + OPT_BIT(0, "reachable", &opts.input, + N_("start walk at all refs"), + COMMIT_GRAPH_INPUT_REACHABLE), + OPT_BIT(0, "stdin-packs", &opts.input, + N_("scan pack-indexes listed by stdin for commits"), + COMMIT_GRAPH_INPUT_STDIN_PACKS), + OPT_BIT(0, "stdin-commits", &opts.input, + N_("start walk at commits listed by stdin"), + COMMIT_GRAPH_INPUT_STDIN_COMMITS), + OPT_BIT(0, "append", &opts.input, + N_("include all commits already in the commit-graph file"), + COMMIT_GRAPH_INPUT_APPEND), OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")), OPT_CALLBACK_F(0, "split", &split_opts.flags, NULL, N_("allow writing an incremental commit-graph file"), @@ -170,11 +203,13 @@ static int graph_write(int argc, const char **argv) builtin_commit_graph_write_options, builtin_commit_graph_write_usage, 0); - if (opts.reachable + opts.stdin_packs + opts.stdin_commits > 1) - die(_("use at most one of --reachable, --stdin-commits, or --stdin-packs")); + if ((!!(opts.input & COMMIT_GRAPH_INPUT_REACHABLE) + + !!(opts.input & COMMIT_GRAPH_INPUT_STDIN_PACKS) + + !!(opts.input & COMMIT_GRAPH_INPUT_STDIN_COMMITS)) > 1) + die(_("use at most one of --input=reachable, --input=stdin-commits, or --input=stdin-packs")); if (!opts.obj_dir) opts.obj_dir = get_object_directory(); - if (opts.append) + if (opts.input & COMMIT_GRAPH_INPUT_APPEND) flags |= COMMIT_GRAPH_WRITE_APPEND; if (opts.split) flags |= COMMIT_GRAPH_WRITE_SPLIT; @@ -184,22 +219,22 @@ static int graph_write(int argc, const char **argv) read_replace_refs = 0; odb = find_odb_or_die(the_repository, opts.obj_dir); - if (opts.reachable) { + if (opts.input & COMMIT_GRAPH_INPUT_REACHABLE) { if (write_commit_graph_reachable(odb, flags, &split_opts)) return 1; return 0; } string_list_init(&lines, 0); - if (opts.stdin_packs || opts.stdin_commits) { + if (opts.input & (COMMIT_GRAPH_INPUT_STDIN_PACKS | COMMIT_GRAPH_INPUT_STDIN_COMMITS)) { struct strbuf buf = STRBUF_INIT; while (strbuf_getline(&buf, stdin) != EOF) string_list_append(&lines, strbuf_detach(&buf, NULL)); - if (opts.stdin_packs) + if (opts.input & COMMIT_GRAPH_INPUT_STDIN_PACKS) pack_indexes = &lines; - if (opts.stdin_commits) { + if (opts.input & COMMIT_GRAPH_INPUT_STDIN_COMMITS) { commit_hex = &lines; flags |= COMMIT_GRAPH_WRITE_CHECK_OIDS; } diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index 0bf98b56ec..6533724bc5 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -23,10 +23,10 @@ test_expect_success 'write graph with no packs' ' test_path_is_missing $objdir/info/commit-graph ' -test_expect_success 'exit with correct error on bad input to --stdin-packs' ' +test_expect_success 'exit with correct error on bad input to --input=stdin-packs' ' cd "$TRASH_DIRECTORY/full" && echo doesnotexist >in && - test_expect_code 1 git commit-graph write --stdin-packs stderr && + test_expect_code 1 git commit-graph write --input=stdin-packs stderr && test_i18ngrep "error adding pack" stderr ' @@ -40,12 +40,12 @@ test_expect_success 'create commits and repack' ' git repack ' -test_expect_success 'exit with correct error on bad input to --stdin-commits' ' +test_expect_success 'exit with correct error on bad input to --input=stdin-commits' ' cd "$TRASH_DIRECTORY/full" && - echo HEAD | test_expect_code 1 git commit-graph write --stdin-commits 2>stderr && + echo HEAD | test_expect_code 1 git commit-graph write --input=stdin-commits 2>stderr && test_i18ngrep "invalid commit object id" stderr && # valid tree OID, but not a commit OID - git rev-parse HEAD^{tree} | test_expect_code 1 git commit-graph write --stdin-commits 2>stderr && + git rev-parse HEAD^{tree} | test_expect_code 1 git commit-graph write --input=stdin-commits 2>stderr && test_i18ngrep "invalid commit object id" stderr ' @@ -227,7 +227,7 @@ graph_git_behavior 'cleared graph, commit 8 vs merge 2' full commits/8 merge/2 test_expect_success 'build graph from latest pack with closure' ' cd "$TRASH_DIRECTORY/full" && - cat new-idx | git commit-graph write --stdin-packs && + cat new-idx | git commit-graph write --input=stdin-packs && test_path_is_file $objdir/info/commit-graph && graph_read_expect "9" "extra_edges" ' @@ -240,7 +240,7 @@ test_expect_success 'build graph from commits with closure' ' git tag -a -m "merge" tag/merge merge/2 && git rev-parse tag/merge >commits-in && git rev-parse merge/1 >>commits-in && - cat commits-in | git commit-graph write --stdin-commits && + cat commits-in | git commit-graph write --input=stdin-commits && test_path_is_file $objdir/info/commit-graph && graph_read_expect "6" ' @@ -250,7 +250,7 @@ graph_git_behavior 'graph from commits, commit 8 vs merge 2' full commits/8 merg test_expect_success 'build graph from commits with append' ' cd "$TRASH_DIRECTORY/full" && - git rev-parse merge/3 | git commit-graph write --stdin-commits --append && + git rev-parse merge/3 | git commit-graph write --input=stdin-commits --input=append && test_path_is_file $objdir/info/commit-graph && graph_read_expect "10" "extra_edges" ' @@ -260,7 +260,7 @@ graph_git_behavior 'append graph, commit 8 vs merge 2' full commits/8 merge/2 test_expect_success 'build graph using --reachable' ' cd "$TRASH_DIRECTORY/full" && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_file $objdir/info/commit-graph && graph_read_expect "11" "extra_edges" ' @@ -301,14 +301,14 @@ test_expect_success 'perform fast-forward merge in full repo' ' test_expect_success 'check that gc computes commit-graph' ' cd "$TRASH_DIRECTORY/full" && git commit --allow-empty -m "blank" && - git commit-graph write --reachable && + git commit-graph write --input=reachable && cp $objdir/info/commit-graph commit-graph-before-gc && git reset --hard HEAD~1 && git config gc.writeCommitGraph true && git gc && cp $objdir/info/commit-graph commit-graph-after-gc && ! test_cmp_bin commit-graph-before-gc commit-graph-after-gc && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_cmp_bin commit-graph-after-gc $objdir/info/commit-graph ' @@ -318,18 +318,18 @@ test_expect_success 'replace-objects invalidates commit-graph' ' git clone full replace && ( cd replace && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_file .git/objects/info/commit-graph && git replace HEAD~1 HEAD~2 && git -c core.commitGraph=false log >expect && git -c core.commitGraph=true log >actual && test_cmp expect actual && - git commit-graph write --reachable && + git commit-graph write --input=reachable && git -c core.commitGraph=false --no-replace-objects log >expect && git -c core.commitGraph=true --no-replace-objects log >actual && test_cmp expect actual && rm -rf .git/objects/info/commit-graph && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_file .git/objects/info/commit-graph ) ' @@ -340,7 +340,7 @@ test_expect_success 'commit grafts invalidate commit-graph' ' git clone full graft && ( cd graft && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_file .git/objects/info/commit-graph && H1=$(git rev-parse --verify HEAD~1) && H3=$(git rev-parse --verify HEAD~3) && @@ -348,12 +348,12 @@ test_expect_success 'commit grafts invalidate commit-graph' ' git -c core.commitGraph=false log >expect && git -c core.commitGraph=true log >actual && test_cmp expect actual && - git commit-graph write --reachable && + git commit-graph write --input=reachable && git -c core.commitGraph=false --no-replace-objects log >expect && git -c core.commitGraph=true --no-replace-objects log >actual && test_cmp expect actual && rm -rf .git/objects/info/commit-graph && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_missing .git/objects/info/commit-graph ) ' @@ -364,10 +364,10 @@ test_expect_success 'replace-objects invalidates commit-graph' ' git clone --depth 2 "file://$TRASH_DIRECTORY/full" shallow && ( cd shallow && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_missing .git/objects/info/commit-graph && git fetch origin --unshallow && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_file .git/objects/info/commit-graph ) ' @@ -380,7 +380,7 @@ test_expect_success 'replace-objects invalidates commit-graph' ' test_expect_success 'git commit-graph verify' ' cd "$TRASH_DIRECTORY/full" && - git rev-parse commits/8 | git commit-graph write --stdin-commits && + git rev-parse commits/8 | git commit-graph write --input=stdin-commits && git commit-graph verify >output ' @@ -591,7 +591,7 @@ test_expect_success 'setup non-the_repository tests' ' test_commit -C repo two && git -C repo config core.commitGraph true && git -C repo rev-parse two | \ - git -C repo commit-graph write --stdin-commits + git -C repo commit-graph write --input=stdin-commits ' test_expect_success 'parse_commit_in_graph works for non-the_repository' ' @@ -637,7 +637,7 @@ test_expect_success 'corrupt commit-graph write (broken parent)' ' EOF broken="$(git hash-object -w -t commit --literally broken)" && git commit-tree -p "$broken" -m "good commit" "$empty" >good && - test_must_fail git commit-graph write --stdin-commits \ + test_must_fail git commit-graph write --input=stdin-commits \ test_err && test_i18ngrep "unable to parse commit" test_err ) @@ -658,7 +658,7 @@ test_expect_success 'corrupt commit-graph write (missing tree)' ' EOF broken="$(git hash-object -w -t commit --literally broken)" && git commit-tree -p "$broken" -m "good" "$tree" >good && - test_must_fail git commit-graph write --stdin-commits \ + test_must_fail git commit-graph write --input=stdin-commits \ test_err && test_i18ngrep "unable to parse commit" test_err ) diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index a165b48afe..dd74295885 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -35,7 +35,7 @@ test_expect_success 'create commits and write commit-graph' ' test_commit $i && git branch commits/$i || return 1 done && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_file $infodir/commit-graph && graph_read_expect 3 ' @@ -87,7 +87,7 @@ test_expect_success 'add more commits, and write a new base graph' ' git reset --hard commits/4 && git merge commits/6 && git branch merge/2 && - git commit-graph write --reachable && + git commit-graph write --input=reachable && graph_read_expect 12 ' @@ -99,7 +99,7 @@ test_expect_success 'fork and fail to base a chain on a commit-graph file' ' rm .git/objects/info/commit-graph && echo "$(pwd)/../.git/objects" >.git/objects/info/alternates && test_commit new-commit && - git commit-graph write --reachable --split && + git commit-graph write --input=reachable --split && test_path_is_file $graphdir/commit-graph-chain && test_line_count = 1 $graphdir/commit-graph-chain && verify_chain_files_exist $graphdir @@ -112,7 +112,7 @@ test_expect_success 'add three more commits, write a tip graph' ' git merge commits/5 && git merge merge/2 && git branch merge/3 && - git commit-graph write --reachable --split && + git commit-graph write --input=reachable --split && test_path_is_missing $infodir/commit-graph && test_path_is_file $graphdir/commit-graph-chain && ls $graphdir/graph-*.graph >graph-files && @@ -125,7 +125,7 @@ graph_git_behavior 'split commit-graph: merge 3 vs 2' merge/3 merge/2 test_expect_success 'add one commit, write a tip graph' ' test_commit 11 && git branch commits/11 && - git commit-graph write --reachable --split && + git commit-graph write --input=reachable --split && test_path_is_missing $infodir/commit-graph && test_path_is_file $graphdir/commit-graph-chain && ls $graphdir/graph-*.graph >graph-files && @@ -138,7 +138,7 @@ graph_git_behavior 'three-layer commit-graph: commit 11 vs 6' commits/11 commits test_expect_success 'add one commit, write a merged graph' ' test_commit 12 && git branch commits/12 && - git commit-graph write --reachable --split && + git commit-graph write --input=reachable --split && test_path_is_file $graphdir/commit-graph-chain && test_line_count = 2 $graphdir/commit-graph-chain && ls $graphdir/graph-*.graph >graph-files && @@ -157,7 +157,7 @@ test_expect_success 'create fork and chain across alternate' ' echo "$(pwd)/../.git/objects" >.git/objects/info/alternates && test_commit 13 && git branch commits/13 && - git commit-graph write --reachable --split && + git commit-graph write --input=reachable --split && test_path_is_file $graphdir/commit-graph-chain && test_line_count = 3 $graphdir/commit-graph-chain && ls $graphdir/graph-*.graph >graph-files && @@ -166,7 +166,7 @@ test_expect_success 'create fork and chain across alternate' ' git -c core.commitGraph=false rev-list HEAD >actual && test_cmp expect actual && test_commit 14 && - git commit-graph write --reachable --split --object-dir=.git/objects/ && + git commit-graph write --input=reachable --split --object-dir=.git/objects/ && test_line_count = 3 $graphdir/commit-graph-chain && ls $graphdir/graph-*.graph >graph-files && test_line_count = 1 graph-files @@ -182,7 +182,7 @@ test_expect_success 'test merge stragety constants' ' git config core.commitGraph true && test_line_count = 2 $graphdir/commit-graph-chain && test_commit 14 && - git commit-graph write --reachable --split --size-multiple=2 && + git commit-graph write --input=reachable --split --size-multiple=2 && test_line_count = 3 $graphdir/commit-graph-chain ) && @@ -192,7 +192,7 @@ test_expect_success 'test merge stragety constants' ' git config core.commitGraph true && test_line_count = 2 $graphdir/commit-graph-chain && test_commit 14 && - git commit-graph write --reachable --split --size-multiple=10 && + git commit-graph write --input=reachable --split --size-multiple=10 && test_line_count = 1 $graphdir/commit-graph-chain && ls $graphdir/graph-*.graph >graph-files && test_line_count = 1 graph-files @@ -203,7 +203,7 @@ test_expect_success 'test merge stragety constants' ' git config core.commitGraph true && test_line_count = 2 $graphdir/commit-graph-chain && test_commit 15 && - git commit-graph write --reachable --split --size-multiple=10 --expire-time=1980-01-01 && + git commit-graph write --input=reachable --split --size-multiple=10 --expire-time=1980-01-01 && test_line_count = 1 $graphdir/commit-graph-chain && ls $graphdir/graph-*.graph >graph-files && test_line_count = 3 graph-files @@ -215,7 +215,7 @@ test_expect_success 'test merge stragety constants' ' test_line_count = 2 $graphdir/commit-graph-chain && test_commit 16 && test_commit 17 && - git commit-graph write --reachable --split --max-commits=1 && + git commit-graph write --input=reachable --split --max-commits=1 && test_line_count = 1 $graphdir/commit-graph-chain && ls $graphdir/graph-*.graph >graph-files && test_line_count = 1 graph-files @@ -227,7 +227,7 @@ test_expect_success 'remove commit-graph-chain file after flattening' ' ( cd flatten && test_line_count = 2 $graphdir/commit-graph-chain && - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_missing $graphdir/commit-graph-chain && ls $graphdir >graph-files && test_line_count = 0 graph-files @@ -306,7 +306,7 @@ test_expect_success 'verify across alternates' ' echo "$altdir" >.git/objects/info/alternates && git commit-graph verify --object-dir="$altdir/" && test_commit extra && - git commit-graph write --reachable --split && + git commit-graph write --input=reachable --split && tip_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph && corrupt_file "$tip_file" 100 "\01" && test_must_fail git commit-graph verify --shallow 2>test_err && @@ -319,7 +319,7 @@ test_expect_success 'add octopus merge' ' git reset --hard commits/10 && git merge commits/3 commits/4 && git branch merge/octopus && - git commit-graph write --reachable --split && + git commit-graph write --input=reachable --split && git commit-graph verify --progress 2>err && test_line_count = 3 err && test_i18ngrep ! warning err && @@ -329,7 +329,7 @@ test_expect_success 'add octopus merge' ' graph_git_behavior 'graph exists' merge/octopus commits/12 test_expect_success 'split across alternate where alternate is not split' ' - git commit-graph write --reachable && + git commit-graph write --input=reachable && test_path_is_file .git/objects/info/commit-graph && cp .git/objects/info/commit-graph . && git clone --no-hardlinks . alt-split && @@ -338,7 +338,7 @@ test_expect_success 'split across alternate where alternate is not split' ' rm -f .git/objects/info/commit-graph && echo "$(pwd)"/../.git/objects >.git/objects/info/alternates && test_commit 18 && - git commit-graph write --reachable --split && + git commit-graph write --input=reachable --split && test_line_count = 1 $graphdir/commit-graph-chain ) && test_cmp commit-graph .git/objects/info/commit-graph @@ -351,10 +351,10 @@ test_expect_success '--split=merge-all always merges incrementals' ' git rev-list -3 HEAD~4 >a && git rev-list -2 HEAD~2 >b && git rev-list -2 HEAD >c && - git commit-graph write --split=no-merge --stdin-commits a && git rev-list HEAD >b && - git commit-graph write --split --stdin-commits X-Patchwork-Id: 11358989 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B22C11398 for ; Fri, 31 Jan 2020 00:28:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 86A6220CC7 for ; Fri, 31 Jan 2020 00:28:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=ttaylorr-com.20150623.gappssmtp.com header.i=@ttaylorr-com.20150623.gappssmtp.com header.b="m1ecs5ya" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727741AbgAaA2b (ORCPT ); Thu, 30 Jan 2020 19:28:31 -0500 Received: from mail-pl1-f193.google.com ([209.85.214.193]:39692 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727380AbgAaA2b (ORCPT ); Thu, 30 Jan 2020 19:28:31 -0500 Received: by mail-pl1-f193.google.com with SMTP id g6so2000154plp.6 for ; Thu, 30 Jan 2020 16:28:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ttaylorr-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=EOCNPIBtLhr6ituh2GewCHjv6q+ScM6+mxAZktUZGAw=; b=m1ecs5yasWHzMHjY5vJun8jBvLjd+9ksYs0JF1vB6KEAOYcKWtkWKeBv4zBIBKgfj8 SU+QEfNr2aj5hKhDBKM4imppTV/wxdI8cxUai/EvLcsOHqdsyMRTGoXpTR/q2X6agsHl bowz2jtgRczIByp/TjT2/9WGS1BtO7TGqGSB3We4xDbxy3KNoWZHHwu5jwQgd8k0/vXr r+nUW555WIT9H82MjOrB7rC1LUJo8gpxTDdWmR80W8p4pf37Yri8G6qmYBQ9CIf6WDsj /UyFBE/dLaun0ToKhCg7Ir43ekJQBCReQ1FX3CcfiH1h4KqGEWxKeRaxigdL1J1j7qJ5 lEDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=EOCNPIBtLhr6ituh2GewCHjv6q+ScM6+mxAZktUZGAw=; b=WDwgHviSwzTcbd0ISbvRSPdxRcEGNJtvNDfxfxsfK9awHTzSXZCxAMacp0QgGA8uJU 2bqJ53e1xQAW99eZGVPWlgfouN8OYEm+DSzuBuT5IAAc/9/k9TAGOBdsWc2OgDS9pj9y wfGuIODUZpCkjosYI2Izorl4wnMgOLVTY0XumYjLMsqkQfkwk0rtaaxGZDA8wUa157Sq scnB9iWKLVGyM60tfDfv7kDcfVvMd3tdD4UM9/dGHkxTTtRuBiinJJrv7fyCxKjoJvE5 CRh6WU7jw6Z6AHSRjvgMLPdc5vrc5XMkULujWfSHHuiqTr5TyVkwp37O8se8NVEb78cd GuEg== X-Gm-Message-State: APjAAAX+RKtsNsFc+101XvKntcZ+XMsqy8pDQl2FoFFExR38ukmUqin4 /p3DZErGvN4PqFR6xV0M17vu9WaZpLBwkw== X-Google-Smtp-Source: APXvYqx1HVKG2N9fcT5UkKNRO7nyBJQlTdAqSUlVWrAPGG//lCGKCjde2aFsVE3ap8QdaYCnUa8CMg== X-Received: by 2002:a17:90a:7303:: with SMTP id m3mr9210038pjk.62.1580430510317; Thu, 30 Jan 2020 16:28:30 -0800 (PST) Received: from localhost ([2601:602:9200:32b0:5c8f:7dac:47b8:95ff]) by smtp.gmail.com with ESMTPSA id c19sm8188277pfc.144.2020.01.30.16.28.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Jan 2020 16:28:24 -0800 (PST) Date: Thu, 30 Jan 2020 16:28:21 -0800 From: Taylor Blau To: git@vger.kernel.org Cc: peff@peff.net, dstolee@microsoft.com, gitster@pobox.com Subject: [PATCH 3/3] builtin/commit-graph.c: support '--input=none' Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.11.4 (2019-03-13) Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org In the previous commit, we introduced '--[no-]merge', and alluded to the fact that '--merge' would be useful for callers who wish to always trigger a merge of an incremental chain. There is a problem with the above approach, which is that there is no way to specify to the commit-graph builtin that a caller only wants to include commits already in the graph. One can specify '--input=append' to include all commits in the existing graphs, but the absence of '--input=stdin-{commits,packs}' causes the builtin to call 'fill_oids_from_all_packs()'. Passing '--input=reachable' (as in 'git commit-graph write --split=merge-all --input=reachable --input=append') works around this issue by making '--input=reachable' effectively a no-op, but this can be prohibitively expensive in large repositories, making it an undesirable choice for some users. Teach '--input=none' as an option to behave as if '--input=append' were given, but to consider no other sources in addition. This, in conjunction with the option introduced in the previous patch offers the convenient way to force the commit-graph machinery to condense a chain of incrementals without requiring any new commits: $ git commit-graph write --split=merge-all --input=none Signed-off-by: Taylor Blau --- Documentation/git-commit-graph.txt | 21 +++++++++++++-------- builtin/commit-graph.c | 13 ++++++++++--- commit-graph.c | 6 ++++-- commit-graph.h | 3 ++- t/t5324-split-commit-graph.sh | 26 ++++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 14 deletions(-) diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.txt index cbf80226e9..d380c42e82 100644 --- a/Documentation/git-commit-graph.txt +++ b/Documentation/git-commit-graph.txt @@ -39,24 +39,29 @@ COMMANDS -------- 'write':: -Write a commit-graph file based on the commits found in packfiles. +Write a commit-graph file based on the commits specified: +* With the `--input=stdin-packs` option, generate the new commit graph +by walking objects only in the specified pack-indexes. (Cannot be +combined with `--input=stdin-commits` or `--input=reachable`.) + -With the `--input=stdin-packs` option, generate the new commit graph by -walking objects only in the specified pack-indexes. (Cannot be combined -with `--input=stdin-commits` or `--input=reachable`.) -+ -With the `--input=stdin-commits` option, generate the new commit graph +* With the `--input=stdin-commits` option, generate the new commit graph by walking commits starting at the commits specified in stdin as a list of OIDs in hex, one OID per line. (Cannot be combined with `--input=stdin-packs` or `--input=reachable`.) + -With the `--input=reachable` option, generate the new commit graph by +* With the `--input=reachable` option, generate the new commit graph by walking commits starting at all refs. (Cannot be combined with `--input=stdin-commits` or `--input=stdin-packs`.) + -With the `--input=append` option, include all commits that are present +* With the `--input=append` option, include all commits that are present in the existing commit-graph file. + +* With the `--input=none` option, behave as if `input=append` were +given, but do not walk other packs to find additional commits. + +If none of the above options are given, then commits found in +packfiles are specified. ++ With the `--split[=]` option, write the commit-graph as a chain of multiple commit-graph files stored in `/info/commit-graphs`. Commit-graph layers are merged based on the diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 03d815e652..937b98e99e 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -10,7 +10,8 @@ static char const * const builtin_commit_graph_usage[] = { N_("git commit-graph verify [--object-dir ] [--shallow] [--[no-]progress]"), N_("git commit-graph write [--object-dir ] [--append] " - "[--split[=]] [--input=] " + "[--split[=]] " + "[--input=] " "[--[no-]progress] "), NULL }; @@ -22,7 +23,8 @@ static const char * const builtin_commit_graph_verify_usage[] = { static const char * const builtin_commit_graph_write_usage[] = { N_("git commit-graph write [--object-dir ] [--append] " - "[--split[=]] [--input=] " + "[--split[=]] " + "[--input=] " "[--[no-]progress] "), NULL }; @@ -31,7 +33,8 @@ enum commit_graph_input { COMMIT_GRAPH_INPUT_REACHABLE = (1 << 1), COMMIT_GRAPH_INPUT_STDIN_PACKS = (1 << 2), COMMIT_GRAPH_INPUT_STDIN_COMMITS = (1 << 3), - COMMIT_GRAPH_INPUT_APPEND = (1 << 4) + COMMIT_GRAPH_INPUT_APPEND = (1 << 4), + COMMIT_GRAPH_INPUT_NONE = (1 << 5) }; static struct opts_commit_graph { @@ -59,6 +62,8 @@ static int option_parse_input(const struct option *opt, const char *arg, *to |= COMMIT_GRAPH_INPUT_STDIN_COMMITS; else if (!strcmp(arg, "append")) *to |= COMMIT_GRAPH_INPUT_APPEND; + else if (!strcmp(arg, "none")) + *to |= (COMMIT_GRAPH_INPUT_APPEND | COMMIT_GRAPH_INPUT_NONE); else die(_("unrecognized --input source, %s"), arg); return 0; @@ -211,6 +216,8 @@ static int graph_write(int argc, const char **argv) opts.obj_dir = get_object_directory(); if (opts.input & COMMIT_GRAPH_INPUT_APPEND) flags |= COMMIT_GRAPH_WRITE_APPEND; + if (opts.input & COMMIT_GRAPH_INPUT_NONE) + flags |= COMMIT_GRAPH_WRITE_NO_INPUT; if (opts.split) flags |= COMMIT_GRAPH_WRITE_SPLIT; if (opts.progress) diff --git a/commit-graph.c b/commit-graph.c index 02e6ad9d1f..a5d7624073 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -808,7 +808,8 @@ struct write_commit_graph_context { unsigned append:1, report_progress:1, split:1, - check_oids:1; + check_oids:1, + no_input:1; const struct split_commit_graph_opts *split_opts; }; @@ -1802,6 +1803,7 @@ int write_commit_graph(struct object_directory *odb, ctx->split = flags & COMMIT_GRAPH_WRITE_SPLIT ? 1 : 0; ctx->check_oids = flags & COMMIT_GRAPH_WRITE_CHECK_OIDS ? 1 : 0; ctx->split_opts = split_opts; + ctx->no_input = flags & COMMIT_GRAPH_WRITE_NO_INPUT ? 1 : 0; if (ctx->split) { struct commit_graph *g; @@ -1860,7 +1862,7 @@ int write_commit_graph(struct object_directory *odb, goto cleanup; } - if (!pack_indexes && !commit_hex) + if (!ctx->no_input && !pack_indexes && !commit_hex) fill_oids_from_all_packs(ctx); close_reachable(ctx); diff --git a/commit-graph.h b/commit-graph.h index dadcc03808..dd8c00a2d8 100644 --- a/commit-graph.h +++ b/commit-graph.h @@ -81,7 +81,8 @@ enum commit_graph_write_flags { COMMIT_GRAPH_WRITE_PROGRESS = (1 << 1), COMMIT_GRAPH_WRITE_SPLIT = (1 << 2), /* Make sure that each OID in the input is a valid commit OID. */ - COMMIT_GRAPH_WRITE_CHECK_OIDS = (1 << 3) + COMMIT_GRAPH_WRITE_CHECK_OIDS = (1 << 3), + COMMIT_GRAPH_WRITE_NO_INPUT = (1 << 4) }; enum commit_graph_split_flags { diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index dd74295885..296b5a9185 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -369,4 +369,30 @@ test_expect_success '--split=no-merge always writes an incremental' ' test_line_count = 2 $graphdir/commit-graph-chain ' +test_expect_success '--split=no-merge, --input=none writes nothing' ' + test_when_finished rm -rf a graphs.before graphs.after && + rm -rf $graphdir && + git reset --hard commits/2 && + git rev-list -1 HEAD~1 >a && + git commit-graph write --split=no-merge --input=stdin-commits graphs.before && + test_line_count = 1 $graphdir/commit-graph-chain && + git commit-graph write --split --input=none && + ls $graphdir/graph-*.graph >graphs.after && + test_cmp graphs.before graphs.after +' + +test_expect_success '--split=merge-all, --input=none merges the chain' ' + test_when_finished rm -rf a b && + rm -rf $graphdir && + git reset --hard commits/2 && + git rev-list -1 HEAD~1 >a && + git rev-list -1 HEAD >b && + git commit-graph write --split=no-merge --input=stdin-commits