#!/bin/bash # # sync-media assets using git-annex # REMOTE="$1" VOLUME="/media/$REMOTE" DOMAIN="`facter domain`" HOST="`facter hostname`" CACHE="/var/cache/$HOST/media" MEDIA="media.$DOMAIN" INCOMING="$CACHE/incoming" WHOAMI="`whoami`" OPTIONS="$*" # Fix identity function sync_media_identity { if [ -z "`git config --local user.email`" ] || [ -z "`git config --local user.name`" ]; then repo="$(basename `pwd`)" git config user.name "${repo^} Archive" git config user.email "$repo@localhost" fi } # Add files into the annex function sync_media_add { git annex add . # Adding hidden files and symlinks, git+while version git status --porcelain -u | sed -e 's/?? //' | while read file; do if [ -h "$file" ]; then git add "$file" else git annex add "$file" fi done } # If there is a playlists folder, make sure mpd user can write to it function sync_media_playlist_perms { if [ -d "playlists" ]; then $sudo chmod 775 playlists $sudo chown -R mpd.audio playlists find playlists -type f -exec sudo chmod 664 {} \; find playlists -type d -exec sudo chmod 775 {} \; fi } # Fix incoming permissions function sync_media_incoming_perms { if [ -d "$INCOMING" ]; then echo "Fixing $INCOMING permissions..." $sudo find $INCOMING -type f -exec chmod 664 {} \; $sudo find $INCOMING -type d -exec chmod 775 {} \; $sudo chown -R $WHOAMI.incoming $INCOMING fi } # Run fsck function sync_media_fsck { if [ "$FSCK" == "true" ]; then git annex fsck --fast fi } # Run dropunused function sync_media_dropunused { if [ "$DROPUNUSED" == "true" ]; then git annex unused git annex dropunused 1-1000 fi } # Get copies of annexed files function sync_media_get { local repo="$1" local numcopies if [ "`git -C $repo config sync-media.get`" != "false" ]; then if git -C $repo config sync-media.numcopies &> /dev/null; then numcopies="`git -C $repo config sync-media.numcopies`" else numcopies="3" fi git annex get . --numcopies=$numcopies fi } # Control whether the repository should have a copy of everything function sync_media_getall { local repo="$1" if [ "`git -C $repo config sync-media.getall`" == "true" ]; then git annex get . fi } # Ensure we have a reference to the remote repository function sync_media_ensure_remote { local remote="$1" local path="$2" if [ -z "$remote" ] || [ -z "$path" ]; then return fi # Check for local or remote repo if [ -z "$DRIVE" ]; then path="$REMOTE.$DOMAIN:$path" elif [ ! -d "$path/.git/annex" ]; then return fi if ! git remote | grep -q "^$remote$"; then echo git remote add $remote $path fi } # Set sudo config if [ "$WHOAMI" != 'root' ]; then sudo="sudo" else echo "Sorry, cannot run as root" exit 1 fi # Set fsck config if echo $OPTIONS | grep -q -- "--fsck"; then FSCK="true" fi # Set unused config if echo $OPTIONS | grep -q -- "--dropunused"; then DROPUNUSED="true" fi # Set drive config if [ ! -z "$REMOTE" ]; then # Check storage media MOUNT="`mount | grep $VOLUME`" if [ ! -z "$MOUNT" ]; then DRIVE="$(basename `echo $MOUNT | awk '{ print $1 }'`)" fi fi # Commit changes if [ -d "$CACHE" ]; then # Fix cache permissions #echo "Fixing $CACHE permissions..." #$sudo find $CACHE -type f -exec chmod 644 {} \; #$sudo find $CACHE -type d -exec chmod 755 {} \; sync_media_incoming_perms # Add and update local repositories for folder in `ls $CACHE`; do if [ -d "$CACHE/$folder/.git/annex" ]; then if [ "`git -C $CACHE/$folder config sync-media.skip`" == "true" ]; then continue fi #if [ "`git -C $CACHE/$folder config sync-media.ready`" != "true" ]; then # echo "Skipping $CACHE/$folder: not sync-media ready, please config your repo." # continue #fi ( cd $CACHE/$folder echo "Syncing $CACHE/$folder..." sync_media_playlist_perms sync_media_ensure_remote $REMOTE $VOLUME/$MEDIA/$folder sync_media_identity sync_media_add git annex sync sync_media_getall $CACHE/$folder sync_media_fsck sync_media_dropunused ) fi done if [ ! -z "$DRIVE" ]; then if [ ! -d "$VOLUME/$MEDIA" ]; then echo "Folder $VOLUME/$MEDIA does not exist..." else for folder in `ls $CACHE`; do if [ -d "$CACHE/$folder/.git/annex" ]; then if [ "`git -C $CACHE/$folder config sync-media.skip`" == "true" ]; then continue fi #if [ "`git -C $CACHE/$folder config sync-media.ready`" != "true" ]; then # echo "Skipping $CACHE/$folder: not sync-media ready, please config your repo." # continue #fi if [ ! -d "$VOLUME/$MEDIA/$folder" ]; then ( cd $VOLUME/$MEDIA echo "Initializing $VOLUME/$MEDIA/$folder..." git clone $CACHE/$folder && cd $folder && sync_media_identity && git annex init $DRIVE && \ git remote rename origin $HOST && cd $CACHE/$folder && git remote add $DRIVE $VOLUME/$MEDIA/$folder ) fi elif [ ! -d "$VOLUME/$MEDIA/$folder" ]; then if [ ! -e "$CACHE/$folder/.sync-media/skip" ]; then echo "Syncing $VOLUME/$MEDIA/$folder..." rsync -av --delete --exclude=.sync-media $CACHE/$folder/ $VOLUME/$MEDIA/$folder/ fi fi done fi fi fi # Retrieve changes at media volumes if [ ! -z "$DRIVE" ] && [ -d "$VOLUME/$MEDIA" ]; then for folder in `ls $VOLUME/$MEDIA`; do if [ -d "$VOLUME/$MEDIA/$folder/.git/annex" ]; then if [ "`git -C $VOLUME/$MEDIA/$folder config sync-media.skip`" == "true" ]; then continue fi ( cd $VOLUME/$MEDIA/$folder echo "Syncing $VOLUME/$MEDIA/$folder..." sync_media_ensure_remote $HOST $CACHE/$folder sync_media_playlist_perms sync_media_identity sync_media_add git annex sync sync_media_get $VOLUME/$MEDIA/$folder sync_media_getall $VOLUME/$MEDIA/$folder sync_media_fsck sync_media_dropunused #git annex drop --auto --numcopies=2 ) elif [ -d "$CACHE/$folder" ]; then if [ ! -e "$CACHE/$folder/.sync-media/skip" ]; then echo "Syncing $VOLUME/$MEDIA/$folder..." rsync -av --delete --exclude=.sync-media $CACHE/$folder/ $VOLUME/$MEDIA/$folder/ fi fi done elif [ ! -z "$REMOTE" ]; then # Try to copy to a remote for folder in `ls $CACHE`; do if [ -d "$CACHE/$folder/.git/annex" ]; then if [ "`git -C $CACHE/$folder config sync-media.skip`" == "true" ]; then continue fi sync_media_ensure_remote $REMOTE $CACHE/$folder ( cd $CACHE/$folder git annex copy . --to $REMOTE git annex sync ) else if [ ! -e "$CACHE/$folder/.sync-media/skip" ]; then echo "Syncing $VOLUME/$MEDIA/$folder..." rsync -av --delete --exclude=.sync-media $CACHE/$folder/ $REMOTE.$DOMAIN:$CACHE/$folder/ fi fi done fi