summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/README7
-rw-r--r--t/helper/test-bitmap.c10
-rw-r--r--t/helper/test-dump-untracked-cache.c6
-rw-r--r--t/helper/test-parse-options.c1
-rw-r--r--t/helper/test-run-command.c9
-rw-r--r--t/helper/test-simple-ipc.c233
-rw-r--r--t/helper/test-submodule-nested-repo-config.c4
-rw-r--r--t/lib-httpd/apache.conf7
-rw-r--r--t/lib-subtest.sh95
-rwxr-xr-xt/perf/aggregate.perl4
-rwxr-xr-xt/perf/p3400-rebase.sh2
-rwxr-xr-xt/perf/p5326-multi-pack-bitmaps.sh15
-rwxr-xr-xt/perf/run2
-rwxr-xr-xt/t0000-basic.sh471
-rwxr-xr-xt/t0004-unwritable.sh3
-rwxr-xr-xt/t0011-hashmap.sh2
-rwxr-xr-xt/t0012-help.sh65
-rwxr-xr-xt/t0016-oidmap.sh2
-rwxr-xr-xt/t0017-env-helper.sh1
-rwxr-xr-xt/t0018-advice.sh1
-rwxr-xr-xt/t0030-stripspace.sh1
-rwxr-xr-xt/t0040-parse-options.sh5
-rwxr-xr-xt/t0063-string-list.sh1
-rwxr-xr-xt/t0090-cache-tree.sh1
-rwxr-xr-xt/t0091-bugreport.sh1
-rwxr-xr-xt/t0301-credential-cache.sh32
-rwxr-xr-xt/t1013-read-tree-submodule.sh1
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh29
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh75
-rwxr-xr-xt/t1400-update-ref.sh34
-rwxr-xr-xt/t1430-bad-ref-name.sh2
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh54
-rwxr-xr-xt/t1600-index.sh13
-rwxr-xr-xt/t1700-split-index.sh34
-rwxr-xr-xt/t2021-checkout-overwrite.sh1
-rwxr-xr-xt/t2500-untracked-overwriting.sh244
-rwxr-xr-xt/t3404-rebase-interactive.sh1
-rwxr-xr-xt/t3407-rebase-abort.sh105
-rwxr-xr-xt/t3435-rebase-gpg-sign.sh1
-rwxr-xr-xt/t3510-cherry-pick-sequence.sh1
-rwxr-xr-xt/t3602-rm-sparse-checkout.sh40
-rwxr-xr-xt/t3705-add-sparse-checkout.sh68
-rwxr-xr-xt/t3903-stash.sh58
-rwxr-xr-xt/t4151-am-abort.sh39
-rwxr-xr-xt/t5304-prune.sh1
-rwxr-xr-xt/t5312-prune-corruption.sh48
-rwxr-xr-xt/t5319-multi-pack-index.sh12
-rwxr-xr-xt/t5326-multi-pack-bitmaps.sh30
-rwxr-xr-xt/t5516-fetch-push.sh19
-rwxr-xr-xt/t5551-http-fetch-smart.sh33
-rwxr-xr-xt/t5600-clone-fail-cleanup.sh4
-rwxr-xr-xt/t5701-git-serve.sh75
-rwxr-xr-xt/t5702-protocol-v2.sh13
-rwxr-xr-xt/t5704-protocol-violations.sh15
-rwxr-xr-xt/t6030-bisect-porcelain.sh18
-rwxr-xr-xt/t6415-merge-dir-to-symlink.sh6
-rwxr-xr-xt/t6424-merge-unrelated-index-changes.sh1
-rwxr-xr-xt/t6430-merge-recursive.sh4
-rwxr-xr-xt/t6436-merge-overwrite.sh3
-rwxr-xr-xt/t7002-mv-sparse-checkout.sh189
-rwxr-xr-xt/t7112-reset-submodule.sh1
-rwxr-xr-xt/t7201-co.sh1
-rwxr-xr-xt/t7519-status-fsmonitor.sh68
-rwxr-xr-xt/t7600-merge.sh1
-rwxr-xr-xt/t7800-difftool.sh74
-rwxr-xr-xt/t7814-grep-recurse-submodules.sh103
-rwxr-xr-xt/t7900-maintenance.sh9
-rwxr-xr-xt/t9400-git-cvsserver-server.sh9
-rw-r--r--t/test-lib.sh27
69 files changed, 1815 insertions, 730 deletions
diff --git a/t/README b/t/README
index 51065d0800..b92155a822 100644
--- a/t/README
+++ b/t/README
@@ -366,6 +366,13 @@ excluded as so much relies on it, but this might change in the future.
GIT_TEST_SPLIT_INDEX=<boolean> forces split-index mode on the whole
test suite. Accept any boolean values that are accepted by git-config.
+GIT_TEST_PASSING_SANITIZE_LEAK=<boolean> when compiled with
+SANITIZE=leak will run only those tests that have whitelisted
+themselves as passing with no memory leaks. Tests can be whitelisted
+by setting "TEST_PASSES_SANITIZE_LEAK=true" before sourcing
+"test-lib.sh" itself at the top of the test script. This test mode is
+used by the "linux-leaks" CI target.
+
GIT_TEST_PROTOCOL_VERSION=<n>, when set, makes 'protocol.version'
default to n.
diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c
index 134a1e9d76..ff35f5999b 100644
--- a/t/helper/test-bitmap.c
+++ b/t/helper/test-bitmap.c
@@ -7,6 +7,11 @@ static int bitmap_list_commits(void)
return test_bitmap_commits(the_repository);
}
+static int bitmap_dump_hashes(void)
+{
+ return test_bitmap_hashes(the_repository);
+}
+
int cmd__bitmap(int argc, const char **argv)
{
setup_git_directory();
@@ -16,9 +21,12 @@ int cmd__bitmap(int argc, const char **argv)
if (!strcmp(argv[1], "list-commits"))
return bitmap_list_commits();
+ if (!strcmp(argv[1], "dump-hashes"))
+ return bitmap_dump_hashes();
usage:
- usage("\ttest-tool bitmap list-commits");
+ usage("\ttest-tool bitmap list-commits\n"
+ "\ttest-tool bitmap dump-hashes");
return -1;
}
diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index cf0f2c7228..99010614f6 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -45,8 +45,10 @@ int cmd__dump_untracked_cache(int ac, const char **av)
struct untracked_cache *uc;
struct strbuf base = STRBUF_INIT;
- /* Hack to avoid modifying the untracked cache when we read it */
- ignore_untracked_cache_config = 1;
+ /* Set core.untrackedCache=keep before setup_git_directory() */
+ xsetenv("GIT_CONFIG_COUNT", "1", 1);
+ xsetenv("GIT_CONFIG_KEY_0", "core.untrackedCache", 1);
+ xsetenv("GIT_CONFIG_VALUE_0", "keep", 1);
setup_git_directory();
if (read_cache() < 0)
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index 2051ce57db..a282b6ff13 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -134,7 +134,6 @@ int cmd__parse_options(int argc, const char **argv)
OPT_NOOP_NOARG(0, "obsolete"),
OPT_STRING_LIST(0, "list", &list, "str", "add str to list"),
OPT_GROUP("Magic arguments"),
- OPT_ARGUMENT("quux", NULL, "means --quux"),
OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
number_callback),
{ OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b",
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index 7ae03dc712..3c4fb86223 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -60,8 +60,10 @@ struct testsuite {
int next;
int quiet, immediate, verbose, verbose_log, trace, write_junit_xml;
};
-#define TESTSUITE_INIT \
- { STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, -1, 0, 0, 0, 0, 0, 0 }
+#define TESTSUITE_INIT { \
+ .tests = STRING_LIST_INIT_DUP, \
+ .failed = STRING_LIST_INIT_DUP, \
+}
static int next_test(struct child_process *cp, struct strbuf *err, void *cb,
void **task_cb)
@@ -142,9 +144,6 @@ static int testsuite(int argc, const char **argv)
OPT_END()
};
- memset(&suite, 0, sizeof(suite));
- suite.tests.strdup_strings = suite.failed.strdup_strings = 1;
-
argc = parse_options(argc, argv, NULL, options,
testsuite_usage, PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
index 42040ef81b..28365ff85b 100644
--- a/t/helper/test-simple-ipc.c
+++ b/t/helper/test-simple-ipc.c
@@ -9,6 +9,7 @@
#include "parse-options.h"
#include "thread-utils.h"
#include "strvec.h"
+#include "run-command.h"
#ifndef SUPPORTS_SIMPLE_IPC
int cmd__simple_ipc(int argc, const char **argv)
@@ -112,7 +113,7 @@ static int app__slow_command(ipc_server_reply_cb *reply_cb,
/*
* The client sent a command followed by a (possibly very) large buffer.
*/
-static int app__sendbytes_command(const char *received,
+static int app__sendbytes_command(const char *received, size_t received_len,
ipc_server_reply_cb *reply_cb,
struct ipc_server_reply_data *reply_data)
{
@@ -123,6 +124,13 @@ static int app__sendbytes_command(const char *received,
int errs = 0;
int ret;
+ /*
+ * The test is setup to send:
+ * "sendbytes" SP <n * char>
+ */
+ if (received_len < strlen("sendbytes "))
+ BUG("received_len is short in app__sendbytes_command");
+
if (skip_prefix(received, "sendbytes ", &p))
len_ballast = strlen(p);
@@ -160,7 +168,7 @@ static ipc_server_application_cb test_app_cb;
* by this application.
*/
static int test_app_cb(void *application_data,
- const char *command,
+ const char *command, size_t command_len,
ipc_server_reply_cb *reply_cb,
struct ipc_server_reply_data *reply_data)
{
@@ -173,7 +181,7 @@ static int test_app_cb(void *application_data,
if (application_data != (void*)&my_app_data)
BUG("application_cb: application_data pointer wrong");
- if (!strcmp(command, "quit")) {
+ if (command_len == 4 && !strncmp(command, "quit", 4)) {
/*
* The client sent a "quit" command. This is an async
* request for the server to shutdown.
@@ -193,22 +201,23 @@ static int test_app_cb(void *application_data,
return SIMPLE_IPC_QUIT;
}
- if (!strcmp(command, "ping")) {
+ if (command_len == 4 && !strncmp(command, "ping", 4)) {
const char *answer = "pong";
return reply_cb(reply_data, answer, strlen(answer));
}
- if (!strcmp(command, "big"))
+ if (command_len == 3 && !strncmp(command, "big", 3))
return app__big_command(reply_cb, reply_data);
- if (!strcmp(command, "chunk"))
+ if (command_len == 5 && !strncmp(command, "chunk", 5))
return app__chunk_command(reply_cb, reply_data);
- if (!strcmp(command, "slow"))
+ if (command_len == 4 && !strncmp(command, "slow", 4))
return app__slow_command(reply_cb, reply_data);
- if (starts_with(command, "sendbytes "))
- return app__sendbytes_command(command, reply_cb, reply_data);
+ if (command_len >= 10 && starts_with(command, "sendbytes "))
+ return app__sendbytes_command(command, command_len,
+ reply_cb, reply_data);
return app__unhandled_command(command, reply_cb, reply_data);
}
@@ -259,186 +268,72 @@ static int daemon__run_server(void)
*/
ret = ipc_server_run(cl_args.path, &opts, test_app_cb, (void*)&my_app_data);
if (ret == -2)
- error(_("socket/pipe already in use: '%s'"), cl_args.path);
+ error("socket/pipe already in use: '%s'", cl_args.path);
else if (ret == -1)
- error_errno(_("could not start server on: '%s'"), cl_args.path);
+ error_errno("could not start server on: '%s'", cl_args.path);
return ret;
}
-#ifndef GIT_WINDOWS_NATIVE
-/*
- * This is adapted from `daemonize()`. Use `fork()` to directly create and
- * run the daemon in a child process.
- */
-static int spawn_server(pid_t *pid)
-{
- struct ipc_server_opts opts = {
- .nr_threads = cl_args.nr_threads,
- };
-
- *pid = fork();
+static start_bg_wait_cb bg_wait_cb;
- switch (*pid) {
- case 0:
- if (setsid() == -1)
- error_errno(_("setsid failed"));
- close(0);
- close(1);
- close(2);
- sanitize_stdfds();
+static int bg_wait_cb(const struct child_process *cp, void *cb_data)
+{
+ int s = ipc_get_active_state(cl_args.path);
- return ipc_server_run(cl_args.path, &opts, test_app_cb,
- (void*)&my_app_data);
+ switch (s) {
+ case IPC_STATE__LISTENING:
+ /* child is "ready" */
+ return 0;
- case -1:
- return error_errno(_("could not spawn daemon in the background"));
+ case IPC_STATE__NOT_LISTENING:
+ case IPC_STATE__PATH_NOT_FOUND:
+ /* give child more time */
+ return 1;
default:
- return 0;
+ case IPC_STATE__INVALID_PATH:
+ case IPC_STATE__OTHER_ERROR:
+ /* all the time in world won't help */
+ return -1;
}
}
-#else
-/*
- * Conceptually like `daemonize()` but different because Windows does not
- * have `fork(2)`. Spawn a normal Windows child process but without the
- * limitations of `start_command()` and `finish_command()`.
- */
-static int spawn_server(pid_t *pid)
-{
- char test_tool_exe[MAX_PATH];
- struct strvec args = STRVEC_INIT;
- int in, out;
-
- GetModuleFileNameA(NULL, test_tool_exe, MAX_PATH);
-
- in = open("/dev/null", O_RDONLY);
- out = open("/dev/null", O_WRONLY);
-
- strvec_push(&args, test_tool_exe);
- strvec_push(&args, "simple-ipc");
- strvec_push(&args, "run-daemon");
- strvec_pushf(&args, "--name=%s", cl_args.path);
- strvec_pushf(&args, "--threads=%d", cl_args.nr_threads);
- *pid = mingw_spawnvpe(args.v[0], args.v, NULL, NULL, in, out, out);
- close(in);
- close(out);
-
- strvec_clear(&args);
-
- if (*pid < 0)
- return error(_("could not spawn daemon in the background"));
-
- return 0;
-}
-#endif
-
-/*
- * This is adapted from `wait_or_whine()`. Watch the child process and
- * let it get started and begin listening for requests on the socket
- * before reporting our success.
- */
-static int wait_for_server_startup(pid_t pid_child)
+static int daemon__start_server(void)
{
- int status;
- pid_t pid_seen;
- enum ipc_active_state s;
- time_t time_limit, now;
+ struct child_process cp = CHILD_PROCESS_INIT;
+ enum start_bg_result sbgr;
- time(&time_limit);
- time_limit += cl_args.max_wait_sec;
+ strvec_push(&cp.args, "test-tool");
+ strvec_push(&cp.args, "simple-ipc");
+ strvec_push(&cp.args, "run-daemon");
+ strvec_pushf(&cp.args, "--name=%s", cl_args.path);
+ strvec_pushf(&cp.args, "--threads=%d", cl_args.nr_threads);
- for (;;) {
- pid_seen = waitpid(pid_child, &status, WNOHANG);
-
- if (pid_seen == -1)
- return error_errno(_("waitpid failed"));
-
- else if (pid_seen == 0) {
- /*
- * The child is still running (this should be
- * the normal case). Try to connect to it on
- * the socket and see if it is ready for
- * business.
- *
- * If there is another daemon already running,
- * our child will fail to start (possibly
- * after a timeout on the lock), but we don't
- * care (who responds) if the socket is live.
- */
- s = ipc_get_active_state(cl_args.path);
- if (s == IPC_STATE__LISTENING)
- return 0;
+ cp.no_stdin = 1;
+ cp.no_stdout = 1;
+ cp.no_stderr = 1;
- time(&now);
- if (now > time_limit)
- return error(_("daemon not online yet"));
+ sbgr = start_bg_command(&cp, bg_wait_cb, NULL, cl_args.max_wait_sec);
- continue;
- }
+ switch (sbgr) {
+ case SBGR_READY:
+ return 0;
- else if (pid_seen == pid_child) {
- /*
- * The new child daemon process shutdown while
- * it was starting up, so it is not listening
- * on the socket.
- *
- * Try to ping the socket in the odd chance
- * that another daemon started (or was already
- * running) while our child was starting.
- *
- * Again, we don't care who services the socket.
- */
- s = ipc_get_active_state(cl_args.path);
- if (s == IPC_STATE__LISTENING)
- return 0;
+ default:
+ case SBGR_ERROR:
+ case SBGR_CB_ERROR:
+ return error("daemon failed to start");
- /*
- * We don't care about the WEXITSTATUS() nor
- * any of the WIF*(status) values because
- * `cmd__simple_ipc()` does the `!!result`
- * trick on all function return values.
- *
- * So it is sufficient to just report the
- * early shutdown as an error.
- */
- return error(_("daemon failed to start"));
- }
+ case SBGR_TIMEOUT:
+ return error("daemon not online yet");
- else
- return error(_("waitpid is confused"));
+ case SBGR_DIED:
+ return error("daemon terminated");
}
}
/*
- * This process will start a simple-ipc server in a background process and
- * wait for it to become ready. This is like `daemonize()` but gives us
- * more control and better error reporting (and makes it easier to write
- * unit tests).
- */
-static int daemon__start_server(void)
-{
- pid_t pid_child;
- int ret;
-
- /*
- * Run the actual daemon in a background process.
- */
- ret = spawn_server(&pid_child);
- if (pid_child <= 0)
- return ret;
-
- /*
- * Let the parent wait for the child process to get started
- * and begin listening for requests on the socket.
- */
- ret = wait_for_server_startup(pid_child);
-
- return ret;
-}
-
-/*
* This process will run a quick probe to see if a simple-ipc server
* is active on this path.
*
@@ -488,7 +383,9 @@ static int client__send_ipc(void)
options.wait_if_busy = 1;
options.wait_if_not_found = 0;
- if (!ipc_client_send_command(cl_args.path, &options, command, &buf)) {
+ if (!ipc_client_send_command(cl_args.path, &options,
+ command, strlen(command),
+ &buf)) {
if (buf.len) {
printf("%s\n", buf.buf);
fflush(stdout);
@@ -538,7 +435,7 @@ static int client__stop_server(void)
time(&now);
if (now > time_limit)
- return error(_("daemon has not shutdown yet"));
+ return error("daemon has not shutdown yet");
}
}
@@ -556,7 +453,9 @@ static int do_sendbytes(int bytecount, char byte, const char *path,
strbuf_addstr(&buf_send, "sendbytes ");
strbuf_addchars(&buf_send, byte, bytecount);
- if (!ipc_client_send_command(path, options, buf_send.buf, &buf_resp)) {
+ if (!ipc_client_send_command(path, options,
+ buf_send.buf, buf_send.len,
+ &buf_resp)) {
strbuf_rtrim(&buf_resp);
printf("sent:%c%08d %s\n", byte, bytecount, buf_resp.buf);
fflush(stdout);
diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c
index e3f11ff5a7..dc1c14bde3 100644
--- a/t/helper/test-submodule-nested-repo-config.c
+++ b/t/helper/test-submodule-nested-repo-config.c
@@ -11,15 +11,13 @@ static void die_usage(const char **argv, const char *msg)
int cmd__submodule_nested_repo_config(int argc, const char **argv)
{
struct repository subrepo;
- const struct submodule *sub;
if (argc < 3)
die_usage(argv, "Wrong number of arguments.");
setup_git_directory();
- sub = submodule_from_path(the_repository, null_oid(), argv[1]);
- if (repo_submodule_init(&subrepo, the_repository, sub)) {
+ if (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid())) {
die_usage(argv, "Submodule not found.");
}
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index afa91e38b0..180a41fe96 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -81,8 +81,6 @@ PassEnv GIT_TRACE
PassEnv GIT_CONFIG_NOSYSTEM
PassEnv GIT_TEST_SIDEBAND_ALL
-SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
-
Alias /dumb/ www/
Alias /auth/dumb/ www/auth/dumb/
@@ -117,6 +115,11 @@ Alias /auth/dumb/ www/auth/dumb/
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
SetEnv GIT_HTTP_EXPORT_ALL
</LocationMatch>
+<LocationMatch /smart_v0/>
+ SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
+ SetEnv GIT_HTTP_EXPORT_ALL
+ SetEnv GIT_PROTOCOL
+</LocationMatch>
ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/
ScriptAliasMatch /error_git_upload_pack/(.*)/git-upload-pack error.sh/
diff --git a/t/lib-subtest.sh b/t/lib-subtest.sh
new file mode 100644
index 0000000000..56ee927f0c
--- /dev/null
+++ b/t/lib-subtest.sh
@@ -0,0 +1,95 @@
+write_sub_test_lib_test () {
+ name="$1" # stdin is the body of the test code
+ mkdir "$name" &&
+ write_script "$name/$name.sh" "$TEST_SHELL_PATH" <<-EOF &&
+ test_description='A test of test-lib.sh itself'
+
+ # Point to the t/test-lib.sh, which isn't in ../ as usual
+ . "\$TEST_DIRECTORY"/test-lib.sh
+ EOF
+ cat >>"$name/$name.sh"
+}
+
+_run_sub_test_lib_test_common () {
+ cmp_op="$1" want_code="$2" name="$3" # stdin is the body of the test code
+ shift 3
+
+ # intercept pseudo-options at the front of the argument list that we
+ # will not pass to child script
+ skip=
+ while test $# -gt 0
+ do
+ case "$1" in
+ --skip=*)
+ skip=${1#--*=}
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+
+ (
+ cd "$name" &&
+
+ # Pretend we're not running under a test harness, whether we
+ # are or not. The test-lib output depends on the setting of
+ # this variable, so we need a stable setting under which to run
+ # the sub-test.
+ sane_unset HARNESS_ACTIVE &&
+
+ export TEST_DIRECTORY &&
+ # The child test re-sources GIT-BUILD-OPTIONS and may thus
+ # override the test output directory. We thus pass it as an
+ # explicit override to the child.
+ TEST_OUTPUT_DIRECTORY_OVERRIDE=$(pwd) &&
+ export TEST_OUTPUT_DIRECTORY_OVERRIDE &&
+ GIT_SKIP_TESTS=$skip &&
+ export GIT_SKIP_TESTS &&
+ sane_unset GIT_TEST_FAIL_PREREQS &&
+ ./"$name.sh" "$@" >out 2>err;
+ ret=$? &&
+ test "$ret" "$cmp_op" "$want_code"
+ )
+}
+
+write_and_run_sub_test_lib_test () {
+ name="$1" descr="$2" # stdin is the body of the test code
+ write_sub_test_lib_test "$@" || return 1
+ _run_sub_test_lib_test_common -eq 0 "$@"
+}
+
+write_and_run_sub_test_lib_test_err () {
+ name="$1" descr="$2" # stdin is the body of the test code
+ write_sub_test_lib_test "$@" || return 1
+ _run_sub_test_lib_test_common -eq 1 "$@"
+}
+
+run_sub_test_lib_test () {
+ _run_sub_test_lib_test_common -eq 0 "$@"
+}
+
+run_sub_test_lib_test_err () {
+ _run_sub_test_lib_test_common -eq 1 "$@"
+}
+
+_check_sub_test_lib_test_common () {
+ name="$1" &&
+ sed -e 's/^> //' -e 's/Z$//' >"$name"/expect.out &&
+ test_cmp "$name"/expect.out "$name"/out
+}
+
+check_sub_test_lib_test () {
+ name="$1" # stdin is the expected output from the test
+ _check_sub_test_lib_test_common "$name" &&
+ test_must_be_empty "$name"/err
+}
+
+check_sub_test_lib_test_err () {
+ name="$1" # stdin is the expected output from the test
+ _check_sub_test_lib_test_common "$name" &&
+ # expected error output is in descriptor 3
+ sed -e 's/^> //' -e 's/Z$//' <&3 >"$name"/expect.err &&
+ test_cmp "$name"/expect.err "$name"/err
+}
diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl
index 82c0df4553..575d2000cc 100755
--- a/t/perf/aggregate.perl
+++ b/t/perf/aggregate.perl
@@ -17,8 +17,8 @@ sub get_times {
my $rt = ((defined $1 ? $1 : 0.0)*60+$2)*60+$3;
return ($rt, $4, $5);
# size
- } elsif ($line =~ /^\d+$/) {
- return $&;
+ } elsif ($line =~ /^\s*(\d+)$/) {
+ return $1;
} else {
die "bad input line: $line";
}
diff --git a/t/perf/p3400-rebase.sh b/t/perf/p3400-rebase.sh
index 7a0bb29448..43d5a34e8c 100755
--- a/t/perf/p3400-rebase.sh
+++ b/t/perf/p3400-rebase.sh
@@ -18,7 +18,7 @@ test_expect_success 'setup rebasing on top of a lot of changes' '
test_tick &&
git commit -m commit$i unrelated-file$i &&
echo change$i >unrelated-file$i &&
- test_seq 1000 | tac >>unrelated-file$i &&
+ test_seq 1000 | sort -nr >>unrelated-file$i &&
git add unrelated-file$i &&
test_tick &&
git commit -m commit$i-reverse unrelated-file$i ||
diff --git a/t/perf/p5326-multi-pack-bitmaps.sh b/t/perf/p5326-multi-pack-bitmaps.sh
index 5845109ac7..f2fa228f16 100755
--- a/t/perf/p5326-multi-pack-bitmaps.sh
+++ b/t/perf/p5326-multi-pack-bitmaps.sh
@@ -6,15 +6,24 @@ test_description='Tests performance using midx bitmaps'
test_perf_large_repo
-test_expect_success 'enable multi-pack index' '
- git config core.multiPackIndex true
+# we need to create the tag up front such that it is covered by the repack and
+# thus by generated bitmaps.
+test_expect_success 'create tags' '
+ git tag --message="tag pointing to HEAD" perf-tag HEAD
+'
+
+test_expect_success 'start with bitmapped pack' '
+ git repack -adb
'
test_perf 'setup multi-pack index' '
- git repack -ad &&
git multi-pack-index write --bitmap
'
+test_expect_success 'drop pack bitmap' '
+ rm -f .git/objects/pack/pack-*.bitmap
+'
+
test_full_bitmap
test_expect_success 'create partial bitmap state' '
diff --git a/t/perf/run b/t/perf/run
index d19dec258a..55219aa405 100755
--- a/t/perf/run
+++ b/t/perf/run
@@ -74,7 +74,7 @@ set_git_test_installed () {
mydir=$1
mydir_abs=$(cd $mydir && pwd)
- mydir_abs_wrappers="$mydir_abs_wrappers/bin-wrappers"
+ mydir_abs_wrappers="$mydir_abs/bin-wrappers"
if test -d "$mydir_abs_wrappers"
then
GIT_TEST_INSTALLED=$mydir_abs_wrappers
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index cb87768513..b007f0efef 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -19,6 +19,7 @@ modification *should* take notice and update the test vectors here.
'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-subtest.sh
try_local_xy () {
local x="local" y="alsolocal" &&
@@ -66,95 +67,8 @@ test_expect_success 'success is reported like this' '
:
'
-_run_sub_test_lib_test_common () {
- neg="$1" name="$2" descr="$3" # stdin is the body of the test code
- shift 3
-
- # intercept pseudo-options at the front of the argument list that we
- # will not pass to child script
- skip=
- while test $# -gt 0
- do
- case "$1" in
- --skip=*)
- skip=${1#--*=}
- shift
- ;;
- *)
- break
- ;;
- esac
- done
-
- mkdir "$name" &&
- (
- # Pretend we're not running under a test harness, whether we
- # are or not. The test-lib output depends on the setting of
- # this variable, so we need a stable setting under which to run
- # the sub-test.
- sane_unset HARNESS_ACTIVE &&
- cd "$name" &&
- write_script "$name.sh" "$TEST_SHELL_PATH" <<-EOF &&
- test_description='$descr (run in sub test-lib)
-
- This is run in a sub test-lib so that we do not get incorrect
- passing metrics
- '
-
- # Point to the t/test-lib.sh, which isn't in ../ as usual
- . "\$TEST_DIRECTORY"/test-lib.sh
- EOF
- cat >>"$name.sh" &&
- export TEST_DIRECTORY &&
- # The child test re-sources GIT-BUILD-OPTIONS and may thus
- # override the test output directory. We thus pass it as an
- # explicit override to the child.
- TEST_OUTPUT_DIRECTORY_OVERRIDE=$(pwd) &&
- export TEST_OUTPUT_DIRECTORY_OVERRIDE &&
- GIT_SKIP_TESTS=$skip &&
- export GIT_SKIP_TESTS &&
- sane_unset GIT_TEST_FAIL_PREREQS &&
- if test -z "$neg"
- then
- ./"$name.sh" "$@" >out 2>err
- else
- ! ./"$name.sh" "$@" >out 2>err
- fi
- )
-}
-
-run_sub_test_lib_test () {
- _run_sub_test_lib_test_common '' "$@"
-}
-
-run_sub_test_lib_test_err () {
- _run_sub_test_lib_test_common '!' "$@"
-}
-
-check_sub_test_lib_test () {
- name="$1" # stdin is the expected output from the test
- (
- cd "$name" &&
- test_must_be_empty err &&
- sed -e 's/^> //' -e 's/Z$//' >expect &&
- test_cmp expect out
- )
-}
-
-check_sub_test_lib_test_err () {
- name="$1" # stdin is the expected output from the test
- # expected error output is in descriptor 3
- (
- cd "$name" &&
- sed -e 's/^> //' -e 's/Z$//' >expect.out &&
- test_cmp expect.out out &&
- sed -e 's/^> //' -e 's/Z$//' <&3 >expect.err &&
- test_cmp expect.err err
- )
-}
-
-test_expect_success 'pretend we have a fully passing test suite' '
- run_sub_test_lib_test full-pass "3 passing tests" <<-\EOF &&
+test_expect_success 'subtest: 3 passing tests' '
+ write_and_run_sub_test_lib_test full-pass <<-\EOF &&
for i in 1 2 3
do
test_expect_success "passing test #$i" "true"
@@ -170,9 +84,8 @@ test_expect_success 'pretend we have a fully passing test suite' '
EOF
'
-test_expect_success 'pretend we have a partially passing test suite' '
- run_sub_test_lib_test_err \
- partial-pass "2/3 tests passing" <<-\EOF &&
+test_expect_success 'subtest: 2/3 tests passing' '
+ write_and_run_sub_test_lib_test_err partial-pass <<-\EOF &&
test_expect_success "passing test #1" "true"
test_expect_success "failing test #2" "false"
test_expect_success "passing test #3" "true"
@@ -188,8 +101,8 @@ test_expect_success 'pretend we have a partially passing test suite' '
EOF
'
-test_expect_success 'pretend we have a known breakage' '
- run_sub_test_lib_test failing-todo "A failing TODO test" <<-\EOF &&
+test_expect_success 'subtest: a failing TODO test' '
+ write_and_run_sub_test_lib_test failing-todo <<-\EOF &&
test_expect_success "passing test" "true"
test_expect_failure "pretend we have a known breakage" "false"
test_done
@@ -203,8 +116,8 @@ test_expect_success 'pretend we have a known breakage' '
EOF
'
-test_expect_success 'pretend we have fixed a known breakage' '
- run_sub_test_lib_test passing-todo "A passing TODO test" <<-\EOF &&
+test_expect_success 'subtest: a passing TODO test' '
+ write_and_run_sub_test_lib_test passing-todo <<-\EOF &&
test_expect_failure "pretend we have fixed a known breakage" "true"
test_done
EOF
@@ -215,9 +128,8 @@ test_expect_success 'pretend we have fixed a known breakage' '
EOF
'
-test_expect_success 'pretend we have fixed one of two known breakages (run in sub test-lib)' '
- run_sub_test_lib_test partially-passing-todos \
- "2 TODO tests, one passing" <<-\EOF &&
+test_expect_success 'subtest: 2 TODO tests, one passin' '
+ write_and_run_sub_test_lib_test partially-passing-todos <<-\EOF &&
test_expect_failure "pretend we have a known breakage" "false"
test_expect_success "pretend we have a passing test" "true"
test_expect_failure "pretend we have fixed another known breakage" "true"
@@ -234,9 +146,8 @@ test_expect_success 'pretend we have fixed one of two known breakages (run in su
EOF
'
-test_expect_success 'pretend we have a pass, fail, and known breakage' '
- run_sub_test_lib_test_err \
- mixed-results1 "mixed results #1" <<-\EOF &&
+test_expect_success 'subtest: mixed results: pass, failure and a TODO test' '
+ write_and_run_sub_test_lib_test_err mixed-results1 <<-\EOF &&
test_expect_success "passing test" "true"
test_expect_success "failing test" "false"
test_expect_failure "pretend we have a known breakage" "false"
@@ -253,9 +164,8 @@ test_expect_success 'pretend we have a pass, fail, and known breakage' '
EOF
'
-test_expect_success 'pretend we have a mix of all possible results' '
- run_sub_test_lib_test_err \
- mixed-results2 "mixed results #2" <<-\EOF &&
+test_expect_success 'subtest: mixed results: a mixture of all possible results' '
+ write_and_run_sub_test_lib_test_err mixed-results2 <<-\EOF &&
test_expect_success "passing test" "true"
test_expect_success "passing test" "true"
test_expect_success "passing test" "true"
@@ -289,9 +199,8 @@ test_expect_success 'pretend we have a mix of all possible results' '
EOF
'
-test_expect_success 'test --verbose' '
- run_sub_test_lib_test_err \
- t1234-verbose "test verbose" --verbose <<-\EOF &&
+test_expect_success 'subtest: --verbose option' '
+ write_and_run_sub_test_lib_test_err t1234-verbose --verbose <<-\EOF &&
test_expect_success "passing test" true
test_expect_success "test with output" "echo foo"
test_expect_success "failing test" false
@@ -316,19 +225,14 @@ test_expect_success 'test --verbose' '
EOF
'
-test_expect_success 'test --verbose-only' '
+test_expect_success 'subtest: --verbose-only option' '
run_sub_test_lib_test_err \
- t2345-verbose-only-2 "test verbose-only=2" \
- --verbose-only=2 <<-\EOF &&
- test_expect_success "passing test" true
- test_expect_success "test with output" "echo foo"
- test_expect_success "failing test" false
- test_done
- EOF
- check_sub_test_lib_test t2345-verbose-only-2 <<-\EOF
+ t1234-verbose \
+ --verbose-only=2 &&
+ check_sub_test_lib_test t1234-verbose <<-\EOF
> ok 1 - passing test
> Z
- > expecting success of 2345.2 '\''test with output'\'': echo foo
+ > expecting success of 1234.2 '\''test with output'\'': echo foo
> foo
> ok 2 - test with output
> Z
@@ -339,18 +243,11 @@ test_expect_success 'test --verbose-only' '
EOF
'
-test_expect_success 'GIT_SKIP_TESTS' '
+test_expect_success 'subtest: skip one with GIT_SKIP_TESTS' '
(
- run_sub_test_lib_test git-skip-tests-basic \
- "GIT_SKIP_TESTS" \
- --skip="git.2" <<-\EOF &&
- for i in 1 2 3
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test git-skip-tests-basic <<-\EOF
+ run_sub_test_lib_test full-pass \
+ --skip="full.2" &&
+ check_sub_test_lib_test full-pass <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (GIT_SKIP_TESTS)
> ok 3 - passing test #3
@@ -360,10 +257,9 @@ test_expect_success 'GIT_SKIP_TESTS' '
)
'
-test_expect_success 'GIT_SKIP_TESTS several tests' '
+test_expect_success 'subtest: skip several with GIT_SKIP_TESTS' '
(
- run_sub_test_lib_test git-skip-tests-several \
- "GIT_SKIP_TESTS several tests" \
+ write_and_run_sub_test_lib_test git-skip-tests-several \
--skip="git.2 git.5" <<-\EOF &&
for i in 1 2 3 4 5 6
do
@@ -384,18 +280,11 @@ test_expect_success 'GIT_SKIP_TESTS several tests' '
)
'
-test_expect_success 'GIT_SKIP_TESTS sh pattern' '
+test_expect_success 'subtest: sh pattern skipping with GIT_SKIP_TESTS' '
(
- run_sub_test_lib_test git-skip-tests-sh-pattern \
- "GIT_SKIP_TESTS sh pattern" \
- --skip="git.[2-5]" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test git-skip-tests-sh-pattern <<-\EOF
+ run_sub_test_lib_test git-skip-tests-several \
+ --skip="git.[2-5]" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (GIT_SKIP_TESTS)
> ok 3 # skip passing test #3 (GIT_SKIP_TESTS)
@@ -408,35 +297,23 @@ test_expect_success 'GIT_SKIP_TESTS sh pattern' '
)
'
-test_expect_success 'GIT_SKIP_TESTS entire suite' '
+test_expect_success 'subtest: skip entire test suite with GIT_SKIP_TESTS' '
(
- run_sub_test_lib_test git-skip-tests-entire-suite \
- "GIT_SKIP_TESTS entire suite" \
- --skip="git" <<-\EOF &&
- for i in 1 2 3
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test git-skip-tests-entire-suite <<-\EOF
+ GIT_SKIP_TESTS="git" && export GIT_SKIP_TESTS &&
+ run_sub_test_lib_test git-skip-tests-several \
+ --skip="git" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> 1..0 # SKIP skip all tests in git
EOF
)
'
-test_expect_success 'GIT_SKIP_TESTS does not skip unmatched suite' '
+test_expect_success 'subtest: GIT_SKIP_TESTS does not skip unmatched suite' '
(
- run_sub_test_lib_test git-skip-tests-unmatched-suite \
- "GIT_SKIP_TESTS does not skip unmatched suite" \
- --skip="notgit" <<-\EOF &&
- for i in 1 2 3
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test git-skip-tests-unmatched-suite <<-\EOF
+ GIT_SKIP_TESTS="notgit" && export GIT_SKIP_TESTS &&
+ run_sub_test_lib_test full-pass \
+ --skip="notfull" &&
+ check_sub_test_lib_test full-pass <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 - passing test #3
@@ -446,16 +323,9 @@ test_expect_success 'GIT_SKIP_TESTS does not skip unmatched suite' '
)
'
-test_expect_success '--run basic' '
- run_sub_test_lib_test run-basic \
- "--run basic" --run="1,3,5" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-basic <<-\EOF
+test_expect_success 'subtest: --run basic' '
+ run_sub_test_lib_test git-skip-tests-several --run="1,3,5" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (--run)
> ok 3 - passing test #3
@@ -467,16 +337,10 @@ test_expect_success '--run basic' '
EOF
'
-test_expect_success '--run with a range' '
- run_sub_test_lib_test run-range \
- "--run with a range" --run="1-3" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-range <<-\EOF
+test_expect_success 'subtest: --run with a range' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="1-3" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 - passing test #3
@@ -488,16 +352,10 @@ test_expect_success '--run with a range' '
EOF
'
-test_expect_success '--run with two ranges' '
- run_sub_test_lib_test run-two-ranges \
- "--run with two ranges" --run="1-2,5-6" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-two-ranges <<-\EOF
+test_expect_success 'subtest: --run with two ranges' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="1-2,5-6" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -509,16 +367,10 @@ test_expect_success '--run with two ranges' '
EOF
'
-test_expect_success '--run with a left open range' '
- run_sub_test_lib_test run-left-open-range \
- "--run with a left open range" --run="-3" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-left-open-range <<-\EOF
+test_expect_success 'subtest: --run with a left open range' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="-3" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 - passing test #3
@@ -530,16 +382,10 @@ test_expect_success '--run with a left open range' '
EOF
'
-test_expect_success '--run with a right open range' '
- run_sub_test_lib_test run-right-open-range \
- "--run with a right open range" --run="4-" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-right-open-range <<-\EOF
+test_expect_success 'subtest: --run with a right open range' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="4-" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 # skip passing test #1 (--run)
> ok 2 # skip passing test #2 (--run)
> ok 3 # skip passing test #3 (--run)
@@ -551,16 +397,10 @@ test_expect_success '--run with a right open range' '
EOF
'
-test_expect_success '--run with basic negation' '
- run_sub_test_lib_test run-basic-neg \
- "--run with basic negation" --run="!3" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-basic-neg <<-\EOF
+test_expect_success 'subtest: --run with basic negation' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="!3" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -572,16 +412,10 @@ test_expect_success '--run with basic negation' '
EOF
'
-test_expect_success '--run with two negations' '
- run_sub_test_lib_test run-two-neg \
- "--run with two negations" --run="!3,!6" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-two-neg <<-\EOF
+test_expect_success 'subtest: --run with two negations' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="!3,!6" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -593,16 +427,10 @@ test_expect_success '--run with two negations' '
EOF
'
-test_expect_success '--run a range and negation' '
- run_sub_test_lib_test run-range-and-neg \
- "--run a range and negation" --run="-4,!2" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-range-and-neg <<-\EOF
+test_expect_success 'subtest: --run a range and negation' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="-4,!2" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (--run)
> ok 3 - passing test #3
@@ -614,16 +442,10 @@ test_expect_success '--run a range and negation' '
EOF
'
-test_expect_success '--run range negation' '
- run_sub_test_lib_test run-range-neg \
- "--run range negation" --run="!1-3" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-range-neg <<-\EOF
+test_expect_success 'subtest: --run range negation' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="!1-3" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 # skip passing test #1 (--run)
> ok 2 # skip passing test #2 (--run)
> ok 3 # skip passing test #3 (--run)
@@ -635,17 +457,10 @@ test_expect_success '--run range negation' '
EOF
'
-test_expect_success '--run include, exclude and include' '
- run_sub_test_lib_test run-inc-neg-inc \
- "--run include, exclude and include" \
- --run="1-5,!1-3,2" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-inc-neg-inc <<-\EOF
+test_expect_success 'subtest: --run include, exclude and include' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="1-5,!1-3,2" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 # skip passing test #1 (--run)
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -657,17 +472,10 @@ test_expect_success '--run include, exclude and include' '
EOF
'
-test_expect_success '--run include, exclude and include, comma separated' '
- run_sub_test_lib_test run-inc-neg-inc-comma \
- "--run include, exclude and include, comma separated" \
- --run=1-5,!1-3,2 <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-inc-neg-inc-comma <<-\EOF
+test_expect_success 'subtest: --run include, exclude and include, comma separated' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run=1-5,!1-3,2 &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 # skip passing test #1 (--run)
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -679,17 +487,10 @@ test_expect_success '--run include, exclude and include, comma separated' '
EOF
'
-test_expect_success '--run exclude and include' '
- run_sub_test_lib_test run-neg-inc \
- "--run exclude and include" \
- --run="!3-,5" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-neg-inc <<-\EOF
+test_expect_success 'subtest: --run exclude and include' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="!3-,5" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -701,17 +502,10 @@ test_expect_success '--run exclude and include' '
EOF
'
-test_expect_success '--run empty selectors' '
- run_sub_test_lib_test run-empty-sel \
- "--run empty selectors" \
- --run="1,,3,,,5" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-empty-sel <<-\EOF
+test_expect_success 'subtest: --run empty selectors' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="1,,3,,,5" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (--run)
> ok 3 - passing test #3
@@ -723,9 +517,8 @@ test_expect_success '--run empty selectors' '
EOF
'
-test_expect_success '--run substring selector' '
- run_sub_test_lib_test run-substring-selector \
- "--run empty selectors" \
+test_expect_success 'subtest: --run substring selector' '
+ write_and_run_sub_test_lib_test run-substring-selector \
--run="relevant" <<-\EOF &&
test_expect_success "relevant test" "true"
for i in 1 2 3 4 5 6
@@ -747,9 +540,8 @@ test_expect_success '--run substring selector' '
EOF
'
-test_expect_success '--run keyword selection' '
- run_sub_test_lib_test_err run-inv-range-start \
- "--run invalid range start" \
+test_expect_success 'subtest: --run keyword selection' '
+ write_and_run_sub_test_lib_test_err run-inv-range-start \
--run="a-5" <<-\EOF &&
test_expect_success "passing test #1" "true"
test_done
@@ -762,14 +554,10 @@ test_expect_success '--run keyword selection' '
EOF_ERR
'
-test_expect_success '--run invalid range end' '
- run_sub_test_lib_test_err run-inv-range-end \
- "--run invalid range end" \
- --run="1-z" <<-\EOF &&
- test_expect_success "passing test #1" "true"
- test_done
- EOF
- check_sub_test_lib_test_err run-inv-range-end \
+test_expect_success 'subtest: --run invalid range end' '
+ run_sub_test_lib_test_err run-inv-range-start \
+ --run="1-z" &&
+ check_sub_test_lib_test_err run-inv-range-start \
<<-\EOF_OUT 3<<-EOF_ERR
> FATAL: Unexpected exit with code 1
EOF_OUT
@@ -777,8 +565,8 @@ test_expect_success '--run invalid range end' '
EOF_ERR
'
-test_expect_success 'tests respect prerequisites' '
- run_sub_test_lib_test prereqs "tests respect prereqs" <<-\EOF &&
+test_expect_success 'subtest: tests respect prerequisites' '
+ write_and_run_sub_test_lib_test prereqs <<-\EOF &&
test_set_prereq HAVEIT
test_expect_success HAVEIT "prereq is satisfied" "true"
@@ -807,8 +595,8 @@ test_expect_success 'tests respect prerequisites' '
EOF
'
-test_expect_success 'tests respect lazy prerequisites' '
- run_sub_test_lib_test lazy-prereqs "respect lazy prereqs" <<-\EOF &&
+test_expect_success 'subtest: tests respect lazy prerequisites' '
+ write_and_run_sub_test_lib_test lazy-prereqs <<-\EOF &&
test_lazy_prereq LAZY_TRUE true
test_expect_success LAZY_TRUE "lazy prereq is satisifed" "true"
@@ -831,8 +619,8 @@ test_expect_success 'tests respect lazy prerequisites' '
EOF
'
-test_expect_success 'nested lazy prerequisites' '
- run_sub_test_lib_test nested-lazy "nested lazy prereqs" <<-\EOF &&
+test_expect_success 'subtest: nested lazy prerequisites' '
+ write_and_run_sub_test_lib_test nested-lazy <<-\EOF &&
test_lazy_prereq NESTED_INNER "
>inner &&
@@ -857,9 +645,9 @@ test_expect_success 'nested lazy prerequisites' '
EOF
'
-test_expect_success 'lazy prereqs do not turn off tracing' '
- run_sub_test_lib_test lazy-prereq-and-tracing \
- "lazy prereqs and -x" -v -x <<-\EOF &&
+test_expect_success 'subtest: lazy prereqs do not turn off tracing' '
+ write_and_run_sub_test_lib_test lazy-prereq-and-tracing \
+ -v -x <<-\EOF &&
test_lazy_prereq LAZY true
test_expect_success lazy "test_have_prereq LAZY && echo trace"
@@ -870,8 +658,8 @@ test_expect_success 'lazy prereqs do not turn off tracing' '
grep "echo trace" lazy-prereq-and-tracing/err
'
-test_expect_success 'tests clean up after themselves' '
- run_sub_test_lib_test cleanup "test with cleanup" <<-\EOF &&
+test_expect_success 'subtest: tests clean up after themselves' '
+ write_and_run_sub_test_lib_test cleanup <<-\EOF &&
clean=no
test_expect_success "do cleanup" "
test_when_finished clean=yes
@@ -890,9 +678,9 @@ test_expect_success 'tests clean up after themselves' '
EOF
'
-test_expect_success 'tests clean up even on failures' '
- run_sub_test_lib_test_err \
- failing-cleanup "Failing tests with cleanup commands" <<-\EOF &&
+test_expect_success 'subtest: tests clean up even on failures' '
+ write_and_run_sub_test_lib_test_err \
+ failing-cleanup <<-\EOF &&
test_expect_success "tests clean up even after a failure" "
touch clean-after-failure &&
test_when_finished rm clean-after-failure &&
@@ -919,9 +707,9 @@ test_expect_success 'tests clean up even on failures' '
EOF
'
-test_expect_success 'test_atexit is run' '
- run_sub_test_lib_test_err \
- atexit-cleanup "Run atexit commands" -i <<-\EOF &&
+test_expect_success 'subtest: test_atexit is run' '
+ write_and_run_sub_test_lib_test_err \
+ atexit-cleanup -i <<-\EOF &&
test_expect_success "tests clean up even after a failure" "
> ../../clean-atexit &&
test_atexit rm ../../clean-atexit &&
@@ -1271,28 +1059,29 @@ P=$(test_oid root)
test_expect_success 'git commit-tree records the correct tree in a commit' '
commit0=$(echo NO | git commit-tree $P) &&
- tree=$(git show --pretty=raw $commit0 |
- sed -n -e "s/^tree //p" -e "/^author /q") &&
+ git show --pretty=raw $commit0 >out &&
+ tree=$(sed -n -e "s/^tree //p" -e "/^author /q" out) &&
test "z$tree" = "z$P"
'
test_expect_success 'git commit-tree records the correct parent in a commit' '
commit1=$(echo NO | git commit-tree $P -p $commit0) &&
- parent=$(git show --pretty=raw $commit1 |
- sed -n -e "s/^parent //p" -e "/^author /q") &&
+ git show --pretty=raw $commit1 >out &&
+ parent=$(sed -n -e "s/^parent //p" -e "/^author /q" out) &&
test "z$commit0" = "z$parent"
'
test_expect_success 'git commit-tree omits duplicated parent in a commit' '
commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) &&
- parent=$(git show --pretty=raw $commit2 |
- sed -n -e "s/^parent //p" -e "/^author /q" |
- sort -u) &&
+ git show --pretty=raw $commit2 >out &&
+ cat >match.sed <<-\EOF &&
+ s/^parent //p
+ /^author /q
+ EOF
+ parent=$(sed -n -f match.sed out | sort -u) &&
test "z$commit0" = "z$parent" &&
- numparent=$(git show --pretty=raw $commit2 |
- sed -n -e "s/^parent //p" -e "/^author /q" |
- wc -l) &&
- test $numparent = 1
+ git show --pretty=raw $commit2 >out &&
+ test_stdout_line_count = 1 sed -n -f match.sed out
'
test_expect_success 'update-index D/F conflict' '
diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh
index e3137d638e..37d68ef03b 100755
--- a/t/t0004-unwritable.sh
+++ b/t/t0004-unwritable.sh
@@ -2,6 +2,7 @@
test_description='detect unwritable repository and fail correctly'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
@@ -21,7 +22,7 @@ test_expect_success POSIXPERM,SANITY 'write-tree should notice unwritable reposi
test_must_fail git write-tree
'
-test_expect_success POSIXPERM,SANITY 'commit should notice unwritable repository' '
+test_expect_success POSIXPERM,SANITY,!SANITIZE_LEAK 'commit should notice unwritable repository' '
test_when_finished "chmod 775 .git/objects .git/objects/??" &&
chmod a-w .git/objects .git/objects/?? &&
test_must_fail git commit -m second
diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh
index 5343ffd3f9..e094975b13 100755
--- a/t/t0011-hashmap.sh
+++ b/t/t0011-hashmap.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test hashmap and string hash functions'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_hashmap() {
diff --git a/t/t0012-help.sh b/t/t0012-help.sh
index 5679e29c62..91b68c74a1 100755
--- a/t/t0012-help.sh
+++ b/t/t0012-help.sh
@@ -34,6 +34,18 @@ test_expect_success 'basic help commands' '
git help -a >/dev/null
'
+test_expect_success 'invalid usage' '
+ test_expect_code 129 git help -g add &&
+ test_expect_code 129 git help -a -c &&
+
+ test_expect_code 129 git help -g add &&
+ test_expect_code 129 git help -a -g &&
+
+ test_expect_code 129 git help -g -c &&
+ test_expect_code 129 git help --config-for-completion add &&
+ test_expect_code 129 git help --config-sections-for-completion add
+'
+
test_expect_success "works for commands and guides by default" '
configure_help &&
git help status &&
@@ -73,6 +85,59 @@ test_expect_success 'git help -g' '
test_i18ngrep "^ tutorial " help.output
'
+test_expect_success 'git help fails for non-existing html pages' '
+ configure_help &&
+ mkdir html-empty &&
+ test_must_fail git -c help.htmlpath=html-empty help status &&
+ test_must_be_empty test-browser.log
+'
+
+test_expect_success 'git help succeeds without git.html' '
+ configure_help &&
+ mkdir html-with-docs &&
+ touch html-with-docs/git-status.html &&
+ git -c help.htmlpath=html-with-docs help status &&
+ echo "html-with-docs/git-status.html" >expect &&
+ test_cmp expect test-browser.log
+'
+
+test_expect_success 'git help -c' '
+ git help -c >help.output &&
+ cat >expect <<-\EOF &&
+
+ '\''git help config'\'' for more information
+ EOF
+ grep -v -E \
+ -e "^[^.]+\.[^.]+$" \
+ -e "^[^.]+\.[^.]+\.[^.]+$" \
+ help.output >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git help --config-for-completion' '
+ git help -c >human &&
+ grep -E \
+ -e "^[^.]+\.[^.]+$" \
+ -e "^[^.]+\.[^.]+\.[^.]+$" human |
+ sed -e "s/\*.*//" -e "s/<.*//" |
+ sort -u >human.munged &&
+
+ git help --config-for-completion >vars &&
+ test_cmp human.munged vars
+'
+
+test_expect_success 'git help --config-sections-for-completion' '
+ git help -c >human &&
+ grep -E \
+ -e "^[^.]+\.[^.]+$" \
+ -e "^[^.]+\.[^.]+\.[^.]+$" human |
+ sed -e "s/\..*//" |
+ sort -u >human.munged &&
+
+ git help --config-sections-for-completion >sections &&
+ test_cmp human.munged sections
+'
+
test_expect_success 'generate builtin list' '
git --list-cmds=builtins >builtins
'
diff --git a/t/t0016-oidmap.sh b/t/t0016-oidmap.sh
index 31f8276ba8..0faef1f4f1 100755
--- a/t/t0016-oidmap.sh
+++ b/t/t0016-oidmap.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test oidmap'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# This purposefully is very similar to t0011-hashmap.sh
diff --git a/t/t0017-env-helper.sh b/t/t0017-env-helper.sh
index 4a159f99e4..2e42fba956 100755
--- a/t/t0017-env-helper.sh
+++ b/t/t0017-env-helper.sh
@@ -2,6 +2,7 @@
test_description='test env--helper'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
diff --git a/t/t0018-advice.sh b/t/t0018-advice.sh
index 39e5e4b34f..c13057a4ca 100755
--- a/t/t0018-advice.sh
+++ b/t/t0018-advice.sh
@@ -2,6 +2,7 @@
test_description='Test advise_if_enabled functionality'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'advice should be printed when config variable is unset' '
diff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh
index 0c24a0f9a3..ae1ca380c1 100755
--- a/t/t0030-stripspace.sh
+++ b/t/t0030-stripspace.sh
@@ -5,6 +5,7 @@
test_description='git stripspace'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
t40='A quick brown fox jumps over the lazy do'
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index ad4746d899..da310ed29b 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -37,7 +37,6 @@ String options
--list <str> add str to list
Magic arguments
- --quux means --quux
-NUM set integer to NUM
+ same as -b
--ambiguous positive ambiguity
@@ -263,10 +262,6 @@ test_expect_success 'detect possible typos' '
test_cmp typo.err output.err
'
-test_expect_success 'keep some options as arguments' '
- test-tool parse-options --expect="arg 00: --quux" --quux
-'
-
cat >expect <<\EOF
Callback: "four", 0
boolean: 5
diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh
index c6ee9f66b1..46d4839194 100755
--- a/t/t0063-string-list.sh
+++ b/t/t0063-string-list.sh
@@ -5,6 +5,7 @@
test_description='Test string list functionality'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_split () {
diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 9bf66c9e68..9067572648 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -195,6 +195,7 @@ test_expect_success 'reset --hard gives cache-tree' '
test_expect_success 'reset --hard without index gives cache-tree' '
rm -f .git/index &&
+ git clean -fd &&
git reset --hard &&
test_cache_tree
'
diff --git a/t/t0091-bugreport.sh b/t/t0091-bugreport.sh
index 526304ff95..eeedbfa919 100755
--- a/t/t0091-bugreport.sh
+++ b/t/t0091-bugreport.sh
@@ -2,6 +2,7 @@
test_description='git bugreport'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Headers "[System Info]" will be followed by a non-empty line if we put some
diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh
index ebd5fa5249..698b7159f0 100755
--- a/t/t0301-credential-cache.sh
+++ b/t/t0301-credential-cache.sh
@@ -9,6 +9,21 @@ test -z "$NO_UNIX_SOCKETS" || {
test_done
}
+uname_s=$(uname -s)
+case $uname_s in
+*MINGW*)
+ test_path_is_socket () {
+ # `test -S` cannot detect Win10's Unix sockets
+ test_path_exists "$1"
+ }
+ ;;
+*)
+ test_path_is_socket () {
+ test -S "$1"
+ }
+ ;;
+esac
+
# don't leave a stale daemon running
test_atexit 'git credential-cache exit'
@@ -21,7 +36,7 @@ test_expect_success 'socket defaults to ~/.cache/git/credential/socket' '
rmdir -p .cache/git/credential/
" &&
test_path_is_missing "$HOME/.git-credential-cache" &&
- test -S "$HOME/.cache/git/credential/socket"
+ test_path_is_socket "$HOME/.cache/git/credential/socket"
'
XDG_CACHE_HOME="$HOME/xdg"
@@ -31,7 +46,7 @@ helper_test cache
test_expect_success "use custom XDG_CACHE_HOME if set and default sockets are not created" '
test_when_finished "git credential-cache exit" &&
- test -S "$XDG_CACHE_HOME/git/credential/socket" &&
+ test_path_is_socket "$XDG_CACHE_HOME/git/credential/socket" &&
test_path_is_missing "$HOME/.git-credential-cache/socket" &&
test_path_is_missing "$HOME/.cache/git/credential/socket"
'
@@ -48,7 +63,7 @@ test_expect_success 'credential-cache --socket option overrides default location
username=store-user
password=store-pass
EOF
- test -S "$HOME/dir/socket"
+ test_path_is_socket "$HOME/dir/socket"
'
test_expect_success "use custom XDG_CACHE_HOME even if xdg socket exists" '
@@ -62,7 +77,7 @@ test_expect_success "use custom XDG_CACHE_HOME even if xdg socket exists" '
username=store-user
password=store-pass
EOF
- test -S "$HOME/.cache/git/credential/socket" &&
+ test_path_is_socket "$HOME/.cache/git/credential/socket" &&
XDG_CACHE_HOME="$HOME/xdg" &&
export XDG_CACHE_HOME &&
check approve cache <<-\EOF &&
@@ -71,7 +86,7 @@ test_expect_success "use custom XDG_CACHE_HOME even if xdg socket exists" '
username=store-user
password=store-pass
EOF
- test -S "$XDG_CACHE_HOME/git/credential/socket"
+ test_path_is_socket "$XDG_CACHE_HOME/git/credential/socket"
'
test_expect_success 'use user socket if user directory exists' '
@@ -79,14 +94,15 @@ test_expect_success 'use user socket if user directory exists' '
git credential-cache exit &&
rmdir \"\$HOME/.git-credential-cache/\"
" &&
- mkdir -p -m 700 "$HOME/.git-credential-cache/" &&
+ mkdir -p "$HOME/.git-credential-cache/" &&
+ chmod 700 "$HOME/.git-credential-cache/" &&
check approve cache <<-\EOF &&
protocol=https
host=example.com
username=store-user
password=store-pass
EOF
- test -S "$HOME/.git-credential-cache/socket"
+ test_path_is_socket "$HOME/.git-credential-cache/socket"
'
test_expect_success SYMLINKS 'use user socket if user directory is a symlink to a directory' '
@@ -103,7 +119,7 @@ test_expect_success SYMLINKS 'use user socket if user directory is a symlink to
username=store-user
password=store-pass
EOF
- test -S "$HOME/.git-credential-cache/socket"
+ test_path_is_socket "$HOME/.git-credential-cache/socket"
'
helper_test_timeout cache --timeout=1
diff --git a/t/t1013-read-tree-submodule.sh b/t/t1013-read-tree-submodule.sh
index b6df7444c0..bfc90d4cf2 100755
--- a/t/t1013-read-tree-submodule.sh
+++ b/t/t1013-read-tree-submodule.sh
@@ -6,7 +6,6 @@ test_description='read-tree can handle submodules'
. "$TEST_DIRECTORY"/lib-submodule-update.sh
KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
-KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1
test_submodule_switch_recursing_with_args "read-tree -u -m"
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index 71236981e6..272ba1b566 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -206,16 +206,21 @@ test_expect_success 'sparse-checkout disable' '
'
test_expect_success 'sparse-index enabled and disabled' '
- git -C repo sparse-checkout init --cone --sparse-index &&
- test_cmp_config -C repo true index.sparse &&
- test-tool -C repo read-cache --table >cache &&
- grep " tree " cache &&
-
- git -C repo sparse-checkout disable &&
- test-tool -C repo read-cache --table >cache &&
- ! grep " tree " cache &&
- git -C repo config --list >config &&
- ! grep index.sparse config
+ (
+ sane_unset GIT_TEST_SPLIT_INDEX &&
+ git -C repo update-index --no-split-index &&
+
+ git -C repo sparse-checkout init --cone --sparse-index &&
+ test_cmp_config -C repo true index.sparse &&
+ test-tool -C repo read-cache --table >cache &&
+ grep " tree " cache &&
+
+ git -C repo sparse-checkout disable &&
+ test-tool -C repo read-cache --table >cache &&
+ ! grep " tree " cache &&
+ git -C repo config --list >config &&
+ ! grep index.sparse config
+ )
'
test_expect_success 'cone mode: init and set' '
@@ -406,7 +411,7 @@ test_expect_success 'sparse-checkout (init|set|disable) warns with unmerged stat
git -C unmerged sparse-checkout disable
'
-test_expect_success 'sparse-checkout reapply' '
+test_expect_failure 'sparse-checkout reapply' '
git clone repo tweak &&
echo dirty >tweak/deep/deeper2/a &&
@@ -438,6 +443,8 @@ test_expect_success 'sparse-checkout reapply' '
test_i18ngrep "warning.*The following paths are unmerged" err &&
test_path_is_file tweak/folder1/a &&
+ # NEEDSWORK: We are asking to update a file outside of the
+ # sparse-checkout cone, but this is no longer allowed.
git -C tweak add folder1/a &&
git -C tweak sparse-checkout reapply 2>err &&
test_must_be_empty err &&
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 886e78715f..ca91c6a67f 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -187,6 +187,16 @@ test_sparse_match () {
test_cmp sparse-checkout-err sparse-index-err
}
+test_sparse_unstaged () {
+ file=$1 &&
+ for repo in sparse-checkout sparse-index
+ do
+ # Skip "unmerged" paths
+ git -C $repo diff --staged --diff-filter=u -- "$file" >diff &&
+ test_must_be_empty diff || return 1
+ done
+}
+
test_expect_success 'sparse-index contents' '
init_repos &&
@@ -291,6 +301,20 @@ test_expect_success 'add, commit, checkout' '
test_all_match git checkout -
'
+test_expect_success 'add outside sparse cone' '
+ init_repos &&
+
+ run_on_sparse mkdir folder1 &&
+ run_on_sparse ../edit-contents folder1/a &&
+ run_on_sparse ../edit-contents folder1/newfile &&
+ test_sparse_match test_must_fail git add folder1/a &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
+ test_sparse_match test_must_fail git add folder1/newfile &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/newfile
+'
+
test_expect_success 'commit including unstaged changes' '
init_repos &&
@@ -339,18 +363,24 @@ test_expect_success 'status/add: outside sparse cone' '
# Adding the path outside of the sparse-checkout cone should fail.
test_sparse_match test_must_fail git add folder1/a &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
test_sparse_match test_must_fail git add --refresh folder1/a &&
-
- # NEEDSWORK: Adding a newly-tracked file outside the cone succeeds
- test_sparse_match git add folder1/new &&
-
- test_all_match git add . &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
+ test_sparse_match test_must_fail git add folder1/new &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/new &&
+ test_sparse_match git add --sparse folder1/a &&
+ test_sparse_match git add --sparse folder1/new &&
+
+ test_all_match git add --sparse . &&
test_all_match git status --porcelain=v2 &&
test_all_match git commit -m folder1/new &&
test_all_match git rev-parse HEAD^{tree} &&
run_on_all ../edit-contents folder1/newer &&
- test_all_match git add folder1/ &&
+ test_all_match git add --sparse folder1/ &&
test_all_match git status --porcelain=v2 &&
test_all_match git commit -m folder1/newer &&
test_all_match git rev-parse HEAD^{tree}
@@ -494,11 +524,6 @@ test_expect_success 'merge, cherry-pick, and rebase' '
done
'
-# NEEDSWORK: This test is documenting current behavior, but that
-# behavior can be confusing to users so there is desire to change it.
-# Right now, users might be using this flow to work through conflicts,
-# so any solution should present advice to users who try this sequence
-# of commands to follow whatever new method we create.
test_expect_success 'merge with conflict outside cone' '
init_repos &&
@@ -513,13 +538,19 @@ test_expect_success 'merge with conflict outside cone' '
test_all_match git status --porcelain=v2 &&
# 2. Add the file with conflict markers
- test_all_match git add folder1/a &&
+ test_sparse_match test_must_fail git add folder1/a &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
+ test_all_match git add --sparse folder1/a &&
test_all_match git status --porcelain=v2 &&
# 3. Rename the file to another sparse filename and
# accept conflict markers as resolved content.
run_on_all mv folder2/a folder2/z &&
- test_all_match git add folder2 &&
+ test_sparse_match test_must_fail git add folder2 &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder2/z &&
+ test_all_match git add --sparse folder2 &&
test_all_match git status --porcelain=v2 &&
test_all_match git merge --continue &&
@@ -544,13 +575,25 @@ test_expect_success 'cherry-pick/rebase with conflict outside cone' '
test_all_match git status --porcelain=v2 &&
# 2. Add the file with conflict markers
- test_all_match git add folder1/a &&
+ # NEEDSWORK: Even though the merge conflict removed the
+ # SKIP_WORKTREE bit from the index entry for folder1/a, we should
+ # warn that this is a problematic add.
+ test_sparse_match test_must_fail git add folder1/a &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
+ test_all_match git add --sparse folder1/a &&
test_all_match git status --porcelain=v2 &&
# 3. Rename the file to another sparse filename and
# accept conflict markers as resolved content.
+ # NEEDSWORK: This mode now fails, because folder2/z is
+ # outside of the sparse-checkout cone and does not match an
+ # existing index entry with the SKIP_WORKTREE bit cleared.
run_on_all mv folder2/a folder2/z &&
- test_all_match git add folder2 &&
+ test_sparse_match test_must_fail git add folder2 &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder2/z &&
+ test_all_match git add --sparse folder2 &&
test_all_match git status --porcelain=v2 &&
test_all_match git $OPERATION --continue &&
@@ -626,6 +669,7 @@ test_expect_success 'clean' '
test_expect_success 'submodule handling' '
init_repos &&
+ test_sparse_match git sparse-checkout add modules &&
test_all_match mkdir modules &&
test_all_match touch modules/a &&
test_all_match git add modules &&
@@ -635,6 +679,7 @@ test_expect_success 'submodule handling' '
test_all_match git commit -m "add submodule" &&
# having a submodule prevents "modules" from collapse
+ test_sparse_match git sparse-checkout set deep/deeper1 &&
test-tool -C sparse-index read-cache --table >cache &&
grep "100644 blob .* modules/a" cache &&
grep "160000 commit $(git -C initial-repo rev-parse HEAD) modules/sub" cache
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 4506cd435b..0d4f73acaa 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -1598,6 +1598,40 @@ test_expect_success 'transaction cannot restart ongoing transaction' '
test_must_fail git show-ref --verify refs/heads/restart
'
+test_expect_success PIPE 'transaction flushes status updates' '
+ mkfifo in out &&
+ (git update-ref --stdin <in >out &) &&
+
+ exec 9>in &&
+ exec 8<out &&
+ test_when_finished "exec 9>&-" &&
+ test_when_finished "exec 8<&-" &&
+
+ echo "start" >&9 &&
+ echo "start: ok" >expected &&
+ read line <&8 &&
+ echo "$line" >actual &&
+ test_cmp expected actual &&
+
+ echo "create refs/heads/flush $A" >&9 &&
+
+ echo prepare >&9 &&
+ echo "prepare: ok" >expected &&
+ read line <&8 &&
+ echo "$line" >actual &&
+ test_cmp expected actual &&
+
+ # This must now fail given that we have locked the ref.
+ test_must_fail git update-ref refs/heads/flush $B 2>stderr &&
+ grep "fatal: update_ref failed for ref ${SQ}refs/heads/flush${SQ}: cannot lock ref" stderr &&
+
+ echo commit >&9 &&
+ echo "commit: ok" >expected &&
+ read line <&8 &&
+ echo "$line" >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'directory not created deleting packed ref' '
git branch d1/d2/r1 HEAD &&
git pack-refs --all &&
diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh
index b1839e0877..fa3aeb80f2 100755
--- a/t/t1430-bad-ref-name.sh
+++ b/t/t1430-bad-ref-name.sh
@@ -170,7 +170,7 @@ test_expect_success 'for-each-ref emits warnings for broken names' '
! grep -e "badname" output &&
! grep -e "broken\.\.\.symref" output &&
test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.ref" error &&
- test_i18ngrep "ignoring broken ref refs/heads/badname" error &&
+ test_i18ngrep ! "ignoring broken ref refs/heads/badname" error &&
test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.symref" error
'
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index b29563fc99..284fe18e72 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -282,4 +282,58 @@ test_expect_success 'test --parseopt --stuck-long and short option with unset op
test_cmp expect output
'
+test_expect_success 'test --parseopt help output: "wrapped" options normal "or:" lines' '
+ sed -e "s/^|//" >spec <<-\EOF &&
+ |cmd [--some-option]
+ | [--another-option]
+ |cmd [--yet-another-option]
+ |--
+ |h,help show the help
+ EOF
+
+ sed -e "s/^|//" >expect <<-\END_EXPECT &&
+ |cat <<\EOF
+ |usage: cmd [--some-option]
+ | or: [--another-option]
+ | or: cmd [--yet-another-option]
+ |
+ | -h, --help show the help
+ |
+ |EOF
+ END_EXPECT
+
+ test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'test --parseopt help output: multi-line blurb after empty line' '
+ sed -e "s/^|//" >spec <<-\EOF &&
+ |cmd [--some-option]
+ | [--another-option]
+ |
+ |multi
+ |line
+ |blurb
+ |--
+ |h,help show the help
+ EOF
+
+ sed -e "s/^|//" >expect <<-\END_EXPECT &&
+ |cat <<\EOF
+ |usage: cmd [--some-option]
+ | or: [--another-option]
+ |
+ | multi
+ | line
+ | blurb
+ |
+ | -h, --help show the help
+ |
+ |EOF
+ END_EXPECT
+
+ test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1600-index.sh b/t/t1600-index.sh
index c9b9e718b8..46329c488b 100755
--- a/t/t1600-index.sh
+++ b/t/t1600-index.sh
@@ -4,6 +4,8 @@ test_description='index file specific tests'
. ./test-lib.sh
+sane_unset GIT_TEST_SPLIT_INDEX
+
test_expect_success 'setup' '
echo 1 >a
'
@@ -13,7 +15,8 @@ test_expect_success 'bogus GIT_INDEX_VERSION issues warning' '
rm -f .git/index &&
GIT_INDEX_VERSION=2bogus &&
export GIT_INDEX_VERSION &&
- git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ git add a 2>err &&
+ sed "s/[0-9]//" err >actual.err &&
sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
warning: GIT_INDEX_VERSION set, but the value is invalid.
Using version Z
@@ -27,7 +30,8 @@ test_expect_success 'out of bounds GIT_INDEX_VERSION issues warning' '
rm -f .git/index &&
GIT_INDEX_VERSION=1 &&
export GIT_INDEX_VERSION &&
- git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ git add a 2>err &&
+ sed "s/[0-9]//" err >actual.err &&
sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
warning: GIT_INDEX_VERSION set, but the value is invalid.
Using version Z
@@ -50,7 +54,8 @@ test_expect_success 'out of bounds index.version issues warning' '
sane_unset GIT_INDEX_VERSION &&
rm -f .git/index &&
git config --add index.version 1 &&
- git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ git add a 2>err &&
+ sed "s/[0-9]//" err >actual.err &&
sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
warning: index.version set, but the value is invalid.
Using version Z
@@ -79,7 +84,7 @@ test_index_version () {
else
unset GIT_INDEX_VERSION
fi &&
- git add a 2>&1 &&
+ git add a &&
echo $EXPECTED_OUTPUT_VERSION >expect &&
test-tool index-version <.git/index >actual &&
test_cmp expect actual
diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh
index 986baa612e..decd2527ed 100755
--- a/t/t1700-split-index.sh
+++ b/t/t1700-split-index.sh
@@ -510,4 +510,38 @@ test_expect_success 'do not refresh null base index' '
)
'
+test_expect_success 'reading split index at alternate location' '
+ git init reading-alternate-location &&
+ (
+ cd reading-alternate-location &&
+ >file-in-alternate &&
+ git update-index --split-index --add file-in-alternate
+ ) &&
+ echo file-in-alternate >expect &&
+
+ # Should be able to find the shared index both right next to
+ # the specified split index file ...
+ GIT_INDEX_FILE=./reading-alternate-location/.git/index \
+ git ls-files --cached >actual &&
+ test_cmp expect actual &&
+
+ # ... and, for backwards compatibility, in the current GIT_DIR
+ # as well.
+ mv -v ./reading-alternate-location/.git/sharedindex.* .git &&
+ GIT_INDEX_FILE=./reading-alternate-location/.git/index \
+ git ls-files --cached >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'GIT_TEST_SPLIT_INDEX works' '
+ git init git-test-split-index &&
+ (
+ cd git-test-split-index &&
+ >file &&
+ GIT_TEST_SPLIT_INDEX=1 git update-index --add file &&
+ ls -l .git/sharedindex.* >actual &&
+ test_line_count = 1 actual
+ )
+'
+
test_done
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
index 70d69263e6..660132ff8d 100755
--- a/t/t2021-checkout-overwrite.sh
+++ b/t/t2021-checkout-overwrite.sh
@@ -48,6 +48,7 @@ test_expect_success 'checkout commit with dir must not remove untracked a/b' '
test_expect_success SYMLINKS 'the symlink remained' '
+ test_when_finished "rm a/b" &&
test -h a/b
'
diff --git a/t/t2500-untracked-overwriting.sh b/t/t2500-untracked-overwriting.sh
new file mode 100755
index 0000000000..5c0bf4d21f
--- /dev/null
+++ b/t/t2500-untracked-overwriting.sh
@@ -0,0 +1,244 @@
+#!/bin/sh
+
+test_description='Test handling of overwriting untracked files'
+
+. ./test-lib.sh
+
+test_setup_reset () {
+ git init reset_$1 &&
+ (
+ cd reset_$1 &&
+ test_commit init &&
+
+ git branch stable &&
+ git branch work &&
+
+ git checkout work &&
+ test_commit foo &&
+
+ git checkout stable
+ )
+}
+
+test_expect_success 'reset --hard will nuke untracked files/dirs' '
+ test_setup_reset hard &&
+ (
+ cd reset_hard &&
+ git ls-tree -r stable &&
+ git log --all --name-status --oneline &&
+ git ls-tree -r work &&
+
+ mkdir foo.t &&
+ echo precious >foo.t/file &&
+ echo foo >expect &&
+
+ git reset --hard work &&
+
+ # check that untracked directory foo.t/ was nuked
+ test_path_is_file foo.t &&
+ test_cmp expect foo.t
+ )
+'
+
+test_expect_success 'reset --merge will preserve untracked files/dirs' '
+ test_setup_reset merge &&
+ (
+ cd reset_merge &&
+
+ mkdir foo.t &&
+ echo precious >foo.t/file &&
+ cp foo.t/file expect &&
+
+ test_must_fail git reset --merge work 2>error &&
+ test_cmp expect foo.t/file &&
+ grep "Updating .foo.t. would lose untracked files" error
+ )
+'
+
+test_expect_success 'reset --keep will preserve untracked files/dirs' '
+ test_setup_reset keep &&
+ (
+ cd reset_keep &&
+
+ mkdir foo.t &&
+ echo precious >foo.t/file &&
+ cp foo.t/file expect &&
+
+ test_must_fail git reset --merge work 2>error &&
+ test_cmp expect foo.t/file &&
+ grep "Updating.*foo.t.*would lose untracked files" error
+ )
+'
+
+test_setup_checkout_m () {
+ git init checkout &&
+ (
+ cd checkout &&
+ test_commit init &&
+
+ test_write_lines file has some >filler &&
+ git add filler &&
+ git commit -m filler &&
+
+ git branch stable &&
+
+ git switch -c work &&
+ echo stuff >notes.txt &&
+ test_write_lines file has some words >filler &&
+ git add notes.txt filler &&
+ git commit -m filler &&
+
+ git checkout stable
+ )
+}
+
+test_expect_success 'checkout -m does not nuke untracked file' '
+ test_setup_checkout_m &&
+ (
+ cd checkout &&
+
+ # Tweak filler
+ test_write_lines this file has some >filler &&
+ # Make an untracked file, save its contents in "expect"
+ echo precious >notes.txt &&
+ cp notes.txt expect &&
+
+ test_must_fail git checkout -m work &&
+ test_cmp expect notes.txt
+ )
+'
+
+test_setup_sequencing () {
+ git init sequencing_$1 &&
+ (
+ cd sequencing_$1 &&
+ test_commit init &&
+
+ test_write_lines this file has some words >filler &&
+ git add filler &&
+ git commit -m filler &&
+
+ mkdir -p foo/bar &&
+ test_commit foo/bar/baz &&
+
+ git branch simple &&
+ git branch fooey &&
+
+ git checkout fooey &&
+ git rm foo/bar/baz.t &&
+ echo stuff >>filler &&
+ git add -u &&
+ git commit -m "changes" &&
+
+ git checkout simple &&
+ echo items >>filler &&
+ echo newstuff >>newfile &&
+ git add filler newfile &&
+ git commit -m another
+ )
+}
+
+test_expect_success 'git rebase --abort and untracked files' '
+ test_setup_sequencing rebase_abort_and_untracked &&
+ (
+ cd sequencing_rebase_abort_and_untracked &&
+ git checkout fooey &&
+ test_must_fail git rebase simple &&
+
+ cat init.t &&
+ git rm init.t &&
+ echo precious >init.t &&
+ cp init.t expect &&
+ git status --porcelain &&
+ test_must_fail git rebase --abort &&
+ test_cmp expect init.t
+ )
+'
+
+test_expect_success 'git rebase fast forwarding and untracked files' '
+ test_setup_sequencing rebase_fast_forward_and_untracked &&
+ (
+ cd sequencing_rebase_fast_forward_and_untracked &&
+ git checkout init &&
+ echo precious >filler &&
+ cp filler expect &&
+ test_must_fail git rebase init simple &&
+ test_cmp expect filler
+ )
+'
+
+test_expect_failure 'git rebase --autostash and untracked files' '
+ test_setup_sequencing rebase_autostash_and_untracked &&
+ (
+ cd sequencing_rebase_autostash_and_untracked &&
+ git checkout simple &&
+ git rm filler &&
+ mkdir filler &&
+ echo precious >filler/file &&
+ cp filler/file expect &&
+ git rebase --autostash init &&
+ test_path_is_file filler/file
+ )
+'
+
+test_expect_failure 'git stash and untracked files' '
+ test_setup_sequencing stash_and_untracked_files &&
+ (
+ cd sequencing_stash_and_untracked_files &&
+ git checkout simple &&
+ git rm filler &&
+ mkdir filler &&
+ echo precious >filler/file &&
+ cp filler/file expect &&
+ git status --porcelain &&
+ git stash push &&
+ git status --porcelain &&
+ test_path_is_file filler/file
+ )
+'
+
+test_expect_success 'git am --abort and untracked dir vs. unmerged file' '
+ test_setup_sequencing am_abort_and_untracked &&
+ (
+ cd sequencing_am_abort_and_untracked &&
+ git format-patch -1 --stdout fooey >changes.mbox &&
+ test_must_fail git am --3way changes.mbox &&
+
+ # Delete the conflicted file; we will stage and commit it later
+ rm filler &&
+
+ # Put an unrelated untracked directory there
+ mkdir filler &&
+ echo foo >filler/file1 &&
+ echo bar >filler/file2 &&
+
+ test_must_fail git am --abort 2>errors &&
+ test_path_is_dir filler &&
+ grep "Updating .filler. would lose untracked files in it" errors
+ )
+'
+
+test_expect_success 'git am --skip and untracked dir vs deleted file' '
+ test_setup_sequencing am_skip_and_untracked &&
+ (
+ cd sequencing_am_skip_and_untracked &&
+ git checkout fooey &&
+ git format-patch -1 --stdout simple >changes.mbox &&
+ test_must_fail git am --3way changes.mbox &&
+
+ # Delete newfile
+ rm newfile &&
+
+ # Put an unrelated untracked directory there
+ mkdir newfile &&
+ echo foo >newfile/file1 &&
+ echo bar >newfile/file2 &&
+
+ # Change our mind about resolutions, just skip this patch
+ test_must_fail git am --skip 2>errors &&
+ test_path_is_dir newfile &&
+ grep "Updating .newfile. would lose untracked files in it" errors
+ )
+'
+
+test_done
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index d877872e8f..972ce026bb 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -297,6 +297,7 @@ test_expect_success 'abort with error when new base cannot be checked out' '
output &&
test_i18ngrep "file1" output &&
test_path_is_missing .git/rebase-merge &&
+ rm file1 &&
git reset --hard HEAD^
'
diff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh
index 7c381fbc89..ebbaed147a 100755
--- a/t/t3407-rebase-abort.sh
+++ b/t/t3407-rebase-abort.sh
@@ -7,77 +7,77 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
-### Test that we handle space characters properly
-work_dir="$(pwd)/test dir"
-
test_expect_success setup '
- mkdir -p "$work_dir" &&
- cd "$work_dir" &&
- git init &&
- echo a > a &&
- git add a &&
- git commit -m a &&
+ test_commit a a a &&
git branch to-rebase &&
- echo b > a &&
- git commit -a -m b &&
- echo c > a &&
- git commit -a -m c &&
+ test_commit --annotate b a b &&
+ test_commit --annotate c a c &&
git checkout to-rebase &&
- echo d > a &&
- git commit -a -m "merge should fail on this" &&
- echo e > a &&
- git commit -a -m "merge should fail on this, too" &&
- git branch pre-rebase
+ test_commit "merge should fail on this" a d d &&
+ test_commit --annotate "merge should fail on this, too" a e pre-rebase
'
+# Check that HEAD is equal to "pre-rebase" and the current branch is
+# "to-rebase"
+check_head() {
+ test_cmp_rev HEAD pre-rebase^{commit} &&
+ test "$(git symbolic-ref HEAD)" = refs/heads/to-rebase
+}
+
testrebase() {
type=$1
- dotest=$2
+ state_dir=$2
test_expect_success "rebase$type --abort" '
- cd "$work_dir" &&
# Clean up the state from the previous one
git reset --hard pre-rebase &&
test_must_fail git rebase$type main &&
- test_path_is_dir "$dotest" &&
+ test_path_is_dir "$state_dir" &&
git rebase --abort &&
- test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
- test ! -d "$dotest"
+ check_head &&
+ test_path_is_missing "$state_dir"
'
test_expect_success "rebase$type --abort after --skip" '
- cd "$work_dir" &&
# Clean up the state from the previous one
git reset --hard pre-rebase &&
test_must_fail git rebase$type main &&
- test_path_is_dir "$dotest" &&
+ test_path_is_dir "$state_dir" &&
test_must_fail git rebase --skip &&
- test $(git rev-parse HEAD) = $(git rev-parse main) &&
+ test_cmp_rev HEAD main &&
git rebase --abort &&
- test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
- test ! -d "$dotest"
+ check_head &&
+ test_path_is_missing "$state_dir"
'
test_expect_success "rebase$type --abort after --continue" '
- cd "$work_dir" &&
# Clean up the state from the previous one
git reset --hard pre-rebase &&
test_must_fail git rebase$type main &&
- test_path_is_dir "$dotest" &&
+ test_path_is_dir "$state_dir" &&
echo c > a &&
echo d >> a &&
git add a &&
test_must_fail git rebase --continue &&
- test $(git rev-parse HEAD) != $(git rev-parse main) &&
+ test_cmp_rev ! HEAD main &&
+ git rebase --abort &&
+ check_head &&
+ test_path_is_missing "$state_dir"
+ '
+
+ test_expect_success "rebase$type --abort when checking out a tag" '
+ test_when_finished "git symbolic-ref HEAD refs/heads/to-rebase" &&
+ git reset --hard a -- &&
+ test_must_fail git rebase$type --onto b c pre-rebase &&
+ test_cmp_rev HEAD b^{commit} &&
git rebase --abort &&
- test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
- test ! -d "$dotest"
+ test_cmp_rev HEAD pre-rebase^{commit} &&
+ ! git symbolic-ref HEAD
'
test_expect_success "rebase$type --abort does not update reflog" '
- cd "$work_dir" &&
# Clean up the state from the previous one
git reset --hard pre-rebase &&
git reflog show to-rebase > reflog_before &&
@@ -89,7 +89,6 @@ testrebase() {
'
test_expect_success 'rebase --abort can not be used with other options' '
- cd "$work_dir" &&
# Clean up the state from the previous one
git reset --hard pre-rebase &&
test_must_fail git rebase$type main &&
@@ -97,33 +96,21 @@ testrebase() {
test_must_fail git rebase --abort -v &&
git rebase --abort
'
+
+ test_expect_success "rebase$type --quit" '
+ test_when_finished "git symbolic-ref HEAD refs/heads/to-rebase" &&
+ # Clean up the state from the previous one
+ git reset --hard pre-rebase &&
+ test_must_fail git rebase$type main &&
+ test_path_is_dir $state_dir &&
+ head_before=$(git rev-parse HEAD) &&
+ git rebase --quit &&
+ test_cmp_rev HEAD $head_before &&
+ test_path_is_missing .git/rebase-apply
+ '
}
testrebase " --apply" .git/rebase-apply
testrebase " --merge" .git/rebase-merge
-test_expect_success 'rebase --apply --quit' '
- cd "$work_dir" &&
- # Clean up the state from the previous one
- git reset --hard pre-rebase &&
- test_must_fail git rebase --apply main &&
- test_path_is_dir .git/rebase-apply &&
- head_before=$(git rev-parse HEAD) &&
- git rebase --quit &&
- test $(git rev-parse HEAD) = $head_before &&
- test ! -d .git/rebase-apply
-'
-
-test_expect_success 'rebase --merge --quit' '
- cd "$work_dir" &&
- # Clean up the state from the previous one
- git reset --hard pre-rebase &&
- test_must_fail git rebase --merge main &&
- test_path_is_dir .git/rebase-merge &&
- head_before=$(git rev-parse HEAD) &&
- git rebase --quit &&
- test $(git rev-parse HEAD) = $head_before &&
- test ! -d .git/rebase-merge
-'
-
test_done
diff --git a/t/t3435-rebase-gpg-sign.sh b/t/t3435-rebase-gpg-sign.sh
index ec10766858..5f8ba2c739 100755
--- a/t/t3435-rebase-gpg-sign.sh
+++ b/t/t3435-rebase-gpg-sign.sh
@@ -65,6 +65,7 @@ test_rebase_gpg_sign ! true -i --gpg-sign --no-gpg-sign
test_rebase_gpg_sign false -i --no-gpg-sign --gpg-sign
test_expect_failure 'rebase -p --no-gpg-sign override commit.gpgsign' '
+ test_when_finished "git clean -f" &&
git reset --hard merged &&
git config commit.gpgsign true &&
git rebase -p --no-gpg-sign --onto=one fork-point main &&
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index 49010aa946..3b0fa66c33 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -238,6 +238,7 @@ test_expect_success 'allow skipping commit but not abort for a new history' '
'
test_expect_success 'allow skipping stopped cherry-pick because of untracked file modifications' '
+ test_when_finished "rm unrelated" &&
pristine_detach initial &&
git rm --cached unrelated &&
git commit -m "untrack unrelated" &&
diff --git a/t/t3602-rm-sparse-checkout.sh b/t/t3602-rm-sparse-checkout.sh
index e9e9a15c74..ecce497a9c 100755
--- a/t/t3602-rm-sparse-checkout.sh
+++ b/t/t3602-rm-sparse-checkout.sh
@@ -11,12 +11,15 @@ test_expect_success 'setup' "
git commit -m files &&
cat >sparse_error_header <<-EOF &&
- The following pathspecs didn't match any eligible path, but they do match index
- entries outside the current sparse checkout:
+ The following paths and/or pathspecs matched paths that exist
+ outside of your sparse-checkout definition, so will not be
+ updated in the index:
EOF
cat >sparse_hint <<-EOF &&
- hint: Disable or modify the sparsity rules if you intend to update such entries.
+ hint: If you intend to update such entries, try one of the following:
+ hint: * Use the --sparse option.
+ hint: * Disable or modify the sparsity rules.
hint: Disable this message with \"git config advice.updateSparsePath false\"
EOF
@@ -37,9 +40,25 @@ done
test_expect_success 'recursive rm does not remove sparse entries' '
git reset --hard &&
git sparse-checkout set sub/dir &&
- git rm -r sub &&
+ test_must_fail git rm -r sub &&
+ git rm --sparse -r sub &&
git status --porcelain -uno >actual &&
- echo "D sub/dir/e" >expected &&
+ cat >expected <<-\EOF &&
+ D sub/d
+ D sub/dir/e
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'recursive rm --sparse removes sparse entries' '
+ git reset --hard &&
+ git sparse-checkout set "sub/dir" &&
+ git rm --sparse -r sub &&
+ git status --porcelain -uno >actual &&
+ cat >expected <<-\EOF &&
+ D sub/d
+ D sub/dir/e
+ EOF
test_cmp expected actual
'
@@ -75,4 +94,15 @@ test_expect_success 'do not warn about sparse entries with --ignore-unmatch' '
git ls-files --error-unmatch b
'
+test_expect_success 'refuse to rm a non-skip-worktree path outside sparse cone' '
+ git reset --hard &&
+ git sparse-checkout set a &&
+ git update-index --no-skip-worktree b &&
+ test_must_fail git rm b 2>stderr &&
+ test_cmp b_error_and_hint stderr &&
+ git rm --sparse b 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing b
+'
+
test_done
diff --git a/t/t3705-add-sparse-checkout.sh b/t/t3705-add-sparse-checkout.sh
index 2b1fd0d0ee..5b904988d4 100755
--- a/t/t3705-add-sparse-checkout.sh
+++ b/t/t3705-add-sparse-checkout.sh
@@ -19,6 +19,7 @@ setup_sparse_entry () {
fi &&
git add sparse_entry &&
git update-index --skip-worktree sparse_entry &&
+ git commit --allow-empty -m "ensure sparse_entry exists at HEAD" &&
SPARSE_ENTRY_BLOB=$(git rev-parse :sparse_entry)
}
@@ -36,14 +37,22 @@ setup_gitignore () {
EOF
}
+test_sparse_entry_unstaged () {
+ git diff --staged -- sparse_entry >diff &&
+ test_must_be_empty diff
+}
+
test_expect_success 'setup' "
cat >sparse_error_header <<-EOF &&
- The following pathspecs didn't match any eligible path, but they do match index
- entries outside the current sparse checkout:
+ The following paths and/or pathspecs matched paths that exist
+ outside of your sparse-checkout definition, so will not be
+ updated in the index:
EOF
cat >sparse_hint <<-EOF &&
- hint: Disable or modify the sparsity rules if you intend to update such entries.
+ hint: If you intend to update such entries, try one of the following:
+ hint: * Use the --sparse option.
+ hint: * Disable or modify the sparsity rules.
hint: Disable this message with \"git config advice.updateSparsePath false\"
EOF
@@ -55,6 +64,7 @@ test_expect_success 'git add does not remove sparse entries' '
setup_sparse_entry &&
rm sparse_entry &&
test_must_fail git add sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged
'
@@ -73,6 +83,7 @@ test_expect_success 'git add . does not remove sparse entries' '
rm sparse_entry &&
setup_gitignore &&
test_must_fail git add . 2>stderr &&
+ test_sparse_entry_unstaged &&
cat sparse_error_header >expect &&
echo . >>expect &&
@@ -88,6 +99,7 @@ do
setup_sparse_entry &&
echo modified >sparse_entry &&
test_must_fail git add $opt sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged
'
@@ -98,6 +110,7 @@ test_expect_success 'git add --refresh does not update sparse entries' '
git ls-files --debug sparse_entry | grep mtime >before &&
test-tool chmtime -60 sparse_entry &&
test_must_fail git add --refresh sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
git ls-files --debug sparse_entry | grep mtime >after &&
test_cmp before after
@@ -106,6 +119,7 @@ test_expect_success 'git add --refresh does not update sparse entries' '
test_expect_success 'git add --chmod does not update sparse entries' '
setup_sparse_entry &&
test_must_fail git add --chmod=+x sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged &&
! test -x sparse_entry
@@ -116,6 +130,7 @@ test_expect_success 'git add --renormalize does not update sparse entries' '
setup_sparse_entry "LINEONE\r\nLINETWO\r\n" &&
echo "sparse_entry text=auto" >.gitattributes &&
test_must_fail git add --renormalize sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged
'
@@ -124,6 +139,7 @@ test_expect_success 'git add --dry-run --ignore-missing warn on sparse path' '
setup_sparse_entry &&
rm sparse_entry &&
test_must_fail git add --dry-run --ignore-missing sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged
'
@@ -145,11 +161,57 @@ test_expect_success 'do not warn when pathspec matches dense entries' '
git ls-files --error-unmatch dense_entry
'
+test_expect_success 'git add fails outside of sparse-checkout definition' '
+ test_when_finished git sparse-checkout disable &&
+ test_commit a &&
+ git sparse-checkout init &&
+ git sparse-checkout set a &&
+ echo >>sparse_entry &&
+
+ git update-index --no-skip-worktree sparse_entry &&
+ test_must_fail git add sparse_entry &&
+ test_sparse_entry_unstaged &&
+
+ test_must_fail git add --chmod=+x sparse_entry &&
+ test_sparse_entry_unstaged &&
+
+ test_must_fail git add --renormalize sparse_entry &&
+ test_sparse_entry_unstaged &&
+
+ # Avoid munging CRLFs to avoid an error message
+ git -c core.autocrlf=input add --sparse sparse_entry 2>stderr &&
+ test_must_be_empty stderr &&
+ test-tool read-cache --table >actual &&
+ grep "^100644 blob.*sparse_entry\$" actual &&
+
+ git add --sparse --chmod=+x sparse_entry 2>stderr &&
+ test_must_be_empty stderr &&
+ test-tool read-cache --table >actual &&
+ grep "^100755 blob.*sparse_entry\$" actual &&
+
+ git reset &&
+
+ # This will print a message over stderr on Windows.
+ git add --sparse --renormalize sparse_entry &&
+ git status --porcelain >actual &&
+ grep "^M sparse_entry\$" actual
+'
+
test_expect_success 'add obeys advice.updateSparsePath' '
setup_sparse_entry &&
test_must_fail git -c advice.updateSparsePath=false add sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp sparse_entry_error stderr
'
+test_expect_success 'add allows sparse entries with --sparse' '
+ git sparse-checkout set a &&
+ echo modified >sparse_entry &&
+ test_must_fail git add sparse_entry &&
+ test_sparse_entry_unchanged &&
+ git add --sparse sparse_entry 2>stderr &&
+ test_must_be_empty stderr
+'
+
test_done
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 873aa56e35..f0a82be9de 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -1307,4 +1307,62 @@ test_expect_success 'stash -c stash.useBuiltin=false warning ' '
test_must_be_empty err
'
+test_expect_success 'git stash succeeds despite directory/file change' '
+ test_create_repo directory_file_switch_v1 &&
+ (
+ cd directory_file_switch_v1 &&
+ test_commit init &&
+
+ test_write_lines this file has some words >filler &&
+ git add filler &&
+ git commit -m filler &&
+
+ git rm filler &&
+ mkdir filler &&
+ echo contents >filler/file &&
+ git stash push
+ )
+'
+
+test_expect_success 'git stash can pop file -> directory saved changes' '
+ test_create_repo directory_file_switch_v2 &&
+ (
+ cd directory_file_switch_v2 &&
+ test_commit init &&
+
+ test_write_lines this file has some words >filler &&
+ git add filler &&
+ git commit -m filler &&
+
+ git rm filler &&
+ mkdir filler &&
+ echo contents >filler/file &&
+ cp filler/file expect &&
+ git stash push --include-untracked &&
+ git stash apply --index &&
+ test_cmp expect filler/file
+ )
+'
+
+test_expect_success 'git stash can pop directory -> file saved changes' '
+ test_create_repo directory_file_switch_v3 &&
+ (
+ cd directory_file_switch_v3 &&
+ test_commit init &&
+
+ mkdir filler &&
+ test_write_lines some words >filler/file1 &&
+ test_write_lines and stuff >filler/file2 &&
+ git add filler &&
+ git commit -m filler &&
+
+ git rm -rf filler &&
+ echo contents >filler &&
+ cp filler expect &&
+ git stash push --include-untracked &&
+ git stash apply --index &&
+ test_cmp expect filler
+ )
+'
+
test_done
diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh
index 9d8d3c72e7..2374151662 100755
--- a/t/t4151-am-abort.sh
+++ b/t/t4151-am-abort.sh
@@ -23,7 +23,13 @@ test_expect_success setup '
test_tick &&
git commit -a -m $i || return 1
done &&
+ git branch changes &&
git format-patch --no-numbered initial &&
+ git checkout -b conflicting initial &&
+ echo different >>file-1 &&
+ echo whatever >new-file &&
+ git add file-1 new-file &&
+ git commit -m different &&
git checkout -b side initial &&
echo local change >file-2-expect
'
@@ -191,4 +197,37 @@ test_expect_success 'am --abort leaves index stat info alone' '
git diff-files --exit-code --quiet
'
+test_expect_success 'git am --abort return failed exit status when it fails' '
+ test_when_finished "rm -rf file-2/ && git reset --hard && git am --abort" &&
+ git checkout changes &&
+ git format-patch -1 --stdout conflicting >changes.mbox &&
+ test_must_fail git am --3way changes.mbox &&
+
+ git rm file-2 &&
+ mkdir file-2 &&
+ echo precious >file-2/somefile &&
+ test_must_fail git am --abort &&
+ test_path_is_dir file-2/
+'
+
+test_expect_success 'git am --abort cleans relevant files' '
+ git checkout changes &&
+ git format-patch -1 --stdout conflicting >changes.mbox &&
+ test_must_fail git am --3way changes.mbox &&
+
+ test_path_is_file new-file &&
+ echo further changes >>file-1 &&
+ echo change other file >>file-2 &&
+
+ # Abort, and expect the files touched by am to be reverted
+ git am --abort &&
+
+ test_path_is_missing new-file &&
+
+ # Files not involved in am operation are left modified
+ git diff --name-only changes >actual &&
+ test_write_lines file-2 >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 7cabb85ca6..8ae314af58 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -291,6 +291,7 @@ test_expect_success 'prune: handle HEAD reflog in multiple worktrees' '
cat ../expected >blob &&
git add blob &&
git commit -m "second commit in third" &&
+ git clean -f && # Remove untracked left behind by deleting index
git reset --hard HEAD^
) &&
git prune --expire=now &&
diff --git a/t/t5312-prune-corruption.sh b/t/t5312-prune-corruption.sh
index 11423b3cb2..ea889c088a 100755
--- a/t/t5312-prune-corruption.sh
+++ b/t/t5312-prune-corruption.sh
@@ -7,6 +7,9 @@ if we see, for example, a ref with a bogus name, it is OK either to
bail out or to proceed using it as a reachable tip, but it is _not_
OK to proceed as if it did not exist. Otherwise we might silently
delete objects that cannot be recovered.
+
+Note that we do assert command failure in these cases, because that is
+what currently happens. If that changes, these tests should be revisited.
'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
@@ -18,39 +21,58 @@ test_expect_success 'disable reflogs' '
git reflog expire --expire=all --all
'
+create_bogus_ref () {
+ test_when_finished 'rm -f .git/refs/heads/bogus..name' &&
+ echo $bogus >.git/refs/heads/bogus..name
+}
+
test_expect_success 'create history reachable only from a bogus-named ref' '
test_tick && git commit --allow-empty -m main &&
base=$(git rev-parse HEAD) &&
test_tick && git commit --allow-empty -m bogus &&
bogus=$(git rev-parse HEAD) &&
git cat-file commit $bogus >saved &&
- echo $bogus >.git/refs/heads/bogus..name &&
git reset --hard HEAD^
'
test_expect_success 'pruning does not drop bogus object' '
test_when_finished "git hash-object -w -t commit saved" &&
- test_might_fail git prune --expire=now &&
- verbose git cat-file -e $bogus
+ create_bogus_ref &&
+ test_must_fail git prune --expire=now &&
+ git cat-file -e $bogus
'
test_expect_success 'put bogus object into pack' '
git tag reachable $bogus &&
git repack -ad &&
git tag -d reachable &&
- verbose git cat-file -e $bogus
+ git cat-file -e $bogus
+'
+
+test_expect_success 'non-destructive repack bails on bogus ref' '
+ create_bogus_ref &&
+ test_must_fail git repack -adk
'
+test_expect_success 'GIT_REF_PARANOIA=0 overrides safety' '
+ create_bogus_ref &&
+ GIT_REF_PARANOIA=0 git repack -adk
+'
+
+
test_expect_success 'destructive repack keeps packed object' '
- test_might_fail git repack -Ad --unpack-unreachable=now &&
- verbose git cat-file -e $bogus &&
- test_might_fail git repack -ad &&
- verbose git cat-file -e $bogus
+ create_bogus_ref &&
+ test_must_fail git repack -Ad --unpack-unreachable=now &&
+ git cat-file -e $bogus &&
+ test_must_fail git repack -ad &&
+ git cat-file -e $bogus
'
-# subsequent tests will have different corruptions
-test_expect_success 'clean up bogus ref' '
- rm .git/refs/heads/bogus..name
+test_expect_success 'destructive repack not confused by dangling symref' '
+ test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ git repack -ad &&
+ test_must_fail git cat-file -e $bogus
'
# We create two new objects here, "one" and "two". Our
@@ -77,8 +99,8 @@ test_expect_success 'create history with missing tip commit' '
test_expect_success 'pruning with a corrupted tip does not drop history' '
test_when_finished "git hash-object -w -t commit saved" &&
- test_might_fail git prune --expire=now &&
- verbose git cat-file -e $recoverable
+ test_must_fail git prune --expire=now &&
+ git cat-file -e $recoverable
'
test_expect_success 'pack-refs does not silently delete broken loose ref' '
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index bb04f0f23b..bd17f308b3 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -174,12 +174,12 @@ test_expect_success 'write progress off for redirected stderr' '
'
test_expect_success 'write force progress on for stderr' '
- GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir --progress write 2>err &&
+ GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir write --progress 2>err &&
test_file_not_empty err
'
test_expect_success 'write with the --no-progress option' '
- GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir --no-progress write 2>err &&
+ GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir write --no-progress 2>err &&
test_line_count = 0 err
'
@@ -474,12 +474,12 @@ test_expect_success 'repack progress off for redirected stderr' '
'
test_expect_success 'repack force progress on for stderr' '
- GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir --progress repack 2>err &&
+ GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir repack --progress 2>err &&
test_file_not_empty err
'
test_expect_success 'repack with the --no-progress option' '
- GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir --no-progress repack 2>err &&
+ GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir repack --no-progress 2>err &&
test_line_count = 0 err
'
@@ -672,7 +672,7 @@ test_expect_success 'expire progress off for redirected stderr' '
test_expect_success 'expire force progress on for stderr' '
(
cd dup &&
- GIT_PROGRESS_DELAY=0 git multi-pack-index --progress expire 2>err &&
+ GIT_PROGRESS_DELAY=0 git multi-pack-index expire --progress 2>err &&
test_file_not_empty err
)
'
@@ -680,7 +680,7 @@ test_expect_success 'expire force progress on for stderr' '
test_expect_success 'expire with the --no-progress option' '
(
cd dup &&
- GIT_PROGRESS_DELAY=0 git multi-pack-index --no-progress expire 2>err &&
+ GIT_PROGRESS_DELAY=0 git multi-pack-index expire --no-progress 2>err &&
test_line_count = 0 err
)
'
diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh
index 4ad7c2c969..ec4aa89f63 100755
--- a/t/t5326-multi-pack-bitmaps.sh
+++ b/t/t5326-multi-pack-bitmaps.sh
@@ -283,4 +283,34 @@ test_expect_success 'pack.preferBitmapTips' '
)
'
+test_expect_success 'hash-cache values are propagated from pack bitmaps' '
+ rm -fr repo &&
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit base &&
+ test_commit base2 &&
+ git repack -adb &&
+
+ test-tool bitmap dump-hashes >pack.raw &&
+ test_file_not_empty pack.raw &&
+ sort pack.raw >pack.hashes &&
+
+ test_commit new &&
+ git repack &&
+ git multi-pack-index write --bitmap &&
+
+ test-tool bitmap dump-hashes >midx.raw &&
+ sort midx.raw >midx.hashes &&
+
+ # ensure that every namehash in the pack bitmap can be found in
+ # the midx bitmap (i.e., that there are no oid-namehash pairs
+ # unique to the pack bitmap).
+ comm -23 pack.hashes midx.hashes >dropped.hashes &&
+ test_must_be_empty dropped.hashes
+ )
+'
+
test_done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 4db8edd9c8..8212ca56dc 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -662,10 +662,10 @@ test_expect_success 'push does not update local refs on failure' '
test_expect_success 'allow deleting an invalid remote ref' '
- mk_test testrepo heads/main &&
+ mk_test testrepo heads/branch &&
rm -f testrepo/.git/objects/??/* &&
- git push testrepo :refs/heads/main &&
- (cd testrepo && test_must_fail git rev-parse --verify refs/heads/main)
+ git push testrepo :refs/heads/branch &&
+ (cd testrepo && test_must_fail git rev-parse --verify refs/heads/branch)
'
@@ -706,25 +706,26 @@ test_expect_success 'pushing valid refs triggers post-receive and post-update ho
'
test_expect_success 'deleting dangling ref triggers hooks with correct args' '
- mk_test_with_hooks testrepo heads/main &&
+ mk_test_with_hooks testrepo heads/branch &&
+ orig=$(git -C testrepo rev-parse refs/heads/branch) &&
rm -f testrepo/.git/objects/??/* &&
- git push testrepo :refs/heads/main &&
+ git push testrepo :refs/heads/branch &&
(
cd testrepo/.git &&
cat >pre-receive.expect <<-EOF &&
- $ZERO_OID $ZERO_OID refs/heads/main
+ $orig $ZERO_OID refs/heads/branch
EOF
cat >update.expect <<-EOF &&
- refs/heads/main $ZERO_OID $ZERO_OID
+ refs/heads/branch $orig $ZERO_OID
EOF
cat >post-receive.expect <<-EOF &&
- $ZERO_OID $ZERO_OID refs/heads/main
+ $orig $ZERO_OID refs/heads/branch
EOF
cat >post-update.expect <<-EOF &&
- refs/heads/main
+ refs/heads/branch
EOF
test_cmp pre-receive.expect pre-receive.actual &&
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 4f87d90c5b..f92c79c132 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -196,8 +196,8 @@ test_expect_success 'GIT_TRACE_CURL redacts auth details' '
# Ensure that there is no "Basic" followed by a base64 string, but that
# the auth details are redacted
- ! grep "Authorization: Basic [0-9a-zA-Z+/]" trace &&
- grep "Authorization: Basic <redacted>" trace
+ ! grep -i "Authorization: Basic [0-9a-zA-Z+/]" trace &&
+ grep -i "Authorization: Basic <redacted>" trace
'
test_expect_success 'GIT_CURL_VERBOSE redacts auth details' '
@@ -208,8 +208,8 @@ test_expect_success 'GIT_CURL_VERBOSE redacts auth details' '
# Ensure that there is no "Basic" followed by a base64 string, but that
# the auth details are redacted
- ! grep "Authorization: Basic [0-9a-zA-Z+/]" trace &&
- grep "Authorization: Basic <redacted>" trace
+ ! grep -i "Authorization: Basic [0-9a-zA-Z+/]" trace &&
+ grep -i "Authorization: Basic <redacted>" trace
'
test_expect_success 'GIT_TRACE_CURL does not redact auth details if GIT_TRACE_REDACT=0' '
@@ -219,7 +219,7 @@ test_expect_success 'GIT_TRACE_CURL does not redact auth details if GIT_TRACE_RE
git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth &&
expect_askpass both user@host &&
- grep "Authorization: Basic [0-9a-zA-Z+/]" trace
+ grep -i "Authorization: Basic [0-9a-zA-Z+/]" trace
'
test_expect_success 'disable dumb http on server' '
@@ -474,10 +474,10 @@ test_expect_success 'cookies are redacted by default' '
GIT_TRACE_CURL=true \
git -c "http.cookieFile=$(pwd)/cookies" clone \
$HTTPD_URL/smart/repo.git clone 2>err &&
- grep "Cookie:.*Foo=<redacted>" err &&
- grep "Cookie:.*Bar=<redacted>" err &&
- ! grep "Cookie:.*Foo=1" err &&
- ! grep "Cookie:.*Bar=2" err
+ grep -i "Cookie:.*Foo=<redacted>" err &&
+ grep -i "Cookie:.*Bar=<redacted>" err &&
+ ! grep -i "Cookie:.*Foo=1" err &&
+ ! grep -i "Cookie:.*Bar=2" err
'
test_expect_success 'empty values of cookies are also redacted' '
@@ -486,7 +486,7 @@ test_expect_success 'empty values of cookies are also redacted' '
GIT_TRACE_CURL=true \
git -c "http.cookieFile=$(pwd)/cookies" clone \
$HTTPD_URL/smart/repo.git clone 2>err &&
- grep "Cookie:.*Foo=<redacted>" err
+ grep -i "Cookie:.*Foo=<redacted>" err
'
test_expect_success 'GIT_TRACE_REDACT=0 disables cookie redaction' '
@@ -496,8 +496,8 @@ test_expect_success 'GIT_TRACE_REDACT=0 disables cookie redaction' '
GIT_TRACE_REDACT=0 GIT_TRACE_CURL=true \
git -c "http.cookieFile=$(pwd)/cookies" clone \
$HTTPD_URL/smart/repo.git clone 2>err &&
- grep "Cookie:.*Foo=1" err &&
- grep "Cookie:.*Bar=2" err
+ grep -i "Cookie:.*Foo=1" err &&
+ grep -i "Cookie:.*Bar=2" err
'
test_expect_success 'GIT_TRACE_CURL_NO_DATA prevents data from being traced' '
@@ -558,4 +558,13 @@ test_expect_success 'http auth forgets bogus credentials' '
expect_askpass both user@host
'
+test_expect_success 'client falls back from v2 to v0 to match server' '
+ GIT_TRACE_PACKET=$PWD/trace \
+ GIT_TEST_PROTOCOL_VERSION=2 \
+ git clone $HTTPD_URL/smart_v0/repo.git repo-v0 &&
+ # check for v0; there the HEAD symref is communicated in the capability
+ # line; v2 uses a different syntax on each ref advertisement line
+ grep symref=HEAD:refs/heads/ trace
+'
+
test_done
diff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh
index 5bf10261d3..34b3df4027 100755
--- a/t/t5600-clone-fail-cleanup.sh
+++ b/t/t5600-clone-fail-cleanup.sh
@@ -35,7 +35,9 @@ test_expect_success 'create a repo to clone' '
'
test_expect_success 'create objects in repo for later corruption' '
- test_commit -C foo file
+ test_commit -C foo file &&
+ git -C foo checkout --detach &&
+ test_commit -C foo detached
'
# source repository given to git clone should be relative to the
diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh
index 930721f053..aa1827d841 100755
--- a/t/t5701-git-serve.sh
+++ b/t/t5701-git-serve.sh
@@ -72,6 +72,37 @@ test_expect_success 'request invalid command' '
test_i18ngrep "invalid command" err
'
+test_expect_success 'request capability as command' '
+ test-tool pkt-line pack >in <<-EOF &&
+ command=agent
+ object-format=$(test_oid algo)
+ 0000
+ EOF
+ test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in &&
+ grep invalid.command.*agent err
+'
+
+test_expect_success 'request command as capability' '
+ test-tool pkt-line pack >in <<-EOF &&
+ command=ls-refs
+ object-format=$(test_oid algo)
+ fetch
+ 0000
+ EOF
+ test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in &&
+ grep unknown.capability err
+'
+
+test_expect_success 'requested command is command=value' '
+ test-tool pkt-line pack >in <<-EOF &&
+ command=ls-refs=whatever
+ object-format=$(test_oid algo)
+ 0000
+ EOF
+ test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in &&
+ grep invalid.command.*ls-refs=whatever err
+'
+
test_expect_success 'wrong object-format' '
test-tool pkt-line pack >in <<-EOF &&
command=fetch
@@ -116,6 +147,19 @@ test_expect_success 'basics of ls-refs' '
test_cmp expect actual
'
+test_expect_success 'ls-refs complains about unknown options' '
+ test-tool pkt-line pack >in <<-EOF &&
+ command=ls-refs
+ object-format=$(test_oid algo)
+ 0001
+ no-such-arg
+ 0000
+ EOF
+
+ test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in &&
+ grep unexpected.line.*no-such-arg err
+'
+
test_expect_success 'basic ref-prefixes' '
test-tool pkt-line pack >in <<-EOF &&
command=ls-refs
@@ -158,6 +202,37 @@ test_expect_success 'refs/heads prefix' '
test_cmp expect actual
'
+test_expect_success 'ignore very large set of prefixes' '
+ # generate a large number of ref-prefixes that we expect
+ # to match nothing; the value here exceeds TOO_MANY_PREFIXES
+ # from ls-refs.c.
+ {
+ echo command=ls-refs &&
+ echo object-format=$(test_oid algo) &&
+ echo 0001 &&
+ perl -le "print \"ref-prefix refs/heads/\$_\" for (1..65536)" &&
+ echo 0000
+ } |
+ test-tool pkt-line pack >in &&
+
+ # and then confirm that we see unmatched prefixes anyway (i.e.,
+ # that the prefix was not applied).
+ cat >expect <<-EOF &&
+ $(git rev-parse HEAD) HEAD
+ $(git rev-parse refs/heads/dev) refs/heads/dev
+ $(git rev-parse refs/heads/main) refs/heads/main
+ $(git rev-parse refs/heads/release) refs/heads/release
+ $(git rev-parse refs/tags/annotated-tag) refs/tags/annotated-tag
+ $(git rev-parse refs/tags/one) refs/tags/one
+ $(git rev-parse refs/tags/two) refs/tags/two
+ 0000
+ EOF
+
+ test-tool serve-v2 --stateless-rpc <in >out &&
+ test-tool pkt-line unpack <out >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'peel parameter' '
test-tool pkt-line pack >in <<-EOF &&
command=ls-refs
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index d3687b1a2e..d527cf6c49 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -237,6 +237,19 @@ test_expect_success '...but not if explicitly forbidden by config' '
! grep "refs/heads/mydefaultbranch" file_empty_child/.git/HEAD
'
+test_expect_success 'bare clone propagates empty default branch' '
+ test_when_finished "rm -rf file_empty_parent file_empty_child.git" &&
+
+ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \
+ git -c init.defaultBranch=mydefaultbranch init file_empty_parent &&
+
+ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \
+ git -c init.defaultBranch=main -c protocol.version=2 \
+ clone --bare \
+ "file://$(pwd)/file_empty_parent" file_empty_child.git &&
+ grep "refs/heads/mydefaultbranch" file_empty_child.git/HEAD
+'
+
test_expect_success 'fetch with file:// using protocol v2' '
test_when_finished "rm -f log" &&
diff --git a/t/t5704-protocol-violations.sh b/t/t5704-protocol-violations.sh
index 5c941949b9..bc393d7c31 100755
--- a/t/t5704-protocol-violations.sh
+++ b/t/t5704-protocol-violations.sh
@@ -32,4 +32,19 @@ test_expect_success 'extra delim packet in v2 fetch args' '
test_i18ngrep "expected flush after fetch arguments" err
'
+test_expect_success 'bogus symref in v0 capabilities' '
+ test_commit foo &&
+ oid=$(git rev-parse HEAD) &&
+ dst=refs/heads/foo &&
+ {
+ printf "%s HEAD\0symref object-format=%s symref=HEAD:%s\n" \
+ "$oid" "$GIT_DEFAULT_HASH" "$dst" |
+ test-tool pkt-line pack-raw-stdin &&
+ printf "0000"
+ } >input &&
+ git ls-remote --symref --upload-pack="cat input; read junk;:" . >actual &&
+ printf "ref: %s\tHEAD\n%s\tHEAD\n" "$dst" "$oid" >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index a1baf4e451..1be85d064e 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -962,4 +962,22 @@ test_expect_success 'bisect handles annotated tags' '
grep "$bad is the first bad commit" output
'
+test_expect_success 'bisect run fails with exit code equals or greater than 128' '
+ write_script test_script.sh <<-\EOF &&
+ exit 128
+ EOF
+ test_must_fail git bisect run ./test_script.sh &&
+ write_script test_script.sh <<-\EOF &&
+ exit 255
+ EOF
+ test_must_fail git bisect run ./test_script.sh
+'
+
+test_expect_success 'bisect visualize with a filename with dash and space' '
+ echo "My test line" >>"./-hello 2" &&
+ git add -- "./-hello 2" &&
+ git commit --quiet -m "Add test line" -- "./-hello 2" &&
+ git bisect visualize -p -- "-hello 2"
+'
+
test_done
diff --git a/t/t6415-merge-dir-to-symlink.sh b/t/t6415-merge-dir-to-symlink.sh
index 2ce104aca7..2655e295f5 100755
--- a/t/t6415-merge-dir-to-symlink.sh
+++ b/t/t6415-merge-dir-to-symlink.sh
@@ -25,7 +25,8 @@ test_expect_success 'checkout does not clobber untracked symlink' '
git reset --hard main &&
git rm --cached a/b &&
git commit -m "untracked symlink remains" &&
- test_must_fail git checkout start^0
+ test_must_fail git checkout start^0 &&
+ git clean -fd # Do not leave the untracked symlink in the way
'
test_expect_success 'a/b-2/c/d is kept when clobbering symlink b' '
@@ -34,7 +35,8 @@ test_expect_success 'a/b-2/c/d is kept when clobbering symlink b' '
git rm --cached a/b &&
git commit -m "untracked symlink remains" &&
git checkout -f start^0 &&
- test_path_is_file a/b-2/c/d
+ test_path_is_file a/b-2/c/d &&
+ git clean -fd # Do not leave the untracked symlink in the way
'
test_expect_success 'checkout should not have deleted a/b-2/c/d' '
diff --git a/t/t6424-merge-unrelated-index-changes.sh b/t/t6424-merge-unrelated-index-changes.sh
index 5e3779ebc9..89dd544f38 100755
--- a/t/t6424-merge-unrelated-index-changes.sh
+++ b/t/t6424-merge-unrelated-index-changes.sh
@@ -132,6 +132,7 @@ test_expect_success 'merge-recursive, when index==head but head!=HEAD' '
# Make index match B
git diff C B -- | git apply --cached &&
+ test_when_finished "git clean -fd" && # Do not leave untracked around
# Merge B & F, with B as "head"
git merge-recursive A -- B F > out &&
test_i18ngrep "Already up to date" out
diff --git a/t/t6430-merge-recursive.sh b/t/t6430-merge-recursive.sh
index ffcc01fe65..a0efe7cb6d 100755
--- a/t/t6430-merge-recursive.sh
+++ b/t/t6430-merge-recursive.sh
@@ -718,7 +718,9 @@ test_expect_success 'merge-recursive remembers the names of all base trees' '
# merge-recursive prints in reverse order, but we do not care
sort <trees >expect &&
sed -n "s/^virtual //p" out | sort >actual &&
- test_cmp expect actual
+ test_cmp expect actual &&
+
+ git clean -fd
'
test_expect_success 'merge-recursive internal merge resolves to the sameness' '
diff --git a/t/t6436-merge-overwrite.sh b/t/t6436-merge-overwrite.sh
index 84b4aacf49..c0b7bd7c3f 100755
--- a/t/t6436-merge-overwrite.sh
+++ b/t/t6436-merge-overwrite.sh
@@ -68,7 +68,8 @@ test_expect_success 'will not overwrite removed file' '
git commit -m "rm c1.c" &&
cp important c1.c &&
test_must_fail git merge c1a &&
- test_cmp important c1.c
+ test_cmp important c1.c &&
+ rm c1.c # Do not leave untracked file in way of future tests
'
test_expect_success 'will not overwrite re-added file' '
diff --git a/t/t7002-mv-sparse-checkout.sh b/t/t7002-mv-sparse-checkout.sh
new file mode 100755
index 0000000000..545748949a
--- /dev/null
+++ b/t/t7002-mv-sparse-checkout.sh
@@ -0,0 +1,189 @@
+#!/bin/sh
+
+test_description='git mv in sparse working trees'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' "
+ mkdir -p sub/dir sub/dir2 &&
+ touch a b c sub/d sub/dir/e sub/dir2/e &&
+ git add -A &&
+ git commit -m files &&
+
+ cat >sparse_error_header <<-EOF &&
+ The following paths and/or pathspecs matched paths that exist
+ outside of your sparse-checkout definition, so will not be
+ updated in the index:
+ EOF
+
+ cat >sparse_hint <<-EOF
+ hint: If you intend to update such entries, try one of the following:
+ hint: * Use the --sparse option.
+ hint: * Disable or modify the sparsity rules.
+ hint: Disable this message with \"git config advice.updateSparsePath false\"
+ EOF
+"
+
+test_expect_success 'mv refuses to move sparse-to-sparse' '
+ test_when_finished rm -f e &&
+ git reset --hard &&
+ git sparse-checkout set a &&
+ touch b &&
+ test_must_fail git mv b e 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo b >>expect &&
+ echo e >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse b e 2>stderr &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'mv refuses to move sparse-to-sparse, ignores failure' '
+ test_when_finished rm -f b c e &&
+ git reset --hard &&
+ git sparse-checkout set a &&
+
+ # tracked-to-untracked
+ touch b &&
+ git mv -k b e 2>stderr &&
+ test_path_exists b &&
+ test_path_is_missing e &&
+ cat sparse_error_header >expect &&
+ echo b >>expect &&
+ echo e >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse b e 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing b &&
+ test_path_exists e &&
+
+ # tracked-to-tracked
+ git reset --hard &&
+ touch b &&
+ git mv -k b c 2>stderr &&
+ test_path_exists b &&
+ test_path_is_missing c &&
+ cat sparse_error_header >expect &&
+ echo b >>expect &&
+ echo c >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse b c 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing b &&
+ test_path_exists c
+'
+
+test_expect_success 'mv refuses to move non-sparse-to-sparse' '
+ test_when_finished rm -f b c e &&
+ git reset --hard &&
+ git sparse-checkout set a &&
+
+ # tracked-to-untracked
+ test_must_fail git mv a e 2>stderr &&
+ test_path_exists a &&
+ test_path_is_missing e &&
+ cat sparse_error_header >expect &&
+ echo e >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse a e 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing a &&
+ test_path_exists e &&
+
+ # tracked-to-tracked
+ rm e &&
+ git reset --hard &&
+ test_must_fail git mv a c 2>stderr &&
+ test_path_exists a &&
+ test_path_is_missing c &&
+ cat sparse_error_header >expect &&
+ echo c >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse a c 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing a &&
+ test_path_exists c
+'
+
+test_expect_success 'mv refuses to move sparse-to-non-sparse' '
+ test_when_finished rm -f b c e &&
+ git reset --hard &&
+ git sparse-checkout set a e &&
+
+ # tracked-to-untracked
+ touch b &&
+ test_must_fail git mv b e 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo b >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse b e 2>stderr &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'recursive mv refuses to move (possible) sparse' '
+ test_when_finished rm -rf b c e sub2 &&
+ git reset --hard &&
+ # Without cone mode, "sub" and "sub2" do not match
+ git sparse-checkout set sub/dir sub2/dir &&
+
+ # Add contained contents to ensure we avoid non-existence errors
+ mkdir sub/dir2 &&
+ touch sub/d sub/dir2/e &&
+
+ test_must_fail git mv sub sub2 2>stderr &&
+ cat sparse_error_header >expect &&
+ cat >>expect <<-\EOF &&
+ sub/d
+ sub2/d
+ sub/dir/e
+ sub2/dir/e
+ sub/dir2/e
+ sub2/dir2/e
+ EOF
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse sub sub2 2>stderr &&
+ test_must_be_empty stderr &&
+ git commit -m "moved sub to sub2" &&
+ git rev-parse HEAD~1:sub >expect &&
+ git rev-parse HEAD:sub2 >actual &&
+ test_cmp expect actual &&
+ git reset --hard HEAD~1
+'
+
+test_expect_success 'recursive mv refuses to move sparse' '
+ git reset --hard &&
+ # Use cone mode so "sub/" matches the sparse-checkout patterns
+ git sparse-checkout init --cone &&
+ git sparse-checkout set sub/dir sub2/dir &&
+
+ # Add contained contents to ensure we avoid non-existence errors
+ mkdir sub/dir2 &&
+ touch sub/dir2/e &&
+
+ test_must_fail git mv sub sub2 2>stderr &&
+ cat sparse_error_header >expect &&
+ cat >>expect <<-\EOF &&
+ sub/dir2/e
+ sub2/dir2/e
+ EOF
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse sub sub2 2>stderr &&
+ test_must_be_empty stderr &&
+ git commit -m "moved sub to sub2" &&
+ git rev-parse HEAD~1:sub >expect &&
+ git rev-parse HEAD:sub2 >actual &&
+ test_cmp expect actual &&
+ git reset --hard HEAD~1
+'
+
+test_done
diff --git a/t/t7112-reset-submodule.sh b/t/t7112-reset-submodule.sh
index 19830d9036..a3e2413bc3 100755
--- a/t/t7112-reset-submodule.sh
+++ b/t/t7112-reset-submodule.sh
@@ -6,7 +6,6 @@ test_description='reset can handle submodules'
. "$TEST_DIRECTORY"/lib-submodule-update.sh
KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
-KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1
test_submodule_switch_recursing_with_args "reset --keep"
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 7f6e23a4bb..b7ba1c3268 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -585,6 +585,7 @@ test_expect_success 'checkout --conflict=diff3' '
'
test_expect_success 'failing checkout -b should not break working tree' '
+ git clean -fd && # Remove untracked files in the way
git reset --hard main &&
git symbolic-ref HEAD refs/heads/main &&
test_must_fail git checkout -b renamer side^ &&
diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index f1463197b9..f488d930df 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -399,41 +399,45 @@ check_sparse_index_behavior () {
}
test_expect_success 'status succeeds with sparse index' '
- git clone . full &&
- git clone --sparse . sparse &&
- git -C sparse sparse-checkout init --cone --sparse-index &&
- git -C sparse sparse-checkout set dir1 dir2 &&
+ (
+ sane_unset GIT_TEST_SPLIT_INDEX &&
- write_script .git/hooks/fsmonitor-test <<-\EOF &&
- printf "last_update_token\0"
- EOF
- git -C full config core.fsmonitor ../.git/hooks/fsmonitor-test &&
- git -C sparse config core.fsmonitor ../.git/hooks/fsmonitor-test &&
- check_sparse_index_behavior ! &&
+ git clone . full &&
+ git clone --sparse . sparse &&
+ git -C sparse sparse-checkout init --cone --sparse-index &&
+ git -C sparse sparse-checkout set dir1 dir2 &&
- write_script .git/hooks/fsmonitor-test <<-\EOF &&
- printf "last_update_token\0"
- printf "dir1/modified\0"
- EOF
- check_sparse_index_behavior ! &&
-
- git -C sparse sparse-checkout add dir1a &&
+ write_script .git/hooks/fsmonitor-test <<-\EOF &&
+ printf "last_update_token\0"
+ EOF
+ git -C full config core.fsmonitor ../.git/hooks/fsmonitor-test &&
+ git -C sparse config core.fsmonitor ../.git/hooks/fsmonitor-test &&
+ check_sparse_index_behavior ! &&
- for repo in full sparse
- do
- cp -r $repo/dir1 $repo/dir1a &&
- git -C $repo add dir1a &&
- git -C $repo commit -m "add dir1a" || return 1
- done &&
- git -C sparse sparse-checkout set dir1 dir2 &&
-
- # This one modifies outside the sparse-checkout definition
- # and hence we expect to expand the sparse-index.
- write_script .git/hooks/fsmonitor-test <<-\EOF &&
- printf "last_update_token\0"
- printf "dir1a/modified\0"
- EOF
- check_sparse_index_behavior
+ write_script .git/hooks/fsmonitor-test <<-\EOF &&
+ printf "last_update_token\0"
+ printf "dir1/modified\0"
+ EOF
+ check_sparse_index_behavior ! &&
+
+ git -C sparse sparse-checkout add dir1a &&
+
+ for repo in full sparse
+ do
+ cp -r $repo/dir1 $repo/dir1a &&
+ git -C $repo add dir1a &&
+ git -C $repo commit -m "add dir1a" || return 1
+ done &&
+ git -C sparse sparse-checkout set dir1 dir2 &&
+
+ # This one modifies outside the sparse-checkout definition
+ # and hence we expect to expand the sparse-index.
+ write_script .git/hooks/fsmonitor-test <<-\EOF &&
+ printf "last_update_token\0"
+ printf "dir1a/modified\0"
+ EOF
+ check_sparse_index_behavior
+ )
'
test_done
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 2ef39d3088..c773e30b3f 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -717,6 +717,7 @@ test_expect_success 'failed fast-forward merge with --autostash' '
git reset --hard c0 &&
git merge-file file file.orig file.5 &&
cp file.5 other &&
+ test_when_finished "rm other" &&
test_must_fail git merge --autostash c1 2>err &&
test_i18ngrep "Applied autostash." err &&
test_cmp file.5 file
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index a173f564bc..096456292c 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -453,6 +453,13 @@ run_dir_diff_test 'difftool --dir-diff' '
grep "^file$" output
'
+run_dir_diff_test 'difftool --dir-diff avoids repeated slashes in TMPDIR' '
+ TMPDIR="${TMPDIR:-/tmp}////" \
+ git difftool --dir-diff $symlinks --extcmd echo branch >output &&
+ grep -v // output >actual &&
+ test_line_count = 1 actual
+'
+
run_dir_diff_test 'difftool --dir-diff ignores --prompt' '
git difftool --dir-diff $symlinks --prompt --extcmd ls branch >output &&
grep "^sub$" output &&
@@ -674,7 +681,6 @@ test_expect_success SYMLINKS 'difftool --dir-diff handles modified symlinks' '
rm c &&
ln -s d c &&
cat >expect <<-EOF &&
- b
c
c
@@ -710,7 +716,6 @@ test_expect_success SYMLINKS 'difftool --dir-diff handles modified symlinks' '
# Deleted symlinks
rm -f c &&
cat >expect <<-EOF &&
- b
c
EOF
@@ -723,6 +728,71 @@ test_expect_success SYMLINKS 'difftool --dir-diff handles modified symlinks' '
test_cmp expect actual
'
+test_expect_success SYMLINKS 'difftool --dir-diff writes symlinks as raw text' '
+ # Start out on a branch called "branch-init".
+ git init -b branch-init symlink-files &&
+ (
+ cd symlink-files &&
+ # This test ensures that symlinks are written as raw text.
+ # The "cat" tools output link and file contents.
+ git config difftool.cat-left-link.cmd "cat \"\$LOCAL/link\"" &&
+ git config difftool.cat-left-a.cmd "cat \"\$LOCAL/file-a\"" &&
+ git config difftool.cat-right-link.cmd "cat \"\$REMOTE/link\"" &&
+ git config difftool.cat-right-b.cmd "cat \"\$REMOTE/file-b\"" &&
+
+ # Record the empty initial state so that we can come back here
+ # later and not have to consider the any cases where difftool
+ # will create symlinks back into the worktree.
+ test_tick &&
+ git commit --allow-empty -m init &&
+
+ # Create a file called "file-a" with a symlink pointing to it.
+ git switch -c branch-a &&
+ echo a >file-a &&
+ ln -s file-a link &&
+ git add file-a link &&
+ test_tick &&
+ git commit -m link-to-file-a &&
+
+ # Create a file called "file-b" and point the symlink to it.
+ git switch -c branch-b &&
+ echo b >file-b &&
+ rm link &&
+ ln -s file-b link &&
+ git add file-b link &&
+ git rm file-a &&
+ test_tick &&
+ git commit -m link-to-file-b &&
+
+ # Checkout the initial branch so that the --symlinks behavior is
+ # not activated. The two directories should be completely
+ # independent with no symlinks pointing back here.
+ git switch branch-init &&
+
+ # The left link must be "file-a" and "file-a" must contain "a".
+ echo file-a >expect &&
+ git difftool --symlinks --dir-diff --tool cat-left-link \
+ branch-a branch-b >actual &&
+ test_cmp expect actual &&
+
+ echo a >expect &&
+ git difftool --symlinks --dir-diff --tool cat-left-a \
+ branch-a branch-b >actual &&
+ test_cmp expect actual &&
+
+ # The right link must be "file-b" and "file-b" must contain "b".
+ echo file-b >expect &&
+ git difftool --symlinks --dir-diff --tool cat-right-link \
+ branch-a branch-b >actual &&
+ test_cmp expect actual &&
+
+ echo b >expect &&
+ git difftool --symlinks --dir-diff --tool cat-right-b \
+ branch-a branch-b >actual &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'add -N and difftool -d' '
test_when_finished git reset --hard &&
diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh
index 3172f5b936..058e5d0c96 100755
--- a/t/t7814-grep-recurse-submodules.sh
+++ b/t/t7814-grep-recurse-submodules.sh
@@ -441,4 +441,107 @@ test_expect_success 'grep --recurse-submodules with --cached ignores worktree mo
test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
test_must_be_empty actual
'
+
+test_expect_failure 'grep --textconv: superproject .gitattributes does not affect submodules' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ echo "a diff=d2x" >.gitattributes &&
+
+ cat >expect <<-\EOF &&
+ a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep --textconv: superproject .gitattributes (from index) does not affect submodules' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ echo "a diff=d2x" >.gitattributes &&
+ git add .gitattributes &&
+ rm .gitattributes &&
+
+ cat >expect <<-\EOF &&
+ a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep --textconv: superproject .git/info/attributes does not affect submodules' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ super_attr="$(git rev-parse --git-path info/attributes)" &&
+ test_when_finished "rm -f \"$super_attr\"" &&
+ echo "a diff=d2x" >"$super_attr" &&
+
+ cat >expect <<-\EOF &&
+ a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+# Note: what currently prevents this test from passing is not that the
+# .gitattributes file from "./submodule" is being ignored, but that it is being
+# propagated to the nested "./submodule/sub" files.
+#
+test_expect_failure 'grep --textconv correctly reads submodule .gitattributes' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ echo "a diff=d2x" >submodule/.gitattributes &&
+
+ cat >expect <<-\EOF &&
+ submodule/a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep --textconv correctly reads submodule .gitattributes (from index)' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ echo "a diff=d2x" >submodule/.gitattributes &&
+ git -C submodule add .gitattributes &&
+ rm submodule/.gitattributes &&
+
+ cat >expect <<-\EOF &&
+ submodule/a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep --textconv correctly reads submodule .git/info/attributes' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+
+ submodule_attr="$(git -C submodule rev-parse --path-format=absolute --git-path info/attributes)" &&
+ test_when_finished "rm -f \"$submodule_attr\"" &&
+ echo "a diff=d2x" >"$submodule_attr" &&
+
+ cat >expect <<-\EOF &&
+ submodule/a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep saves textconv cache in the appropriate repository' '
+ reset_and_clean &&
+ test_config_global diff.d2x_cached.textconv "sed -e \"s/d/x/\"" &&
+ test_config_global diff.d2x_cached.cachetextconv true &&
+ echo "a diff=d2x_cached" >submodule/.gitattributes &&
+
+ # We only read/write to the textconv cache when grepping from an OID,
+ # as the working tree file might have modifications.
+ git grep --textconv --cached --recurse-submodules x &&
+
+ super_textconv_cache="$(git rev-parse --git-path refs/notes/textconv/d2x_cached)" &&
+ sub_textconv_cache="$(git -C submodule rev-parse \
+ --path-format=absolute --git-path refs/notes/textconv/d2x_cached)" &&
+ test_path_is_missing "$super_textconv_cache" &&
+ test_path_is_file "$sub_textconv_cache"
+'
+
test_done
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 36a4218745..9b9f11a8e7 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -21,8 +21,7 @@ test_xmllint () {
}
test_lazy_prereq SYSTEMD_ANALYZE '
- systemd-analyze --help >out &&
- grep verify out
+ systemd-analyze verify /lib/systemd/system/basic.target
'
test_systemd_analyze_verify () {
@@ -277,7 +276,7 @@ test_expect_success 'incremental-repack task' '
# Delete refs that have not been repacked in these packs.
git for-each-ref --format="delete %(refname)" \
- refs/prefetch refs/tags >refs &&
+ refs/prefetch refs/tags refs/remotes >refs &&
git update-ref --stdin <refs &&
# Replace the object directory with this pack layout.
@@ -286,6 +285,10 @@ test_expect_success 'incremental-repack task' '
ls $packDir/*.pack >packs-before &&
test_line_count = 3 packs-before &&
+ # make sure we do not have any broken refs that were
+ # missed in the deletion above
+ git for-each-ref &&
+
# the job repacks the two into a new pack, but does not
# delete the old ones.
git maintenance run --task=incremental-repack &&
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index 2d29d486ee..17f988edd2 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -36,6 +36,13 @@ CVSWORK="$PWD/cvswork"
CVS_SERVER=git-cvsserver
export CVSROOT CVS_SERVER
+if perl -e 'exit(1) if not defined crypt("", "cv")'
+then
+ PWDHASH='lac2ItudM3.KM'
+else
+ PWDHASH='$2b$10$t8fGvE/a9eLmfOLzsZme2uOa2QtoMYwIxq9wZA6aBKtF1Yb7FJIzi'
+fi
+
rm -rf "$CVSWORK" "$SERVERDIR"
test_expect_success 'setup' '
git config push.default matching &&
@@ -54,7 +61,7 @@ test_expect_success 'setup' '
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" &&
GIT_DIR="$SERVERDIR" git config gitcvs.authdb "$SERVERDIR/auth.db" &&
- echo cvsuser:cvGVEarMLnhlA > "$SERVERDIR/auth.db"
+ echo "cvsuser:$PWDHASH" >"$SERVERDIR/auth.db"
'
# note that cvs doesn't accept absolute pathnames
diff --git a/t/test-lib.sh b/t/test-lib.sh
index d5ee964254..8361b5c1c5 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -534,7 +534,7 @@ SQ=\'
# when case-folding filenames
u200c=$(printf '\342\200\214')
-export _x05 _x35 _x40 _z40 LF u200c EMPTY_TREE EMPTY_BLOB ZERO_OID OID_REGEX
+export _x05 _x35 LF u200c EMPTY_TREE EMPTY_BLOB ZERO_OID OID_REGEX
# Each test should start with something like this, after copyright notices:
#
@@ -1381,6 +1381,26 @@ then
test_done
fi
+# skip non-whitelisted tests when compiled with SANITIZE=leak
+if test -n "$SANITIZE_LEAK"
+then
+ if test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
+ then
+ # We need to see it in "git env--helper" (via
+ # test_bool_env)
+ export TEST_PASSES_SANITIZE_LEAK
+
+ if ! test_bool_env TEST_PASSES_SANITIZE_LEAK false
+ then
+ skip_all="skipping $this_test under GIT_TEST_PASSING_SANITIZE_LEAK=true"
+ test_done
+ fi
+ fi
+elif test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
+then
+ error "GIT_TEST_PASSING_SANITIZE_LEAK=true has no effect except when compiled with SANITIZE=leak"
+fi
+
# Last-minute variable setup
USER_HOME="$HOME"
HOME="$TRASH_DIRECTORY"
@@ -1425,10 +1445,9 @@ then
fi
# Convenience
-# A regexp to match 5, 35 and 40 hexdigits
+# A regexp to match 5 and 35 hexdigits
_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x35="$_x05$_x05$_x05$_x05$_x05$_x05$_x05"
-_x40="$_x35$_x05"
test_oid_init
@@ -1437,7 +1456,6 @@ OID_REGEX=$(echo $ZERO_OID | sed -e 's/0/[0-9a-f]/g')
OIDPATH_REGEX=$(test_oid_to_path $ZERO_OID | sed -e 's/0/[0-9a-f]/g')
EMPTY_TREE=$(test_oid empty_tree)
EMPTY_BLOB=$(test_oid empty_blob)
-_z40=$ZERO_OID
# Provide an implementation of the 'yes' utility; the upper bound
# limit is there to help Windows that cannot stop this loop from
@@ -1536,6 +1554,7 @@ test -z "$NO_PYTHON" && test_set_prereq PYTHON
test -n "$USE_LIBPCRE2" && test_set_prereq PCRE
test -n "$USE_LIBPCRE2" && test_set_prereq LIBPCRE2
test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
+test -n "$SANITIZE_LEAK" && test_set_prereq SANITIZE_LEAK
if test -z "$GIT_TEST_CHECK_CACHE_TREE"
then