Update script for 329841 finished. Comments?



Hi Gabriel,

Just finished my small patch for the Updater.cs to add a leading 0 to
the Month and Day directory.

And as you requested.
try
	1) Create Directory
	2) hard link photo
	3) update database
	4) move thumbnails
catch
	revert thumbnails
	remove new hard link
	remove new directory

remove old hard link
remove old directories


The patch for FileImporterBacken.cs is just 2 lines.
The patch for Updater.cs is 333 lines!!!!
Guess I need a refresher course in C#, or rather a beginner course

Would appreciate some comments if anyone have any.

Do bear in mind that please test this on a test system, not on your live
data. Also, just after 4 (in the above pseudo code) you can uncomment a
raise exception so no changes will be made...

/Bengt
Index: FileImportBackend.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/FileImportBackend.cs,v
retrieving revision 1.28
diff -u -r1.28 FileImportBackend.cs
--- FileImportBackend.cs	3 Dec 2005 18:43:55 -0000	1.28
+++ FileImportBackend.cs	15 Feb 2006 13:37:17 -0000
@@ -115,8 +115,8 @@
 						 FSpot.Global.PhotoDirectory,
 						 System.IO.Path.DirectorySeparatorChar,
 						 time.Year,
-						 time.Month,
-						 time.Day);
+						 time.ToString("MM"),	// To get months with leading 0 as in 01 - 12 
+						 time.ToString("dd"));	// To get days with leading 0 as in 01 - 31 
 		
 		if (!System.IO.Directory.Exists (dest_dir))
 			System.IO.Directory.CreateDirectory (dest_dir);
Index: Updater.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/Updater.cs,v
retrieving revision 1.4
diff -u -r1.4 Updater.cs
--- Updater.cs	13 Feb 2006 07:27:36 -0000	1.4
+++ Updater.cs	15 Feb 2006 13:35:50 -0000
@@ -62,6 +62,341 @@
 				System.Console.WriteLine ("Other tag restored.  Sorry about that!");
 			});
 			
+			// Modify directory structure so Day and Months have a leading 0's if needed. 01 instead of 1
+			AddUpdate (delegate (SqliteConnection connection) {
+				string slask, orig_directory, new_directory, orig_name, orig_name_w_extension, old_photo, new_photo, photo_extension;
+				int i;
+				// We keep 4 ArrayList to keep track of Directory, photo and id. They are syncronised, so 
+				// there will be duplicates in Directory and ID if the photo has versions.
+				ArrayList new_directories = new ArrayList(); // A list of all directories to be created
+				ArrayList old_photo_names = new ArrayList(); // A list of all photos to be moved
+				ArrayList new_photo_names = new ArrayList(); // A list of the new photo name
+				ArrayList photo_ids = new ArrayList(); // A list of the internal photo id of the photos to be moved
+				
+				orig_name = "";
+				photo_extension = "";
+
+				Console.WriteLine ("About to update the directory structure (adding leading 0's).");
+				
+				// Get minimum Photo ID
+				slask = SelectSingleString (
+					String.Format ("SELECT MIN (id) from photos"));
+
+				if (slask == null)
+					return;
+
+				int min_photo_id = System.Int32.Parse (slask);
+				
+				// Get maximum Photo ID
+				slask = SelectSingleString (
+					String.Format ("SELECT MAX (id) from photos"));
+
+				int max_photo_id = System.Int32.Parse (slask);
+
+//				Console.WriteLine ("Min photo id = {0}, Max photo id = {1}", min_photo_id, max_photo_id);
+				
+				// Iterate through all photos to check if directory structure needs to be modified
+				for (int id = min_photo_id;  id <= max_photo_id; id++) {
+
+					//Console.WriteLine ("Checking photo {0}", id);
+					
+					// Check if starting with FSpot.Global.PhotoDirectory (~/Photos)
+					orig_directory = SelectSingleString (
+						String.Format ("SELECT directory_path from photos where id = {0}", id));
+	
+					// Set new_directory to same as old_directory by default
+					new_directory = orig_directory;
+
+					if (orig_directory.StartsWith (FSpot.Global.PhotoDirectory)) {
+						// Console.WriteLine ("{0} ({1}) is under ~/Photos.", id, orig_directory);
+
+						// Check if Day and/or Month is less than 10
+						slask = SelectSingleString (
+							String.Format ("SELECT time from photos where id = {0}", id));
+						
+						// Convert the sqlite string to a long, and then to unix time.
+						DateTime photo_time = DbUtils.DateTimeFromUnixTime ( System.Int64.Parse (slask) );
+						
+						if ((photo_time.Month < 10) || (photo_time.Day < 10)) {
+							// Get the name of the photo
+							orig_name_w_extension = SelectSingleString (
+								String.Format ("SELECT name from photos where id = {0}", id));
+							photo_extension = System.IO.Path.GetExtension (orig_name_w_extension);
+							orig_name = System.IO.Path.GetFileNameWithoutExtension (orig_name_w_extension);
+							
+							// Console.WriteLine ("Need to modify photo id {0} - directory {1} - Month {2} - Day {3}, Name {4}", id, orig_directory, photo_time.Month, photo_time.Day, orig_name );
+
+							// Ok, lets create the directory path
+							new_directory = String.Format ("{0}{1}{2}{1}{3}{1}{4}",
+								FSpot.Global.PhotoDirectory,
+								System.IO.Path.DirectorySeparatorChar,
+								photo_time.Year,
+								photo_time.ToString("MM"),	// To get months with leading 0 as in 01 - 12 
+								photo_time.ToString("dd"));	// To get days with leading 0 as in 01 - 31 								
+
+							// Console.WriteLine ("New directory path {0} - {1}", new_directory, new_directory.Replace("'", "''"));
+
+						} // if Month or day < 10
+
+						// Only proceed if month/day directory name is missing leading "0"
+						if (orig_directory != new_directory) {
+
+							// Lets create the old and the new photo names
+							old_photo = String.Format ("{0}{1}{2}{3}", 
+								orig_directory, System.IO.Path.DirectorySeparatorChar, orig_name, photo_extension);
+							new_photo = String.Format ("{0}{1}{2}{3}", 
+								new_directory, System.IO.Path.DirectorySeparatorChar, orig_name, photo_extension);
+							
+							// Ensure that the old photo name exists, and that the new photo name do not exist
+							if (!System.IO.File.Exists (old_photo))
+								throw new Exception (String.Format("Photo with name {0} do not exists", old_photo));
+							if (System.IO.File.Exists (new_photo))
+								throw new Exception (String.Format("Photo with name {0} already exists", new_photo));
+							
+//							Console.WriteLine ("Rename '{0}' to '{1}'", old_photo, new_photo);
+
+							// Store all names for processing last
+							old_photo_names.Add (old_photo);
+							new_photo_names.Add (new_photo);
+							new_directories.Add (new_directory);
+							photo_ids.Add (id);
+							
+							// We have done the main version, now we need to move all versions as well
+							int min_version_id = 9999;
+							int max_version_id = 0;
+							
+							// Get minimum Version ID
+							slask = SelectSingleString (
+								String.Format ("SELECT MIN (version_id) from photo_versions where photo_id = {0}", id));
+
+							if (slask == null)
+								min_version_id = 9999;	// no versions exists, set min to be more than max.
+							else {
+								min_version_id = System.Int32.Parse (slask);
+				
+								// Get maximum Photo ID
+								slask = SelectSingleString (
+									String.Format ("SELECT MAX (version_id) from photo_versions where photo_id = {0}", id));
+
+								if (slask == null)
+									max_version_id = 0; // no versions exists, set max to be less than min.
+								else
+									max_version_id = System.Int32.Parse (slask);
+							} // if min(verson_id) exists
+							
+							// Console.WriteLine ("Min version id = {0}, Max version id = {1}", min_version_id, max_version_id);
+							for (int vid = min_version_id;  vid <= max_version_id; vid++) {
+								string version_name = SelectSingleString (
+									String.Format ("SELECT name from photo_versions where photo_id = {0} and version_id = {1}", id, vid));
+								
+								// Lets create the old and the new photo names
+								old_photo = String.Format ("{0}{1}{2} ({3}){4}", 
+									orig_directory, System.IO.Path.DirectorySeparatorChar, orig_name, version_name, photo_extension);
+								new_photo = String.Format ("{0}{1}{2} ({3}){4}", 
+									new_directory, System.IO.Path.DirectorySeparatorChar, orig_name, version_name, photo_extension);
+
+								// Ensure that the old photo name exists, and that the new photo name do not exist
+								if (!System.IO.File.Exists (old_photo))
+									throw new Exception (String.Format("Photo with name {0} do not exists", old_photo));
+								if (System.IO.File.Exists (new_photo))
+									throw new Exception (String.Format("Photo with name {0} already exists", new_photo));
+
+								// Store all names for processing last
+								old_photo_names.Add (old_photo);
+								new_photo_names.Add (new_photo);
+								new_directories.Add (new_directory);	// just so all array lists are the same
+								photo_ids.Add (id);			// just so all array lists are the same
+
+//								Console.WriteLine ("Rename {0} to {1}", old_photo, new_photo);
+
+								// Console.WriteLine ("Photo id {0}, Directory {1}, Version {2}, Name {3}", id, orig_directory, vid, name);
+							} // for each version
+							
+							
+						} // if month and day part missing leading "0"
+//						else  // Month and Day > 10, or have leading "0"
+//							Console.WriteLine ("----> {0} ----< directory {1} - Month {2} - Day {3} is OK.", id, orig_directory, photo_time.Day, photo_time.Month);
+						
+					} // under ~/Photos
+//					else  // Not under ~/Photos
+//						Console.WriteLine ("----> {0} ----< Directory ({1}) is outside ~/Photos ignore it.", id, orig_directory);
+
+				} // end for
+			
+				// Lets ensure that our ArrayLists have the same amount of entries.
+				if ((new_directories.Count == old_photo_names.Count) &&
+					(old_photo_names.Count == new_photo_names.Count) &&
+					(new_photo_names.Count == photo_ids.Count)) {
+//					Console.WriteLine (String.Format("ArrayList have same number of entries: dirs {0}, old {1}, new {2}, id {3}", new_directories.Count, old_photo_names.Count, new_photo_names.Count, photo_ids.Count));
+				} else {
+					throw new Exception (String.Format(
+					"ArrayList have different number of entries: dirs {0}, old {1}, new {2}, id {3}",
+					new_directories.Count, old_photo_names.Count, new_photo_names.Count, photo_ids.Count));
+				}
+
+				// Start processing, if we have some photo to move
+				if (new_directories.Count > 0) {
+					
+					// Ok we now have all the data. Lets process it.
+					// We do all the work inside an internal try/catch so we can roll back everyting if needed.
+
+					try {
+						Console.WriteLine ("Creating new directories");
+	
+						// Ensure that the new directory exists 
+						for (i = 0; i < new_photo_names.Count; i++) {
+							if ( !System.IO.Directory.Exists(new_directories[i].ToString()) ) {
+								// FIXME Directory Permissions?
+								System.IO.Directory.CreateDirectory(new_directories[i].ToString());
+//								Console.WriteLine ("Created {0} - {1}", i, new_directories[i].ToString());
+							}
+						} // for 
+
+						Console.WriteLine ("Creating hard links for the new photos");
+
+						// Create a hard link instead of copy. Save spaces and goes fast
+						// FIXME Does this work for BSD????
+						for (i = 0; i < new_photo_names.Count; i++) {
+							Mono.Unix.Native.Syscall.link (
+								old_photo_names[i].ToString(), new_photo_names[i].ToString());
+//							Console.WriteLine ("Linked {0} - {1} to {2}", i, old_photo_names[i].ToString(), new_photo_names[i].ToString());
+						} // for 
+
+						Console.WriteLine ("Updating the directory path in the database");
+
+						// Modify main photo
+						for (i = 0; i < new_directories.Count; i++) {
+							ExecuteNonQuery ( 
+								String.Format ("UPDATE photos set directory_path = '{0}' WHERE id = {1}", 
+									new_directories[i].ToString().Replace ("'", "''"), photo_ids[i]));
+//							Console.WriteLine ("Updated database {0} - id {1} {2}", i, photo_ids[i], new_directories[i].ToString());
+						} // for 
+
+						Console.WriteLine ("Updating the thumbnails");
+
+						// Move the thumbnail
+						for (i = 0; i < new_photo_names.Count; i++) {
+							if (System.IO.File.Exists (Gnome.Thumbnail.PathForUri (old_photo_names[i].ToString(), Gnome.ThumbnailSize.Large))) {
+								System.IO.File.Move (
+									Gnome.Thumbnail.PathForUri (old_photo_names[i].ToString(), Gnome.ThumbnailSize.Large),
+									Gnome.Thumbnail.PathForUri (new_photo_names[i].ToString(), Gnome.ThumbnailSize.Large));
+//								Console.WriteLine ("Updated ThumbNails {0} - {1}", i, new_photo_names[i].ToString());
+							} // if old thumbnail exists
+						} // for 
+						
+// Lets quit since we are only testing...
+// throw new Exception ("Testing only, so revert changes.");
+					
+					} catch (System.Exception e) {
+						Console.WriteLine ("Some error occurred, so we are rolling back");
+//Console.WriteLine ("Press enter.....");
+//string slask2 = Console.ReadLine();
+						
+						// Lets do everything in reverse order
+						
+						Console.WriteLine ("Rolling back the thumbnails");
+
+						// Move the thumbnail (only if the new one exists)
+						for (i = 0; i < new_photo_names.Count; i++) {
+							if (System.IO.File.Exists(Gnome.Thumbnail.PathForUri (new_photo_names[i].ToString(), Gnome.ThumbnailSize.Large))) {
+								System.IO.File.Move (
+									Gnome.Thumbnail.PathForUri (new_photo_names[i].ToString(), Gnome.ThumbnailSize.Large),
+									Gnome.Thumbnail.PathForUri (old_photo_names[i].ToString(), Gnome.ThumbnailSize.Large));
+//								Console.WriteLine ("Rolledback ThumbNails {0} - {1}", i, old_photo_names[i].ToString());
+							}
+						} // for 
+
+						// Database rolling back will be handle by transaction rollback.
+	
+						Console.WriteLine ("Removing just created new photos");
+						// Delete the new photo
+						for (i = 0; i < new_photo_names.Count; i++) {
+							if (System.IO.File.Exists(new_photo_names[i].ToString()))
+								try {
+									System.IO.File.Delete ( new_photo_names[i].ToString());
+//									Console.WriteLine ("Remove Linked {0} - {1}", i, new_photo_names[i].ToString());
+								} catch  { // if some error (not empty?), lets continue
+								}
+						} // for 
+
+						Console.WriteLine ("Delete the new directory");
+						for (i = 0; i < new_photo_names.Count; i++) {
+							if (System.IO.Directory.Exists(new_directories[i].ToString()))
+								try {
+									System.IO.Directory.Delete (new_directories[i].ToString());
+//									Console.WriteLine ("Deleted directory {0} - {1}", i, new_directories[i].ToString());
+								} catch  { // if some error (not empty?), lets continue
+								}
+						} // for 
+
+						// Rethrow the exception so we rollback the database.
+						throw e;
+					
+					} // catch
+			
+					// Ok, we got to this point, which means all is ok. Only one thing left, to clean up.
+					// Delete the old photos
+					Console.WriteLine ("Removing the old photos");
+					for (i = 0; i < old_photo_names.Count; i++) {
+						try {
+							System.IO.File.Delete ( old_photo_names[i].ToString());
+//							Console.WriteLine (String.Format("Removed old file {0}", old_photo_names[i].ToString()));
+						} catch  {
+							Console.WriteLine (String.Format("Could not delete {0}, continuing", old_photo_names[i].ToString()));
+						}
+					} // for 
+				
+					// Delete the old directories (Month and Day)
+					Console.WriteLine ("Removing the old Month / Day directory");
+
+					ArrayList dir_list = new ArrayList();
+					string dir_str;
+
+					for (i = 0; i < old_photo_names.Count; i++) 
+						dir_list.Add (System.IO.Path.GetDirectoryName (old_photo_names[i].ToString()));
+					dir_list.Sort();
+					int last_i = -1;
+					for (i = 0; i < dir_list.Count; i++) 
+						if ((last_i < 0) || (dir_list[i].ToString() != dir_list[last_i].ToString()))  {
+							dir_str = dir_list[i].ToString();
+							if (System.IO.Directory.Exists(dir_str)) 
+								try {
+									System.IO.Directory.Delete(dir_str);
+//									Console.WriteLine (String.Format("Removed old directory {0}", dir_str));
+								} catch  {
+									Console.WriteLine (String.Format("Could not delete {0} (not empty?), continuing", dir_str));
+								}
+							last_i = i;
+						}
+					// Lets remove the months
+					// First remove the day part of the directory string
+					for (i = 0; i < dir_list.Count; i++) {
+						dir_str = dir_list[i].ToString();
+						while (!dir_str.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString())) {
+							dir_str = dir_str.Remove(dir_str.Length-1, 1); // remove last char
+						} // while
+						dir_list[i] = dir_str.Remove(dir_str.Length-1, 1); // remove last "/"
+
+					} // for
+					dir_list.Sort();
+					last_i = -1;
+					for (i = 0; i < dir_list.Count; i++) 
+						if ((last_i < 0) || (dir_list[i].ToString() != dir_list[last_i].ToString()))  {
+							dir_str = dir_list[i].ToString();
+							bool single_digit_month = (dir_str.Substring (dir_str.Length - 2, 1) == System.IO.Path.DirectorySeparatorChar.ToString());
+							if (single_digit_month && System.IO.Directory.Exists(dir_str)) 
+								try {
+									System.IO.Directory.Delete(dir_str);
+//									Console.WriteLine (String.Format("Removed old directory {0}", dir_str));
+								} catch  {
+									Console.WriteLine (String.Format("Could not delete {0} (not empty?), continuing", dir_str));
+								}
+							last_i = i;
+						} // if
+				} // If new_directories > 0
+				
+			}); // AddUpdate
+
 			// Update from version 2 to 3
 			//AddUpdate (delegate (SqliteConnection connection) {
 			//	do update here


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