Backup Rotator

This script demonstrates an automated backup rotation system that keeps only the most recent backups while deleting older ones.

import { dir_exists, dir_create, file_exists } from "std/fs"
import { parse_int, trim } from "std/text"
import { date_now, date_format_posix } from "std/date"

fun get_backup_count(backup_dir: Text): Int? {
    let count_output = trust $ ls -1 "{backup_dir}" | wc -l $
    return parse_int(trim(count_output))?
}

fun create_backup(source: Text, backup_dir: Text): Int? {
    let timestamp = date_format_posix(date_now())?
    let backup_name = "backup_{timestamp}.tar.gz"

    echo("Creating backup: {backup_name}")
    sudo $ tar -czf "{backup_dir}/{backup_name}" "{source}" $?

    echo("Backup created successfully")
    return 0
}

fun rotate_backups(backup_dir: Text, max_backups: Int) {
    let current_count = get_backup_count(backup_dir)?
    echo("Current backup count: {current_count}")

    // Remove old backups while we have too many
    while current_count > max_backups {
        echo("Removing oldest backup (count: {current_count}/{max_backups})")

        // Get the oldest backup file
        let oldest = trust $ ls -1t "{backup_dir}" | tail -n 1 $

        sudo $ rm "{backup_dir}/{oldest}" $ succeeded {
            echo("Removed: {oldest}")
        }
        current_count = get_backup_count(backup_dir)?
    }
    echo("Backup rotation complete. Keeping {current_count} backups.")
}

main(args) {
    if len(args) < 2 {
        echo("Usage: backup-rotator <source_dir> <backup_dir> [max_backups]")
        echo("Example: backup-rotator /var/www /backups 5")
        exit(1)
    }

    let source_dir = args[0]
    let backup_dir = args[1]
    let max_backups = len(args) >= 3
        then parse_int(args[2])?
        else 5

    // Validate source directory
    if not dir_exists(source_dir) {
        echo("Error: Source directory '{source_dir}' does not exist")
        exit(1)
    }

    // Create backup directory if it doesn't exist
    if not dir_exists(backup_dir) {
        echo("Creating backup directory: {backup_dir}")
        sudo dir_create(backup_dir) failed {
            echo("Failed to create backup directory")
            exit(1)
        }
    }

    // Create new backup
    create_backup(source_dir, backup_dir)?

    // Rotate old backups
    rotate_backups(backup_dir, max_backups)?
}