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:
-rw-r--r--.github/workflows/coverity.yml163
-rw-r--r--.github/workflows/main.yml13
-rw-r--r--Documentation/config/rebase.txt6
-rw-r--r--Documentation/diff-options.txt8
-rw-r--r--Documentation/scalar.txt8
-rw-r--r--add-interactive.c2
-rw-r--r--builtin/add.c3
-rw-r--r--builtin/am.c4
-rw-r--r--builtin/describe.c6
-rw-r--r--builtin/diff-files.c12
-rw-r--r--builtin/diff-index.c4
-rw-r--r--builtin/diff-tree.c2
-rw-r--r--builtin/diff.c79
-rw-r--r--builtin/gc.c2
-rw-r--r--builtin/grep.c2
-rw-r--r--builtin/log.c2
-rw-r--r--builtin/receive-pack.c6
-rw-r--r--builtin/stash.c16
-rw-r--r--builtin/submodule--helper.c7
-rwxr-xr-xci/lib.sh2
-rw-r--r--commit-graph.c38
-rw-r--r--contrib/completion/git-completion.bash5
-rw-r--r--diff-lib.c20
-rw-r--r--diff-no-index.c3
-rw-r--r--diff.c46
-rw-r--r--diff.h6
-rw-r--r--fetch-pack.c6
-rw-r--r--git-compat-util.h4
-rw-r--r--http.c37
-rw-r--r--ref-filter.c21
-rw-r--r--scalar.c70
-rw-r--r--sequencer.c231
-rw-r--r--setup.c34
-rw-r--r--setup.h35
-rwxr-xr-xt/t3321-notes-stripspace.sh1
-rwxr-xr-xt/t3404-rebase-interactive.sh53
-rwxr-xr-xt/t3418-rebase-continue.sh18
-rwxr-xr-xt/t3430-rebase-merges.sh41
-rwxr-xr-xt/t4015-diff-whitespace.sh39
-rwxr-xr-xt/t4017-diff-retval.sh5
-rwxr-xr-xt/t4040-whitespace-status.sh3
-rwxr-xr-xt/t4053-diff-no-index.sh19
-rwxr-xr-xt/t5318-commit-graph.sh18
-rwxr-xr-xt/t5407-post-rewrite-hook.sh48
-rwxr-xr-xt/t5510-fetch.sh46
-rwxr-xr-xt/t5546-receive-limits.sh35
-rwxr-xr-xt/t5571-pre-push-hook.sh1
-rwxr-xr-xt/t5583-push-branches.sh1
-rwxr-xr-xt/t6300-for-each-ref.sh15
-rwxr-xr-xt/t7516-commit-races.sh2
-rwxr-xr-xt/t7527-builtin-fsmonitor.sh5
-rwxr-xr-xt/t9211-scalar-clone.sh12
-rwxr-xr-xt/t9902-completion.sh12
-rw-r--r--t/test-lib.sh1
-rw-r--r--wt-status.c18
55 files changed, 964 insertions, 332 deletions
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
new file mode 100644
index 0000000000..e5532d381b
--- /dev/null
+++ b/.github/workflows/coverity.yml
@@ -0,0 +1,163 @@
+name: Coverity
+
+# This GitHub workflow automates submitting builds to Coverity Scan. To enable it,
+# set the repository variable `ENABLE_COVERITY_SCAN_FOR_BRANCHES` (for details, see
+# https://docs.github.com/en/actions/learn-github-actions/variables) to a JSON
+# string array containing the names of the branches for which the workflow should be
+# run, e.g. `["main", "next"]`.
+#
+# In addition, two repository secrets must be set (for details how to add secrets, see
+# https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions):
+# `COVERITY_SCAN_EMAIL` and `COVERITY_SCAN_TOKEN`. The former specifies the
+# email to which the Coverity reports should be sent and the latter can be
+# obtained from the Project Settings tab of the Coverity project).
+#
+# The workflow runs on `ubuntu-latest` by default. This can be overridden by setting
+# the repository variable `ENABLE_COVERITY_SCAN_ON_OS` to a JSON string array specifying
+# the operating systems, e.g. `["ubuntu-latest", "windows-latest"]`.
+#
+# By default, the builds are submitted to the Coverity project `git`. To override this,
+# set the repository variable `COVERITY_PROJECT`.
+
+on:
+ push:
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ coverity:
+ if: contains(fromJSON(vars.ENABLE_COVERITY_SCAN_FOR_BRANCHES || '[""]'), github.ref_name)
+ strategy:
+ matrix:
+ os: ${{ fromJSON(vars.ENABLE_COVERITY_SCAN_ON_OS || '["ubuntu-latest"]') }}
+ runs-on: ${{ matrix.os }}
+ env:
+ COVERITY_PROJECT: ${{ vars.COVERITY_PROJECT || 'git' }}
+ COVERITY_LANGUAGE: cxx
+ COVERITY_PLATFORM: overridden-below
+ steps:
+ - uses: actions/checkout@v3
+ - name: install minimal Git for Windows SDK
+ if: contains(matrix.os, 'windows')
+ uses: git-for-windows/setup-git-for-windows-sdk@v1
+ - run: ci/install-dependencies.sh
+ if: contains(matrix.os, 'ubuntu') || contains(matrix.os, 'macos')
+ env:
+ runs_on_pool: ${{ matrix.os }}
+
+ # The Coverity site says the tool is usually updated twice yearly, so the
+ # MD5 of download can be used to determine whether there's been an update.
+ - name: get the Coverity Build Tool hash
+ id: lookup
+ run: |
+ case "${{ matrix.os }}" in
+ *windows*)
+ COVERITY_PLATFORM=win64
+ COVERITY_TOOL_FILENAME=cov-analysis.zip
+ MAKEFLAGS=-j$(nproc)
+ ;;
+ *macos*)
+ COVERITY_PLATFORM=macOSX
+ COVERITY_TOOL_FILENAME=cov-analysis.dmg
+ MAKEFLAGS=-j$(sysctl -n hw.physicalcpu)
+ ;;
+ *ubuntu*)
+ COVERITY_PLATFORM=linux64
+ COVERITY_TOOL_FILENAME=cov-analysis.tgz
+ MAKEFLAGS=-j$(nproc)
+ ;;
+ *)
+ echo '::error::unhandled OS ${{ matrix.os }}' >&2
+ exit 1
+ ;;
+ esac
+ echo "COVERITY_PLATFORM=$COVERITY_PLATFORM" >>$GITHUB_ENV
+ echo "COVERITY_TOOL_FILENAME=$COVERITY_TOOL_FILENAME" >>$GITHUB_ENV
+ echo "MAKEFLAGS=$MAKEFLAGS" >>$GITHUB_ENV
+ MD5=$(curl https://scan.coverity.com/download/$COVERITY_LANGUAGE/$COVERITY_PLATFORM \
+ --fail \
+ --form token='${{ secrets.COVERITY_SCAN_TOKEN }}' \
+ --form project="$COVERITY_PROJECT" \
+ --form md5=1)
+ case $? in
+ 0) ;; # okay
+ 22) # 40x, i.e. access denied
+ echo "::error::incorrect token or project?" >&2
+ exit 1
+ ;;
+ *) # other error
+ echo "::error::Failed to retrieve MD5" >&2
+ exit 1
+ ;;
+ esac
+ echo "hash=$MD5" >>$GITHUB_OUTPUT
+
+ # Try to cache the tool to avoid downloading 1GB+ on every run.
+ # A cache miss will add ~30s to create, but a cache hit will save minutes.
+ - name: restore the Coverity Build Tool
+ id: cache
+ uses: actions/cache/restore@v3
+ with:
+ path: ${{ runner.temp }}/cov-analysis
+ key: cov-build-${{ env.COVERITY_LANGUAGE }}-${{ env.COVERITY_PLATFORM }}-${{ steps.lookup.outputs.hash }}
+ - name: download the Coverity Build Tool (${{ env.COVERITY_LANGUAGE }} / ${{ env.COVERITY_PLATFORM}})
+ if: steps.cache.outputs.cache-hit != 'true'
+ run: |
+ curl https://scan.coverity.com/download/$COVERITY_LANGUAGE/$COVERITY_PLATFORM \
+ --fail --no-progress-meter \
+ --output $RUNNER_TEMP/$COVERITY_TOOL_FILENAME \
+ --form token='${{ secrets.COVERITY_SCAN_TOKEN }}' \
+ --form project="$COVERITY_PROJECT"
+ - name: extract the Coverity Build Tool
+ if: steps.cache.outputs.cache-hit != 'true'
+ run: |
+ case "$COVERITY_TOOL_FILENAME" in
+ *.tgz)
+ mkdir $RUNNER_TEMP/cov-analysis &&
+ tar -xzf $RUNNER_TEMP/$COVERITY_TOOL_FILENAME --strip 1 -C $RUNNER_TEMP/cov-analysis
+ ;;
+ *.dmg)
+ cd $RUNNER_TEMP &&
+ attach="$(hdiutil attach $COVERITY_TOOL_FILENAME)" &&
+ volume="$(echo "$attach" | cut -f 3 | grep /Volumes/)" &&
+ mkdir cov-analysis &&
+ cd cov-analysis &&
+ sh "$volume"/cov-analysis-macosx-*.sh &&
+ ls -l &&
+ hdiutil detach "$volume"
+ ;;
+ *.zip)
+ cd $RUNNER_TEMP &&
+ mkdir cov-analysis-tmp &&
+ unzip -d cov-analysis-tmp $COVERITY_TOOL_FILENAME &&
+ mv cov-analysis-tmp/* cov-analysis
+ ;;
+ *)
+ echo "::error::unhandled archive type: $COVERITY_TOOL_FILENAME" >&2
+ exit 1
+ ;;
+ esac
+ - name: cache the Coverity Build Tool
+ if: steps.cache.outputs.cache-hit != 'true'
+ uses: actions/cache/save@v3
+ with:
+ path: ${{ runner.temp }}/cov-analysis
+ key: cov-build-${{ env.COVERITY_LANGUAGE }}-${{ env.COVERITY_PLATFORM }}-${{ steps.lookup.outputs.hash }}
+ - name: build with cov-build
+ run: |
+ export PATH="$RUNNER_TEMP/cov-analysis/bin:$PATH" &&
+ cov-configure --gcc &&
+ cov-build --dir cov-int make
+ - name: package the build
+ run: tar -czvf cov-int.tgz cov-int
+ - name: submit the build to Coverity Scan
+ run: |
+ curl \
+ --fail \
+ --form token='${{ secrets.COVERITY_SCAN_TOKEN }}' \
+ --form email='${{ secrets.COVERITY_SCAN_EMAIL }}' \
+ --form file=@cov-int.tgz \
+ --form version='${{ github.sha }}' \
+ "https://scan.coverity.com/builds?project=$COVERITY_PROJECT"
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 079645b776..1b41278a7f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -5,6 +5,19 @@ on: [push, pull_request]
env:
DEVELOPER: 1
+# If more than one workflow run is triggered for the very same commit hash
+# (which happens when multiple branches pointing to the same commit), only
+# the first one is allowed to run, the second will be kept in the "queued"
+# state. This allows a successful completion of the first run to be reused
+# in the second run via the `skip-if-redundant` logic in the `config` job.
+#
+# The only caveat is that if a workflow run is triggered for the same commit
+# hash that another run is already being held, that latter run will be
+# canceled. For more details about the `concurrency` attribute, see:
+# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency
+concurrency:
+ group: ${{ github.sha }}
+
jobs:
ci-config:
name: config
diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt
index afaf6dad99..9c248accec 100644
--- a/Documentation/config/rebase.txt
+++ b/Documentation/config/rebase.txt
@@ -77,3 +77,9 @@ rebase.rebaseMerges::
equivalent to `--no-rebase-merges`. Passing `--rebase-merges` on the
command line, with or without an argument, overrides any
`rebase.rebaseMerges` configuration.
+
+rebase.maxLabelLength::
+ When generating label names from commit subjects, truncate the names to
+ this length. By default, the names are truncated to a little less than
+ `NAME_MAX` (to allow e.g. `.lock` files to be written for the
+ corresponding loose refs).
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 9f33f88771..c07488b123 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -22,13 +22,7 @@ ifndef::git-format-patch[]
-p::
-u::
--patch::
- Generate patch (see section titled
-ifdef::git-log[]
-<<generate_patch_text_with_p, "Generating patch text with -p">>).
-endif::git-log[]
-ifndef::git-log[]
-"Generating patch text with -p").
-endif::git-log[]
+ Generate patch (see <<generate_patch_text_with_p>>).
ifdef::git-diff[]
This is the default.
endif::git-diff[]
diff --git a/Documentation/scalar.txt b/Documentation/scalar.txt
index f33436c7f6..361f51a647 100644
--- a/Documentation/scalar.txt
+++ b/Documentation/scalar.txt
@@ -8,7 +8,8 @@ scalar - A tool for managing large Git repositories
SYNOPSIS
--------
[verse]
-scalar clone [--single-branch] [--branch <main-branch>] [--full-clone] <url> [<enlistment>]
+scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]
+ [--[no-]src] <url> [<enlistment>]
scalar list
scalar register [<enlistment>]
scalar unregister [<enlistment>]
@@ -80,6 +81,11 @@ remote-tracking branch for the branch this option was used for the initial
cloning. If the HEAD at the remote did not point at any branch when
`--single-branch` clone was made, no remote-tracking branch is created.
+--[no-]src::
+ By default, `scalar clone` places the cloned repository within a
+ `<entlistment>/src` directory. Use `--no-src` to place the cloned
+ repository directly in the `<enlistment>` directory.
+
--[no-]full-clone::
A sparse-checkout is initialized by default. This behavior can be
turned off via `--full-clone`.
diff --git a/add-interactive.c b/add-interactive.c
index add9a1ad43..7fd00c5e25 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -569,7 +569,7 @@ static int get_modified_files(struct repository *r,
copy_pathspec(&rev.prune_data, ps);
if (s.mode == FROM_INDEX)
- run_diff_index(&rev, 1);
+ run_diff_index(&rev, DIFF_INDEX_CACHED);
else {
rev.diffopt.flags.ignore_dirty_submodules = 1;
run_diff_files(&rev, 0);
diff --git a/builtin/add.c b/builtin/add.c
index 4b0dd798df..12c5aa6d1f 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -194,8 +194,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
out = xopen(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
rev.diffopt.file = xfdopen(out, "w");
rev.diffopt.close_file = 1;
- if (run_diff_files(&rev, 0))
- die(_("Could not write patch"));
+ run_diff_files(&rev, 0);
if (launch_editor(file, NULL, NULL))
die(_("editing patch failed"));
diff --git a/builtin/am.c b/builtin/am.c
index 8bde034fae..202040b62e 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1430,7 +1430,7 @@ static void write_index_patch(const struct am_state *state)
rev_info.diffopt.close_file = 1;
add_pending_object(&rev_info, &tree->object, "");
diff_setup_done(&rev_info.diffopt);
- run_diff_index(&rev_info, 1);
+ run_diff_index(&rev_info, DIFF_INDEX_CACHED);
release_revisions(&rev_info);
}
@@ -1593,7 +1593,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
rev_info.diffopt.filter |= diff_filter_bit('M');
add_pending_oid(&rev_info, "HEAD", &our_tree, 0);
diff_setup_done(&rev_info.diffopt);
- run_diff_index(&rev_info, 1);
+ run_diff_index(&rev_info, DIFF_INDEX_CACHED);
release_revisions(&rev_info);
}
diff --git a/builtin/describe.c b/builtin/describe.c
index b28a4a1f82..a9e375882b 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -668,7 +668,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
struct lock_file index_lock = LOCK_INIT;
struct rev_info revs;
struct strvec args = STRVEC_INIT;
- int fd, result;
+ int fd;
setup_work_tree();
prepare_repo_settings(the_repository);
@@ -685,9 +685,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
strvec_pushv(&args, diff_index_args);
if (setup_revisions(args.nr, args.v, &revs, NULL) != 1)
BUG("malformed internal diff-index command line");
- result = run_diff_index(&revs, 0);
+ run_diff_index(&revs, 0);
- if (!diff_result_code(&revs.diffopt, result))
+ if (!diff_result_code(&revs.diffopt))
suffix = NULL;
else
suffix = dirty;
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index 50330b8dd2..f38912cd40 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -80,14 +80,10 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
(rev.diffopt.output_format & DIFF_FORMAT_PATCH))
diff_merges_set_dense_combined_if_unset(&rev);
- if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) {
- perror("repo_read_index_preload");
- result = -1;
- goto cleanup;
- }
- result = run_diff_files(&rev, options);
- result = diff_result_code(&rev.diffopt, result);
-cleanup:
+ if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0)
+ die_errno("repo_read_index_preload");
+ run_diff_files(&rev, options);
+ result = diff_result_code(&rev.diffopt);
release_revisions(&rev);
return result;
}
diff --git a/builtin/diff-index.c b/builtin/diff-index.c
index 9db7139b83..220f341ffa 100644
--- a/builtin/diff-index.c
+++ b/builtin/diff-index.c
@@ -72,8 +72,8 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
perror("repo_read_index");
return -1;
}
- result = run_diff_index(&rev, option);
- result = diff_result_code(&rev.diffopt, result);
+ run_diff_index(&rev, option);
+ result = diff_result_code(&rev.diffopt);
release_revisions(&rev);
return result;
}
diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index c9ba35f143..86be634286 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -232,5 +232,5 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
diff_free(&opt->diffopt);
}
- return diff_result_code(&opt->diffopt, 0);
+ return diff_result_code(&opt->diffopt);
}
diff --git a/builtin/diff.c b/builtin/diff.c
index b19530c996..0b313549c7 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -77,9 +77,9 @@ static void stuff_change(struct diff_options *opt,
diff_queue(&diff_queued_diff, one, two);
}
-static int builtin_diff_b_f(struct rev_info *revs,
- int argc, const char **argv UNUSED,
- struct object_array_entry **blob)
+static void builtin_diff_b_f(struct rev_info *revs,
+ int argc, const char **argv UNUSED,
+ struct object_array_entry **blob)
{
/* Blob vs file in the working tree*/
struct stat st;
@@ -109,12 +109,11 @@ static int builtin_diff_b_f(struct rev_info *revs,
path);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
- return 0;
}
-static int builtin_diff_blobs(struct rev_info *revs,
- int argc, const char **argv UNUSED,
- struct object_array_entry **blob)
+static void builtin_diff_blobs(struct rev_info *revs,
+ int argc, const char **argv UNUSED,
+ struct object_array_entry **blob)
{
const unsigned mode = canon_mode(S_IFREG | 0644);
@@ -134,11 +133,10 @@ static int builtin_diff_blobs(struct rev_info *revs,
blob_path(blob[0]), blob_path(blob[1]));
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
- return 0;
}
-static int builtin_diff_index(struct rev_info *revs,
- int argc, const char **argv)
+static void builtin_diff_index(struct rev_info *revs,
+ int argc, const char **argv)
{
unsigned int option = 0;
while (1 < argc) {
@@ -163,20 +161,18 @@ static int builtin_diff_index(struct rev_info *revs,
setup_work_tree();
if (repo_read_index_preload(the_repository,
&revs->diffopt.pathspec, 0) < 0) {
- perror("repo_read_index_preload");
- return -1;
+ die_errno("repo_read_index_preload");
}
} else if (repo_read_index(the_repository) < 0) {
- perror("repo_read_cache");
- return -1;
+ die_errno("repo_read_cache");
}
- return run_diff_index(revs, option);
+ run_diff_index(revs, option);
}
-static int builtin_diff_tree(struct rev_info *revs,
- int argc, const char **argv,
- struct object_array_entry *ent0,
- struct object_array_entry *ent1)
+static void builtin_diff_tree(struct rev_info *revs,
+ int argc, const char **argv,
+ struct object_array_entry *ent0,
+ struct object_array_entry *ent1)
{
const struct object_id *(oid[2]);
struct object_id mb_oid;
@@ -209,13 +205,12 @@ static int builtin_diff_tree(struct rev_info *revs,
}
diff_tree_oid(oid[0], oid[1], "", &revs->diffopt);
log_tree_diff_flush(revs);
- return 0;
}
-static int builtin_diff_combined(struct rev_info *revs,
- int argc, const char **argv UNUSED,
- struct object_array_entry *ent,
- int ents, int first_non_parent)
+static void builtin_diff_combined(struct rev_info *revs,
+ int argc, const char **argv UNUSED,
+ struct object_array_entry *ent,
+ int ents, int first_non_parent)
{
struct oid_array parents = OID_ARRAY_INIT;
int i;
@@ -236,7 +231,6 @@ static int builtin_diff_combined(struct rev_info *revs,
}
diff_tree_combined(&ent[first_non_parent].item->oid, &parents, revs);
oid_array_clear(&parents);
- return 0;
}
static void refresh_index_quietly(void)
@@ -254,7 +248,7 @@ static void refresh_index_quietly(void)
repo_update_index_if_able(the_repository, &lock_file);
}
-static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv)
+static void builtin_diff_files(struct rev_info *revs, int argc, const char **argv)
{
unsigned int options = 0;
@@ -269,8 +263,10 @@ static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv
options |= DIFF_SILENT_ON_REMOVED;
else if (!strcmp(argv[1], "-h"))
usage(builtin_diff_usage);
- else
- return error(_("invalid option: %s"), argv[1]);
+ else {
+ error(_("invalid option: %s"), argv[1]);
+ usage(builtin_diff_usage);
+ }
argv++; argc--;
}
@@ -287,10 +283,9 @@ static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv
setup_work_tree();
if (repo_read_index_preload(the_repository, &revs->diffopt.pathspec,
0) < 0) {
- perror("repo_read_index_preload");
- return -1;
+ die_errno("repo_read_index_preload");
}
- return run_diff_files(revs, options);
+ run_diff_files(revs, options);
}
struct symdiff {
@@ -404,7 +399,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
int blobs = 0, paths = 0;
struct object_array_entry *blob[2];
int nongit = 0, no_index = 0;
- int result = 0;
+ int result;
struct symdiff sdiff;
/*
@@ -583,17 +578,17 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
if (!ent.nr) {
switch (blobs) {
case 0:
- result = builtin_diff_files(&rev, argc, argv);
+ builtin_diff_files(&rev, argc, argv);
break;
case 1:
if (paths != 1)
usage(builtin_diff_usage);
- result = builtin_diff_b_f(&rev, argc, argv, blob);
+ builtin_diff_b_f(&rev, argc, argv, blob);
break;
case 2:
if (paths)
usage(builtin_diff_usage);
- result = builtin_diff_blobs(&rev, argc, argv, blob);
+ builtin_diff_blobs(&rev, argc, argv, blob);
break;
default:
usage(builtin_diff_usage);
@@ -602,18 +597,18 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
else if (blobs)
usage(builtin_diff_usage);
else if (ent.nr == 1)
- result = builtin_diff_index(&rev, argc, argv);
+ builtin_diff_index(&rev, argc, argv);
else if (ent.nr == 2) {
if (sdiff.warn)
warning(_("%s...%s: multiple merge bases, using %s"),
sdiff.left, sdiff.right, sdiff.base);
- result = builtin_diff_tree(&rev, argc, argv,
- &ent.objects[0], &ent.objects[1]);
+ builtin_diff_tree(&rev, argc, argv,
+ &ent.objects[0], &ent.objects[1]);
} else
- result = builtin_diff_combined(&rev, argc, argv,
- ent.objects, ent.nr,
- first_non_parent);
- result = diff_result_code(&rev.diffopt, result);
+ builtin_diff_combined(&rev, argc, argv,
+ ent.objects, ent.nr,
+ first_non_parent);
+ result = diff_result_code(&rev.diffopt);
if (1 < rev.diffopt.skip_stat_unmatch)
refresh_index_quietly();
release_revisions(&rev);
diff --git a/builtin/gc.c b/builtin/gc.c
index 5c4315f0d8..719cae9a88 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -2397,7 +2397,7 @@ static int systemd_timer_write_unit_templates(const char *exec_path)
"LockPersonality=yes\n"
"MemoryDenyWriteExecute=yes\n"
"NoNewPrivileges=yes\n"
- "RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6\n"
+ "RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_VSOCK\n"
"RestrictNamespaces=yes\n"
"RestrictRealtime=yes\n"
"RestrictSUIDSGID=yes\n"
diff --git a/builtin/grep.c b/builtin/grep.c
index 50e712a184..2a261074f1 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -990,7 +990,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
OPT_CALLBACK_F(0, "and", &opt, NULL,
N_("combine patterns specified with -e"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback),
- OPT_BOOL(0, "or", &dummy, ""),
+ OPT_BOOL_F(0, "or", &dummy, "", PARSE_OPT_NONEG),
OPT_CALLBACK_F(0, "not", &opt, NULL, "",
PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback),
OPT_CALLBACK_F('(', NULL, &opt, NULL, "",
diff --git a/builtin/log.c b/builtin/log.c
index db3a88bfe9..5d808c92f4 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -549,7 +549,7 @@ static int cmd_log_walk_no_free(struct rev_info *rev)
rev->diffopt.flags.check_failed) {
return 02;
}
- return diff_result_code(&rev->diffopt, 0);
+ return diff_result_code(&rev->diffopt);
}
static int cmd_log_walk(struct rev_info *rev)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index fb8e1549d1..8c4f0cb90a 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2527,10 +2527,10 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
if (cert_nonce_seed)
push_cert_nonce = prepare_push_cert_nonce(service_dir, time(NULL));
- if (0 <= transfer_unpack_limit)
- unpack_limit = transfer_unpack_limit;
- else if (0 <= receive_unpack_limit)
+ if (0 <= receive_unpack_limit)
unpack_limit = receive_unpack_limit;
+ else if (0 <= transfer_unpack_limit)
+ unpack_limit = transfer_unpack_limit;
switch (determine_protocol_version_server()) {
case protocol_v2:
diff --git a/builtin/stash.c b/builtin/stash.c
index fe64cde9ce..53e8868ba1 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -973,7 +973,7 @@ static int show_stash(int argc, const char **argv, const char *prefix)
}
log_tree_diff_flush(&rev);
- ret = diff_result_code(&rev.diffopt, 0);
+ ret = diff_result_code(&rev.diffopt);
cleanup:
strvec_clear(&stash_args);
free_stash_info(&info);
@@ -1089,7 +1089,6 @@ static int get_untracked_files(const struct pathspec *ps, int include_untracked,
*/
static int check_changes_tracked_files(const struct pathspec *ps)
{
- int result;
struct rev_info rev;
struct object_id dummy;
int ret = 0;
@@ -1111,14 +1110,14 @@ static int check_changes_tracked_files(const struct pathspec *ps)
add_head_to_pending(&rev);
diff_setup_done(&rev.diffopt);
- result = run_diff_index(&rev, 1);
- if (diff_result_code(&rev.diffopt, result)) {
+ run_diff_index(&rev, DIFF_INDEX_CACHED);
+ if (diff_result_code(&rev.diffopt)) {
ret = 1;
goto done;
}
- result = run_diff_files(&rev, 0);
- if (diff_result_code(&rev.diffopt, result)) {
+ run_diff_files(&rev, 0);
+ if (diff_result_code(&rev.diffopt)) {
ret = 1;
goto done;
}
@@ -1309,10 +1308,7 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
add_pending_object(&rev, parse_object(the_repository, &info->b_commit),
"");
- if (run_diff_index(&rev, 0)) {
- ret = -1;
- goto done;
- }
+ run_diff_index(&rev, 0);
cp_upd_index.git_cmd = 1;
strvec_pushl(&cp_upd_index.args, "update-index",
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f6871efd95..6f3bf33e61 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -629,7 +629,6 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
char *displaypath;
struct strvec diff_files_args = STRVEC_INIT;
struct rev_info rev = REV_INFO_INIT;
- int diff_files_result;
struct strbuf buf = STRBUF_INIT;
const char *git_dir;
struct setup_revision_opt opt = {
@@ -669,9 +668,9 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
repo_init_revisions(the_repository, &rev, NULL);
rev.abbrev = 0;
setup_revisions(diff_files_args.nr, diff_files_args.v, &rev, &opt);
- diff_files_result = run_diff_files(&rev, 0);
+ run_diff_files(&rev, 0);
- if (!diff_result_code(&rev.diffopt, diff_files_result)) {
+ if (!diff_result_code(&rev.diffopt)) {
print_status(flags, ' ', path, ce_oid,
displaypath);
} else if (!(flags & OPT_CACHED)) {
@@ -1141,7 +1140,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
}
if (diff_cmd == DIFF_INDEX)
- run_diff_index(&rev, info->cached);
+ run_diff_index(&rev, info->cached ? DIFF_INDEX_CACHED : 0);
else
run_diff_files(&rev, 0);
prepare_submodule_summary(info, &list);
diff --git a/ci/lib.sh b/ci/lib.sh
index 369d462f13..6fbb5bade1 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -280,6 +280,8 @@ linux-leaks)
;;
linux-asan-ubsan)
export SANITIZE=address,undefined
+ export NO_SVN_TESTS=LetsSaveSomeTime
+ MAKEFLAGS="$MAKEFLAGS NO_PYTHON=YepBecauseP4FlakesTooOften"
;;
esac
diff --git a/commit-graph.c b/commit-graph.c
index 0aa1640d15..9e6eaa8a46 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -128,6 +128,16 @@ timestamp_t commit_graph_generation(const struct commit *c)
return GENERATION_NUMBER_INFINITY;
}
+static timestamp_t commit_graph_generation_from_graph(const struct commit *c)
+{
+ struct commit_graph_data *data =
+ commit_graph_data_slab_peek(&commit_graph_data_slab, c);
+
+ if (!data || data->graph_pos == COMMIT_NOT_FROM_GRAPH)
+ return GENERATION_NUMBER_INFINITY;
+ return data->generation;
+}
+
static struct commit_graph_data *commit_graph_data_at(const struct commit *c)
{
unsigned int i, nth_slab;
@@ -2550,9 +2560,6 @@ static void graph_report(const char *fmt, ...)
va_end(ap);
}
-#define GENERATION_ZERO_EXISTS 1
-#define GENERATION_NUMBER_EXISTS 2
-
static int commit_graph_checksum_valid(struct commit_graph *g)
{
return hashfile_checksum_valid(g->data, g->data_len);
@@ -2565,7 +2572,8 @@ static int verify_one_commit_graph(struct repository *r,
{
uint32_t i, cur_fanout_pos = 0;
struct object_id prev_oid, cur_oid;
- int generation_zero = 0;
+ struct commit *seen_gen_zero = NULL;
+ struct commit *seen_gen_non_zero = NULL;
verify_commit_graph_error = verify_commit_graph_lite(g);
if (verify_commit_graph_error)
@@ -2659,7 +2667,7 @@ static int verify_one_commit_graph(struct repository *r,
oid_to_hex(&graph_parents->item->object.oid),
oid_to_hex(&odb_parents->item->object.oid));
- generation = commit_graph_generation(graph_parents->item);
+ generation = commit_graph_generation_from_graph(graph_parents->item);
if (generation > max_generation)
max_generation = generation;
@@ -2671,16 +2679,12 @@ static int verify_one_commit_graph(struct repository *r,
graph_report(_("commit-graph parent list for commit %s terminates early"),
oid_to_hex(&cur_oid));
- if (!commit_graph_generation(graph_commit)) {
- if (generation_zero == GENERATION_NUMBER_EXISTS)
- graph_report(_("commit-graph has generation number zero for commit %s, but non-zero elsewhere"),
- oid_to_hex(&cur_oid));
- generation_zero = GENERATION_ZERO_EXISTS;
- } else if (generation_zero == GENERATION_ZERO_EXISTS)
- graph_report(_("commit-graph has non-zero generation number for commit %s, but zero elsewhere"),
- oid_to_hex(&cur_oid));
+ if (commit_graph_generation_from_graph(graph_commit))
+ seen_gen_non_zero = graph_commit;
+ else
+ seen_gen_zero = graph_commit;
- if (generation_zero == GENERATION_ZERO_EXISTS)
+ if (seen_gen_zero)
continue;
/*
@@ -2706,6 +2710,12 @@ static int verify_one_commit_graph(struct repository *r,
odb_commit->date);
}
+ if (seen_gen_zero && seen_gen_non_zero)
+ graph_report(_("commit-graph has both zero and non-zero "
+ "generations (e.g., commits '%s' and '%s')"),
+ oid_to_hex(&seen_gen_zero->object.oid),
+ oid_to_hex(&seen_gen_non_zero->object.oid));
+
return verify_commit_graph_error;
}
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 133ec92bfa..55950057c8 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -28,6 +28,7 @@
# completion style. For example '!f() { : git commit ; ... }; f' will
# tell the completion to use commit completion. This also works with aliases
# of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '".
+# Be sure to add a space between the command name and the ';'.
#
# If you have a command that is not part of git, but you would still
# like completion, you can use __git_complete:
@@ -1607,7 +1608,7 @@ _git_checkout ()
if [ -n "$(__git_find_on_cmdline "-b -B -d --detach --orphan")" ]; then
__git_complete_refs --mode="refs"
- elif [ -n "$(__git_find_on_cmdline "--track")" ]; then
+ elif [ -n "$(__git_find_on_cmdline "-t --track")" ]; then
__git_complete_refs --mode="remote-heads"
else
__git_complete_refs $dwim_opt --mode="refs"
@@ -2514,7 +2515,7 @@ _git_switch ()
if [ -n "$(__git_find_on_cmdline "-c -C -d --detach")" ]; then
__git_complete_refs --mode="refs"
- elif [ -n "$(__git_find_on_cmdline "--track")" ]; then
+ elif [ -n "$(__git_find_on_cmdline "-t --track")" ]; then
__git_complete_refs --mode="remote-heads"
else
__git_complete_refs $dwim_opt --mode="heads"
diff --git a/diff-lib.c b/diff-lib.c
index 6b0c6a7180..5848e4f9ca 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -36,14 +36,14 @@
* exists for ce that is a submodule -- it is a submodule that is not
* checked out). Return negative for an error.
*/
-static int check_removed(const struct index_state *istate, const struct cache_entry *ce, struct stat *st)
+static int check_removed(const struct cache_entry *ce, struct stat *st)
{
- assert(is_fsmonitor_refreshed(istate));
- if (!(ce->ce_flags & CE_FSMONITOR_VALID) && lstat(ce->name, st) < 0) {
+ if (lstat(ce->name, st) < 0) {
if (!is_missing_file_error(errno))
return -1;
return 1;
}
+
if (has_symlink_leading_path(ce->name, ce_namelen(ce)))
return 1;
if (S_ISDIR(st->st_mode)) {
@@ -96,7 +96,7 @@ static int match_stat_with_submodule(struct diff_options *diffopt,
return changed;
}
-int run_diff_files(struct rev_info *revs, unsigned int option)
+void run_diff_files(struct rev_info *revs, unsigned int option)
{
int entries, i;
int diff_unmerged_stage = revs->max_count;
@@ -149,7 +149,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
memset(&(dpath->parent[0]), 0,
sizeof(struct combine_diff_parent)*5);
- changed = check_removed(istate, ce, &st);
+ changed = check_removed(ce, &st);
if (!changed)
wt_mode = ce_mode_from_stat(ce, st.st_mode);
else {
@@ -229,7 +229,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
} else {
struct stat st;
- changed = check_removed(istate, ce, &st);
+ changed = check_removed(ce, &st);
if (changed) {
if (changed < 0) {
perror(ce->name);
@@ -272,7 +272,6 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
trace_performance_since(start, "diff-files");
- return 0;
}
/*
@@ -304,7 +303,7 @@ static int get_stat_data(const struct index_state *istate,
if (!cached && !ce_uptodate(ce)) {
int changed;
struct stat st;
- changed = check_removed(istate, ce, &st);
+ changed = check_removed(ce, &st);
if (changed < 0)
return -1;
else if (changed) {
@@ -606,7 +605,7 @@ void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb)
free_commit_list(merge_bases);
}
-int run_diff_index(struct rev_info *revs, unsigned int option)
+void run_diff_index(struct rev_info *revs, unsigned int option)
{
struct object_array_entry *ent;
int cached = !!(option & DIFF_INDEX_CACHED);
@@ -640,7 +639,6 @@ int run_diff_index(struct rev_info *revs, unsigned int option)
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
trace_performance_leave("diff-index");
- return 0;
}
int do_diff_cache(const struct object_id *tree_oid, struct diff_options *opt)
@@ -682,7 +680,7 @@ int index_differs_from(struct repository *r,
rev.diffopt.flags.ignore_submodules = flags->ignore_submodules;
}
rev.diffopt.ita_invisible_in_index = ita_invisible_in_index;
- run_diff_index(&rev, 1);
+ run_diff_index(&rev, DIFF_INDEX_CACHED);
has_changes = rev.diffopt.flags.has_changes;
release_revisions(&rev);
return (has_changes != 0);
diff --git a/diff-no-index.c b/diff-no-index.c
index 4771cf02aa..e7041b89e3 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -232,6 +232,7 @@ static int queue_diff(struct diff_options *o,
if (o->flags.reverse_diff) {
SWAP(mode1, mode2);
SWAP(name1, name2);
+ SWAP(special1, special2);
}
d1 = noindex_filespec(name1, mode1, special1);
@@ -364,7 +365,7 @@ int diff_no_index(struct rev_info *revs,
* The return code for --no-index imitates diff(1):
* 0 = no changes, 1 = changes, else error
*/
- ret = diff_result_code(&revs->diffopt, 0);
+ ret = diff_result_code(&revs->diffopt);
out:
for (i = 0; i < ARRAY_SIZE(to_free); i++)
diff --git a/diff.c b/diff.c
index ee3eb629e3..bccb018da4 100644
--- a/diff.c
+++ b/diff.c
@@ -3563,18 +3563,21 @@ static void builtin_diff(const char *name_a,
strbuf_addf(&header, "%s%snew file mode %06o%s\n", line_prefix, meta, two->mode, reset);
if (xfrm_msg)
strbuf_addstr(&header, xfrm_msg);
+ o->found_changes = 1;
must_show_header = 1;
}
else if (lbl[1][0] == '/') {
strbuf_addf(&header, "%s%sdeleted file mode %06o%s\n", line_prefix, meta, one->mode, reset);
if (xfrm_msg)
strbuf_addstr(&header, xfrm_msg);
+ o->found_changes = 1;
must_show_header = 1;
}
else {
if (one->mode != two->mode) {
strbuf_addf(&header, "%s%sold mode %06o%s\n", line_prefix, meta, one->mode, reset);
strbuf_addf(&header, "%s%snew mode %06o%s\n", line_prefix, meta, two->mode, reset);
+ o->found_changes = 1;
must_show_header = 1;
}
if (xfrm_msg)
@@ -4832,6 +4835,10 @@ void diff_setup_done(struct diff_options *options)
else
options->prefix_length = 0;
+ /*
+ * --name-only, --name-status, --checkdiff, and -s
+ * turn other output format off.
+ */
if (options->output_format & (DIFF_FORMAT_NAME |
DIFF_FORMAT_NAME_STATUS |
DIFF_FORMAT_CHECKDIFF |
@@ -6206,6 +6213,8 @@ static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
fprintf(opt->file, "%s", diff_line_prefix(opt));
write_name_quoted(name_a, opt->file, opt->line_termination);
}
+
+ opt->found_changes = 1;
}
static void show_file_mode_name(struct diff_options *opt, const char *newdelete, struct diff_filespec *fs)
@@ -6684,6 +6693,21 @@ void diff_flush(struct diff_options *options)
separator++;
}
+ if (output_format & DIFF_FORMAT_PATCH) {
+ if (separator) {
+ emit_diff_symbol(options, DIFF_SYMBOL_SEPARATOR, NULL, 0, 0);
+ if (options->stat_sep)
+ /* attach patch instead of inline */
+ emit_diff_symbol(options, DIFF_SYMBOL_STAT_SEP,
+ NULL, 0, 0);
+ }
+
+ diff_flush_patch_all_file_pairs(options);
+ }
+
+ if (output_format & DIFF_FORMAT_CALLBACK)
+ options->format_callback(q, options, options->format_callback_data);
+
if (output_format & DIFF_FORMAT_NO_OUTPUT &&
options->flags.exit_with_status &&
options->flags.diff_from_contents) {
@@ -6705,21 +6729,6 @@ void diff_flush(struct diff_options *options)
}
}
- if (output_format & DIFF_FORMAT_PATCH) {
- if (separator) {
- emit_diff_symbol(options, DIFF_SYMBOL_SEPARATOR, NULL, 0, 0);
- if (options->stat_sep)
- /* attach patch instead of inline */
- emit_diff_symbol(options, DIFF_SYMBOL_STAT_SEP,
- NULL, 0, 0);
- }
-
- diff_flush_patch_all_file_pairs(options);
- }
-
- if (output_format & DIFF_FORMAT_CALLBACK)
- options->format_callback(q, options, options->format_callback_data);
-
free_queue:
diff_free_queue(q);
DIFF_QUEUE_CLEAR(q);
@@ -6973,16 +6982,14 @@ void diffcore_std(struct diff_options *options)
options->found_follow = 0;
}
-int diff_result_code(struct diff_options *opt, int status)
+int diff_result_code(struct diff_options *opt)
{
int result = 0;
diff_warn_rename_limit("diff.renameLimit",
opt->needed_rename_limit,
opt->degraded_cc_to_c);
- if (!opt->flags.exit_with_status &&
- !(opt->output_format & DIFF_FORMAT_CHECKDIFF))
- return status;
+
if (opt->flags.exit_with_status &&
opt->flags.has_changes)
result |= 01;
@@ -7029,6 +7036,7 @@ void compute_diffstat(struct diff_options *options,
if (check_pair_status(p))
diff_flush_stat(p, options, diffstat);
}
+ options->found_changes = !!diffstat->nr;
}
void diff_addremove(struct diff_options *options,
diff --git a/diff.h b/diff.h
index 260c454155..caf1528bf0 100644
--- a/diff.h
+++ b/diff.h
@@ -637,17 +637,17 @@ void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb);
#define DIFF_SILENT_ON_REMOVED 01
/* report racily-clean paths as modified */
#define DIFF_RACY_IS_MODIFIED 02
-int run_diff_files(struct rev_info *revs, unsigned int option);
+void run_diff_files(struct rev_info *revs, unsigned int option);
#define DIFF_INDEX_CACHED 01
#define DIFF_INDEX_MERGE_BASE 02
-int run_diff_index(struct rev_info *revs, unsigned int option);
+void run_diff_index(struct rev_info *revs, unsigned int option);
int do_diff_cache(const struct object_id *, struct diff_options *);
int diff_flush_patch_id(struct diff_options *, struct object_id *, int);
void flush_one_hunk(struct object_id *result, git_hash_ctx *ctx);
-int diff_result_code(struct diff_options *, int);
+int diff_result_code(struct diff_options *);
int diff_no_index(struct rev_info *,
int implicit_no_index, int, const char **);
diff --git a/fetch-pack.c b/fetch-pack.c
index 65c1ff4bb4..26999e3b65 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1911,10 +1911,10 @@ static void fetch_pack_setup(void)
if (did_setup)
return;
fetch_pack_config();
- if (0 <= transfer_unpack_limit)
- unpack_limit = transfer_unpack_limit;
- else if (0 <= fetch_unpack_limit)
+ if (0 <= fetch_unpack_limit)
unpack_limit = fetch_unpack_limit;
+ else if (0 <= transfer_unpack_limit)
+ unpack_limit = transfer_unpack_limit;
did_setup = 1;
}
diff --git a/git-compat-util.h b/git-compat-util.h
index d32aa754ae..3e7a59b5ff 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -422,6 +422,10 @@ char *gitdirname(char *);
#define PATH_MAX 4096
#endif
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
typedef uintmax_t timestamp_t;
#define PRItime PRIuMAX
#define parse_timestamp strtoumax
diff --git a/http.c b/http.c
index e138b4b96f..8f71bf00d8 100644
--- a/http.c
+++ b/http.c
@@ -738,18 +738,43 @@ static int redact_sensitive_header(struct strbuf *header, size_t offset)
return ret;
}
+static int match_curl_h2_trace(const char *line, const char **out)
+{
+ const char *p;
+
+ /*
+ * curl prior to 8.1.0 gives us:
+ *
+ * h2h3 [<header-name>: <header-val>]
+ *
+ * Starting in 8.1.0, the first token became just "h2".
+ */
+ if (skip_iprefix(line, "h2h3 [", out) ||
+ skip_iprefix(line, "h2 [", out))
+ return 1;
+
+ /*
+ * curl 8.3.0 uses:
+ * [HTTP/2] [<stream-id>] [<header-name>: <header-val>]
+ * where <stream-id> is numeric.
+ */
+ if (skip_iprefix(line, "[HTTP/2] [", &p)) {
+ while (isdigit(*p))
+ p++;
+ if (skip_prefix(p, "] [", out))
+ return 1;
+ }
+
+ return 0;
+}
+
/* Redact headers in info */
static void redact_sensitive_info_header(struct strbuf *header)
{
const char *sensitive_header;
- /*
- * curl's h2h3 prints headers in info, e.g.:
- * h2h3 [<header-name>: <header-val>]
- */
if (trace_curl_redact &&
- (skip_iprefix(header->buf, "h2h3 [", &sensitive_header) ||
- skip_iprefix(header->buf, "h2 [", &sensitive_header))) {
+ match_curl_h2_trace(header->buf, &sensitive_header)) {
if (redact_sensitive_header(header, sensitive_header - header->buf)) {
/* redaction ate our closing bracket */
strbuf_addch(header, ']');
diff --git a/ref-filter.c b/ref-filter.c
index 1bfaf20fbf..9dbc4f71bd 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -582,9 +582,10 @@ static int contents_atom_parser(struct ref_format *format, struct used_atom *ato
atom->u.contents.option = C_BARE;
else if (!strcmp(arg, "body"))
atom->u.contents.option = C_BODY;
- else if (!strcmp(arg, "size"))
+ else if (!strcmp(arg, "size")) {
+ atom->type = FIELD_ULONG;
atom->u.contents.option = C_LENGTH;
- else if (!strcmp(arg, "signature"))
+ } else if (!strcmp(arg, "signature"))
atom->u.contents.option = C_SIG;
else if (!strcmp(arg, "subject"))
atom->u.contents.option = C_SUB;
@@ -690,9 +691,10 @@ static int raw_atom_parser(struct ref_format *format UNUSED,
{
if (!arg)
atom->u.raw_data.option = RAW_BARE;
- else if (!strcmp(arg, "size"))
+ else if (!strcmp(arg, "size")) {
+ atom->type = FIELD_ULONG;
atom->u.raw_data.option = RAW_LENGTH;
- else
+ } else
return err_bad_arg(err, "raw", arg);
return 0;
}
@@ -1857,7 +1859,8 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct exp
v->s = xmemdupz(buf, buf_size);
v->s_size = buf_size;
} else if (atom->u.raw_data.option == RAW_LENGTH) {
- v->s = xstrfmt("%"PRIuMAX, (uintmax_t)buf_size);
+ v->value = buf_size;
+ v->s = xstrfmt("%"PRIuMAX, v->value);
}
continue;
}
@@ -1883,9 +1886,10 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct exp
v->s = strbuf_detach(&sb, NULL);
} else if (atom->u.contents.option == C_BODY_DEP)
v->s = xmemdupz(bodypos, bodylen);
- else if (atom->u.contents.option == C_LENGTH)
- v->s = xstrfmt("%"PRIuMAX, (uintmax_t)strlen(subpos));
- else if (atom->u.contents.option == C_BODY)
+ else if (atom->u.contents.option == C_LENGTH) {
+ v->value = strlen(subpos);
+ v->s = xstrfmt("%"PRIuMAX, v->value);
+ } else if (atom->u.contents.option == C_BODY)
v->s = xmemdupz(bodypos, nonsiglen);
else if (atom->u.contents.option == C_SIG)
v->s = xmemdupz(sigpos, siglen);
@@ -2265,6 +2269,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
v->s_size = ATOM_SIZE_UNSPECIFIED;
v->handler = append_atom;
+ v->value = 0;
v->atom = atom;
if (*name == '*') {
diff --git a/scalar.c b/scalar.c
index df7358f481..fb2940c2a0 100644
--- a/scalar.c
+++ b/scalar.c
@@ -409,6 +409,7 @@ static int cmd_clone(int argc, const char **argv)
{
const char *branch = NULL;
int full_clone = 0, single_branch = 0, show_progress = isatty(2);
+ int src = 1;
struct option clone_options[] = {
OPT_STRING('b', "branch", &branch, N_("<branch>"),
N_("branch to checkout after clone")),
@@ -417,10 +418,13 @@ static int cmd_clone(int argc, const char **argv)
OPT_BOOL(0, "single-branch", &single_branch,
N_("only download metadata for the branch that will "
"be checked out")),
+ OPT_BOOL(0, "src", &src,
+ N_("create repository within 'src' directory")),
OPT_END(),
};
const char * const clone_usage[] = {
- N_("scalar clone [<options>] [--] <repo> [<dir>]"),
+ N_("scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n"
+ "\t[--[no-]src] <url> [<enlistment>]"),
NULL
};
const char *url;
@@ -456,7 +460,10 @@ static int cmd_clone(int argc, const char **argv)
if (is_directory(enlistment))
die(_("directory '%s' exists already"), enlistment);
- dir = xstrfmt("%s/src", enlistment);
+ if (src)
+ dir = xstrfmt("%s/src", enlistment);
+ else
+ dir = xstrdup(enlistment);
strbuf_reset(&buf);
if (branch)
@@ -657,6 +664,7 @@ static int cmd_reconfigure(int argc, const char **argv)
git_config(get_scalar_repos, &scalar_repos);
for (i = 0; i < scalar_repos.nr; i++) {
+ int succeeded = 0;
const char *dir = scalar_repos.items[i].string;
strbuf_reset(&commondir);
@@ -667,30 +675,56 @@ static int cmd_reconfigure(int argc, const char **argv)
if (errno != ENOENT) {
warning_errno(_("could not switch to '%s'"), dir);
- res = -1;
- continue;
+ goto loop_end;
}
strbuf_addstr(&buf, dir);
if (remove_deleted_enlistment(&buf))
- res = error(_("could not remove stale "
- "scalar.repo '%s'"), dir);
- else
- warning(_("removing stale scalar.repo '%s'"),
+ error(_("could not remove stale "
+ "scalar.repo '%s'"), dir);
+ else {
+ warning(_("removed stale scalar.repo '%s'"),
dir);
+ succeeded = 1;
+ }
strbuf_release(&buf);
- } else if (discover_git_directory(&commondir, &gitdir) < 0) {
- warning_errno(_("git repository gone in '%s'"), dir);
- res = -1;
- } else {
- git_config_clear();
+ goto loop_end;
+ }
+
+ switch (discover_git_directory_reason(&commondir, &gitdir)) {
+ case GIT_DIR_INVALID_OWNERSHIP:
+ warning(_("repository at '%s' has different owner"), dir);
+ goto loop_end;
+
+ case GIT_DIR_INVALID_GITFILE:
+ case GIT_DIR_INVALID_FORMAT:
+ warning(_("repository at '%s' has a format issue"), dir);
+ goto loop_end;
+
+ case GIT_DIR_DISCOVERED:
+ succeeded = 1;
+ break;
+
+ default:
+ warning(_("repository not found in '%s'"), dir);
+ break;
+ }
- the_repository = &r;
- r.commondir = commondir.buf;
- r.gitdir = gitdir.buf;
+ git_config_clear();
- if (set_recommended_config(1) < 0)
- res = -1;
+ the_repository = &r;
+ r.commondir = commondir.buf;
+ r.gitdir = gitdir.buf;
+
+ if (set_recommended_config(1) >= 0)
+ succeeded = 1;
+
+loop_end:
+ if (!succeeded) {
+ res = -1;
+ warning(_("to unregister this repository from Scalar, run\n"
+ "\tgit config --global --unset --fixed-value scalar.repo \"%s\""),
+ dir);
}
}
diff --git a/sequencer.c b/sequencer.c
index 5e0c15a16b..81e1ad5832 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -51,6 +51,15 @@
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
+/*
+ * To accommodate common filesystem limitations, where the loose refs' file
+ * names must not exceed `NAME_MAX`, the labels generated by `git rebase
+ * --rebase-merges` need to be truncated if the corresponding commit subjects
+ * are too long.
+ * Add some margin to stay clear from reaching `NAME_MAX`.
+ */
+#define GIT_MAX_LABEL_LENGTH ((NAME_MAX) - (LOCK_SUFFIX_LEN) - 16)
+
static const char sign_off_header[] = "Signed-off-by: ";
static const char cherry_picked_prefix[] = "(cherry picked from commit ";
@@ -139,6 +148,11 @@ static GIT_PATH_FUNC(rebase_path_amend, "rebase-merge/amend")
*/
static GIT_PATH_FUNC(rebase_path_stopped_sha, "rebase-merge/stopped-sha")
/*
+ * When we stop for the user to resolve conflicts this file contains
+ * the patch of the commit that is being picked.
+ */
+static GIT_PATH_FUNC(rebase_path_patch, "rebase-merge/patch")
+/*
* For the post-rewrite hook, we make a list of rewritten commits and
* their new sha1s. The rewritten-pending list keeps the sha1s of
* commits that have been processed, but not committed yet,
@@ -3392,7 +3406,8 @@ give_advice:
return -1;
}
-static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
+static int save_todo(struct todo_list *todo_list, struct replay_opts *opts,
+ int reschedule)
{
struct lock_file todo_lock = LOCK_INIT;
const char *todo_path = get_todo_path(opts);
@@ -3402,7 +3417,7 @@ static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
* rebase -i writes "git-rebase-todo" without the currently executing
* command, appending it to "done" instead.
*/
- if (is_rebase_i(opts))
+ if (is_rebase_i(opts) && !reschedule)
next++;
fd = hold_lock_file_for_update(&todo_lock, todo_path, 0);
@@ -3415,7 +3430,7 @@ static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
if (commit_lock_file(&todo_lock) < 0)
return error(_("failed to finalize '%s'"), todo_path);
- if (is_rebase_i(opts) && next > 0) {
+ if (is_rebase_i(opts) && !reschedule && next > 0) {
const char *done = rebase_path_done();
int fd = open(done, O_CREAT | O_WRONLY | O_APPEND, 0666);
int ret = 0;
@@ -3496,18 +3511,19 @@ static int make_patch(struct repository *r,
struct commit *commit,
struct replay_opts *opts)
{
- struct strbuf buf = STRBUF_INIT;
struct rev_info log_tree_opt;
const char *subject;
char hex[GIT_MAX_HEXSZ + 1];
int res = 0;
+ if (!is_rebase_i(opts))
+ BUG("make_patch should only be called when rebasing");
+
oid_to_hex_r(hex, &commit->object.oid);
if (write_message(hex, strlen(hex), rebase_path_stopped_sha(), 1) < 0)
return -1;
res |= write_rebase_head(&commit->object.oid);
- strbuf_addf(&buf, "%s/patch", get_dir(opts));
memset(&log_tree_opt, 0, sizeof(log_tree_opt));
repo_init_revisions(r, &log_tree_opt, NULL);
log_tree_opt.abbrev = 0;
@@ -3515,28 +3531,26 @@ static int make_patch(struct repository *r,
log_tree_opt.diffopt.output_format = DIFF_FORMAT_PATCH;
log_tree_opt.disable_stdin = 1;
log_tree_opt.no_commit_id = 1;
- log_tree_opt.diffopt.file = fopen(buf.buf, "w");
+ log_tree_opt.diffopt.file = fopen(rebase_path_patch(), "w");
log_tree_opt.diffopt.use_color = GIT_COLOR_NEVER;
if (!log_tree_opt.diffopt.file)
- res |= error_errno(_("could not open '%s'"), buf.buf);
+ res |= error_errno(_("could not open '%s'"),
+ rebase_path_patch());
else {
res |= log_tree_commit(&log_tree_opt, commit);
fclose(log_tree_opt.diffopt.file);
}
- strbuf_reset(&buf);
- strbuf_addf(&buf, "%s/message", get_dir(opts));
- if (!file_exists(buf.buf)) {
+ if (!file_exists(rebase_path_message())) {
const char *encoding = get_commit_output_encoding();
const char *commit_buffer = repo_logmsg_reencode(r,
commit, NULL,
encoding);
find_commit_subject(commit_buffer, &subject);
- res |= write_message(subject, strlen(subject), buf.buf, 1);
+ res |= write_message(subject, strlen(subject), rebase_path_message(), 1);
repo_unuse_commit_buffer(r, commit,
commit_buffer);
}
- strbuf_release(&buf);
release_revisions(&log_tree_opt);
return res;
@@ -4154,6 +4168,7 @@ static int do_merge(struct repository *r,
if (ret < 0) {
error(_("could not even attempt to merge '%.*s'"),
merge_arg_len, arg);
+ unlink(git_path_merge_msg(r));
goto leave_merge;
}
/*
@@ -4641,6 +4656,68 @@ N_("Could not execute the todo command\n"
" git rebase --edit-todo\n"
" git rebase --continue\n");
+static int pick_one_commit(struct repository *r,
+ struct todo_list *todo_list,
+ struct replay_opts *opts,
+ int *check_todo, int* reschedule)
+{
+ int res;
+ struct todo_item *item = todo_list->items + todo_list->current;
+ const char *arg = todo_item_get_arg(todo_list, item);
+ if (is_rebase_i(opts))
+ opts->reflog_message = reflog_message(
+ opts, command_to_string(item->command), NULL);
+
+ res = do_pick_commit(r, item, opts, is_final_fixup(todo_list),
+ check_todo);
+ if (is_rebase_i(opts) && res < 0) {
+ /* Reschedule */
+ *reschedule = 1;
+ return -1;
+ }
+ if (item->command == TODO_EDIT) {
+ struct commit *commit = item->commit;
+ if (!res) {
+ if (!opts->verbose)
+ term_clear_line();
+ fprintf(stderr, _("Stopped at %s... %.*s\n"),
+ short_commit_name(commit), item->arg_len, arg);
+ }
+ return error_with_patch(r, commit,
+ arg, item->arg_len, opts, res, !res);
+ }
+ if (is_rebase_i(opts) && !res)
+ record_in_rewritten(&item->commit->object.oid,
+ peek_command(todo_list, 1));
+ if (res && is_fixup(item->command)) {
+ if (res == 1)
+ intend_to_amend();
+ return error_failed_squash(r, item->commit, opts,
+ item->arg_len, arg);
+ } else if (res && is_rebase_i(opts) && item->commit) {
+ int to_amend = 0;
+ struct object_id oid;
+
+ /*
+ * If we are rewording and have either
+ * fast-forwarded already, or are about to
+ * create a new root commit, we want to amend,
+ * otherwise we do not.
+ */
+ if (item->command == TODO_REWORD &&
+ !repo_get_oid(r, "HEAD", &oid) &&
+ (oideq(&item->commit->object.oid, &oid) ||
+ (opts->have_squash_onto &&
+ oideq(&opts->squash_onto, &oid))))
+ to_amend = 1;
+
+ return res | error_with_patch(r, item->commit,
+ arg, item->arg_len, opts,
+ res, to_amend);
+ }
+ return res;
+}
+
static int pick_commits(struct repository *r,
struct todo_list *todo_list,
struct replay_opts *opts)
@@ -4656,12 +4733,17 @@ static int pick_commits(struct repository *r,
if (read_and_refresh_cache(r, opts))
return -1;
+ unlink(rebase_path_message());
+ unlink(rebase_path_stopped_sha());
+ unlink(rebase_path_amend());
+ unlink(rebase_path_patch());
+
while (todo_list->current < todo_list->nr) {
struct todo_item *item = todo_list->items + todo_list->current;
const char *arg = todo_item_get_arg(todo_list, item);
int check_todo = 0;
- if (save_todo(todo_list, opts))
+ if (save_todo(todo_list, opts, reschedule))
return -1;
if (is_rebase_i(opts)) {
if (item->command != TODO_COMMENT) {
@@ -4679,10 +4761,7 @@ static int pick_commits(struct repository *r,
todo_list->total_nr,
opts->verbose ? "\n" : "\r");
}
- unlink(rebase_path_message());
unlink(rebase_path_author_script());
- unlink(rebase_path_stopped_sha());
- unlink(rebase_path_amend());
unlink(git_path_merge_head(r));
unlink(git_path_auto_merge(r));
delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
@@ -4694,66 +4773,10 @@ static int pick_commits(struct repository *r,
}
}
if (item->command <= TODO_SQUASH) {
- if (is_rebase_i(opts))
- opts->reflog_message = reflog_message(opts,
- command_to_string(item->command), NULL);
-
- res = do_pick_commit(r, item, opts,
- is_final_fixup(todo_list),
- &check_todo);
- if (is_rebase_i(opts) && res < 0) {
- /* Reschedule */
- advise(_(rescheduled_advice),
- get_item_line_length(todo_list,
- todo_list->current),
- get_item_line(todo_list,
- todo_list->current));
- todo_list->current--;
- if (save_todo(todo_list, opts))
- return -1;
- }
- if (item->command == TODO_EDIT) {
- struct commit *commit = item->commit;
- if (!res) {
- if (!opts->verbose)
- term_clear_line();
- fprintf(stderr,
- _("Stopped at %s... %.*s\n"),
- short_commit_name(commit),
- item->arg_len, arg);
- }
- return error_with_patch(r, commit,
- arg, item->arg_len, opts, res, !res);
- }
- if (is_rebase_i(opts) && !res)
- record_in_rewritten(&item->commit->object.oid,
- peek_command(todo_list, 1));
- if (res && is_fixup(item->command)) {
- if (res == 1)
- intend_to_amend();
- return error_failed_squash(r, item->commit, opts,
- item->arg_len, arg);
- } else if (res && is_rebase_i(opts) && item->commit) {
- int to_amend = 0;
- struct object_id oid;
-
- /*
- * If we are rewording and have either
- * fast-forwarded already, or are about to
- * create a new root commit, we want to amend,
- * otherwise we do not.
- */
- if (item->command == TODO_REWORD &&
- !repo_get_oid(r, "HEAD", &oid) &&
- (oideq(&item->commit->object.oid, &oid) ||
- (opts->have_squash_onto &&
- oideq(&opts->squash_onto, &oid))))
- to_amend = 1;
-
- return res | error_with_patch(r, item->commit,
- arg, item->arg_len, opts,
- res, to_amend);
- }
+ res = pick_one_commit(r, todo_list, opts, &check_todo,
+ &reschedule);
+ if (!res && item->command == TODO_EDIT)
+ return 0;
} else if (item->command == TODO_EXEC) {
char *end_of_arg = (char *)(arg + item->arg_len);
int saved = *end_of_arg;
@@ -4801,22 +4824,19 @@ static int pick_commits(struct repository *r,
get_item_line_length(todo_list,
todo_list->current),
get_item_line(todo_list, todo_list->current));
- todo_list->current--;
- if (save_todo(todo_list, opts))
+ if (save_todo(todo_list, opts, reschedule))
return -1;
if (item->commit)
- return error_with_patch(r,
- item->commit,
- arg, item->arg_len,
- opts, res, 0);
+ write_rebase_head(&item->commit->object.oid);
} else if (is_rebase_i(opts) && check_todo && !res &&
reread_todo_if_changed(r, todo_list, opts)) {
return -1;
}
- todo_list->current++;
if (res)
return res;
+
+ todo_list->current++;
}
if (is_rebase_i(opts)) {
@@ -4969,6 +4989,11 @@ static int commit_staged_changes(struct repository *r,
is_clean = !has_uncommitted_changes(r, 0);
+ if (!is_clean && !file_exists(rebase_path_message())) {
+ const char *gpg_opt = gpg_sign_opt_quoted(opts);
+
+ return error(_(staged_changes_advice), gpg_opt, gpg_opt);
+ }
if (file_exists(rebase_path_amend())) {
struct strbuf rev = STRBUF_INIT;
struct object_id head, to_amend;
@@ -5352,6 +5377,7 @@ struct label_state {
struct oidmap commit2label;
struct hashmap labels;
struct strbuf buf;
+ int max_label_length;
};
static const char *label_oid(struct object_id *oid, const char *label,
@@ -5408,6 +5434,8 @@ static const char *label_oid(struct object_id *oid, const char *label,
}
} else {
struct strbuf *buf = &state->buf;
+ int label_is_utf8 = 1; /* start with this assumption */
+ size_t max_len = buf->len + state->max_label_length;
/*
* Sanitize labels by replacing non-alpha-numeric characters
@@ -5416,14 +5444,34 @@ static const char *label_oid(struct object_id *oid, const char *label,
*
* Note that we retain non-ASCII UTF-8 characters (identified
* via the most significant bit). They should be all acceptable
- * in file names. We do not validate the UTF-8 here, that's not
- * the job of this function.
+ * in file names.
+ *
+ * As we will use the labels as names of (loose) refs, it is
+ * vital that the name not be longer than the maximum component
+ * size of the file system (`NAME_MAX`). We are careful to
+ * truncate the label accordingly, allowing for the `.lock`
+ * suffix and for the label to be UTF-8 encoded (i.e. we avoid
+ * truncating in the middle of a character).
*/
- for (; *label; label++)
- if ((*label & 0x80) || isalnum(*label))
+ for (; *label && buf->len + 1 < max_len; label++)
+ if (isalnum(*label) ||
+ (!label_is_utf8 && (*label & 0x80)))
strbuf_addch(buf, *label);
+ else if (*label & 0x80) {
+ const char *p = label;
+
+ utf8_width(&p, NULL);
+ if (p) {
+ if (buf->len + (p - label) > max_len)
+ break;
+ strbuf_add(buf, label, p - label);
+ label = p - 1;
+ } else {
+ label_is_utf8 = 0;
+ strbuf_addch(buf, *label);
+ }
/* avoid leading dash and double-dashes */
- else if (buf->len && buf->buf[buf->len - 1] != '-')
+ } else if (buf->len && buf->buf[buf->len - 1] != '-')
strbuf_addch(buf, '-');
if (!buf->len) {
strbuf_addstr(buf, "rev-");
@@ -5485,7 +5533,8 @@ static int make_script_with_merges(struct pretty_print_context *pp,
struct string_entry *entry;
struct oidset interesting = OIDSET_INIT, child_seen = OIDSET_INIT,
shown = OIDSET_INIT;
- struct label_state state = { OIDMAP_INIT, { NULL }, STRBUF_INIT };
+ struct label_state state =
+ { OIDMAP_INIT, { NULL }, STRBUF_INIT, GIT_MAX_LABEL_LENGTH };
int abbr = flags & TODO_LIST_ABBREVIATE_CMDS;
const char *cmd_pick = abbr ? "p" : "pick",
@@ -5493,6 +5542,8 @@ static int make_script_with_merges(struct pretty_print_context *pp,
*cmd_reset = abbr ? "t" : "reset",
*cmd_merge = abbr ? "m" : "merge";
+ git_config_get_int("rebase.maxlabellength", &state.max_label_length);
+
oidmap_init(&commit2todo, 0);
oidmap_init(&state.commit2label, 0);
hashmap_init(&state.labels, labels_cmp, NULL, 0);
@@ -6194,7 +6245,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
if (checkout_onto(r, opts, onto_name, &oid, orig_head))
goto cleanup;
- if (require_clean_work_tree(r, "rebase", "", 1, 1))
+ if (require_clean_work_tree(r, "rebase", NULL, 1, 1))
goto cleanup;
todo_list_write_total_nr(&new_todo);
diff --git a/setup.c b/setup.c
index 18927a847b..2e607632db 100644
--- a/setup.c
+++ b/setup.c
@@ -1221,19 +1221,6 @@ static const char *allowed_bare_repo_to_string(
return NULL;
}
-enum discovery_result {
- GIT_DIR_NONE = 0,
- GIT_DIR_EXPLICIT,
- GIT_DIR_DISCOVERED,
- GIT_DIR_BARE,
- /* these are errors */
- GIT_DIR_HIT_CEILING = -1,
- GIT_DIR_HIT_MOUNT_POINT = -2,
- GIT_DIR_INVALID_GITFILE = -3,
- GIT_DIR_INVALID_OWNERSHIP = -4,
- GIT_DIR_DISALLOWED_BARE = -5,
-};
-
/*
* We cannot decide in this function whether we are in the work tree or
* not, since the config can only be read _after_ this function was called.
@@ -1385,21 +1372,23 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
}
}
-int discover_git_directory(struct strbuf *commondir,
- struct strbuf *gitdir)
+enum discovery_result discover_git_directory_reason(struct strbuf *commondir,
+ struct strbuf *gitdir)
{
struct strbuf dir = STRBUF_INIT, err = STRBUF_INIT;
size_t gitdir_offset = gitdir->len, cwd_len;
size_t commondir_offset = commondir->len;
struct repository_format candidate = REPOSITORY_FORMAT_INIT;
+ enum discovery_result result;
if (strbuf_getcwd(&dir))
- return -1;
+ return GIT_DIR_CWD_FAILURE;
cwd_len = dir.len;
- if (setup_git_directory_gently_1(&dir, gitdir, NULL, 0) <= 0) {
+ result = setup_git_directory_gently_1(&dir, gitdir, NULL, 0);
+ if (result <= 0) {
strbuf_release(&dir);
- return -1;
+ return result;
}
/*
@@ -1429,11 +1418,11 @@ int discover_git_directory(struct strbuf *commondir,
strbuf_setlen(commondir, commondir_offset);
strbuf_setlen(gitdir, gitdir_offset);
clear_repository_format(&candidate);
- return -1;
+ return GIT_DIR_INVALID_FORMAT;
}
clear_repository_format(&candidate);
- return 0;
+ return result;
}
const char *setup_git_directory_gently(int *nongit_ok)
@@ -1515,10 +1504,11 @@ const char *setup_git_directory_gently(int *nongit_ok)
}
*nongit_ok = 1;
break;
- case GIT_DIR_NONE:
+ case GIT_DIR_CWD_FAILURE:
+ case GIT_DIR_INVALID_FORMAT:
/*
* As a safeguard against setup_git_directory_gently_1 returning
- * this value, fallthrough to BUG. Otherwise it is possible to
+ * these values, fallthrough to BUG. Otherwise it is possible to
* set startup_info->have_repository to 1 when we did nothing to
* find a repository.
*/
diff --git a/setup.h b/setup.h
index 58fd2605dd..b48cf1c43b 100644
--- a/setup.h
+++ b/setup.h
@@ -42,16 +42,45 @@ const char *resolve_gitdir_gently(const char *suspect, int *return_error_code);
#define resolve_gitdir(path) resolve_gitdir_gently((path), NULL)
void setup_work_tree(void);
+
+/*
+ * discover_git_directory_reason() is similar to discover_git_directory(),
+ * except it returns an enum value instead. It is important to note that
+ * a zero-valued return here is actually GIT_DIR_NONE, which is different
+ * from discover_git_directory.
+ */
+enum discovery_result {
+ GIT_DIR_EXPLICIT = 1,
+ GIT_DIR_DISCOVERED = 2,
+ GIT_DIR_BARE = 3,
+ /* these are errors */
+ GIT_DIR_HIT_CEILING = -1,
+ GIT_DIR_HIT_MOUNT_POINT = -2,
+ GIT_DIR_INVALID_GITFILE = -3,
+ GIT_DIR_INVALID_OWNERSHIP = -4,
+ GIT_DIR_DISALLOWED_BARE = -5,
+ GIT_DIR_INVALID_FORMAT = -6,
+ GIT_DIR_CWD_FAILURE = -7,
+};
+enum discovery_result discover_git_directory_reason(struct strbuf *commondir,
+ struct strbuf *gitdir);
+
/*
* Find the commondir and gitdir of the repository that contains the current
* working directory, without changing the working directory or other global
* state. The result is appended to commondir and gitdir. If the discovered
* gitdir does not correspond to a worktree, then 'commondir' and 'gitdir' will
* both have the same result appended to the buffer. The return value is
- * either 0 upon success and non-zero if no repository was found.
+ * either 0 upon success and -1 if no repository was found.
*/
-int discover_git_directory(struct strbuf *commondir,
- struct strbuf *gitdir);
+static inline int discover_git_directory(struct strbuf *commondir,
+ struct strbuf *gitdir)
+{
+ if (discover_git_directory_reason(commondir, gitdir) <= 0)
+ return -1;
+ return 0;
+}
+
const char *setup_git_directory_gently(int *);
const char *setup_git_directory(void);
char *prefix_path(const char *prefix, int len, const char *path);
diff --git a/t/t3321-notes-stripspace.sh b/t/t3321-notes-stripspace.sh
index 028d825e8f..36abdca5ee 100755
--- a/t/t3321-notes-stripspace.sh
+++ b/t/t3321-notes-stripspace.sh
@@ -5,6 +5,7 @@
test_description='Test commit notes with stripspace behavior'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
MULTI_LF="$LF$LF$LF"
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 96a56aafbe..939fe8dfbc 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -604,7 +604,8 @@ test_expect_success 'clean error after failed "exec"' '
echo "edited again" > file7 &&
git add file7 &&
test_must_fail git rebase --continue 2>error &&
- test_i18ngrep "you have staged changes in your working tree" error
+ test_i18ngrep "you have staged changes in your working tree" error &&
+ test_i18ngrep ! "could not open.*for reading" error
'
test_expect_success 'rebase a detached HEAD' '
@@ -1276,20 +1277,34 @@ test_expect_success 'todo count' '
'
test_expect_success 'rebase -i commits that overwrite untracked files (pick)' '
- git checkout --force branch2 &&
+ git checkout --force A &&
git clean -f &&
+ cat >todo <<-EOF &&
+ exec >file2
+ pick $(git rev-parse B) B
+ pick $(git rev-parse C) C
+ pick $(git rev-parse D) D
+ exec cat .git/rebase-merge/done >actual
+ EOF
(
- set_fake_editor &&
- FAKE_LINES="edit 1 2" git rebase -i A
- ) &&
- test_cmp_rev HEAD F &&
- test_path_is_missing file6 &&
- >file6 &&
- test_must_fail git rebase --continue &&
- test_cmp_rev HEAD F &&
- rm file6 &&
+ set_replace_editor todo &&
+ test_must_fail git rebase -i A
+ ) &&
+ test_cmp_rev HEAD B &&
+ test_cmp_rev REBASE_HEAD C &&
+ head -n3 todo >expect &&
+ test_cmp expect .git/rebase-merge/done &&
+ rm file2 &&
+ test_path_is_missing .git/rebase-merge/patch &&
+ echo changed >file1 &&
+ git add file1 &&
+ test_must_fail git rebase --continue 2>err &&
+ grep "error: you have staged changes in your working tree" err &&
+ git reset --hard HEAD &&
git rebase --continue &&
- test_cmp_rev HEAD I
+ test_cmp_rev HEAD D &&
+ tail -n3 todo >>expect &&
+ test_cmp expect actual
'
test_expect_success 'rebase -i commits that overwrite untracked files (squash)' '
@@ -1305,7 +1320,14 @@ test_expect_success 'rebase -i commits that overwrite untracked files (squash)'
>file6 &&
test_must_fail git rebase --continue &&
test_cmp_rev HEAD F &&
+ test_cmp_rev REBASE_HEAD I &&
rm file6 &&
+ test_path_is_missing .git/rebase-merge/patch &&
+ echo changed >file1 &&
+ git add file1 &&
+ test_must_fail git rebase --continue 2>err &&
+ grep "error: you have staged changes in your working tree" err &&
+ git reset --hard HEAD &&
git rebase --continue &&
test $(git cat-file commit HEAD | sed -ne \$p) = I &&
git reset --hard original-branch2
@@ -1323,7 +1345,14 @@ test_expect_success 'rebase -i commits that overwrite untracked files (no ff)' '
>file6 &&
test_must_fail git rebase --continue &&
test $(git cat-file commit HEAD | sed -ne \$p) = F &&
+ test_cmp_rev REBASE_HEAD I &&
rm file6 &&
+ test_path_is_missing .git/rebase-merge/patch &&
+ echo changed >file1 &&
+ git add file1 &&
+ test_must_fail git rebase --continue 2>err &&
+ grep "error: you have staged changes in your working tree" err &&
+ git reset --hard HEAD &&
git rebase --continue &&
test $(git cat-file commit HEAD | sed -ne \$p) = I
'
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index fb7b68990c..c4e2fcac67 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -268,6 +268,24 @@ test_expect_success 'the todo command "break" works' '
test_path_is_file execed
'
+test_expect_success 'patch file is removed before break command' '
+ test_when_finished "git rebase --abort" &&
+ cat >todo <<-\EOF &&
+ pick commit-new-file-F2-on-topic-branch
+ break
+ EOF
+
+ (
+ set_replace_editor todo &&
+ test_must_fail git rebase -i --onto commit-new-file-F2 HEAD
+ ) &&
+ test_path_is_file .git/rebase-merge/patch &&
+ echo 22>F2 &&
+ git add F2 &&
+ git rebase --continue &&
+ test_path_is_missing .git/rebase-merge/patch
+'
+
test_expect_success '--reschedule-failed-exec' '
test_when_finished "git rebase --abort" &&
test_must_fail git rebase -x false --reschedule-failed-exec HEAD^ &&
diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh
index 96ae0edf1e..59b5d6b6f2 100755
--- a/t/t3430-rebase-merges.sh
+++ b/t/t3430-rebase-merges.sh
@@ -128,14 +128,24 @@ test_expect_success 'generate correct todo list' '
'
test_expect_success '`reset` refuses to overwrite untracked files' '
- git checkout -b refuse-to-reset &&
+ git checkout B &&
test_commit dont-overwrite-untracked &&
- git checkout @{-1} &&
- : >dont-overwrite-untracked.t &&
- echo "reset refs/tags/dont-overwrite-untracked" >script-from-scratch &&
+ cat >script-from-scratch <<-EOF &&
+ exec >dont-overwrite-untracked.t
+ pick $(git rev-parse B) B
+ reset refs/tags/dont-overwrite-untracked
+ pick $(git rev-parse C) C
+ exec cat .git/rebase-merge/done >actual
+ EOF
test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
- test_must_fail git rebase -ir HEAD &&
- git rebase --abort
+ test_must_fail git rebase -ir A &&
+ test_cmp_rev HEAD B &&
+ head -n3 script-from-scratch >expect &&
+ test_cmp expect .git/rebase-merge/done &&
+ rm dont-overwrite-untracked.t &&
+ git rebase --continue &&
+ tail -n3 script-from-scratch >>expect &&
+ test_cmp expect actual
'
test_expect_success '`reset` rejects trees' '
@@ -165,12 +175,16 @@ test_expect_success 'failed `merge -C` writes patch (may be rescheduled, too)' '
test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
test_tick &&
test_must_fail git rebase -ir HEAD &&
+ test_cmp_rev REBASE_HEAD H^0 &&
grep "^merge -C .* G$" .git/rebase-merge/done &&
grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
- test_path_is_file .git/rebase-merge/patch &&
+ test_path_is_missing .git/rebase-merge/patch &&
+ echo changed >file1 &&
+ git add file1 &&
+ test_must_fail git rebase --continue 2>err &&
+ grep "error: you have staged changes in your working tree" err &&
: fail because of merge conflict &&
- rm G.t .git/rebase-merge/patch &&
git reset --hard conflicting-G &&
test_must_fail git rebase --continue &&
! grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
@@ -586,4 +600,15 @@ test_expect_success 'progress shows the correct total' '
test_line_count = 14 progress
'
+test_expect_success 'truncate label names' '
+ commit=$(git commit-tree -p HEAD^ -p HEAD -m "0123456789 我 123" HEAD^{tree}) &&
+ git merge --ff-only $commit &&
+
+ done="$(git rev-parse --git-path rebase-merge/done)" &&
+ git -c rebase.maxLabelLength=14 rebase --rebase-merges -x "cp \"$done\" out" --root &&
+ grep "label 0123456789-我$" out &&
+ git -c rebase.maxLabelLength=13 rebase --rebase-merges -x "cp \"$done\" out" --root &&
+ grep "label 0123456789-$" out
+'
+
test_done
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index b298f220e0..fcd2473e52 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -1,7 +1,7 @@
#!/bin/sh
#
# Copyright (c) 2006 Johannes E. Schindelin
-#
+# Copyright (c) 2023 Google LLC
test_description='Test special whitespace in diff engine.
@@ -11,6 +11,43 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh
+for opt_res in --patch --quiet -s --stat --shortstat --dirstat=lines \
+ --raw! --name-only! --name-status!
+do
+ opts=${opt_res%!} expect_failure=
+ test "$opts" = "$opt_res" ||
+ expect_failure="test_expect_code 1"
+
+ test_expect_success "status with $opts (different)" '
+ echo foo >x &&
+ git add x &&
+ echo bar >x &&
+ test_expect_code 1 git diff -w $opts --exit-code x
+ '
+
+ test_expect_success POSIXPERM "status with $opts (mode differs)" '
+ test_when_finished "git update-index --chmod=-x x" &&
+ echo foo >x &&
+ git add x &&
+ git update-index --chmod=+x x &&
+ test_expect_code 1 git diff -w $opts --exit-code x
+ '
+
+ test_expect_success "status with $opts (removing an empty file)" '
+ : >x &&
+ git add x &&
+ rm x &&
+ test_expect_code 1 git diff -w $opts --exit-code -- x
+ '
+
+ test_expect_success "status with $opts (different but equivalent)" '
+ echo foo >x &&
+ git add x &&
+ echo " foo" >x &&
+ $expect_failure git diff -w $opts --exit-code x
+ '
+done
+
test_expect_success "Ray Lehtiniemi's example" '
cat <<-\EOF >x &&
do {
diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh
index 5bc28ad9f0..f439f469bd 100755
--- a/t/t4017-diff-retval.sh
+++ b/t/t4017-diff-retval.sh
@@ -138,4 +138,9 @@ test_expect_success 'check honors conflict marker length' '
git reset --hard
'
+test_expect_success 'option errors are not confused by --exit-code' '
+ test_must_fail git diff --exit-code --nonsense 2>err &&
+ grep '^usage:' err
+'
+
test_done
diff --git a/t/t4040-whitespace-status.sh b/t/t4040-whitespace-status.sh
index e70e020ae9..eec3d73dc2 100755
--- a/t/t4040-whitespace-status.sh
+++ b/t/t4040-whitespace-status.sh
@@ -28,8 +28,7 @@ test_expect_success 'diff-tree --exit-code' '
test_expect_success 'diff-tree -b --exit-code' '
git diff -b --exit-code HEAD^ HEAD &&
- git diff-tree -b -p --exit-code HEAD^ HEAD &&
- git diff-tree -b --exit-code HEAD^ HEAD
+ git diff-tree -b -p --exit-code HEAD^ HEAD
'
test_expect_success 'diff-index --cached --exit-code' '
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 6781cc9078..5f059f65fc 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -224,6 +224,25 @@ test_expect_success "diff --no-index treats '-' as stdin" '
test_must_be_empty actual
'
+test_expect_success "diff --no-index -R treats '-' as stdin" '
+ cat >expect <<-EOF &&
+ diff --git b/a/1 a/-
+ index $(git hash-object --stdin <a/1)..$ZERO_OID 100644
+ --- b/a/1
+ +++ a/-
+ @@ -1 +1 @@
+ -1
+ +x
+ EOF
+
+ test_write_lines x | test_expect_code 1 \
+ git -c core.abbrev=no diff --no-index -R -- - a/1 >actual &&
+ test_cmp expect actual &&
+
+ test_write_lines 1 | git diff --no-index -R -- a/1 - >actual &&
+ test_must_be_empty actual
+'
+
test_expect_success 'diff --no-index refuses to diff stdin and a directory' '
test_must_fail git diff --no-index -- - a </dev/null 2>err &&
grep "fatal: cannot compare stdin to a directory" err
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 4df76173a8..ba65f17dd9 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -450,14 +450,15 @@ GRAPH_BYTE_FANOUT2=$(($GRAPH_FANOUT_OFFSET + 4 * 255))
GRAPH_OID_LOOKUP_OFFSET=$(($GRAPH_FANOUT_OFFSET + 4 * 256))
GRAPH_BYTE_OID_LOOKUP_ORDER=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * 8))
GRAPH_BYTE_OID_LOOKUP_MISSING=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * 4 + 10))
+GRAPH_COMMIT_DATA_WIDTH=$(($HASH_LEN + 16))
GRAPH_COMMIT_DATA_OFFSET=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * $NUM_COMMITS))
GRAPH_BYTE_COMMIT_TREE=$GRAPH_COMMIT_DATA_OFFSET
GRAPH_BYTE_COMMIT_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN))
GRAPH_BYTE_COMMIT_EXTRA_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 4))
GRAPH_BYTE_COMMIT_WRONG_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 3))
GRAPH_BYTE_COMMIT_GENERATION=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 11))
+GRAPH_BYTE_COMMIT_GENERATION_LAST=$(($GRAPH_BYTE_COMMIT_GENERATION + $(($NUM_COMMITS - 1)) * $GRAPH_COMMIT_DATA_WIDTH))
GRAPH_BYTE_COMMIT_DATE=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 12))
-GRAPH_COMMIT_DATA_WIDTH=$(($HASH_LEN + 16))
GRAPH_OCTOPUS_DATA_OFFSET=$(($GRAPH_COMMIT_DATA_OFFSET + \
$GRAPH_COMMIT_DATA_WIDTH * $NUM_COMMITS))
GRAPH_BYTE_OCTOPUS=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4))
@@ -596,11 +597,6 @@ test_expect_success 'detect incorrect generation number' '
"generation for commit"
'
-test_expect_success 'detect incorrect generation number' '
- corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\01" \
- "commit-graph generation for commit"
-'
-
test_expect_success 'detect incorrect commit date' '
corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_DATE "\01" \
"commit date"
@@ -622,6 +618,16 @@ test_expect_success 'detect incorrect chunk count' '
$GRAPH_CHUNK_LOOKUP_OFFSET
'
+test_expect_success 'detect mixed generation numbers (non-zero to zero)' '
+ corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION_LAST "\0\0\0\0" \
+ "both zero and non-zero generations"
+'
+
+test_expect_success 'detect mixed generation numbers (zero to non-zero)' '
+ corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\0\0\0\0" \
+ "both zero and non-zero generations"
+'
+
test_expect_success 'git fsck (checks commit-graph when config set to true)' '
git -C full fsck &&
corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh
index 5f3ff051ca..ad7f8c6f00 100755
--- a/t/t5407-post-rewrite-hook.sh
+++ b/t/t5407-post-rewrite-hook.sh
@@ -17,6 +17,12 @@ test_expect_success 'setup' '
git checkout A^0 &&
test_commit E bar E &&
test_commit F foo F &&
+ git checkout B &&
+ git merge E &&
+ git tag merge-E &&
+ test_commit G G &&
+ test_commit H H &&
+ test_commit I I &&
git checkout main &&
test_hook --setup post-rewrite <<-EOF
@@ -173,6 +179,48 @@ test_fail_interactive_rebase () {
)
}
+test_expect_success 'git rebase with failed pick' '
+ clear_hook_input &&
+ cat >todo <<-\EOF &&
+ exec >bar
+ merge -C merge-E E
+ exec >G
+ pick G
+ exec >H 2>I
+ pick H
+ fixup I
+ EOF
+
+ (
+ set_replace_editor todo &&
+ test_must_fail git rebase -i D D 2>err
+ ) &&
+ grep "would be overwritten" err &&
+ rm bar &&
+
+ test_must_fail git rebase --continue 2>err &&
+ grep "would be overwritten" err &&
+ rm G &&
+
+ test_must_fail git rebase --continue 2>err &&
+ grep "would be overwritten" err &&
+ rm H &&
+
+ test_must_fail git rebase --continue 2>err &&
+ grep "would be overwritten" err &&
+ rm I &&
+
+ git rebase --continue &&
+ echo rebase >expected.args &&
+ cat >expected.data <<-EOF &&
+ $(git rev-parse merge-E) $(git rev-parse HEAD~2)
+ $(git rev-parse G) $(git rev-parse HEAD~1)
+ $(git rev-parse H) $(git rev-parse HEAD)
+ $(git rev-parse I) $(git rev-parse HEAD)
+ EOF
+ verify_hook_input
+'
+
test_expect_success 'git rebase -i (unchanged)' '
git reset --hard D &&
clear_hook_input &&
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 4f289063ce..19c36b57f4 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -1127,6 +1127,52 @@ do
'
done
+test_expect_success 'prepare source branch' '
+ echo one >onebranch &&
+ git checkout --orphan onebranch &&
+ git rm --cached -r . &&
+ git add onebranch &&
+ git commit -m onebranch &&
+ git rev-list --objects onebranch -- >actual &&
+ # 3 objects should be created, at least ...
+ test 3 -le $(wc -l <actual)
+'
+
+validate_store_type () {
+ git -C dest count-objects -v >actual &&
+ case "$store_type" in
+ packed)
+ grep "^count: 0$" actual ;;
+ loose)
+ grep "^packs: 0$" actual ;;
+ esac || {
+ echo "store_type is $store_type"
+ cat actual
+ false
+ }
+}
+
+test_unpack_limit () {
+ store_type=$1
+
+ case "$store_type" in
+ packed) fetch_limit=1 transfer_limit=10000 ;;
+ loose) fetch_limit=10000 transfer_limit=1 ;;
+ esac
+
+ test_expect_success "fetch trumps transfer limit" '
+ rm -fr dest &&
+ git --bare init dest &&
+ git -C dest config fetch.unpacklimit $fetch_limit &&
+ git -C dest config transfer.unpacklimit $transfer_limit &&
+ git -C dest fetch .. onebranch &&
+ validate_store_type
+ '
+}
+
+test_unpack_limit packed
+test_unpack_limit loose
+
setup_negotiation_tip () {
SERVER="$1"
URL="$2"
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
index eed3c9d81a..9fc9ba552f 100755
--- a/t/t5546-receive-limits.sh
+++ b/t/t5546-receive-limits.sh
@@ -9,10 +9,26 @@ TEST_PASSES_SANITIZE_LEAK=true
# When the limit is 1, `git receive-pack` will call `git index-pack`.
# When the limit is 10000, `git receive-pack` will call `git unpack-objects`.
+validate_store_type () {
+ git -C dest count-objects -v >actual &&
+ case "$store_type" in
+ index)
+ grep "^count: 0$" actual ;;
+ unpack)
+ grep "^packs: 0$" actual ;;
+ esac || {
+ echo "store_type is $store_type"
+ cat actual
+ false;
+ }
+}
+
test_pack_input_limit () {
- case "$1" in
- index) unpack_limit=1 ;;
- unpack) unpack_limit=10000 ;;
+ store_type=$1
+
+ case "$store_type" in
+ index) unpack_limit=1 other_limit=10000 ;;
+ unpack) unpack_limit=10000 other_limit=1 ;;
esac
test_expect_success 'prepare destination repository' '
@@ -43,6 +59,19 @@ test_pack_input_limit () {
git --git-dir=dest config receive.maxInputSize 0 &&
git push dest HEAD
'
+
+ test_expect_success 'prepare destination repository (once more)' '
+ rm -fr dest &&
+ git --bare init dest
+ '
+
+ test_expect_success 'receive trumps transfer' '
+ git --git-dir=dest config receive.unpacklimit "$unpack_limit" &&
+ git --git-dir=dest config transfer.unpacklimit "$other_limit" &&
+ git push dest HEAD &&
+ validate_store_type
+ '
+
}
test_expect_success "create known-size (1024 bytes) commit" '
diff --git a/t/t5571-pre-push-hook.sh b/t/t5571-pre-push-hook.sh
index a11b20e378..448134c4bf 100755
--- a/t/t5571-pre-push-hook.sh
+++ b/t/t5571-pre-push-hook.sh
@@ -4,6 +4,7 @@ test_description='check pre-push hooks'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5583-push-branches.sh b/t/t5583-push-branches.sh
index e7e1b6dab6..320f49c753 100755
--- a/t/t5583-push-branches.sh
+++ b/t/t5583-push-branches.sh
@@ -5,6 +5,7 @@ test_description='check the consisitency of behavior of --all and --branches'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
delete_refs() {
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 5b434ab451..1b84bf66e0 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -1017,16 +1017,16 @@ test_expect_success 'Verify sorts with raw' '
test_expect_success 'Verify sorts with raw:size' '
cat >expected <<-EOF &&
refs/myblobs/blob8
- refs/myblobs/first
refs/myblobs/blob7
- refs/heads/main
refs/myblobs/blob4
refs/myblobs/blob1
refs/myblobs/blob2
refs/myblobs/blob3
refs/myblobs/blob5
refs/myblobs/blob6
+ refs/myblobs/first
refs/mytrees/first
+ refs/heads/main
EOF
git for-each-ref --format="%(refname)" --sort=raw:size \
refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
@@ -1138,6 +1138,17 @@ test_expect_success 'for-each-ref --format compare with cat-file --batch' '
test_cmp expected actual
'
+test_expect_success 'verify sorts with contents:size' '
+ cat >expect <<-\EOF &&
+ refs/heads/main
+ refs/heads/newtag
+ refs/heads/ambiguous
+ EOF
+ git for-each-ref --format="%(refname)" \
+ --sort=contents:size refs/heads/ >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'set up multiple-sort tags' '
for when in 100000 200000
do
diff --git a/t/t7516-commit-races.sh b/t/t7516-commit-races.sh
index 2d38a16480..bb95f09810 100755
--- a/t/t7516-commit-races.sh
+++ b/t/t7516-commit-races.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git commit races'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'race to create orphan commit' '
diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh
index 0c241d6c14..78503158fd 100755
--- a/t/t7527-builtin-fsmonitor.sh
+++ b/t/t7527-builtin-fsmonitor.sh
@@ -809,6 +809,11 @@ my_match_and_clean () {
status --porcelain=v2 >actual.without &&
test_cmp actual.with actual.without &&
+ git -C super --no-optional-locks diff-index --name-status HEAD >actual.with &&
+ git -C super --no-optional-locks -c core.fsmonitor=false \
+ diff-index --name-status HEAD >actual.without &&
+ test_cmp actual.with actual.without &&
+
git -C super/dir_1/dir_2/sub reset --hard &&
git -C super/dir_1/dir_2/sub clean -d -f
}
diff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh
index 872ad1c9c2..7869f45ee6 100755
--- a/t/t9211-scalar-clone.sh
+++ b/t/t9211-scalar-clone.sh
@@ -180,4 +180,16 @@ test_expect_success 'scalar clone warns when background maintenance fails' '
grep "could not turn on maintenance" err
'
+test_expect_success '`scalar clone --no-src`' '
+ scalar clone --src "file://$(pwd)/to-clone" with-src &&
+ scalar clone --no-src "file://$(pwd)/to-clone" without-src &&
+
+ test_path_is_dir with-src/src &&
+ test_path_is_missing without-src/src &&
+
+ (cd with-src/src && ls ?*) >with &&
+ (cd without-src && ls ?*) >without &&
+ test_cmp with without
+'
+
test_done
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 8835e16e81..47e20fb8b1 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -1622,14 +1622,22 @@ test_expect_success 'git checkout - with -d, complete only references' '
'
test_expect_success 'git switch - with --track, complete only remote branches' '
- test_completion "git switch --track " <<-\EOF
+ test_completion "git switch --track " <<-\EOF &&
+ other/branch-in-other Z
+ other/main-in-other Z
+ EOF
+ test_completion "git switch -t " <<-\EOF
other/branch-in-other Z
other/main-in-other Z
EOF
'
test_expect_success 'git checkout - with --track, complete only remote branches' '
- test_completion "git checkout --track " <<-\EOF
+ test_completion "git checkout --track " <<-\EOF &&
+ other/branch-in-other Z
+ other/main-in-other Z
+ EOF
+ test_completion "git checkout -t " <<-\EOF
other/branch-in-other Z
other/main-in-other Z
EOF
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 293caf0f20..5ea5d1d62a 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -334,6 +334,7 @@ nr_san_dir_leaks_ () {
find "$TEST_RESULTS_SAN_DIR" \
-type f \
-name "$TEST_RESULTS_SAN_FILE_PFX.*" 2>/dev/null |
+ xargs grep -lv "Unable to get registers from thread" |
wc -l
}
diff --git a/wt-status.c b/wt-status.c
index 5b1378965c..d03dfab9e4 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -675,7 +675,7 @@ static void wt_status_collect_changes_index(struct wt_status *s)
rev.diffopt.flags.recursive = 1;
copy_pathspec(&rev.prune_data, &s->pathspec);
- run_diff_index(&rev, 1);
+ run_diff_index(&rev, DIFF_INDEX_CACHED);
release_revisions(&rev);
}
@@ -1156,7 +1156,7 @@ static void wt_longstatus_print_verbose(struct wt_status *s)
rev.diffopt.a_prefix = "c/";
rev.diffopt.b_prefix = "i/";
} /* else use prefix as per user config */
- run_diff_index(&rev, 1);
+ run_diff_index(&rev, DIFF_INDEX_CACHED);
if (s->verbose > 1 &&
wt_status_check_worktree_changes(s, &dirty_submodules)) {
status_printf_ln(s, c,
@@ -2580,8 +2580,8 @@ int has_unstaged_changes(struct repository *r, int ignore_submodules)
}
rev_info.diffopt.flags.quick = 1;
diff_setup_done(&rev_info.diffopt);
- result = run_diff_files(&rev_info, 0);
- result = diff_result_code(&rev_info.diffopt, result);
+ run_diff_files(&rev_info, 0);
+ result = diff_result_code(&rev_info.diffopt);
release_revisions(&rev_info);
return result;
}
@@ -2614,8 +2614,8 @@ int has_uncommitted_changes(struct repository *r,
}
diff_setup_done(&rev_info.diffopt);
- result = run_diff_index(&rev_info, 1);
- result = diff_result_code(&rev_info.diffopt, result);
+ run_diff_index(&rev_info, DIFF_INDEX_CACHED);
+ result = diff_result_code(&rev_info.diffopt);
release_revisions(&rev_info);
return result;
}
@@ -2655,8 +2655,12 @@ int require_clean_work_tree(struct repository *r,
}
if (err) {
- if (hint)
+ if (hint) {
+ if (!*hint)
+ BUG("empty hint passed to require_clean_work_tree();"
+ " use NULL instead");
error("%s", hint);
+ }
if (!gently)
exit(128);
}