From 01c4b19baa81fd88518c23dbdfa6d4be1cc19c34 Mon Sep 17 00:00:00 2001
From: Gerhard Gonter <ggonter@gmail.com>
Date: Fri, 3 Jan 2014 10:05:39 +0100
Subject: [PATCH] added quick scan option for upcoming script "tbshow"

---
 perl/Gnome-Tomboy/lib/Tomboy/Directory.pm | 109 +++++++++++++++++++---
 perl/Gnome-Tomboy/s2.pl                   |  60 ++++++++++--
 2 files changed, 148 insertions(+), 21 deletions(-)

diff --git a/perl/Gnome-Tomboy/lib/Tomboy/Directory.pm b/perl/Gnome-Tomboy/lib/Tomboy/Directory.pm
index 333e280..437a663 100644
--- a/perl/Gnome-Tomboy/lib/Tomboy/Directory.pm
+++ b/perl/Gnome-Tomboy/lib/Tomboy/Directory.pm
@@ -12,18 +12,32 @@
 
 process a directory containing note files in Tomboy format
 
+=head1 SYNOPSIS
+
+  my $tb_dir= new Tomboy::Directory;
+  $tb_toc= $tb_dir->scan_dir ($directory);
+
 =cut
 
 package Tomboy::Directory;
 
 use strict;
 
+use Data::Dumper;
+$Data::Dumper::Indent= 1;
+
 use Tomboy::Note::Simple;
 
 # attributes read from the note itself or from the filesystem
 my @TB_note_attrs= qw(title create-date last-change-date last-metadata-change-date notebook is_template fnm);
-my @TB_meta_attrs= qw(uuid mtime size);
-sub TB_attrs { return (@TB_meta_attrs, @TB_note_attrs) }
+my @TB_meta_attrs= qw(uuid mtime size ino);
+=head1 METHODS
+
+=head2 my $tb_dir= new Tomboy::Directory()
+
+creates a new directory object
+
+=cut
 
 sub new
 {
@@ -42,10 +56,26 @@ sub new
   $obj;
 }
 
+=head2 $tb_dir->scan_dir ($directory, ($rows, $quick]))
+
+Scan named directory for Tomboy notes and extract key features using
+Tomboy::Note::Simple.  These features are placed into a record and all
+these records are returned as array reference.
+
+Optionally pass an array reference of such records as $rows and when
+$quick has a true value, the note files are only processed when they
+do not appear to be modified, otherwise the earlier record is passed in
+the result set.
+
+=cut
+
 sub scan_dir
 {
-  my $obj= shift;
-  my $dir= shift;
+  my $obj=   shift;
+  my $dir=   shift;
+  my $rows=  shift; # contents of an earlier scan
+  my $quick= shift; # 0/undef: full scan
+                    # 1: quick scan
 
   $dir=~ s#/+$##;
   unless (opendir (DIR, $dir))
@@ -54,7 +84,21 @@ sub scan_dir
     return undef;
   }
 
+  my %fnm;
+  if (defined ($quick) && defined ($rows))
+  {
+    print "scan_dir: quick=[$quick]\n";
+    # print "rows: ", Dumper ($rows);
+    %fnm= map { $_->{'fnm'} => $_ } @$rows;
+    # print "fnm: ", Dumper (\%fnm);
+  }
+  else
+  {
+    $quick= 0;
+  }
+
   my @res= ();
+  my ($cnt_added, $cnt_updated, $cnt_unchanged)= (0, 0, 0);
   NOTE: while (my $e= readdir (DIR))
   {
     next NOTE if ($e eq '.' || $e eq '..');
@@ -70,6 +114,34 @@ sub scan_dir
       next NOTE;
     }
 
+    if ($quick)
+    {
+      my $x_rec= $fnm{$fp};
+
+      if (defined ($x_rec))
+      {
+        if ($x_rec->{'mtime'}   == $st[9]
+            && $x_rec->{'size'} == $st[7]
+            && $x_rec->{'ino'}  == $st[1]
+           )
+        {
+          $cnt_unchanged++;
+          push (@res, $x_rec);
+          next NOTE;
+        }
+        else
+        {
+          print "updated: $fp\n";
+          $cnt_updated++;
+        }
+      }
+      else
+      {
+        print "added: $fp\n";
+        $cnt_added++;
+      }
+    }
+
     my $n= parse Tomboy::Note::Simple ($fp);
 
     unless (defined ($n))
@@ -83,26 +155,33 @@ sub scan_dir
     $rec{'uuid'}= $fnm_uuid;
     $rec{'mtime'}= $st[9];
     $rec{'size'}= $st[7];
+    $rec{'ino'}= $st[1];
 
-=begin comment
-
-... this is now part of Tomboy::Note::Simple
-    foreach my $tag (@{$n->{'tags'}})
-    {
-         if ($tag =~ m#system:notebook:(.+)#) { $rec{'notebook'}= $1 }
-      elsif ($tag eq 'system:template')       { $rec{'is_template'}= 1 }
-    }
-
-=end comment
-=cut
+    # $rec{'present'}= 1; # flag to indicate which objects were dropped
 
     push (@res, \%rec);
   }
 
   closedir (DIR);
 
+# TODO: list dropped files
+# TODO: save statistics and/or file status for later processing
+
+  print "statistics: cnt_added=$cnt_added cnt_updated=$cnt_updated cnt_unchanged=$cnt_unchanged\n";
   (wantarray) ? @res : \@res;
 }
 
+=head2 $tb_dir->TB_attrs
+
+return a list of directory attributes
+
+=cut
+
+sub TB_attrs
+{
+  my $s= shift;
+  return (@TB_meta_attrs, @TB_note_attrs);
+}
+
 1;
 
diff --git a/perl/Gnome-Tomboy/s2.pl b/perl/Gnome-Tomboy/s2.pl
index 86d6186..e571139 100755
--- a/perl/Gnome-Tomboy/s2.pl
+++ b/perl/Gnome-Tomboy/s2.pl
@@ -23,23 +23,71 @@ $Data::Dumper::Indent= 1;
 # use Tomboy::Note::Simple;
 use Tomboy::Directory;
 
-my $note_dir= shift (@ARGV);
 my $toc_file= 'Tomboy-TOC.csv';
 
+my @PAR= ();
+while (my $arg= shift (@ARGV))
+{
+  if ($arg =~ /^-/)
+  {
+    usage();
+  }
+  else
+  {
+    push (@PAR, $arg);
+  }
+}
+
+my $note_dir= shift (@PAR);
 die "no note dir specified" unless ($note_dir);
 
 $note_dir=~ s#/+$##;
-my $tb_d= new Tomboy::Directory ('dir' => $note_dir);
-
+my $tb_d= new Tomboy::Directory ();
 print "tb_d: ", Dumper ($tb_d);
 
-my $toc_data= $tb_d->scan_dir ($note_dir);
+my $toc= new Util::Simple_CSV ('UTF8' => 1, 'no_array' => 1, 'separator' => "\t", 'UTF8' => 1);
+
+my $mode= 0;
+my $rows= [];
+
+if (-f $toc_file)
+{
+  $toc->load_csv_file ($toc_file);
+
+  $mode= 1;
+  $rows= $toc->{'data'};
+  print "preparing quick scan, loaded [$toc_file]\n";
+  # print "toc: ", Dumper ($toc);
+  # print "rows: ", Dumper ($rows);
+  # exit;
+}
+else
+{
+  # $toc->define_columns (Tomboy::Directory::TB_attrs());
+  $toc->define_columns ($tb_d->TB_attrs());
+}
+
+my $toc_data= $tb_d->scan_dir ($note_dir, $rows, $mode);
 # TODO: if verbose or so print "toc_data: ", Dumper ($toc_data);
 
-my $toc= new Util::Simple_CSV ('UTF8' => 1, 'no_hash' => 1);
-$toc->define_columns (Tomboy::Directory::TB_attrs());
 $toc->{'data'}= $toc_data;
+# TODO: optionally sort the returned values
+$toc->sort ('uuid');
+# print "toc: ", Dumper ($toc);
 $toc->save_csv_file ('filename' => $toc_file, 'separator' => "\t", 'UTF8' => 1);
 
 exit (0);
 
+__END__
+
+=head1 TODO
+
+ * enhance this to create a standalone script (e.g. tbshow)
+ * cache the data in ~/.gcache ?? check out how this is supposed to work
+ * optionally, integrate with version control for quick synchronization
+
+
+
+
+
+
-- 
GitLab