From 1421fa36272f29e9c1f32ed3b62f12b8aa483603 Mon Sep 17 00:00:00 2001 From: Michael Lohmann Date: Tue, 16 Jan 2024 23:03:35 +0100 Subject: [PATCH] redeem-nuggit: store nuggits in objects of remote repository This is done in order to make it a) less likely that a player will find the dangling objects and b) eventually we want to show the player about dangling references and these just pollute the output --- build.sh | 8 +++----- lib.sh | 16 ++++++++++++---- src/hook_preamble.sh | 2 +- src/redeem-nuggit.sh | 35 ++++++++++++++++++++++++----------- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/build.sh b/build.sh index abd9736..2205659 100755 --- a/build.sh +++ b/build.sh @@ -52,13 +52,11 @@ git commit-tree "$(printf "" | git mktree)" -m "RootOfAllNuggits Have a free nuggit!" > .git/nuggits -# TODO: once we have the origin and another "clone" in the .git folder, we should store the blobs in there, because it is trivial to list all of them with `git fsck --dangling | cut -d " " -f3 | xargs -n 1 git cat-file -p` -# shellcheck disable=1091 # it does not seem to like the indirection store_nuggits -ALMOST_CREDITS_HASH="$(git hash-object -w "$DOCDIR/almost_credits.txt")" +ALMOST_CREDITS_HASH="$(remote_hash_object_write "$DOCDIR/almost_credits.txt")" # for the final credits do a little rot13, just to make life a bit harder if anyone e.g. greps through the loose objects... -FINAL_CREDITS_HASH="$(tr 'A-Za-z' 'N-ZA-Mn-za-m' < "$DOCDIR/credits.txt" | git hash-object -w --stdin)" -CREDITS_TREE="$(printf "100644 blob %s almost\n100644 blob %s final\n" "$ALMOST_CREDITS_HASH" "$FINAL_CREDITS_HASH" | git mktree)" +FINAL_CREDITS_HASH="$(tr 'A-Za-z' 'N-ZA-Mn-za-m' < "$DOCDIR/credits.txt" | remote_hash_object_write --stdin)" +CREDITS_TREE="$(printf "100644 blob %s almost\n100644 blob %s final\n" "$ALMOST_CREDITS_HASH" "$FINAL_CREDITS_HASH" | remote_mktree)" NUMBER_OF_NUGGITS="$(($(wc -l <"$DOCDIR/nuggits.tsv")))" diff --git a/lib.sh b/lib.sh index c51ef20..f44e456 100644 --- a/lib.sh +++ b/lib.sh @@ -101,6 +101,14 @@ create_chapter() { printf "\e[32mCreating chapter '%s'\e[0m\n" "$chapter" } +remote_git_dir=.git/my-origin +remote_mktree() { + GIT_DIR="$remote_git_dir" git mktree +} +remote_hash_object_write() { + GIT_DIR="$remote_git_dir" git hash-object -w "$@" +} + # register the nuggits in our "git database" (aka some loose objects) store_nuggits() { # To avoid the player just running @@ -109,14 +117,14 @@ store_nuggits() { # We create a folder with subfolders of the names of the nuggit hashes, and # each of them contains a file for the `git log nuggits`-description and # the custom success message when redeeming it - NUGGIT_DESCRIPTION_TREE="$(git mktree < <(while read -r line; do + NUGGIT_DESCRIPTION_TREE="$(remote_mktree < <(while read -r line; do nuggit="$(printf "%s" "$line" | cut -d " " -f 1)" nuggit_folder_name="$(echo "$nuggit" | git hash-object --stdin)" nuggit_description="$(printf "%s" "$line" | cut -d " " -f 2)" nuggit_success_message="$(printf "%s" "$line" | cut -d " " -f 3)" - nuggit_description_file_hash="$(git hash-object -w --stdin <<< "$nuggit_description")" - success_file_hash="$(echo "Success! What a nice nuggit for your collection! 🏅 $nuggit_success_message" | git hash-object -w --stdin)" - description_tree_hash="$(printf "100644 blob %s description\n100644 blob %s success\n" "$nuggit_description_file_hash" "$success_file_hash"| git mktree)" + nuggit_description_file_hash="$(remote_hash_object_write --stdin <<< "$nuggit_description")" + success_file_hash="$(echo "Success! What a nice nuggit for your collection! 🏅 $nuggit_success_message" | remote_hash_object_write --stdin)" + description_tree_hash="$(printf "100644 blob %s description\n100644 blob %s success\n" "$nuggit_description_file_hash" "$success_file_hash"| remote_mktree)" if [ "$nuggit" = LocalCodeExecution ]; then printf "%s" "$description_tree_hash" > tmp fi diff --git a/src/hook_preamble.sh b/src/hook_preamble.sh index 3501be8..bd4ae45 100755 --- a/src/hook_preamble.sh +++ b/src/hook_preamble.sh @@ -9,7 +9,7 @@ this_file="$0" hash="LOCAL_CODE_EXECUTION_HASH" # Make sure to delete the nuggit, so it can't be redeemed after this got triggered once -rm ".git/objects/${hash:0:2}/${hash:2}" +rm ".git/my-origin/objects/${hash:0:2}/${hash:2}" ( cd "$ROOT/.git/hooks" || exit diff --git a/src/redeem-nuggit.sh b/src/redeem-nuggit.sh index ccc1727..12a1f09 100755 --- a/src/redeem-nuggit.sh +++ b/src/redeem-nuggit.sh @@ -23,9 +23,22 @@ fi already_redeemed="'$nuggit' already redeemed" tried_before="You tried '$nuggit' before. It still isn't a valid answer... 🙄" +# A helper function to write to the remote git objects +# This is done, because: +# a) we don't want to "pollute" the local objects, since we eventually want to +# also teach the player about that and it would only be noise +# b) it makes it just a tiny bit harder to discover the nuggits +hash_object_write() { + GIT_DIR=.git/my-origin git hash-object --stdin -w >/dev/null 2>&1 +} +# A helper function to read from to the remote git objects +catfile() { + GIT_DIR=.git/my-origin git cat-file "$@" +} + redeemed=0 # check if this nuggit was already_redeemed -git cat-file -e "$(echo "$already_redeemed" | git hash-object --stdin)" 2>/dev/null && redeemed=1 +catfile -e "$(echo "$already_redeemed" | git hash-object --stdin)" 2>/dev/null && redeemed=1 # The total number of nuggits is one bigger than the already committed ones # because of the root commit, so we have to subtract 1 if this one was already # redeemed @@ -35,31 +48,31 @@ redeemed_nuggits="$(($(git rev-list --count nuggits) - redeemed))" # to give a hint that LocalCodeExecution is self-deleting. # CREDITS_TREE is a tree-object and CREDITS_TREE:almost means the blob with the # name "almost" inside of it -[ "$redeemed_nuggits" -ne $((NUMBER_OF_NUGGITS - 1)) ] || git cat-file -p CREDITS_TREE:almost; +[ "$redeemed_nuggits" -ne $((NUMBER_OF_NUGGITS - 1)) ] || catfile -p CREDITS_TREE:almost; # shellcheck disable=2170 # NUMBER_OF_NUGGITS will be replaced by an integer, once we "build" it. [ "$redeemed_nuggits" -ne NUMBER_OF_NUGGITS ] || { # check if the player did not just add a commit to our "nuggits" # pseudobranch by looking up if we wrote the last number of redeemed # nuggits to the objects. This is just a very basic "cheat-detection"... - git cat-file -e "$(git hash-object --stdin <<< "$((NUMBER_OF_NUGGITS - 1))" | git hash-object --stdin)" 2>/dev/null || { echo Naughty boy!; exit 1; } + catfile -e "$(git hash-object --stdin <<< "$((NUMBER_OF_NUGGITS - 1))" | git hash-object --stdin)" 2>/dev/null || { echo Naughty boy!; exit 1; } # print the final credits. See "almost" above for syntax description # Also do rot13 on the result in order to make it just a bit harder to just # find the blob and read it - git cat-file -p CREDITS_TREE:final | tr 'A-Za-z' 'N-ZA-Mn-za-m'; + catfile -p CREDITS_TREE:final | tr 'A-Za-z' 'N-ZA-Mn-za-m'; } # if we already have redeemed this nuggit, print that it was already redeemed and exit -git cat-file -p "$(echo "$already_redeemed" | git hash-object --stdin)" 2>/dev/null && exit +catfile -p "$(echo "$already_redeemed" | git hash-object --stdin)" 2>/dev/null && exit # if the user already tried to submit this wrong string, print the error and exit -git cat-file -p "$(echo "$tried_before" | git hash-object --stdin)" 2>/dev/null && exit 1 +catfile -p "$(echo "$tried_before" | git hash-object --stdin)" 2>/dev/null && exit 1 # Print the success message for this nuggit if it exists -git cat-file -p "NUGGIT_DESCRIPTION_TREE:$(echo "$nuggit" | git hash-object --stdin)/success" 2>/dev/null || { +catfile -p "NUGGIT_DESCRIPTION_TREE:$(echo "$nuggit" | git hash-object --stdin)/success" 2>/dev/null || { # if it does not exist, then this is not a valid nuggit (or it was # LocalCodeExecution and that was deleted) echo "Unfortunately that is not a valid nuggit :/ Try again!" >&2 - echo "$tried_before" | git hash-object --stdin -w >/dev/null 2>&1 + echo "$tried_before" | hash_object_write >/dev/null 2>&1 exit 1 } @@ -69,7 +82,7 @@ git cat-file -p "NUGGIT_DESCRIPTION_TREE:$(echo "$nuggit" | git hash-object --st tree="$(git rev-parse "nuggits^{tree}")" # get the description from our "nuggit tree object" from the folder with # the hash of the nuggit and inside of that the description file -description="$(git cat-file -p "NUGGIT_DESCRIPTION_TREE:$(echo "$nuggit" | git hash-object --stdin)/description")" +description="$(catfile -p "NUGGIT_DESCRIPTION_TREE:$(echo "$nuggit" | git hash-object --stdin)/description")" # add an empty commit with the parent being nuggits and "reset nuggits to that new commit" git commit-tree "$tree" -p "$(cat .git/nuggits)" -m "$(printf "%s\n\n" "$nuggit" "$description")" > .git/nuggits.bak # We can't directly pipe it into the file, because it will empty it before we read it... @@ -79,6 +92,6 @@ mv .git/nuggits.bak .git/nuggits # update our "branch" # Print some stats for the player, so they know if they still need to look for other nuggits echo "Number of redeemed nuggits: $redeemed_nuggits of NUMBER_OF_NUGGITS" # Write to our database, that this nuggit is now redeemed -echo "$already_redeemed" | git hash-object --stdin -w >/dev/null 2>&1 +echo "$already_redeemed" | hash_object_write # Write as a "cheat-detection" for the final credits how many we have redeemed -git hash-object --stdin <<< "$redeemed_nuggits"| git hash-object --stdin -w >/dev/null 2>&1 +git hash-object --stdin <<< "$redeemed_nuggits"| hash_object_write