[Haiku-commits] r31042 - haiku/trunk/src/apps/installer

stippi at mail.berlios.de stippi at mail.berlios.de
Sun Jun 14 13:07:56 CEST 2009


Author: stippi
Date: 2009-06-14 13:07:52 +0200 (Sun, 14 Jun 2009)
New Revision: 31042
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31042&view=rev

Modified:
   haiku/trunk/src/apps/installer/CopyEngine.cpp
   haiku/trunk/src/apps/installer/CopyEngine.h
   haiku/trunk/src/apps/installer/InstallerWindow.cpp
   haiku/trunk/src/apps/installer/WorkerThread.cpp
Log:
* Fixed problems when installing onto non-empty target volumes. The
  'system' folder will be a clean copy of the source volume. Other
  folders will be merged (as before), but in case a folder is in the
  way of a link or file from the source volume, it will now be purged.
* Clarified the alert for non-empty target volumes, so it is very clear
  what happens. (Maybe there ought to the be option to only copy the system
  folder, though.)
* Fixed a problem with copying attributes in certain cases.
* Fixed the main GUI not resetting state properly after encountering an
  error during the copy process.


Modified: haiku/trunk/src/apps/installer/CopyEngine.cpp
===================================================================
--- haiku/trunk/src/apps/installer/CopyEngine.cpp	2009-06-14 11:03:39 UTC (rev 31041)
+++ haiku/trunk/src/apps/installer/CopyEngine.cpp	2009-06-14 11:07:52 UTC (rev 31042)
@@ -263,8 +263,11 @@
 		return ret;
 
 	ret = create_directory(_destination, 0777);
-	if (ret < B_OK && ret != B_FILE_EXISTS)
+	if (ret < B_OK && ret != B_FILE_EXISTS) {
+		fprintf(stderr, "Could not create '%s': %s\n", _destination,
+			strerror(ret));
 		return ret;
+	}
 
 	BDirectory destination(_destination);
 	ret = destination.InitCheck();
@@ -301,10 +304,24 @@
 			// handle recursive directory copy
 
 			if (copy.Exists()) {
-				// Do not overwrite attributes on folders that exist.
-				// This should work better when the install target already
-				// contains a Haiku installation.
-				copyAttributes = false;
+				ret = B_OK;
+				if (copy.IsDirectory()) {
+					if (_ShouldClobberFolder(name, statInfo, level))
+						ret = _RemoveFolder(copy);
+					else {
+						// Do not overwrite attributes on folders that exist.
+						// This should work better when the install target
+						// already contains a Haiku installation.
+						copyAttributes = false;
+					}
+				} else
+					ret = copy.Remove();
+
+				if (ret != B_OK) {
+					fprintf(stderr, "Failed to make room for folder '%s': "
+						"%s\n", name, strerror(ret));
+					return ret;
+				}
 			}
 
 			BPath srcFolder;
@@ -329,35 +346,52 @@
 				// We are supposed to quit
 				return B_CANCELED;
 			}
-		} else if (S_ISLNK(statInfo.st_mode)) {
-			// copy symbolic links
-			BSymLink srcLink(&entry);
-			if (ret < B_OK)
-				return ret;
-
-			char linkPath[B_PATH_NAME_LENGTH];
-			ssize_t read = srcLink.ReadLink(linkPath, B_PATH_NAME_LENGTH - 1);
-			if (read < 0)
-				return (status_t)read;
-
-			// just in case it already exists...
-			copy.Remove();
-
-			BSymLink dstLink;
-			ret = destination.CreateSymLink(name, linkPath, &dstLink);
-			if (ret < B_OK)
-				return ret;
 		} else {
-			// copy file data
-			// NOTE: Do not pass the locker, we simply keep holding the lock!
-			ret = CopyFile(entry, copy);
-			if (ret < B_OK)
-				return ret;
+			if (copy.Exists()) {
+				if (copy.IsDirectory())
+					ret = _RemoveFolder(copy);
+				else
+					ret = copy.Remove();
+				if (ret != B_OK) {
+					fprintf(stderr, "Failed to make room for entry '%s': "
+						"%s\n", name, strerror(ret));
+					return ret;
+				}
+			}
+			if (S_ISLNK(statInfo.st_mode)) {
+				// copy symbolic links
+				BSymLink srcLink(&entry);
+				if (ret < B_OK)
+					return ret;
+	
+				char linkPath[B_PATH_NAME_LENGTH];
+				ssize_t read = srcLink.ReadLink(linkPath, B_PATH_NAME_LENGTH - 1);
+				if (read < 0)
+					return (status_t)read;
+	
+				// just in case it already exists...
+				copy.Remove();
+	
+				BSymLink dstLink;
+				ret = destination.CreateSymLink(name, linkPath, &dstLink);
+				if (ret < B_OK)
+					return ret;
+			} else {
+				// copy file data
+				// NOTE: Do not pass the locker, we simply keep holding the lock!
+				ret = CopyFile(entry, copy);
+				if (ret < B_OK)
+					return ret;
+			}
 		}
 
 		if (!copyAttributes)
 			continue;
 
+		ret = copy.SetTo(&destination, name);
+		if (ret != B_OK)
+			return ret;
+
 		// copy attributes
 		BNode sourceNode(&entry);
 		BNode targetNode(&copy);
@@ -396,6 +430,30 @@
 }
 
 
+status_t
+CopyEngine::_RemoveFolder(BEntry& entry)
+{
+	BDirectory directory(&entry);
+	status_t ret = directory.InitCheck();
+	if (ret != B_OK)
+		return ret;
+
+	BEntry subEntry;
+	while (directory.GetNextEntry(&subEntry) == B_OK) {
+		if (subEntry.IsDirectory()) {
+			ret = _RemoveFolder(subEntry);
+			if (ret != B_OK)
+				return ret;
+		} else {
+			ret = subEntry.Remove();
+			if (ret != B_OK)
+				return ret;
+		}
+	}
+	return entry.Remove();
+}
+
+
 void
 CopyEngine::_UpdateProgress()
 {
@@ -430,6 +488,24 @@
 }
 
 
+bool
+CopyEngine::_ShouldClobberFolder(const char* name, const struct stat& statInfo,
+	int32 level) const
+{
+	if (level == 1 && S_ISDIR(statInfo.st_mode)) {
+		if (strcmp("system", name) == 0) {
+			printf("clobbering '%s'.\n", name);
+			return true;
+		}
+//		if (strcmp("develop", name) == 0) {
+//			printf("clobbering '%s'.\n", name);
+//			return true;
+//		}
+	}
+	return false;
+}
+
+
 int32
 CopyEngine::_WriteThreadEntry(void* cookie)
 {

Modified: haiku/trunk/src/apps/installer/CopyEngine.h
===================================================================
--- haiku/trunk/src/apps/installer/CopyEngine.h	2009-06-14 11:03:39 UTC (rev 31041)
+++ haiku/trunk/src/apps/installer/CopyEngine.h	2009-06-14 11:07:52 UTC (rev 31042)
@@ -48,6 +48,12 @@
 									const struct stat& statInfo,
 									int32 level) const;
 
+			bool				_ShouldClobberFolder(const char* name,
+									const struct stat& statInfo,
+									int32 level) const;
+
+			status_t			_RemoveFolder(BEntry& entry);
+
 			void				_UpdateProgress();
 
 	static	int32				_WriteThreadEntry(void* cookie);

Modified: haiku/trunk/src/apps/installer/InstallerWindow.cpp
===================================================================
--- haiku/trunk/src/apps/installer/InstallerWindow.cpp	2009-06-14 11:03:39 UTC (rev 31041)
+++ haiku/trunk/src/apps/installer/InstallerWindow.cpp	2009-06-14 11:07:52 UTC (rev 31042)
@@ -373,15 +373,12 @@
 				(new BAlert("error", errorMessage, "Ok"))->Go();
 			}
 
-			fInstallStatus = kReadyForInstall;
-			fBeginButton->SetEnabled(true);
 			_DisableInterface(false);
 
 			fProgressLayoutItem->SetVisible(false);
 			fPkgSwitchLayoutItem->SetVisible(true);
 			_ShowOptionalPackages();
-
-			fBeginButton->SetLabel("Begin");
+			_UpdateControls();
 			break;
 		}
 		case START_SCAN:

Modified: haiku/trunk/src/apps/installer/WorkerThread.cpp
===================================================================
--- haiku/trunk/src/apps/installer/WorkerThread.cpp	2009-06-14 11:03:39 UTC (rev 31041)
+++ haiku/trunk/src/apps/installer/WorkerThread.cpp	2009-06-14 11:07:52 UTC (rev 31042)
@@ -234,14 +234,14 @@
 
 
 void
-WorkerThread::_PerformInstall(BMenu *srcMenu, BMenu *targetMenu)
+WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu)
 {
 	CALLED();
 
 	BPath targetDirectory, srcDirectory;
 	BDirectory targetDir;
 	BDiskDevice device;
-	BPartition *partition;
+	BPartition* partition;
 	BVolume targetVolume;
 	status_t err = B_OK;
 	int32 entries = 0;
@@ -250,8 +250,8 @@
 	BMessenger messenger(fWindow);
 	CopyEngine engine(messenger, new BMessage(MSG_STATUS_MESSAGE));
 
-	PartitionMenuItem *targetItem = (PartitionMenuItem *)targetMenu->FindMarked();
-	PartitionMenuItem *srcItem = (PartitionMenuItem *)srcMenu->FindMarked();
+	PartitionMenuItem* targetItem = (PartitionMenuItem*)targetMenu->FindMarked();
+	PartitionMenuItem* srcItem = (PartitionMenuItem*)srcMenu->FindMarked();
 	if (!srcItem || !targetItem) {
 		ERR("bad menu items\n");
 		goto error;
@@ -381,7 +381,12 @@
 	}
 	if (entries != 0
 		&& ((new BAlert("", "The target volume is not empty. Are you sure you "
-			"want to install anyway?", "Install Anyway", "Cancel", 0,
+			"want to install anyway?\n\nNote: The 'system' folder will be a "
+			"clean copy from the source volume, all other folders will be "
+			"merged, whereas files and links that exist on both the source "
+			"and target volume will be overwritten with the source volume "
+			"version.",
+			"Install Anyway", "Cancel", 0,
 			B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go() != 0)) {
 		err = B_CANCELED;
 		goto error;




More information about the Haiku-commits mailing list