Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,21 @@ On macOS, it has a few disadvantages compared to Time Machine - in particular it

## Backup expiration logic

Backup sets are automatically deleted following a simple expiration strategy defined with the `--strategy` flag. This strategy is a series of time intervals with each item being defined as `x:y`, which means "after x days, keep one backup every y days". The default strategy is `1:1 30:7 365:30`, which means:
Backup sets are automatically deleted following a simple expiration strategy defined with the `--strategy` flag. This strategy is a series of time intervals with each item being defined as `x:y`, which means "after x days, keep one backup every y days". The value y can either be a positive integer or the character `x`.

The default strategy is `1:1 30:7 365:30`, which means:

- After **1** day, keep one backup every **1** day (**1:1**).
- After **30** days, keep one backup every **7** days (**30:7**).
- After **365** days, keep one backup every **30** days (**365:30**).

Before the first interval (i.e. by default within the first 24h) it is implied that all backup sets are kept. Additionally, if the backup destination directory is full, the oldest backups are deleted until enough space is available.

An example of a backup strategy using `x` is givne by `1:1 50:x`, which means:

- After **1** day, keep one backup every **1** day (**1:1**).
- After **50** days, no longer keep backups.

## Exclusion file

An optional exclude file can be provided as a third parameter. It should be compatible with the `--exclude-from` parameter of rsync. See [this tutorial](https://sites.google.com/site/rsync2u/home/rsync-tutorial/the-exclude-from-option) for more information.
Expand Down
4 changes: 2 additions & 2 deletions rsync_tmbackup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ fn_expire_backups() {
# If we've found the strategy token that applies to this backup
if [ "$backup_timestamp" -le "$cut_off_timestamp" ]; then

# Special case: if Y is "0" we delete every time
if [ $cut_off_interval -eq "0" ]; then
# Special case: if Y is "0", "x" or "X" we delete every time
if [[ ($cut_off_interval -eq "0") || ($cut_off_interval -eq "x") || ($cut_off_interval -eq "X") ]]; then
fn_expire_backup "$backup_dir"
break
fi
Expand Down
3 changes: 3 additions & 0 deletions tests/populate_dest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
throw new Exception('Not implemented');
}

mkdir($destDir);
touch($destDir . '/backup.marker');

$d = new DateTime();
$d->sub(new DateInterval('P' . $totalDays . 'D'));

Expand Down
42 changes: 42 additions & 0 deletions tests/test_expiration_of_zero.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

$backupDirectory = './TestDest/';

chdir(__DIR__);

exec('rm -rf ./TestDest');

include 'populate_dest.php';

exec('../rsync_tmbackup.sh --strategy "1:1 30:x" ./TestSource/ ' . $backupDirectory, $output, $return);

if ($return !== 0) {
echo 'Invalid return code';
echo implode(PHP_EOL, $output);
exit(1);
}

$backups = array_filter(
scandir($backupDirectory),
function ($file) use ($backupDirectory) {
return is_dir($backupDirectory . $file) && !in_array($file, ['.', '..']);
}
);

$expected = 33;
if (count($backups) !== $expected) {
echo 'Given this strategy there should be ' . $expected . ' directories. But ' . count($backups) . ' directories found.';
echo 'Found directories:';
echo implode(
PHP_EOL,
array_map(
function ($directory) { return "- {$directory}"; },
$backups
)
);

exit(1);
}

echo 'All assertions succeeded';
exit(0);