aboutsummaryrefslogtreecommitdiff
path: root/comp2041/tigger
diff options
context:
space:
mode:
authorNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-13 18:00:17 +1100
committerNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-13 18:00:17 +1100
commit98cef5e9a772602d42acfcf233838c760424db9a (patch)
tree5277fa1d7cc0a69a0f166fcbf10fd320f345f049 /comp2041/tigger
initial commit
Diffstat (limited to 'comp2041/tigger')
-rwxr-xr-xcomp2041/tigger/test00.sh58
-rwxr-xr-xcomp2041/tigger/test01.sh53
-rwxr-xr-xcomp2041/tigger/test02.sh73
-rwxr-xr-xcomp2041/tigger/test03.sh56
-rwxr-xr-xcomp2041/tigger/test04.sh45
-rwxr-xr-xcomp2041/tigger/test05.sh46
-rwxr-xr-xcomp2041/tigger/test06.sh62
-rwxr-xr-xcomp2041/tigger/test07.sh51
-rwxr-xr-xcomp2041/tigger/test08.sh70
-rwxr-xr-xcomp2041/tigger/test09.sh61
-rwxr-xr-xcomp2041/tigger/tigger-add42
-rwxr-xr-xcomp2041/tigger/tigger-branch68
-rwxr-xr-xcomp2041/tigger/tigger-checkout84
-rwxr-xr-xcomp2041/tigger/tigger-commit88
-rwxr-xr-xcomp2041/tigger/tigger-init39
-rwxr-xr-xcomp2041/tigger/tigger-log24
-rwxr-xr-xcomp2041/tigger/tigger-rm66
-rwxr-xr-xcomp2041/tigger/tigger-show63
-rwxr-xr-xcomp2041/tigger/tigger-status100
19 files changed, 1149 insertions, 0 deletions
diff --git a/comp2041/tigger/test00.sh b/comp2041/tigger/test00.sh
new file mode 100755
index 0000000..b76f4a3
--- /dev/null
+++ b/comp2041/tigger/test00.sh
@@ -0,0 +1,58 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to ensure that removing the expected .tigger
+# folder does reset the state of tigger. In addition, there should be NO extra
+# files at the end of this operation, even if it fails. We are only allowed to
+# edit/create .tigger and what is inside .tigger!
+
+num_files_before=$(find ./ | wc -l)
+assert_good_exec "./tigger-init"
+num_files_after=$(find ./ | wc -l)
+assert_bad_exec "./tigger-init" # should make no more files
+if [ "$(find ./ | wc -l)" -ne "$num_files_after" ]; then
+ printf "the amount of files should be equal to before when tigger-init was called previously!\n" >&2
+ exit 1
+fi
+rm -rf ./.tigger
+if [ "$(find ./ | wc -l)" -ne "$num_files_before" ]; then
+ printf "there should be the same amount as files as before any commands were run!\n" >&2
+ exit 1
+fi
+assert_good_exec "./tigger-init"
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/test01.sh b/comp2041/tigger/test01.sh
new file mode 100755
index 0000000..246ed2a
--- /dev/null
+++ b/comp2041/tigger/test01.sh
@@ -0,0 +1,53 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to ensure that all commands fail if a valid
+# repository is not present (naturally aside from tigger-init).
+
+#assert_bad_exec "./tigger-init"
+assert_bad_exec "./tigger-add"
+assert_bad_exec "./tigger-commit"
+assert_bad_exec "./tigger-log"
+assert_bad_exec "./tigger-show"
+assert_bad_exec "./tigger-commit"
+assert_bad_exec "./tigger-rm"
+assert_bad_exec "./tigger-status"
+assert_bad_exec "./tigger-branch"
+assert_bad_exec "./tigger-checkout"
+assert_bad_exec "./tigger-merge"
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/test02.sh b/comp2041/tigger/test02.sh
new file mode 100755
index 0000000..461da82
--- /dev/null
+++ b/comp2041/tigger/test02.sh
@@ -0,0 +1,73 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to ensure that there are no arbitrary limits on
+# the amount of times a command may be performed, and that file
+# creation/deletion and increment logic is handled correctly between commits.
+# It's possible that this fails due to bad increment handling at the radix
+# point (if a program is implemented incorrectly). This test might also expose
+# complexity issues if they are present.
+
+# Specifically we might use sort as opposed to sort -n, which works until 10.
+# ... i did :(
+
+assert_good_exec "./tigger-init"
+printf "adding and committing large number of files...\n"
+for _ in $(seq 25); do
+ echo "repeated\n" >> repeated
+ assert_good_exec "./tigger-add repeated" > /dev/null
+ assert_good_exec "./tigger-commit -m placeholder" > /dev/null
+done
+
+# Commit count should be 50 here!
+printf "testing commit count string result\n"
+printf "repeated\n" >> repeated
+assert_good_exec "./tigger-add repeated" > /dev/null
+if [ "$(./tigger-commit -m placeholder)" != "Committed as commit 25" ]; then
+ printf "bad commit count string\n" >&2
+ exit 0
+fi
+
+# New one added so 26 now.
+printf "testing tigger-log line count\n"
+assert_good_exec "./tigger-log" > /dev/null
+if [ "$(./tigger-log | wc --line)" -ne 26 ]; then
+ printf "bad tigger log string length\n" >&2
+ exit 0
+fi
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/test03.sh b/comp2041/tigger/test03.sh
new file mode 100755
index 0000000..6ce8559
--- /dev/null
+++ b/comp2041/tigger/test03.sh
@@ -0,0 +1,56 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to test whether tigger-add handles a large number
+# of filenames. Also tests tigger-status against a new, uncommitted repo.
+
+assert_good_exec "./tigger-init"
+filenames=$(seq 20)
+printf "adding large number of files...\n"
+for filename in $filenames; do
+ touch "$filename" > /dev/null
+ assert_good_exec "./tigger-add $filename" > /dev/null
+done
+
+# Test the length of tigger-status.
+printf "testing tigger-status line count\n"
+if [ "$(./tigger-status | wc --line)" -ge 100 ]; then
+ printf "bad tigger status line count\n" >&2
+ exit 1
+fi
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/test04.sh b/comp2041/tigger/test04.sh
new file mode 100755
index 0000000..80f7b2e
--- /dev/null
+++ b/comp2041/tigger/test04.sh
@@ -0,0 +1,45 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to ensure that it isn't possible to commit a
+# binary file. (as specified, all files should be string-representable).
+
+assert_good_exec "./tigger-init"
+dd if=/dev/zero of=zero bs=1c count=1 status=none # stack overflow make binary file
+assert_bad_exec "./tigger-add a" >&2
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/test05.sh b/comp2041/tigger/test05.sh
new file mode 100755
index 0000000..cc49cd1
--- /dev/null
+++ b/comp2041/tigger/test05.sh
@@ -0,0 +1,46 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to ensure that adding a file with spacebars
+# results in an error. This is specified to not occur in the spec, but it should
+# still be handled correctly.
+
+assert_good_exec "./tigger-init"
+printf "placeholder contents" > "file name"
+assert_bad_exec "./tigger-add "file name""
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/test06.sh b/comp2041/tigger/test06.sh
new file mode 100755
index 0000000..33c93f6
--- /dev/null
+++ b/comp2041/tigger/test06.sh
@@ -0,0 +1,62 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to ensure that deleting a .tigger folder, and then
+# restoring the folder, results in the same state that occurred before deletion.
+# This implies that the metadata is held only in the .tigger directory.
+
+assert_good_exec "./tigger-init"
+touch a
+touch b
+touch c
+assert_good_exec "./tigger-add a b c"
+echo a >> a
+assert_good_exec "./tigger-add a"
+touch d
+assert_good_exec "./tigger-commit -m commit_message"
+status=$(./tigger-status)
+mv ./.tigger ./.tigger.old
+assert_good_exec "./tigger-init"
+rm -r ./.tigger
+mv ./.tigger.old ./.tigger
+printf "testing previous status is the same as the current status\n"
+if [ "$(./tigger-status)" != "$status" ]; then
+ printf "tigger-status was not the same between copies\n" >&2
+ exit 1
+fi
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/test07.sh b/comp2041/tigger/test07.sh
new file mode 100755
index 0000000..fdffb7c
--- /dev/null
+++ b/comp2041/tigger/test07.sh
@@ -0,0 +1,51 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to ensure that calling ./tigger-status and
+# tigger-log in an empty directory is not considered an error and results in
+# empty output.
+
+assert_good_exec "./tigger-init"
+assert_good_exec "./tigger-status"
+assert_good_exec "./tigger-log"
+printf "testing tigger status in an empty dir\n"
+if [ "$(./tigger-status | grep -E -v "^tigger-*")" != "" ]; then # remove tigger-* files from output
+ printf "tigger-status was not empty in an empty dir\n" >&2
+ exit 1
+fi
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/test08.sh b/comp2041/tigger/test08.sh
new file mode 100755
index 0000000..6d9116f
--- /dev/null
+++ b/comp2041/tigger/test08.sh
@@ -0,0 +1,70 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to ensure that creating a new branch from an empty
+# branch branches with multiple files with multiple commits and then deleting
+# the branch results in the same status as an empty branch.
+
+# TODO CURRENTLY DOESNT FUNCTION BECAUSE CHECKOUT IS WRONG IN MY IMPLEMENTATION!
+
+printf "WARNING: DOESN'T FUNCTION DUE TO NON FULLY IMPLEMENTED CHECKOUT\n\n"
+
+assert_good_exec "./tigger-init"
+touch z
+assert_good_exec "./tigger-add z"
+assert_good_exec "./tigger-commit -m commitmessage"
+before_status=$(./tigger-status)
+assert_good_exec "./tigger-branch new"
+assert_good_exec "./tigger-checkout new"
+touch a
+touch b
+assert_good_exec "./tigger-add a b"
+assert_good_exec "./tigger-commit -m commitmessage"
+touch c
+touch d
+assert_good_exec "./tigger-add c d"
+assert_good_exec "./tigger-commit -m commitmessage"
+assert_good_exec "./tigger-checkout master"
+assert_good_exec "./tigger-branch -d new"
+
+printf "testing tigger status is the same as before the branch was created\n"
+if [ "$(./tigger-status)" != "$before_status" ]; then
+ printf "tigger-status was not empty in an empty dir\n" >&2
+ exit 1
+fi
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/test09.sh b/comp2041/tigger/test09.sh
new file mode 100755
index 0000000..6931de6
--- /dev/null
+++ b/comp2041/tigger/test09.sh
@@ -0,0 +1,61 @@
+#!/bin/dash
+
+# Test startup, create a temporary directory and cd into it with files.
+tmp_dir=$(mktemp --directory --quiet --tmpdir=./)
+if [ "$(find tigger-* | wc -l)" -le 0 ]; then
+ printf "error: no tigger commands found, cannot run tests\n" >&2
+ exit 1
+fi
+cp tigger-* "$tmp_dir"/
+cd "$tmp_dir" || exit
+
+# Functions to test if the return value was 0 or non-zero.
+assert_good_exec () {
+ printf "%s: " "$1"
+ if $1; then
+ return
+ fi
+ printf "test failed, previous command expected zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+# Functions to test if the return value was 0 or non-zero.
+assert_bad_exec () {
+ printf "%s: " "$1"
+ if ! $1; then
+ return
+ fi
+ printf "test failed, previous command expected non-zero output code\n" >&2
+ rm -rf ../"$tmp_dir"
+ exit 1
+}
+printf "starting tests: output and order will be printed\n\n"
+# End of test startup
+
+# The purpose of this test is to ensure that tigger-rm'ing a file can still be
+# retrieved later (provided it was in a different commit).
+assert_good_exec "./tigger-init"
+printf "contents" > a
+assert_good_exec "./tigger-add a"
+assert_good_exec "./tigger-commit -m commitmessage"
+assert_good_exec "./tigger-rm a"
+assert_good_exec "./tigger-commit -m commitmessage"
+
+# Ensure it was deleted.
+if [ -e a ]; then
+ printf "error: file was not deleted after git rm\n" >&2
+ exit 1
+fi
+
+# Ensure it can be later retrieved.
+assert_good_exec "./tigger-show 0:a"
+if [ "$(./tigger-show 0:a)" = "" ]; then
+ printf "error: file was not retrievable after git rm\n" >&2
+ exit 1
+fi
+
+
+# Test teardown/cleanup
+printf "\ntest completed successfully\n"
+rm -rf ../"$tmp_dir"
+exit 0
diff --git a/comp2041/tigger/tigger-add b/comp2041/tigger/tigger-add
new file mode 100755
index 0000000..4ec51bb
--- /dev/null
+++ b/comp2041/tigger/tigger-add
@@ -0,0 +1,42 @@
+#!/bin/dash
+
+# Test if we have a valid repo before doing anything.
+if ! [ -d ".tigger/" ]; then
+ printf "tigger-add: error: tigger repository directory .tigger not found\n"
+ exit 1
+fi
+
+# Get current branch, then current commit (default 0).
+branch=$(cat .tigger/branch.tig)
+mkdir --parents ".tigger/$branch/"
+
+
+# Grabs the latest commit
+commit=$(find .tigger/"$branch"/ -maxdepth 1 -type d | grep -o -E "[\/][^\/]*$" | tr -d "/" | sort -n -r | head -n 1)
+if [ "$commit" = "" ]; then
+ commit="0"
+ mkdir --parents ".tigger/$branch/$commit/"
+fi
+
+
+staged_dir=".tigger/$branch/$commit/staged/"
+mkdir --parents "$staged_dir"
+for filename in "$@"; do
+
+ if ! [ -f "$filename" ]; then
+
+ # If it doesn't exist in the dir, but does exist in staged, delete staged.
+ if [ -f .tigger/"$branch"/"$commit"/staged/"$filename" ]; then
+ rm --force .tigger/"$branch"/"$commit"/staged/"$filename"
+ continue
+ fi
+
+ printf "tigger-add: error: can not open '%s'\n" "$filename"
+ exit 1
+ fi
+
+
+ cp "$filename" "$staged_dir"
+done
+
+exit 0
diff --git a/comp2041/tigger/tigger-branch b/comp2041/tigger/tigger-branch
new file mode 100755
index 0000000..f4a5472
--- /dev/null
+++ b/comp2041/tigger/tigger-branch
@@ -0,0 +1,68 @@
+#!/bin/dash
+
+# Test if we have a valid repo before doing anything.
+if ! [ -d ".tigger/" ]; then
+ printf "tigger-add: error: tigger repository directory .tigger not found\n" >&2
+ exit 1
+fi
+
+
+# For some reason we have to make it so that we can only run this if we're after
+# the first commit, even though this isn't a part of git and our program can do
+# it without issues.
+if ! [ -e ".tigger/branch.unlock" ]; then
+ printf "tigger-branch: error: this command can not be run until after the first commit\n" >&2
+ exit 1
+fi
+
+# Case where we give it no arguments -> list the branches.
+if [ "$(echo "$@" | tr -d " \n")" = "" ]; then
+ printf "%s\n" "$(find .tigger/* -maxdepth 0 -type d | sort | grep -o -E "[\/][^\/]*$" | tr -d "/")"
+ exit 0
+fi
+
+target_branch=$(echo "$@" | sed "s|-d||g" | tr -d " ");
+if [ "$target_branch" = "" ]; then
+ # no branch provided
+ printf "tigger-branch: error: no branch provided\n" >&2
+ exit 1
+fi
+
+# Delete a branch, again taking care that we remove the target branch string
+# before testing if it contains -d.
+if [ "$(echo "$@" | sed "s|$target_branch||g" | grep -o -E "\-d" | tr -d " ")" != "" ]; then
+
+ if [ "$target_branch" = master ]; then
+ printf "tigger-branch: error: can not delete branch '%s'\n" "$target_branch" >&2
+ exit 1
+ fi
+
+ if ! [ -d .tigger/"$target_branch"/ ]; then
+ printf "tigger-branch: error: branch '%s' doesn't exist\n" "$target_branch" >&2
+ exit 1
+ fi
+
+ rm -r .tigger/"$target_branch"
+ printf "Deleted branch '%s'\n" "$target_branch"
+ exit 0
+fi
+
+# Adding branch logic should test if a branch exists before adding it.
+if [ -d .tigger/"$target_branch"/ ]; then
+ printf "tigger-branch: error: branch '%s' already exists\n" "$target_branch" >&2
+ exit 1
+fi
+
+# We have to copy our current commit to the target branch.
+current_branch=$(cat .tigger/branch.tig)
+current_commit=$(find .tigger/"$current_branch"/ -maxdepth 1 -type d | grep -o -E "[\/][^\/]*$" | tr -d "/" | sort -n -r | head -n 1)
+if [ "$current_commit" = "" ]; then
+ current_commit="0"
+ mkdir --parents ".tigger/$current_branch/$current_commit/"
+fi
+
+mkdir --parents .tigger/"$target_branch"/
+mkdir --parents .tigger/"$target_branch"/0/staged
+cp -r .tigger/"$current_branch"/"$current_commit"/commit .tigger/"$target_branch"/0/
+
+exit 0
diff --git a/comp2041/tigger/tigger-checkout b/comp2041/tigger/tigger-checkout
new file mode 100755
index 0000000..a1a5a21
--- /dev/null
+++ b/comp2041/tigger/tigger-checkout
@@ -0,0 +1,84 @@
+#!/bin/dash
+
+# Test if we have a valid repo before doing anything.
+if ! [ -d ".tigger/" ]; then
+ printf "tigger-add: error: tigger repository directory .tigger not found\n" >&2
+ exit 1
+fi
+
+# Case where we give it no arguments -> early out (without error?)
+target_branch=$(echo "$@" | tr -d " ");
+if [ "$target_branch" = "" ]; then
+ # no branch provided, idk if we should print anything so just early out
+ exit 1
+fi
+
+if ! [ -d .tigger/"$target_branch" ]; then
+ printf "tigger-checkout: error: unknown branch '%s'\n" "$target_branch" >&2
+ exit 1
+fi
+
+
+current_branch=$(cat .tigger/branch.tig)
+current_commit=$(find .tigger/"$current_branch"/ -maxdepth 1 -type d | grep -o -E "[\/][^\/]*$" | tr -d "/" | sort -n -r | head -n 1)
+if [ "$current_commit" = "" ]; then
+ current_commit="0"
+ mkdir --parents ".tigger/$current_branch/$current_commit/"
+fi
+
+target_commit=$(find .tigger/"$target_branch"/ -maxdepth 1 -type d | grep -o -E "[\/][^\/]*$" | tr -d "/" | sort -n -r | head -n 1)
+if [ "$target_commit" = "" ]; then
+ target_commit="0"
+ mkdir --parents ".tigger/$target_branch/$target_commit/"
+fi
+
+for filename in *; do
+ basename=$(basename "$filename")
+
+ # nothing in dir, just exit (should exit)
+ if ! [ -e "$filename" ]; then
+ continue
+ fi
+
+ # if it's in staging, do not remove
+ #if [ -e .tigger/"$current_branch"/"$current_commit"/staged/"$basename" ]; then
+ # continue
+ #fi
+
+ # if it doesn't exist in the target commit, remove
+ if ! [ -e .tigger/"$target_branch"/"$target_commit"/commit/"$basename" ]; then
+ rm "$basename"
+ continue
+ fi
+done
+
+for filename in .tigger/"$target_branch"/"$target_commit"/commit/*; do
+ basename=$(basename "$filename")
+
+ # nothing in dir, just exit (should exit)
+ if ! [ -e "$filename" ]; then
+ continue
+ fi
+
+ # if it's in the current dir, do nothing TODO fix if different
+ if [ -e "$basename" ]; then
+
+ # If it's the same AND not different to current staging, don't copy.
+ if [ "$(diff .tigger/"$target_branch"/"$target_commit"/commit/"$basename" "$basename")" = "" ]; then
+ if [ "$(diff .tigger/"$current_branch"/"$current_commit"/staged/"$basename" "$basename")" != "" ]; then
+ continue
+ fi
+ fi
+
+ fi
+
+ cp "$filename" ./
+done
+
+# Non-compliant tigger vs git behaviour: copy our staged to theirs.
+rm -rf .tigger/"$target_branch"/"$target_commit"/staged
+cp -r .tigger/"$current_branch"/"$current_commit"/staged .tigger/"$target_branch"/"$target_commit"/staged
+
+echo "$target_branch" > .tigger/branch.tig
+printf "Switched to branch '%s'\n" "$target_branch"
+exit 0
diff --git a/comp2041/tigger/tigger-commit b/comp2041/tigger/tigger-commit
new file mode 100755
index 0000000..b2c7573
--- /dev/null
+++ b/comp2041/tigger/tigger-commit
@@ -0,0 +1,88 @@
+#!/bin/dash
+
+# Test if we have a valid repo before doing anything.
+if ! [ -d ".tigger/" ]; then
+ printf "tigger-add: error: tigger repository directory .tigger not found\n" >&2
+ exit 1
+fi
+
+
+# Get current branch, then current commit (default 0).
+branch=$(cat .tigger/branch.tig)
+mkdir --parents ".tigger/$branch/"
+commit=$(find .tigger/"$branch"/ -maxdepth 1 -type d | grep -o -E "[\/][^\/]*$" | tr -d "/" | sort -n -r | head -n 1)
+if [ "$commit" = "" ]; then
+ commit="0"
+ mkdir --parents ".tigger/$branch/$commit/"
+fi
+
+
+commit_files=".tigger/$branch/$commit/"
+file_dir="$commit_files/commit/"
+mkdir --parents "$file_dir"
+mkdir --parents "$commit_files/staged/"
+
+
+# -a causes all files already in the index to have their contents from the
+# current directory added to the index before the commit. We have to remove
+# the message arg before testing the regex here.
+message=$(echo "$@" | grep -o -E "\-m\s?.*" | cut -d' ' -f2- | tr -d \"\')
+if [ "$(echo "$@" | sed "s|$message||g" | grep -o -E "\-a")" != "" ]; then
+ for filename in "$commit_files"/staged/*; do
+ basename=$(basename "$filename")
+ if ! [ -e "$basename" ]; then
+ continue
+ fi
+ cp "$basename" "$commit_files"/staged/
+ done
+fi
+
+
+# If all files in staging are equal to those in commit, we have nothing to commit.
+different=""
+for filename in "$commit_files"/staged/*; do
+ basename=$(basename "$filename")
+
+ EXISTS="$(cmp --silent .tigger/"$branch"/"$commit"/commit/"$basename" "$filename"; echo $?)"
+ if [ "$EXISTS" -ne 0 ]; then
+ different="true"
+ break
+ fi
+done
+for filename in "$commit_files"/commit/*; do
+ basename=$(basename "$filename")
+
+ EXISTS="$(cmp --silent .tigger/"$branch"/"$commit"/staged/"$basename" "$filename"; echo $?)"
+ if [ "$EXISTS" -ne 0 ]; then
+ different="true"
+ break
+ fi
+done
+if [ "$different" = "" ] || [ -z "$(find .tigger/"$branch"/"$commit"/staged/ .tigger/"$branch"/"$commit"/commit/ -maxdepth 1 -type f)" ] ; then
+ printf "nothing to commit\n"
+ exit 0
+fi
+
+
+# Copy all from staged into commit.
+#for filename in "$commit_files"/staged/*; do
+# cp "$filename" "$file_dir"
+#done
+rm -r --force "$commit_files"/commit/
+cp -r "$commit_files"/staged "$commit_files"/commit/
+
+
+# Copy our commit message and setup our new commit (n + 1).
+#printf "%s > .tigger/%s/%s/message.tig\n" "$branch" "$commit"
+printf "%s" "$message" > .tigger/"$branch"/"$commit"/message.tig
+new_commit="$((($(cat .tigger/commit_count.tig) + 1)))"
+mkdir --parents ".tigger/$branch/$new_commit/commit"
+cp -r ".tigger/$branch/$commit/commit" ".tigger/$branch/$new_commit/"
+cp -r ".tigger/$branch/$commit/commit" ".tigger/$branch/$new_commit/staged"
+touch .tigger/branch.unlock
+
+# Increment our commit count value (which isn't used outside of printing).
+echo "$new_commit" > .tigger/commit_count.tig
+
+printf "Committed as commit %s\n" "$((($(printf "%s" "$new_commit") - 1)))"
+exit 0
diff --git a/comp2041/tigger/tigger-init b/comp2041/tigger/tigger-init
new file mode 100755
index 0000000..cee1a77
--- /dev/null
+++ b/comp2041/tigger/tigger-init
@@ -0,0 +1,39 @@
+#!/bin/dash
+
+# We will create a new file in .tigger called "branch.tig" with our current
+# branch. By default this should be master. All future ops should read this.
+
+# Commits will be contained in files starting at 0...n inside our branch dir.
+# Our directory heirarchy might look like:
+# .tigger/
+# branch.tig // current branch
+# commit_count.tig // see the below comment @ echo "0"...
+# master/
+# 0/
+# commit/
+# staged/
+# message.tig // because we have a message, it's a finished commit
+# 1/
+# commit/
+# staged/
+
+if [ -d ".tigger/" ]; then
+ printf "tigger-init: error: .tigger already exists\n" >&2
+ exit 1
+fi
+
+branch="master" # in future should be ~ branch=$(cat ./.tigger/branch.tig)
+mkdir --parents ".tigger/$branch"
+echo "$branch" > ".tigger/branch.tig"
+
+# This is necessary because their implementation of git branch considers a
+# global commit count as opposed to a (more logical) per branch commit count.
+# Whenever we do any commit we have to increment this value (which is only
+# used for printing so that we are compliant with their autotests).
+echo "0" > .tigger/commit_count.tig
+
+mkdir --parents ".tigger/$branch/0/commit"
+mkdir --parents ".tigger/$branch/0/staged"
+
+printf "Initialized empty tigger repository in .tigger\n"
+exit 0
diff --git a/comp2041/tigger/tigger-log b/comp2041/tigger/tigger-log
new file mode 100755
index 0000000..5e269c2
--- /dev/null
+++ b/comp2041/tigger/tigger-log
@@ -0,0 +1,24 @@
+#!/bin/dash
+
+# Test if we have a valid repo before doing anything.
+if ! [ -d ".tigger/" ]; then
+ printf "tigger-add: error: tigger repository directory .tigger not found\n" >&2
+ exit 1
+fi
+
+# Get current branch.
+branch=$(cat .tigger/branch.tig)
+mkdir --parents ".tigger/$branch/"
+
+# Iterate through commits and print their message.
+for commit in $(find .tigger/"$branch"/* -maxdepth 0 -type d | grep -o -E "[\/][^\/]*$" | tr -d "/" | sort -r -n); do
+
+ # No message = we're working on it, so it's not considered here.
+ if ! [ -e .tigger/"$branch"/"$commit"/message.tig ]; then
+ continue
+ fi
+
+ printf "%s %s\n" "$commit" "$(cat .tigger/"$branch"/"$commit"/message.tig)"
+done
+
+exit 0
diff --git a/comp2041/tigger/tigger-rm b/comp2041/tigger/tigger-rm
new file mode 100755
index 0000000..e50420a
--- /dev/null
+++ b/comp2041/tigger/tigger-rm
@@ -0,0 +1,66 @@
+#!/bin/dash
+
+# Test if we have a valid repo before doing anything.
+if ! [ -d ".tigger/" ]; then
+ printf "tigger-add: error: tigger repository directory .tigger not found\n" >&2
+ exit 1
+fi
+
+# Get current branch, then current commit (default 0).
+branch=$(cat .tigger/branch.tig)
+mkdir --parents ".tigger/$branch/"
+commit=$(find .tigger/"$branch"/ -maxdepth 1 -type d | grep -o -E "[\/][^\/]*$" | tr -d "/" | sort -n -r | head -n 1)
+if [ "$commit" = "" ]; then
+ commit="0"
+ mkdir --parents ".tigger/$branch/$commit/"
+fi
+
+commit_files=".tigger/$branch/$commit/"
+mkdir --parents "$commit_files/commit/"
+mkdir --parents "$commit_files/staged/"
+
+for filename in $(echo "$@" | sed "s|--force||g" | sed "s|--cached||g"); do
+
+ basename=$(basename "$filename")
+ if ! [ -e .tigger/"$branch"/"$commit"/staged/"$basename" ]; then
+ printf "tigger-rm: error: '%s' is not in the tigger repository\n" "$basename" >&2
+ exit 1
+ fi
+
+ # Accidental deletion checking, should be non-cached and non-forced.
+ if [ "$(echo "$@" | grep -o -E "\-\-force")" = "" ]; then
+
+ if [ "$(cmp --silent .tigger/"$branch"/"$commit"/staged/"$basename" "$basename"; echo $?)" -ne 0 ]; then
+
+ if [ "$(cmp --silent .tigger/"$branch"/"$commit"/staged/"$basename" .tigger/"$branch"/"$commit"/commit/"$basename"; echo $?)" -ne 0 ]; then
+ printf "tigger-rm: error: '%s' in index is different to both the working file and the repository\n" "$basename" >&2
+ exit 1
+ fi
+
+ if ! [ "$(echo "$@" | grep -o -E "\-\-cached")" != "" ]; then
+ printf "tigger-rm: error: '%s' in the repository is different to the working file\n" "$basename" >&2
+ exit 1
+ fi
+
+ fi
+
+
+ if ! [ "$(echo "$@" | grep -o -E "\-\-cached")" != "" ]; then
+ if [ "$(cmp --silent .tigger/"$branch"/"$commit"/staged/"$basename" .tigger/"$branch"/"$commit"/commit/"$basename"; echo $?)" -ne 0 ]; then
+ printf "tigger-rm: error: '%s' has staged changes in the index\n" "$basename" >&2
+ exit 1
+ fi
+ fi
+ fi
+
+ rm --force .tigger/"$branch"/"$commit"/staged/"$basename"
+ # If the cached option is specified the files are removed only from the index.
+ if [ "$(echo "$@" | grep -o -E "\-\-cached")" != "" ]; then
+ continue
+ fi
+
+ rm --force "$basename"
+
+done
+
+exit 0
diff --git a/comp2041/tigger/tigger-show b/comp2041/tigger/tigger-show
new file mode 100755
index 0000000..05d8405
--- /dev/null
+++ b/comp2041/tigger/tigger-show
@@ -0,0 +1,63 @@
+#!/bin/dash
+
+# Test if we have a valid repo before doing anything.
+if ! [ -d ".tigger/" ]; then
+ printf "tigger-add: error: tigger repository directory .tigger not found\n" >&2
+ exit 1
+fi
+
+if [ "$(printf "%s" "$@")" = "" ]; then
+ printf "tigger-show: error: no arguments provided\n" >&2
+ exit 1
+fi
+
+branch=$(cat .tigger/branch.tig)
+filename=$(echo "$@" | cut -d':' -f2-2)
+commit=$(echo "$@" | cut -d':' -f1-1)
+
+# Lots of error checking here and unnecessarily distinct printing per error.
+
+target="" # LAMBDA CAPTURE
+if [ "$commit" != "" ]; then
+ target=".tigger/$branch/$commit/commit/$filename"
+
+ if ! [ -e ".tigger/$branch/$commit/message.tig" ]; then
+ printf "tigger-show: error: unknown commit '%s'\n" "$commit" >&2
+ exit 1
+ fi
+
+ if ! [ -e "$target" ]; then
+ printf "tigger-show: error: '%s' not found in commit %s\n" "$filename" "$commit" >&2
+ exit 1
+ fi
+
+ printf "%s\n" "$(cat "$target")"
+ exit 0
+
+else
+ commit=$(find .tigger/"$branch"/ -maxdepth 1 -type d | grep -o -E "[\/][^\/]*$" | tr -d "/" | sort -n -r | head -n 1)
+ if [ "$commit" = "" ]; then
+ commit="0"
+ mkdir --parents ".tigger/$branch/$commit/"
+ fi
+
+ if ! [ -e ".tigger/$branch/$commit/staged/$filename" ]; then
+ printf "tigger-show: error: '%s' not found in index\n" "$filename" >&2
+ exit 1
+ fi
+
+ target=".tigger/$branch/$commit/staged/$filename"
+fi
+
+if ! [ -e ".tigger/$branch/$commit/" ]; then
+ printf "tigger-show: error: unknown commit '%s'\n" "$commit" >&2
+ exit 1
+fi
+
+if ! [ -e "$target" ]; then
+ printf "tigger-show: error: '%s' not found in commit %s\n" "$filename" "$commit" >&2
+ exit 1
+fi
+
+printf "%s\n" "$(cat "$target")"
+exit 0
diff --git a/comp2041/tigger/tigger-status b/comp2041/tigger/tigger-status
new file mode 100755
index 0000000..b623432
--- /dev/null
+++ b/comp2041/tigger/tigger-status
@@ -0,0 +1,100 @@
+#!/bin/dash
+
+# Test if we have a valid repo before doing anything.
+if ! [ -d ".tigger/" ]; then
+ printf "tigger-add: error: tigger repository directory .tigger not found\n" >&2
+ exit 1
+fi
+
+# Get current branch + commit as usual.
+branch=$(cat .tigger/branch.tig)
+mkdir --parents ".tigger/$branch/"
+commit=$(find .tigger/"$branch"/ -maxdepth 1 -type d | grep -o -E "[\/][^\/]*$" | tr -d "/" | sort -n -r | head -n 1)
+if [ "$commit" = "" ]; then
+ commit="0"
+ mkdir --parents ".tigger/$branch/$commit/"
+fi
+
+# Grabs regular files from our working dir, staging and commit.
+files=$(find .tigger/"$branch"/"$commit"/commit/ .tigger/"$branch"/"$commit"/staged/ ./ -maxdepth 1 -type f -printf "%P\n" | sort | uniq | grep -v -E "^\." 2>/dev/null)
+for filename in $files; do
+
+ c_dir=".tigger/$branch/$commit/commit/$filename";
+ s_dir=".tigger/$branch/$commit/staged/$filename";
+
+ is_c=0
+ is_s=0
+ is_w=0
+ if [ -e "$c_dir" ]; then
+ is_c=1
+ fi
+ if [ -e "$s_dir" ]; then
+ is_s=1
+ fi
+ if [ -e "$filename" ]; then
+ is_w=1
+ fi
+
+ # There are a LOT of very specific cases here.
+
+ if [ $is_w -eq 0 ] && [ $is_s -eq 0 ] && [ $is_c -eq 1 ]; then
+ printf "%s - deleted\n" "$filename"
+ continue
+ fi
+
+ if [ $is_w -eq 1 ] && [ $is_s -eq 0 ] && [ $is_c -eq 0 ]; then
+ printf "%s - untracked\n" "$filename"
+ continue;
+ fi
+
+ if [ $is_w -eq 1 ] && [ $is_s -eq 1 ] && [ $is_c -eq 1 ]; then
+ c="$(cat "$c_dir")"
+ s="$(cat "$s_dir")"
+ w="$(cat "$filename")"
+
+ if [ "$w" != "$s" ] && [ "$s" != "$c" ] && [ "$c" != "$w" ]; then
+ printf "%s - file changed, different changes staged for commit\n" "$filename"
+ continue
+ fi
+
+ if [ "$w" = "$s" ] && [ "$s" != "$c" ]; then
+ printf "%s - file changed, changes staged for commit\n" "$filename"
+ continue
+ fi
+
+ if [ "$w" != "$s" ] && [ "$s" = "$c" ]; then
+ printf "%s - file changed, changes not staged for commit\n" "$filename"
+ continue
+ fi
+
+ if [ "$w" = "$s" ] && [ "$s" = "$c" ]; then
+ printf "%s - same as repo\n" "$filename"
+ continue
+ fi
+ fi
+
+ if [ $is_w -eq 0 ] && [ $is_s -eq 1 ] && [ $is_c -eq 1 ] && [ "$(diff "$s_dir" "$c_dir")" = "" ]; then
+ printf "%s - file deleted\n" "$filename"
+ continue
+ fi
+
+ if [ $is_w -eq 1 ] && [ $is_s -eq 1 ] && [ $is_c -eq 0 ] && [ "$(diff "$filename" "$s_dir")" = "" ]; then
+ printf "%s - added to index\n" "$filename"
+ continue
+ fi
+
+ if [ $is_w -eq 1 ] && [ $is_s -eq 1 ] && [ $is_c -eq 0 ] && [ "$(diff "$filename" "$s_dir")" != "" ]; then
+ printf "%s - added to index, file changed\n" "$filename"
+ continue;
+ fi
+
+ if [ $is_w -eq 0 ] && [ $is_s -eq 1 ] && [ $is_c -eq 0 ]; then
+ printf "%s - added to index, file deleted\n" "$filename"
+ continue;
+ fi
+
+ printf "%s - untracked\n" "$filename"
+
+done
+
+exit 0