]> git.ipfire.org Git - thirdparty/git.git/commitdiff
t/lib-httpd: refactor "one-time-perl" CGI script to not depend on Perl
authorPatrick Steinhardt <ps@pks.im>
Thu, 3 Apr 2025 05:06:07 +0000 (07:06 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 7 Apr 2025 21:47:40 +0000 (14:47 -0700)
Our Apache HTTPD setup exposes an "one_time_perl" endpoint to access
repositories. If used, we execute the "apply-one-time-perl.sh" CGI
script that checks whether we have a "one-time-perl" script. If so, that
script gets executed so that it can munge what would be served. Once
done, the script gets removed so that it doesn't execute a second time.

As the name says, this functionality expects the user to pass a Perl
script. This isn't really necessary though: we can just as easily
implement the same thing with arbitrary scripts.

Refactor the code so that we instead expect an arbitrary script to
exist and rename the functionality to "one-time-script". Adapt callers
to use shell utilities instead of Perl so that we can drop the
PERL_TEST_HELPERS prerequisite.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
t/lib-httpd.sh
t/lib-httpd/apache.conf
t/lib-httpd/apply-one-time-perl.sh [deleted file]
t/lib-httpd/apply-one-time-script.sh [new file with mode: 0644]
t/t5537-fetch-shallow.sh
t/t5616-partial-clone.sh
t/t5702-protocol-v2.sh
t/t5703-upload-pack-ref-in-want.sh

index d83bafeab32d40d6fd373e084757221ac7181d06..5091db949b7f998be8ef1dde7fd0efe37bbe032f 100644 (file)
@@ -165,7 +165,7 @@ prepare_httpd() {
        install_script broken-smart-http.sh
        install_script error-smart-http.sh
        install_script error.sh
-       install_script apply-one-time-perl.sh
+       install_script apply-one-time-script.sh
        install_script nph-custom-auth.sh
 
        ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
index 022276a6b9ace5565211327053f9900ff4a1fb06..e631ab0eb5ef051a199a93dcc52fcf603420dc21 100644 (file)
@@ -135,7 +135,7 @@ SetEnv PERL_PATH ${PERL_PATH}
        SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
        SetEnv GIT_HTTP_EXPORT_ALL
 </LocationMatch>
-<LocationMatch /one_time_perl/>
+<LocationMatch /one_time_script/>
        SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
        SetEnv GIT_HTTP_EXPORT_ALL
 </LocationMatch>
@@ -159,7 +159,7 @@ ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
 ScriptAlias /broken_smart/ broken-smart-http.sh/
 ScriptAlias /error_smart/ error-smart-http.sh/
 ScriptAlias /error/ error.sh/
-ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1
+ScriptAliasMatch /one_time_script/(.*) apply-one-time-script.sh/$1
 ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1
 <Directory ${GIT_EXEC_PATH}>
        Options FollowSymlinks
@@ -182,7 +182,7 @@ ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1
 <Files error.sh>
   Options ExecCGI
 </Files>
-<Files apply-one-time-perl.sh>
+<Files apply-one-time-script.sh>
        Options ExecCGI
 </Files>
 <Files ${GIT_EXEC_PATH}/git-http-backend>
diff --git a/t/lib-httpd/apply-one-time-perl.sh b/t/lib-httpd/apply-one-time-perl.sh
deleted file mode 100644 (file)
index d7f9fed..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-# If "one-time-perl" exists in $HTTPD_ROOT_PATH, run perl on the HTTP response,
-# using the contents of "one-time-perl" as the perl command to be run. If the
-# response was modified as a result, delete "one-time-perl" so that subsequent
-# HTTP responses are no longer modified.
-#
-# This can be used to simulate the effects of the repository changing in
-# between HTTP request-response pairs.
-if test -f one-time-perl
-then
-       LC_ALL=C
-       export LC_ALL
-
-       "$GIT_EXEC_PATH/git-http-backend" >out
-       "$PERL_PATH" -pe "$(cat one-time-perl)" out >out_modified
-
-       if cmp -s out out_modified
-       then
-               cat out
-       else
-               cat out_modified
-               rm one-time-perl
-       fi
-else
-       "$GIT_EXEC_PATH/git-http-backend"
-fi
diff --git a/t/lib-httpd/apply-one-time-script.sh b/t/lib-httpd/apply-one-time-script.sh
new file mode 100644 (file)
index 0000000..b168294
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# If "one-time-script" exists in $HTTPD_ROOT_PATH, run the script on the HTTP
+# response. If the response was modified as a result, delete "one-time-script"
+# so that subsequent HTTP responses are no longer modified.
+#
+# This can be used to simulate the effects of the repository changing in
+# between HTTP request-response pairs.
+if test -f one-time-script
+then
+       LC_ALL=C
+       export LC_ALL
+
+       "$GIT_EXEC_PATH/git-http-backend" >out
+       ./one-time-script out >out_modified
+
+       if cmp -s out out_modified
+       then
+               cat out
+       else
+               cat out_modified
+               rm one-time-script
+       fi
+else
+       "$GIT_EXEC_PATH/git-http-backend"
+fi
index 77d20d191103542ce0946b83ddda9969d507461a..6588ce62264331919110fbe729154be336ca08da 100755 (executable)
@@ -256,7 +256,7 @@ start_httpd
 
 REPO="$HTTPD_DOCUMENT_ROOT_PATH/repo"
 
-test_expect_success PERL_TEST_HELPERS 'shallow fetches check connectivity before writing shallow file' '
+test_expect_success 'shallow fetches check connectivity before writing shallow file' '
        rm -rf "$REPO" client &&
 
        git init "$REPO" &&
@@ -271,22 +271,21 @@ test_expect_success PERL_TEST_HELPERS 'shallow fetches check connectivity before
        git -C "$REPO" config protocol.version 2 &&
        git -C client config protocol.version 2 &&
 
-       git -C client fetch --depth=2 "$HTTPD_URL/one_time_perl/repo" main:a_branch &&
+       git -C client fetch --depth=2 "$HTTPD_URL/one_time_script/repo" main:a_branch &&
 
        # Craft a situation in which the server sends back an unshallow request
        # with an empty packfile. This is done by refetching with a shorter
        # depth (to ensure that the packfile is empty), and overwriting the
        # shallow line in the response with the unshallow line we want.
-       printf "$(test_oid perl)" \
-              "$(git -C "$REPO" rev-parse HEAD)" \
-              "$(git -C "$REPO" rev-parse HEAD^)" \
-              >"$HTTPD_ROOT_PATH/one-time-perl" &&
+       write_script "$HTTPD_ROOT_PATH/one-time-script" <<-EOF &&
+       sed "$(printf "$(test_oid perl)" "$(git -C "$REPO" rev-parse HEAD)" "$(git -C "$REPO" rev-parse HEAD^)")" "\$1"
+       EOF
        test_must_fail env GIT_TEST_SIDEBAND_ALL=0 git -C client \
-               fetch --depth=1 "$HTTPD_URL/one_time_perl/repo" \
+               fetch --depth=1 "$HTTPD_URL/one_time_script/repo" \
                main:a_branch &&
 
-       # Ensure that the one-time-perl script was used.
-       ! test -e "$HTTPD_ROOT_PATH/one-time-perl" &&
+       # Ensure that the one-time-script script was used.
+       ! test -e "$HTTPD_ROOT_PATH/one-time-script" &&
 
        # Ensure that the resulting repo is consistent, despite our failure to
        # fetch.
index bc7e0fec8dcdbb1ab2a6c851f8ae52676c958cc7..1e354e057fa12ce354c8146bd3920b380d97a08e 100755 (executable)
@@ -737,21 +737,25 @@ intersperse () {
        sed 's/\(..\)/'$1'\1/g'
 }
 
-# Create a one-time-perl command to replace the existing packfile with $1.
+# Create a one-time-script command to replace the existing packfile with $1.
 replace_packfile () {
-       # The protocol requires that the packfile be sent in sideband 1, hence
-       # the extra \x01 byte at the beginning.
-       cp $1 "$HTTPD_ROOT_PATH/one-time-pack" &&
-       echo 'if (/packfile/) {
-               print;
-               my $length = -s "one-time-pack";
-               printf "%04x\x01", $length + 5;
-               print `cat one-time-pack` . "0000";
-               last
-       }' >"$HTTPD_ROOT_PATH/one-time-perl"
+       cp "$1" one-time-pack &&
+       write_script "$HTTPD_ROOT_PATH/one-time-script" <<-EOF
+       if grep packfile "\$1" >/dev/null
+       then
+               sed '/packfile/q' "\$1" &&
+               # The protocol requires that the packfile be sent in sideband
+               # 1, hence the extra \001 byte at the beginning.
+               printf "%04x\001" \$((\$(wc -c <"$PWD/one-time-pack") + 5)) &&
+               cat "$PWD/one-time-pack" &&
+               printf "0000"
+       else
+               cat "\$1"
+       fi
+       EOF
 }
 
-test_expect_success PERL_TEST_HELPERS 'upon cloning, check that all refs point to objects' '
+test_expect_success 'upon cloning, check that all refs point to objects' '
        SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
        rm -rf "$SERVER" repo &&
        test_create_repo "$SERVER" &&
@@ -776,15 +780,15 @@ test_expect_success PERL_TEST_HELPERS 'upon cloning, check that all refs point t
        # section header.
        test_config -C "$SERVER" protocol.version 2 &&
        test_must_fail git -c protocol.version=2 clone \
-               --filter=blob:none $HTTPD_URL/one_time_perl/server repo 2>err &&
+               --filter=blob:none $HTTPD_URL/one_time_script/server repo 2>err &&
 
        test_grep "did not send all necessary objects" err &&
 
-       # Ensure that the one-time-perl script was used.
-       ! test -e "$HTTPD_ROOT_PATH/one-time-perl"
+       # Ensure that the one-time-script script was used.
+       ! test -e "$HTTPD_ROOT_PATH/one-time-script"
 '
 
-test_expect_success PERL_TEST_HELPERS 'when partial cloning, tolerate server not sending target of tag' '
+test_expect_success 'when partial cloning, tolerate server not sending target of tag' '
        SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
        rm -rf "$SERVER" repo &&
        test_create_repo "$SERVER" &&
@@ -818,11 +822,11 @@ test_expect_success PERL_TEST_HELPERS 'when partial cloning, tolerate server not
 
        # Exercise to make sure it works.
        git -c protocol.version=2 clone \
-               --filter=blob:none $HTTPD_URL/one_time_perl/server repo 2> err &&
+               --filter=blob:none $HTTPD_URL/one_time_script/server repo 2> err &&
        ! grep "missing object referenced by" err &&
 
-       # Ensure that the one-time-perl script was used.
-       ! test -e "$HTTPD_ROOT_PATH/one-time-perl"
+       # Ensure that the one-time-script script was used.
+       ! test -e "$HTTPD_ROOT_PATH/one-time-script"
 '
 
 test_expect_success PERL_TEST_HELPERS 'tolerate server sending REF_DELTA against missing promisor objects' '
@@ -845,7 +849,7 @@ test_expect_success PERL_TEST_HELPERS 'tolerate server sending REF_DELTA against
 
        # Clone. The client has deltabase_have but not deltabase_missing.
        git -c protocol.version=2 clone --no-checkout \
-               --filter=blob:none $HTTPD_URL/one_time_perl/server repo &&
+               --filter=blob:none $HTTPD_URL/one_time_script/server repo &&
        git -C repo hash-object -w -- "$SERVER/have.txt" &&
 
        # Sanity check to ensure that the client does not have
@@ -899,8 +903,8 @@ test_expect_success PERL_TEST_HELPERS 'tolerate server sending REF_DELTA against
        grep "want $(cat deltabase_missing)" trace &&
        ! grep "want $(cat deltabase_have)" trace &&
 
-       # Ensure that the one-time-perl script was used.
-       ! test -e "$HTTPD_ROOT_PATH/one-time-perl"
+       # Ensure that the one-time-script script was used.
+       ! test -e "$HTTPD_ROOT_PATH/one-time-script"
 '
 
 # DO NOT add non-httpd-specific tests here, because the last part of this
index ad5e772cd725d4df9950463862828a0519e06d93..8548854f32ecc420a6ba14312ac9353920e1f884 100755 (executable)
@@ -1120,7 +1120,7 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' '
        ! grep "git< version 2" log
 '
 
-test_expect_success PERL_TEST_HELPERS 'when server sends "ready", expect DELIM' '
+test_expect_success 'when server sends "ready", expect DELIM' '
        rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child &&
 
        git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
@@ -1132,15 +1132,16 @@ test_expect_success PERL_TEST_HELPERS 'when server sends "ready", expect DELIM'
 
        # After "ready" in the acknowledgments section, pretend that a FLUSH
        # (0000) was sent instead of a DELIM (0001).
-       printf "\$ready = 1 if /ready/; \$ready && s/0001/0000/" \
-               >"$HTTPD_ROOT_PATH/one-time-perl" &&
+       write_script "$HTTPD_ROOT_PATH/one-time-script" <<-\EOF &&
+       sed "/ready/{n;s/0001/0000/;}" "$1"
+       EOF
 
        test_must_fail git -C http_child -c protocol.version=2 \
-               fetch "$HTTPD_URL/one_time_perl/http_parent" 2> err &&
+               fetch "$HTTPD_URL/one_time_script/http_parent" 2> err &&
        test_grep "expected packfile to be sent after .ready." err
 '
 
-test_expect_success PERL_TEST_HELPERS 'when server does not send "ready", expect FLUSH' '
+test_expect_success 'when server does not send "ready", expect FLUSH' '
        rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child log &&
 
        git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
@@ -1157,12 +1158,13 @@ test_expect_success PERL_TEST_HELPERS 'when server does not send "ready", expect
 
        # After the acknowledgments section, pretend that a DELIM
        # (0001) was sent instead of a FLUSH (0000).
-       printf "\$ack = 1 if /acknowledgments/; \$ack && s/0000/0001/" \
-               >"$HTTPD_ROOT_PATH/one-time-perl" &&
+       write_script "$HTTPD_ROOT_PATH/one-time-script" <<-\EOF &&
+       sed "/acknowledgments/,//{s/0000/0001/;}" "$1"
+       EOF
 
        test_must_fail env GIT_TRACE_PACKET="$(pwd)/log" git -C http_child \
                -c protocol.version=2 \
-               fetch "$HTTPD_URL/one_time_perl/http_parent" 2> err &&
+               fetch "$HTTPD_URL/one_time_script/http_parent" 2> err &&
        grep "fetch< .*acknowledgments" log &&
        ! grep "fetch< .*ready" log &&
        test_grep "expected no other sections to be sent after no .ready." err
@@ -1446,14 +1448,15 @@ test_expect_success 'http:// --negotiate-only' '
        grep "$COMMON" out
 '
 
-test_expect_success PERL_TEST_HELPERS 'http:// --negotiate-only without wait-for-done support' '
+test_expect_success 'http:// --negotiate-only without wait-for-done support' '
        SERVER="server" &&
-       URI="$HTTPD_URL/one_time_perl/server" &&
+       URI="$HTTPD_URL/one_time_script/server" &&
 
        setup_negotiate_only "$SERVER" "$URI" &&
 
-       echo "s/ wait-for-done/ xxxx-xxx-xxxx/" \
-               >"$HTTPD_ROOT_PATH/one-time-perl" &&
+       write_script "$HTTPD_ROOT_PATH/one-time-script" <<-\EOF &&
+       sed "s/ wait-for-done/ xxxx-xxx-xxxx/" "$1"
+       EOF
 
        test_must_fail git -c protocol.version=2 -C client fetch \
                --no-tags \
index f59d47aa6c62a9ed8664aed0fdd03759708f81a7..fc915e7b823e80e227729850e6460b191f5ee334 100755 (executable)
@@ -468,7 +468,7 @@ test_expect_success 'setup repos for change-while-negotiating test' '
                test_commit m3 &&
                git tag -d m2 m3
        ) &&
-       git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_perl/repo" &&
+       git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_script/repo" &&
        git -C "$LOCAL_PRISTINE" config protocol.version 2
 '
 
@@ -481,7 +481,9 @@ inconsistency () {
        # RPCs during a single negotiation.
        oid1=$(git -C "$REPO" rev-parse $1) &&
        oid2=$(git -C "$REPO" rev-parse $2) &&
-       echo "s/$oid1/$oid2/" >"$HTTPD_ROOT_PATH/one-time-perl"
+       write_script "$HTTPD_ROOT_PATH/one-time-script" <<-EOF
+       sed "s/$oid1/$oid2/" "\$1"
+       EOF
 }
 
 test_expect_success 'server is initially ahead - no ref in want' '
@@ -533,7 +535,9 @@ test_expect_success 'server loses a ref - ref in want' '
        git -C "$REPO" config uploadpack.allowRefInWant true &&
        rm -rf local &&
        cp -r "$LOCAL_PRISTINE" local &&
-       echo "s/main/rain/" >"$HTTPD_ROOT_PATH/one-time-perl" &&
+       write_script "$HTTPD_ROOT_PATH/one-time-script" <<-\EOF &&
+       sed "s/main/rain/" "$1"
+       EOF
        test_must_fail git -C local fetch 2>err &&
 
        test_grep "fatal: remote error: unknown ref refs/heads/rain" err