diff --git a/gitwatch.sh b/gitwatch.sh index a7eb841..5c8e950 100755 --- a/gitwatch.sh +++ b/gitwatch.sh @@ -43,6 +43,7 @@ COMMITMSG="Scripted auto-commit on change (%d) by gitwatch.sh" LISTCHANGES=-1 LISTCHANGES_COLOR="--color=always" EVENTS="close_write,move,delete,create" +GIT_DIR="" # Print a message about how to use this script shelp () { @@ -75,6 +76,8 @@ shelp () { echo " 'git push :' where" echo " is the target of HEAD (at launch)" echo " if no remote was defined with -r, this option has no effect" + echo " -g Location of the .git directory, if stored elsewhere in" + echo " a remote location. This specifies the --git-dir parameter" echo " -l Log the actual changes made in this commit, upto a given" echo " number of lines, or all lines if 0 is given" echo " -L Same as -l but without colored formatting" @@ -122,12 +125,13 @@ is_command () { ############################################################################### -while getopts b:d:h:L:l:m:p:r:s:e: option # Process command line options +while getopts b:d:h:g:L:l:m:p:r:s:e: option # Process command line options do case "${option}" in b) BRANCH=${OPTARG};; d) DATE_FMT=${OPTARG};; h) shelp; exit;; + g) GIT_DIR=${OPTARG};; l) LISTCHANGES=${OPTARG};; L) LISTCHANGES=${OPTARG}; LISTCHANGES_COLOR="";; m) COMMITMSG=${OPTARG};; @@ -179,6 +183,18 @@ else exit 1 fi +# If $GIT_DIR is set, verify that it is a directory, and then add parameters to +# git command as need be +if [ -n "$GIT_DIR" ]; then + + if [ ! -d "$GIT_DIR" ]; then + stderr ".git location is not a directory: $GIT_DIR"; + exit 1; + fi + + GIT="$GIT --work-tree $TARGETDIR --git-dir $GIT_DIR" +fi + # Check if commit message needs any formatting (date splicing) if ! grep "%d" > /dev/null <<< "$COMMITMSG"; then # if commitmsg didnt contain %d, grep returns non-zero DATE_FMT="" # empty date format (will disable splicing in the main loop) @@ -189,14 +205,14 @@ cd "$TARGETDIR" # CD into right dir if [ -n "$REMOTE" ]; then # are we pushing to a remote? if [ -z "$BRANCH" ]; then # Do we have a branch set to push to ? - PUSH_CMD="'$GIT' push $REMOTE" # Branch not set, push to remote without a branch + PUSH_CMD="$GIT push $REMOTE" # Branch not set, push to remote without a branch else # check if we are on a detached HEAD - HEADREF=$(git symbolic-ref HEAD 2> /dev/null) + HEADREF=$($GIT symbolic-ref HEAD 2> /dev/null) if [ $? -eq 0 ]; then # HEAD is not detached - PUSH_CMD="'$GIT' push $REMOTE $(sed "s_^refs/heads/__" <<< "$HEADREF"):$BRANCH" + PUSH_CMD="$GIT push $REMOTE $(sed "s_^refs/heads/__" <<< "$HEADREF"):$BRANCH" else # HEAD is detached - PUSH_CMD="'$GIT' push $REMOTE $BRANCH" + PUSH_CMD="$GIT push $REMOTE $BRANCH" fi fi else @@ -257,7 +273,7 @@ eval $INCOMMAND | while read -r line; do fi if [[ "$LISTCHANGES" -ge 0 ]]; then # allow listing diffs in the commit log message, unless if there are too many lines changed - DIFF_COMMITMSG="$(git diff -U0 $LISTCHANGES_COLOR | diff-lines)" + DIFF_COMMITMSG="$($GIT diff -U0 $LISTCHANGES_COLOR | diff-lines)" LENGTH_DIFF_COMMITMSG=0 if [[ "$LISTCHANGES" -ge 1 ]]; then LENGTH_DIFF_COMMITMSG=$(echo -n "$DIFF_COMMITMSG" | grep -c '^') @@ -267,21 +283,22 @@ eval $INCOMMAND | while read -r line; do if [ -n "$DIFF_COMMITMSG" ]; then FORMATTED_COMMITMSG="$DIFF_COMMITMSG" else - FORMATTED_COMMITMSG="New files added: $(git status -s)" + FORMATTED_COMMITMSG="New files added: $($GIT status -s)" fi else #FORMATTED_COMMITMSG="Many lines were modified. $FORMATTED_COMMITMSG" - FORMATTED_COMMITMSG=$(git diff --stat | grep '|') + FORMATTED_COMMITMSG=$($GIT diff --stat | grep '|') fi fi cd "$TARGETDIR" # CD into right dir STATUS=$($GIT status -s) if [ -n "$STATUS" ]; then # only commit if status shows tracked changes. - "$GIT" add $GIT_ADD_ARGS # add file(s) to index - "$GIT" commit $GIT_COMMIT_ARGS -m"$FORMATTED_COMMITMSG" # construct commit message and commit + $GIT add $GIT_ADD_ARGS # add file(s) to index + $GIT commit $GIT_COMMIT_ARGS -m"$FORMATTED_COMMITMSG" # construct commit message and commit if [ -n "$PUSH_CMD" ]; then + echo "Push command is $PUSH_CMD"; eval $PUSH_CMD; fi fi diff --git a/tests/commitlog.bats b/tests/commitlog.bats new file mode 100644 index 0000000..bbe300c --- /dev/null +++ b/tests/commitlog.bats @@ -0,0 +1,38 @@ +#!/usr/bin/env bats + +# This is a testscript using the bats testing framework: +# https://github.com/sstephenson/bats +# To run it, at a command prompt: +# bats testscript.bats + +load startup-shutdown + +@test "commit log messages working" { + # Start up gitwatch with logging, see if works + ${BATS_TEST_DIRNAME}/../gitwatch.sh -l 10 "$testdir/local/remote" 3>&- & + GITWATCH_PID=$! + + # Keeps kill message from printing to screen + disown + + # Create a file, verify that it hasn't been added yet, then commit + cd remote + + # According to inotify documentation, a race condition results if you write + # to directory too soon after it has been created; hence, a short wait. + sleep 1 + echo "line1" >> file1.txt + + # Wait a bit for inotify to figure out the file has changed, and do its add, + # and commit + sleep $WAITTIME + + # Make a new change + echo "line2" >> file1.txt + sleep $WAITTIME + + # Check commit log that the diff is in there + run git log -1 --oneline + [[ $output == *"file1.txt"* ]] +} + diff --git a/tests/remotedirs.bats b/tests/remotedirs.bats new file mode 100644 index 0000000..bbb1e94 --- /dev/null +++ b/tests/remotedirs.bats @@ -0,0 +1,51 @@ +#!/usr/bin/env bats + +# This is a testscript using the bats testing framework: +# https://github.com/sstephenson/bats +# To run it, at a command prompt: +# bats testscript.bats + +load startup-shutdown + +@test "remote git dirs working, with commit logging" { + # Move .git somewhere else + dotgittestdir=$(mktemp -d) + mv "$testdir/local/remote/.git" "$dotgittestdir" + + # Start up gitwatch, intentionally in wrong directory, with remote dir specified + ${BATS_TEST_DIRNAME}/../gitwatch.sh -l 10 -g "$dotgittestdir/.git" "$testdir/local/remote" 3>&- & + GITWATCH_PID=$! + + # Keeps kill message from printing to screen + disown + + # Create a file, verify that it hasn't been added yet, then commit + cd remote + + # According to inotify documentation, a race condition results if you write + # to directory too soon after it has been created; hence, a short wait. + sleep 1 + echo "line1" >> file1.txt + + # Wait a bit for inotify to figure out the file has changed, and do its add, + # and commit + sleep $WAITTIME + + # Store commit for later comparison + lastcommit=$(git --git-dir $dotgittestdir/.git rev-parse master) + + # Make a new change + echo "line2" >> file1.txt + sleep $WAITTIME + + # Verify that new commit has happened + currentcommit=$(git --git-dir $dotgittestdir/.git rev-parse master) + [ "$lastcommit" != "$currentcommit" ] + + # Check commit log that the diff is in there + run git --git-dir $dotgittestdir/.git log -1 --oneline + [[ $output == *"file1.txt"* ]] + + rm -rf $dotgittestdir +} + diff --git a/tests/startup-shutdown.bash b/tests/startup-shutdown.bash new file mode 100644 index 0000000..c22e3b6 --- /dev/null +++ b/tests/startup-shutdown.bash @@ -0,0 +1,26 @@ +setup() { + # Time to wait for gitwatch to respond + WAITTIME=4 + # Set up directory structure and initialize remote + testdir=$(mktemp -d) + cd $testdir + mkdir remote + cd remote + git init -q --bare + cd .. + mkdir local + cd local + git clone -q ../remote +} + + +teardown() { + # Remove testing directories + cd /tmp + +# rm -rf $testdir + + # Make sure gitwatch script gets killed if script stopped background + # Must kill the entire tree of processes generated + pkill -15 -P $GITWATCH_PID +} diff --git a/tests/status-change.bats b/tests/status-change.bats new file mode 100644 index 0000000..bda456f --- /dev/null +++ b/tests/status-change.bats @@ -0,0 +1,40 @@ +#!/usr/bin/env bats + +# This is a testscript using the bats testing framework: +# https://github.com/sstephenson/bats +# To run it, at a command prompt: +# bats testscript.bats + +load startup-shutdown + +@test "commit only when git status change" { + + # Start up gitwatch and capture its output + ${BATS_TEST_DIRNAME}/../gitwatch.sh "$testdir/local/remote" > "$testdir/output.txt" 3>&- & + GITWATCH_PID=$! + + # Keeps kill message from printing to screen + disown + + # Create a file, verify that it hasn't been added yet, then commit + cd remote + + # According to inotify documentation, a race condition results if you write + # to directory too soon after it has been created; hence, a short wait. + sleep 1 + echo "line1" >> file1.txt + + # Wait a bit for inotify to figure out the file has changed, and do its add, + # and commit + sleep $WAITTIME + + # Touch the file, but no change + touch file1.txt + sleep $WAITTIME + + run bash -c "grep \"nothing to commit\" \"$testdir/output.txt\" | wc -l" + [[ $output == "0" ]] + +} + + diff --git a/tests/sync.bats b/tests/sync.bats new file mode 100644 index 0000000..76cb241 --- /dev/null +++ b/tests/sync.bats @@ -0,0 +1,72 @@ +#!/usr/bin/env bats + +# This is a testscript using the bats testing framework: +# https://github.com/sstephenson/bats +# To run it, at a command prompt: +# bats testscript.bats + +load startup-shutdown + +@test "syncing correctly" { + # Start up gitwatch and see if commit and push happen automatically + # after waiting two seconds + ${BATS_TEST_DIRNAME}/../gitwatch.sh -r origin "$testdir/local/remote" 3>- & + GITWATCH_PID=$! + + # Keeps kill message from printing to screen + disown + + # Create a file, verify that it hasn't been added yet, + # then commit and push + cd remote + + # According to inotify documentation, a race condition results if you write + # to directory too soon after it has been created; hence, a short wait. + sleep 1 + echo "line1" >> file1.txt + + # Wait a bit for inotify to figure out the file has changed, and do its add, + # commit, and push. + sleep $WAITTIME + + # Verify that push happened + currentcommit=$(git rev-parse master) + remotecommit=$(git rev-parse origin/master) + [ "$currentcommit" = "$remotecommit" ] + + # Try making subdirectory with file + lastcommit=$(git rev-parse master) + mkdir subdir + cd subdir + echo "line2" >> file2.txt + + sleep $WAITTIME + + # Verify that new commit has happened + currentcommit=$(git rev-parse master) + [ "$lastcommit" != "$currentcommit" ] + + # Verify that push happened + currentcommit=$(git rev-parse master) + remotecommit=$(git rev-parse origin/master) + [ "$currentcommit" = "$remotecommit" ] + + + # Try removing file to see if can work + rm file2.txt + sleep $WAITTIME + + # Verify that new commit has happened + currentcommit=$(git rev-parse master) + [ "$lastcommit" != "$currentcommit" ] + + # Verify that push happened + currentcommit=$(git rev-parse master) + remotecommit=$(git rev-parse origin/master) + [ "$currentcommit" = "$remotecommit" ] + + # Remove testing directories + cd /tmp + rm -rf $testdir +} + diff --git a/testscript.bats b/testscript.bats deleted file mode 100644 index 8708914..0000000 --- a/testscript.bats +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env bats - -# This is a testscript using the bats testing framework: -# https://github.com/sstephenson/bats -# To run it, at a command prompt: -# bats testscript.bats - -setup() { - # Set up directory structure and initialize remote - testdir=$(mktemp -d) - cd $testdir - mkdir remote - cd remote - git init -q --bare - cd .. - mkdir local - cd local - git clone -q ../remote -} - -@test "syncing correctly" { - # Start up gitwatch and see if commit and push happen automatically - # after waiting two seconds - ${BATS_TEST_DIRNAME}/gitwatch.sh -r origin "$testdir/local/remote" 3>- & - GITWATCH_PID=$! - - # Keeps kill message from printing to screen - disown - - # Create a file, verify that it hasn't been added yet, - # then commit and push - cd remote - - # According to inotify documentation, a race condition results if you write - # to directory too soon after it has been created; hence, a short wait. - sleep 1 - echo "line1" >> file1.txt - - # Wait a bit for inotify to figure out the file has changed, and do its add, - # commit, and push. - sleep 5 - - # Verify that push happened - currentcommit=$(git rev-parse master) - remotecommit=$(git rev-parse origin/master) - [ "$currentcommit" = "$remotecommit" ] - - # Try making subdirectory with file - lastcommit=$(git rev-parse master) - mkdir subdir - cd subdir - echo "line2" >> file2.txt - - sleep 5 - - # Verify that new commit has happened - currentcommit=$(git rev-parse master) - [ "$lastcommit" != "$currentcommit" ] - - # Verify that push happened - currentcommit=$(git rev-parse master) - remotecommit=$(git rev-parse origin/master) - [ "$currentcommit" = "$remotecommit" ] - - - # Try removing file to see if can work - rm file2.txt - sleep 5 - - # Verify that new commit has happened - currentcommit=$(git rev-parse master) - [ "$lastcommit" != "$currentcommit" ] - - # Verify that push happened - currentcommit=$(git rev-parse master) - remotecommit=$(git rev-parse origin/master) - [ "$currentcommit" = "$remotecommit" ] - - # Remove testing directories - cd /tmp - rm -rf $testdir -} - - -@test "commit log messages working" { - # Start up gitwatch with logging, see if works - ${BATS_TEST_DIRNAME}/gitwatch.sh -l 10 "$testdir/local/remote" 3>&- & - GITWATCH_PID=$! - - # Keeps kill message from printing to screen - disown - - # Create a file, verify that it hasn't been added yet, then commit - cd remote - - # According to inotify documentation, a race condition results if you write - # to directory too soon after it has been created; hence, a short wait. - sleep 1 - echo "line1" >> file1.txt - - # Wait a bit for inotify to figure out the file has changed, and do its add, - # and commit - sleep 5 - - # Make a new change - echo "line2" >> file1.txt - sleep 5 - - # Check commit log that the diff is in there - run git log -1 --oneline - [[ $output == *"file1.txt"* ]] -} - -@test "commit only when git status change" { - - # Start up gitwatch and capture its output - ${BATS_TEST_DIRNAME}/gitwatch.sh "$testdir/local/remote" > "$testdir/output.txt" 3>&- & - GITWATCH_PID=$! - - # Keeps kill message from printing to screen - disown - - # Create a file, verify that it hasn't been added yet, then commit - cd remote - - # According to inotify documentation, a race condition results if you write - # to directory too soon after it has been created; hence, a short wait. - sleep 1 - echo "line1" >> file1.txt - - # Wait a bit for inotify to figure out the file has changed, and do its add, - # and commit - sleep 5 - - # Touch the file, but no change - touch file1.txt - sleep 5 - - run bash -c "grep \"nothing to commit\" \"$testdir/output.txt\" | wc -l" - [[ $output == "0" ]] - -} - - -teardown() { - # Remove testing directories - cd /tmp - - rm -rf $testdir - - # Make sure gitwatch script gets killed if script stopped background - # Must kill the entire tree of processes generated - pkill -15 -P $GITWATCH_PID -}