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;
+}


Reply via email to