* [PATCH v9 3/3] ci: run unit tests in CI
From: Josh Steadmon @ 2023-11-01 23:31 UTC (permalink / raw)
To: git
Cc: gitster, phillip.wood123, rsbecker, oswald.buddenhagen,
christian.couder
In-Reply-To: <cover.1698881249.git.steadmon@google.com>
Run unit tests in both Cirrus and GitHub CI. For sharded CI instances
(currently just Windows on GitHub), run only on the first shard. This is
OK while we have only a single unit test executable, but we may wish to
distribute tests more evenly when we add new unit tests in the future.
We may also want to add more status output in our unit test framework,
so that we can do similar post-processing as in
ci/lib.sh:handle_failed_tests().
Signed-off-by: Josh Steadmon <steadmon@google.com>
---
.cirrus.yml | 2 +-
ci/run-build-and-tests.sh | 2 ++
ci/run-test-slice.sh | 5 +++++
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index 4860bebd32..b6280692d2 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -19,4 +19,4 @@ freebsd_12_task:
build_script:
- su git -c gmake
test_script:
- - su git -c 'gmake test'
+ - su git -c 'gmake DEFAULT_UNIT_TEST_TARGET=unit-tests-prove test unit-tests'
diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh
index 2528f25e31..7a1466b868 100755
--- a/ci/run-build-and-tests.sh
+++ b/ci/run-build-and-tests.sh
@@ -50,6 +50,8 @@ if test -n "$run_tests"
then
group "Run tests" make test ||
handle_failed_tests
+ group "Run unit tests" \
+ make DEFAULT_UNIT_TEST_TARGET=unit-tests-prove unit-tests
fi
check_unignored_build_artifacts
diff --git a/ci/run-test-slice.sh b/ci/run-test-slice.sh
index a3c67956a8..ae8094382f 100755
--- a/ci/run-test-slice.sh
+++ b/ci/run-test-slice.sh
@@ -15,4 +15,9 @@ group "Run tests" make --quiet -C t T="$(cd t &&
tr '\n' ' ')" ||
handle_failed_tests
+# We only have one unit test at the moment, so run it in the first slice
+if [ "$1" == "0" ] ; then
+ group "Run unit tests" make --quiet -C t unit-tests-prove
+fi
+
check_unignored_build_artifacts
--
2.42.0.869.gea05f2083d-goog
^ permalink raw reply related
* [PATCH v9 2/3] unit tests: add TAP unit test framework
From: Josh Steadmon @ 2023-11-01 23:31 UTC (permalink / raw)
To: git
Cc: gitster, phillip.wood123, rsbecker, oswald.buddenhagen,
christian.couder
In-Reply-To: <cover.1698881249.git.steadmon@google.com>
From: Phillip Wood <phillip.wood@dunelm.org.uk>
This patch contains an implementation for writing unit tests with TAP
output. Each test is a function that contains one or more checks. The
test is run with the TEST() macro and if any of the checks fail then the
test will fail. A complete program that tests STRBUF_INIT would look
like
#include "test-lib.h"
#include "strbuf.h"
static void t_static_init(void)
{
struct strbuf buf = STRBUF_INIT;
check_uint(buf.len, ==, 0);
check_uint(buf.alloc, ==, 0);
check_char(buf.buf[0], ==, '\0');
}
int main(void)
{
TEST(t_static_init(), "static initialization works);
return test_done();
}
The output of this program would be
ok 1 - static initialization works
1..1
If any of the checks in a test fail then they print a diagnostic message
to aid debugging and the test will be reported as failing. For example a
failing integer check would look like
# check "x >= 3" failed at my-test.c:102
# left: 2
# right: 3
not ok 1 - x is greater than or equal to three
There are a number of check functions implemented so far. check() checks
a boolean condition, check_int(), check_uint() and check_char() take two
values to compare and a comparison operator. check_str() will check if
two strings are equal. Custom checks are simple to implement as shown in
the comments above test_assert() in test-lib.h.
Tests can be skipped with test_skip() which can be supplied with a
reason for skipping which it will print. Tests can print diagnostic
messages with test_msg(). Checks that are known to fail can be wrapped
in TEST_TODO().
There are a couple of example test programs included in this
patch. t-basic.c implements some self-tests and demonstrates the
diagnostic output for failing test. The output of this program is
checked by t0080-unit-test-output.sh. t-strbuf.c shows some example
unit tests for strbuf.c
The unit tests will be built as part of the default "make all" target,
to avoid bitrot. If you wish to build just the unit tests, you can run
"make build-unit-tests". To run the tests, you can use "make unit-tests"
or run the test binaries directly, as in "./t/unit-tests/bin/t-strbuf".
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Josh Steadmon <steadmon@google.com>
---
Makefile | 28 ++-
t/Makefile | 15 +-
t/t0080-unit-test-output.sh | 58 +++++++
t/unit-tests/.gitignore | 1 +
t/unit-tests/t-basic.c | 95 +++++++++++
t/unit-tests/t-strbuf.c | 120 +++++++++++++
t/unit-tests/test-lib.c | 329 ++++++++++++++++++++++++++++++++++++
t/unit-tests/test-lib.h | 149 ++++++++++++++++
8 files changed, 791 insertions(+), 4 deletions(-)
create mode 100755 t/t0080-unit-test-output.sh
create mode 100644 t/unit-tests/.gitignore
create mode 100644 t/unit-tests/t-basic.c
create mode 100644 t/unit-tests/t-strbuf.c
create mode 100644 t/unit-tests/test-lib.c
create mode 100644 t/unit-tests/test-lib.h
diff --git a/Makefile b/Makefile
index e440728c24..18c13f06c0 100644
--- a/Makefile
+++ b/Makefile
@@ -682,6 +682,9 @@ TEST_BUILTINS_OBJS =
TEST_OBJS =
TEST_PROGRAMS_NEED_X =
THIRD_PARTY_SOURCES =
+UNIT_TEST_PROGRAMS =
+UNIT_TEST_DIR = t/unit-tests
+UNIT_TEST_BIN = $(UNIT_TEST_DIR)/bin
# Having this variable in your environment would break pipelines because
# you cause "cd" to echo its destination to stdout. It can also take
@@ -1331,6 +1334,12 @@ THIRD_PARTY_SOURCES += compat/regex/%
THIRD_PARTY_SOURCES += sha1collisiondetection/%
THIRD_PARTY_SOURCES += sha1dc/%
+UNIT_TEST_PROGRAMS += t-basic
+UNIT_TEST_PROGRAMS += t-strbuf
+UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))
+UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
+UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o
+
# xdiff and reftable libs may in turn depend on what is in libgit.a
GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)
EXTLIBS =
@@ -2672,6 +2681,7 @@ OBJECTS += $(TEST_OBJS)
OBJECTS += $(XDIFF_OBJS)
OBJECTS += $(FUZZ_OBJS)
OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS)
+OBJECTS += $(UNIT_TEST_OBJS)
ifndef NO_CURL
OBJECTS += http.o http-walker.o remote-curl.o
@@ -3167,7 +3177,7 @@ endif
test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
-all:: $(TEST_PROGRAMS) $(test_bindir_programs)
+all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS)
bin-wrappers/%: wrap-for-bin.sh
$(call mkdir_p_parent_template)
@@ -3592,7 +3602,7 @@ endif
artifacts-tar:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) \
GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \
- $(MOFILES)
+ $(UNIT_TEST_PROGS) $(MOFILES)
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) \
SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)'
test -n "$(ARTIFACTS_DIRECTORY)"
@@ -3653,7 +3663,7 @@ clean: profile-clean coverage-clean cocciclean
$(RM) $(OBJECTS)
$(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB)
$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS)
- $(RM) $(TEST_PROGRAMS)
+ $(RM) $(TEST_PROGRAMS) $(UNIT_TEST_PROGS)
$(RM) $(FUZZ_PROGRAMS)
$(RM) $(SP_OBJ)
$(RM) $(HCC)
@@ -3831,3 +3841,15 @@ $(FUZZ_PROGRAMS): all
$(XDIFF_OBJS) $(EXTLIBS) git.o $@.o $(LIB_FUZZING_ENGINE) -o $@
fuzz-all: $(FUZZ_PROGRAMS)
+
+$(UNIT_TEST_BIN):
+ @mkdir -p $(UNIT_TEST_BIN)
+
+$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_DIR)/test-lib.o $(GITLIBS) GIT-LDFLAGS $(UNIT_TEST_BIN)
+ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
+ $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
+
+.PHONY: build-unit-tests unit-tests
+build-unit-tests: $(UNIT_TEST_PROGS)
+unit-tests: $(UNIT_TEST_PROGS)
+ $(MAKE) -C t/ unit-tests
diff --git a/t/Makefile b/t/Makefile
index 3e00cdd801..75d9330437 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -17,6 +17,7 @@ TAR ?= $(TAR)
RM ?= rm -f
PROVE ?= prove
DEFAULT_TEST_TARGET ?= test
+DEFAULT_UNIT_TEST_TARGET ?= unit-tests-raw
TEST_LINT ?= test-lint
ifdef TEST_OUTPUT_DIRECTORY
@@ -41,6 +42,7 @@ TPERF = $(sort $(wildcard perf/p[0-9][0-9][0-9][0-9]-*.sh))
TINTEROP = $(sort $(wildcard interop/i[0-9][0-9][0-9][0-9]-*.sh))
CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.test)))
CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl
+UNIT_TESTS = $(sort $(filter-out unit-tests/bin/t-basic%,$(wildcard unit-tests/bin/t-*)))
# `test-chainlint` (which is a dependency of `test-lint`, `test` and `prove`)
# checks all tests in all scripts via a single invocation, so tell individual
@@ -65,6 +67,17 @@ prove: pre-clean check-chainlint $(TEST_LINT)
$(T):
@echo "*** $@ ***"; '$(TEST_SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
+$(UNIT_TESTS):
+ @echo "*** $@ ***"; $@
+
+.PHONY: unit-tests unit-tests-raw unit-tests-prove
+unit-tests: $(DEFAULT_UNIT_TEST_TARGET)
+
+unit-tests-raw: $(UNIT_TESTS)
+
+unit-tests-prove:
+ @echo "*** prove - unit tests ***"; $(PROVE) $(GIT_PROVE_OPTS) $(UNIT_TESTS)
+
pre-clean:
$(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
@@ -149,4 +162,4 @@ perf:
$(MAKE) -C perf/ all
.PHONY: pre-clean $(T) aggregate-results clean valgrind perf \
- check-chainlint clean-chainlint test-chainlint
+ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS)
diff --git a/t/t0080-unit-test-output.sh b/t/t0080-unit-test-output.sh
new file mode 100755
index 0000000000..961b54b06c
--- /dev/null
+++ b/t/t0080-unit-test-output.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+test_description='Test the output of the unit test framework'
+
+. ./test-lib.sh
+
+test_expect_success 'TAP output from unit tests' '
+ cat >expect <<-EOF &&
+ ok 1 - passing test
+ ok 2 - passing test and assertion return 1
+ # check "1 == 2" failed at t/unit-tests/t-basic.c:76
+ # left: 1
+ # right: 2
+ not ok 3 - failing test
+ ok 4 - failing test and assertion return 0
+ not ok 5 - passing TEST_TODO() # TODO
+ ok 6 - passing TEST_TODO() returns 1
+ # todo check ${SQ}check(x)${SQ} succeeded at t/unit-tests/t-basic.c:25
+ not ok 7 - failing TEST_TODO()
+ ok 8 - failing TEST_TODO() returns 0
+ # check "0" failed at t/unit-tests/t-basic.c:30
+ # skipping test - missing prerequisite
+ # skipping check ${SQ}1${SQ} at t/unit-tests/t-basic.c:32
+ ok 9 - test_skip() # SKIP
+ ok 10 - skipped test returns 1
+ # skipping test - missing prerequisite
+ ok 11 - test_skip() inside TEST_TODO() # SKIP
+ ok 12 - test_skip() inside TEST_TODO() returns 1
+ # check "0" failed at t/unit-tests/t-basic.c:48
+ not ok 13 - TEST_TODO() after failing check
+ ok 14 - TEST_TODO() after failing check returns 0
+ # check "0" failed at t/unit-tests/t-basic.c:56
+ not ok 15 - failing check after TEST_TODO()
+ ok 16 - failing check after TEST_TODO() returns 0
+ # check "!strcmp("\thello\\\\", "there\"\n")" failed at t/unit-tests/t-basic.c:61
+ # left: "\011hello\\\\"
+ # right: "there\"\012"
+ # check "!strcmp("NULL", NULL)" failed at t/unit-tests/t-basic.c:62
+ # left: "NULL"
+ # right: NULL
+ # check "${SQ}a${SQ} == ${SQ}\n${SQ}" failed at t/unit-tests/t-basic.c:63
+ # left: ${SQ}a${SQ}
+ # right: ${SQ}\012${SQ}
+ # check "${SQ}\\\\${SQ} == ${SQ}\\${SQ}${SQ}" failed at t/unit-tests/t-basic.c:64
+ # left: ${SQ}\\\\${SQ}
+ # right: ${SQ}\\${SQ}${SQ}
+ not ok 17 - messages from failing string and char comparison
+ # BUG: test has no checks at t/unit-tests/t-basic.c:91
+ not ok 18 - test with no checks
+ ok 19 - test with no checks returns 0
+ 1..19
+ EOF
+
+ ! "$GIT_BUILD_DIR"/t/unit-tests/bin/t-basic >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/unit-tests/.gitignore b/t/unit-tests/.gitignore
new file mode 100644
index 0000000000..5e56e040ec
--- /dev/null
+++ b/t/unit-tests/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/t/unit-tests/t-basic.c b/t/unit-tests/t-basic.c
new file mode 100644
index 0000000000..fda1ae59a6
--- /dev/null
+++ b/t/unit-tests/t-basic.c
@@ -0,0 +1,95 @@
+#include "test-lib.h"
+
+/*
+ * The purpose of this "unit test" is to verify a few invariants of the unit
+ * test framework itself, as well as to provide examples of output from actually
+ * failing tests. As such, it is intended that this test fails, and thus it
+ * should not be run as part of `make unit-tests`. Instead, we verify it behaves
+ * as expected in the integration test t0080-unit-test-output.sh
+ */
+
+/* Used to store the return value of check_int(). */
+static int check_res;
+
+/* Used to store the return value of TEST(). */
+static int test_res;
+
+static void t_res(int expect)
+{
+ check_int(check_res, ==, expect);
+ check_int(test_res, ==, expect);
+}
+
+static void t_todo(int x)
+{
+ check_res = TEST_TODO(check(x));
+}
+
+static void t_skip(void)
+{
+ check(0);
+ test_skip("missing prerequisite");
+ check(1);
+}
+
+static int do_skip(void)
+{
+ test_skip("missing prerequisite");
+ return 1;
+}
+
+static void t_skip_todo(void)
+{
+ check_res = TEST_TODO(do_skip());
+}
+
+static void t_todo_after_fail(void)
+{
+ check(0);
+ TEST_TODO(check(0));
+}
+
+static void t_fail_after_todo(void)
+{
+ check(1);
+ TEST_TODO(check(0));
+ check(0);
+}
+
+static void t_messages(void)
+{
+ check_str("\thello\\", "there\"\n");
+ check_str("NULL", NULL);
+ check_char('a', ==, '\n');
+ check_char('\\', ==, '\'');
+}
+
+static void t_empty(void)
+{
+ ; /* empty */
+}
+
+int cmd_main(int argc, const char **argv)
+{
+ test_res = TEST(check_res = check_int(1, ==, 1), "passing test");
+ TEST(t_res(1), "passing test and assertion return 1");
+ test_res = TEST(check_res = check_int(1, ==, 2), "failing test");
+ TEST(t_res(0), "failing test and assertion return 0");
+ test_res = TEST(t_todo(0), "passing TEST_TODO()");
+ TEST(t_res(1), "passing TEST_TODO() returns 1");
+ test_res = TEST(t_todo(1), "failing TEST_TODO()");
+ TEST(t_res(0), "failing TEST_TODO() returns 0");
+ test_res = TEST(t_skip(), "test_skip()");
+ TEST(check_int(test_res, ==, 1), "skipped test returns 1");
+ test_res = TEST(t_skip_todo(), "test_skip() inside TEST_TODO()");
+ TEST(t_res(1), "test_skip() inside TEST_TODO() returns 1");
+ test_res = TEST(t_todo_after_fail(), "TEST_TODO() after failing check");
+ TEST(check_int(test_res, ==, 0), "TEST_TODO() after failing check returns 0");
+ test_res = TEST(t_fail_after_todo(), "failing check after TEST_TODO()");
+ TEST(check_int(test_res, ==, 0), "failing check after TEST_TODO() returns 0");
+ TEST(t_messages(), "messages from failing string and char comparison");
+ test_res = TEST(t_empty(), "test with no checks");
+ TEST(check_int(test_res, ==, 0), "test with no checks returns 0");
+
+ return test_done();
+}
diff --git a/t/unit-tests/t-strbuf.c b/t/unit-tests/t-strbuf.c
new file mode 100644
index 0000000000..de434a4441
--- /dev/null
+++ b/t/unit-tests/t-strbuf.c
@@ -0,0 +1,120 @@
+#include "test-lib.h"
+#include "strbuf.h"
+
+/* wrapper that supplies tests with an empty, initialized strbuf */
+static void setup(void (*f)(struct strbuf*, void*), void *data)
+{
+ struct strbuf buf = STRBUF_INIT;
+
+ f(&buf, data);
+ strbuf_release(&buf);
+ check_uint(buf.len, ==, 0);
+ check_uint(buf.alloc, ==, 0);
+}
+
+/* wrapper that supplies tests with a populated, initialized strbuf */
+static void setup_populated(void (*f)(struct strbuf*, void*), char *init_str, void *data)
+{
+ struct strbuf buf = STRBUF_INIT;
+
+ strbuf_addstr(&buf, init_str);
+ check_uint(buf.len, ==, strlen(init_str));
+ f(&buf, data);
+ strbuf_release(&buf);
+ check_uint(buf.len, ==, 0);
+ check_uint(buf.alloc, ==, 0);
+}
+
+static int assert_sane_strbuf(struct strbuf *buf)
+{
+ /* Initialized strbufs should always have a non-NULL buffer */
+ if (!check(!!buf->buf))
+ return 0;
+ /* Buffers should always be NUL-terminated */
+ if (!check_char(buf->buf[buf->len], ==, '\0'))
+ return 0;
+ /*
+ * Freshly-initialized strbufs may not have a dynamically allocated
+ * buffer
+ */
+ if (buf->len == 0 && buf->alloc == 0)
+ return 1;
+ /* alloc must be at least one byte larger than len */
+ return check_uint(buf->len, <, buf->alloc);
+}
+
+static void t_static_init(void)
+{
+ struct strbuf buf = STRBUF_INIT;
+
+ check_uint(buf.len, ==, 0);
+ check_uint(buf.alloc, ==, 0);
+ check_char(buf.buf[0], ==, '\0');
+}
+
+static void t_dynamic_init(void)
+{
+ struct strbuf buf;
+
+ strbuf_init(&buf, 1024);
+ check(assert_sane_strbuf(&buf));
+ check_uint(buf.len, ==, 0);
+ check_uint(buf.alloc, >=, 1024);
+ check_char(buf.buf[0], ==, '\0');
+ strbuf_release(&buf);
+}
+
+static void t_addch(struct strbuf *buf, void *data)
+{
+ const char *p_ch = data;
+ const char ch = *p_ch;
+ size_t orig_alloc = buf->alloc;
+ size_t orig_len = buf->len;
+
+ if (!check(assert_sane_strbuf(buf)))
+ return;
+ strbuf_addch(buf, ch);
+ if (!check(assert_sane_strbuf(buf)))
+ return;
+ if (!(check_uint(buf->len, ==, orig_len + 1) &&
+ check_uint(buf->alloc, >=, orig_alloc)))
+ return; /* avoid de-referencing buf->buf */
+ check_char(buf->buf[buf->len - 1], ==, ch);
+ check_char(buf->buf[buf->len], ==, '\0');
+}
+
+static void t_addstr(struct strbuf *buf, void *data)
+{
+ const char *text = data;
+ size_t len = strlen(text);
+ size_t orig_alloc = buf->alloc;
+ size_t orig_len = buf->len;
+
+ if (!check(assert_sane_strbuf(buf)))
+ return;
+ strbuf_addstr(buf, text);
+ if (!check(assert_sane_strbuf(buf)))
+ return;
+ if (!(check_uint(buf->len, ==, orig_len + len) &&
+ check_uint(buf->alloc, >=, orig_alloc) &&
+ check_uint(buf->alloc, >, orig_len + len) &&
+ check_char(buf->buf[orig_len + len], ==, '\0')))
+ return;
+ check_str(buf->buf + orig_len, text);
+}
+
+int cmd_main(int argc, const char **argv)
+{
+ if (!TEST(t_static_init(), "static initialization works"))
+ test_skip_all("STRBUF_INIT is broken");
+ TEST(t_dynamic_init(), "dynamic initialization works");
+ TEST(setup(t_addch, "a"), "strbuf_addch adds char");
+ TEST(setup(t_addch, ""), "strbuf_addch adds NUL char");
+ TEST(setup_populated(t_addch, "initial value", "a"),
+ "strbuf_addch appends to initial value");
+ TEST(setup(t_addstr, "hello there"), "strbuf_addstr adds string");
+ TEST(setup_populated(t_addstr, "initial value", "hello there"),
+ "strbuf_addstr appends string to initial value");
+
+ return test_done();
+}
diff --git a/t/unit-tests/test-lib.c b/t/unit-tests/test-lib.c
new file mode 100644
index 0000000000..b20f543121
--- /dev/null
+++ b/t/unit-tests/test-lib.c
@@ -0,0 +1,329 @@
+#include "test-lib.h"
+
+enum result {
+ RESULT_NONE,
+ RESULT_FAILURE,
+ RESULT_SKIP,
+ RESULT_SUCCESS,
+ RESULT_TODO
+};
+
+static struct {
+ enum result result;
+ int count;
+ unsigned failed :1;
+ unsigned lazy_plan :1;
+ unsigned running :1;
+ unsigned skip_all :1;
+ unsigned todo :1;
+} ctx = {
+ .lazy_plan = 1,
+ .result = RESULT_NONE,
+};
+
+static void msg_with_prefix(const char *prefix, const char *format, va_list ap)
+{
+ fflush(stderr);
+ if (prefix)
+ fprintf(stdout, "%s", prefix);
+ vprintf(format, ap); /* TODO: handle newlines */
+ putc('\n', stdout);
+ fflush(stdout);
+}
+
+void test_msg(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ msg_with_prefix("# ", format, ap);
+ va_end(ap);
+}
+
+void test_plan(int count)
+{
+ assert(!ctx.running);
+
+ fflush(stderr);
+ printf("1..%d\n", count);
+ fflush(stdout);
+ ctx.lazy_plan = 0;
+}
+
+int test_done(void)
+{
+ assert(!ctx.running);
+
+ if (ctx.lazy_plan)
+ test_plan(ctx.count);
+
+ return ctx.failed;
+}
+
+void test_skip(const char *format, ...)
+{
+ va_list ap;
+
+ assert(ctx.running);
+
+ ctx.result = RESULT_SKIP;
+ va_start(ap, format);
+ if (format)
+ msg_with_prefix("# skipping test - ", format, ap);
+ va_end(ap);
+}
+
+void test_skip_all(const char *format, ...)
+{
+ va_list ap;
+ const char *prefix;
+
+ if (!ctx.count && ctx.lazy_plan) {
+ /* We have not printed a test plan yet */
+ prefix = "1..0 # SKIP ";
+ ctx.lazy_plan = 0;
+ } else {
+ /* We have already printed a test plan */
+ prefix = "Bail out! # ";
+ ctx.failed = 1;
+ }
+ ctx.skip_all = 1;
+ ctx.result = RESULT_SKIP;
+ va_start(ap, format);
+ msg_with_prefix(prefix, format, ap);
+ va_end(ap);
+}
+
+int test__run_begin(void)
+{
+ assert(!ctx.running);
+
+ ctx.count++;
+ ctx.result = RESULT_NONE;
+ ctx.running = 1;
+
+ return ctx.skip_all;
+}
+
+static void print_description(const char *format, va_list ap)
+{
+ if (format) {
+ fputs(" - ", stdout);
+ vprintf(format, ap);
+ }
+}
+
+int test__run_end(int was_run UNUSED, const char *location, const char *format, ...)
+{
+ va_list ap;
+
+ assert(ctx.running);
+ assert(!ctx.todo);
+
+ fflush(stderr);
+ va_start(ap, format);
+ if (!ctx.skip_all) {
+ switch (ctx.result) {
+ case RESULT_SUCCESS:
+ printf("ok %d", ctx.count);
+ print_description(format, ap);
+ break;
+
+ case RESULT_FAILURE:
+ printf("not ok %d", ctx.count);
+ print_description(format, ap);
+ break;
+
+ case RESULT_TODO:
+ printf("not ok %d", ctx.count);
+ print_description(format, ap);
+ printf(" # TODO");
+ break;
+
+ case RESULT_SKIP:
+ printf("ok %d", ctx.count);
+ print_description(format, ap);
+ printf(" # SKIP");
+ break;
+
+ case RESULT_NONE:
+ test_msg("BUG: test has no checks at %s", location);
+ printf("not ok %d", ctx.count);
+ print_description(format, ap);
+ ctx.result = RESULT_FAILURE;
+ break;
+ }
+ }
+ va_end(ap);
+ ctx.running = 0;
+ if (ctx.skip_all)
+ return 1;
+ putc('\n', stdout);
+ fflush(stdout);
+ ctx.failed |= ctx.result == RESULT_FAILURE;
+
+ return ctx.result != RESULT_FAILURE;
+}
+
+static void test_fail(void)
+{
+ assert(ctx.result != RESULT_SKIP);
+
+ ctx.result = RESULT_FAILURE;
+}
+
+static void test_pass(void)
+{
+ assert(ctx.result != RESULT_SKIP);
+
+ if (ctx.result == RESULT_NONE)
+ ctx.result = RESULT_SUCCESS;
+}
+
+static void test_todo(void)
+{
+ assert(ctx.result != RESULT_SKIP);
+
+ if (ctx.result != RESULT_FAILURE)
+ ctx.result = RESULT_TODO;
+}
+
+int test_assert(const char *location, const char *check, int ok)
+{
+ assert(ctx.running);
+
+ if (ctx.result == RESULT_SKIP) {
+ test_msg("skipping check '%s' at %s", check, location);
+ return 1;
+ } else if (!ctx.todo) {
+ if (ok) {
+ test_pass();
+ } else {
+ test_msg("check \"%s\" failed at %s", check, location);
+ test_fail();
+ }
+ }
+
+ return !!ok;
+}
+
+void test__todo_begin(void)
+{
+ assert(ctx.running);
+ assert(!ctx.todo);
+
+ ctx.todo = 1;
+}
+
+int test__todo_end(const char *location, const char *check, int res)
+{
+ assert(ctx.running);
+ assert(ctx.todo);
+
+ ctx.todo = 0;
+ if (ctx.result == RESULT_SKIP)
+ return 1;
+ if (res) {
+ test_msg("todo check '%s' succeeded at %s", check, location);
+ test_fail();
+ } else {
+ test_todo();
+ }
+
+ return !res;
+}
+
+int check_bool_loc(const char *loc, const char *check, int ok)
+{
+ return test_assert(loc, check, ok);
+}
+
+union test__tmp test__tmp[2];
+
+int check_int_loc(const char *loc, const char *check, int ok,
+ intmax_t a, intmax_t b)
+{
+ int ret = test_assert(loc, check, ok);
+
+ if (!ret) {
+ test_msg(" left: %"PRIdMAX, a);
+ test_msg(" right: %"PRIdMAX, b);
+ }
+
+ return ret;
+}
+
+int check_uint_loc(const char *loc, const char *check, int ok,
+ uintmax_t a, uintmax_t b)
+{
+ int ret = test_assert(loc, check, ok);
+
+ if (!ret) {
+ test_msg(" left: %"PRIuMAX, a);
+ test_msg(" right: %"PRIuMAX, b);
+ }
+
+ return ret;
+}
+
+static void print_one_char(char ch, char quote)
+{
+ if ((unsigned char)ch < 0x20u || ch == 0x7f) {
+ /* TODO: improve handling of \a, \b, \f ... */
+ printf("\\%03o", (unsigned char)ch);
+ } else {
+ if (ch == '\\' || ch == quote)
+ putc('\\', stdout);
+ putc(ch, stdout);
+ }
+}
+
+static void print_char(const char *prefix, char ch)
+{
+ printf("# %s: '", prefix);
+ print_one_char(ch, '\'');
+ fputs("'\n", stdout);
+}
+
+int check_char_loc(const char *loc, const char *check, int ok, char a, char b)
+{
+ int ret = test_assert(loc, check, ok);
+
+ if (!ret) {
+ fflush(stderr);
+ print_char(" left", a);
+ print_char(" right", b);
+ fflush(stdout);
+ }
+
+ return ret;
+}
+
+static void print_str(const char *prefix, const char *str)
+{
+ printf("# %s: ", prefix);
+ if (!str) {
+ fputs("NULL\n", stdout);
+ } else {
+ putc('"', stdout);
+ while (*str)
+ print_one_char(*str++, '"');
+ fputs("\"\n", stdout);
+ }
+}
+
+int check_str_loc(const char *loc, const char *check,
+ const char *a, const char *b)
+{
+ int ok = (!a && !b) || (a && b && !strcmp(a, b));
+ int ret = test_assert(loc, check, ok);
+
+ if (!ret) {
+ fflush(stderr);
+ print_str(" left", a);
+ print_str(" right", b);
+ fflush(stdout);
+ }
+
+ return ret;
+}
diff --git a/t/unit-tests/test-lib.h b/t/unit-tests/test-lib.h
new file mode 100644
index 0000000000..a8f07ae0b7
--- /dev/null
+++ b/t/unit-tests/test-lib.h
@@ -0,0 +1,149 @@
+#ifndef TEST_LIB_H
+#define TEST_LIB_H
+
+#include "git-compat-util.h"
+
+/*
+ * Run a test function, returns 1 if the test succeeds, 0 if it
+ * fails. If test_skip_all() has been called then the test will not be
+ * run. The description for each test should be unique. For example:
+ *
+ * TEST(test_something(arg1, arg2), "something %d %d", arg1, arg2)
+ */
+#define TEST(t, ...) \
+ test__run_end(test__run_begin() ? 0 : (t, 1), \
+ TEST_LOCATION(), __VA_ARGS__)
+
+/*
+ * Print a test plan, should be called before any tests. If the number
+ * of tests is not known in advance test_done() will automatically
+ * print a plan at the end of the test program.
+ */
+void test_plan(int count);
+
+/*
+ * test_done() must be called at the end of main(). It will print the
+ * plan if plan() was not called at the beginning of the test program
+ * and returns the exit code for the test program.
+ */
+int test_done(void);
+
+/* Skip the current test. */
+__attribute__((format (printf, 1, 2)))
+void test_skip(const char *format, ...);
+
+/* Skip all remaining tests. */
+__attribute__((format (printf, 1, 2)))
+void test_skip_all(const char *format, ...);
+
+/* Print a diagnostic message to stdout. */
+__attribute__((format (printf, 1, 2)))
+void test_msg(const char *format, ...);
+
+/*
+ * Test checks are built around test_assert(). checks return 1 on
+ * success, 0 on failure. If any check fails then the test will fail. To
+ * create a custom check define a function that wraps test_assert() and
+ * a macro to wrap that function to provide a source location and
+ * stringified arguments. Custom checks that take pointer arguments
+ * should be careful to check that they are non-NULL before
+ * dereferencing them. For example:
+ *
+ * static int check_oid_loc(const char *loc, const char *check,
+ * struct object_id *a, struct object_id *b)
+ * {
+ * int res = test_assert(loc, check, a && b && oideq(a, b));
+ *
+ * if (!res) {
+ * test_msg(" left: %s", a ? oid_to_hex(a) : "NULL";
+ * test_msg(" right: %s", b ? oid_to_hex(a) : "NULL";
+ *
+ * }
+ * return res;
+ * }
+ *
+ * #define check_oid(a, b) \
+ * check_oid_loc(TEST_LOCATION(), "oideq("#a", "#b")", a, b)
+ */
+int test_assert(const char *location, const char *check, int ok);
+
+/* Helper macro to pass the location to checks */
+#define TEST_LOCATION() TEST__MAKE_LOCATION(__LINE__)
+
+/* Check a boolean condition. */
+#define check(x) \
+ check_bool_loc(TEST_LOCATION(), #x, x)
+int check_bool_loc(const char *loc, const char *check, int ok);
+
+/*
+ * Compare two integers. Prints a message with the two values if the
+ * comparison fails. NB this is not thread safe.
+ */
+#define check_int(a, op, b) \
+ (test__tmp[0].i = (a), test__tmp[1].i = (b), \
+ check_int_loc(TEST_LOCATION(), #a" "#op" "#b, \
+ test__tmp[0].i op test__tmp[1].i, \
+ test__tmp[0].i, test__tmp[1].i))
+int check_int_loc(const char *loc, const char *check, int ok,
+ intmax_t a, intmax_t b);
+
+/*
+ * Compare two unsigned integers. Prints a message with the two values
+ * if the comparison fails. NB this is not thread safe.
+ */
+#define check_uint(a, op, b) \
+ (test__tmp[0].u = (a), test__tmp[1].u = (b), \
+ check_uint_loc(TEST_LOCATION(), #a" "#op" "#b, \
+ test__tmp[0].u op test__tmp[1].u, \
+ test__tmp[0].u, test__tmp[1].u))
+int check_uint_loc(const char *loc, const char *check, int ok,
+ uintmax_t a, uintmax_t b);
+
+/*
+ * Compare two chars. Prints a message with the two values if the
+ * comparison fails. NB this is not thread safe.
+ */
+#define check_char(a, op, b) \
+ (test__tmp[0].c = (a), test__tmp[1].c = (b), \
+ check_char_loc(TEST_LOCATION(), #a" "#op" "#b, \
+ test__tmp[0].c op test__tmp[1].c, \
+ test__tmp[0].c, test__tmp[1].c))
+int check_char_loc(const char *loc, const char *check, int ok,
+ char a, char b);
+
+/* Check whether two strings are equal. */
+#define check_str(a, b) \
+ check_str_loc(TEST_LOCATION(), "!strcmp("#a", "#b")", a, b)
+int check_str_loc(const char *loc, const char *check,
+ const char *a, const char *b);
+
+/*
+ * Wrap a check that is known to fail. If the check succeeds then the
+ * test will fail. Returns 1 if the check fails, 0 if it
+ * succeeds. For example:
+ *
+ * TEST_TODO(check(0));
+ */
+#define TEST_TODO(check) \
+ (test__todo_begin(), test__todo_end(TEST_LOCATION(), #check, check))
+
+/* Private helpers */
+
+#define TEST__STR(x) #x
+#define TEST__MAKE_LOCATION(line) __FILE__ ":" TEST__STR(line)
+
+union test__tmp {
+ intmax_t i;
+ uintmax_t u;
+ char c;
+};
+
+extern union test__tmp test__tmp[2];
+
+int test__run_begin(void);
+__attribute__((format (printf, 3, 4)))
+int test__run_end(int, const char *, const char *, ...);
+void test__todo_begin(void);
+int test__todo_end(const char *, const char *, int);
+
+#endif /* TEST_LIB_H */
--
2.42.0.869.gea05f2083d-goog
^ permalink raw reply related
* Re: [PATCH v8 2.5/3] fixup! unit tests: add TAP unit test framework
From: Junio C Hamano @ 2023-11-01 23:48 UTC (permalink / raw)
To: Josh Steadmon; +Cc: Phillip Wood, calvinwan, git, linusa, rsbecker
In-Reply-To: <ZUKQ8xtFSYbSBPXb@google.com>
Josh Steadmon <steadmon@google.com> writes:
> On 2023.10.16 09:41, Junio C Hamano wrote:
>> Phillip Wood <phillip.wood123@gmail.com> writes:
>>
>> > From: Phillip Wood <phillip.wood@dunelm.org.uk>
>> >
>> > Here are a couple of cleanups for the unit test framework that I
>> > noticed.
>>
>> Thanks. I trust that this will be squashed into the next update,
>> but in the meantime, I'll include it in the copy of the series I
>> have (without squashing). Here is another one I noticed.
>>
>> ----- >8 --------- >8 --------- >8 -----
>> Subject: [PATCH] fixup! ci: run unit tests in CI
>>
>> A CI job failed due to contrib/coccinelle/equals-null.cocci
>> and suggested this change, which seems sensible.
>>
>> Signed-off-by: Junio C Hamano <gitster@pobox.com>
>> ---
>> t/unit-tests/t-strbuf.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> Applied in v9, thanks!
Thanks for working well together.
^ permalink raw reply
* Re: [PATCH v8 1/3] unit tests: Add a project plan document
From: Junio C Hamano @ 2023-11-01 23:49 UTC (permalink / raw)
To: Josh Steadmon
Cc: Christian Couder, git, phillip.wood123, linusa, calvinwan,
rsbecker
In-Reply-To: <ZUKPJsW1mT62Mcjy@google.com>
Josh Steadmon <steadmon@google.com> writes:
> On 2023.10.27 22:12, Christian Couder wrote:
>> On Tue, Oct 10, 2023 at 12:22 AM Josh Steadmon <steadmon@google.com> wrote:
>> >
>> > In our current testing environment, we spend a significant amount of
>> > effort crafting end-to-end tests for error conditions that could easily
>> > be captured by unit tests (or we simply forgo some hard-to-setup and
>> > rare error conditions). Describe what we hope to accomplish by
>> > implementing unit tests, and explain some open questions and milestones.
>> > Discuss desired features for test frameworks/harnesses, and provide a
>> > preliminary comparison of several different frameworks.
>>
>> Nit: Not sure why the test framework comparison is "preliminary" as we
>> have actually selected a unit test framework and are adding it in the
>> next patch of the series. I understand that this was perhaps written
>> before the choice was made, but maybe we might want to update that
>> now.
>
> Fixed in v9, thanks.
Thanks for working well together.
^ permalink raw reply
* Re: [PATCH v8 2.5/3] fixup! unit tests: add TAP unit test framework
From: Junio C Hamano @ 2023-11-01 23:49 UTC (permalink / raw)
To: Josh Steadmon
Cc: Phillip Wood, calvinwan, git, linusa, phillip.wood123, rsbecker
In-Reply-To: <ZUKQ2eYmfMEhc_gH@google.com>
Josh Steadmon <steadmon@google.com> writes:
> On 2023.10.16 14:43, Phillip Wood wrote:
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> Here are a couple of cleanups for the unit test framework that I
>> noticed.
>>
>> Update the documentation of the example custom check to reflect the
>> change in return value of test_assert() and mention that
>> checks should be careful when dereferencing pointer arguments.
>>
>> Also avoid evaluating macro augments twice in check_int() and
>> friends. The global variable test__tmp was introduced to avoid
>> evaluating the arguments to these macros more than once but the macros
>> failed to use it when passing the values being compared to
>> check_int_loc().
>>
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> ---
>> t/unit-tests/test-lib.h | 26 ++++++++++++++++----------
>> 1 file changed, 16 insertions(+), 10 deletions(-)
>
> Applied in v9, thanks!
Thanks for working well together.
^ permalink raw reply
* Re: [PATCH v3 1/2] git-merge-file doc: drop "-file" from argument placeholders
From: Junio C Hamano @ 2023-11-01 23:53 UTC (permalink / raw)
To: brian m. carlson
Cc: git, Elijah Newren, Phillip Wood, Eric Sunshine, Taylor Blau,
Martin Ågren
In-Reply-To: <20231101192419.794162-2-sandals@crustytoothpaste.net>
"brian m. carlson" <sandals@crustytoothpaste.net> writes:
> From: Martin Ågren <martin.agren@gmail.com>
>
> `git merge-file` takes three positional arguments. Each of them is
> documented as `<foo-file>`. In preparation for teaching this command to
> alternatively take three object IDs, make these placeholders a bit more
Minor nit. Don't we want to say "three blob object names"? Unless
we plan to grow this feature into accepting three tree object names,
that is.
^ permalink raw reply
* Re: [PATCH v3 0/2] Object ID support for git merge-file
From: Junio C Hamano @ 2023-11-01 23:55 UTC (permalink / raw)
To: brian m. carlson
Cc: git, Elijah Newren, Phillip Wood, Eric Sunshine, Taylor Blau,
Martin Ågren
In-Reply-To: <20231101192419.794162-1-sandals@crustytoothpaste.net>
"brian m. carlson" <sandals@crustytoothpaste.net> writes:
> This series introduces an --object-id option to git merge-file such
> that, instead of reading and writing from files on the system, it reads
> from and writes to the object store using blobs.
>
> Changes from v2:
> * Include a patch from Martin to pre-improve the documentation
> * Remove incorrect portion of commit message
Looking good. Will replace. Shall we mark the topic ready for
'next'?
Thanks.
^ permalink raw reply
* [PATCH 1/1] attr: enable attr pathspec magic for git-add and git-stash
From: Joanna Wang @ 2023-11-02 1:55 UTC (permalink / raw)
To: jojwang; +Cc: git, gitster
In-Reply-To: <20231011202008.609921-1-jojwang@google.com>
This lets users limit files or exclude files based on file
attributes during git-add and git-stash.
For example, the chromium project would like to use this like
"git add --all ':(exclude,attr:submodule)'", as submodules are managed in a
unique way and often results in submodule changes that users do not want in
their commits.
This does not change any attr magic implementation. It is only adding
attr as an allowed pathspec in git-add and git-stash, which was previously
blocked by GUARD_PATHSPEC and a pathspec mask in parse_pathspec()).
However, this does fix a bug in prefix_magic() where attr values were unintentionally removed.
This was hit whenever parse_pathspec() is called with PATHSPEC_PREFIX_ORIGIN as a flag,
which was the case for git-stash. More details here:
https://lore.kernel.org/git/CAMmZTi-0QKtj7Q=sbC5qhipGsQxJFOY-Qkk1jfkRYwfF5FcUVg@mail.gmail.com/
It is possible that when the attr pathspec feature was first added in
b0db704652 (pathspec: allow querying for attributes, 2017-03-13),
"PATHSPEC_ATTR" was just unintentionally left out of a few GUARD_PATHSPEC() invocations.
Later, to get a more user-friendly error message when attr was used with git-add,
PATHSPEC_ATTR was added as a mask to git-add's invocation of parse_pathspec()
84d938b732 (add: do not accept pathspec magic 'attr', 2018-09-18).
However, this user-friendly error message was never added for git-stash.
Signed-off-by: Joanna Wang <jojwang@google.com>
---
PTAL.
I've updated this to include the fix for git-stash. I was initially going to fix this bug [1]
separately, but I thought it would make more sense to put everything in one patch so attr
could be enabled for both git-add and git-stash and tested.
[1] https://lore.kernel.org/git/CAMmZTi-0QKtj7Q=sbC5qhipGsQxJFOY-Qkk1jfkRYwfF5FcUVg@mail.gmail.com/
builtin/add.c | 7 ++-
dir.c | 3 +-
pathspec.c | 11 +++-
t/t6135-pathspec-with-attrs.sh | 108 +++++++++++++++++++++++++++++++--
4 files changed, 118 insertions(+), 11 deletions(-)
diff --git a/builtin/add.c b/builtin/add.c
index 5126d2ede3..d46e4d10e9 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -424,7 +424,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
* Check the "pathspec '%s' did not match any files" block
* below before enabling new magic.
*/
- parse_pathspec(&pathspec, PATHSPEC_ATTR,
+ parse_pathspec(&pathspec, 0,
PATHSPEC_PREFER_FULL |
PATHSPEC_SYMLINK_LEADING_PATH,
prefix, argv);
@@ -433,7 +433,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (pathspec.nr)
die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
- parse_pathspec_file(&pathspec, PATHSPEC_ATTR,
+ parse_pathspec_file(&pathspec, 0,
PATHSPEC_PREFER_FULL |
PATHSPEC_SYMLINK_LEADING_PATH,
prefix, pathspec_from_file, pathspec_file_nul);
@@ -504,7 +504,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
PATHSPEC_LITERAL |
PATHSPEC_GLOB |
PATHSPEC_ICASE |
- PATHSPEC_EXCLUDE);
+ PATHSPEC_EXCLUDE |
+ PATHSPEC_ATTR);
for (i = 0; i < pathspec.nr; i++) {
const char *path = pathspec.items[i].match;
diff --git a/dir.c b/dir.c
index 16fdb03f2a..4d1cd039be 100644
--- a/dir.c
+++ b/dir.c
@@ -2179,7 +2179,8 @@ static int exclude_matches_pathspec(const char *path, int pathlen,
PATHSPEC_LITERAL |
PATHSPEC_GLOB |
PATHSPEC_ICASE |
- PATHSPEC_EXCLUDE);
+ PATHSPEC_EXCLUDE |
+ PATHSPEC_ATTR);
for (i = 0; i < pathspec->nr; i++) {
const struct pathspec_item *item = &pathspec->items[i];
diff --git a/pathspec.c b/pathspec.c
index bb1efe1f39..40bd8a8819 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -109,7 +109,7 @@ static struct pathspec_magic {
{ PATHSPEC_ATTR, '\0', "attr" },
};
-static void prefix_magic(struct strbuf *sb, int prefixlen, unsigned magic)
+static void prefix_magic(struct strbuf *sb, int prefixlen, unsigned magic, const char *element)
{
int i;
strbuf_addstr(sb, ":(");
@@ -118,6 +118,13 @@ static void prefix_magic(struct strbuf *sb, int prefixlen, unsigned magic)
if (sb->buf[sb->len - 1] != '(')
strbuf_addch(sb, ',');
strbuf_addstr(sb, pathspec_magic[i].name);
+ if (pathspec_magic[i].bit & PATHSPEC_ATTR) {
+ /* extract and insert the attr magic value */
+ char* p = strstr(element, "attr:");
+ char buff[128];
+ sscanf(p, "attr%[^)|,]", buff);
+ strbuf_addstr(sb, buff);
+ }
}
strbuf_addf(sb, ",prefix:%d)", prefixlen);
}
@@ -493,7 +500,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,
struct strbuf sb = STRBUF_INIT;
/* Preserve the actual prefix length of each pattern */
- prefix_magic(&sb, prefixlen, element_magic);
+ prefix_magic(&sb, prefixlen, element_magic, elt);
strbuf_addstr(&sb, match);
item->original = strbuf_detach(&sb, NULL);
diff --git a/t/t6135-pathspec-with-attrs.sh b/t/t6135-pathspec-with-attrs.sh
index f70c395e75..e46fa176ed 100755
--- a/t/t6135-pathspec-with-attrs.sh
+++ b/t/t6135-pathspec-with-attrs.sh
@@ -64,12 +64,24 @@ test_expect_success 'setup .gitattributes' '
fileSetLabel label
fileValue label=foo
fileWrongLabel label☺
+ newFileA* labelA
+ newFileB* labelB
EOF
echo fileSetLabel label1 >sub/.gitattributes &&
git add .gitattributes sub/.gitattributes &&
git commit -m "add attributes"
'
+test_expect_success 'setup .gitignore' '
+ cat <<-\EOF >.gitignore &&
+ actual
+ expect
+ pathspec_file
+ EOF
+ git add .gitignore &&
+ git commit -m "add gitignore"
+'
+
test_expect_success 'check specific set attr' '
cat <<-\EOF >expect &&
fileSetLabel
@@ -150,6 +162,7 @@ test_expect_success 'check specific value attr (2)' '
test_expect_success 'check unspecified attr' '
cat <<-\EOF >expect &&
.gitattributes
+ .gitignore
fileA
fileAB
fileAC
@@ -175,6 +188,7 @@ test_expect_success 'check unspecified attr' '
test_expect_success 'check unspecified attr (2)' '
cat <<-\EOF >expect &&
HEAD:.gitattributes
+ HEAD:.gitignore
HEAD:fileA
HEAD:fileAB
HEAD:fileAC
@@ -200,6 +214,7 @@ test_expect_success 'check unspecified attr (2)' '
test_expect_success 'check multiple unspecified attr' '
cat <<-\EOF >expect &&
.gitattributes
+ .gitignore
fileC
fileNoLabel
fileWrongLabel
@@ -239,16 +254,99 @@ test_expect_success 'fail on multiple attr specifiers in one pathspec item' '
test_i18ngrep "Only one" actual
'
-test_expect_success 'fail if attr magic is used places not implemented' '
+test_expect_success 'fail if attr magic is used in places not implemented' '
# The main purpose of this test is to check that we actually fail
# when you attempt to use attr magic in commands that do not implement
- # attr magic. This test does not advocate git-add to stay that way,
- # though, but git-add is convenient as it has its own internal pathspec
- # parsing.
- test_must_fail git add ":(attr:labelB)" 2>actual &&
+ # attr magic. This test does not advocate check-ignore to stay that way.
+ # When you teach the command to grok the pathspec, you need to find
+ # another command to replace it for the test.
+ test_must_fail git check-ignore ":(attr:labelB)" 2>actual &&
test_i18ngrep "magic not supported" actual
'
+test_expect_success 'check that attr magic works for git stash push' '
+ cat <<-\EOF >expect &&
+ A sub/newFileA-foo
+ EOF
+ >sub/newFileA-foo &&
+ >sub/newFileB-foo &&
+ git stash push --include-untracked -- ":(exclude,attr:labelB)" &&
+ git stash show --include-untracked --name-status >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check that attr magic works for git add --all' '
+ cat <<-\EOF >expect &&
+ sub/newFileA-foo
+ EOF
+ >sub/newFileA-foo &&
+ >sub/newFileB-foo &&
+ git add --all ":(exclude,attr:labelB)" &&
+ git diff --name-only --cached >actual &&
+ git restore -W -S . &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check that attr magic works for git add -u' '
+ cat <<-\EOF >expect &&
+ sub/fileA
+ EOF
+ >sub/newFileA-foo &&
+ >sub/newFileB-foo &&
+ >sub/fileA &&
+ >sub/fileB &&
+ git add -u ":(exclude,attr:labelB)" &&
+ git diff --name-only --cached >actual &&
+ git restore -S -W . && rm sub/new* &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check that attr magic works for git add <path>' '
+ cat <<-\EOF >expect &&
+ fileA
+ fileB
+ sub/fileA
+ EOF
+ >fileA &&
+ >fileB &&
+ >sub/fileA &&
+ >sub/fileB &&
+ git add ":(exclude,attr:labelB)sub/*" &&
+ git diff --name-only --cached >actual &&
+ git restore -S -W . &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check that attr magic works for git -add .' '
+ cat <<-\EOF >expect &&
+ sub/fileA
+ EOF
+ >fileA &&
+ >fileB &&
+ >sub/fileA &&
+ >sub/fileB &&
+ cd sub &&
+ git add . ":(exclude,attr:labelB)" &&
+ cd .. &&
+ git diff --name-only --cached >actual &&
+ git restore -S -W . &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check that attr magic works for git add --pathspec-from-file' '
+ cat <<-\EOF >pathspec_file &&
+ :(exclude,attr:labelB)
+ EOF
+ cat <<-\EOF >expect &&
+ sub/newFileA-foo
+ EOF
+ >sub/newFileA-foo &&
+ >sub/newFileB-foo &&
+ git add --all --pathspec-from-file=pathspec_file &&
+ git diff --name-only --cached >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'abort on giving invalid label on the command line' '
test_must_fail git ls-files . ":(attr:☺)"
'
--
2.42.0.820.g83a721a137-goog
^ permalink raw reply related
* Re: [PATCH 1/1] attr: enable attr pathspec magic for git-add and git-stash
From: Junio C Hamano @ 2023-11-02 5:00 UTC (permalink / raw)
To: Joanna Wang; +Cc: git
In-Reply-To: <20231102015554.34089-1-jojwang@google.com>
Joanna Wang <jojwang@google.com> writes:
> I've updated this to include the fix for git-stash. I was
> initially going to fix this bug [1] separately, but I thought it
> would make more sense to put everything in one patch so attr could
> be enabled for both git-add and git-stash and tested.
I think that is perfectly fine, as long as it is described well in
the proposed log message what is done in the patch, and how two
seemingly different things done in the patch are so closely linked
that it makes sense to do so in a single patch.
Will queue.
Thanks.
> diff --git a/pathspec.c b/pathspec.c
> index bb1efe1f39..40bd8a8819 100644
> --- a/pathspec.c
> +++ b/pathspec.c
> @@ -109,7 +109,7 @@ static struct pathspec_magic {
> { PATHSPEC_ATTR, '\0', "attr" },
> };
>
> -static void prefix_magic(struct strbuf *sb, int prefixlen, unsigned magic)
> +static void prefix_magic(struct strbuf *sb, int prefixlen, unsigned magic, const char *element)
> {
> int i;
> strbuf_addstr(sb, ":(");
> @@ -118,6 +118,13 @@ static void prefix_magic(struct strbuf *sb, int prefixlen, unsigned magic)
> if (sb->buf[sb->len - 1] != '(')
> strbuf_addch(sb, ',');
> strbuf_addstr(sb, pathspec_magic[i].name);
> + if (pathspec_magic[i].bit & PATHSPEC_ATTR) {
> + /* extract and insert the attr magic value */
> + char* p = strstr(element, "attr:");
In our codebase, the asterisk sticks to the variable, not to the
type, i.e.
char *p = strstr(element, "attr:");
> + char buff[128];
Will this fixed-size buffer make an inviting target for script
kiddies, as pathspec often come from the command line and under
control by whoever is making a request?
Aren't we going to copy what is in the elt literally from where
attr: appears up to the next delimiter like ',', ')'? I am not sure
if we need a separate buffer. Would something along this line work?
strbuf_add(sb, p, strcspn(p, ",)");
I am unsure if this "unparsing" is the way we want to go. For one,
just like %(attr:foo) can take an arbitrary end-user supplied string
in the "foo" part, we can have new pathspec magic in the future that
will take an arbitrary end-user supplied string as its value. And the
above unparsing code will be utterly confused when that value
happens to contain "attr:" as its substring, e.g.,
$ git add . ":(exclude,frotz:diattr:0,attr:submodule)"
Also, do we (and if not right now, then do we want to) support
giving more than one attribute?
$ git add ":(attr:text,attr:small)*.py"
Not supporting multiple attributes would be OK for now, but when it
becomes needed, the "unparse using the bits in the element_magic"
does not look like the right approach.
Indeed, if you are going to pass the original "elt" string *anyway*,
you have all the info in there that you need. I wonder if it makes
sense to get rid of the "unsigned magic" bitset from the parameter,
and discard the loop over the pathspec_magic[] array and do
something like:
- if the original "elt" already has some magic (i.e., begins
with ":(" and not in the literal mode), then copy them
literally and textually from ":(" up to the closing ")", but
also insert the necessary "prefix:<num>" magic;
- otherwise, give ":(prefix:<num>)" magic.
without even attempting to unparse the bits in "element_magic"?
Thanks.
^ permalink raw reply
* Re: why does git set X in LESS env var?
From: Thomas Guyot @ 2023-11-02 6:01 UTC (permalink / raw)
To: Dragan Simic, Junio C Hamano; +Cc: Jeff King, Christoph Anton Mitterer, git
In-Reply-To: <cfbe174f-23ac-4a35-8db4-66bdfdfdc14e@gmail.com>
On 2023-11-02 01:48, Thomas Guyot wrote:
> Hey there...
I obviously thought about checking this client's setting the moment I
hit the send button - if the response is garbled I'll resend it properly.
--
Thomas
^ permalink raw reply
* Re: why does git set X in LESS env var?
From: Dragan Simic @ 2023-11-02 6:14 UTC (permalink / raw)
To: Thomas Guyot; +Cc: Junio C Hamano, Jeff King, Christoph Anton Mitterer, git
In-Reply-To: <aefa38cd-d0fa-4dc6-8d10-4358e36b39af@gmail.com>
On 2023-11-02 07:01, Thomas Guyot wrote:
> On 2023-11-02 01:48, Thomas Guyot wrote:
>> Hey there...
>
> I obviously thought about checking this client's setting the moment I
> hit the send button - if the response is garbled I'll resend it
> properly.
It's in HTML format, which isn't the preferred way, but it's still
readable.
^ permalink raw reply
* Re: why does git set X in LESS env var?
From: Dragan Simic @ 2023-11-02 6:48 UTC (permalink / raw)
To: Thomas Guyot; +Cc: Junio C Hamano, Jeff King, Christoph Anton Mitterer, git
In-Reply-To: <cfbe174f-23ac-4a35-8db4-66bdfdfdc14e@gmail.com>
On 2023-11-02 06:48, Thomas Guyot wrote:
> On 2023-10-13 16:12, Dragan Simic wrote:
>> On 2023-10-12 18:19, Junio C Hamano wrote:
>>> Dragan Simic <dsimic@manjaro.org> writes:
>>>> Please note that dropping "-X" and leaving "-F" would actually
>>>> introduce the inconsistency that I already mentioned. To reiterate,
>>>> short outputs would then remain displayed on screen, while long
>>>> outputs would disappear after exiting less(1).
>>>
>>> Good point.
>>
>> I've been thinking about this, and a rather elegant,
>> backward-compatible
>> solution is possible, but it requires some improvements to be made to
>> less(1) first. I'll reach out to the author of less(1) and propose
>> that
>> new feature, and I'll let you know his opinion about it.
>
> Hey there...
Hello!
> I'm clearly late to the party but I'm wondering, has anyone tested
> adding -cy0 ? From the manpage (slightly edited):
>
> -c or --clear-screen ( and backward compat. -C or
> --CLEAR-SCREEN )
> Causes full screen repaints to be painted from the top
> line down. By default, full screen repaints are done by scrolling
> from the bottom of the screen.
AFAIK, the "-c" option is about the way screen contents is updated when
scrolled, and it exists to aid in resolving possible issues with some
terminal emulators. To make sure, I just tested it, and "-c" doesn't
replace "-X".
> -yn or --max-forw-scroll=n
> Specifies a maximum number of lines to scroll
> forward. If it is necessary to scroll forward more than n lines, the
> screen is repainted in‐
> stead. The -c or -C option may be used to repaint from
> the top of the screen if desired. By default, any forward movement
> causes scrolling.
This option is, I'd guess, also about aiding in resolving possible
issues with some terminal emulators. Or maybe even with some actual
terminals as pieces of hardware, who knows, which may be too slow to
scroll many lines at once.
> I actually have one major issue with it, it's that displaying anything
> less than a full page will fill the screen with ~ on the bottom, just
> like when scrolling up on a partial page without -F. I can see this
> being a major annoyance when using for ex. git log -1, git show --stat
> or --name-only, etc. as I usually do it to keep the latest history
> within the current screen (and there's likely even commands that I
> never seen using the pager because I never exceeded the page height).
Huh, this confuses me a bit, quite frankly. Isn't the "-F" option used
specifically to make pagination invisible in case fewer lines than one
full screen are displayed?
> OTOH by repainting from the top, the scrollback buffer is never
> affected. only the last displayed page remains on the terminal.
Just to clarify, it's the "-X" option that creates all the issues, and
the "--redraw-on-quit" option is already there to replace it with no
associated issues, but the trouble is that only newer versions of
less(1) support the "--redraw-on-quit" option. IOW, it's all about
improving less(1) to avoid complex workarounds required to handle
different versions, such as the workarounds used in bat(1).
> If less could only enable this behavior after the first full page
> draw, that would be perfect!
Could you, please, elaborate a bit on that?
> Dragan, that may be useful if you're discussing with less
> developers...
We've basically reached some kind of an agreement about the need for a
good solution, which turned out to be rather complex as a result of
being quite universal and extensible, which was required for it to,
hopefully, be accepted into less(1). Also, the author of less(1) seems
to be quite busy with some other things, and he prefers to implement new
features himself.
We've also agreed on another new feature for less(1), hopefully, which
isn't exactly related, but should be quite useful. It's about the
secure mode for less(1).
^ permalink raw reply
* [PATCH v3 1/9] t: allow skipping expected object ID in `ref-store update-ref`
From: Patrick Steinhardt @ 2023-11-02 8:46 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1698914571.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 1771 bytes --]
We require the caller to pass both the old and new expected object ID to
our `test-tool ref-store update-ref` helper. When trying to update a
symbolic reference though it's impossible to specify the expected object
ID, which means that the test would instead have to force-update the
reference. This is currently impossible though.
Update the helper to optionally skip verification of the old object ID
in case the test passes in an empty old object ID as input.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/helper/test-ref-store.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 48552e6a9e0..702ec1f128a 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -298,16 +298,19 @@ static int cmd_update_ref(struct ref_store *refs, const char **argv)
const char *new_sha1_buf = notnull(*argv++, "new-sha1");
const char *old_sha1_buf = notnull(*argv++, "old-sha1");
unsigned int flags = arg_flags(*argv++, "flags", transaction_flags);
- struct object_id old_oid;
+ struct object_id old_oid, *old_oid_ptr = NULL;
struct object_id new_oid;
- if (get_oid_hex(old_sha1_buf, &old_oid))
- die("cannot parse %s as %s", old_sha1_buf, the_hash_algo->name);
+ if (*old_sha1_buf) {
+ if (get_oid_hex(old_sha1_buf, &old_oid))
+ die("cannot parse %s as %s", old_sha1_buf, the_hash_algo->name);
+ old_oid_ptr = &old_oid;
+ }
if (get_oid_hex(new_sha1_buf, &new_oid))
die("cannot parse %s as %s", new_sha1_buf, the_hash_algo->name);
return refs_update_ref(refs, msg, refname,
- &new_oid, &old_oid,
+ &new_oid, old_oid_ptr,
flags, UPDATE_REFS_DIE_ON_ERR);
}
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v3 0/9] t: reduce direct disk access to data structures
From: Patrick Steinhardt @ 2023-11-02 8:46 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1697607222.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 8559 bytes --]
Hi,
this is the third version of my patch series that aims to reduce access
to on-disk data structures in favor of using plumbing tools where
possible.
There are no changes compared to v2 except for a rebase on top of
0497e6c611 (t: use git-show-ref(1) to check for ref existence,
2023-10-31), which has been merged to "next" now and conflicts with this
patch series.
Patrick
Patrick Steinhardt (9):
t: allow skipping expected object ID in `ref-store update-ref`
t: convert tests to not write references via the filesystem
t: convert tests to not access symrefs via the filesystem
t: convert tests to not access reflog via the filesystem
t1450: convert tests to remove worktrees via git-worktree(1)
t4207: delete replace references via git-update-ref(1)
t7300: assert exact states of repo
t7900: assert the absence of refs via git-for-each-ref(1)
t: mark several tests that assume the files backend with REFFILES
t/helper/test-ref-store.c | 11 ++++---
t/t1400-update-ref.sh | 50 ++++++++++++++++--------------
t/t1430-bad-ref-name.sh | 12 +++----
t/t1450-fsck.sh | 44 +++++++++++++-------------
t/t2011-checkout-invalid-head.sh | 16 +++++-----
t/t3200-branch.sh | 41 ++++++++++++------------
t/t3400-rebase.sh | 2 +-
t/t3404-rebase-interactive.sh | 2 +-
t/t4013-diff-various.sh | 2 +-
t/t4202-log.sh | 2 +-
t/t4207-log-decoration-colors.sh | 10 ++++--
t/t5526-fetch-submodules.sh | 2 +-
t/t5605-clone-local.sh | 4 +--
t/t5702-protocol-v2.sh | 24 ++++++++++----
t/t7300-clean.sh | 23 ++++++++------
t/t7900-maintenance.sh | 3 +-
t/t9133-git-svn-nested-git-repo.sh | 2 +-
17 files changed, 142 insertions(+), 108 deletions(-)
Range-diff against v2:
1: c868198f8c1 = 1: 3caf9e3f28f t: allow skipping expected object ID in `ref-store update-ref`
2: 4c0939d868e = 2: 1884b7006cf t: convert tests to not write references via the filesystem
3: 048583ed2c3 ! 3: d6307177132 t: convert tests to not access symrefs via the filesystem
@@ t/t1430-bad-ref-name.sh: test_expect_success 'update-ref -d can delete broken na
- printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref &&
+ test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/main &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" &&
+ test_ref_exists refs/heads/broken...symref &&
git update-ref --no-deref -d refs/heads/broken...symref >output 2>error &&
- test_path_is_missing .git/refs/heads/broken...symref &&
@@ t/t1430-bad-ref-name.sh: test_expect_success 'update-ref --no-deref -d can delete symref with broken name
'
@@ t/t1430-bad-ref-name.sh: test_expect_success 'update-ref --no-deref -d can delet
- printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref &&
+ test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/main &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" &&
+ test_ref_exists refs/heads/broken...symref &&
git branch -d broken...symref >output 2>error &&
- test_path_is_missing .git/refs/heads/broken...symref &&
@@ t/t1430-bad-ref-name.sh: test_expect_success 'branch -d can delete symref with broken name' '
'
@@ t/t1430-bad-ref-name.sh: test_expect_success 'branch -d can delete symref with b
- printf "ref: refs/heads/idonotexist\n" >.git/refs/heads/broken...symref &&
+ test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/idonotexist &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" &&
+ test_ref_exists refs/heads/broken...symref &&
git update-ref --no-deref -d refs/heads/broken...symref >output 2>error &&
- test_path_is_missing .git/refs/heads/broken...symref &&
@@ t/t1430-bad-ref-name.sh: test_expect_success 'update-ref --no-deref -d can delete dangling symref with br
'
@@ t/t1430-bad-ref-name.sh: test_expect_success 'update-ref --no-deref -d can delet
- printf "ref: refs/heads/idonotexist\n" >.git/refs/heads/broken...symref &&
+ test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/idonotexist &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" &&
+ test_ref_exists refs/heads/broken...symref &&
git branch -d broken...symref >output 2>error &&
- test_path_is_missing .git/refs/heads/broken...symref &&
## t/t1450-fsck.sh ##
@@ t/t1450-fsck.sh: test_expect_success 'HEAD link pointing at a funny object' '
@@ t/t3200-branch.sh: test_expect_success 'git branch -M should leave orphaned HEAD
+ git symbolic-ref HEAD >expect &&
+ echo refs/heads/lonely >actual &&
+ test_cmp expect actual &&
- test_path_is_missing .git/refs/head/lonely &&
+ test_ref_missing refs/head/lonely &&
git branch -M main mistress &&
- grep lonely .git/HEAD
+ git symbolic-ref HEAD >expect &&
@@ t/t3200-branch.sh: test_expect_success 'deleting a symref' '
+ git symbolic-ref --no-recurse refs/heads/dangling-symref &&
echo "Deleted branch dangling-symref (was nowhere)." >expect &&
git branch -d dangling-symref >actual &&
- test_path_is_missing .git/refs/heads/dangling-symref &&
+ test_ref_missing refs/heads/dangling-symref &&
## t/t4013-diff-various.sh ##
@@ t/t4013-diff-various.sh: test_expect_success 'log -S requires an argument' '
4: 5e7937e7904 ! 4: fdf67689227 t: convert tests to not access reflog via the filesystem
@@ t/t3200-branch.sh: test_expect_success 'git branch HEAD should fail' '
test_expect_success 'git branch --create-reflog d/e/f should create a branch and a log' '
GIT_COMMITTER_DATE="2005-05-26 23:30" \
git -c core.logallrefupdates=false branch --create-reflog d/e/f &&
- test_path_is_file .git/refs/heads/d/e/f &&
+ test_ref_exists refs/heads/d/e/f &&
- test_path_is_file .git/logs/refs/heads/d/e/f &&
- test_cmp expect .git/logs/refs/heads/d/e/f
+ git reflog show --no-abbrev-commit refs/heads/d/e/f >actual &&
@@ t/t3200-branch.sh: test_expect_success '--set-upstream-to notices an error to se
test_expect_success 'git checkout -b g/h/i -l should create a branch and a log' '
GIT_COMMITTER_DATE="2005-05-26 23:30" \
git checkout -b g/h/i -l main &&
- test_path_is_file .git/refs/heads/g/h/i &&
+ test_ref_exists refs/heads/g/h/i &&
- test_path_is_file .git/logs/refs/heads/g/h/i &&
- test_cmp expect .git/logs/refs/heads/g/h/i
+ git reflog show --no-abbrev-commit refs/heads/g/h/i >actual &&
5: 089565a358e = 5: a5d55b68828 t1450: convert tests to remove worktrees via git-worktree(1)
6: cb738888ed7 = 6: 3213d45b537 t4207: delete replace references via git-update-ref(1)
7: e730e011de4 = 7: 36e79f266c2 t7300: assert exact states of repo
8: a1bdea52397 = 8: 4af0dc00165 t7900: assert the absence of refs via git-for-each-ref(1)
9: 497e43ae5c3 ! 9: 9fc039a1764 t: mark several tests that assume the files backend with REFFILES
@@ t/t2011-checkout-invalid-head.sh: test_expect_success 'create ref directory/file
## t/t3200-branch.sh ##
@@ t/t3200-branch.sh: test_expect_success 'git branch --help should not have created a bogus branch' '
- test_path_is_missing .git/refs/heads/--help
+ test_ref_missing refs/heads/--help
'
-test_expect_success 'branch -h in broken repository' '
@@ t/t3200-branch.sh: test_expect_success 'git branch -M baz bam should succeed whe
git worktree add -f bazdir2 baz &&
touch .git/worktrees/bazdir1/HEAD.lock &&
@@ t/t3200-branch.sh: test_expect_success 'renaming a symref is not allowed' '
- test_path_is_missing .git/refs/heads/new-topic
+ test_ref_missing refs/heads/new-topic
'
-test_expect_success SYMLINKS 'git branch -m u v should fail when the reflog for u is a symlink' '
base-commit: 0497e6c61172faabf412e013f2fc30a05054a46d
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH v3 2/9] t: convert tests to not write references via the filesystem
From: Patrick Steinhardt @ 2023-11-02 8:46 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1698914571.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 9376 bytes --]
Some of our tests manually create, update or delete references by
writing the respective new values into the filesystem directly. While
this works with the current files reference backend, this will break
once we have a second reference backend implementation in our codebase.
Refactor these tests to instead use git-update-ref(1) or our `ref-store`
test tool. The latter is required in some cases where safety checks of
git-update-ref(1) would otherwise reject a reference update.
While at it, refactor some of the tests to schedule the cleanup command
via `test_when_finished` before modifying the repository.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/t1400-update-ref.sh | 17 ++++++++---------
t/t1450-fsck.sh | 26 +++++++++++++-------------
t/t3404-rebase-interactive.sh | 2 +-
t/t5526-fetch-submodules.sh | 2 +-
4 files changed, 23 insertions(+), 24 deletions(-)
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 4d66cd7f4a1..91cc6dff724 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -9,8 +9,6 @@ test_description='Test git update-ref and basic ref logging'
Z=$ZERO_OID
m=refs/heads/main
-n_dir=refs/heads/gu
-n=$n_dir/fixes
outside=refs/foo
bare=bare-repo
@@ -62,10 +60,10 @@ test_expect_success "delete $m without oldvalue verification" '
test_must_fail git show-ref --verify -q $m
'
-test_expect_success "fail to create $n" '
- test_when_finished "rm -f .git/$n_dir" &&
- touch .git/$n_dir &&
- test_must_fail git update-ref $n $A
+test_expect_success "fail to create $n due to file/directory conflict" '
+ test_when_finished "git update-ref -d refs/heads/gu" &&
+ git update-ref refs/heads/gu $A &&
+ test_must_fail git update-ref refs/heads/gu/fixes $A
'
test_expect_success "create $m (by HEAD)" '
@@ -221,16 +219,16 @@ test_expect_success 'delete symref without dereference when the referred ref is
'
test_expect_success 'update-ref -d is not confused by self-reference' '
+ test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF refs/heads/self" &&
git symbolic-ref refs/heads/self refs/heads/self &&
- test_when_finished "rm -f .git/refs/heads/self" &&
test_path_is_file .git/refs/heads/self &&
test_must_fail git update-ref -d refs/heads/self &&
test_path_is_file .git/refs/heads/self
'
test_expect_success 'update-ref --no-deref -d can delete self-reference' '
+ test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF refs/heads/self" &&
git symbolic-ref refs/heads/self refs/heads/self &&
- test_when_finished "rm -f .git/refs/heads/self" &&
test_path_is_file .git/refs/heads/self &&
git update-ref --no-deref -d refs/heads/self &&
test_must_fail git show-ref --verify -q refs/heads/self
@@ -434,7 +432,8 @@ test_expect_success 'Query "main@{2005-05-28}" (past end of history)' '
test_i18ngrep -F "warning: log for ref $m unexpectedly ended on $ld" e
'
-rm -f .git/$m .git/logs/$m expect
+rm -f expect
+git update-ref -d $m
test_expect_success 'creating initial files' '
test_when_finished rm -f M &&
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 10a539158c4..f55b539b083 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -15,6 +15,7 @@ test_expect_success setup '
git config --unset i18n.commitencoding &&
git checkout HEAD^0 &&
test_commit B fileB two &&
+ orig_head=$(git rev-parse HEAD) &&
git tag -d A B &&
git reflog expire --expire=now --all
'
@@ -115,15 +116,15 @@ test_expect_success 'zlib corrupt loose object output ' '
'
test_expect_success 'branch pointing to non-commit' '
- git rev-parse HEAD^{tree} >.git/refs/heads/invalid &&
+ tree_oid=$(git rev-parse --verify HEAD^{tree}) &&
test_when_finished "git update-ref -d refs/heads/invalid" &&
+ test-tool ref-store main update-ref msg refs/heads/invalid $tree_oid $ZERO_OID REF_SKIP_OID_VERIFICATION &&
test_must_fail git fsck 2>out &&
test_i18ngrep "not a commit" out
'
test_expect_success 'HEAD link pointing at a funny object' '
- test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
- mv .git/HEAD .git/SAVED_HEAD &&
+ test_when_finished "git update-ref HEAD $orig_head" &&
echo $ZERO_OID >.git/HEAD &&
# avoid corrupt/broken HEAD from interfering with repo discovery
test_must_fail env GIT_DIR=.git git fsck 2>out &&
@@ -131,8 +132,7 @@ test_expect_success 'HEAD link pointing at a funny object' '
'
test_expect_success 'HEAD link pointing at a funny place' '
- test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
- mv .git/HEAD .git/SAVED_HEAD &&
+ test_when_finished "git update-ref --no-deref HEAD $orig_head" &&
echo "ref: refs/funny/place" >.git/HEAD &&
# avoid corrupt/broken HEAD from interfering with repo discovery
test_must_fail env GIT_DIR=.git git fsck 2>out &&
@@ -140,10 +140,9 @@ test_expect_success 'HEAD link pointing at a funny place' '
'
test_expect_success 'HEAD link pointing at a funny object (from different wt)' '
- test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
+ test_when_finished "git update-ref HEAD $orig_head" &&
test_when_finished "rm -rf .git/worktrees wt" &&
git worktree add wt &&
- mv .git/HEAD .git/SAVED_HEAD &&
echo $ZERO_OID >.git/HEAD &&
# avoid corrupt/broken HEAD from interfering with repo discovery
test_must_fail git -C wt fsck 2>out &&
@@ -161,7 +160,8 @@ test_expect_success 'other worktree HEAD link pointing at a funny object' '
test_expect_success 'other worktree HEAD link pointing at missing object' '
test_when_finished "rm -rf .git/worktrees other" &&
git worktree add other &&
- echo "Contents missing from repo" | git hash-object --stdin >.git/worktrees/other/HEAD &&
+ object_id=$(echo "Contents missing from repo" | git hash-object --stdin) &&
+ test-tool -C other ref-store main update-ref msg HEAD $object_id "" REF_NO_DEREF,REF_SKIP_OID_VERIFICATION &&
test_must_fail git fsck 2>out &&
test_i18ngrep "worktrees/other/HEAD: invalid sha1 pointer" out
'
@@ -391,7 +391,7 @@ test_expect_success 'tag pointing to nonexistent' '
tag=$(git hash-object -t tag -w --stdin <invalid-tag) &&
test_when_finished "remove_object $tag" &&
- echo $tag >.git/refs/tags/invalid &&
+ git update-ref refs/tags/invalid $tag &&
test_when_finished "git update-ref -d refs/tags/invalid" &&
test_must_fail git fsck --tags >out &&
test_i18ngrep "broken link" out
@@ -411,7 +411,7 @@ test_expect_success 'tag pointing to something else than its type' '
tag=$(git hash-object -t tag -w --stdin <wrong-tag) &&
test_when_finished "remove_object $tag" &&
- echo $tag >.git/refs/tags/wrong &&
+ git update-ref refs/tags/wrong $tag &&
test_when_finished "git update-ref -d refs/tags/wrong" &&
test_must_fail git fsck --tags
'
@@ -428,7 +428,7 @@ test_expect_success 'tag with incorrect tag name & missing tagger' '
tag=$(git hash-object --literally -t tag -w --stdin <wrong-tag) &&
test_when_finished "remove_object $tag" &&
- echo $tag >.git/refs/tags/wrong &&
+ git update-ref refs/tags/wrong $tag &&
test_when_finished "git update-ref -d refs/tags/wrong" &&
git fsck --tags 2>out &&
@@ -452,7 +452,7 @@ test_expect_success 'tag with bad tagger' '
tag=$(git hash-object --literally -t tag -w --stdin <wrong-tag) &&
test_when_finished "remove_object $tag" &&
- echo $tag >.git/refs/tags/wrong &&
+ git update-ref refs/tags/wrong $tag &&
test_when_finished "git update-ref -d refs/tags/wrong" &&
test_must_fail git fsck --tags 2>out &&
test_i18ngrep "error in tag .*: invalid author/committer" out
@@ -471,7 +471,7 @@ test_expect_success 'tag with NUL in header' '
tag=$(git hash-object --literally -t tag -w --stdin <tag-NUL-header) &&
test_when_finished "remove_object $tag" &&
- echo $tag >.git/refs/tags/wrong &&
+ git update-ref refs/tags/wrong $tag &&
test_when_finished "git update-ref -d refs/tags/wrong" &&
test_must_fail git fsck --tags 2>out &&
test_i18ngrep "error in tag $tag.*unterminated header: NUL at offset" out
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 8ea2bf13026..d2a7a91f170 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -2160,7 +2160,7 @@ test_expect_success '--update-refs: check failed ref update' '
# recorded in the update-refs file. We will force-update the
# "second" ref, but "git branch -f" will not work because of
# the lock in the update-refs file.
- git rev-parse third >.git/refs/heads/second &&
+ git update-ref refs/heads/second third &&
test_must_fail git rebase --continue 2>err &&
grep "update_ref failed for ref '\''refs/heads/second'\''" err &&
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index 26e933f93ae..7ab220fa313 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -771,7 +771,7 @@ test_expect_success 'fetching submodule into a broken repository' '
git -C dst fetch --recurse-submodules &&
# Break the receiving submodule
- rm -f dst/sub/.git/HEAD &&
+ test-tool -C dst/sub ref-store main delete-refs REF_NO_DEREF msg HEAD &&
# NOTE: without the fix the following tests will recurse forever!
# They should terminate with an error.
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v3 3/9] t: convert tests to not access symrefs via the filesystem
From: Patrick Steinhardt @ 2023-11-02 8:46 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1698914571.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 13670 bytes --]
Some of our tests access symbolic references via the filesystem
directly. While this works with the current files reference backend, it
this will break once we have a second reference backend in our codebase.
Refactor these tests to instead use git-symbolic-ref(1) or our
`ref-store` test tool. The latter is required in some cases where safety
checks of git-symbolic-ref(1) would otherwise reject writing a symbolic
reference.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/t1400-update-ref.sh | 8 ++++----
t/t1430-bad-ref-name.sh | 12 ++++++------
t/t1450-fsck.sh | 4 ++--
t/t3200-branch.sh | 9 ++++++---
t/t4013-diff-various.sh | 2 +-
t/t4202-log.sh | 2 +-
t/t5605-clone-local.sh | 2 +-
t/t5702-protocol-v2.sh | 24 ++++++++++++++++++------
t/t9133-git-svn-nested-git-repo.sh | 2 +-
9 files changed, 40 insertions(+), 25 deletions(-)
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 91cc6dff724..51a8d0bba98 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -221,15 +221,15 @@ test_expect_success 'delete symref without dereference when the referred ref is
test_expect_success 'update-ref -d is not confused by self-reference' '
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF refs/heads/self" &&
git symbolic-ref refs/heads/self refs/heads/self &&
- test_path_is_file .git/refs/heads/self &&
+ git symbolic-ref --no-recurse refs/heads/self &&
test_must_fail git update-ref -d refs/heads/self &&
- test_path_is_file .git/refs/heads/self
+ git symbolic-ref --no-recurse refs/heads/self
'
test_expect_success 'update-ref --no-deref -d can delete self-reference' '
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF refs/heads/self" &&
git symbolic-ref refs/heads/self refs/heads/self &&
- test_path_is_file .git/refs/heads/self &&
+ git symbolic-ref --no-recurse refs/heads/self &&
git update-ref --no-deref -d refs/heads/self &&
test_must_fail git show-ref --verify -q refs/heads/self
'
@@ -239,7 +239,7 @@ test_expect_success 'update-ref --no-deref -d can delete reference to bad ref' '
test_when_finished "rm -f .git/refs/heads/bad" &&
git symbolic-ref refs/heads/ref-to-bad refs/heads/bad &&
test_when_finished "git update-ref -d refs/heads/ref-to-bad" &&
- test_path_is_file .git/refs/heads/ref-to-bad &&
+ git symbolic-ref --no-recurse refs/heads/ref-to-bad &&
git update-ref --no-deref -d refs/heads/ref-to-bad &&
test_must_fail git show-ref --verify -q refs/heads/ref-to-bad
'
diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh
index 7b7d6953c62..5debb91f7b7 100755
--- a/t/t1430-bad-ref-name.sh
+++ b/t/t1430-bad-ref-name.sh
@@ -164,9 +164,9 @@ test_expect_success 'rev-parse skips symref pointing to broken name' '
test_expect_success 'for-each-ref emits warnings for broken names' '
test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" &&
- printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname &&
+ test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" &&
- printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref &&
+ test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/main &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" &&
git for-each-ref >output 2>error &&
! grep -e "broken\.\.\.ref" output &&
@@ -257,7 +257,7 @@ test_expect_success 'update-ref -d can delete broken name through symref' '
'
test_expect_success 'update-ref --no-deref -d can delete symref with broken name' '
- printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref &&
+ test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/main &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" &&
test_ref_exists refs/heads/broken...symref &&
git update-ref --no-deref -d refs/heads/broken...symref >output 2>error &&
@@ -267,7 +267,7 @@ test_expect_success 'update-ref --no-deref -d can delete symref with broken name
'
test_expect_success 'branch -d can delete symref with broken name' '
- printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref &&
+ test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/main &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" &&
test_ref_exists refs/heads/broken...symref &&
git branch -d broken...symref >output 2>error &&
@@ -277,7 +277,7 @@ test_expect_success 'branch -d can delete symref with broken name' '
'
test_expect_success 'update-ref --no-deref -d can delete dangling symref with broken name' '
- printf "ref: refs/heads/idonotexist\n" >.git/refs/heads/broken...symref &&
+ test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/idonotexist &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" &&
test_ref_exists refs/heads/broken...symref &&
git update-ref --no-deref -d refs/heads/broken...symref >output 2>error &&
@@ -287,7 +287,7 @@ test_expect_success 'update-ref --no-deref -d can delete dangling symref with br
'
test_expect_success 'branch -d can delete dangling symref with broken name' '
- printf "ref: refs/heads/idonotexist\n" >.git/refs/heads/broken...symref &&
+ test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/idonotexist &&
test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" &&
test_ref_exists refs/heads/broken...symref &&
git branch -d broken...symref >output 2>error &&
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index f55b539b083..a3c97b9c7fc 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -133,7 +133,7 @@ test_expect_success 'HEAD link pointing at a funny object' '
test_expect_success 'HEAD link pointing at a funny place' '
test_when_finished "git update-ref --no-deref HEAD $orig_head" &&
- echo "ref: refs/funny/place" >.git/HEAD &&
+ test-tool ref-store main create-symref HEAD refs/funny/place &&
# avoid corrupt/broken HEAD from interfering with repo discovery
test_must_fail env GIT_DIR=.git git fsck 2>out &&
test_i18ngrep "HEAD points to something strange" out
@@ -169,7 +169,7 @@ test_expect_success 'other worktree HEAD link pointing at missing object' '
test_expect_success 'other worktree HEAD link pointing at a funny place' '
test_when_finished "rm -rf .git/worktrees other" &&
git worktree add other &&
- echo "ref: refs/funny/place" >.git/worktrees/other/HEAD &&
+ git -C other symbolic-ref HEAD refs/funny/place &&
test_must_fail git fsck 2>out &&
test_i18ngrep "worktrees/other/HEAD points to something strange" out
'
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index bde4f1485b7..874520e3f10 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -215,10 +215,13 @@ test_expect_success 'git branch -M should leave orphaned HEAD alone' '
cd orphan &&
test_commit initial &&
git checkout --orphan lonely &&
- grep lonely .git/HEAD &&
+ git symbolic-ref HEAD >expect &&
+ echo refs/heads/lonely >actual &&
+ test_cmp expect actual &&
test_ref_missing refs/head/lonely &&
git branch -M main mistress &&
- grep lonely .git/HEAD
+ git symbolic-ref HEAD >expect &&
+ test_cmp expect actual
)
'
@@ -809,7 +812,7 @@ test_expect_success 'deleting a symref' '
test_expect_success 'deleting a dangling symref' '
git symbolic-ref refs/heads/dangling-symref nowhere &&
- test_path_is_file .git/refs/heads/dangling-symref &&
+ git symbolic-ref --no-recurse refs/heads/dangling-symref &&
echo "Deleted branch dangling-symref (was nowhere)." >expect &&
git branch -d dangling-symref >actual &&
test_ref_missing refs/heads/dangling-symref &&
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 4b474808311..fc8a0588acc 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -522,7 +522,7 @@ test_expect_success 'log -S requires an argument' '
'
test_expect_success 'diff --cached on unborn branch' '
- echo ref: refs/heads/unborn >.git/HEAD &&
+ git symbolic-ref HEAD refs/heads/unborn &&
git diff --cached >result &&
process_diffs result >actual &&
process_diffs "$TEST_DIRECTORY/t4013/diff.diff_--cached" >expected &&
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index af4a123cd22..57b298a4e22 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -2265,7 +2265,7 @@ test_expect_success REFFILES 'log diagnoses bogus HEAD hash' '
test_expect_success REFFILES 'log diagnoses bogus HEAD symref' '
git init empty &&
- echo "ref: refs/heads/invalid.lock" > empty/.git/HEAD &&
+ test-tool -C empty ref-store main create-symref HEAD refs/heads/invalid.lock &&
test_must_fail git -C empty log 2>stderr &&
test_i18ngrep broken stderr &&
test_must_fail git -C empty log --default totally-bogus 2>stderr &&
diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh
index 946c5751885..bedd29d0550 100755
--- a/t/t5605-clone-local.sh
+++ b/t/t5605-clone-local.sh
@@ -65,7 +65,7 @@ test_expect_success 'Even without -l, local will make a hardlink' '
'
test_expect_success 'local clone of repo with nonexistent ref in HEAD' '
- echo "ref: refs/heads/nonexistent" > a.git/HEAD &&
+ git -C a.git symbolic-ref HEAD refs/heads/nonexistent &&
git clone a d &&
(cd d &&
git fetch &&
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 6af5c2062fd..dcc4cd95fe7 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -221,7 +221,9 @@ test_expect_success 'clone of empty repo propagates name of default branch' '
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \
git -c init.defaultBranch=main -c protocol.version=2 \
clone "file://$(pwd)/file_empty_parent" file_empty_child &&
- grep "refs/heads/mydefaultbranch" file_empty_child/.git/HEAD
+ echo refs/heads/mydefaultbranch >expect &&
+ git -C file_empty_child symbolic-ref HEAD >actual &&
+ test_cmp expect actual
'
test_expect_success '...but not if explicitly forbidden by config' '
@@ -234,7 +236,9 @@ test_expect_success '...but not if explicitly forbidden by config' '
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \
git -c init.defaultBranch=main -c protocol.version=2 \
clone "file://$(pwd)/file_empty_parent" file_empty_child &&
- ! grep "refs/heads/mydefaultbranch" file_empty_child/.git/HEAD
+ echo refs/heads/main >expect &&
+ git -C file_empty_child symbolic-ref HEAD >actual &&
+ test_cmp expect actual
'
test_expect_success 'bare clone propagates empty default branch' '
@@ -247,7 +251,9 @@ test_expect_success 'bare clone propagates empty default branch' '
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
+ echo "refs/heads/mydefaultbranch" >expect &&
+ git -C file_empty_child.git symbolic-ref HEAD >actual &&
+ test_cmp expect actual
'
test_expect_success 'clone propagates unborn HEAD from non-empty repo' '
@@ -265,7 +271,9 @@ test_expect_success 'clone propagates unborn HEAD from non-empty repo' '
git -c init.defaultBranch=main -c protocol.version=2 \
clone "file://$(pwd)/file_unborn_parent" \
file_unborn_child 2>stderr &&
- grep "refs/heads/mydefaultbranch" file_unborn_child/.git/HEAD &&
+ echo "refs/heads/mydefaultbranch" >expect &&
+ git -C file_unborn_child symbolic-ref HEAD >actual &&
+ test_cmp expect actual &&
grep "warning: remote HEAD refers to nonexistent ref" stderr
'
@@ -295,7 +303,9 @@ test_expect_success 'bare clone propagates unborn HEAD from non-empty repo' '
git -c init.defaultBranch=main -c protocol.version=2 \
clone --bare "file://$(pwd)/file_unborn_parent" \
file_unborn_child.git 2>stderr &&
- grep "refs/heads/mydefaultbranch" file_unborn_child.git/HEAD &&
+ echo "refs/heads/mydefaultbranch" >expect &&
+ git -C file_unborn_child.git symbolic-ref HEAD >actual &&
+ test_cmp expect actual &&
! grep "warning:" stderr
'
@@ -315,7 +325,9 @@ test_expect_success 'defaulted HEAD uses remote branch if available' '
git -c init.defaultBranch=branchwithstuff -c protocol.version=2 \
clone "file://$(pwd)/file_unborn_parent" \
file_unborn_child 2>stderr &&
- grep "refs/heads/branchwithstuff" file_unborn_child/.git/HEAD &&
+ echo "refs/heads/branchwithstuff" >expect &&
+ git -C file_unborn_child symbolic-ref HEAD >actual &&
+ test_cmp expect actual &&
test_path_is_file file_unborn_child/stuff.t &&
! grep "warning:" stderr
'
diff --git a/t/t9133-git-svn-nested-git-repo.sh b/t/t9133-git-svn-nested-git-repo.sh
index d8d536269cf..8ca24670acb 100755
--- a/t/t9133-git-svn-nested-git-repo.sh
+++ b/t/t9133-git-svn-nested-git-repo.sh
@@ -11,7 +11,7 @@ test_expect_success 'setup repo with a git repo inside it' '
(
cd s &&
git init &&
- test -f .git/HEAD &&
+ git symbolic-ref HEAD &&
> .git/a &&
echo a > a &&
svn_cmd add .git a &&
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v3 4/9] t: convert tests to not access reflog via the filesystem
From: Patrick Steinhardt @ 2023-11-02 8:46 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1698914571.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 7125 bytes --]
Some of our tests reach directly into the filesystem in order to both
read or modify the reflog, which will break once we have a second
reference backend in our codebase that stores reflogs differently.
Refactor these tests to either use git-reflog(1) or the ref-store test
helper. Note that the refactoring to use git-reflog(1) also requires us
to adapt our expectations in some cases where we previously verified the
exact on-disk log entries. This seems like an acceptable tradeoff though
to ensure that different backends have the same user-visible behaviour
as any user would typically use git-reflog(1) anyway to access the logs.
Any backend-specific verification of the written on-disk format should
be implemented in a separate, backend-specific test.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/t1400-update-ref.sh | 17 +++++++++++------
t/t3200-branch.sh | 24 ++++++++++++------------
2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 51a8d0bba98..b7d1e5deede 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -90,7 +90,8 @@ test_expect_success "deleting current branch adds message to HEAD's log" '
git symbolic-ref HEAD $m &&
git update-ref -m delete-$m -d $m &&
test_must_fail git show-ref --verify -q $m &&
- grep "delete-$m$" .git/logs/HEAD
+ test-tool ref-store main for-each-reflog-ent HEAD >actual &&
+ grep "delete-$m$" actual
'
test_expect_success "deleting by HEAD adds message to HEAD's log" '
@@ -99,7 +100,8 @@ test_expect_success "deleting by HEAD adds message to HEAD's log" '
git symbolic-ref HEAD $m &&
git update-ref -m delete-by-head -d HEAD &&
test_must_fail git show-ref --verify -q $m &&
- grep "delete-by-head$" .git/logs/HEAD
+ test-tool ref-store main for-each-reflog-ent HEAD >actual &&
+ grep "delete-by-head$" actual
'
test_expect_success 'update-ref does not create reflogs by default' '
@@ -130,7 +132,7 @@ test_expect_success 'creates no reflog in bare repository' '
test_expect_success 'core.logAllRefUpdates=true creates reflog in bare repository' '
test_when_finished "git -C $bare config --unset core.logAllRefUpdates && \
- rm $bare/logs/$m" &&
+ test-tool ref-store main delete-reflog $m" &&
git -C $bare config core.logAllRefUpdates true &&
git -C $bare update-ref $m $bareB &&
git -C $bare rev-parse $bareB >expect &&
@@ -263,7 +265,10 @@ test_expect_success "(not) changed .git/$m" '
! test $B = $(git show-ref -s --verify $m)
'
-rm -f .git/logs/refs/heads/main
+test_expect_success "clean up reflog" '
+ test-tool ref-store main delete-reflog $m
+'
+
test_expect_success "create $m (logged by touch)" '
test_config core.logAllRefUpdates false &&
GIT_COMMITTER_DATE="2005-05-26 23:30" \
@@ -316,7 +321,7 @@ $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150260 +0000 Switch
$B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150860 +0000
EOF
test_expect_success "verifying $m's log (logged by touch)" '
- test_when_finished "git update-ref -d $m && rm -rf .git/logs actual expect" &&
+ test_when_finished "git update-ref -d $m && git reflog expire --expire=all --all && rm -rf actual expect" &&
test-tool ref-store main for-each-reflog-ent $m >actual &&
test_cmp actual expect
'
@@ -346,7 +351,7 @@ $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 +0000 Switch
$B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 +0000
EOF
test_expect_success "verifying $m's log (logged by config)" '
- test_when_finished "git update-ref -d $m && rm -rf .git/logs actual expect" &&
+ test_when_finished "git update-ref -d $m && git reflog expire --expire=all --all && rm -rf actual expect" &&
test-tool ref-store main for-each-reflog-ent $m >actual &&
test_cmp actual expect
'
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 874520e3f10..933aa9eebbd 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -76,14 +76,14 @@ test_expect_success 'git branch HEAD should fail' '
'
cat >expect <<EOF
-$ZERO_OID $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from main
+$HEAD refs/heads/d/e/f@{0}: branch: Created from main
EOF
test_expect_success 'git branch --create-reflog d/e/f should create a branch and a log' '
GIT_COMMITTER_DATE="2005-05-26 23:30" \
git -c core.logallrefupdates=false branch --create-reflog d/e/f &&
test_ref_exists refs/heads/d/e/f &&
- test_path_is_file .git/logs/refs/heads/d/e/f &&
- test_cmp expect .git/logs/refs/heads/d/e/f
+ git reflog show --no-abbrev-commit refs/heads/d/e/f >actual &&
+ test_cmp expect actual
'
test_expect_success 'git branch -d d/e/f should delete a branch and a log' '
@@ -203,10 +203,9 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou
test $(git rev-parse --abbrev-ref HEAD) = bam
'
-test_expect_success 'git branch -M baz bam should add entries to .git/logs/HEAD' '
- msg="Branch: renamed refs/heads/baz to refs/heads/bam" &&
- grep " $ZERO_OID.*$msg$" .git/logs/HEAD &&
- grep "^$ZERO_OID.*$msg$" .git/logs/HEAD
+test_expect_success 'git branch -M baz bam should add entries to HEAD reflog' '
+ git reflog show HEAD >actual &&
+ grep "HEAD@{0}: Branch: renamed refs/heads/baz to refs/heads/bam" actual
'
test_expect_success 'git branch -M should leave orphaned HEAD alone' '
@@ -228,7 +227,7 @@ test_expect_success 'git branch -M should leave orphaned HEAD alone' '
test_expect_success 'resulting reflog can be shown by log -g' '
oid=$(git rev-parse HEAD) &&
cat >expect <<-EOF &&
- HEAD@{0} $oid $msg
+ HEAD@{0} $oid Branch: renamed refs/heads/baz to refs/heads/bam
HEAD@{2} $oid checkout: moving from foo to baz
EOF
git log -g --format="%gd %H %gs" -2 HEAD >actual &&
@@ -702,7 +701,8 @@ test_expect_success 'git branch -C c1 c2 should succeed when c1 is checked out'
test_expect_success 'git branch -C c1 c2 should never touch HEAD' '
msg="Branch: copied refs/heads/c1 to refs/heads/c2" &&
- ! grep "$msg$" .git/logs/HEAD
+ git reflog HEAD >actual &&
+ ! grep "$msg$" actual
'
test_expect_success 'git branch -C main should work when main is checked out' '
@@ -1143,14 +1143,14 @@ test_expect_success '--set-upstream-to notices an error to set branch as own ups
# Keep this test last, as it changes the current branch
cat >expect <<EOF
-$ZERO_OID $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from main
+$HEAD refs/heads/g/h/i@{0}: branch: Created from main
EOF
test_expect_success 'git checkout -b g/h/i -l should create a branch and a log' '
GIT_COMMITTER_DATE="2005-05-26 23:30" \
git checkout -b g/h/i -l main &&
test_ref_exists refs/heads/g/h/i &&
- test_path_is_file .git/logs/refs/heads/g/h/i &&
- test_cmp expect .git/logs/refs/heads/g/h/i
+ git reflog show --no-abbrev-commit refs/heads/g/h/i >actual &&
+ test_cmp expect actual
'
test_expect_success 'checkout -b makes reflog by default' '
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v3 5/9] t1450: convert tests to remove worktrees via git-worktree(1)
From: Patrick Steinhardt @ 2023-11-02 8:46 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1698914571.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 2516 bytes --]
Some of our tests in t1450 create worktrees and then corrupt them.
As it is impossible to delete such worktrees via a normal call to `git
worktree remove`, we instead opt to remove them manually by calling
rm(1) instead.
This is ultimately unnecessary though as we can use the `-f` switch to
remove the worktree. Let's convert the tests to do so such that we don't
have to reach into internal implementation details of worktrees.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/t1450-fsck.sh | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index a3c97b9c7fc..a6af550867c 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -141,7 +141,7 @@ test_expect_success 'HEAD link pointing at a funny place' '
test_expect_success 'HEAD link pointing at a funny object (from different wt)' '
test_when_finished "git update-ref HEAD $orig_head" &&
- test_when_finished "rm -rf .git/worktrees wt" &&
+ test_when_finished "git worktree remove -f wt" &&
git worktree add wt &&
echo $ZERO_OID >.git/HEAD &&
# avoid corrupt/broken HEAD from interfering with repo discovery
@@ -150,7 +150,7 @@ test_expect_success 'HEAD link pointing at a funny object (from different wt)' '
'
test_expect_success 'other worktree HEAD link pointing at a funny object' '
- test_when_finished "rm -rf .git/worktrees other" &&
+ test_when_finished "git worktree remove -f other" &&
git worktree add other &&
echo $ZERO_OID >.git/worktrees/other/HEAD &&
test_must_fail git fsck 2>out &&
@@ -158,7 +158,7 @@ test_expect_success 'other worktree HEAD link pointing at a funny object' '
'
test_expect_success 'other worktree HEAD link pointing at missing object' '
- test_when_finished "rm -rf .git/worktrees other" &&
+ test_when_finished "git worktree remove -f other" &&
git worktree add other &&
object_id=$(echo "Contents missing from repo" | git hash-object --stdin) &&
test-tool -C other ref-store main update-ref msg HEAD $object_id "" REF_NO_DEREF,REF_SKIP_OID_VERIFICATION &&
@@ -167,7 +167,7 @@ test_expect_success 'other worktree HEAD link pointing at missing object' '
'
test_expect_success 'other worktree HEAD link pointing at a funny place' '
- test_when_finished "rm -rf .git/worktrees other" &&
+ test_when_finished "git worktree remove -f other" &&
git worktree add other &&
git -C other symbolic-ref HEAD refs/funny/place &&
test_must_fail git fsck 2>out &&
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v3 6/9] t4207: delete replace references via git-update-ref(1)
From: Patrick Steinhardt @ 2023-11-02 8:47 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1698914571.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 1784 bytes --]
In t4207 we set up a set of replace objects via git-replace(1). Because
these references should not be impacting subsequent tests we also set up
some cleanup logic that deletes the replacement references via a call to
`rm -rf`. This reaches into the internal implementation details of the
reference backend and will thus break when we grow an alternative refdb
implementation.
Refactor the tests to delete the replacement refs via Git commands so
that we become independent of the actual refdb that's in use. As we
don't have a nice way to delete all replacements or all references in a
certain namespace, we opt for a combination of git-for-each-ref(1) and
git-update-ref(1)'s `--stdin` mode.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/t4207-log-decoration-colors.sh | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh
index 21986a866df..73ea9e51550 100755
--- a/t/t4207-log-decoration-colors.sh
+++ b/t/t4207-log-decoration-colors.sh
@@ -70,8 +70,14 @@ ${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
cmp_filtered_decorations
'
+remove_replace_refs () {
+ git for-each-ref 'refs/replace*/**' --format='delete %(refname)' >in &&
+ git update-ref --stdin <in &&
+ rm in
+}
+
test_expect_success 'test coloring with replace-objects' '
- test_when_finished rm -rf .git/refs/replace* &&
+ test_when_finished remove_replace_refs &&
test_commit C &&
test_commit D &&
@@ -99,7 +105,7 @@ EOF
'
test_expect_success 'test coloring with grafted commit' '
- test_when_finished rm -rf .git/refs/replace* &&
+ test_when_finished remove_replace_refs &&
git replace --graft HEAD HEAD~2 &&
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v3 7/9] t7300: assert exact states of repo
From: Patrick Steinhardt @ 2023-11-02 8:47 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1698914571.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 2913 bytes --]
Some of the tests in t7300 verify that git-clean(1) doesn't touch
repositories that are embedded into the main repository. This is done by
asserting a small set of substructures that are assumed to always exist,
like the "refs/", "objects/" or "HEAD". This has the downside that we
need to assume a specific repository structure that may be subject to
change when new backends for the refdb land. At the same time, we don't
thoroughly assert that git-clean(1) really didn't end up cleaning any
files in the repository either.
Convert the tests to instead assert that all files continue to exist
after git-clean(1) by comparing a file listing via find(1) before and
after executing clean. This makes our actual assertions stricter while
having to care less about the repository's actual on-disk format.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/t7300-clean.sh | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 0ef7b784573..d7d9202f37f 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -517,8 +517,12 @@ test_expect_success 'nested (empty) git should be kept' '
git init empty_repo &&
mkdir to_clean &&
>to_clean/should_clean.this &&
+ # Note that we put the expect file in the .git directory so that it
+ # does not get cleaned.
+ find empty_repo | sort >.git/expect &&
git clean -f -d &&
- test_path_is_file empty_repo/.git/HEAD &&
+ find empty_repo | sort >actual &&
+ test_cmp .git/expect actual &&
test_path_is_missing to_clean
'
@@ -559,10 +563,10 @@ test_expect_success 'giving path in nested git work tree will NOT remove it' '
mkdir -p bar/baz &&
test_commit msg bar/baz/hello.world
) &&
+ find repo | sort >expect &&
git clean -f -d repo/bar/baz &&
- test_path_is_file repo/.git/HEAD &&
- test_path_is_dir repo/bar/ &&
- test_path_is_file repo/bar/baz/hello.world
+ find repo | sort >actual &&
+ test_cmp expect actual
'
test_expect_success 'giving path to nested .git will not remove it' '
@@ -573,10 +577,10 @@ test_expect_success 'giving path to nested .git will not remove it' '
git init &&
test_commit msg hello.world
) &&
+ find repo | sort >expect &&
git clean -f -d repo/.git &&
- test_path_is_file repo/.git/HEAD &&
- test_path_is_dir repo/.git/refs &&
- test_path_is_dir repo/.git/objects &&
+ find repo | sort >actual &&
+ test_cmp expect actual &&
test_path_is_dir untracked/
'
@@ -588,9 +592,10 @@ test_expect_success 'giving path to nested .git/ will NOT remove contents' '
git init &&
test_commit msg hello.world
) &&
+ find repo | sort >expect &&
git clean -f -d repo/.git/ &&
- test_path_is_dir repo/.git &&
- test_path_is_file repo/.git/HEAD &&
+ find repo | sort >actual &&
+ test_cmp expect actual &&
test_path_is_dir untracked/
'
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v3 8/9] t7900: assert the absence of refs via git-for-each-ref(1)
From: Patrick Steinhardt @ 2023-11-02 8:47 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1698914571.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 1319 bytes --]
We're asserting that a prefetch of remotes via git-maintenance(1)
doesn't write any references in refs/remotes by validating that the
directory ".git/refs/remotes" is missing. This is quite roundabout: we
don't care about the directory existing, we care about the references
not existing, and the way these are stored is on the behest of the
reference database.
Convert the test to instead check via git-for-each-ref(1) whether any
remote reference exist.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/t7900-maintenance.sh | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index e56f5980dc4..cefecee732f 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -157,7 +157,8 @@ test_expect_success 'prefetch multiple remotes' '
fetchargs="--prefetch --prune --no-tags --no-write-fetch-head --recurse-submodules=no --quiet" &&
test_subcommand git fetch remote1 $fetchargs <run-prefetch.txt &&
test_subcommand git fetch remote2 $fetchargs <run-prefetch.txt &&
- test_path_is_missing .git/refs/remotes &&
+ git for-each-ref refs/remotes >actual &&
+ test_must_be_empty actual &&
git log prefetch/remotes/remote1/one &&
git log prefetch/remotes/remote2/two &&
git fetch --all &&
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v3 9/9] t: mark several tests that assume the files backend with REFFILES
From: Patrick Steinhardt @ 2023-11-02 8:47 UTC (permalink / raw)
To: git; +Cc: Han-Wen Nienhuys, Eric Sunshine, Taylor Blau, Junio C Hamano
In-Reply-To: <cover.1698914571.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 8909 bytes --]
Add the REFFILES prerequisite to several tests that assume we're using
the files backend. There are various reasons why we cannot easily
convert those tests to be backend-independent, where the most common
one is that we have no way to write corrupt references into the refdb
via our tooling. We may at a later point in time grow the tooling to
make this possible, but for now we just mark these tests as requiring
the files backend.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/t1400-update-ref.sh | 8 ++++----
t/t1450-fsck.sh | 6 +++---
t/t2011-checkout-invalid-head.sh | 16 ++++++++--------
t/t3200-branch.sh | 8 ++++----
t/t3400-rebase.sh | 2 +-
t/t5605-clone-local.sh | 2 +-
6 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index b7d1e5deede..70a760ba378 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -236,7 +236,7 @@ test_expect_success 'update-ref --no-deref -d can delete self-reference' '
test_must_fail git show-ref --verify -q refs/heads/self
'
-test_expect_success 'update-ref --no-deref -d can delete reference to bad ref' '
+test_expect_success REFFILES 'update-ref --no-deref -d can delete reference to bad ref' '
>.git/refs/heads/bad &&
test_when_finished "rm -f .git/refs/heads/bad" &&
git symbolic-ref refs/heads/ref-to-bad refs/heads/bad &&
@@ -288,7 +288,7 @@ test_expect_success "set $m (logged by touch)" '
test $A = $(git show-ref -s --verify $m)
'
-test_expect_success 'empty directory removal' '
+test_expect_success REFFILES 'empty directory removal' '
git branch d1/d2/r1 HEAD &&
git branch d1/r2 HEAD &&
test_path_is_file .git/refs/heads/d1/d2/r1 &&
@@ -300,7 +300,7 @@ test_expect_success 'empty directory removal' '
test_path_is_file .git/logs/refs/heads/d1/r2
'
-test_expect_success 'symref empty directory removal' '
+test_expect_success REFFILES 'symref empty directory removal' '
git branch e1/e2/r1 HEAD &&
git branch e1/r2 HEAD &&
git checkout e1/e2/r1 &&
@@ -1639,7 +1639,7 @@ test_expect_success PIPE 'transaction flushes status updates' '
test_cmp expected actual
'
-test_expect_success 'directory not created deleting packed ref' '
+test_expect_success REFFILES 'directory not created deleting packed ref' '
git branch d1/d2/r1 HEAD &&
git pack-refs --all &&
test_path_is_missing .git/refs/heads/d1/d2 &&
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index a6af550867c..50b15bd7fc0 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -123,7 +123,7 @@ test_expect_success 'branch pointing to non-commit' '
test_i18ngrep "not a commit" out
'
-test_expect_success 'HEAD link pointing at a funny object' '
+test_expect_success REFFILES 'HEAD link pointing at a funny object' '
test_when_finished "git update-ref HEAD $orig_head" &&
echo $ZERO_OID >.git/HEAD &&
# avoid corrupt/broken HEAD from interfering with repo discovery
@@ -139,7 +139,7 @@ test_expect_success 'HEAD link pointing at a funny place' '
test_i18ngrep "HEAD points to something strange" out
'
-test_expect_success 'HEAD link pointing at a funny object (from different wt)' '
+test_expect_success REFFILES 'HEAD link pointing at a funny object (from different wt)' '
test_when_finished "git update-ref HEAD $orig_head" &&
test_when_finished "git worktree remove -f wt" &&
git worktree add wt &&
@@ -149,7 +149,7 @@ test_expect_success 'HEAD link pointing at a funny object (from different wt)' '
test_i18ngrep "main-worktree/HEAD: detached HEAD points" out
'
-test_expect_success 'other worktree HEAD link pointing at a funny object' '
+test_expect_success REFFILES 'other worktree HEAD link pointing at a funny object' '
test_when_finished "git worktree remove -f other" &&
git worktree add other &&
echo $ZERO_OID >.git/worktrees/other/HEAD &&
diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh
index d9997e7b6b4..3c8135831b8 100755
--- a/t/t2011-checkout-invalid-head.sh
+++ b/t/t2011-checkout-invalid-head.sh
@@ -18,18 +18,18 @@ test_expect_success 'checkout should not start branch from a tree' '
test_must_fail git checkout -b newbranch main^{tree}
'
-test_expect_success 'checkout main from invalid HEAD' '
+test_expect_success REFFILES 'checkout main from invalid HEAD' '
echo $ZERO_OID >.git/HEAD &&
git checkout main --
'
-test_expect_success 'checkout notices failure to lock HEAD' '
+test_expect_success REFFILES 'checkout notices failure to lock HEAD' '
test_when_finished "rm -f .git/HEAD.lock" &&
>.git/HEAD.lock &&
test_must_fail git checkout -b other
'
-test_expect_success 'create ref directory/file conflict scenario' '
+test_expect_success REFFILES 'create ref directory/file conflict scenario' '
git update-ref refs/heads/outer/inner main &&
# do not rely on symbolic-ref to get a known state,
@@ -39,26 +39,26 @@ test_expect_success 'create ref directory/file conflict scenario' '
}
'
-test_expect_success 'checkout away from d/f HEAD (unpacked, to branch)' '
+test_expect_success REFFILES 'checkout away from d/f HEAD (unpacked, to branch)' '
reset_to_df &&
git checkout main
'
-test_expect_success 'checkout away from d/f HEAD (unpacked, to detached)' '
+test_expect_success REFFILES 'checkout away from d/f HEAD (unpacked, to detached)' '
reset_to_df &&
git checkout --detach main
'
-test_expect_success 'pack refs' '
+test_expect_success REFFILES 'pack refs' '
git pack-refs --all --prune
'
-test_expect_success 'checkout away from d/f HEAD (packed, to branch)' '
+test_expect_success REFFILES 'checkout away from d/f HEAD (packed, to branch)' '
reset_to_df &&
git checkout main
'
-test_expect_success 'checkout away from d/f HEAD (packed, to detached)' '
+test_expect_success REFFILES 'checkout away from d/f HEAD (packed, to detached)' '
reset_to_df &&
git checkout --detach main
'
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 933aa9eebbd..606c50fe66c 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -28,7 +28,7 @@ test_expect_success 'git branch --help should not have created a bogus branch' '
test_ref_missing refs/heads/--help
'
-test_expect_success 'branch -h in broken repository' '
+test_expect_success REFFILES 'branch -h in broken repository' '
mkdir broken &&
(
cd broken &&
@@ -245,7 +245,7 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou
git worktree prune
'
-test_expect_success 'git branch -M fails if updating any linked working tree fails' '
+test_expect_success REFFILES 'git branch -M fails if updating any linked working tree fails' '
git worktree add -b baz bazdir1 &&
git worktree add -f bazdir2 baz &&
touch .git/worktrees/bazdir1/HEAD.lock &&
@@ -836,14 +836,14 @@ test_expect_success 'renaming a symref is not allowed' '
test_ref_missing refs/heads/new-topic
'
-test_expect_success SYMLINKS 'git branch -m u v should fail when the reflog for u is a symlink' '
+test_expect_success SYMLINKS,REFFILES 'git branch -m u v should fail when the reflog for u is a symlink' '
git branch --create-reflog u &&
mv .git/logs/refs/heads/u real-u &&
ln -s real-u .git/logs/refs/heads/u &&
test_must_fail git branch -m u v
'
-test_expect_success SYMLINKS 'git branch -m with symlinked .git/refs' '
+test_expect_success SYMLINKS,REFFILES 'git branch -m with symlinked .git/refs' '
test_when_finished "rm -rf subdir" &&
git init --bare subdir &&
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index d3df19a51f8..435943a0891 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -424,7 +424,7 @@ test_expect_success 'refuse to switch to branch checked out elsewhere' '
test_i18ngrep "already used by worktree at" err
'
-test_expect_success MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' '
+test_expect_success REFFILES,MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' '
git checkout main &&
mv .git/logs actual_logs &&
cmd //c "mklink /D .git\logs ..\actual_logs" &&
diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh
index bedd29d0550..a3055869bc7 100755
--- a/t/t5605-clone-local.sh
+++ b/t/t5605-clone-local.sh
@@ -157,7 +157,7 @@ test_expect_success 'cloning locally respects "-u" for fetching refs' '
test_must_fail git clone --bare -u false a should_not_work.git
'
-test_expect_success 'local clone from repo with corrupt refs fails gracefully' '
+test_expect_success REFFILES 'local clone from repo with corrupt refs fails gracefully' '
git init corrupt &&
test_commit -C corrupt one &&
echo a >corrupt/.git/refs/heads/topic &&
--
2.42.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* Re: [PATCH v3 2/2] merge-file: add an option to process object IDs
From: Martin Ågren @ 2023-11-02 8:51 UTC (permalink / raw)
To: brian m. carlson
Cc: git, Junio C Hamano, Elijah Newren, Phillip Wood, Eric Sunshine,
Taylor Blau
In-Reply-To: <20231101192419.794162-3-sandals@crustytoothpaste.net>
On Wed, 1 Nov 2023 at 20:24, brian m. carlson
<sandals@crustytoothpaste.net> wrote:
>
> From: "brian m. carlson" <bk2204@github.com>
>
> git merge-file knows how to merge files on the file system already. It
> would be helpful, however, to allow it to also merge single blobs.
> Teach it an `--object-id` option which means that its arguments are
> object IDs and not files to allow it to do so.
>
> We handle the empty blob specially since read_mmblob doesn't read it
> directly and otherwise users cannot specify an empty ancestor.
>
> Signed-off-by: brian m. carlson <bk2204@github.com>
Ok, good solution to the misleading paragraph I noticed: dropping it.
> 'git merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
> [--ours|--theirs|--union] [-p|--stdout] [-q|--quiet] [--marker-size=<n>]
> - [--[no-]diff3] <current> <base> <other>
> + [--[no-]diff3] [--object-id] <current> <base> <other>
Ok. This is where rebasing onto the new, initial patch could possibly
have tripped up. Of course you didn't. Looks good.
Martin
^ permalink raw reply
* What's cooking in git.git (Nov 2023, #01; Thu, 2)
From: Junio C Hamano @ 2023-11-02 8:52 UTC (permalink / raw)
To: git
Here are the topics that have been cooking in my tree. Commits
prefixed with '+' are in 'next' (being in 'next' is a sign that a
topic is stable enough to be used and are candidate to be in a
future release). Commits prefixed with '-' are only in 'seen', and
aren't considered "accepted" at all and may be annotated with an URL
to a message that raises issues but they are no means exhaustive. A
topic without enough support may be discarded after a long period of
no activity (of course they can be resubmit when new interests
arise).
The preview release for 2.43 will be tagged and pushed out shortly.
Copies of the source code to Git live in many repositories, and the
following is a list of the ones I push into or their mirrors. Some
repositories have only a subset of branches.
With maint, master, next, seen, todo:
git://git.kernel.org/pub/scm/git/git.git/
git://repo.or.cz/alt-git.git/
https://kernel.googlesource.com/pub/scm/git/git/
https://github.com/git/git/
https://gitlab.com/git-vcs/git/
With all the integration branches and topics broken out:
https://github.com/gitster/git/
Even though the preformatted documentation in HTML and man format
are not sources, they are published in these repositories for
convenience (replace "htmldocs" with "manpages" for the manual
pages):
git://git.kernel.org/pub/scm/git/git-htmldocs.git/
https://github.com/gitster/git-htmldocs.git/
Release tarballs are available at:
https://www.kernel.org/pub/software/scm/git/
--------------------------------------------------
[New Topics]
* jc/strbuf-comment-line-char (2023-11-01) 4 commits
- strbuf: move env-using functions to environment.c
- strbuf: make add_lines() public
- strbuf_add_commented_lines(): drop the comment_line_char parameter
- strbuf_commented_addf(): drop the comment_line_char parameter
Code simplification.
source: <cover.1698791220.git.jonathantanmy@google.com>
* ps/show-ref (2023-11-01) 12 commits
(merged to 'next' on 2023-11-02 at 987bb117f5)
+ t: use git-show-ref(1) to check for ref existence
+ builtin/show-ref: add new mode to check for reference existence
+ builtin/show-ref: explicitly spell out different modes in synopsis
+ builtin/show-ref: ensure mutual exclusiveness of subcommands
+ builtin/show-ref: refactor options for patterns subcommand
+ builtin/show-ref: stop using global vars for `show_one()`
+ builtin/show-ref: stop using global variable to count matches
+ builtin/show-ref: refactor `--exclude-existing` options
+ builtin/show-ref: fix dead code when passing patterns
+ builtin/show-ref: fix leaking string buffer
+ builtin/show-ref: split up different subcommands
+ builtin/show-ref: convert pattern to a local variable
Teach "git show-ref" a mode to check the existence of a ref.
Will merge to 'master'.
source: <cover.1698739941.git.ps@pks.im>
* rc/trace-upload-pack (2023-10-30) 1 commit
(merged to 'next' on 2023-11-01 at 90892b5cf0)
+ upload-pack: add tracing for fetches
Trace2 update.
Will merge to 'master'.
source: <pull.1598.v2.git.1697577168128.gitgitgadget@gmail.com>
* bc/merge-file-object-input (2023-11-02) 2 commits
- merge-file: add an option to process object IDs
- git-merge-file doc: drop "-file" from argument placeholders
"git merge-file" learns a mode to read three contents to be merged
from blob objects.
Will merge to 'next'.
source: <20231101192419.794162-1-sandals@crustytoothpaste.net>
* jc/test-i18ngrep (2023-10-31) 2 commits
- tests: teach callers of test_i18ngrep to use test_grep
- test framework: further deprecate test_i18ngrep
Another step to deprecate test_i18ngrep.
Will merge to 'next'.
source: <20231031052330.3762989-1-gitster@pobox.com>
* an/clang-format-typofix (2023-11-01) 1 commit
(merged to 'next' on 2023-11-02 at 7f639690ab)
+ clang-format: fix typo in comment
Typofix.
Will merge to 'master'.
source: <pull.1602.v2.git.git.1698759629166.gitgitgadget@gmail.com>
* jk/tree-name-and-depth-limit (2023-11-02) 1 commit
- max_tree_depth: lower it for MSVC to avoid stack overflows
Further limit tree depth max to avoid Windows build running out of
the stack space.
Will merge to 'next' and then to 'master'.
source: <pull.1604.v2.git.1698843810814.gitgitgadget@gmail.com>
--------------------------------------------------
[Graduated to 'master']
* da/t7601-style-fix (2023-10-18) 1 commit
(merged to 'next' on 2023-10-20 at 8e7326458c)
+ t7601: use "test_path_is_file" etc. instead of "test -f"
Coding style update.
source: <20231018124538.68549-2-anonolitunya@gmail.com>
* ii/branch-error-messages-update (2023-10-23) 1 commit
(merged to 'next' on 2023-10-23 at 3d00599173)
+ builtin/branch.c: adjust error messages to coding guidelines
Error message update.
source: <20231023160656.4341-1-isokenjune@gmail.com>
* jc/am-doc-whitespace-action-fix (2023-10-18) 1 commit
(merged to 'next' on 2023-10-20 at 9200d39c08)
+ am: align placeholder for --whitespace option with apply
Docfix.
source: <xmqqwmvjzeqd.fsf@gitster.g>
* jc/attr-tree-config (2023-10-13) 2 commits
(merged to 'next' on 2023-10-19 at 202dc1c453)
+ attr: add attr.tree for setting the treeish to read attributes from
+ attr: read attributes from HEAD when bare repo
The attribute subsystem learned to honor `attr.tree` configuration
that specifies which tree to read the .gitattributes files from.
source: <pull.1577.v5.git.git.1697218770.gitgitgadget@gmail.com>
* jc/commit-new-underscore-index-fix (2023-10-17) 1 commit
(merged to 'next' on 2023-10-22 at 0e4787303d)
+ commit: do not use cryptic "new_index" in end-user facing messages
Message fix.
source: <xmqqo7gwvd8c.fsf_-_@gitster.g>
* jc/update-list-references-to-lore (2023-10-06) 1 commit
(merged to 'next' on 2023-10-19 at 83a721a137)
+ doc: update list archive reference to use lore.kernel.org
Doc update.
source: <xmqq7cnz741s.fsf@gitster.g>
* jk/send-email-fix-addresses-from-composed-messages (2023-10-20) 3 commits
(merged to 'next' on 2023-10-22 at 43221cc3a4)
+ send-email: handle to/cc/bcc from --compose message
+ Revert "send-email: extract email-parsing code into a subroutine"
+ doc/send-email: mention handling of "reply-to" with --compose
The codepath to handle recipient addresses `git send-email
--compose` learns from the user was completely broken, which has
been corrected.
source: <20231020100343.GA2194322@coredump.intra.peff.net>
* jm/bisect-run-synopsis-fix (2023-10-23) 1 commit
(merged to 'next' on 2023-10-23 at 8dfa3ed356)
+ doc/git-bisect: clarify `git bisect run` syntax
Doc and usage message update.
source: <pull.1602.v2.git.1698088990478.gitgitgadget@gmail.com>
* kh/pathspec-error-wo-repository-fix (2023-10-20) 1 commit
(merged to 'next' on 2023-10-22 at 4f77af1e40)
+ grep: die gracefully when outside repository
The pathspec code carelessly dereferenced NULL while emitting an
error message, which has been corrected.
source: <5c8ef6bec1c99e0fae7ada903885a8e77f8137f9.1697819838.git.code@khaugsbakk.name>
* mm/p4-symlink-with-lfs (2023-10-19) 1 commit
(merged to 'next' on 2023-10-20 at 9c05ce7e85)
+ git-p4 shouldn't attempt to store symlinks in LFS
"git p4" tried to store symlinks to LFS when told, but has been
fixed not to do so, because it does not make sense.
source: <20231019002558.867830-1-mmcclain@noprivs.com>
* ms/doc-push-fix (2023-10-20) 1 commit
(merged to 'next' on 2023-10-22 at 7ce3cef56b)
+ git-push doc: more visibility for -q option
Docfix.
source: <20231020184627.14336-1-msuchanek@suse.de>
* ni/die-message-fix-for-git-add (2023-10-17) 1 commit
(merged to 'next' on 2023-10-22 at f46c5dfd63)
+ builtin/add.c: clean up die() messages
Message updates.
source: <20231017113946.747-1-naomi.ibeh69@gmail.com>
* ob/rebase-cleanup (2023-10-20) 3 commits
(merged to 'next' on 2023-10-22 at 05e14ca4fc)
+ rebase: move parse_opt_keep_empty() down
+ rebase: handle --strategy via imply_merge() as well
+ rebase: simplify code related to imply_merge()
Code clean-up.
source: <20231020093654.922890-1-oswald.buddenhagen@gmx.de>
* ps/git-repack-doc-fixes (2023-10-16) 2 commits
(merged to 'next' on 2023-10-22 at df64849f26)
+ doc/git-repack: don't mention nonexistent "--unpacked" option
+ doc/git-repack: fix syntax for `-g` shorthand option
Doc updates.
source: <cover.1697440686.git.ps@pks.im>
* sn/typo-grammo-phraso-fixes (2023-10-05) 5 commits
(merged to 'next' on 2023-10-18 at 575d767f9a)
+ t/README: fix multi-prerequisite example
+ doc/gitk: s/sticked/stuck/
+ git-jump: admit to passing merge mode args to ls-files
+ doc/diff-options: improve wording of the log.diffMerges mention
+ doc: fix some typos, grammar and wording issues
Many typos, ungrammatical sentences and wrong phrasing have been
fixed.
source: <20231003082107.3002173-1-stepnem@smrk.net>
* wx/merge-ort-comment-typofix (2023-10-21) 1 commit
(merged to 'next' on 2023-10-22 at ad1e33883a)
+ merge-ort.c: fix typo 'neeed' to 'needed'
Typofix.
source: <pull.1592.v3.git.git.1697942768555.gitgitgadget@gmail.com>
--------------------------------------------------
[Stalled]
* pw/rebase-sigint (2023-09-07) 1 commit
- rebase -i: ignore signals when forking subprocesses
If the commit log editor or other external programs (spawned via
"exec" insn in the todo list) receive internactive signal during
"git rebase -i", it caused not just the spawned program but the
"Git" process that spawned them, which is often not what the end
user intended. "git" learned to ignore SIGINT and SIGQUIT while
waiting for these subprocesses.
Expecting a reroll.
cf. <12c956ea-330d-4441-937f-7885ab519e26@gmail.com>
source: <pull.1581.git.1694080982621.gitgitgadget@gmail.com>
* tk/cherry-pick-sequence-requires-clean-worktree (2023-06-01) 1 commit
- cherry-pick: refuse cherry-pick sequence if index is dirty
"git cherry-pick A" that replays a single commit stopped before
clobbering local modification, but "git cherry-pick A..B" did not,
which has been corrected.
Expecting a reroll.
cf. <999f12b2-38d6-f446-e763-4985116ad37d@gmail.com>
source: <pull.1535.v2.git.1685264889088.gitgitgadget@gmail.com>
* jc/diff-cached-fsmonitor-fix (2023-09-15) 3 commits
- diff-lib: fix check_removed() when fsmonitor is active
- Merge branch 'jc/fake-lstat' into jc/diff-cached-fsmonitor-fix
- Merge branch 'js/diff-cached-fsmonitor-fix' into jc/diff-cached-fsmonitor-fix
(this branch uses jc/fake-lstat.)
The optimization based on fsmonitor in the "diff --cached"
codepath is resurrected with the "fake-lstat" introduced earlier.
It is unknown if the optimization is worth resurrecting, but in case...
source: <xmqqr0n0h0tw.fsf@gitster.g>
--------------------------------------------------
[Cooking]
* ar/submitting-patches-doc-update (2023-10-24) 1 commit
(merged to 'next' on 2023-10-30 at e140009eb6)
+ SubmittingPatches: call gitk's command "Copy commit reference"
Doc update.
Will merge to 'master'.
source: <20231024195123.911431-1-rybak.a.v@gmail.com>
* es/bugreport-no-extra-arg (2023-10-29) 2 commits
(merged to 'next' on 2023-11-01 at 4ca0a9c77c)
+ bugreport: reject positional arguments
+ t0091-bugreport: stop using i18ngrep
"git bugreport" learned to complain when it received a command line
argument that it will not use.
Will merge to 'master'.
source: <20231026155459.2234929-1-nasamuffin@google.com>
* js/my-first-contribution-update (2023-10-28) 1 commit
(merged to 'next' on 2023-11-01 at 94590ee724)
+ Include gettext.h in MyFirstContribution tutorial
Documentation update.
Will merge to 'master'.
source: <20231017041503.3249-1-jacob@initialcommit.io>
* ms/send-email-validate-fix (2023-10-26) 1 commit
(merged to 'next' on 2023-11-01 at f9dd32186b)
+ send-email: move validation code below process_address_list
"git send-email" did not have certain pieces of data computed yet
when it tried to validate the outging messages and its recipient
addresses, which has been sorted out.
Will merge to 'master'.
source: <ddd4bfdd-ed14-44f4-89d3-192332bbc1c4@amd.com>
* ps/ci-gitlab (2023-11-02) 8 commits
- ci: add support for GitLab CI
- ci: install test dependencies for linux-musl
- ci: squelch warnings when testing with unusable Git repo
- ci: unify setup of some environment variables
- ci: split out logic to set up failed test artifacts
- ci: group installation of Docker dependencies
- ci: make grouping setup more generic
- ci: reorder definitions for grouping functions
Add support for GitLab CI.
Comments?
source: <cover.1698843660.git.ps@pks.im>
* ps/ref-tests-update (2023-10-24) 9 commits
- t: mark several tests that assume the files backend with REFFILES
- t7900: assert the absence of refs via git-for-each-ref(1)
- t7300: assert exact states of repo
- t4207: delete replace references via git-update-ref(1)
- t1450: convert tests to remove worktrees via git-worktree(1)
- t: convert tests to not access reflog via the filesystem
- t: convert tests to not access symrefs via the filesystem
- t: convert tests to not write references via the filesystem
- t: allow skipping expected object ID in `ref-store update-ref`
Update ref-related tests.
Will merge to 'next'?
source: <cover.1698156169.git.ps@pks.im>
* rs/fix-arghelp (2023-10-29) 1 commit
(merged to 'next' on 2023-11-01 at cd923d3362)
+ am, rebase: fix arghelp syntax of --empty
Doc and help update.
Will merge to 'master'.
source: <10e09b2d-15d7-4af1-b24c-217f9e2f457a@web.de>
* rs/parse-options-cmdmode (2023-10-29) 2 commits
(merged to 'next' on 2023-11-01 at b83328f1e7)
+ am: simplify --show-current-patch handling
+ parse-options: make CMDMODE errors more precise
parse-options improvements for OPT_CMDMODE options.
Will merge to 'master'.
source: <4520156b-9418-493c-a50c-e61b42e805b3@web.de>
* rs/reflog-expire-single-worktree-fix (2023-10-29) 1 commit
(merged to 'next' on 2023-11-01 at 6b4dab2cd2)
+ reflog: fix expire --single-worktree
"git reflog expire --single-worktree" has been broken for the past
20 months or so, which has been corrected.
Will merge to 'master'.
source: <63eade0e-bf2c-4906-8b4c-689797cff737@web.de>
* jx/fetch-atomic-error-message-fix (2023-10-19) 2 commits
- fetch: no redundant error message for atomic fetch
- t5574: test porcelain output of atomic fetch
"git fetch --atomic" issued an unnecessary empty error message,
which has been corrected.
Needs review.
source: <ced46baeb1c18b416b4b4cc947f498bea2910b1b.1697725898.git.zhiyou.jx@alibaba-inc.com>
* js/bugreport-in-the-same-minute (2023-10-16) 1 commit
- bugreport: include +i in outfile suffix as needed
Instead of auto-generating a filename that is already in use for
output and fail the command, `git bugreport` learned to fuzz the
filename to avoid collisions with existing files.
Expecting a reroll.
cf. <ZTtZ5CbIGETy1ucV.jacob@initialcommit.io>
source: <20231016214045.146862-2-jacob@initialcommit.io>
* kh/t7900-cleanup (2023-10-17) 9 commits
- t7900: fix register dependency
- t7900: factor out packfile dependency
- t7900: fix `print-args` dependency
- t7900: fix `pfx` dependency
- t7900: factor out common schedule setup
- t7900: factor out inheritance test dependency
- t7900: create commit so that branch is born
- t7900: setup and tear down clones
- t7900: remove register dependency
Test clean-up.
Perhaps discard?
cf. <655ca147-c214-41be-919d-023c1b27b311@app.fastmail.com>
source: <cover.1697319294.git.code@khaugsbakk.name>
* tb/merge-tree-write-pack (2023-10-23) 5 commits
- builtin/merge-tree.c: implement support for `--write-pack`
- bulk-checkin: introduce `index_tree_bulk_checkin_incore()`
- bulk-checkin: introduce `index_blob_bulk_checkin_incore()`
- bulk-checkin: generify `stream_blob_to_pack()` for arbitrary types
- bulk-checkin: extract abstract `bulk_checkin_source`
"git merge-tree" learned "--write-pack" to record its result
without creating loose objects.
Will merge to 'next'?
source: <cover.1698101088.git.me@ttaylorr.com>
* tb/format-pack-doc-update (2023-11-01) 2 commits
(merged to 'next' on 2023-11-02 at 538991fe9b)
+ Documentation/gitformat-pack.txt: fix incorrect MIDX documentation
+ Documentation/gitformat-pack.txt: fix typo
Doc update.
Will merge to 'master'.
source: <cover.1698780244.git.me@ttaylorr.com>
* ps/do-not-trust-commit-graph-blindly-for-existence (2023-11-01) 2 commits
(merged to 'next' on 2023-11-01 at 06037376ee)
+ commit: detect commits that exist in commit-graph but not in the ODB
+ commit-graph: introduce envvar to disable commit existence checks
(this branch is used by kn/rev-list-missing-fix.)
The codepath to traverse the commit-graph learned to notice that a
commit is missing (e.g., corrupt repository lost an object), even
though it knows something about the commit (like its parents) from
what is in commit-graph.
Will merge to 'master'.
source: <cover.1698736363.git.ps@pks.im>
* tb/pair-chunk-expect-size (2023-10-14) 8 commits
- midx: read `OOFF` chunk with `pair_chunk_expect()`
- midx: read `OIDL` chunk with `pair_chunk_expect()`
- midx: read `OIDF` chunk with `pair_chunk_expect()`
- commit-graph: read `BIDX` chunk with `pair_chunk_expect()`
- commit-graph: read `GDAT` chunk with `pair_chunk_expect()`
- commit-graph: read `CDAT` chunk with `pair_chunk_expect()`
- commit-graph: read `OIDF` chunk with `pair_chunk_expect()`
- chunk-format: introduce `pair_chunk_expect()` helper
Code clean-up for jk/chunk-bounds topic.
Comments?
source: <45cac29403e63483951f7766c6da3c022c68d9f0.1697225110.git.me@ttaylorr.com>
source: <cover.1697225110.git.me@ttaylorr.com>
* jc/grep-f-relative-to-cwd (2023-10-12) 1 commit
(merged to 'next' on 2023-10-31 at 0d32547b18)
+ grep: -f <path> is relative to $cwd
"cd sub && git grep -f patterns" tried to read "patterns" file at
the top level of the working tree; it has been corrected to read
"sub/patterns" instead.
Will merge to 'master'.
cf. <ZUAnEVk65VQQE263@nand.local>
source: <xmqqedhzg37z.fsf@gitster.g>
* tb/path-filter-fix (2023-10-18) 17 commits
- bloom: introduce `deinit_bloom_filters()`
- commit-graph: reuse existing Bloom filters where possible
- object.h: fix mis-aligned flag bits table
- commit-graph: drop unnecessary `graph_read_bloom_data_context`
- commit-graph.c: unconditionally load Bloom filters
- bloom: prepare to discard incompatible Bloom filters
- bloom: annotate filters with hash version
- commit-graph: new filter ver. that fixes murmur3
- repo-settings: introduce commitgraph.changedPathsVersion
- t4216: test changed path filters with high bit paths
- t/helper/test-read-graph: implement `bloom-filters` mode
- bloom.h: make `load_bloom_filter_from_graph()` public
- t/helper/test-read-graph.c: extract `dump_graph_info()`
- gitformat-commit-graph: describe version 2 of BDAT
- commit-graph: ensure Bloom filters are read with consistent settings
- revision.c: consult Bloom filters for root commits
- t/t4216-log-bloom.sh: harden `test_bloom_filters_not_used()`
The Bloom filter used for path limited history traversal was broken
on systems whose "char" is unsigned; update the implementation and
bump the format version to 2.
Needs (hopefully final and quick) review.
source: <cover.1697653929.git.me@ttaylorr.com>
* kn/rev-list-missing-fix (2023-11-01) 4 commits
(merged to 'next' on 2023-11-02 at 2469dfc402)
+ rev-list: add commit object support in `--missing` option
+ rev-list: move `show_commit()` to the bottom
+ revision: rename bit to `do_not_die_on_missing_objects`
+ Merge branch 'ps/do-not-trust-commit-graph-blindly-for-existence' into kn/rev-list-missing-fix
(this branch uses ps/do-not-trust-commit-graph-blindly-for-existence.)
"git rev-list --missing" did not work for missing commit objects,
which has been corrected.
Will merge to 'master'.
source: <20231026101109.43110-1-karthik.188@gmail.com>
* cc/git-replay (2023-10-10) 14 commits
- replay: stop assuming replayed branches do not diverge
- replay: add --contained to rebase contained branches
- replay: add --advance or 'cherry-pick' mode
- replay: use standard revision ranges
- replay: make it a minimal server side command
- replay: remove HEAD related sanity check
- replay: remove progress and info output
- replay: add an important FIXME comment about gpg signing
- replay: change rev walking options
- replay: introduce pick_regular_commit()
- replay: die() instead of failing assert()
- replay: start using parse_options API
- replay: introduce new builtin
- t6429: remove switching aspects of fast-rebase
Introduce "git replay", a tool meant on the server side without
working tree to recreate a history.
Expectting a (hopefully final and quick) reroll.
cf. <bd872b81-80a9-5e4e-dcb6-faebc9671848@gmx.de>
source: <20231010123847.2777056-1-christian.couder@gmail.com>
* ak/color-decorate-symbols (2023-10-23) 7 commits
- log: add color.decorate.pseudoref config variable
- refs: exempt pseudorefs from pattern prefixing
- refs: add pseudorefs array and iteration functions
- log: add color.decorate.ref config variable
- log: add color.decorate.symbol config variable
- log: use designated inits for decoration_colors
- config: restructure color.decorate documentation
A new config for coloring.
Needs review.
source: <20231023221143.72489-1-andy.koppe@gmail.com>
* js/update-urls-in-doc-and-comment (2023-09-26) 4 commits
- doc: refer to internet archive
- doc: update links for andre-simon.de
- doc: update links to current pages
- doc: switch links to https
Stale URLs have been updated to their current counterparts (or
archive.org) and HTTP links are replaced with working HTTPS links.
Needs review.
source: <pull.1589.v2.git.1695553041.gitgitgadget@gmail.com>
* la/trailer-cleanups (2023-10-20) 3 commits
- trailer: use offsets for trailer_start/trailer_end
- trailer: find the end of the log message
- commit: ignore_non_trailer computes number of bytes to ignore
Code clean-up.
Will merge to 'next'?
source: <pull.1563.v5.git.1697828495.gitgitgadget@gmail.com>
* eb/hash-transition (2023-10-02) 30 commits
- t1016-compatObjectFormat: add tests to verify the conversion between objects
- t1006: test oid compatibility with cat-file
- t1006: rename sha1 to oid
- test-lib: compute the compatibility hash so tests may use it
- builtin/ls-tree: let the oid determine the output algorithm
- object-file: handle compat objects in check_object_signature
- tree-walk: init_tree_desc take an oid to get the hash algorithm
- builtin/cat-file: let the oid determine the output algorithm
- rev-parse: add an --output-object-format parameter
- repository: implement extensions.compatObjectFormat
- object-file: update object_info_extended to reencode objects
- object-file-convert: convert commits that embed signed tags
- object-file-convert: convert commit objects when writing
- object-file-convert: don't leak when converting tag objects
- object-file-convert: convert tag objects when writing
- object-file-convert: add a function to convert trees between algorithms
- object: factor out parse_mode out of fast-import and tree-walk into in object.h
- cache: add a function to read an OID of a specific algorithm
- tag: sign both hashes
- commit: export add_header_signature to support handling signatures on tags
- commit: convert mergetag before computing the signature of a commit
- commit: write commits for both hashes
- object-file: add a compat_oid_in parameter to write_object_file_flags
- object-file: update the loose object map when writing loose objects
- loose: compatibilty short name support
- loose: add a mapping between SHA-1 and SHA-256 for loose objects
- repository: add a compatibility hash algorithm
- object-names: support input of oids in any supported hash
- oid-array: teach oid-array to handle multiple kinds of oids
- object-file-convert: stubs for converting from one object format to another
Teach a repository to work with both SHA-1 and SHA-256 hash algorithms.
Needs review.
source: <878r8l929e.fsf@gmail.froward.int.ebiederm.org>
* jx/remote-archive-over-smart-http (2023-10-04) 4 commits
- archive: support remote archive from stateless transport
- transport-helper: call do_take_over() in connect_helper
- transport-helper: call do_take_over() in process_connect
- transport-helper: no connection restriction in connect_helper
"git archive --remote=<remote>" learned to talk over the smart
http (aka stateless) transport.
Needs review.
source: <cover.1696432593.git.zhiyou.jx@alibaba-inc.com>
* jx/sideband-chomp-newline-fix (2023-10-04) 3 commits
- pkt-line: do not chomp newlines for sideband messages
- pkt-line: memorize sideband fragment in reader
- test-pkt-line: add option parser for unpack-sideband
Sideband demultiplexer fixes.
Needs review.
source: <cover.1696425168.git.zhiyou.jx@alibaba-inc.com>
* js/config-parse (2023-09-21) 5 commits
- config-parse: split library out of config.[c|h]
- config.c: accept config_parse_options in git_config_from_stdin
- config: report config parse errors using cb
- config: split do_event() into start and flush operations
- config: split out config_parse_options
The parsing routines for the configuration files have been split
into a separate file.
Needs review.
source: <cover.1695330852.git.steadmon@google.com>
* jc/fake-lstat (2023-09-15) 1 commit
- cache: add fake_lstat()
(this branch is used by jc/diff-cached-fsmonitor-fix.)
A new helper to let us pretend that we called lstat() when we know
our cache_entry is up-to-date via fsmonitor.
Needs review.
source: <xmqqcyykig1l.fsf@gitster.g>
* js/doc-unit-tests (2023-11-02) 3 commits
- ci: run unit tests in CI
- unit tests: add TAP unit test framework
- unit tests: add a project plan document
(this branch is used by js/doc-unit-tests-with-cmake.)
Process to add some form of low-level unit tests has started.
Will merge to 'next'?
source: <cover.1698881249.git.steadmon@google.com>
* js/doc-unit-tests-with-cmake (2023-11-02) 7 commits
- cmake: handle also unit tests
- cmake: use test names instead of full paths
- cmake: fix typo in variable name
- artifacts-tar: when including `.dll` files, don't forget the unit-tests
- unit-tests: do show relative file paths
- unit-tests: do not mistake `.pdb` files for being executable
- cmake: also build unit tests
(this branch uses js/doc-unit-tests.)
Update the base topic to work with CMake builds.
Will merge to 'next'?
source: <pull.1579.v3.git.1695640836.gitgitgadget@gmail.com>
* jc/rerere-cleanup (2023-08-25) 4 commits
- rerere: modernize use of empty strbuf
- rerere: try_merge() should use LL_MERGE_ERROR when it means an error
- rerere: fix comment on handle_file() helper
- rerere: simplify check_one_conflict() helper function
Code clean-up.
Not ready to be reviewed yet.
source: <20230824205456.1231371-1-gitster@pobox.com>
* rj/status-bisect-while-rebase (2023-10-16) 1 commit
- status: fix branch shown when not only bisecting
"git status" is taught to show both the branch being bisected and
being rebased when both are in effect at the same time.
Needs review.
source: <2e24ca9b-9c5f-f4df-b9f8-6574a714dfb2@gmail.com>
--------------------------------------------------
[Discarded]
* rs/parse-options-value-int (2023-09-18) 2 commits
. parse-options: use and require int pointer for OPT_CMDMODE
. parse-options: add int value pointer to struct option
A bit of type safety for the "value" pointer used in the
parse-options API.
Retracted.
cf. <4014e490-c6c1-453d-b0ed-645220e3e614@web.de>
source: <e6d8a291-03de-cfd3-3813-747fc2cad145@web.de>
^ permalink raw reply
* Re: [PATCH v3 1/2] git-merge-file doc: drop "-file" from argument placeholders
From: Martin Ågren @ 2023-11-02 8:53 UTC (permalink / raw)
To: Junio C Hamano
Cc: brian m. carlson, git, Elijah Newren, Phillip Wood, Eric Sunshine,
Taylor Blau
In-Reply-To: <xmqq8r7howsq.fsf@gitster.g>
On Thu, 2 Nov 2023 at 00:53, Junio C Hamano <gitster@pobox.com> wrote:
>
> "brian m. carlson" <sandals@crustytoothpaste.net> writes:
>
> > From: Martin Ågren <martin.agren@gmail.com>
> >
> > `git merge-file` takes three positional arguments. Each of them is
> > documented as `<foo-file>`. In preparation for teaching this command to
> > alternatively take three object IDs, make these placeholders a bit more
>
> Minor nit. Don't we want to say "three blob object names"? Unless
> we plan to grow this feature into accepting three tree object names,
> that is.
Hmm, yeah. Or just "three non-filename arguments". I do wonder: doesn't
this mean that the second patch could/should possibly move away from the
notion of "object ID"/`--object-id`? (That's not trying to shift any
blame from one patch to the other, that's my honest reaction.)
Ah, yes, I thought I recognized this. Quoting your response [1] to v2:
> I briefly thought about suggesting --blob-id instead of --object-id
> simply because you'd never want to feed it trees and commits, but
> the error message from read_mmblob() the users would get mentions
> 'blob' to signal that non-blob objects are unwelcome, so the name of
> the optionwould be OK as-is.
Maybe you having a similar reaction a second time makes this smell a bit
more?
[1] https://lore.kernel.org/git/xmqqo7ge2xzl.fsf@gitster.g/
Martin
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox