blob: 84f010f488b2c1db60b255fafac760f07d8825a0 (
plain) (
tree)
|
|
#!/usr/local/bin/bash
#
# License: CC0-1.0
#
# Usage:
#
# $ tball /path/to/tball-info.txt
#
#
parse_opts() {
export TBFILE=$1
if [ -z $TBFILE ]; then
echo 'Info file not passed! Exiting.'
exit 1
fi
if [ ! -f $TBFILE ]; then
echo $TBFILE 'does not exist! Exiting.'
exit 1
fi
}
parse_src() {
if [ ! -d $1 ] && [ ! -f $1 ]; then
echo 'Source "'$1'" does not exists'
exit 1
fi
return 0
}
parse_bdest() {
if [ ! -d $1 ]; then
echo 'Making '$1' ...'
mkdir -p $1
[[ $? == 1 ]] && exit 1
fi
return 0
}
setup_dest() {
export DEST=$1/$2
if [ ! -d $DEST ]; then
echo 'Making '$DEST' ...'
mkdir -p $DEST
[[ $? == 1 ]] && exit 1
fi
}
clean_tmp() {
echo 'Cleaning up... '$1
rm -rf $1
}
file_updated() {
local SRC=$1
local DEST=$2
# Get modified time for file
local FTIME=$(stat -r $SRC | cut -d ' ' -f 10)
# Get the last time source was tballed.
local TBALLT=$(find $DEST -type f -name '.suffixes' -exec cat '{}' \; \
| tail -n 1)
[[ -z $TBALLT ]] && return 1 # source not tballed at all.
# Check if file was updated after the last tball.
[[ $FTIME -gt $TBALLT ]] && return 1
return 0
}
dir_updated() {
local SRC=$1
local DEST=$2
# Get file that was last modified in this directory.
local F=$(find $SRC -type f -exec stat -r '{}' \; \
| sort -r -k 10 | head -n 1 | cut -d ' ' -f 15);
return $(file_updated $F $DEST)
}
should_tb() {
local SRC=$1
local DEST=$2
# Get the number of tballs that exists
local TBALLS=$(find $DEST -type f -name '*.tar.gz' | wc -l)
[[ $TBALLS == 0 ]] && return 1
if [ -d $SRC ]; then
# Check if any files under this directory was modified <= 24hrs
return $(dir_updated $SRC $DEST)
else
return $(file_updated $SRC $DEST)
fi
}
parse_maxtb() {
local MAX=$1
if [ -z $MAX ]; then
echo 10
else
echo $MAX
fi
}
rm_file() {
local F=$1
if [ ! -f $F ]; then
echo 'File not found: Cannot remove '$F
return 0
fi
# Remove file.
echo 'Removing '$F'...'
rm $F && return 0
return 1 # rm failed
}
clean_ol_tbs() {
local D=$1
local S=$1/.suffixes
local MAX=$2 # TODO: check MAX's value.
# Check if suffixes file exists.
if [ ! -f $S ]; then
echo 'Cannot remove old tballs at '$1 \
': .suffixes not found'
return 0
fi
# Get total timestamps.
local TOTT=$(wc -l $S | sed -E 's/^ +//' | cut -f 1 -d ' ')
if [ $TOTT -lt $MAX ]; then
echo 'No old tballs to clean up [0]'
return 0
fi
# Get number of timestamps to remove.
local RM=$(($TOTT-$MAX))
if [ $RM -lt 1 ]; then
echo 'No old tballs to clean up [1]'
return 0
fi
# Make temp dir.
local TMP_DIR=$(mktemp -d /tmp/clean_tb.XXXXXX)
[[ $? == 1 ]] && exit 1
# Get timestamps to remove.
local RMT=$TMP_DIR/rmt
$(head -n $RM $S > $RMT)
[[ $? == 1 ]] && exit 1
# Get timestamps to keep.
local KT=$TMP_DIR/kt
$(tail -n $MAX $S > $KT)
[[ $? == 1 ]] && exit 1
# Get basename.
local BN=$(basename $D)
echo 'Removing old tballs...'
while read -r ts; do
rm_file $D/$BN.$ts.tar.xz
done <$RMT
# Update suffixes
mv $KT $S
[[ $? == 1 ]] && exit 1
# Clean up tmp dir.
rm -rf $TMP_DIR
return 0
}
tb() {
local SRC=${1/#\~/$HOME}
local BDEST=${2/#\~/$HOME}
local MAX_TB=$(parse_maxtb $3) # Maximum tballs for a BDEST.
parse_src $SRC
parse_bdest $BDEST
# Get basename.
local BN=$(basename $SRC)
# Setup destination dir.
setup_dest $BDEST $BN
# Check if source needs to be tballed
should_tb $SRC $DEST
[[ $? == 0 ]] && \
echo $SRC 'is good! Not tballing it' \
&& clean_ol_tbs $DEST $MAX_TB \
&& return 0
# SUFFIX (current unix time)
local SUFFIX=$(date '+%s')
# Make temp dir.
local TMP_DIR=$(mktemp -d /tmp/tball.XXXXXX)
[[ $? == 1 ]] && exit 1
# Make ball name
local BALL=$TMP_DIR/$BN.$SUFFIX.tar
local FLIST=$TMP_DIR/files
# Make ball.
echo 'Making '$BALL'.xz...'
if [ ${SRC: -6} == 'tar.xz' ]; then
cp $SRC $BALL # SRC is already a tar ball
else
find $SRC -type f > $FLIST \
&& tar cvf $BALL -I $FLIST && xz $BALL
fi
[[ $? == 1 ]] && clean_tmp $TMP_DIR && exit 1
# Drop ball in destination.
echo 'rsyncing '$BALL'.xz to '$DEST'...'
rsync $BALL.xz $DEST
[[ $? == 1 ]] && clean_tmp $TMP_DIR && exit 1
# Store suffix
echo $SUFFIX >> $DEST/.suffixes
# Clean up ol' tballs.
clean_ol_tbs $DEST $MAX_TB
# Clean up
clean_tmp $TMP_DIR
unset DEST
}
parse_opts $1
# Tarball 'em all up
while read -r line; do
tb $line
done <$TBFILE
|