[darwinbuild-changes] [906] trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Nov 3 15:56:00 PDT 2010


Revision: 906
          http://trac.macosforge.org/projects/darwinbuild/changeset/906
Author:   wsiegrist at apple.com
Date:     2010-11-03 15:55:58 -0700 (Wed, 03 Nov 2010)
Log Message:
-----------
Merged PR-8604911

Modified Paths:
--------------
    trunk/darwinup/Depot.cpp
    trunk/darwinup/File.cpp
    trunk/darwinup/File.h
    trunk/testing/darwinup/dest.tar.gz
    trunk/testing/darwinup/rep_file_dir.tar.gz
    trunk/testing/darwinup/rep_flink_dir.tar.gz
    trunk/testing/darwinup/rep_link_dir.tar.gz
    trunk/testing/darwinup/run-tests.sh

Property Changed:
----------------
    trunk/


Property changes on: trunk
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/PR-4841388:399-419
/branches/PR-6358021:442-443
/branches/PR-6392966:423-427
/branches/PR-6398060:433-434
/branches/PR-6493844:460-461
/branches/PR-6497694:466-468,471
/branches/PR-6634286:632-650
/branches/PR-6688645:479-490
/branches/PR-6722857:495-499
/branches/PR-6729491:655-664
/branches/PR-6973110:804-813
/branches/PR-7250612:635-650
/branches/PR-7341154:682-694
/branches/PR-7431723:660-664
/branches/PR-7461534:650-664
/branches/PR-7482850:670-671
/branches/PR-7489777:676-731
/branches/PR-7529688:692-694
/branches/PR-7593824:739-772
/branches/PR-7598640:703-731
/branches/PR-7748469:777-785
/branches/PR-7765119:790-791
/branches/PR-7798586:796-799
/branches/PR-7872907:830-840
/branches/PR-7935095:819-821
/branches/PR-8116613:849
/branches/PR-8279204:854-862
/branches/PR-8416637:870-880
/branches/PR-8486662:885-889
/branches/PR-8488185:894-898
   + /branches/PR-4841388:399-419
/branches/PR-6358021:442-443
/branches/PR-6392966:423-427
/branches/PR-6398060:433-434
/branches/PR-6493844:460-461
/branches/PR-6497694:466-468,471
/branches/PR-6634286:632-650
/branches/PR-6688645:479-490
/branches/PR-6722857:495-499
/branches/PR-6729491:655-664
/branches/PR-6973110:804-813
/branches/PR-7250612:635-650
/branches/PR-7341154:682-694
/branches/PR-7431723:660-664
/branches/PR-7461534:650-664
/branches/PR-7482850:670-671
/branches/PR-7489777:676-731
/branches/PR-7529688:692-694
/branches/PR-7593824:739-772
/branches/PR-7598640:703-731
/branches/PR-7748469:777-785
/branches/PR-7765119:790-791
/branches/PR-7798586:796-799
/branches/PR-7872907:830-840
/branches/PR-7935095:819-821
/branches/PR-8116613:849
/branches/PR-8279204:854-862
/branches/PR-8416637:870-880
/branches/PR-8486662:885-889
/branches/PR-8488185:894-898
/branches/PR-8604911:903-905

Modified: trunk/darwinup/Depot.cpp
===================================================================
--- trunk/darwinup/Depot.cpp	2010-11-01 20:40:42 UTC (rev 905)
+++ trunk/darwinup/Depot.cpp	2010-11-03 22:55:58 UTC (rev 906)
@@ -458,6 +458,32 @@
 					actual->info_set(FILE_INFO_ROLLBACK_DATA);
 					file->info_set(FILE_INFO_INSTALL_DATA);
 				}
+				// if actual is a dir and file is not, recurse to save its children
+				if (S_ISDIR(actual->mode()) && !S_ISDIR(file->mode())) {
+					IF_DEBUG("[analyze]    directory being replaced by file, save children\n");
+					const char* sub_argv[] = { actual->path(), NULL };
+					FTS* subfts = fts_open((char**)sub_argv, 
+										   FTS_PHYSICAL | FTS_COMFOLLOW | FTS_XDEV, 
+										   fts_compare);
+					FTSENT* subent = fts_read(subfts); // throw away actual
+					while ((subent = fts_read(subfts)) != NULL) {
+						IF_DEBUG("saving child: %s\n", subent->fts_path);
+						// skip post-order visits
+						if (subent->fts_info == FTS_DP) {
+							continue;
+						}
+						File* subact = FileFactory(subent->fts_path);
+						subact->info_set(FILE_INFO_BASE_SYSTEM);
+						if (subent->fts_info != FTS_D) {
+							IF_DEBUG("saving file data\n");
+							subact->info_set(FILE_INFO_ROLLBACK_DATA);
+						}
+						if (!dryrun) {
+							res = this->insert(rollback, subact);
+						}
+						*rollback_files += 1;
+					}
+				}
 				preceding = actual;
 			}
 		
@@ -527,41 +553,7 @@
 				IF_DEBUG("[analyze]    external changes but file same as actual\n");
 				state = 'E';
 			}
-			
-			// XXX: should this be done in backup_file?
-			// If we're going to need to squirrel away data, create
-			// the directory hierarchy now.
-			if (INFO_TEST(actual->info(), FILE_INFO_ROLLBACK_DATA)) {
-				char path[PATH_MAX];
-				char* backup_dirpath;
-
-				// we need the path minus our destination prefix for moving to the archive
-				strlcpy(path, actual->path() + strlen(m_prefix) - 1, sizeof(path));
-
-				const char* dir = dirname(path);
-				assert(dir != NULL);
-				
-				char *uuidpath;
-				char uuidstr[37];
-				uuid_unparse_upper(rollback->uuid(), uuidstr);
-				
-				asprintf(&uuidpath, "%s/%s", m_archives_path, uuidstr);
-				assert(uuidpath != NULL);
-				join_path(&backup_dirpath, uuidpath, dir);
-				assert(backup_dirpath != NULL);
-				
-				if (!dryrun) res = mkdir_p(backup_dirpath);
-				if (res != 0 && errno != EEXIST) {
-					fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
-							__FILE__, __LINE__, backup_dirpath, strerror(errno), errno);
-				} else {
-					res = 0;
-				}
-				free(backup_dirpath);
-				free(uuidpath);
-			}
-			
-			
+						
 			if ((state != ' ' && preceding_flags != FILE_INFO_IDENTICAL) ||
 				INFO_TEST(actual->info(), FILE_INFO_BASE_SYSTEM | FILE_INFO_ROLLBACK_DATA)) {
 				*rollback_files += 1;
@@ -619,12 +611,42 @@
 	IF_DEBUG("[backup] backup_file: %s , %s \n", file->path(), context->archive->m_name);
 
 	if (INFO_TEST(file->info(), FILE_INFO_ROLLBACK_DATA)) {
-	        char *path;        // the file's path
+		char *path;        // the file's path
 		char *dstpath;     // the path inside the archives
 		char *relpath;     // the file's path minus the destination prefix
 		char *uuidpath;    // archives path plus the uuid
 		char uuidstr[37];
 
+		// If we're going to need to squirrel away data, create
+		// the directory hierarchy now.
+		char backup_path[PATH_MAX];
+		char* backup_dirpath;
+
+		// we need the path minus our destination prefix for moving to the archive
+		IF_DEBUG("[backup] file->path() = %s \n", file->path());
+		strlcpy(backup_path, file->path(), sizeof(backup_path));
+		IF_DEBUG("[backup] backup_path = %s \n", backup_path);
+			
+		const char* dir = dirname(backup_path);
+		assert(dir != NULL);
+		IF_DEBUG("[backup] dir = %s \n", dir);
+
+		uuid_unparse_upper(context->archive->uuid(), uuidstr);
+		asprintf(&uuidpath, "%s/%s", context->depot->m_archives_path, uuidstr);
+		assert(uuidpath != NULL);
+		IF_DEBUG("[backup] uuidpath = %s \n", uuidpath);
+		join_path(&backup_dirpath, uuidpath, dir);
+		assert(backup_dirpath != NULL);
+		
+		IF_DEBUG("mkdir_p: %s\n", backup_dirpath);
+		res = mkdir_p(backup_dirpath);
+		if (res != 0 && errno != EEXIST) {
+			fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+					__FILE__, __LINE__, backup_dirpath, strerror(errno), errno);
+		} else {
+			res = 0;
+		}
+		
 		// we need the path minus our destination path for moving to the archive
 		size_t prefixlen = strlen(context->depot->m_prefix);
 		if (strncmp(context->archive->m_name, "<Rollback>", strlen("<Rollback>")) == 0) {
@@ -637,17 +659,14 @@
 		        relpath += prefixlen - 1;
 		}
 
-		uuid_unparse_upper(context->archive->uuid(), uuidstr);		
-		asprintf(&uuidpath, "%s/%s", context->depot->m_archives_path, uuidstr);
-		assert(uuidpath != NULL);
 		join_path(&dstpath, uuidpath, relpath);
 		assert(dstpath != NULL);
 
 		IF_DEBUG("[backup] path = %s \n", path);
 		IF_DEBUG("[backup] relpath = %s \n", relpath);
 		IF_DEBUG("[backup] dstpath = %s \n", dstpath);
-		IF_DEBUG("[backup] uuidpath = %s \n", uuidpath);
 
+
 		++context->files_modified;
 
 		// XXX: res = file->backup()
@@ -656,9 +675,14 @@
 
 		if (res != 0) fprintf(stderr, "%s:%d: backup failed: %s: %s (%d)\n", 
 							  __FILE__, __LINE__, dstpath, strerror(errno), errno);
+
+		// XXX: we cant propagate error from callback, but its safe to die here
+		assert(res == 0);
+		
 		free(path);
 		free(dstpath);
 		free(uuidpath);
+		free(backup_dirpath);
 	}
 	return res;
 }
@@ -919,8 +943,16 @@
 					state = 'U';
 					IF_DEBUG("[uninstall]    restoring\n");
 					if (!dryrun && res == 0) {
-						res = preceding->install(context->depot->m_archives_path, 
-												 context->depot->m_prefix);
+						if (INFO_TEST(flags, FILE_INFO_TYPE_DIFFERS) &&
+							S_ISDIR(preceding->mode())) {
+							// use rename instead of mkdir so children are restored
+							res = preceding->dirrename(context->depot->m_archives_path, 
+													   context->depot->m_prefix);							
+
+						} else {
+							res = preceding->install(context->depot->m_archives_path, 
+													 context->depot->m_prefix);							
+						}
 					}
 				} else if (INFO_TEST(flags, FILE_INFO_MODE_DIFFERS) ||
 					   INFO_TEST(flags, FILE_INFO_GID_DIFFERS) ||

Modified: trunk/darwinup/File.cpp
===================================================================
--- trunk/darwinup/File.cpp	2010-11-01 20:40:42 UTC (rev 905)
+++ trunk/darwinup/File.cpp	2010-11-03 22:55:58 UTC (rev 906)
@@ -228,6 +228,11 @@
 	return res;
 }
 
+int File::dirrename(const char* prefix, const char* dest) {
+	// only used for directories
+	assert(0);
+}
+
 int File::remove() {
 	// not implemented
 	fprintf(stderr, "%s:%d: call to abstract function File::remove\n", 
@@ -341,6 +346,14 @@
 : File(serial, archive, info, path, mode, uid, gid, size, digest) {};
 
 int Directory::install(const char* prefix, const char* dest) {
+	return this->_install(prefix, dest, false);
+}
+
+int Directory::dirrename(const char* prefix, const char* dest) {
+	return this->_install(prefix, dest, true);	
+}
+
+int Directory::_install(const char* prefix, const char* dest, bool use_rename) {
 	// We create a new directory instead of renaming the
 	// existing one, since that would move the entire
 	// sub-tree, and lead to a lot of ENOENT errors.
@@ -352,12 +365,36 @@
 	mode_t mode = this->mode() & ALLPERMS;
 	uid_t uid = this->uid();
 	gid_t gid = this->gid();
-	
-	IF_DEBUG("[install] mkdir(%s, %04o)\n", dstpath, mode);
-	if (res == 0) res = mkdir(dstpath, mode);
-	// mkdir is limited by umask, so ensure mode is set
-	if (res == 0) res = chmod(dstpath, mode); 
 
+	if (use_rename) {
+		// determine source path under archives directory for rename
+		char srcpath[PATH_MAX];
+		const char* path = this->path();
+		Archive* archive = this->archive();
+		char* dirpath = archive->directory_name(prefix);
+		IF_DEBUG("[install] dirpath is %s\n", dirpath);
+		if (is_directory(dirpath) == 0) {
+			IF_DEBUG("[install] expanding archive for directory rename\n");
+			res = archive->expand_directory(prefix);
+		}
+		if (res == 0 && dirpath) {
+			ssize_t len = snprintf(srcpath, sizeof(srcpath), "%s/%s", dirpath, path);
+			if ((size_t)len > sizeof(srcpath)) {
+				fprintf(stderr, "ERROR: [install] path too long: %s/%s\n", 
+						dirpath, path);
+				return -1;
+			}
+		}
+		if (is_regular_file(dstpath)) unlink(dstpath);
+		if (res == 0) IF_DEBUG("[install] rename(%s, %s)\n", srcpath, dstpath);
+		if (res == 0) res = rename(srcpath, dstpath);
+	} else {
+		IF_DEBUG("[install] mkdir(%s, %04o)\n", dstpath, mode);
+		res = mkdir(dstpath, mode);			
+		// mkdir is limited by umask, so ensure mode is set
+		if (res == 0) res = chmod(dstpath, mode); 
+	}
+
 	if (res && errno == EEXIST) {
 		if (is_directory(dstpath)) {
 			// this is expected in normal cases, so no need to force

Modified: trunk/darwinup/File.h
===================================================================
--- trunk/darwinup/File.h	2010-11-01 20:40:42 UTC (rev 905)
+++ trunk/darwinup/File.h	2010-11-03 22:55:58 UTC (rev 906)
@@ -172,7 +172,9 @@
 	// Installs the file from the archive into the prefix
 	// i.e., for regular files:
 	// rename(prefix + this->archive()->uuid() + this->path(), dest + this->path());
-        virtual int install(const char* prefix, const char* dest);
+	virtual int install(const char* prefix, const char* dest);
+	// only used for directories
+	virtual int dirrename(const char* prefix, const char* dest);
 	
 	// Sets the mode, uid, and gid of the file in the dest path
 	// XXX: rename as repair()?
@@ -242,6 +244,8 @@
 	Directory(Archive* archive, FTSENT* ent);
 	Directory(uint64_t serial, Archive* archive, uint32_t info, const char* path, mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest);
 	virtual int install(const char* prefix, const char* dest);
+	virtual int dirrename(const char* prefix, const char* dest);
+	int _install(const char* prefix, const char* dest, bool use_rename);
 	virtual int remove();
 };
 

Modified: trunk/testing/darwinup/dest.tar.gz
===================================================================
(Binary files differ)

Modified: trunk/testing/darwinup/rep_file_dir.tar.gz
===================================================================
(Binary files differ)

Modified: trunk/testing/darwinup/rep_flink_dir.tar.gz
===================================================================
(Binary files differ)

Modified: trunk/testing/darwinup/rep_link_dir.tar.gz
===================================================================
(Binary files differ)

Modified: trunk/testing/darwinup/run-tests.sh
===================================================================
--- trunk/testing/darwinup/run-tests.sh	2010-11-01 20:40:42 UTC (rev 905)
+++ trunk/testing/darwinup/run-tests.sh	2010-11-03 22:55:58 UTC (rev 906)
@@ -353,6 +353,9 @@
 is_file $DEST/rep_file
 $DARWINUP -f install $PREFIX/rep_file_dir
 is_dir $DEST/rep_file
+is_file $DEST/rep_file/subfile
+is_dir $DEST/rep_file/subdir
+is_file $DEST/rep_file/subdir/subsubfile
 $DARWINUP uninstall newest
 is_file $DEST/rep_file
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
@@ -369,19 +372,31 @@
 
 echo "========== TEST: Forcing object change: directory to file ==========" 
 is_dir $DEST/rep_dir
+is_file $DEST/rep_dir/subfile
+is_dir $DEST/rep_dir/subdir
+is_file $DEST/rep_dir/subdir/subsubfile
 $DARWINUP -f install $PREFIX/rep_dir_file
 is_file $DEST/rep_dir
 $DARWINUP uninstall newest
 is_dir $DEST/rep_dir
+is_file $DEST/rep_dir/subfile
+is_dir $DEST/rep_dir/subdir
+is_file $DEST/rep_dir/subdir/subsubfile
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
 $DIFF $ORIG $DEST 2>&1
 
 echo "========== TEST: Forcing object change: directory to symlink ==========" 
 is_dir $DEST/rep_dir
+is_file $DEST/rep_dir/subfile
+is_dir $DEST/rep_dir/subdir
+is_file $DEST/rep_dir/subdir/subsubfile
 $DARWINUP -f install $PREFIX/rep_dir_link
 is_link $DEST/rep_dir
 $DARWINUP uninstall newest
 is_dir $DEST/rep_dir
+is_file $DEST/rep_dir/subfile
+is_dir $DEST/rep_dir/subdir
+is_file $DEST/rep_dir/subdir/subsubfile
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
 $DIFF $ORIG $DEST 2>&1
 
@@ -398,6 +413,9 @@
 is_link $DEST/rep_link
 $DARWINUP -f install $PREFIX/rep_link_dir
 is_dir $DEST/rep_link
+is_file $DEST/rep_link/anotherfile
+is_dir $DEST/rep_link/anotherdir
+is_file $DEST/rep_link/anotherdir/anothersubfile
 $DARWINUP uninstall newest
 is_link $DEST/rep_link
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
@@ -416,6 +434,9 @@
 is_link $DEST/rep_flink
 $DARWINUP -f install $PREFIX/rep_flink_dir
 is_dir $DEST/rep_flink
+is_file $DEST/rep_flink/subfile
+is_dir $DEST/rep_flink/subdir
+is_file $DEST/rep_flink/subdir/subsubfile
 $DARWINUP uninstall newest
 is_link $DEST/rep_flink
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20101103/4c081408/attachment-0001.html>


More information about the darwinbuild-changes mailing list