1 In Files

All I need to do to start the file with the following line:

Org mode
# -*- mode: org; eval: (add-hook 'after-save-hook (lambda () (org-html-export-to-html) (start-process "ucc-stuff-rsync" (get-buffer-create "ucc-stuff-rsync") "~/Desktop/UCC Stuff/rsync.sh")) nil t) -*-

To view the ucc-stuff-rsync buffer with colour, execute

Emacs Lisp
(ansi-color-apply-on-region (point-min) (point-max))

2 Client side

First up, let’s get the active directory so we can give rsync an absolute path.

workdirShell Script
echo ${PWD/#$HOME/\~}/ | sed 's/ /\\ /'

Then we just rsync and run the server side script

Shell Script
rsync -avz --delete <<workdir()>> "ucc:~/public-html/UCC\ Stuff"
ssh ucc '~/public-html/UCC\ Stuff/rsync-serverside.sh'

3 Server side

Let’s start off by letting me know this script is being run.

Shell Script
echo "\033[0;1mRunning post-rsync script\033[0;0m"

3.1 Caching changes

It’s good to save what changes have been made by others. For that we’ll use a patchfile. So we can refer to it later we’ll save the path to a variable.

Shell Script
patchfile=~/public/Documents_$(date +'%Y-%m-%dT%H:%M:%S').diff

No we run diff to get the patch between the two folders. The -r, u, and -N flags produce a recursive, unified diff that takes note of new files.

Shell Script
diff -ruN \
    ~/public/Documents/ \
    ~/public-html/UCC\ Stuff/Documents/ \

3.1.1 Further arguments

We’ll be filtering only for .org files later, but for now we can exclude a lot of noise by adding --exclude flags.

Shell Script
--exclude="*~" \
--exclude="*.md" \
--exclude="*.txt" \
--exclude="*.html" \
--exclude="*.pdf" \
--exclude="*.svg" \
--exclude="*.zip*" \
--exclude="*.gz" \
--exclude="*.tar" \

We tell diff not to bother expanding symlinks too.

Shell Script
--no-dereference \

3.1.2 Output handling

First off, we want to restrict the diff to just .org files. For this we can use filterdiff from patchutils.

Shell Script
| filterdiff -i "*.org" \

Then we pipe this result into the pre-determined patch file.

Shell Script
> $patchfile

3.1.3 No empty patch

If the patch is empty, just delete it.

Shell Script
if [ ! -s $patchfile ]; then
    rm $patchfile

3.1.4 Notify about patch status

It’s nice to keep track about how many patches have accumulated.

Shell Script
cd ~/public
patchcount=$(ls -l *.diff | wc -l)
patchsize=${$(du -ach *.diff | tail -1 | sed -e 's/\s.*$//'):-0}
echo "\033[0;34mThere $([[ $pathcount -eq 1 ]] && echo "is" || echo "are") currently \033[1m$patchcount\033[0;34m patch$([[ $pathcount -eq 1 ]] && echo "" || echo "es"), totalling \033[1m${patchsize}B\033[0;0m"
ls -gGh *.diff | awk '{gsub("_|\\."," "); print " - \033[0;33m"$8, "\033[1m"$3"B\033[0;0m"}'

3.2 Updating the working dir

To update the working state, we shall use rsync a second time. All the arguments are fairly self explanatory — the goal it to gain an up-to-date copy of the current published state, without any fluff (empty dirs), able to be edited by anyone

Shell Script
rsync -ai --include='*/' \
    --include='*.org' \
    --exclude='*' \
    --prune-empty-dirs \
    --chmod='a+rw' \
    --group='committee' \
    --delete \
    ~/public-html/UCC\ Stuff/Documents/ \

3.3 Protecting sensitive entries

Some folders contain content that may not quite be fit for public consumption (yet). These are marked by a .sensitive file.

We want to (recursively) restrict access to these folders by changing the mode to prevent the other group from accessing them.

This can be performed in a three step process:

  1. Locate .sensitive files in the source directory
  2. Verify that folder has been copied over
  3. Run chmod -R on that folder in the destination directory
Shell Script
cd ~/public-html/UCC\ Stuff/Documents/
sensitive_folders=$(find . -type f -name "*.sensitive" | xargs dirname 2>/dev/null)
cd ~/public/Documents/

for s_folder in $sensitive_folders; do
    if [ -e $s_folder ]; then
        chmod -R o-rwx $s_folder

Author: TEC

Created: 2020-10-19 Mon 21:59