Author: bdonlan
Date: 2004-06-05 17:37:23 -0400 (Sat, 05 Jun 2004)
New Revision: 226
Added:
trunk/dev-tools/cold-backup.pl
Log:
Add cold-backup.pl for svnadmin dmups
Copied: trunk/dev-tools/cold-backup.pl (from rev 225,
trunk/dev-tools/hot-backup.pl)
===================================================================
--- trunk/dev-tools/hot-backup.pl 2004-06-05 20:53:32 UTC (rev 225)
+++ trunk/dev-tools/cold-backup.pl 2004-06-05 21:37:23 UTC (rev 226)
@@ -0,0 +1,179 @@
+#!/usr/bin/perl
+#
+# hot-backup.pl: perform a "hot" backup of a Berkeley DB repository.
+# (and clean old logfiles after backup completes.)
+######################################################################
+
+use strict;
+use warnings;
+use File::Spec;
+use File::Basename 'basename';
+use IO::Dir;
+use Getopt::Long;
+use File::Path ();
+use IPC::Open3;
+
+######################################################################
+# Global Settings
+
+my %option = (
+ symlink => 0,
+ overwrite => 0,
+ backlog => 10,
+ svnadmin => '/usr/bin/svnadmin',
+ svnlook => '/usr/bin/svnlook',
+);
+
+GetOptions(\%option, 'backlog=i', 'overwrite|force', 'svnadmin=s',
'svnlook=s', 'symlink');
+
+
+# Path to svnlook utility
+my $svnlook = $option{svnlook};
+
+# Path to svnadmin utility
+my $svnadmin = $option{svnadmin};
+
+# Number of backups to keep around (0 for "keep them all")
+my $num_backups = 5;
+
+######################################################################
+# Command line arguments
+
+
+if (@ARGV != 2) {
+ print 'Usage: ', basename($0), ' [options] <repos_path> <backup_path>',
"\n";
+ exit 1;
+}
+
+# Path to repository
+my $repo_dir = $ARGV[0];
+my $repo = basename(File::Spec->rel2abs($repo_dir || ''));
+
+# Where to store the repository backup. The backup will be placed in
+# a file in this location, named after the youngest revision.
+my $backup_dir = $ARGV[1];
+
+######################################################################
+# Main
+
+print "Beginning cold backup of '$repo_dir'.\n";
+
+
+### Step 1: get the youngest revision.
+
+my $pipe;
+my $pid = open($pipe, '-|', $svnlook, 'youngest', $repo_dir)
+ or die "Can't run $svnlook, $!";
+
+my $youngest = readline $pipe;
+chomp $youngest;
+
+print "Youngest revision is $youngest\n";
+
+### Step 2: Find next available backup path
+
+#backup_subdir = os.path.join(backup_dir, repo + "-" + youngest)
+my $backup_file = File::Spec->catfile($backup_dir, "$repo-$youngest");
+
+# Normally, you don't need to re-dump if there's no revision
+
+unless ($option{'overwrite'}) {
+ if (-e $backup_file) {
+ print "Target file already exists.\n";
+ exit 1;
+ }
+} else {
+ if (-e $backup_file ) {
+ unlink($backup_file)
+ or die "Unable to unlink old copy of $backup_file: $!";
+ }
+}
+
+### Step 3: Ask subversion to make a dump of a repository.
+
+system("(svnadmin dump $repo > $backup_file) 2>&1") and exit $?;
+
+### Step 3+1: If --symlink is given, symlink the latest version.
+if ($option{symlink}) {
+ my $current = File::Spec->catfile($backup_dir, "$repo-current");
+ my $backup_file = "$repo-$youngest";
+ print "Symlinking $backup_file to $current (if needed)\n";
+
+ my $do_link = 1;
+
+ if (-e $current) {
+ my $link = readlink $current
+ or warn "Error reading link $current, $!\n";
+
+ if ($link ne $backup_file) {
+ unlink($current) or warn "Can't unlink $current. $!\n";
+ } else {
+ $do_link = 0;
+ }
+ }
+
+ if ($do_link) {
+ print "Performing symlink\n";
+ symlink($backup_file, $current)
+ or warn "Can't symlink $backup_file to $current! $!\n";
+ }
+}
+
+### Step 4: finally, remove all repository backups other than the last
+### $option{backlog}.
+
+if ($option{backlog} > 0) {
+ my $regexp = qr/^$repo-\d+(-\d+)?$/;
+ my @dirs = listdir($backup_dir);
+ my @old = grep (/$regexp/, @dirs);
+ @old = sort { comparator($a, $b) } @old;
+
+ my $start = max(0, @old - $option{backlog});
+ my $stop = @old;
+ splice(@old, $start, $stop);
+
+ my $item;
+ for $item (@old) {
+ my $old_backup_file = File::Spec->catdir($backup_dir, $item);
+ print "Removing old backup: $old_backup_file\n";
+ unlink $old_backup_file
+ or warn "Can't unlink $old_backup_file: $!";
+ }
+}
+
+######################################################################
+# Helper functions
+
+sub comparator {
+ my ($a, $b) = @_;
+
+ my $regexp = qr/-([0-9]+)(?:-([0-9]+))?$/;
+ my ($reva, $inca) = $a =~ $regexp;
+ my ($revb, $incb) = $b =~ $regexp;
+
+ if ($reva < $revb) {
+ return -1;
+ } elsif ($reva > $revb) {
+ return 1;
+ } else {
+ if (not $inca) {
+ return -1;
+ } elsif (not $incb) {
+ return 1;
+ } elsif (int($inca) < int($incb)) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+}
+
+sub listdir {
+ my ($dir) = @_;
+ grep (!/^\.\.?$/, IO::Dir->new($backup_dir)->read);
+}
+
+sub max {
+ my ($a, $b) = @_;
+ $a > $b ? $a : $b;
+}