[tomboy] [sync] Don't try to handle conflicts when the notes are actually identical



commit ad659facc32405477cba1c9998d26f125b1a0408
Author: Sandy Armstrong <sanfordarmstrong gmail com>
Date:   Mon Feb 8 11:36:55 2010 -0800

    [sync] Don't try to handle conflicts when the notes are actually identical
    
    This makes sync a lot nicer when you already have your notes copied
    to a second machine, or when for whatever reason Tomboy thinks you
    changed your note but nothing important has changed.

 Tomboy/Note.cs                        |   40 +++++++++++++++++-------
 Tomboy/Synchronization/SyncManager.cs |   55 +++++++++++++++++++++++++++++++-
 2 files changed, 81 insertions(+), 14 deletions(-)
---
diff --git a/Tomboy/Note.cs b/Tomboy/Note.cs
index 9539db7..d4296d8 100644
--- a/Tomboy/Note.cs
+++ b/Tomboy/Note.cs
@@ -1258,15 +1258,40 @@ namespace Tomboy
 
 		public virtual NoteData ReadFile (string read_file, string uri)
 		{
-			NoteData note = new NoteData (uri);
-			string version = "";
-
 			StreamReader reader = new StreamReader (read_file,
 			                                        System.Text.Encoding.UTF8);
 			XmlTextReader xml = new XmlTextReader (reader);
 			xml.Namespaces = false;
+
+			string version;
+			NoteData data = Read (xml, uri, out version);
+
+			if (version != NoteArchiver.CURRENT_VERSION) {
+				// Note has old format, so rewrite it.  No need
+				// to reread, since we are not adding anything.
+				Logger.Log ("Updating note XML to newest format...");
+				NoteArchiver.Write (read_file, data);
+			}
+
+			reader.Close ();
+			xml.Close ();
+
+			return data;
+		}
+
+		public virtual NoteData Read (XmlTextReader xml, string uri)
+		{
+			string version; // discarded
+			NoteData data = Read (xml, uri, out version);
+			return data;
+		}
+
+		private NoteData Read (XmlTextReader xml, string uri, out string version)
+		{
+			NoteData note = new NoteData (uri);
 			DateTime date;
 			int num;
+			version = String.Empty;
 
 			while (xml.Read ()) {
 				switch (xml.NodeType) {
@@ -1338,15 +1363,6 @@ namespace Tomboy
 					break;
 				}
 			}
-			reader.Close ();
-			xml.Close ();
-
-			if (version != NoteArchiver.CURRENT_VERSION) {
-				// Note has old format, so rewrite it.  No need
-				// to reread, since we are not adding anything.
-				Logger.Log ("Updating note XML to newest format...");
-				NoteArchiver.Write (read_file, note);
-			}
 
 			return note;
 		}
diff --git a/Tomboy/Synchronization/SyncManager.cs b/Tomboy/Synchronization/SyncManager.cs
index 758381c..0b1551a 100644
--- a/Tomboy/Synchronization/SyncManager.cs
+++ b/Tomboy/Synchronization/SyncManager.cs
@@ -321,7 +321,8 @@ namespace Tomboy.Sync
 				{
 					if (FindNoteByUUID (noteUpdate.UUID) == null) {
 						Note existingNote = NoteMgr.Find (noteUpdate.Title);
-						if (existingNote != null) {
+						if (existingNote != null && !noteUpdate.BasicallyEqualTo (existingNote)) {
+//							Logger.Debug ("Sync: Early conflict detection for '{0}'", noteUpdate.Title);
 							if (NoteConflictDetected != null) {
 								NoteConflictDetected (NoteMgr, existingNote, noteUpdate, noteUpdateTitles);
 
@@ -354,10 +355,12 @@ namespace Tomboy.Sync
 							DeleteNoteInMainThread (existingNote);
 						}
 						CreateNoteInMainThread (noteUpdate);
-					} else if (existingNote.MetadataChangeDate.CompareTo (client.LastSyncDate) <= 0) {
+					} else if (existingNote.MetadataChangeDate.CompareTo (client.LastSyncDate) <= 0 ||
+					           noteUpdate.BasicallyEqualTo (existingNote)) {
 						// Existing note hasn't been modified since last sync; simply update it from server
 						UpdateNoteInMainThread (existingNote, noteUpdate);
 					} else {
+//						Logger.Debug ("Sync: Late conflict detection for '{0}'", noteUpdate.Title);
 						Logger.Debug (string.Format (
 						                      "SyncManager: Content conflict in note update for note '{0}'",
 						                      noteUpdate.Title));
@@ -727,6 +730,54 @@ namespace Tomboy.Sync
 				}
 			}
 		}
+
+		public bool BasicallyEqualTo (Note existingNote)
+		{
+//			Logger.Debug ("Comparing NoteData for '{0}'", existingNote.Title);
+			// NOTE: This would be so much easier if NoteUpdate
+			//       was not just a container for a big XML string
+			NoteData updateData = null;
+			using (var xml = new XmlTextReader (new StringReader (XmlContent))) {
+				xml.Namespaces = false;
+				updateData = NoteArchiver.Instance.Read (xml, UUID);
+			}
+
+			// NOTE: Mostly a hack to ignore missing version attributes
+			string existingInnerContent = GetInnerContent (existingNote.Data.Text);
+			string updateInnerContent = GetInnerContent (updateData.Text);
+
+//			Logger.Debug ("existingNote.Data.Title: {0}", existingNote.Data.Title);
+//			Logger.Debug ("updateData.Title: {0}", updateData.Title);
+//
+//			Logger.Debug ("existingInnerContent: {0}", existingInnerContent);
+//			Logger.Debug ("updateInnerContent: {0}", updateInnerContent);
+
+			return existingInnerContent == updateInnerContent &&
+				existingNote.Data.Title == updateData.Title &&
+				CompareTags (existingNote.Data.Tags, updateData.Tags);
+				// TODO: Compare open-on-startup, pinned
+		}
+
+		private string GetInnerContent (string fullContentElement)
+		{
+			const string noteContentRegex =
+				@"^<note-content(\s+version=""(?<contentVersion>[^""]*)"")?\s*((/>)|(>(?<innerContent>.*)</note-content>))$";
+			Match m = Regex.Match (fullContentElement, noteContentRegex, RegexOptions.Singleline);
+			Group contentGroup = m.Groups ["innerContent"];
+			if (!contentGroup.Success)
+				return null;
+			return contentGroup.Value;
+		}
+
+		private bool CompareTags (Dictionary<string, Tag> set1, Dictionary<string, Tag> set2)
+		{
+			if (set1.Count != set2.Count)
+				return false;
+			foreach (string key in set1.Keys)
+				if (!set2.ContainsKey (key))
+					return false;
+			return true;
+		}
 	}
 
 	public class SyncLockInfo



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]