Git fork

Merge branch 'vd/scalar-to-main'

Hoist the remainder of "scalar" out of contrib/ to the main part of
the codebase.

* vd/scalar-to-main:
Documentation/technical: include Scalar technical doc
t/perf: add 'GIT_PERF_USE_SCALAR' run option
t/perf: add Scalar performance tests
scalar-clone: add test coverage
scalar: add to 'git help -a' command list
scalar: implement the `help` subcommand
git help: special-case `scalar`
scalar: include in standard Git build & installation
scalar: fix command documentation section header

+472 -415
+1
.gitignore
··· 185 185 /git-whatchanged 186 186 /git-worktree 187 187 /git-write-tree 188 + /scalar 188 189 /git-core-*/?* 189 190 /git.res 190 191 /gitweb/GITWEB-BUILD-OPTIONS
+2
Documentation/Makefile
··· 21 21 MAN1_TXT += git.txt 22 22 MAN1_TXT += gitk.txt 23 23 MAN1_TXT += gitweb.txt 24 + MAN1_TXT += scalar.txt 24 25 25 26 # man5 / man7 guides (note: new guides should also be added to command-list.txt) 26 27 MAN5_TXT += gitattributes.txt ··· 116 117 TECH_DOCS += technical/partial-clone 117 118 TECH_DOCS += technical/racy-git 118 119 TECH_DOCS += technical/reftable 120 + TECH_DOCS += technical/scalar 119 121 TECH_DOCS += technical/send-pack-pipeline 120 122 TECH_DOCS += technical/shallow 121 123 TECH_DOCS += technical/trivial-merge
+1 -1
Documentation/cmd-list.perl
··· 10 10 $state = 0; 11 11 open I, '<', "$name.txt" or die "No such file $name.txt"; 12 12 while (<I>) { 13 - if (/^git[a-z0-9-]*\(([0-9])\)$/) { 13 + if (/^(git|scalar)[a-z0-9-]*\(([0-9])\)$/) { 14 14 $mansection = $1; 15 15 next; 16 16 }
-61
Documentation/technical/scalar.txt
··· 64 64 Because `scalar` is not invoked as a Git subcommand (like `git scalar`), it is 65 65 built and installed as its own executable in the `bin/` directory, alongside 66 66 `git`, `git-gui`, etc. 67 - 68 - Roadmap 69 - ------- 70 - 71 - NOTE: this section will be removed once the remaining tasks outlined in this 72 - roadmap are complete. 73 - 74 - Scalar is a large enough project that it is being upstreamed incrementally, 75 - living in `contrib/` until it is feature-complete. So far, the following patch 76 - series have been accepted: 77 - 78 - - `scalar-the-beginning`: The initial patch series which sets up 79 - `contrib/scalar/` and populates it with a minimal `scalar` command that 80 - demonstrates the fundamental ideas. 81 - 82 - - `scalar-c-and-C`: The `scalar` command learns about two options that can be 83 - specified before the command, `-c <key>=<value>` and `-C <directory>`. 84 - 85 - - `scalar-diagnose`: The `scalar` command is taught the `diagnose` subcommand. 86 - 87 - - `scalar-generalize-diagnose`: Move the functionality of `scalar diagnose` 88 - into `git diagnose` and `git bugreport --diagnose`. 89 - 90 - - 'scalar-add-fsmonitor: Enable the built-in FSMonitor in Scalar 91 - enlistments. At the end of this series, Scalar should be feature-complete 92 - from the perspective of a user. 93 - 94 - Roughly speaking (and subject to change), the following series are needed to 95 - "finish" this initial version of Scalar: 96 - 97 - - Move Scalar to toplevel: Move Scalar out of `contrib/` and into the root of 98 - `git`. This includes a variety of related updates, including: 99 - - building & installing Scalar in the Git root-level 'make [install]'. 100 - - builing & testing Scalar as part of CI. 101 - - moving and expanding test coverage of Scalar (including perf tests). 102 - - implementing 'scalar help'/'git help scalar' to display scalar 103 - documentation. 104 - 105 - Finally, there are two additional patch series that exist in Microsoft's fork of 106 - Git, but there is no current plan to upstream them. There are some interesting 107 - ideas there, but the implementation is too specific to Azure Repos and/or VFS 108 - for Git to be of much help in general. 109 - 110 - These still exist mainly because the GVFS protocol is what Azure Repos has 111 - instead of partial clone, while Git is focused on improving partial clone: 112 - 113 - - `scalar-with-gvfs`: The primary purpose of this patch series is to support 114 - existing Scalar users whose repositories are hosted in Azure Repos (which does 115 - not support Git's partial clones, but supports its predecessor, the GVFS 116 - protocol, which is used by Scalar to emulate the partial clone). 117 - 118 - Since the GVFS protocol will never be supported by core Git, this patch series 119 - will remain in Microsoft's fork of Git. 120 - 121 - - `run-scalar-functional-tests`: The Scalar project developed a quite 122 - comprehensive set of integration tests (or, "Functional Tests"). They are the 123 - sole remaining part of the original C#-based Scalar project, and this patch 124 - adds a GitHub workflow that runs them all. 125 - 126 - Since the tests partially depend on features that are only provided in the 127 - `scalar-with-gvfs` patch series, this patch cannot be upstreamed.
+18 -13
Makefile
··· 605 605 FUZZ_PROGRAMS = 606 606 GIT_OBJS = 607 607 LIB_OBJS = 608 + SCALAR_OBJS = 608 609 OBJECTS = 610 + OTHER_PROGRAMS = 609 611 PROGRAM_OBJS = 610 612 PROGRAMS = 611 613 EXCLUDED_PROGRAMS = ··· 819 821 BUILT_INS += git-whatchanged$X 820 822 821 823 # what 'all' will build but not install in gitexecdir 822 - OTHER_PROGRAMS = git$X 824 + OTHER_PROGRAMS += git$X 825 + OTHER_PROGRAMS += scalar$X 823 826 824 827 # what test wrappers are needed and 'install' will install, in bindir 825 828 BINDIR_PROGRAMS_NEED_X += git 829 + BINDIR_PROGRAMS_NEED_X += scalar 826 830 BINDIR_PROGRAMS_NEED_X += git-receive-pack 827 831 BINDIR_PROGRAMS_NEED_X += git-shell 828 832 BINDIR_PROGRAMS_NEED_X += git-upload-archive ··· 2220 2224 2221 2225 all:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS 2222 2226 ifneq (,$X) 2223 - $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) git$X)), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';) 2227 + $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) $(OTHER_PROGRAMS))), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';) 2224 2228 endif 2225 2229 2226 2230 all:: ··· 2543 2547 .PHONY: git-objs 2544 2548 git-objs: $(GIT_OBJS) 2545 2549 2550 + SCALAR_OBJS += scalar.o 2551 + .PHONY: scalar-objs 2552 + scalar-objs: $(SCALAR_OBJS) 2553 + 2546 2554 OBJECTS += $(GIT_OBJS) 2555 + OBJECTS += $(SCALAR_OBJS) 2547 2556 OBJECTS += $(PROGRAM_OBJS) 2548 2557 OBJECTS += $(TEST_OBJS) 2549 2558 OBJECTS += $(XDIFF_OBJS) ··· 2554 2563 OBJECTS += http.o http-walker.o remote-curl.o 2555 2564 endif 2556 2565 2557 - SCALAR_SOURCES := contrib/scalar/scalar.c 2558 - SCALAR_OBJECTS := $(SCALAR_SOURCES:c=o) 2559 - OBJECTS += $(SCALAR_OBJECTS) 2560 - 2561 2566 .PHONY: objects 2562 2567 objects: $(OBJECTS) 2563 2568 ··· 2683 2688 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ 2684 2689 $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS) 2685 2690 2686 - contrib/scalar/scalar$X: $(SCALAR_OBJECTS) GIT-LDFLAGS $(GITLIBS) 2691 + scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS) 2687 2692 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \ 2688 2693 $(filter %.o,$^) $(LIBS) 2689 2694 ··· 2739 2744 XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \ 2740 2745 --keyword=__ --keyword=N__ --keyword="__n:1,2" 2741 2746 MSGMERGE_FLAGS = --add-location --backup=off --update 2742 - LOCALIZED_C = $(sort $(FOUND_C_SOURCES) $(FOUND_H_SOURCES) $(SCALAR_SOURCES) \ 2743 - $(GENERATED_H)) 2747 + LOCALIZED_C = $(sort $(FOUND_C_SOURCES) $(FOUND_H_SOURCES) $(GENERATED_H)) 2744 2748 LOCALIZED_SH = $(sort $(SCRIPT_SH) git-sh-setup.sh) 2745 2749 LOCALIZED_PERL = $(sort $(SCRIPT_PERL)) 2746 2750 ··· 3054 3058 $(call mkdir_p_parent_template) 3055 3059 $(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ 3056 3060 -e 's|@@BUILD_DIR@@|$(shell pwd)|' \ 3057 - -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%$(X),$(@F))$(patsubst git%,$(X),$(filter $(@F),$(BINDIR_PROGRAMS_NEED_X)))|' < $< > $@ && \ 3061 + -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%,$(@F))$(if $(filter-out $(BINDIR_PROGRAMS_NO_X),$(@F)),$(X),)|' < $< > $@ && \ 3058 3062 chmod +x $@ 3059 3063 3060 3064 # GNU make supports exporting all variables by "export" without parameters. ··· 3268 3272 $(MAKE) -C git-gui gitexecdir='$(gitexec_instdir_SQ)' install 3269 3273 endif 3270 3274 ifneq (,$X) 3271 - $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) git$X)), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';) 3275 + $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) $(OTHER_PROGRAMS))), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';) 3272 3276 endif 3273 3277 3274 3278 bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \ 3275 3279 execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \ 3276 3280 destdir_from_execdir_SQ=$$(echo '$(gitexecdir_relative_SQ)' | sed -e 's|[^/][^/]*|..|g') && \ 3277 3281 { test "$$bindir/" = "$$execdir/" || \ 3278 - for p in git$X $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \ 3282 + for p in $(OTHER_PROGRAMS) $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \ 3279 3283 $(RM) "$$execdir/$$p" && \ 3280 3284 test -n "$(INSTALL_SYMLINKS)" && \ 3281 3285 ln -s "$$destdir_from_execdir_SQ/$(bindir_relative_SQ)/$$p" "$$execdir/$$p" || \ ··· 3450 3454 $(RM) git.res 3451 3455 $(RM) $(OBJECTS) 3452 3456 $(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB) 3453 - $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X 3457 + $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) 3454 3458 $(RM) $(TEST_PROGRAMS) 3455 3459 $(RM) $(FUZZ_PROGRAMS) 3456 3460 $(RM) $(SP_OBJ) ··· 3501 3505 ALL_COMMANDS += git-gui 3502 3506 ALL_COMMANDS += gitk 3503 3507 ALL_COMMANDS += gitweb 3508 + ALL_COMMANDS += scalar 3504 3509 3505 3510 .PHONY: check-docs 3506 3511 check-docs::
+2
builtin/help.c
··· 440 440 return git_cmd; 441 441 else if (is_git_command(git_cmd)) 442 442 return xstrfmt("git-%s", git_cmd); 443 + else if (!strcmp("scalar", git_cmd)) 444 + return xstrdup(git_cmd); 443 445 else 444 446 return xstrfmt("git%s", git_cmd); 445 447 }
+1
command-list.txt
··· 235 235 gittutorial-2 guide 236 236 gitweb ancillaryinterrogators 237 237 gitworkflows guide 238 + scalar mainporcelain
+6 -3
contrib/buildsystems/CMakeLists.txt
··· 610 610 #programs 611 611 set(PROGRAMS_BUILT 612 612 git git-daemon git-http-backend git-sh-i18n--envsubst 613 - git-shell) 613 + git-shell scalar) 614 614 615 615 if(NOT CURL_FOUND) 616 616 list(APPEND excluded_progs git-http-fetch git-http-push) ··· 756 756 757 757 add_executable(git-shell ${CMAKE_SOURCE_DIR}/shell.c) 758 758 target_link_libraries(git-shell common-main) 759 + 760 + add_executable(scalar ${CMAKE_SOURCE_DIR}/scalar.c) 761 + target_link_libraries(scalar common-main) 759 762 760 763 if(CURL_FOUND) 761 764 add_library(http_obj OBJECT ${CMAKE_SOURCE_DIR}/http.c) ··· 903 906 904 907 #install 905 908 foreach(program ${PROGRAMS_BUILT}) 906 - if(program STREQUAL "git" OR program STREQUAL "git-shell") 909 + if(program MATCHES "^(git|git-shell|scalar)$") 907 910 install(TARGETS ${program} 908 911 RUNTIME DESTINATION bin) 909 912 else() ··· 977 980 978 981 #wrapper scripts 979 982 set(wrapper_scripts 980 - git git-upload-pack git-receive-pack git-upload-archive git-shell git-remote-ext) 983 + git git-upload-pack git-receive-pack git-upload-archive git-shell git-remote-ext scalar) 981 984 982 985 set(wrapper_test_scripts 983 986 test-fake-ssh test-tool)
-2
contrib/scalar/.gitignore
··· 1 - /*.exe 2 - /scalar
-35
contrib/scalar/Makefile
··· 1 - # The default target of this Makefile is... 2 - all:: 3 - 4 - # Import tree-wide shared Makefile behavior and libraries 5 - include ../../shared.mak 6 - 7 - include ../../config.mak.uname 8 - -include ../../config.mak.autogen 9 - -include ../../config.mak 10 - 11 - TARGETS = scalar$(X) scalar.o 12 - GITLIBS = ../../common-main.o ../../libgit.a ../../xdiff/lib.a 13 - 14 - all:: scalar$(X) ../../bin-wrappers/scalar 15 - 16 - $(GITLIBS): 17 - $(QUIET_SUBDIR0)../.. $(QUIET_SUBDIR1) $(subst ../../,,$@) 18 - 19 - $(TARGETS): $(GITLIBS) scalar.c 20 - $(QUIET_SUBDIR0)../.. $(QUIET_SUBDIR1) $(patsubst %,contrib/scalar/%,$@) 21 - 22 - clean: 23 - $(RM) $(TARGETS) ../../bin-wrappers/scalar 24 - 25 - ../../bin-wrappers/scalar: ../../wrap-for-bin.sh Makefile 26 - @mkdir -p ../../bin-wrappers 27 - $(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ 28 - -e 's|@@BUILD_DIR@@|$(shell cd ../.. && pwd)|' \ 29 - -e 's|@@PROG@@|contrib/scalar/scalar$(X)|' < $< > $@ && \ 30 - chmod +x $@ 31 - 32 - test: all 33 - $(MAKE) -C t 34 - 35 - .PHONY: $(GITLIBS) all clean test FORCE
+20
contrib/scalar/scalar.c scalar.c
··· 819 819 return res; 820 820 } 821 821 822 + static int cmd_help(int argc, const char **argv) 823 + { 824 + struct option options[] = { 825 + OPT_END(), 826 + }; 827 + const char * const usage[] = { 828 + "scalar help", 829 + NULL 830 + }; 831 + 832 + argc = parse_options(argc, argv, NULL, options, 833 + usage, 0); 834 + 835 + if (argc != 0) 836 + usage_with_options(usage, options); 837 + 838 + return run_git("help", "scalar", NULL); 839 + } 840 + 822 841 static int cmd_version(int argc, const char **argv) 823 842 { 824 843 int verbose = 0, build_options = 0; ··· 858 877 { "run", cmd_run }, 859 878 { "reconfigure", cmd_reconfigure }, 860 879 { "delete", cmd_delete }, 880 + { "help", cmd_help }, 861 881 { "version", cmd_version }, 862 882 { "diagnose", cmd_diagnose }, 863 883 { NULL, NULL},
+2 -2
contrib/scalar/scalar.txt Documentation/scalar.txt
··· 161 161 -------- 162 162 linkgit:git-clone[1], linkgit:git-maintenance[1]. 163 163 164 - Scalar 164 + GIT 165 165 --- 166 - Associated with the linkgit:git[1] suite 166 + Part of the linkgit:git[1] suite
-81
contrib/scalar/t/Makefile
··· 1 - # Import tree-wide shared Makefile behavior and libraries 2 - include ../../../shared.mak 3 - 4 - # Run scalar tests 5 - # 6 - # Copyright (c) 2005,2021 Junio C Hamano, Johannes Schindelin 7 - # 8 - 9 - -include ../../../config.mak.autogen 10 - -include ../../../config.mak 11 - 12 - SHELL_PATH ?= $(SHELL) 13 - PERL_PATH ?= /usr/bin/perl 14 - RM ?= rm -f 15 - PROVE ?= prove 16 - DEFAULT_TEST_TARGET ?= test 17 - TEST_LINT ?= test-lint 18 - 19 - ifdef TEST_OUTPUT_DIRECTORY 20 - TEST_RESULTS_DIRECTORY = $(TEST_OUTPUT_DIRECTORY)/test-results 21 - else 22 - TEST_RESULTS_DIRECTORY = ../../../t/test-results 23 - endif 24 - 25 - # Shell quote; 26 - SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) 27 - PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) 28 - TEST_RESULTS_DIRECTORY_SQ = $(subst ','\'',$(TEST_RESULTS_DIRECTORY)) 29 - 30 - T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)) 31 - 32 - all: $(DEFAULT_TEST_TARGET) 33 - 34 - test: $(TEST_LINT) 35 - $(MAKE) aggregate-results-and-cleanup 36 - 37 - prove: $(TEST_LINT) 38 - @echo "*** prove ***"; GIT_CONFIG=.git/config $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS) 39 - $(MAKE) clean-except-prove-cache 40 - 41 - $(T): 42 - @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) 43 - 44 - clean-except-prove-cache: 45 - $(RM) -r 'trash directory'.* 46 - $(RM) -r valgrind/bin 47 - 48 - clean: clean-except-prove-cache 49 - $(RM) .prove 50 - 51 - test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax 52 - 53 - test-lint-duplicates: 54 - @dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \ 55 - test -z "$$dups" || { \ 56 - echo >&2 "duplicate test numbers:" $$dups; exit 1; } 57 - 58 - test-lint-executable: 59 - @bad=`for i in $(T); do test -x "$$i" || echo $$i; done` && \ 60 - test -z "$$bad" || { \ 61 - echo >&2 "non-executable tests:" $$bad; exit 1; } 62 - 63 - test-lint-shell-syntax: 64 - @'$(PERL_PATH_SQ)' ../../../t/check-non-portable-shell.pl $(T) 65 - 66 - aggregate-results-and-cleanup: $(T) 67 - $(MAKE) aggregate-results 68 - $(MAKE) clean 69 - 70 - aggregate-results: 71 - for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \ 72 - echo "$$f"; \ 73 - done | '$(SHELL_PATH_SQ)' ../../../t/aggregate-results.sh 74 - 75 - valgrind: 76 - $(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind" 77 - 78 - test-results: 79 - mkdir -p test-results 80 - 81 - .PHONY: $(T) aggregate-results clean valgrind
-216
contrib/scalar/t/t9099-scalar.sh
··· 1 - #!/bin/sh 2 - 3 - test_description='test the `scalar` command' 4 - 5 - TEST_DIRECTORY=$PWD/../../../t 6 - export TEST_DIRECTORY 7 - 8 - # Make it work with --no-bin-wrappers 9 - PATH=$PWD/..:$PATH 10 - 11 - . ../../../t/test-lib.sh 12 - 13 - GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab ../cron.txt,launchctl:true,schtasks:true" 14 - export GIT_TEST_MAINT_SCHEDULER 15 - 16 - test_expect_success 'scalar shows a usage' ' 17 - test_expect_code 129 scalar -h 18 - ' 19 - 20 - test_expect_success 'scalar invoked on enlistment root' ' 21 - test_when_finished rm -rf test src deeper && 22 - 23 - for enlistment_root in test src deeper/test 24 - do 25 - git init ${enlistment_root}/src && 26 - 27 - # Register 28 - scalar register ${enlistment_root} && 29 - scalar list >out && 30 - grep "$(pwd)/${enlistment_root}/src\$" out && 31 - 32 - # Delete (including enlistment root) 33 - scalar delete $enlistment_root && 34 - test_path_is_missing $enlistment_root && 35 - scalar list >out && 36 - ! grep "^$(pwd)/${enlistment_root}/src\$" out || return 1 37 - done 38 - ' 39 - 40 - test_expect_success 'scalar invoked on enlistment src repo' ' 41 - test_when_finished rm -rf test src deeper && 42 - 43 - for enlistment_root in test src deeper/test 44 - do 45 - git init ${enlistment_root}/src && 46 - 47 - # Register 48 - scalar register ${enlistment_root}/src && 49 - scalar list >out && 50 - grep "$(pwd)/${enlistment_root}/src\$" out && 51 - 52 - # Delete (will not include enlistment root) 53 - scalar delete ${enlistment_root}/src && 54 - test_path_is_dir $enlistment_root && 55 - scalar list >out && 56 - ! grep "^$(pwd)/${enlistment_root}/src\$" out || return 1 57 - done 58 - ' 59 - 60 - test_expect_success 'scalar invoked when enlistment root and repo are the same' ' 61 - test_when_finished rm -rf test src deeper && 62 - 63 - for enlistment_root in test src deeper/test 64 - do 65 - git init ${enlistment_root} && 66 - 67 - # Register 68 - scalar register ${enlistment_root} && 69 - scalar list >out && 70 - grep "$(pwd)/${enlistment_root}\$" out && 71 - 72 - # Delete (will not include enlistment root) 73 - scalar delete ${enlistment_root} && 74 - test_path_is_missing $enlistment_root && 75 - scalar list >out && 76 - ! grep "^$(pwd)/${enlistment_root}\$" out && 77 - 78 - # Make sure we did not accidentally delete the trash dir 79 - test_path_is_dir "$TRASH_DIRECTORY" || return 1 80 - done 81 - ' 82 - 83 - test_expect_success 'scalar repo search respects GIT_CEILING_DIRECTORIES' ' 84 - test_when_finished rm -rf test && 85 - 86 - git init test/src && 87 - mkdir -p test/src/deep && 88 - GIT_CEILING_DIRECTORIES="$(pwd)/test/src" && 89 - ! scalar register test/src/deep 2>err && 90 - grep "not a git repository" err 91 - ' 92 - 93 - test_expect_success 'scalar enlistments need a worktree' ' 94 - test_when_finished rm -rf bare test && 95 - 96 - git init --bare bare/src && 97 - ! scalar register bare/src 2>err && 98 - grep "Scalar enlistments require a worktree" err && 99 - 100 - git init test/src && 101 - ! scalar register test/src/.git 2>err && 102 - grep "Scalar enlistments require a worktree" err 103 - ' 104 - 105 - test_expect_success FSMONITOR_DAEMON 'scalar register starts fsmon daemon' ' 106 - git init test/src && 107 - test_must_fail git -C test/src fsmonitor--daemon status && 108 - scalar register test/src && 109 - git -C test/src fsmonitor--daemon status && 110 - test_cmp_config -C test/src true core.fsmonitor 111 - ' 112 - 113 - test_expect_success 'scalar unregister' ' 114 - git init vanish/src && 115 - scalar register vanish/src && 116 - git config --get --global --fixed-value \ 117 - maintenance.repo "$(pwd)/vanish/src" && 118 - scalar list >scalar.repos && 119 - grep -F "$(pwd)/vanish/src" scalar.repos && 120 - rm -rf vanish/src/.git && 121 - scalar unregister vanish && 122 - test_must_fail git config --get --global --fixed-value \ 123 - maintenance.repo "$(pwd)/vanish/src" && 124 - scalar list >scalar.repos && 125 - ! grep -F "$(pwd)/vanish/src" scalar.repos 126 - ' 127 - 128 - test_expect_success 'set up repository to clone' ' 129 - test_commit first && 130 - test_commit second && 131 - test_commit third && 132 - git switch -c parallel first && 133 - mkdir -p 1/2 && 134 - test_commit 1/2/3 && 135 - git config uploadPack.allowFilter true && 136 - git config uploadPack.allowAnySHA1InWant true 137 - ' 138 - 139 - test_expect_success 'scalar clone' ' 140 - second=$(git rev-parse --verify second:second.t) && 141 - scalar clone "file://$(pwd)" cloned --single-branch && 142 - ( 143 - cd cloned/src && 144 - 145 - git config --get --global --fixed-value maintenance.repo \ 146 - "$(pwd)" && 147 - 148 - git for-each-ref --format="%(refname)" refs/remotes/origin/ >actual && 149 - echo "refs/remotes/origin/parallel" >expect && 150 - test_cmp expect actual && 151 - 152 - test_path_is_missing 1/2 && 153 - test_must_fail git rev-list --missing=print $second && 154 - git rev-list $second && 155 - git cat-file blob $second >actual && 156 - echo "second" >expect && 157 - test_cmp expect actual 158 - ) 159 - ' 160 - 161 - test_expect_success 'scalar reconfigure' ' 162 - git init one/src && 163 - scalar register one && 164 - git -C one/src config core.preloadIndex false && 165 - scalar reconfigure one && 166 - test true = "$(git -C one/src config core.preloadIndex)" && 167 - git -C one/src config core.preloadIndex false && 168 - scalar reconfigure -a && 169 - test true = "$(git -C one/src config core.preloadIndex)" 170 - ' 171 - 172 - test_expect_success 'scalar delete without enlistment shows a usage' ' 173 - test_expect_code 129 scalar delete 174 - ' 175 - 176 - test_expect_success 'scalar delete with enlistment' ' 177 - scalar delete cloned && 178 - test_path_is_missing cloned 179 - ' 180 - 181 - test_expect_success 'scalar supports -c/-C' ' 182 - test_when_finished "scalar delete sub" && 183 - git init sub && 184 - scalar -C sub -c status.aheadBehind=bogus register && 185 - test -z "$(git -C sub config --local status.aheadBehind)" && 186 - test true = "$(git -C sub config core.preloadIndex)" 187 - ' 188 - 189 - test_expect_success '`scalar [...] <dir>` errors out when dir is missing' ' 190 - ! scalar run config cloned 2>err && 191 - grep "cloned. does not exist" err 192 - ' 193 - 194 - SQ="'" 195 - test_expect_success UNZIP 'scalar diagnose' ' 196 - scalar clone "file://$(pwd)" cloned --single-branch && 197 - git repack && 198 - echo "$(pwd)/.git/objects/" >>cloned/src/.git/objects/info/alternates && 199 - test_commit -C cloned/src loose && 200 - scalar diagnose cloned >out 2>err && 201 - grep "Available space" out && 202 - sed -n "s/.*$SQ\\(.*\\.zip\\)$SQ.*/\\1/p" <err >zip_path && 203 - zip_path=$(cat zip_path) && 204 - test -n "$zip_path" && 205 - "$GIT_UNZIP" -v "$zip_path" && 206 - folder=${zip_path%.zip} && 207 - test_path_is_missing "$folder" && 208 - "$GIT_UNZIP" -p "$zip_path" diagnostics.log >out && 209 - test_file_not_empty out && 210 - "$GIT_UNZIP" -p "$zip_path" packs-local.txt >out && 211 - grep "$(pwd)/.git/objects" out && 212 - "$GIT_UNZIP" -p "$zip_path" objects-local.txt >out && 213 - grep "^Total: [1-9]" out 214 - ' 215 - 216 - test_done
+4
t/perf/README
··· 95 95 Git (e.g., performance of index-pack as the number of threads 96 96 changes). These can be enabled with GIT_PERF_EXTRA. 97 97 98 + GIT_PERF_USE_SCALAR 99 + Boolean indicating whether to register test repo(s) with Scalar 100 + before executing tests. 101 + 98 102 You can also pass the options taken by ordinary git tests; the most 99 103 useful one is: 100 104
+39
t/perf/p9210-scalar.sh
··· 1 + #!/bin/sh 2 + 3 + test_description='test scalar performance' 4 + . ./perf-lib.sh 5 + 6 + test_perf_large_repo "$TRASH_DIRECTORY/to-clone" 7 + 8 + test_expect_success 'enable server-side partial clone' ' 9 + git -C to-clone config uploadpack.allowFilter true && 10 + git -C to-clone config uploadpack.allowAnySHA1InWant true 11 + ' 12 + 13 + test_perf 'scalar clone' ' 14 + rm -rf scalar-clone && 15 + scalar clone "file://$(pwd)/to-clone" scalar-clone 16 + ' 17 + 18 + test_perf 'git clone' ' 19 + rm -rf git-clone && 20 + git clone "file://$(pwd)/to-clone" git-clone 21 + ' 22 + 23 + test_compare_perf () { 24 + command=$1 25 + shift 26 + args=$* 27 + test_perf "$command $args (scalar)" " 28 + $command -C scalar-clone/src $args 29 + " 30 + 31 + test_perf "$command $args (non-scalar)" " 32 + $command -C git-clone $args 33 + " 34 + } 35 + 36 + test_compare_perf git status 37 + test_compare_perf test_commit --append --no-tag A 38 + 39 + test_done
+12 -1
t/perf/perf-lib.sh
··· 49 49 MODERN_GIT=$GIT_BUILD_DIR/bin-wrappers/git 50 50 export MODERN_GIT 51 51 52 + MODERN_SCALAR=$GIT_BUILD_DIR/bin-wrappers/scalar 53 + export MODERN_SCALAR 54 + 52 55 perf_results_dir=$TEST_RESULTS_DIR 53 56 test -n "$GIT_PERF_SUBSECTION" && perf_results_dir="$perf_results_dir/$GIT_PERF_SUBSECTION" 54 57 mkdir -p "$perf_results_dir" ··· 120 123 # status" due to a locked index. Since we have 121 124 # a copy it's fine to remove the lock. 122 125 rm .git/index.lock 126 + fi && 127 + if test_bool_env GIT_PERF_USE_SCALAR false 128 + then 129 + "$MODERN_SCALAR" register 123 130 fi 124 131 ) || error "failed to copy repository '$source' to '$repo'" 125 132 } ··· 130 137 "$MODERN_GIT" init -q "$repo" && 131 138 ( 132 139 cd "$repo" && 133 - test_perf_do_repo_symlink_config_ 140 + test_perf_do_repo_symlink_config_ && 141 + if test_bool_env GIT_PERF_USE_SCALAR false 142 + then 143 + "$MODERN_SCALAR" register 144 + fi 134 145 ) 135 146 } 136 147
+3
t/perf/run
··· 171 171 get_var_from_env_or_config "GIT_PERF_MAKE_COMMAND" "perf" "makeCommand" 172 172 get_var_from_env_or_config "GIT_PERF_MAKE_OPTS" "perf" "makeOpts" 173 173 174 + get_var_from_env_or_config "GIT_PERF_USE_SCALAR" "perf" "useScalar" "--bool" 175 + export GIT_PERF_USE_SCALAR 176 + 174 177 get_var_from_env_or_config "GIT_PERF_REPO_NAME" "perf" "repoName" 175 178 export GIT_PERF_REPO_NAME 176 179
+210
t/t9210-scalar.sh
··· 1 + #!/bin/sh 2 + 3 + test_description='test the `scalar` command' 4 + 5 + . ./test-lib.sh 6 + 7 + GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab cron.txt,launchctl:true,schtasks:true" 8 + export GIT_TEST_MAINT_SCHEDULER 9 + 10 + test_expect_success 'scalar shows a usage' ' 11 + test_expect_code 129 scalar -h 12 + ' 13 + 14 + test_expect_success 'scalar invoked on enlistment root' ' 15 + test_when_finished rm -rf test src deeper && 16 + 17 + for enlistment_root in test src deeper/test 18 + do 19 + git init ${enlistment_root}/src && 20 + 21 + # Register 22 + scalar register ${enlistment_root} && 23 + scalar list >out && 24 + grep "$(pwd)/${enlistment_root}/src\$" out && 25 + 26 + # Delete (including enlistment root) 27 + scalar delete $enlistment_root && 28 + test_path_is_missing $enlistment_root && 29 + scalar list >out && 30 + ! grep "^$(pwd)/${enlistment_root}/src\$" out || return 1 31 + done 32 + ' 33 + 34 + test_expect_success 'scalar invoked on enlistment src repo' ' 35 + test_when_finished rm -rf test src deeper && 36 + 37 + for enlistment_root in test src deeper/test 38 + do 39 + git init ${enlistment_root}/src && 40 + 41 + # Register 42 + scalar register ${enlistment_root}/src && 43 + scalar list >out && 44 + grep "$(pwd)/${enlistment_root}/src\$" out && 45 + 46 + # Delete (will not include enlistment root) 47 + scalar delete ${enlistment_root}/src && 48 + test_path_is_dir $enlistment_root && 49 + scalar list >out && 50 + ! grep "^$(pwd)/${enlistment_root}/src\$" out || return 1 51 + done 52 + ' 53 + 54 + test_expect_success 'scalar invoked when enlistment root and repo are the same' ' 55 + test_when_finished rm -rf test src deeper && 56 + 57 + for enlistment_root in test src deeper/test 58 + do 59 + git init ${enlistment_root} && 60 + 61 + # Register 62 + scalar register ${enlistment_root} && 63 + scalar list >out && 64 + grep "$(pwd)/${enlistment_root}\$" out && 65 + 66 + # Delete (will not include enlistment root) 67 + scalar delete ${enlistment_root} && 68 + test_path_is_missing $enlistment_root && 69 + scalar list >out && 70 + ! grep "^$(pwd)/${enlistment_root}\$" out && 71 + 72 + # Make sure we did not accidentally delete the trash dir 73 + test_path_is_dir "$TRASH_DIRECTORY" || return 1 74 + done 75 + ' 76 + 77 + test_expect_success 'scalar repo search respects GIT_CEILING_DIRECTORIES' ' 78 + test_when_finished rm -rf test && 79 + 80 + git init test/src && 81 + mkdir -p test/src/deep && 82 + GIT_CEILING_DIRECTORIES="$(pwd)/test/src" && 83 + ! scalar register test/src/deep 2>err && 84 + grep "not a git repository" err 85 + ' 86 + 87 + test_expect_success 'scalar enlistments need a worktree' ' 88 + test_when_finished rm -rf bare test && 89 + 90 + git init --bare bare/src && 91 + ! scalar register bare/src 2>err && 92 + grep "Scalar enlistments require a worktree" err && 93 + 94 + git init test/src && 95 + ! scalar register test/src/.git 2>err && 96 + grep "Scalar enlistments require a worktree" err 97 + ' 98 + 99 + test_expect_success FSMONITOR_DAEMON 'scalar register starts fsmon daemon' ' 100 + git init test/src && 101 + test_must_fail git -C test/src fsmonitor--daemon status && 102 + scalar register test/src && 103 + git -C test/src fsmonitor--daemon status && 104 + test_cmp_config -C test/src true core.fsmonitor 105 + ' 106 + 107 + test_expect_success 'scalar unregister' ' 108 + git init vanish/src && 109 + scalar register vanish/src && 110 + git config --get --global --fixed-value \ 111 + maintenance.repo "$(pwd)/vanish/src" && 112 + scalar list >scalar.repos && 113 + grep -F "$(pwd)/vanish/src" scalar.repos && 114 + rm -rf vanish/src/.git && 115 + scalar unregister vanish && 116 + test_must_fail git config --get --global --fixed-value \ 117 + maintenance.repo "$(pwd)/vanish/src" && 118 + scalar list >scalar.repos && 119 + ! grep -F "$(pwd)/vanish/src" scalar.repos 120 + ' 121 + 122 + test_expect_success 'set up repository to clone' ' 123 + test_commit first && 124 + test_commit second && 125 + test_commit third && 126 + git switch -c parallel first && 127 + mkdir -p 1/2 && 128 + test_commit 1/2/3 && 129 + git config uploadPack.allowFilter true && 130 + git config uploadPack.allowAnySHA1InWant true 131 + ' 132 + 133 + test_expect_success 'scalar clone' ' 134 + second=$(git rev-parse --verify second:second.t) && 135 + scalar clone "file://$(pwd)" cloned --single-branch && 136 + ( 137 + cd cloned/src && 138 + 139 + git config --get --global --fixed-value maintenance.repo \ 140 + "$(pwd)" && 141 + 142 + git for-each-ref --format="%(refname)" refs/remotes/origin/ >actual && 143 + echo "refs/remotes/origin/parallel" >expect && 144 + test_cmp expect actual && 145 + 146 + test_path_is_missing 1/2 && 147 + test_must_fail git rev-list --missing=print $second && 148 + git rev-list $second && 149 + git cat-file blob $second >actual && 150 + echo "second" >expect && 151 + test_cmp expect actual 152 + ) 153 + ' 154 + 155 + test_expect_success 'scalar reconfigure' ' 156 + git init one/src && 157 + scalar register one && 158 + git -C one/src config core.preloadIndex false && 159 + scalar reconfigure one && 160 + test true = "$(git -C one/src config core.preloadIndex)" && 161 + git -C one/src config core.preloadIndex false && 162 + scalar reconfigure -a && 163 + test true = "$(git -C one/src config core.preloadIndex)" 164 + ' 165 + 166 + test_expect_success 'scalar delete without enlistment shows a usage' ' 167 + test_expect_code 129 scalar delete 168 + ' 169 + 170 + test_expect_success 'scalar delete with enlistment' ' 171 + scalar delete cloned && 172 + test_path_is_missing cloned 173 + ' 174 + 175 + test_expect_success 'scalar supports -c/-C' ' 176 + test_when_finished "scalar delete sub" && 177 + git init sub && 178 + scalar -C sub -c status.aheadBehind=bogus register && 179 + test -z "$(git -C sub config --local status.aheadBehind)" && 180 + test true = "$(git -C sub config core.preloadIndex)" 181 + ' 182 + 183 + test_expect_success '`scalar [...] <dir>` errors out when dir is missing' ' 184 + ! scalar run config cloned 2>err && 185 + grep "cloned. does not exist" err 186 + ' 187 + 188 + SQ="'" 189 + test_expect_success UNZIP 'scalar diagnose' ' 190 + scalar clone "file://$(pwd)" cloned --single-branch && 191 + git repack && 192 + echo "$(pwd)/.git/objects/" >>cloned/src/.git/objects/info/alternates && 193 + test_commit -C cloned/src loose && 194 + scalar diagnose cloned >out 2>err && 195 + grep "Available space" out && 196 + sed -n "s/.*$SQ\\(.*\\.zip\\)$SQ.*/\\1/p" <err >zip_path && 197 + zip_path=$(cat zip_path) && 198 + test -n "$zip_path" && 199 + "$GIT_UNZIP" -v "$zip_path" && 200 + folder=${zip_path%.zip} && 201 + test_path_is_missing "$folder" && 202 + "$GIT_UNZIP" -p "$zip_path" diagnostics.log >out && 203 + test_file_not_empty out && 204 + "$GIT_UNZIP" -p "$zip_path" packs-local.txt >out && 205 + grep "$(pwd)/.git/objects" out && 206 + "$GIT_UNZIP" -p "$zip_path" objects-local.txt >out && 207 + grep "^Total: [1-9]" out 208 + ' 209 + 210 + test_done
+151
t/t9211-scalar-clone.sh
··· 1 + #!/bin/sh 2 + 3 + test_description='test the `scalar clone` subcommand' 4 + 5 + . ./test-lib.sh 6 + 7 + GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab cron.txt,launchctl:true,schtasks:true" 8 + export GIT_TEST_MAINT_SCHEDULER 9 + 10 + test_expect_success 'set up repository to clone' ' 11 + rm -rf .git && 12 + git init to-clone && 13 + ( 14 + cd to-clone && 15 + git branch -m base && 16 + 17 + test_commit first && 18 + test_commit second && 19 + test_commit third && 20 + 21 + git switch -c parallel first && 22 + mkdir -p 1/2 && 23 + test_commit 1/2/3 && 24 + 25 + git switch base && 26 + 27 + # By default, permit 28 + git config uploadpack.allowfilter true && 29 + git config uploadpack.allowanysha1inwant true 30 + ) 31 + ' 32 + 33 + cleanup_clone () { 34 + rm -rf "$1" 35 + } 36 + 37 + test_expect_success 'creates content in enlistment root' ' 38 + enlistment=cloned && 39 + 40 + scalar clone "file://$(pwd)/to-clone" $enlistment && 41 + ls -A $enlistment >enlistment-root && 42 + test_line_count = 1 enlistment-root && 43 + test_path_is_dir $enlistment/src && 44 + test_path_is_dir $enlistment/src/.git && 45 + 46 + cleanup_clone $enlistment 47 + ' 48 + 49 + test_expect_success 'with spaces' ' 50 + enlistment="cloned with space" && 51 + 52 + scalar clone "file://$(pwd)/to-clone" "$enlistment" && 53 + test_path_is_dir "$enlistment" && 54 + test_path_is_dir "$enlistment/src" && 55 + test_path_is_dir "$enlistment/src/.git" && 56 + 57 + cleanup_clone "$enlistment" 58 + ' 59 + 60 + test_expect_success 'partial clone if supported by server' ' 61 + enlistment=partial-clone && 62 + 63 + scalar clone "file://$(pwd)/to-clone" $enlistment && 64 + 65 + ( 66 + cd $enlistment/src && 67 + 68 + # Two promisor packs: one for refs, the other for blobs 69 + ls .git/objects/pack/pack-*.promisor >promisorlist && 70 + test_line_count = 2 promisorlist 71 + ) && 72 + 73 + cleanup_clone $enlistment 74 + ' 75 + 76 + test_expect_success 'fall back on full clone if partial unsupported' ' 77 + enlistment=no-partial-support && 78 + 79 + test_config -C to-clone uploadpack.allowfilter false && 80 + test_config -C to-clone uploadpack.allowanysha1inwant false && 81 + 82 + scalar clone "file://$(pwd)/to-clone" $enlistment 2>err && 83 + grep "filtering not recognized by server, ignoring" err && 84 + 85 + ( 86 + cd $enlistment/src && 87 + 88 + # Still get a refs promisor file, but none for blobs 89 + ls .git/objects/pack/pack-*.promisor >promisorlist && 90 + test_line_count = 1 promisorlist 91 + ) && 92 + 93 + cleanup_clone $enlistment 94 + ' 95 + 96 + test_expect_success 'initializes sparse-checkout by default' ' 97 + enlistment=sparse && 98 + 99 + scalar clone "file://$(pwd)/to-clone" $enlistment && 100 + ( 101 + cd $enlistment/src && 102 + test_cmp_config true core.sparseCheckout && 103 + test_cmp_config true core.sparseCheckoutCone 104 + ) && 105 + 106 + cleanup_clone $enlistment 107 + ' 108 + 109 + test_expect_success '--full-clone does not create sparse-checkout' ' 110 + enlistment=full-clone && 111 + 112 + scalar clone --full-clone "file://$(pwd)/to-clone" $enlistment && 113 + ( 114 + cd $enlistment/src && 115 + test_cmp_config "" --default "" core.sparseCheckout && 116 + test_cmp_config "" --default "" core.sparseCheckoutCone 117 + ) && 118 + 119 + cleanup_clone $enlistment 120 + ' 121 + 122 + test_expect_success '--single-branch clones HEAD only' ' 123 + enlistment=single-branch && 124 + 125 + scalar clone --single-branch "file://$(pwd)/to-clone" $enlistment && 126 + ( 127 + cd $enlistment/src && 128 + git for-each-ref refs/remotes/origin >out && 129 + test_line_count = 1 out && 130 + grep "refs/remotes/origin/base" out 131 + ) && 132 + 133 + cleanup_clone $enlistment 134 + ' 135 + 136 + test_expect_success '--no-single-branch clones all branches' ' 137 + enlistment=no-single-branch && 138 + 139 + scalar clone --no-single-branch "file://$(pwd)/to-clone" $enlistment && 140 + ( 141 + cd $enlistment/src && 142 + git for-each-ref refs/remotes/origin >out && 143 + test_line_count = 2 out && 144 + grep "refs/remotes/origin/base" out && 145 + grep "refs/remotes/origin/parallel" out 146 + ) && 147 + 148 + cleanup_clone $enlistment 149 + ' 150 + 151 + test_done