#!/usr/bin/perl # Copyright (C) 2007-2009 Eric L. Wilhelm use warnings; use strict; =head1 NAME vc-checkup - cached version-control status checker =head1 About This program checks the status of a version-controlled checkout and prints a message if something has changed. It is suitable as a cron job for tracking changes to configuration or code directories. It keeps a cache in your ~/.vc_checkup/ directory and is currently hard-coded to create a reminder message every 6 hours after a change. Your help and input are welcome. =head1 See Also This uses L to handle the version-control actions. =cut package bin::vc_checkup; use Cwd (); use VCfs; use YAML::Syck; my $app_dir = $ENV{HOME} . '/.vc_checkup/'; my $cache_dir = $app_dir . '/cache/'; sub main { my (@args) = @_; my $now = time; my ($dir) = @args; my $pwd = Cwd::cwd(); if($dir) { chdir($dir) or die "cannot chdir $dir"; $dir = Cwd::abs_path($dir); } else { $dir = $pwd; } my $cachefile = $cache_dir . sub { my $p = shift; $p =~ s#^/+##; $p =~ s#/+#%2F#g; return($p); }->($dir); my %status = VCfs->new('.')->status; unless(%status) { # if it has been checked-in, clean the slate if(-e $cachefile) { unlink($cachefile) or die "cannot unlink '$cachefile' $!"; } return; } my $st = YAML::Syck::Dump(\%status); if(-e $cachefile) { my $cache = YAML::Syck::LoadFile($cachefile); # check if it changed or needs reminding my $notice; if($cache->{status} eq $st) { my $was = $cache->{updated} || $cache->{detected}; my $delta = 60*60*6; # XXX config if($was + $delta > $now) { return; # not worried yet } $cache->{updated} = $now; $notice = 'reminder'; } else { delete($cache->{updated}); $cache->{detected} = $now; $cache->{status} = $st; $notice = 'change detected'; } $notice or die "ack"; print "$notice\n\n$st"; YAML::Syck::DumpFile($cachefile, $cache); } else { # create a new cache unless(-d $cache_dir) { (-e $cache_dir) and die "'$cache_dir' exists, but is not a directory"; require File::Path; File::Path::mkpath($cache_dir); } print "change detected\n\n$st"; YAML::Syck::DumpFile($cachefile, { detected => $now, status => $st, }); } } package main; if($0 eq __FILE__) { bin::vc_checkup::main(@ARGV); } # vi:ts=2:sw=2:et:sta my $package = 'bin::vc_checkup';