]> git.donarmstrong.com Git - bin.git/commitdiff
* Add stodo command which will automatically commit changes to todo files backed...
authorDon Armstrong <don@donarmstrong.com>
Tue, 27 Dec 2005 06:09:29 +0000 (06:09 +0000)
committerDon Armstrong <don@donarmstrong.com>
Tue, 27 Dec 2005 06:09:29 +0000 (06:09 +0000)
stodo [new file with mode: 0644]

diff --git a/stodo b/stodo
new file mode 100644 (file)
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 <don@donarmstrong.com>.
+# $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 <<EOF\n";
+     print $commit_message;
+     print "EOF\n";
+}
+else {
+     system('svn','commit','-m',$commit_message,$tododb);
+}
+
+
+# Commit the changes with an appropriate commit message
+
+
+sub fix_content {
+     my ($s) = @_;
+     foreach my $entry (values %{$s}) {
+         if (exists $entry->{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__