From 92fb4c0da9f1b16833147fd35e7a6e7a772866f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Mon, 28 Nov 2022 19:18:14 +0100 Subject: [PATCH 1/8] Fix markdown lint errors --- README.md | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 82e79b0..3252dea 100644 --- a/README.md +++ b/README.md @@ -12,14 +12,13 @@ If a commit in the range has already been tested, then by default `git test` rep The test results are recorded by the *tree* that was tested, not the commit, so old test results remain valid even across some kinds of commit rewriting: -* If commits are rewritten to change their log messages, authorship, dates, etc., the test results remain valid. -* If consecutive commits are squashed, the results remain valid. -* If a commit is split into two, only the first (partial) commit needs to be tested. -* If some commits deep in a branch are reordered, the test results for commits built on top of the reordered commits often remain valid. +* If commits are rewritten to change their log messages, authorship, dates, etc., the test results remain valid. +* If consecutive commits are squashed, the results remain valid. +* If a commit is split into two, only the first (partial) commit needs to be tested. +* If some commits deep in a branch are reordered, the test results for commits built on top of the reordered commits often remain valid. Of course this means that your tests should not depend on things besides the files in the tree. For example, whether your test passes/fails should *not* depend on the current branch name or commit message. - ## Usage ### Defining tests @@ -112,7 +111,6 @@ The last command can be re-run any time; it only does significant work when some Because linked worktrees share branches and the git configuration with the main repository, test definitions and test results are visible across all worktrees. So you could even run multiple tests at the same time in multiple linked worktrees. - ## Installation Requirements: @@ -122,38 +120,35 @@ Requirements: Just put `bin/git-test` somewhere in your `$PATH`, adjusting its first line if necessary to invoke the desired Python interpreter properly in your environment. - ## Ideas for future enhancements Some other features that would be nice: -* Be more consistent about restoring `HEAD`. `git test run` currently checks out the branch that you started on when it is finished, but only if all of the tests passed. We need some kind of `git test reset` command analogous to `git bisect reset`. +* Be more consistent about restoring `HEAD`. `git test run` currently checks out the branch that you started on when it is finished, but only if all of the tests passed. We need some kind of `git test reset` command analogous to `git bisect reset`. -* `git test bisect`: run `git bisect run` against a range of commits, using a configured test as the command that `bisect` uses to decide whether a commit is good/bad. +* `git test bisect`: run `git bisect run` against a range of commits, using a configured test as the command that `bisect` uses to decide whether a commit is good/bad. -* `git test prune`: delete notes for obsolete trees. +* `git test prune`: delete notes for obsolete trees. -* Continuous testing mode, where `git test` watches the repository for changes and re-runs itself automatically whenever the commits it is watching change. +* Continuous testing mode, where `git test` watches the repository for changes and re-runs itself automatically whenever the commits it is watching change. -* Dependencies between tests; for example: +* Dependencies between tests; for example: - * Provide a way to say "if my `full` test passes, that implies that the `build` test would also pass". + * Provide a way to say "if my `full` test passes, that implies that the `build` test would also pass". - * Provide a way to run the `build` test (and record the `build` test's results) as the first step of the `full` test. + * Provide a way to run the `build` test (and record the `build` test's results) as the first step of the `full` test. -* Allow trees to be marked `skip`, if they shouldn't be tested (e.g., due to a known breakage). Perhaps allow the test script to emit a special return code to ask that the commit be marked `skip` (probably following the convention of `git bisect run`). +* Allow trees to be marked `skip`, if they shouldn't be tested (e.g., due to a known breakage). Perhaps allow the test script to emit a special return code to ask that the commit be marked `skip` (probably following the convention of `git bisect run`). -* Remember return codes and give them back out if the old result is reused. +* Remember return codes and give them back out if the old result is reused. -* Add a `git test fix `, which starts an interactive rebase, changing the command for the first broken commit from "pick" to "edit". - -* Support tests that depend on the *commit*, not the *tree*, that they are run against. +* Add a `git test fix `, which starts an interactive rebase, changing the command for the first broken commit from "pick" to "edit". +* Support tests that depend on the *commit*, not the *tree*, that they are run against. ## License -`git test` is released under the GPLv2+ license. Pull requests are welcome at the project's GitHub page, https://github.com/mhagger/git-test - +`git test` is released under the GPLv2+ license. Pull requests are welcome at the project's GitHub page, . ## Caveats and disclaimers From 41cc74cc2636f45a95fdbd90444b9d0346f7b12d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Mon, 28 Nov 2022 19:59:27 +0100 Subject: [PATCH 2/8] Add note about excluding notes from history when using --all --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 3252dea..3377b64 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,8 @@ Some other features that would be nice: `git test` has pretty good automated tests, but it undoubtedly still has bugs and rough edges. Use it at your own risk. +### Detached head + Please note that when you tell `git test run` to test specified commits, it checks those commits out in your working directory. If the tests fail, it leaves the failing commit checked out *in a detached HEAD state*. This is intentional, so that you can examine the cause of the failure. But it means that if you had changes on your original HEAD that weren't part of any branch, they will now be unreachable. If you don't know what a detached HEAD state is, please read up on it. Additionally, **it is recommended that you run `git test` in a separate worktree**, which is more convenient anyway (see above for instructions). Note that the `git worktree` command was added in Git release 2.5, so make sure you are using that version of Git or (preferably) newer. @@ -167,3 +169,19 @@ and git test run HEAD don't change the commit that is checked out, and they won't change your working copy to a detached HEAD state. + +### Test result "noise" when viewing history with `--all` + +Notice that as a side effect of `git test` saving test results in git notes, +these notes will become visible "noise" when viewing history with `git log` or +`gitk` and using the version specifier `--all`. The solution is to tell git +to ignore those notes with `--exclude` (NB, must be specified *before* `--all` +in order to have effect). + +Writing the full exclude phrase every time will probably be too cumbersome, so +you most likely want to write wrapper scripts like the following + + #!/bin/sh + exec gitk --exclude=refs/notes/* --all "$@" & + +or include `--exclude` in your git aliases. From 9364cfed226c269a1e9ae7e2e06155b48a6d265d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Mon, 28 Nov 2022 20:03:55 +0100 Subject: [PATCH 3/8] Add link to worktree section --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3377b64..7be1ac6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ `git-test` is a command-line script for running automated tests against commits in a Git repository. It is especially targeted at developers who like their tests to pass on *every* commit in a branch, not just the branch tip. -The best way to use `git test` is to keep a window open in a second linked worktree of your repository, and as often as you like run +The best way to use `git test` is to keep a window open in a second linked +[worktree](#best-practice-use-git-test-in-a-linked-worktree) of your repository, +and as often as you like run git test run master..mybranch From 99a077be3fef5b8655a3969804a3a3f7241915b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Mon, 28 Nov 2022 20:07:37 +0100 Subject: [PATCH 4/8] Add link to git-notes documentation --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7be1ac6..49bd913 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,9 @@ and as often as you like run git test run master..mybranch -`git test` will test the commits in the specified range, reporting any failures. The pass/fail results of running tests are also recorded permanently in your repository as Git "notes" (see `git-notes(1)`). +`git test` will test the commits in the specified range, reporting any failures. +The pass/fail results of running tests are also recorded permanently in your +repository as Git "notes" (see [git-notes(1)](https://www.git-scm.com/docs/git-notes)). If a commit in the range has already been tested, then by default `git test` reports the old results rather than testing it again. This means that you can run the above command over and over as you work, and `git test` won't repeat tests whose results it already knows. (Of course there are options to allow you to request explicitly that commits be retested.) From e127b840b5bd84243d37427057b9f59464e40f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Mon, 28 Nov 2022 20:15:18 +0100 Subject: [PATCH 5/8] Add run --forget examples Especially since an example for forget-results is given, people just skimming the documentation might inadvertenly pick up the wrong forget command. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 49bd913..b32f27d 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,11 @@ You can define multiple tests in a single repository (e.g., cheap vs. expensive If you have flaky tests that occasionally fail for bogus reasons, you might want to re-run the test against a commit even though `git test` has already recorded a result for that commit. To do so, run `git test run` with the `--force`/`-f` or `--retest` options. -If you want to forget particular old test results without retesting, run `git test run` with the `--forget` option. +If you want to forget particular old test results without retesting, run +`git test run` with the `--forget` option, e.g. + + git test run [--test=] --forget commit1 + git test run [--test=] --forget commit1..commit2 If you want to permanently forget *all* stored results for a particular test (e.g., if something in your environment has changed), run From 1c0c32641de4a00fa6f5fbd4ddcb478bf5a6ca3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Mon, 28 Nov 2022 20:55:14 +0100 Subject: [PATCH 6/8] Provide script to run tests continously --- README.md | 1 + run-continously.sh | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100755 run-continously.sh diff --git a/README.md b/README.md index b32f27d..f82f55b 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,7 @@ Some other features that would be nice: * `git test prune`: delete notes for obsolete trees. * Continuous testing mode, where `git test` watches the repository for changes and re-runs itself automatically whenever the commits it is watching change. + For now you can use the [run-continously.sh](run-continously.sh) script. * Dependencies between tests; for example: diff --git a/run-continously.sh b/run-continously.sh new file mode 100755 index 0000000..3ff2013 --- /dev/null +++ b/run-continously.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +if [[ $# -lt 1 ]] +then + echo "Usage: $0 [-t name] " 1>&2 + exit 1 +fi + +while true +do + git test run "$@" + n=0 + while [[ $n -lt ${GIT_TEST_CONTINOUS_INTERVAL:-30} ]] + do + n=$(( n + 1 )) + echo -n . + sleep 1 + done + echo +done From e42d298cff233471c47b50f0f44bb05867109a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Mon, 28 Nov 2022 21:38:54 +0100 Subject: [PATCH 7/8] Extract waiting out to a function --- run-continously.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/run-continously.sh b/run-continously.sh index 3ff2013..6342fa6 100755 --- a/run-continously.sh +++ b/run-continously.sh @@ -6,9 +6,7 @@ then exit 1 fi -while true -do - git test run "$@" +wait_for_next_run() { n=0 while [[ $n -lt ${GIT_TEST_CONTINOUS_INTERVAL:-30} ]] do @@ -17,4 +15,11 @@ do sleep 1 done echo +} + +while true +do + git test run "$@" + + wait_for_next_run done From c9c15782d81d5f6b1c89ae37bfdc9677b3b32fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Mon, 28 Nov 2022 22:11:54 +0100 Subject: [PATCH 8/8] Use inotifywait if available inotifywait command copied from https://github.com/peff/git/blob/meta/ci mentioned in https://github.com/mhagger/git-test/issues/6. --- run-continously.sh | 48 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/run-continously.sh b/run-continously.sh index 6342fa6..dd8693b 100755 --- a/run-continously.sh +++ b/run-continously.sh @@ -6,15 +6,47 @@ then exit 1 fi +get_main_worktree() { + # Example output: + + # worktree /home/user/src/git-test + # HEAD e42d298cff233471c47b50f0f44bb05867109a24 + # branch refs/heads/main + # + # worktree /home/user/src/worktree.test.git-test + # HEAD 1c0c32641de4a00fa6f5fbd4ddcb478bf5a6ca3f + # detached + + # Main worktree is always listed first. + git worktree list --porcelain | sed -n '1s/^worktree //p' +} + wait_for_next_run() { - n=0 - while [[ $n -lt ${GIT_TEST_CONTINOUS_INTERVAL:-30} ]] - do - n=$(( n + 1 )) - echo -n . - sleep 1 - done - echo + if type -P inotifywait >/dev/null + then + gitdir=$(git rev-parse --git-dir) + case $gitdir + in + *.git/worktrees*) + # Inside a linked worktree so use .git dir for main worktree for monitoring. + gitdir=$(cd $(get_main_worktree); git rev-parse --path-format=absolute --git-dir) + ;; + *) + ;; + esac + # We need delete_self to pick up changes to HEAD (since it gets renamed + # over), and "move" to pick up changes in the refs directories. + inotifywait -qq -e delete_self -e move -r "$gitdir/HEAD" "$gitdir/refs" + else + n=0 + while [[ $n -lt ${GIT_TEST_CONTINOUS_INTERVAL:-30} ]] + do + n=$(( n + 1 )) + echo -n . + sleep 1 + done + echo + fi } while true