WIP Note Directory Watcher Patch - v2

View: New views
7 Messages — Rating Filter:   Alert me  

WIP Note Directory Watcher Patch - v2

by Michael Fletcher-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The NoteDirectoryWatcher Addin is nearly ready.  Its useful and there
is little chance of you losing your data.  Please check out the
updated patch and preamble.



If you use an external process to modify you ".note" files (ie
DropBox) there is a significant risk that you will lose you note data.
 Tomboy will overwrite the note on disk with its representation in
memory.

NoteDirectoryWatcher will watch your ~/.tomboy directory for changes
and update Tomboy's in-memory copy of the note if the note changes.
This reduces the change of losing notes.

Unfortunately there is still a small chance you will lose data.  If you
a) Update a note externally.
b) Change the note in Tomboy more than 4 seconds but less than five
seconds after A.  I'll work on this later.

There is still one corner case that needs to be handled
(FileSystemWatcher.Error) but its highly unlikely you will encounter
it.  Running Tomboy under windows with your notes on a SMB share is a
good way to try :).

[watch.patch]

diff --git a/Tomboy/Addins/Makefile.am b/Tomboy/Addins/Makefile.am
index 57f5f56..9520b67 100644
--- a/Tomboy/Addins/Makefile.am
+++ b/Tomboy/Addins/Makefile.am
@@ -13,5 +13,6 @@ SUBDIRS = \
  SshSyncService \
  StickyNoteImport \
  Tasque \
+ NoteDirectoryWatcher \
  WebDavSyncService
 
diff --git a/Tomboy/Addins/NoteDirectoryWatcher/Makefile.am b/Tomboy/Addins/NoteDirectoryWatcher/Makefile.am
new file mode 100644
index 0000000..8250fd2
--- /dev/null
+++ b/Tomboy/Addins/NoteDirectoryWatcher/Makefile.am
@@ -0,0 +1,39 @@
+include $(top_srcdir)/Makefile.include
+
+CSFLAGS = \
+ -debug \
+ -define:DEBUG \
+ -target:library
+
+ASSEMBLIES = \
+ $(LINK_TOMBOY_EXE) \
+ $(GTKSHARP_LIBS) \
+ $(LINK_MONO_ADDINS) \
+ -r:Mono.Posix
+
+ADDIN_NAME = NoteDirectoryWatcher
+TARGET = $(ADDIN_NAME).dll
+CSFILES = \
+ $(srcdir)/NoteDirectoryWatcherApplicationAddin.cs
+RESOURCES = \
+ -resource:$(srcdir)/$(ADDIN_NAME).addin.xml
+
+$(TARGET).mdb: $(TARGET)
+
+$(TARGET): $(CSFILES) $(top_builddir)/Tomboy/Tomboy.exe
+ $(CSC) -out:$@ $(CSFLAGS) $(ASSEMBLIES) $(CSFILES) $(RESOURCES)
+
+
+addinsdir = $(pkglibdir)/addins
+addins_DATA = \
+ $(TARGET) \
+ $(TARGET).mdb
+
+EXTRA_DIST =             \
+ $(CSFILES) \
+ $(srcdir)/$(ADDIN_NAME).addin.xml
+
+CLEANFILES = \
+ $(TARGET).mdb \
+ $(TARGET)
+
diff --git a/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml
new file mode 100644
index 0000000..6bfd500
--- /dev/null
+++ b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml
@@ -0,0 +1,22 @@
+<Addin id="NoteDirectoryWatcher"
+ namespace="Tomboy"
+ name="Note Directory Watcher"
+ author="Tomboy Project"
+ description="Watch your Tomboy note directory for changes to your notes."
+ category="Tools"
+ defaultEnabled="false"
+ version="0.1">
+
+ <Runtime>
+ <Import assembly="NoteDirectoryWatcher.dll" />
+ </Runtime>
+
+ <Dependencies>
+ <Addin id="Tomboy" version="0.10" />
+ </Dependencies>
+
+ <Extension path="/Tomboy/ApplicationAddins">
+ <ApplicationAddin type="Tomboy.NoteDirectoryWatcher.NoteDirectoryWatcherApplicationAddin" />
+ </Extension>
+
+</Addin>
diff --git a/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs
new file mode 100644
index 0000000..07ab267
--- /dev/null
+++ b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs
@@ -0,0 +1,233 @@
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+using Tomboy;
+
+namespace Tomboy.NoteDirectoryWatcher
+{
+ class NoteFileChangeRecord
+ {
+ public DateTime last_change;
+ public bool deleted;
+ public bool changed;
+ }
+
+ public class NoteDirectoryWatcherApplicationAddin : ApplicationAddin
+ {
+ private static bool VERBOSE_LOGGING = false;
+
+ private FileSystemWatcher file_system_watcher;
+ private bool initialized;
+
+ private Dictionary<string, NoteFileChangeRecord> file_change_records;
+
+ public override void Initialize ()
+ {
+ string note_path = Tomboy.DefaultNoteManager.NoteDirectoryPath;
+
+ file_change_records = new Dictionary<string, NoteFileChangeRecord>();
+
+ file_system_watcher = new FileSystemWatcher (note_path);
+
+ file_system_watcher.Changed += HandleFileSystemChangeEvent;
+ file_system_watcher.Deleted += HandleFileSystemChangeEvent;
+ file_system_watcher.Created += HandleFileSystemChangeEvent;
+ file_system_watcher.Renamed += HandleFileSystemChangeEvent;
+
+ file_system_watcher.Error += HandleFileSystemErrorEvent;
+
+ // Setting to true will starts the FileSystemWatcher.
+ file_system_watcher.EnableRaisingEvents = true;
+
+ initialized = true;
+ }
+
+ public override void Shutdown ()
+ {
+ file_system_watcher.EnableRaisingEvents = false;
+ initialized = false;
+ }
+
+ public override bool Initialized
+ {
+ get
+ {
+ return initialized;
+ }
+ }
+
+ private void HandleFileSystemErrorEvent (Object sender, ErrorEventArgs arg)
+ {
+ // TODO Rescan the local notes in case some of them have changed.
+ }
+
+ private void HandleFileSystemChangeEvent (Object sender, FileSystemEventArgs arg)
+ {
+ string note_id = GetId(arg.FullPath);
+
+ if (VERBOSE_LOGGING)
+ {
+ Logger.Debug ("{0} has {1} (note_id={2})", arg.FullPath, arg.ChangeType, note_id);
+ }
+
+ // If the note_id is long 36 characters then the file probably wasn't a note.
+ if (note_id.Length != 36)
+ {
+ if (VERBOSE_LOGGING)
+ {
+ Logger.Debug ("Ignoring change to {0}", arg.FullPath);
+ }
+
+ return;
+ }
+
+ // Record that the file has been added/changed/deleted.  Adds/changes trump
+ // deletes.  Record the date.
+ lock (file_change_records)
+ {
+ NoteFileChangeRecord record = null;
+
+ if (file_change_records.ContainsKey (note_id))
+ {
+ record = file_change_records[note_id];
+ }
+ else
+ {
+ record = new NoteFileChangeRecord ();
+ file_change_records[note_id] = record;
+ }
+
+ if (arg.ChangeType == WatcherChangeTypes.Changed)
+ {
+ record.changed = true;
+ record.deleted = false;
+ }
+ else if (arg.ChangeType == WatcherChangeTypes.Created)
+ {
+ record.changed = true;
+ record.deleted = false;
+ }
+ else if (arg.ChangeType == WatcherChangeTypes.Renamed)
+ {
+ record.changed = true;
+ record.deleted = false;
+ }
+ else if (arg.ChangeType == WatcherChangeTypes.Deleted)
+ {
+ if (!record.changed)
+ {
+ record.deleted = true;
+ }
+ }
+ else
+ {
+ String message = "Unexpected WatcherChangeType " + arg.ChangeType;
+ Logger.Error (message);
+ throw new Exception (message);
+ }
+
+ record.last_change = DateTime.Now;
+ }
+
+ GLib.Timeout.Add (5000, new GLib.TimeoutHandler (HandleTimeout));
+ }
+
+ private bool HandleTimeout ()
+ {
+ lock (file_change_records)
+ {
+ List<string> keysToRemove = new List<string> (file_change_records.Count);
+
+ foreach (KeyValuePair<string, NoteFileChangeRecord> pair in file_change_records)
+ {
+ if (VERBOSE_LOGGING)
+ {
+ Logger.Debug ("Handling (timeout) {0}", pair.Key);
+ }
+
+ if (DateTime.Now > pair.Value.last_change.Add (new TimeSpan (4000)) )
+ {
+ if (pair.Value.deleted)
+ {
+ DeleteNote (pair.Key);
+ }
+ else
+ {
+ AddOrUpdateNote (pair.Key);
+ }
+
+ keysToRemove.Add (pair.Key);
+ }
+ }
+
+ foreach (string note_id in keysToRemove)
+ {
+ file_change_records.Remove (note_id);
+ }
+ }
+
+ return false;
+ }
+
+ private static void DeleteNote (string note_id)
+ {
+ Logger.Debug ("Deleting {0} because file deleted.", note_id);
+
+ string note_uri = MakeUri (note_id);
+
+ Note note_to_delete = Tomboy.DefaultNoteManager.FindByUri (note_uri);
+
+ Tomboy.DefaultNoteManager.Notes.Remove (note_to_delete);
+
+ note_to_delete.Delete ();
+ }
+
+ private static void AddOrUpdateNote (string note_id)
+ {
+ string note_path = Tomboy.DefaultNoteManager.NoteDirectoryPath +
+ Path.DirectorySeparatorChar + note_id + ".note";
+
+ string note_uri = MakeUri (note_id);
+
+ Note note = Tomboy.DefaultNoteManager.FindByUri (note_uri);
+
+ if (note == null)
+ {
+ Logger.Debug ("Adding {0} because file changed.", note_id);
+ Note new_note = Note.Load (note_path, Tomboy.DefaultNoteManager);
+ Tomboy.DefaultNoteManager.Notes.Add (new_note);
+ }
+ else
+ {
+ NoteData data = NoteArchiver.Instance.ReadFile (note_path, note_uri);
+
+ // Only record changes if the note actually changes.  This prevents the Addin from
+ // noticing changes from Tomboy itself.
+ if (data.Text == note.XmlContent)
+ {
+ if (VERBOSE_LOGGING)
+ {
+ Logger.Debug ("Ignoring {0} because contents identical", note_id);
+ }
+ }
+                               else
+                               {
+ Logger.Debug ("Updating {0} because file changed.", note_id);
+ note.XmlContent = data.Text;
+ note.Title = data.Title;
+ }
+ }
+ }
+
+ private static String MakeUri (string note_id)
+               {
+ return "note://tomboy/" + note_id;
+ }
+
+ private static string GetId (string path)
+               {
+ int last_slash = path.LastIndexOf (Path.DirectorySeparatorChar);
+ int first_period = path.IndexOf ('.', last_slash);
+
+ return path.Substring (last_slash + 1, first_period - last_slash - 1);
+ }
+ }
+}
diff --git a/configure.in b/configure.in
index ab9b951..8563e58 100644
--- a/configure.in
+++ b/configure.in
@@ -333,6 +333,7 @@ Tomboy/Addins/SshSyncService/Makefile
 Tomboy/Addins/StickyNoteImport/Makefile
 Tomboy/Addins/Tasque/Makefile
 Tomboy/Addins/WebDavSyncService/Makefile
+Tomboy/Addins/NoteDirectoryWatcher/Makefile
 test/Makefile
 po/Makefile.in
 ])


_______________________________________________
Tomboy-list mailing list
Tomboy-list@...
http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com

Re: WIP Note Directory Watcher Patch - v2

by Sandy Armstrong :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Only time for a quick look right now, but I still think you should use
Note.LoadForeignNoteXml instead of setting note.XmlContent and
note.Title (it picks up a bunch of other metadata, whereas XmlContent
just picks up stuff in the content area).

Going to play with this soon, want to get it in git ASAP.

BTW, does anybody else feel weird writing "git" all lower-case, after
years of "CVS" and "SVN"?  :-P

On Tue, Apr 28, 2009 at 12:40 PM, Michael Fletcher
<m.fletcher@...> wrote:

> The NoteDirectoryWatcher Addin is nearly ready.  Its useful and there
> is little chance of you losing your data.  Please check out the
> updated patch and preamble.
>
>
>
> If you use an external process to modify you ".note" files (ie
> DropBox) there is a significant risk that you will lose you note data.
>  Tomboy will overwrite the note on disk with its representation in
> memory.
>
> NoteDirectoryWatcher will watch your ~/.tomboy directory for changes
> and update Tomboy's in-memory copy of the note if the note changes.
> This reduces the change of losing notes.
>
> Unfortunately there is still a small chance you will lose data.  If you
> a) Update a note externally.
> b) Change the note in Tomboy more than 4 seconds but less than five
> seconds after A.  I'll work on this later.
>
> There is still one corner case that needs to be handled
> (FileSystemWatcher.Error) but its highly unlikely you will encounter
> it.  Running Tomboy under windows with your notes on a SMB share is a
> good way to try :).
>
> _______________________________________________
> Tomboy-list mailing list
> Tomboy-list@...
> http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com
>
>
_______________________________________________
Tomboy-list mailing list
Tomboy-list@...
http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com

Re: WIP Note Directory Watcher Patch - v2

by Michael Fletcher-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> Only time for a quick look right now, but I still think you should use
> Note.LoadForeignNoteXml instead of setting note.XmlContent and
> note.Title (it picks up a bunch of other metadata, whereas XmlContent
> just picks up stuff in the content area).
Sorry, I was going to comment on this.  I tried and it didn't work.
The UI was never updated.  I don't know enough about Tomboy internals
to know why.
_______________________________________________
Tomboy-list mailing list
Tomboy-list@...
http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com

Re: WIP Note Directory Watcher Patch - v2

by Sandy Armstrong :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Apr 28, 2009 at 2:11 PM, Michael Fletcher
<m.fletcher@...> wrote:
>> Only time for a quick look right now, but I still think you should use
>> Note.LoadForeignNoteXml instead of setting note.XmlContent and
>> note.Title (it picks up a bunch of other metadata, whereas XmlContent
>> just picks up stuff in the content area).
> Sorry, I was going to comment on this.  I tried and it didn't work.
> The UI was never updated.  I don't know enough about Tomboy internals
> to know why.

Okay, I'll look into it, thanks!

Sandy
_______________________________________________
Tomboy-list mailing list
Tomboy-list@...
http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com

Re: WIP Note Directory Watcher Patch - v2

by Sandy Armstrong :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Apr 28, 2009 at 2:45 PM, Sandy Armstrong
<sanfordarmstrong@...> wrote:

> On Tue, Apr 28, 2009 at 2:11 PM, Michael Fletcher
> <m.fletcher@...> wrote:
>>> Only time for a quick look right now, but I still think you should use
>>> Note.LoadForeignNoteXml instead of setting note.XmlContent and
>>> note.Title (it picks up a bunch of other metadata, whereas XmlContent
>>> just picks up stuff in the content area).
>> Sorry, I was going to comment on this.  I tried and it didn't work.
>> The UI was never updated.  I don't know enough about Tomboy internals
>> to know why.
>
> Okay, I'll look into it, thanks!

Mike, I'd like to get this into git, and work on it centrally.  Can
you commit to master, make a patch with git-format-patch, and email
that to the list?  Then I'll push it and we can start polishing it a
bit.

Thanks,
Sandy
_______________________________________________
Tomboy-list mailing list
Tomboy-list@...
http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com

Parent Message unknown Re: WIP Note Directory Watcher Patch - v2

by Michael Fletcher-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello

The patch using git-format-patch is attached.

[0001-If-you-use-an-external-process-to-modify-you-.note.patch]

From ed8f963732266f40b63d1a1868f5e3a3ab03980f Mon Sep 17 00:00:00 2001
From: Michael Fletcher <m.fletcher@...>
Date: Wed, 29 Apr 2009 19:45:29 -0600
Subject: [PATCH] If you use an external process to modify you ".note" files (ie
 DropBox) there is a significant risk that you will lose you note data.
  Tomboy will overwrite the note on disk with its representation in
 memory.

This patch will watch your ~/.tomboy directory for changes
and update Tomboy's in-memory copy of the note if the note changes.
This reduces the change of losing notes.
---
 Tomboy/Addins/Makefile.am                          |    1 +
 Tomboy/Addins/NoteDirectoryWatcher/Makefile.am     |   39 ++++
 .../NoteDirectoryWatcher.addin.xml                 |   22 ++
 .../NoteDirectoryWatcherApplicationAddin.cs        |  237 ++++++++++++++++++++
 configure.in                                       |    1 +
 5 files changed, 300 insertions(+), 0 deletions(-)
 create mode 100644 Tomboy/Addins/NoteDirectoryWatcher/Makefile.am
 create mode 100644 Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml
 create mode 100644 Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs

diff --git a/Tomboy/Addins/Makefile.am b/Tomboy/Addins/Makefile.am
index 57f5f56..9520b67 100644
--- a/Tomboy/Addins/Makefile.am
+++ b/Tomboy/Addins/Makefile.am
@@ -13,5 +13,6 @@ SUBDIRS = \
  SshSyncService \
  StickyNoteImport \
  Tasque \
+ NoteDirectoryWatcher \
  WebDavSyncService
 
diff --git a/Tomboy/Addins/NoteDirectoryWatcher/Makefile.am b/Tomboy/Addins/NoteDirectoryWatcher/Makefile.am
new file mode 100644
index 0000000..8250fd2
--- /dev/null
+++ b/Tomboy/Addins/NoteDirectoryWatcher/Makefile.am
@@ -0,0 +1,39 @@
+include $(top_srcdir)/Makefile.include
+
+CSFLAGS = \
+ -debug \
+ -define:DEBUG \
+ -target:library
+
+ASSEMBLIES = \
+ $(LINK_TOMBOY_EXE) \
+ $(GTKSHARP_LIBS) \
+ $(LINK_MONO_ADDINS) \
+ -r:Mono.Posix
+
+ADDIN_NAME = NoteDirectoryWatcher
+TARGET = $(ADDIN_NAME).dll
+CSFILES = \
+ $(srcdir)/NoteDirectoryWatcherApplicationAddin.cs
+RESOURCES = \
+ -resource:$(srcdir)/$(ADDIN_NAME).addin.xml
+
+$(TARGET).mdb: $(TARGET)
+
+$(TARGET): $(CSFILES) $(top_builddir)/Tomboy/Tomboy.exe
+ $(CSC) -out:$@ $(CSFLAGS) $(ASSEMBLIES) $(CSFILES) $(RESOURCES)
+
+
+addinsdir = $(pkglibdir)/addins
+addins_DATA = \
+ $(TARGET) \
+ $(TARGET).mdb
+
+EXTRA_DIST =             \
+ $(CSFILES) \
+ $(srcdir)/$(ADDIN_NAME).addin.xml
+
+CLEANFILES = \
+ $(TARGET).mdb \
+ $(TARGET)
+
diff --git a/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml
new file mode 100644
index 0000000..6bfd500
--- /dev/null
+++ b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml
@@ -0,0 +1,22 @@
+<Addin id="NoteDirectoryWatcher"
+ namespace="Tomboy"
+ name="Note Directory Watcher"
+ author="Tomboy Project"
+ description="Watch your Tomboy note directory for changes to your notes."
+ category="Tools"
+ defaultEnabled="false"
+ version="0.1">
+
+ <Runtime>
+ <Import assembly="NoteDirectoryWatcher.dll" />
+ </Runtime>
+
+ <Dependencies>
+ <Addin id="Tomboy" version="0.10" />
+ </Dependencies>
+
+ <Extension path="/Tomboy/ApplicationAddins">
+ <ApplicationAddin type="Tomboy.NoteDirectoryWatcher.NoteDirectoryWatcherApplicationAddin" />
+ </Extension>
+
+</Addin>
diff --git a/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs
new file mode 100644
index 0000000..6584246
--- /dev/null
+++ b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs
@@ -0,0 +1,237 @@
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+using Tomboy;
+
+namespace Tomboy.NoteDirectoryWatcher
+{
+ class NoteFileChangeRecord
+ {
+ public DateTime last_change;
+ public bool deleted;
+ public bool changed;
+ }
+
+ public class NoteDirectoryWatcherApplicationAddin : ApplicationAddin
+ {
+ private static bool VERBOSE_LOGGING = false;
+
+ private FileSystemWatcher file_system_watcher;
+ private bool initialized;
+
+ private Dictionary<string, NoteFileChangeRecord> file_change_records;
+
+ public override void Initialize ()
+ {
+ string note_path = Tomboy.DefaultNoteManager.NoteDirectoryPath;
+
+ file_change_records = new Dictionary<string, NoteFileChangeRecord>();
+
+ file_system_watcher = new FileSystemWatcher (note_path);
+
+ file_system_watcher.Changed += HandleFileSystemChangeEvent;
+ file_system_watcher.Deleted += HandleFileSystemChangeEvent;
+ file_system_watcher.Created += HandleFileSystemChangeEvent;
+ file_system_watcher.Renamed += HandleFileSystemChangeEvent;
+
+ file_system_watcher.Error += HandleFileSystemErrorEvent;
+
+ // Setting to true will starts the FileSystemWatcher.
+ file_system_watcher.EnableRaisingEvents = true;
+
+ initialized = true;
+ }
+
+ public override void Shutdown ()
+ {
+ file_system_watcher.EnableRaisingEvents = false;
+ initialized = false;
+ }
+
+ public override bool Initialized
+ {
+ get
+ {
+ return initialized;
+ }
+ }
+
+ private void HandleFileSystemErrorEvent (Object sender, ErrorEventArgs arg)
+ {
+ // TODO Rescan the local notes in case some of them have changed.
+ }
+
+ private void HandleFileSystemChangeEvent (Object sender, FileSystemEventArgs arg)
+ {
+ string note_id = GetId(arg.FullPath);
+
+ if (VERBOSE_LOGGING)
+ {
+ Logger.Debug ("{0} has {1} (note_id={2})", arg.FullPath, arg.ChangeType, note_id);
+ }
+
+ // If the note_id is long 36 characters then the file probably wasn't a note.
+ if (note_id.Length != 36)
+ {
+ if (VERBOSE_LOGGING)
+ {
+ Logger.Debug ("Ignoring change to {0}", arg.FullPath);
+ }
+
+ return;
+ }
+
+ // Record that the file has been added/changed/deleted.  Adds/changes trump
+ // deletes.  Record the date.
+ lock (file_change_records)
+ {
+ NoteFileChangeRecord record = null;
+
+ if (file_change_records.ContainsKey (note_id))
+ {
+ record = file_change_records[note_id];
+ }
+ else
+ {
+ record = new NoteFileChangeRecord ();
+ file_change_records[note_id] = record;
+ }
+
+ if (arg.ChangeType == WatcherChangeTypes.Changed)
+ {
+ record.changed = true;
+ record.deleted = false;
+ }
+ else if (arg.ChangeType == WatcherChangeTypes.Created)
+ {
+ record.changed = true;
+ record.deleted = false;
+ }
+ else if (arg.ChangeType == WatcherChangeTypes.Renamed)
+ {
+ record.changed = true;
+ record.deleted = false;
+ }
+ else if (arg.ChangeType == WatcherChangeTypes.Deleted)
+ {
+ if (!record.changed)
+ {
+ record.deleted = true;
+ }
+ }
+ else
+ {
+ String message = "Unexpected WatcherChangeType " + arg.ChangeType;
+ Logger.Error (message);
+ throw new Exception (message);
+ }
+
+ record.last_change = DateTime.Now;
+ }
+
+ GLib.Timeout.Add (5000, new GLib.TimeoutHandler (HandleTimeout));
+ }
+
+ private bool HandleTimeout ()
+ {
+ lock (file_change_records)
+ {
+ List<string> keysToRemove = new List<string> (file_change_records.Count);
+
+ foreach (KeyValuePair<string, NoteFileChangeRecord> pair in file_change_records)
+ {
+ if (VERBOSE_LOGGING)
+ {
+ Logger.Debug ("Handling (timeout) {0}", pair.Key);
+ }
+
+ if (DateTime.Now > pair.Value.last_change.Add (new TimeSpan (4000)) )
+ {
+ if (pair.Value.deleted)
+ {
+ DeleteNote (pair.Key);
+ }
+ else
+ {
+ AddOrUpdateNote (pair.Key);
+ }
+
+ keysToRemove.Add (pair.Key);
+ }
+ }
+
+ foreach (string note_id in keysToRemove)
+ {
+ file_change_records.Remove (note_id);
+ }
+ }
+
+ return false;
+ }
+
+ private static void DeleteNote (string note_id)
+ {
+ Logger.Debug ("Deleting {0} because file deleted.", note_id);
+
+ string note_uri = MakeUri (note_id);
+
+ Note note_to_delete = Tomboy.DefaultNoteManager.FindByUri (note_uri);
+
+ Tomboy.DefaultNoteManager.Notes.Remove (note_to_delete);
+
+ note_to_delete.Delete ();
+ }
+
+ private static void AddOrUpdateNote (string note_id)
+ {
+ string note_path = Tomboy.DefaultNoteManager.NoteDirectoryPath +
+ Path.DirectorySeparatorChar + note_id + ".note";
+
+ string note_uri = MakeUri (note_id);
+
+ Note note = Tomboy.DefaultNoteManager.FindByUri (note_uri);
+
+ if (note == null)
+ {
+ Logger.Debug ("Adding {0} because file changed.", note_id);
+ Note new_note = Note.Load (note_path, Tomboy.DefaultNoteManager);
+ Tomboy.DefaultNoteManager.Notes.Add (new_note);
+ }
+ else
+ {
+ NoteData data = NoteArchiver.Instance.ReadFile (note_path, note_uri);
+
+ // Only record changes if the note actually changes.  This prevents the Addin from
+ // noticing changes from Tomboy itself.
+ if (data.Text == note.XmlContent)
+ {
+ if (VERBOSE_LOGGING)
+ {
+ Logger.Debug ("Ignoring {0} because contents identical", note_id);
+ }
+ }
+ else
+ {
+ Logger.Debug ("Updating {0} because file changed.", note_id);
+ note.XmlContent = data.Text;
+ note.Title = data.Title;
+ }
+ }
+ }
+
+ private static String MakeUri (string note_id)
+ {
+ return "note://tomboy/" + note_id;
+ }
+
+ private static string GetId (string path)
+ {
+ int last_slash = path.LastIndexOf (Path.DirectorySeparatorChar);
+ int first_period = path.IndexOf ('.', last_slash);
+
+ return path.Substring (last_slash + 1, first_period - last_slash - 1);
+ }
+ }
+}
diff --git a/configure.in b/configure.in
index ab9b951..8563e58 100644
--- a/configure.in
+++ b/configure.in
@@ -333,6 +333,7 @@ Tomboy/Addins/SshSyncService/Makefile
 Tomboy/Addins/StickyNoteImport/Makefile
 Tomboy/Addins/Tasque/Makefile
 Tomboy/Addins/WebDavSyncService/Makefile
+Tomboy/Addins/NoteDirectoryWatcher/Makefile
 test/Makefile
 po/Makefile.in
 ])
--
1.6.0.4



_______________________________________________
Tomboy-list mailing list
Tomboy-list@...
http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com

Re: WIP Note Directory Watcher Patch - v2

by Sandy Armstrong :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wed, Apr 29, 2009 at 6:52 PM, Michael Fletcher
<m.fletcher@...> wrote:
> Hello
>
> The patch using git-format-patch is attached.

Pushed.  I modified your commit message a bit.  We try to keep the
first line to be a very short summary of what the commit is for.

I have not yet looked at the problems with LoadForeignNoteXml, but the
code is now in git for anybody to work on.

Awesome work,
Sandy
_______________________________________________
Tomboy-list mailing list
Tomboy-list@...
http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com