[darwinbuild-changes] [664] branches/PR-7431723/darwinup

source_changes at macosforge.org source_changes at macosforge.org
Tue Dec 15 13:01:10 PST 2009


Revision: 664
          http://trac.macosforge.org/projects/darwinbuild/changeset/664
Author:   wsiegrist at apple.com
Date:     2009-12-15 13:01:09 -0800 (Tue, 15 Dec 2009)
Log Message:
-----------
Refactor the commands that take an archive as argument. Split iterate_archives into several functions so they are flexible enough to handle operations on "all" archives. Add a new archive() function that synthesises an Archive object from a sqlite row. Cleanup printing of files/lists so they look nice and lineup when asking for "all".

Modified Paths:
--------------
    branches/PR-7431723/darwinup/Archive.h
    branches/PR-7431723/darwinup/Depot.cpp
    branches/PR-7431723/darwinup/Depot.h
    branches/PR-7431723/darwinup/main.cpp

Modified: branches/PR-7431723/darwinup/Archive.h
===================================================================
--- branches/PR-7431723/darwinup/Archive.h	2009-12-14 19:30:19 UTC (rev 663)
+++ branches/PR-7431723/darwinup/Archive.h	2009-12-15 21:01:09 UTC (rev 664)
@@ -120,7 +120,7 @@
 
 	// Constructor for subclasses and Depot to use when unserializing an archive from the database.
 	Archive(uint64_t serial, uuid_t uuid, const char* name, const char* path, uint64_t info, time_t date_installed);
-
+	
 	uint64_t	m_serial;
 	uuid_t		m_uuid;
 	char*		m_name;

Modified: branches/PR-7431723/darwinup/Depot.cpp
===================================================================
--- branches/PR-7431723/darwinup/Depot.cpp	2009-12-14 19:30:19 UTC (rev 663)
+++ branches/PR-7431723/darwinup/Depot.cpp	2009-12-15 21:01:09 UTC (rev 664)
@@ -254,6 +254,25 @@
 	return archive;	
 }
 
+// create a new Archive from a database row
+Archive* Depot::archive(sqlite3_stmt* stmt) {
+	uuid_t uuid;
+	uint64_t serial = sqlite3_column_int64(stmt, 0);
+	const void* blob = sqlite3_column_blob(stmt, 1);
+	int blobsize = sqlite3_column_bytes(stmt, 1);
+	const unsigned char* name = sqlite3_column_text(stmt, 2);
+	uint64_t info = sqlite3_column_int64(stmt, 3);
+	time_t date_added = sqlite3_column_int(stmt, 4);
+	if (blobsize > 0) {
+		assert(blobsize == sizeof(uuid_t));
+		memcpy(uuid, blob, sizeof(uuid_t));
+	} else {
+		uuid_clear(uuid);
+	}
+	return new Archive(serial, uuid, (const char*)name, NULL, info, date_added);	
+}
+
+
 // Return Archive from database matching arg, which is one of:
 //
 //   uuid (ex: 22969F32-9C4F-4370-82C8-DD3609736D8D)
@@ -283,48 +302,71 @@
 	return Depot::archive((archive_name_t)arg);
 }
 
-int Depot::iterate_archives(ArchiveIteratorFunc func, void* context) {
+Archive** Depot::get_all_archives(size_t* count) {
+	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) {
-		const char* query = "SELECT serial, uuid, name, info, date_added FROM archives ORDER BY serial DESC";
+		const char* query = "SELECT serial, uuid, name, info, date_added FROM archives WHERE name != '<Rollback>' ORDER BY serial DESC";
+		if (verbosity & VERBOSE_DEBUG) {
+			query = "SELECT serial, uuid, name, info, date_added FROM archives ORDER BY serial DESC";
+		}
 		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) {
-		while (res == 0) {
+		size_t i = 0;
+		while (res != SQLITE_DONE) {
 			res = sqlite3_step(stmt);
 			if (res == SQLITE_ROW) {
-				res = 0;
-				uuid_t uuid;
-				uint64_t serial = sqlite3_column_int64(stmt, 0);
-				const void* blob = sqlite3_column_blob(stmt, 1);
-				int blobsize = sqlite3_column_bytes(stmt, 1);
-				const unsigned char* name = sqlite3_column_text(stmt, 2);
-				uint64_t info = sqlite3_column_int64(stmt, 3);
-				time_t date_added = sqlite3_column_int(stmt, 4);
-				if (blobsize > 0) {
-					assert(blobsize == sizeof(uuid_t));
-					memcpy(uuid, blob, sizeof(uuid_t));
-				} else {
-					uuid_clear(uuid);
-				}
-				Archive* archive = new Archive(serial, uuid, (const char*)name, NULL, info, date_added);
-				if (archive) {
-					res = func(archive, context);
-					delete archive;
-				} else {
-					fprintf(stderr, "%s:%d: new Archive returned NULL\n", __FILE__, __LINE__);
-					res = -1;
-					break;
-				}
-			} else if (res == SQLITE_DONE) {
-				res = 0;
-				break;
-			}
+				//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);
 	}
+	return list;	
+}
+
+size_t Depot::count_archives() {
+	extern uint32_t verbosity;
+	int res = 0;
+	size_t count = 0;
+	static sqlite3_stmt* stmt = NULL;
+	if (stmt == NULL && m_db) {
+		const char* query = "SELECT count(*) FROM archives WHERE name != '<Rollback>'";
+		if (verbosity & VERBOSE_DEBUG) {
+			query = "SELECT count(*) FROM archives";
+		}
+		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) {
+		res = sqlite3_step(stmt);
+		if (res == SQLITE_ROW) {
+			count = sqlite3_column_int64(stmt, 0);
+		}
+		sqlite3_reset(stmt);
+	}
+	return count;
+}
+
+int Depot::iterate_archives(ArchiveIteratorFunc func, void* context) {
+	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];
+		}
+	}
 	return res;
 }
 
@@ -818,12 +860,18 @@
 }
 
 int Depot::uninstall(Archive* archive) {
+	extern uint32_t verbosity;
 	int res = 0;
 
 	assert(archive != NULL);
 	uint64_t serial = archive->serial();
 
 	if (INFO_TEST(archive->info(), ARCHIVE_INFO_ROLLBACK)) {
+		// if in debug mode, get_all_archives returns rollbacks too, so just ignore
+		if (verbosity & VERBOSE_DEBUG) {
+			fprintf(stderr, "[uninstall] skipping uninstall since archive is a rollback.\n");
+			return 0;
+		}
 		fprintf(stderr, "%s:%d: cannot uninstall a rollback archive.\n", __FILE__, __LINE__);
 		return -1;
 	}
@@ -888,13 +936,16 @@
 
 int Depot::verify(Archive* archive) {
 	int res = 0;
+	fprintf(stdout, "%-6s %-36s  %-23s  %s\n", "Serial", "UUID", "Date Installed", "Name");
+	fprintf(stdout, "====== ====================================  =======================  =================\n");
+	list_archive(archive, stdout);	
+	fprintf(stdout, "=======================================================================================\n");
 	if (res == 0) res = this->iterate_files(archive, &Depot::verify_file, NULL);
+	fprintf(stdout, "=======================================================================================\n\n");
 	return res;
 }
 
-int Depot::list_archive(Archive* archive, void* context) {
-	extern uint32_t verbosity;
-	
+int Depot::list_archive(Archive* archive, void* context) {	
 	uint64_t serial = archive->serial();
 	
 	char uuid[37];
@@ -906,10 +957,7 @@
 	localtime_r(&seconds, &local);
 	strftime(date, sizeof(date), "%F %T %Z", &local);
 
-	if (!INFO_TEST(archive->info(), ARCHIVE_INFO_ROLLBACK) ||
-	    (verbosity & VERBOSE_DEBUG)) {
-		fprintf((FILE*)context, "%-6llu %-36s  %-23s  %s\n", serial, uuid, date, archive->name());
-	}
+	fprintf((FILE*)context, "%-6llu %-36s  %-23s  %s\n", serial, uuid, date, archive->name());
 	
 	return 0;
 }
@@ -931,11 +979,12 @@
 
 int Depot::files(Archive* archive) {
 	int res = 0;
-	fprintf(stdout, "%-36s  %-23s  %s\n", "UUID", "Date Installed", "Name");
-	fprintf(stdout, "====================================  =======================  =================\n");
+	fprintf(stdout, "%-6s %-36s  %-23s  %s\n", "Serial", "UUID", "Date Installed", "Name");
+	fprintf(stdout, "====== ====================================  =======================  =================\n");
 	list_archive(archive, stdout);
-	fprintf(stdout, "================================================================================\n");
+	fprintf(stdout, "=======================================================================================\n");
 	if (res == 0) res = this->iterate_files(archive, &Depot::print_file, stdout);
+	fprintf(stdout, "=======================================================================================\n\n");
 	return res;
 }
 
@@ -943,9 +992,9 @@
 	Depot* depot = (Depot*)context;
 	int res = 0;
 	list_archive(archive, stdout);
-	fprintf(stdout, "================================================================================\n");
+	fprintf(stdout, "=======================================================================================\n");
 	if (res == 0) res = depot->iterate_files(archive, &Depot::print_file, stdout);
-	fprintf(stdout, "================================================================================\n\n\n");
+	fprintf(stdout, "=======================================================================================\n\n");
 	return res;
 }
 
@@ -953,8 +1002,8 @@
 	extern uint32_t verbosity;
 	verbosity = 0xFFFFFFFF; // dump is intrinsically a debug command
 	int res = 0;
-	fprintf(stdout, "%-36s  %-23s  %s\n", "UUID", "Date Installed", "Name");
-	fprintf(stdout, "====================================  =======================  =================\n");
+	fprintf(stdout, "%-6s %-36s  %-23s  %s\n", "Serial", "UUID", "Date Installed", "Name");
+	fprintf(stdout, "====== ====================================  =======================  =================\n");
 	if (res == 0) res = this->iterate_archives(&Depot::dump_archive, this);
 	return res;
 }
@@ -1223,7 +1272,63 @@
 	return res;
 }
 
+// helper to dispatch the actual command for process_archive()
+int Depot::dispatch_command(Archive* archive, const char* command) {
+	int res = 0;
 
+	if (strncasecmp((char*)command, "files", 5) == 0) {
+		res = this->files(archive);
+	} else if (strncasecmp((char*)command, "uninstall", 9) == 0) {
+		res = this->uninstall(archive);
+	} else if (strncasecmp((char*)command, "verify", 6) == 0) {
+		res = this->verify(archive);
+	} else {
+		fprintf(stderr, "Error: unknown command given to dispatch_command.\n");
+	}
+	if (res != 0) {
+		fprintf(stderr, "An error occurred.\n");
+	}
+	return res;
+}
+
+// perform a command on an archive specification
+int Depot::process_archive(const char* command, const char* arg) {
+	extern uint32_t verbosity;
+	int res = 0;
+	size_t count = 0;
+	Archive** list = NULL;
+	
+	if (strncasecmp(arg, "all", 3) == 0) {
+		list = this->get_all_archives(&count);
+	} else {
+		// make a list of 1 Archive
+		list = (Archive**)malloc(sizeof(Archive*));
+		list[0] = this->get_archive(arg);
+		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;
+		}
+		if (verbosity & VERBOSE_DEBUG) {
+			char uuid[37];
+			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];
+	} 
+	free(list);
+	return res;
+}
+
+
 #define __SQL(callback, context, fmt) \
 	va_list args; \
 	char* errmsg; \

Modified: branches/PR-7431723/darwinup/Depot.h
===================================================================
--- branches/PR-7431723/darwinup/Depot.h	2009-12-14 19:30:19 UTC (rev 663)
+++ branches/PR-7431723/darwinup/Depot.h	2009-12-15 21:01:09 UTC (rev 664)
@@ -56,7 +56,7 @@
 	int initialize();
 	int is_initialized();
 	
-        const char*     prefix();
+	const char* prefix();
 	const char*	database_path();
 	const char*	archives_path();
 
@@ -64,12 +64,17 @@
 	virtual int	commit_transaction();
 	virtual int	rollback_transaction();
 
-	Archive*	archive(uint64_t serial);
-	Archive*	archive(uuid_t uuid);
-	Archive*	archive(archive_name_t name);
-	Archive*	archive(archive_keyword_t keyword);
-	Archive*	get_archive(const char* arg);
+	Archive* archive(uint64_t serial);
+	Archive* archive(uuid_t uuid);
+	Archive* archive(archive_name_t name);
+	Archive* archive(archive_keyword_t keyword);
+	Archive* archive(sqlite3_stmt* stmt);
+	Archive* get_archive(const char* arg);
 
+	// returns a list of Archive*. Caller must free the list. 
+	Archive** get_all_archives(size_t *count);
+	size_t count_archives();
+	
 	int dump();
 	static int dump_archive(Archive* archive, void* context);
 	
@@ -92,8 +97,13 @@
 	int iterate_files(Archive* archive, FileIteratorFunc func, void* context);
 	int iterate_archives(ArchiveIteratorFunc func, void* context);
 
-        // test if the depot is currently locked 
-        int is_locked();
+	// processes an archive according to command
+	//  arg is an archive identifier, such as serial or uuid
+	int dispatch_command(Archive* archive, const char* command);
+	int process_archive(const char* command, const char* arg);
+	
+	// test if the depot is currently locked 
+	int is_locked();
 
 	protected:
 
@@ -123,7 +133,7 @@
 	
 	// Removes all archive entries which have no corresponding files entries.
 	int		prune_archives();
-
+	
 	File*		file_superseded_by(File* file);
 	File*		file_preceded_by(File* file);
 	File*		file_star_eded_by(File* file, sqlite3_stmt* stmt);

Modified: branches/PR-7431723/darwinup/main.cpp
===================================================================
--- branches/PR-7431723/darwinup/main.cpp	2009-12-14 19:30:19 UTC (rev 663)
+++ branches/PR-7431723/darwinup/main.cpp	2009-12-15 21:01:09 UTC (rev 664)
@@ -154,50 +154,11 @@
 	} else if (argc == 1 && strcmp(argv[0], "dump") == 0) {
 		depot->dump();
 	} else if (argc == 2 && strcmp(argv[0], "files") == 0) {
-		Archive* archive = depot->get_archive(argv[1]);
-		if (archive) {
-			res = depot->files(archive);
-			delete archive;
-		} else {
-			fprintf(stderr, "Archive not found: %s\n", argv[1]);
-			res = 1;
-		}
+		res = depot->process_archive(argv[0], argv[1]);
 	} else if (argc == 2 && strcmp(argv[0], "uninstall") == 0) {
-		Archive* archive = depot->get_archive(argv[1]);
-		if (archive) {
-			if (verbosity & VERBOSE_DEBUG) {
-				char uuid[37];
-				uuid_unparse_upper(archive->uuid(), uuid);
-				fprintf(stderr, "[uninstall] found archive: %s\n", uuid);
-			}
-			res = depot->uninstall(archive);
-			if (res != 0) {
-				fprintf(stderr, "An error occurred.\n");
-				res = 1;
-			}
-			delete archive;
-		} else {
-			fprintf(stderr, "Archive not found: %s\n", argv[1]);
-			res = 1;
-		}
+		res = depot->process_archive(argv[0], argv[1]);
 	} else if (argc == 2 && strcmp(argv[0], "verify") == 0) {
-		Archive* archive = depot->get_archive(argv[1]);
-		if (archive) {
-			if (verbosity & VERBOSE_DEBUG) {
-				char uuid[37];
-				uuid_unparse_upper(archive->uuid(), uuid);
-				fprintf(stderr, "[uninstall] found archive: %s\n", uuid);
-			}			
-			res = depot->verify(archive);
-			if (res != 0) {
-				fprintf(stderr, "An error occurred.\n");
-				res = 1;
-			}
-			delete archive;
-		} else {
-			fprintf(stderr, "Archive not found: %s\n", argv[1]);
-			res = 1;
-		}
+		res = depot->process_archive(argv[0], argv[1]);
 	} else {
 		usage(progname);
 	}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20091215/28aae93f/attachment-0001.html>


More information about the darwinbuild-changes mailing list