Skip to content

Commit

Permalink
redeem-nuggit: store nuggits in objects of remote repository
Browse files Browse the repository at this point in the history
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
  • Loading branch information
miallo committed Jan 16, 2024
1 parent 0fc633b commit 1421fa3
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 21 deletions.
8 changes: 3 additions & 5 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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")))"

Expand Down
16 changes: 12 additions & 4 deletions lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/hook_preamble.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 24 additions & 11 deletions src/redeem-nuggit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}

Expand All @@ -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...
Expand All @@ -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

0 comments on commit 1421fa3

Please sign in to comment.