[darwinbuild-changes] [672] trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Dec 22 13:47:57 PST 2009


Revision: 672
          http://trac.macosforge.org/projects/darwinbuild/changeset/672
Author:   wsiegrist at apple.com
Date:     2009-12-22 13:47:55 -0800 (Tue, 22 Dec 2009)
Log Message:
-----------
Merge PR-7482850

Modified Paths:
--------------
    trunk/CHANGES
    trunk/darwinup/Depot.cpp
    trunk/darwinup/Depot.h
    trunk/testing/darwinup/run-tests.sh

Added Paths:
-----------
    trunk/testing/darwinup/root5.tar.gz
    trunk/testing/darwinup/root6.tar.gz
    trunk/testing/darwinup/root7.tar.gz

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-7250612:635-650
/branches/PR-7431723:660-664
/branches/PR-7461534:650-664
/trunk:432-434
   + /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-7250612:635-650
/branches/PR-7431723:660-664
/branches/PR-7461534:650-664
/branches/PR-7482850:670-671
/trunk:432-434

Modified: trunk/CHANGES
===================================================================
--- trunk/CHANGES	2009-12-21 19:04:39 UTC (rev 671)
+++ trunk/CHANGES	2009-12-22 21:47:55 UTC (rev 672)
@@ -1,6 +1,11 @@
 Darwin Build Scripts Change History
 -----------------------------------
 
+Release 13.1 [22-Dec-2009]
+	- darwinup: fix bug where rollback archives for user modifications
+	  did not contain parent directories and thus certain
+	  install/modify/uninstall patterns would result in data loss. 
+
 Release 13 [16-Dec-2009]
 	- darwinup: convert use of fork()/exec() to posix_spawn()
 	- darwinup: add Serial to archive list, allow use of serial, name, 

Modified: trunk/darwinup/Depot.cpp
===================================================================
--- trunk/darwinup/Depot.cpp	2009-12-21 19:04:39 UTC (rev 671)
+++ trunk/darwinup/Depot.cpp	2009-12-22 21:47:55 UTC (rev 672)
@@ -316,7 +316,6 @@
 	extern uint32_t verbosity;
 	int res = 0;
 	*count = this->count_archives();
-	//fprintf(stderr, "DEBUG: get_all_archives got count = %d \n", (int)*count);
 	Archive** list = (Archive**)malloc(*count * sizeof(Archive*));
 	static sqlite3_stmt* stmt = NULL;
 	if (stmt == NULL && m_db) {
@@ -332,9 +331,7 @@
 		while (res != SQLITE_DONE) {
 			res = sqlite3_step(stmt);
 			if (res == SQLITE_ROW) {
-				//fprintf(stderr, "DEBUG: making %d-th archive \n", (int)i);
 				list[i++] = this->archive(stmt);
-				//fprintf(stderr, "DEBUG: archive = %p \n", list[i-1]);
 			} 
 		}
 		sqlite3_reset(stmt);
@@ -369,9 +366,7 @@
 	int res = 0;
 	size_t count = 0;
 	Archive** list = this->get_all_archives(&count);
-	//fprintf(stderr, "DEBUG: iterate got: %p %d \n", *list, (int)count);
 	for (size_t i = 0; i < count; i++) {
-		//fprintf(stderr, "DEBUG: iterating on i = %d list[i] = %p \n", (int)i, list[i]);
 		if (list[i]) {
 			res = func(list[i], context);
 			delete list[i];
@@ -558,6 +553,30 @@
 				IF_DEBUG("[analyze]    insert rollback\n");
 				res = this->insert(rollback, actual);
 				assert(res == 0);
+				// need to save parent directories as well
+				char *ppath;
+				char *pathbuf;
+				pathbuf = strdup(actual->path());
+				ppath = dirname(pathbuf);
+				free(pathbuf);
+				// while we have a valid path that is below the prefix
+				while (ppath 
+					   && strncmp(ppath, this->prefix(), strlen(this->prefix())) == 0
+					   && strncmp(ppath, this->prefix(), strlen(ppath)) > 0) {
+					File* parent = FileFactory(ppath);
+					// if parent dir does not exist, we are
+					//  generating a rollback of base system
+					//  which does not have matching directories,
+					//  so we can just move on.
+					if (!parent) {
+						IF_DEBUG("[analyze]      parent path not found, skipping parents\n");
+						break;
+					}
+					IF_DEBUG("[analyze]      adding parent to rollback: %s \n", parent->path());
+					res = this->insert(rollback, parent);
+					assert(res == 0);
+					ppath = dirname(ppath);
+				}
 			}
 
 			fprintf(stderr, "%c %s\n", state, file->path());
@@ -1227,7 +1246,7 @@
 
 int Depot::insert(Archive* archive, File* file) {
 	int res = 0;
-
+	int do_update = 0;
 	// check for the destination prefix in file's path, remove if found
 	char *path, *relpath;
 	size_t prefixlen = strlen(this->prefix());
@@ -1237,15 +1256,21 @@
 	        relpath += prefixlen - 1;
 	}
 
-	static sqlite3_stmt* stmt = NULL;
-	if (stmt == NULL && m_db) {
-		const char* query = "INSERT INTO files (archive, info, mode, uid, gid, digest, path) VALUES (?, ?, ?, ?, ?, ?, ?)";
+	const char* query = NULL;
+	if (this->has_file(archive, file)) {
+		do_update = 1;
+		IF_DEBUG("archive(%llu) already has %s, updating instead \n", archive->serial(), relpath);
+		query = "UPDATE files SET info=?, mode=?, uid=?, gid=?, digest=? WHERE archive=? and path=?";
+	} else {
+		query = "INSERT INTO files (info, mode, uid, gid, digest, archive, path) VALUES (?, ?, ?, ?, ?, ?, ?)";	
+	}
+	sqlite3_stmt* stmt = NULL;
+	if (m_db) {
 		res = sqlite3_prepare(m_db, query, -1, &stmt, NULL);
 		if (res != 0) fprintf(stderr, "%s:%d: sqlite3_prepare: %s: %s (%d)\n", __FILE__, __LINE__, query, sqlite3_errmsg(m_db), res);
 	}
 	if (stmt && res == 0) {
 		int i = 1;
-		if (res == 0) res = sqlite3_bind_int64(stmt, i++, archive->serial());
 		if (res == 0) res = sqlite3_bind_int(stmt, i++, file->info());
 		if (res == 0) res = sqlite3_bind_int(stmt, i++, file->mode());
 		if (res == 0) res = sqlite3_bind_int(stmt, i++, file->uid());
@@ -1253,10 +1278,14 @@
 		Digest* dig = file->digest();
 		if (res == 0 && dig) res = sqlite3_bind_blob(stmt, i++, dig->data(), dig->size(), SQLITE_STATIC);
 		else if (res == 0) res = sqlite3_bind_blob(stmt, i++, NULL, 0, SQLITE_STATIC);
+		if (res == 0) res = sqlite3_bind_int64(stmt, i++, archive->serial());
 		if (res == 0) res = sqlite3_bind_text(stmt, i++, relpath, -1, SQLITE_STATIC);
 		if (res == 0) res = sqlite3_step(stmt);
 		if (res == SQLITE_DONE) {
-			file->m_serial = (uint64_t)sqlite3_last_insert_rowid(m_db);
+			// if we did an insert, update the file serial
+			if (!do_update) {
+				file->m_serial = (uint64_t)sqlite3_last_insert_rowid(m_db);
+			}
 			res = 0;
 		} else {
 			fprintf(stderr, "%s:%d: Could not add file to database: %s (%d)\n", __FILE__, __LINE__, sqlite3_errmsg(m_db), res);
@@ -1267,6 +1296,42 @@
 	return res;
 }
 
+int Depot::has_file(Archive* archive, File* file) {
+	int res = 0;
+	size_t count = 0;
+	// check for the destination prefix in file's path, remove if found
+	char *path, *relpath;
+	size_t prefixlen = strlen(this->prefix());
+	asprintf(&path, "%s", file->path());
+	relpath = path;
+	if (strncmp(file->path(), this->prefix(), prefixlen) == 0) {
+		relpath += prefixlen - 1;
+	}
+	
+	static sqlite3_stmt* stmt = NULL;
+	if (stmt == NULL && m_db) {
+		const char* query = "SELECT count(*) FROM files WHERE archive=? and path=?";
+		res = sqlite3_prepare(m_db, query, -1, &stmt, NULL);
+		if (res != 0) fprintf(stderr, "%s:%d: sqlite3_prepare: %s: %s (%d)\n", __FILE__, __LINE__, query, sqlite3_errmsg(m_db), res);
+	}
+	if (stmt && res == 0) {
+		int i = 1;
+		if (res == 0) res = sqlite3_bind_int64(stmt, i++, archive->serial());
+		if (res == 0) res = sqlite3_bind_text(stmt, i++, relpath, -1, SQLITE_STATIC);
+		if (res == 0) res = sqlite3_step(stmt);
+		if (res == SQLITE_ROW) {
+			count = sqlite3_column_int64(stmt, 0);
+			IF_DEBUG("has_file(%llu, %s) got count = %u \n", archive->serial(), relpath, (unsigned int)count);
+		} else {
+			res = -1;
+			fprintf(stderr, "%s:%d: Could not query for file in archive: %s (%d)\n", __FILE__, __LINE__, sqlite3_errmsg(m_db), res);
+		}
+		sqlite3_reset(stmt);
+	}
+	free(path);
+	return count > 0;
+}
+
 int Depot::remove(Archive* archive) {
 	int res = 0;
 	uint64_t serial = archive->serial();
@@ -1317,10 +1382,7 @@
 		count = 1;
 	}
 	
-	//fprintf(stderr, "DEBUG: count = %d \n", (int)count);
-	
 	for (size_t i = 0; i < count; i++) {
-		//fprintf(stderr, "DEBUG: i = %d \n", (int)i);
 		if (!list[i]) {
 			fprintf(stderr, "Archive not found: %s\n", arg);
 			return -1;
@@ -1330,7 +1392,6 @@
 			uuid_unparse_upper(list[i]->uuid(), uuid);
 			fprintf(stderr, "Found archive: %s\n", uuid);
 		}
-		//fprintf(stderr, "DEBUG: dispatching %p %s \n", list[i], command);
 		res = this->dispatch_command(list[i], command);
 		delete list[i];
 	} 

Modified: trunk/darwinup/Depot.h
===================================================================
--- trunk/darwinup/Depot.h	2009-12-21 19:04:39 UTC (rev 671)
+++ trunk/darwinup/Depot.h	2009-12-22 21:47:55 UTC (rev 672)
@@ -123,6 +123,8 @@
 	// If the File already has a serial number, it cannot be inserted.
 	int insert(Archive* archive, File* file);
 
+	int has_file(Archive* archive, File* file);
+	
 	// Removes an Archive from the database.
 	int remove(Archive* archive);
 	

Copied: trunk/testing/darwinup/root5.tar.gz (from rev 671, branches/PR-7482850/testing/darwinup/root5.tar.gz)
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/root6.tar.gz (from rev 671, branches/PR-7482850/testing/darwinup/root6.tar.gz)
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/root7.tar.gz (from rev 671, branches/PR-7482850/testing/darwinup/root7.tar.gz)
===================================================================
(Binary files differ)

Modified: trunk/testing/darwinup/run-tests.sh
===================================================================
--- trunk/testing/darwinup/run-tests.sh	2009-12-21 19:04:39 UTC (rev 671)
+++ trunk/testing/darwinup/run-tests.sh	2009-12-22 21:47:55 UTC (rev 672)
@@ -1,4 +1,6 @@
 #!/bin/bash
+set -e
+set -x
 
 #
 # Run tests on darwinup
@@ -9,6 +11,8 @@
 DEST=$PREFIX/dest
 DESTTAR=dest.tar.gz
 
+DIFF="diff -x .DarwinDepot -qru"
+
 ROOTS="root root2 root3"
 
 echo "INFO: Cleaning up testing area ..."
@@ -22,8 +26,12 @@
 do
 	tar zxvf $R.tar.gz -C $PREFIX
 done;
-tar zxvf root4.tar.gz -C $PREFIX
 
+for R in root4 root5 root6 root7;
+do
+	tar zxvf $R.tar.gz -C $PREFIX
+done;
+
 mkdir -p $ORIG
 cp -R $DEST/* $ORIG/
 
@@ -32,13 +40,11 @@
 do
 	echo "INFO: Installing $R ...";
 	darwinup -vv -p $DEST install $PREFIX/$R
-	if [ $? -gt 0 ]; then exit 1; fi
 	UUID=$(darwinup -p $DEST list | head -3 | tail -1 | awk '{print $1}')
 	echo "INFO: Uninstalling $R ...";
 	darwinup -vv -p $DEST uninstall $UUID
-	if [ $? -gt 0 ]; then exit 1; fi
 	echo "DIFF: diffing original test files to dest (should be no diffs) ..."
-	diff -qru $ORIG $DEST 2>&1 | grep -v \\.DarwinDepot
+	$DIFF $ORIG $DEST 2>&1
 done
 
 echo "TEST: Trying all roots at once, uninstall in reverse ...";
@@ -46,74 +52,79 @@
 do
 	echo "INFO: Installing $R ...";
 	darwinup -vv -p $DEST install $PREFIX/$R
-	if [ $? -gt 0 ]; then exit 1; fi
 done
 for R in $ROOTS;
 do
 	UUID=$(darwinup -p $DEST list | head -3 | tail -1 | awk '{print $1}')
 	echo "INFO: Uninstalling $UUID ...";
 	darwinup -vv -p $DEST uninstall $UUID
-	if [ $? -gt 0 ]; then exit 1; fi
 done	
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
-diff -qru $ORIG $DEST 2>&1 | grep -v \\.DarwinDepot
+$DIFF $ORIG $DEST 2>&1
 
 echo "TEST: Trying all roots at once, uninstall in install order ..."
 for R in $ROOTS;
 do
         echo "INFO: Installing $R ...";
         darwinup -vv -p $DEST install $PREFIX/$R
-	if [ $? -gt 0 ]; then exit 1; fi
 done
 for R in $ROOTS;
 do
         UUID=$(darwinup -p $DEST list | grep $R$ | awk '{print $1}')
         echo "INFO: Uninstalling $UUID ...";
         darwinup -vv -p $DEST uninstall $UUID
-	if [ $? -gt 0 ]; then exit 1; fi
 done
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
-diff -qru $ORIG $DEST 2>&1 | grep -v \\.DarwinDepot
+$DIFF $ORIG $DEST 2>&1
 
 echo "TEST: Trying all roots at once, uninstall root2, root3, root ..."
 for R in $ROOTS;
 do
         echo "INFO: Installing $R ...";
         darwinup -vv -p $DEST install $PREFIX/$R
-	if [ $? -gt 0 ]; then exit 1; fi
 done
 for R in root2 root3 root;
 do
         UUID=$(darwinup -p $DEST list | grep $R$ | awk '{print $1}')
         echo "INFO: Uninstalling $UUID ...";
         darwinup -vv -p $DEST uninstall $UUID
-	if [ $? -gt 0 ]; then exit 1; fi
 done
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
-diff -qru $ORIG $DEST 2>&1 | grep -v \\.DarwinDepot
+$DIFF $ORIG $DEST 2>&1
 
 echo "TEST: Trying roots in reverse, uninstall in install order ..."
 for R in root3 root2 root;
 do
         echo "INFO: Installing $R ...";
         darwinup -vv -p $DEST install $PREFIX/$R
-	if [ $? -gt 0 ]; then exit 1; fi
 done
 for R in root3 root2 root;
 do
         UUID=$(darwinup -p $DEST list | grep $R$ | awk '{print $1}')
         echo "INFO: Uninstalling $UUID ...";
         darwinup -vv -p $DEST uninstall $UUID
-	if [ $? -gt 0 ]; then exit 1; fi
 done
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
-diff -qru $ORIG $DEST 2>&1 | grep -v \\.DarwinDepot
+$DIFF $ORIG $DEST 2>&1
 
+echo "TEST: Try uninstalling with user data in rollback"
+echo "INFO: Installing root5 ...";
+darwinup -vv -p $DEST install $PREFIX/root5
+darwinup -vv -p $DEST install $PREFIX/root6
+echo "modification" >> $DEST/d/file
+darwinup -vv -p $DEST install $PREFIX/root7
+darwinup -vv -p $DEST uninstall root6
+darwinup -vv -p $DEST uninstall root5
+darwinup -vv -p $DEST uninstall root7
+
+
+set +e
+
 echo "TEST: Trying a root that will fail due to object change ..."
 darwinup -vv -p $DEST install $PREFIX/root4
 if [ $? -ne 1 ]; then exit 1; fi
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
-diff -qru $ORIG $DEST 2>&1 | grep -v \\.DarwinDepot
+$DIFF $ORIG $DEST 2>&1
 
 echo "INFO: Done testing!"
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20091222/0ff84ddd/attachment-0001.html>


More information about the darwinbuild-changes mailing list