From: Don Armstrong Date: Tue, 27 Dec 2005 06:09:29 +0000 (+0000) Subject: * Add stodo command which will automatically commit changes to todo files backed... X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=94e4d50539e8694d969d5ace319329b9ed95f250;p=bin.git * Add stodo command which will automatically commit changes to todo files backed by an svn repository --- diff --git a/stodo b/stodo new file mode 100644 index 0000000..d13fae7 --- /dev/null +++ b/stodo @@ -0,0 +1,259 @@ +#! /usr/bin/perl +# ss makes a screenshot of the screen using import, and is released +# under the terms of the GPL version 2, or any later version, at your +# option. See the file README and COPYING for more information. +# Copyright 2004 by Don Armstrong . +# $Id: ss,v 1.3 2004/09/27 05:58:55 don Exp $ + + +use warnings; +use strict; + + +use Getopt::Long; +use Pod::Usage; + +=head1 NAME + +stodo - devtodo event script which attempts to commit the changes made to a .todo file after a change + +=head1 SYNOPSIS + +stodo [options] + + Options: + --simulate, -s simulate: don't actually do anything + --quiet, -q don't output to STDOUT + --debug, -d debugging level (Default 0) + --help, -h display this help + --man, -m display manual + +=head1 OPTIONS + +=over + +=item B<--simulate, -s> + +Simulation mode, don't actually commit anything. + +=item B<--quiet, -q> + +Don't output anything to STDOUT + +=item B<--debug, -d> + +Debug verbosity. (Default 0) + +=item B<--help, -h> + +Display brief useage information. + +=item B<--man, -m> + +Display this manual. + +=back + +=head1 EXAMPLES + + on save { + exec stodo + } + + +=cut + + + +use Cwd qw(cwd); +use IO::File; +use XML::Simple; +use IO::Handle; +use Data::Diff qw(Diff); +use File::Basename qw(dirname basename); + +use vars qw($DEBUG); + +# XXX parse config file + +my %options = (quiet => 0, + debug => 0, + help => 0, + man => 0, + simulate => 0, + ); + +GetOptions(\%options,'debug|d+','help|h|?','man|m','quiet|q+','simulate|s+'); + +pod2usage() if $options{help} or not exists $ENV{TODODB}; +pod2usage({verbose=>2}) if $options{man}; + +$DEBUG = $options{debug}; + +# Figure out what we're doing +my $tododb = $ENV{TODODB}; +if ($tododb !~ m#^/#) { + $tododb = cwd().'/'.$tododb; +} +$tododb = full_readlink($tododb); +my $base_dir = dirname($tododb); +my $tododb_name = basename($tododb); + +if (not -e "$base_dir/.svn") { + print "$base_dir/.svn doesns't exist, not commiting" unless $options{quiet}; + exit 0; +} + +# Make sure that we can ping the subversion server +my $svn_entries_fh = new IO::File "$base_dir/.svn/entries",'r' + or die "unable to open $base_dir/.svn/entries: $!"; +my $url_type; +my $svn_host; +while (<$svn_entries_fh>) { + next unless m#^\s+url=\"(http|svn\+ssh|file):///?([^\/]+)#; + $url_type = $1; + last if $url_type eq 'file'; + $svn_host = $2; + last; +} + +if (not defined $svn_host and $url_type ne 'file') { + die "Was unable to find which host the svn repository is located on"; +} +if ($url_type ne 'file') { + qx(ping -q -c 3 $svn_host >/dev/null 2>&1); + if ($? != 0) { + print "Unable to ping $svn_host" unless $options{quiet}; + exit 0 unless $options{simulate}; + } +} + + +# See what has changed +#my $svn_fh = new IO::Handle; +#open($svn_fh,'-|','svn','diff',$tododb) or die "Unable to execute svn diff $tododb; $!"; +#while (<$svn_fh>) { +# next unless /^[-+]/; +#} + +my $todo_db_old = fix_content(XMLin("$base_dir/.svn/text-base/${tododb_name}.svn-base",KeyAttr=>'time')->{note}); +my $todo_db_new = fix_content(XMLin($tododb,KeyAttr=>'time')->{note}); + +my @commit_message; + +my $diff = Diff($todo_db_new,$todo_db_old); + +#use Data::Dumper; +#print Dumper($diff); + +if (exists $diff->{uniq_a}) { + foreach (values %{$diff->{uniq_a}}) { + my ($content,$priority) = map {s/^\s*|\s*$//g; s/\n/ /g; $_;} @{$_}{qw(content priority)}; + push @commit_message,qq( * Added todo: [$priority] $content); + } +} + +if (exists $diff->{uniq_b}) { + foreach (values %{$diff->{uniq_b}}) { + my ($content,$priority) = map {s/^\s*|\s*$//g; s/\n/ /g; $_;} @{$_}{qw(content priority)}; + push @commit_message,qq( * Deleted todo: [$priority] $content); + } +} + +if (exists $diff->{diff}) { + # This entry has either been edited, completed, or uncompleted + foreach my $entry_key (keys %{$diff->{diff}}) { + my ($content,$priority) = map {s/^\s*|\s*$//g; s/\n/ /g; $_;} @{$todo_db_new->{$entry_key}}{qw(content priority)}; + my $diff_entry = $diff->{diff}{$entry_key}; + if (exists $diff_entry->{uniq_a} and exists $diff_entry->{uniq_a}{done}) { + push @commit_message,qq( * Finished todo: [$priority] $content); + } + if (exists $diff_entry->{uniq_a} and exists $diff_entry->{uniq_b}{done}) { + push @commit_message,qq( * Marked as undone: [$priority] $content); + } + if (exists $diff_entry->{diff}) { + my @what_changed; + if (exists $diff_entry->{diff}{content}) { + push @what_changed,'content'; + } + if (exists $diff_entry->{diff}{priority}) { + push @what_changed,'priority'; + } + if (not @what_changed) { + @what_changed = keys %{$diff_entry->{diff}}; + } + push @commit_message,qq( * Todo changed ).join(' and ',@what_changed).qq( [$priority] $content); + } + } +} + +if (exists $diff->{same}) { + foreach my $entry_key (keys %{$diff->{same}}) { + my ($content,$priority) = map {s/^\s*|\s*$//g; s/\n/ /g; $_;} @{$todo_db_new->{$entry_key}}{qw(content priority)}; + my $diff_entry = $diff->{same}{$entry_key}; + if (exists $diff_entry->{uniq_a} and exists $diff_entry->{uniq_a}{done}) { + push @commit_message,qq( * Finished todo: [$priority] $content); + } + if (exists $diff_entry->{uniq_a} and exists $diff_entry->{uniq_b}{done}) { + push @commit_message,qq( * Marked as undone: [$priority] $content); + } + if (exists $diff_entry->{diff}) { + my @what_changed; + if (exists $diff_entry->{diff}{content}) { + push @what_changed,'content'; + } + if (exists $diff_entry->{diff}{priority}) { + push @what_changed,'priority'; + } + if (not @what_changed) { + @what_changed = keys %{$diff_entry->{diff}}; + } + push @commit_message,qq( * Todo changed ).join(' and ',@what_changed).qq( [$priority] $content); + } + } +} + + +if (not @commit_message) { + print "No commit message\n" if $DEBUG or $options{simulate}; + exit 0; +} + +my $commit_message = join('', map {qq($_\n)} @commit_message); +if ($options{simulate}) { + print "svn commit -F - $tododb <{content}) { + $entry->{content} =~ s/^\s*|\s*$//g; + } + if (exists $entry->{comment}) { + $entry->{comment} =~ s/^\s*|\s*$//g; + } + } + return $s; +} + + +sub full_readlink { + my ($file) = @_; + while (-l $file) { + $file = readlink $file; + } + + return $file; +} + +__END__