[darwinbuild-changes] [773] trunk
source_changes at macosforge.org
source_changes at macosforge.org
Fri Mar 12 14:20:44 PST 2010
Revision: 773
http://trac.macosforge.org/projects/darwinbuild/changeset/773
Author: wsiegrist at apple.com
Date: 2010-03-12 14:20:40 -0800 (Fri, 12 Mar 2010)
Log Message:
-----------
Merge PR-7593824
Modified Paths:
--------------
trunk/darwinup/Archive.cpp
trunk/darwinup/Archive.h
trunk/darwinup/Column.cpp
trunk/darwinup/Column.h
trunk/darwinup/DB.cpp
trunk/darwinup/DB.h
trunk/darwinup/Database.cpp
trunk/darwinup/Database.h
trunk/darwinup/Depot.cpp
trunk/darwinup/Depot.h
trunk/darwinup/Table.cpp
trunk/darwinup/Table.h
trunk/darwinup/Utils.cpp
trunk/darwinup/Utils.h
trunk/darwinup/main.cpp
trunk/testing/darwinup/run-tests.sh
Property Changed:
----------------
trunk/
trunk/darwinbuild/darwinbuild.in
trunk/darwinbuild/darwinmaster.in
trunk/darwinbuild/installXcode.in
trunk/darwinbuild/packageRoots.in
trunk/darwinbuild/thinPackages.in
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-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-7598640:703-731
/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-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
Property changes on: trunk/darwinbuild/darwinbuild.in
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/PR-4841388/darwinbuild/darwinbuild:399-419
/branches/PR-6358021/darwinbuild/darwinbuild:442-443
/branches/PR-6392966/darwinbuild/darwinbuild:423-427
/branches/PR-6398060/darwinbuild/darwinbuild:433-434
/branches/PR-6493844/darwinbuild/darwinbuild.in:460-461
/branches/PR-6497694/darwinbuild/darwinbuild.in:466-468,471
/branches/PR-6634286/darwinbuild/darwinbuild.in:632-650
/branches/PR-6688645/darwinbuild/darwinbuild.in:479-490
/branches/PR-6722857/darwinbuild/darwinbuild.in:495-499
/branches/PR-6729491/darwinbuild/darwinbuild.in:655-664
/branches/PR-7250612/darwinbuild/darwinbuild.in:635-650
/branches/PR-7341154/darwinbuild/darwinbuild.in:682-694
/branches/PR-7431723/darwinbuild/darwinbuild.in:660-664
/branches/PR-7461534/darwinbuild/darwinbuild.in:650-664
/branches/PR-7489777/darwinbuild/darwinbuild.in:676-731
/branches/PR-7529688/darwinbuild/darwinbuild.in:692-694
/branches/PR-7598640/darwinbuild/darwinbuild.in:703-731
/trunk/darwinbuild/darwinbuild:432-434
+ /branches/PR-4841388/darwinbuild/darwinbuild:399-419
/branches/PR-6358021/darwinbuild/darwinbuild:442-443
/branches/PR-6392966/darwinbuild/darwinbuild:423-427
/branches/PR-6398060/darwinbuild/darwinbuild:433-434
/branches/PR-6493844/darwinbuild/darwinbuild.in:460-461
/branches/PR-6497694/darwinbuild/darwinbuild.in:466-468,471
/branches/PR-6634286/darwinbuild/darwinbuild.in:632-650
/branches/PR-6688645/darwinbuild/darwinbuild.in:479-490
/branches/PR-6722857/darwinbuild/darwinbuild.in:495-499
/branches/PR-6729491/darwinbuild/darwinbuild.in:655-664
/branches/PR-7250612/darwinbuild/darwinbuild.in:635-650
/branches/PR-7341154/darwinbuild/darwinbuild.in:682-694
/branches/PR-7431723/darwinbuild/darwinbuild.in:660-664
/branches/PR-7461534/darwinbuild/darwinbuild.in:650-664
/branches/PR-7489777/darwinbuild/darwinbuild.in:676-731
/branches/PR-7529688/darwinbuild/darwinbuild.in:692-694
/branches/PR-7593824/darwinbuild/darwinbuild.in:739-772
/branches/PR-7598640/darwinbuild/darwinbuild.in:703-731
Property changes on: trunk/darwinbuild/darwinmaster.in
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/PR-4841388/darwinbuild/darwinmaster.sh:399-419
/branches/PR-6358021/darwinbuild/darwinmaster.sh:442-443
/branches/PR-6392966/darwinbuild/darwinmaster.sh:423-427
/branches/PR-6398060/darwinbuild/darwinmaster.sh:433-434
/branches/PR-6493844/darwinbuild/darwinmaster.sh.in:460-461
/branches/PR-6497694/darwinbuild/darwinmaster.sh.in:466-468,471
/branches/PR-6634286/darwinbuild/darwinmaster.in:632-650
/branches/PR-6688645/darwinbuild/darwinmaster.sh.in:479-490
/branches/PR-6722857/darwinbuild/darwinmaster.sh.in:495-499
/branches/PR-6729491/darwinbuild/darwinmaster.in:655-664
/branches/PR-7250612/darwinbuild/darwinmaster.in:635-650
/branches/PR-7341154/darwinbuild/darwinmaster.in:682-694
/branches/PR-7431723/darwinbuild/darwinmaster.in:660-664
/branches/PR-7461534/darwinbuild/darwinmaster.in:650-664
/branches/PR-7489777/darwinbuild/darwinmaster.in:676-731
/branches/PR-7529688/darwinbuild/darwinmaster.in:692-694
/branches/PR-7598640/darwinbuild/darwinmaster.in:703-731
/trunk/darwinbuild/darwinmaster.sh:432-434
+ /branches/PR-4841388/darwinbuild/darwinmaster.sh:399-419
/branches/PR-6358021/darwinbuild/darwinmaster.sh:442-443
/branches/PR-6392966/darwinbuild/darwinmaster.sh:423-427
/branches/PR-6398060/darwinbuild/darwinmaster.sh:433-434
/branches/PR-6493844/darwinbuild/darwinmaster.sh.in:460-461
/branches/PR-6497694/darwinbuild/darwinmaster.sh.in:466-468,471
/branches/PR-6634286/darwinbuild/darwinmaster.in:632-650
/branches/PR-6688645/darwinbuild/darwinmaster.sh.in:479-490
/branches/PR-6722857/darwinbuild/darwinmaster.sh.in:495-499
/branches/PR-6729491/darwinbuild/darwinmaster.in:655-664
/branches/PR-7250612/darwinbuild/darwinmaster.in:635-650
/branches/PR-7341154/darwinbuild/darwinmaster.in:682-694
/branches/PR-7431723/darwinbuild/darwinmaster.in:660-664
/branches/PR-7461534/darwinbuild/darwinmaster.in:650-664
/branches/PR-7489777/darwinbuild/darwinmaster.in:676-731
/branches/PR-7529688/darwinbuild/darwinmaster.in:692-694
/branches/PR-7593824/darwinbuild/darwinmaster.in:739-772
/branches/PR-7598640/darwinbuild/darwinmaster.in:703-731
Property changes on: trunk/darwinbuild/installXcode.in
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/PR-4841388/darwinbuild/installXcode:399-419
/branches/PR-6358021/darwinbuild/installXcode:442-443
/branches/PR-6392966/darwinbuild/installXcode:423-427
/branches/PR-6398060/darwinbuild/installXcode:433-434
/branches/PR-6493844/darwinbuild/installXcode.in:460-461
/branches/PR-6497694/darwinbuild/installXcode.in:466-468,471
/branches/PR-6634286/darwinbuild/installXcode.in:632-650
/branches/PR-6688645/darwinbuild/installXcode.in:479-490
/branches/PR-6722857/darwinbuild/installXcode.in:495-499
/branches/PR-6729491/darwinbuild/installXcode.in:655-664
/branches/PR-7250612/darwinbuild/installXcode.in:635-650
/branches/PR-7341154/darwinbuild/installXcode.in:682-694
/branches/PR-7431723/darwinbuild/installXcode.in:660-664
/branches/PR-7461534/darwinbuild/installXcode.in:650-664
/branches/PR-7489777/darwinbuild/installXcode.in:676-731
/branches/PR-7529688/darwinbuild/installXcode.in:692-694
/branches/PR-7598640/darwinbuild/installXcode.in:703-731
/trunk/darwinbuild/installXcode:432-434
+ /branches/PR-4841388/darwinbuild/installXcode:399-419
/branches/PR-6358021/darwinbuild/installXcode:442-443
/branches/PR-6392966/darwinbuild/installXcode:423-427
/branches/PR-6398060/darwinbuild/installXcode:433-434
/branches/PR-6493844/darwinbuild/installXcode.in:460-461
/branches/PR-6497694/darwinbuild/installXcode.in:466-468,471
/branches/PR-6634286/darwinbuild/installXcode.in:632-650
/branches/PR-6688645/darwinbuild/installXcode.in:479-490
/branches/PR-6722857/darwinbuild/installXcode.in:495-499
/branches/PR-6729491/darwinbuild/installXcode.in:655-664
/branches/PR-7250612/darwinbuild/installXcode.in:635-650
/branches/PR-7341154/darwinbuild/installXcode.in:682-694
/branches/PR-7431723/darwinbuild/installXcode.in:660-664
/branches/PR-7461534/darwinbuild/installXcode.in:650-664
/branches/PR-7489777/darwinbuild/installXcode.in:676-731
/branches/PR-7529688/darwinbuild/installXcode.in:692-694
/branches/PR-7593824/darwinbuild/installXcode.in:739-772
/branches/PR-7598640/darwinbuild/installXcode.in:703-731
Property changes on: trunk/darwinbuild/packageRoots.in
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/PR-4841388/darwinbuild/packageRoots.sh:399-419
/branches/PR-6358021/darwinbuild/packageRoots.sh:442-443
/branches/PR-6392966/darwinbuild/packageRoots.sh:423-427
/branches/PR-6398060/darwinbuild/packageRoots.sh:433-434
/branches/PR-6493844/darwinbuild/packageRoots.sh.in:460-461
/branches/PR-6497694/darwinbuild/packageRoots.sh.in:466-468,471
/branches/PR-6634286/darwinbuild/packageRoots.in:632-650
/branches/PR-6688645/darwinbuild/packageRoots.sh.in:479-490
/branches/PR-6722857/darwinbuild/packageRoots.sh.in:495-499
/branches/PR-6729491/darwinbuild/packageRoots.in:655-664
/branches/PR-7250612/darwinbuild/packageRoots.in:635-650
/branches/PR-7341154/darwinbuild/packageRoots.in:682-694
/branches/PR-7431723/darwinbuild/packageRoots.in:660-664
/branches/PR-7461534/darwinbuild/packageRoots.in:650-664
/branches/PR-7489777/darwinbuild/packageRoots.in:676-731
/branches/PR-7529688/darwinbuild/packageRoots.in:692-694
/branches/PR-7598640/darwinbuild/packageRoots.in:703-731
/trunk/darwinbuild/packageRoots.sh:432-434
+ /branches/PR-4841388/darwinbuild/packageRoots.sh:399-419
/branches/PR-6358021/darwinbuild/packageRoots.sh:442-443
/branches/PR-6392966/darwinbuild/packageRoots.sh:423-427
/branches/PR-6398060/darwinbuild/packageRoots.sh:433-434
/branches/PR-6493844/darwinbuild/packageRoots.sh.in:460-461
/branches/PR-6497694/darwinbuild/packageRoots.sh.in:466-468,471
/branches/PR-6634286/darwinbuild/packageRoots.in:632-650
/branches/PR-6688645/darwinbuild/packageRoots.sh.in:479-490
/branches/PR-6722857/darwinbuild/packageRoots.sh.in:495-499
/branches/PR-6729491/darwinbuild/packageRoots.in:655-664
/branches/PR-7250612/darwinbuild/packageRoots.in:635-650
/branches/PR-7341154/darwinbuild/packageRoots.in:682-694
/branches/PR-7431723/darwinbuild/packageRoots.in:660-664
/branches/PR-7461534/darwinbuild/packageRoots.in:650-664
/branches/PR-7489777/darwinbuild/packageRoots.in:676-731
/branches/PR-7529688/darwinbuild/packageRoots.in:692-694
/branches/PR-7593824/darwinbuild/packageRoots.in:739-772
/branches/PR-7598640/darwinbuild/packageRoots.in:703-731
Property changes on: trunk/darwinbuild/thinPackages.in
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/PR-4841388/darwinbuild/thinPackages.sh:399-419
/branches/PR-6358021/darwinbuild/thinPackages.sh:442-443
/branches/PR-6392966/darwinbuild/thinPackages.sh:423-427
/branches/PR-6398060/darwinbuild/thinPackages.sh:433-434
/branches/PR-6493844/darwinbuild/thinPackages.sh.in:460-461
/branches/PR-6497694/darwinbuild/thinPackages.sh.in:466-468,471
/branches/PR-6634286/darwinbuild/thinPackages.in:632-650
/branches/PR-6688645/darwinbuild/thinPackages.sh.in:479-490
/branches/PR-6722857/darwinbuild/thinPackages.sh.in:495-499
/branches/PR-6729491/darwinbuild/thinPackages.in:655-664
/branches/PR-7250612/darwinbuild/thinPackages.in:635-650
/branches/PR-7341154/darwinbuild/thinPackages.in:682-694
/branches/PR-7431723/darwinbuild/thinPackages.in:660-664
/branches/PR-7461534/darwinbuild/thinPackages.in:650-664
/branches/PR-7489777/darwinbuild/thinPackages.in:676-731
/branches/PR-7529688/darwinbuild/thinPackages.in:692-694
/branches/PR-7598640/darwinbuild/thinPackages.in:703-731
/trunk/darwinbuild/thinPackages.sh:432-434
+ /branches/PR-4841388/darwinbuild/thinPackages.sh:399-419
/branches/PR-6358021/darwinbuild/thinPackages.sh:442-443
/branches/PR-6392966/darwinbuild/thinPackages.sh:423-427
/branches/PR-6398060/darwinbuild/thinPackages.sh:433-434
/branches/PR-6493844/darwinbuild/thinPackages.sh.in:460-461
/branches/PR-6497694/darwinbuild/thinPackages.sh.in:466-468,471
/branches/PR-6634286/darwinbuild/thinPackages.in:632-650
/branches/PR-6688645/darwinbuild/thinPackages.sh.in:479-490
/branches/PR-6722857/darwinbuild/thinPackages.sh.in:495-499
/branches/PR-6729491/darwinbuild/thinPackages.in:655-664
/branches/PR-7250612/darwinbuild/thinPackages.in:635-650
/branches/PR-7341154/darwinbuild/thinPackages.in:682-694
/branches/PR-7431723/darwinbuild/thinPackages.in:660-664
/branches/PR-7461534/darwinbuild/thinPackages.in:650-664
/branches/PR-7489777/darwinbuild/thinPackages.in:676-731
/branches/PR-7529688/darwinbuild/thinPackages.in:692-694
/branches/PR-7593824/darwinbuild/thinPackages.in:739-772
/branches/PR-7598640/darwinbuild/thinPackages.in:703-731
Modified: trunk/darwinup/Archive.cpp
===================================================================
--- trunk/darwinup/Archive.cpp 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Archive.cpp 2010-03-12 22:20:40 UTC (rev 773)
@@ -53,11 +53,13 @@
m_date_installed = time(NULL);
}
-Archive::Archive(uint64_t serial, uuid_t uuid, const char* name, const char* path, uint64_t info, time_t date_installed) {
+Archive::Archive(uint64_t serial, uuid_t uuid, const char* name, const char* path,
+ uint64_t info, time_t date_installed, const char* build) {
m_serial = serial;
uuid_copy(m_uuid, uuid);
m_name = name ? strdup(name) : NULL;
m_path = path ? strdup(path) : NULL;
+ m_build = build ? strdup(build) : NULL;
m_info = info;
m_date_installed = date_installed;
}
@@ -66,12 +68,14 @@
Archive::~Archive() {
if (m_path) free(m_path);
if (m_name) free(m_name);
+ if (m_build) free(m_build);
}
uint64_t Archive::serial() { return m_serial; }
uint8_t* Archive::uuid() { return m_uuid; }
const char* Archive::name() { return m_name; }
const char* Archive::path() { return m_path; }
+const char* Archive::build() { return m_build; }
uint64_t Archive::info() { return m_info; }
time_t Archive::date_installed() { return m_date_installed; }
Modified: trunk/darwinup/Archive.h
===================================================================
--- trunk/darwinup/Archive.h 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Archive.h 2010-03-12 22:20:40 UTC (rev 773)
@@ -97,13 +97,16 @@
// Do not modify or free(3).
virtual const char* path();
+ // the OS build this archive was installed onto
+ virtual const char* build();
+
// ARCHIVE_INFO flags.
virtual uint64_t info();
// The epoch seconds when the archive was installed.
virtual time_t date_installed();
-
-
+
+
////
// Member functions
////
@@ -130,13 +133,16 @@
protected:
- // 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);
+ // 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, const char* build);
uint64_t m_serial;
uuid_t m_uuid;
char* m_name;
char* m_path;
+ char* m_build;
uint64_t m_info;
time_t m_date_installed;
Modified: trunk/darwinup/Column.cpp
===================================================================
--- trunk/darwinup/Column.cpp 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Column.cpp 2010-03-12 22:20:40 UTC (rev 773)
@@ -39,25 +39,30 @@
Column::Column(const char* name, uint32_t type) {
m_name = strdup(name);
m_create_sql = NULL;
+ m_alter_sql = NULL;
m_type = type;
m_is_index = false;
m_is_pk = false;
m_is_unique = false;
+ m_version = 0;
}
Column::Column(const char* name, uint32_t type,
bool is_index, bool is_pk, bool is_unique) {
m_name = strdup(name);
m_create_sql = NULL;
+ m_alter_sql = NULL;
m_type = type;
m_is_index = is_index;
m_is_pk = is_pk;
m_is_unique = is_unique;
+ m_version = 0;
}
Column::~Column() {
free(m_name);
free(m_create_sql);
+ free(m_alter_sql);
}
const char* Column::name() {
@@ -80,6 +85,9 @@
return m_is_unique;
}
+uint32_t Column::version() {
+ return m_version;
+}
const char* Column::typestr() {
switch(m_type) {
@@ -117,3 +125,12 @@
}
return (const char*)m_create_sql;
}
+
+const char* Column::alter(const char* table_name) {
+ if (!m_alter_sql) {
+ asprintf(&m_alter_sql, "ALTER TABLE %s ADD COLUMN %s;",
+ table_name, this->create());
+ }
+ return (const char*)m_alter_sql;
+}
+
Modified: trunk/darwinup/Column.h
===================================================================
--- trunk/darwinup/Column.h 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Column.h 2010-03-12 22:20:40 UTC (rev 773)
@@ -55,6 +55,8 @@
const bool is_pk();
const bool is_unique();
+ uint32_t version();
+
// return size of this column when packed into a result record
uint32_t size();
@@ -68,9 +70,13 @@
// generate the sql needed to create this column
const char* create();
+ // generate alter table sql for this column for table named table_name
+ const char* alter(const char* table_name);
char* m_name;
- char* m_create_sql;
+ uint32_t m_version; // schema version this was added
+ char* m_create_sql; // sql fragment for use in CREATE TABLE
+ char* m_alter_sql; // entire ALTER TABLE ADD COLUMN sql
uint32_t m_type; // SQLITE_* type definition
bool m_is_index;
bool m_is_pk;
Modified: trunk/darwinup/DB.cpp
===================================================================
--- trunk/darwinup/DB.cpp 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/DB.cpp 2010-03-12 22:20:40 UTC (rev 773)
@@ -35,23 +35,32 @@
DarwinupDatabase::DarwinupDatabase(const char* path) : Database(path) {
this->connect();
+ this->last_archive = NULL;
}
DarwinupDatabase::~DarwinupDatabase() {
// parent automatically deallocates schema objects
+
+ if (this->last_archive) delete this->last_archive;
}
-void DarwinupDatabase::init_schema() {
+int DarwinupDatabase::init_schema() {
+
+
+ SCHEMA_VERSION(0);
+
this->m_archives_table = new Table("archives");
+ ADD_TABLE(this->m_archives_table);
ADD_PK(m_archives_table, "serial");
ADD_INDEX(m_archives_table, "uuid", TYPE_BLOB, true);
ADD_TEXT(m_archives_table, "name");
ADD_INTEGER(m_archives_table, "date_added");
ADD_INTEGER(m_archives_table, "active");
ADD_INTEGER(m_archives_table, "info");
- assert(this->add_table(this->m_archives_table)==0);
+
this->m_files_table = new Table("files");
+ ADD_TABLE(this->m_files_table);
ADD_PK(m_files_table, "serial");
ADD_INDEX(m_files_table, "archive", TYPE_INTEGER, false);
ADD_INTEGER(m_files_table, "info");
@@ -61,10 +70,17 @@
ADD_INTEGER(m_files_table, "size");
ADD_BLOB(m_files_table, "digest");
ADD_INDEX(m_files_table, "path", TYPE_TEXT, false);
+
// custom index to protect from duplicate files
assert(this->m_files_table->set_custom_create("CREATE UNIQUE INDEX files_archive_path "
"ON files (archive, path);") == 0);
- assert(this->add_table(this->m_files_table)==0);
+
+
+ SCHEMA_VERSION(1);
+
+ ADD_TEXT(m_archives_table, "osbuild");
+
+ return 0;
}
int DarwinupDatabase::activate_archive(uint64_t serial) {
@@ -78,6 +94,7 @@
}
int DarwinupDatabase::set_archive_active(uint64_t serial, uint64_t* active) {
+ this->clear_last_archive();
return this->update_value("activate_archive",
this->m_archives_table,
this->m_archives_table->column(4), // active
@@ -89,6 +106,7 @@
int DarwinupDatabase::update_archive(uint64_t serial, uuid_t uuid, const char* name,
time_t date_added, uint32_t active, uint32_t info) {
+ this->clear_last_archive();
return this->update(this->m_archives_table, serial,
(uint8_t*)uuid,
(uint32_t)sizeof(uuid_t),
@@ -99,7 +117,7 @@
}
uint64_t DarwinupDatabase::insert_archive(uuid_t uuid, uint32_t info, const char* name,
- time_t date_added) {
+ time_t date_added, const char* build) {
int res = this->insert(this->m_archives_table,
(uint8_t*)uuid,
@@ -107,7 +125,8 @@
name,
(uint64_t)date_added,
(uint64_t)0,
- (uint64_t)info);
+ (uint64_t)info,
+ build);
if (res != SQLITE_OK) {
fprintf(stderr, "Error: unable to insert archive %s: %s \n",
name, this->error());
@@ -146,17 +165,23 @@
char* path;
memcpy(&path, &data[this->file_offset(8)], sizeof(char*));
- uint8_t* archive_data;
- int res = this->get_archive(&archive_data, archive_serial);
- Archive* archive = NULL;
- if (FOUND(res)) {
- archive = this->make_archive(archive_data);
+ // get archive, which may be stored in last_archive
+ int res = DB_OK;
+ bool cached = false;
+ Archive* archive = this->get_last_archive(archive_serial);
+ if (archive) {
+ cached = true;
} else {
+ uint8_t* archive_data;
+ res = this->get_archive(&archive_data, archive_serial);
+ this->set_last_archive(archive_data);
+ archive = this->last_archive;
+ }
+ if (!archive) {
fprintf(stderr, "Error: DB::make_file could not find the archive for file: %s: %d \n", path, res);
return NULL;
}
- this->m_archives_table->free_result(archive_data);
-
+
File* result = FileFactory(serial, archive, info, (const char*)path, mode, uid, gid, size, digest);
this->m_files_table->free_result(data);
@@ -318,6 +343,10 @@
return DB_OK;
}
+int DarwinupDatabase::free_archive(uint8_t* data) {
+ return this->m_archives_table->free_result(data);
+}
+
int DarwinupDatabase::delete_file(File* file) {
int res = this->del(this->m_files_table, file->serial());
if (res != SQLITE_OK) return DB_ERROR;
@@ -340,6 +369,9 @@
return DB_OK;
}
+int DarwinupDatabase::free_file(uint8_t* data) {
+ return this->m_files_table->free_result(data);
+}
int DarwinupDatabase::get_inactive_archive_serials(uint64_t** serials, uint32_t* count) {
int res = this->get_column("inactive_archive_serials",
@@ -392,9 +424,12 @@
memcpy(&date_added, &data[this->archive_offset(3)], sizeof(time_t));
uint64_t info;
memcpy(&info, &data[this->archive_offset(5)], sizeof(uint64_t));
+ char* build;
+ memcpy(&build, &data[this->archive_offset(6)], sizeof(char*));
- Archive* archive = new Archive(serial, *uuid, name, NULL, info, date_added);
+ Archive* archive = new Archive(serial, *uuid, name, NULL, info, date_added, build);
this->m_archives_table->free_result(data);
+
return archive;
}
@@ -402,7 +437,7 @@
int res = this->get_all_ordered("get_archives",
data, count,
this->m_archives_table,
- this->m_archives_table->column(0), // order by path
+ this->m_archives_table->column(0), // order by serial
ORDER_BY_DESC,
1,
this->m_archives_table->column(2), // name
@@ -425,7 +460,6 @@
return DB_ERROR;
}
-// XXX: get_archive gets called repeatedly by make_file, should memoize
int DarwinupDatabase::get_archive(uint8_t** data, uint64_t serial) {
int res = this->get_row("archive__serial",
data,
@@ -433,7 +467,9 @@
1,
this->m_archives_table->column(0), // serial
'=', serial);
- if (res == SQLITE_ROW) return (DB_FOUND | DB_OK);
+ if (res == SQLITE_ROW) {
+ return (DB_FOUND | DB_OK);
+ }
if (res == SQLITE_DONE) return DB_OK;
return DB_ERROR;
}
@@ -453,12 +489,14 @@
int DarwinupDatabase::get_archive(uint8_t** data, archive_keyword_t keyword) {
int res = SQLITE_OK;
int order = ORDER_BY_DESC;
+ const char* name = "archive_newest";
if (keyword == DEPOT_ARCHIVE_OLDEST) {
order = ORDER_BY_ASC;
+ name = "archive_oldest";
}
- res = this->get_row_ordered("archive__keyword",
+ res = this->get_row_ordered(name,
data,
this->m_archives_table,
this->m_archives_table->column(3), // order by date_added
@@ -479,3 +517,22 @@
int DarwinupDatabase::file_offset(int column) {
return this->m_files_table->offset(column);
}
+
+Archive* DarwinupDatabase::get_last_archive(uint64_t serial) {
+ if (this->last_archive && this->last_archive->serial() == serial) {
+ return this->last_archive;
+ }
+ return NULL;
+}
+
+int DarwinupDatabase::clear_last_archive() {
+ delete this->last_archive;
+ this->last_archive = NULL;
+ return 0;
+}
+
+int DarwinupDatabase::set_last_archive(uint8_t* data) {
+ this->last_archive = this->make_archive(data);
+ if (this->last_archive) return 0;
+ return 1;
+}
Modified: trunk/darwinup/DB.h
===================================================================
--- trunk/darwinup/DB.h 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/DB.h 2010-03-12 22:20:40 UTC (rev 773)
@@ -56,7 +56,7 @@
struct DarwinupDatabase : Database {
DarwinupDatabase(const char* path);
virtual ~DarwinupDatabase();
- void init_schema();
+ int init_schema();
uint64_t count_files(Archive* archive, const char* path);
uint64_t count_archives(bool include_rollbacks);
@@ -74,16 +74,19 @@
int deactivate_archive(uint64_t serial);
int update_archive(uint64_t serial, uuid_t uuid, const char* name,
time_t date_added, uint32_t active, uint32_t info);
- uint64_t insert_archive(uuid_t uuid, uint32_t info, const char* name, time_t date);
+ uint64_t insert_archive(uuid_t uuid, uint32_t info, const char* name,
+ time_t date, const char* build);
int delete_empty_archives();
int delete_archive(Archive* archive);
int delete_archive(uint64_t serial);
+ int free_archive(uint8_t* data);
// Files
File* make_file(uint8_t* data);
int get_next_file(uint8_t** data, File* file, file_starseded_t star);
int get_file_serials(uint64_t** serials, uint32_t* count);
- int get_file_serial_from_archive(Archive* archive, const char* path, uint64_t** serial);
+ int get_file_serial_from_archive(Archive* archive, const char* path,
+ uint64_t** serial);
int get_files(uint8_t*** data, uint32_t* count, Archive* archive);
int file_offset(int column);
int update_file(uint64_t serial, Archive* archive, uint32_t info, mode_t mode,
@@ -93,7 +96,13 @@
int delete_file(uint64_t serial);
int delete_file(File* file);
int delete_files(Archive* archive);
+ int free_file(uint8_t* data);
+ // memoization
+ Archive* get_last_archive(uint64_t serial);
+ int clear_last_archive();
+ int set_last_archive(uint8_t* data);
+
protected:
@@ -102,6 +111,9 @@
Table* m_archives_table;
Table* m_files_table;
+ // memoize some get_archive calls
+ Archive* last_archive;
+
};
#endif
Modified: trunk/darwinup/Database.cpp
===================================================================
--- trunk/darwinup/Database.cpp 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Database.cpp 2010-03-12 22:20:40 UTC (rev 773)
@@ -36,10 +36,11 @@
* sqlite3_trace callback for debugging
*/
void dbtrace(void* context, const char* sql) {
- IF_DEBUG("[TRACE] %s \n", sql);
+ fprintf(stderr, "[SQL] %s\n", sql);
}
Database::Database() {
+ m_schema_version = 0;
m_table_max = 2;
m_table_count = 0;
m_tables = (Table**)malloc(sizeof(Table*) * m_table_max);
@@ -51,6 +52,7 @@
}
Database::Database(const char* path) {
+ m_schema_version = 0;
m_table_max = 2;
m_table_count = 0;
m_tables = (Table**)malloc(sizeof(Table*) * m_table_max);
@@ -80,11 +82,24 @@
free(m_error);
}
+uint32_t Database::schema_version() {
+ return this->m_schema_version;
+}
-void Database::init_schema() {
+void Database::schema_version(uint32_t v) {
+ this->m_schema_version = v;
+}
+
+int Database::init_schema() {
// do nothing... children should implement this
+ return DB_OK;
}
+int Database::post_table_creation() {
+ // clients can implement this
+ return DB_OK;
+}
+
const char* Database::path() {
return m_path;
}
@@ -94,12 +109,20 @@
}
int Database::connect() {
+ int res = DB_OK;
+
if (!m_path) {
fprintf(stderr, "Error: need to specify a path to Database.\n");
return -1;
}
- int res = SQLITE_OK;
- this->init_schema();
+
+ res = this->pre_connect();
+ if (res) {
+ fprintf(stderr, "Error: pre-connection failed.\n");
+ return res;
+ }
+
+ int exists = is_regular_file(m_path);
res = sqlite3_open(m_path, &m_db);
if (res) {
sqlite3_close(m_db);
@@ -107,24 +130,67 @@
fprintf(stderr, "Error: unable to connect to database at: %s \n",
m_path);
return res;
- }
- sqlite3_trace(m_db, dbtrace, NULL);
- if (this->is_empty()) {
+ }
+
+ res = this->post_connect();
+ if (res) {
+ fprintf(stderr, "Error: post-connection failed.\n");
+ return res;
+ }
+
+ if (!exists) {
+ // create schema since it is empty
assert(this->create_tables() == 0);
+ assert(this->set_schema_version(this->m_schema_version) == 0);
+ } else {
+ // test schema versions
+ uint32_t version = 0;
+ if (this->has_information_table()) {
+ version = this->get_schema_version();
+ }
+
+ if (version < this->m_schema_version) {
+ IF_DEBUG("Upgrading schema from %u to %u \n", version, this->m_schema_version);
+ assert(this->upgrade_schema(version) == 0);
+ assert(this->set_schema_version(this->m_schema_version) == 0);
+ }
+ if (version > this->m_schema_version) {
+ fprintf(stderr, "Error: this client is too old!\n");
+ return DB_ERROR;
+ }
}
+ return res;
+}
+
+int Database::pre_connect() {
+ int res = DB_OK;
+ res = this->init_internal_schema();
+ res = this->init_schema();
+ return res;
+}
+
+int Database::post_connect() {
+ int res = DB_OK;
+
// prepare transaction statements
- if (res == SQLITE_OK)
+ if (res == DB_OK)
res = sqlite3_prepare_v2(m_db, "BEGIN TRANSACTION", 18,
&m_begin_transaction, NULL);
- if (res == SQLITE_OK)
+ if (res == DB_OK)
res = sqlite3_prepare_v2(m_db, "ROLLBACK TRANSACTION", 21,
&m_rollback_transaction, NULL);
- if (res == SQLITE_OK)
+ if (res == DB_OK)
res = sqlite3_prepare_v2(m_db, "COMMIT TRANSACTION", 19,
- &m_commit_transaction, NULL);
-
- return res;
+ &m_commit_transaction, NULL);
+
+ // debug settings
+ extern uint32_t verbosity;
+ if (verbosity & VERBOSE_SQL) {
+ sqlite3_trace(m_db, dbtrace, NULL);
+ }
+
+ return res;
}
int Database::connect(const char* path) {
@@ -550,6 +616,7 @@
m_table_max *= REALLOC_FACTOR;
}
m_tables[m_table_count++] = t;
+ t->m_version = this->m_schema_version;
return 0;
}
@@ -571,6 +638,16 @@
return res != SQLITE_OK;
}
+int Database::create_table(Table* table) {
+ int res = this->sql_once(table->create());
+ if (res != DB_OK) {
+ fprintf(stderr, "Error: sql error trying to create"
+ " table: %s: %s\n",
+ table->name(), m_error);
+ }
+ return res;
+}
+
int Database::create_tables() {
int res = SQLITE_OK;
for (uint32_t i=0; i<m_table_count; i++) {
@@ -581,9 +658,150 @@
return res;
}
}
+ if (res == DB_OK) res = this->initial_data();
+ if (res == DB_OK) res = this->post_table_creation();
return res;
}
+int Database::upgrade_schema(uint32_t version) {
+ int res = DB_OK;
+ this->begin_transaction();
+
+ res = this->upgrade_internal_schema(version);
+ if (res != DB_OK) {
+ fprintf(stderr, "Error: unable to upgrade internal schema.\n");
+ this->rollback_transaction();
+ return res;
+ }
+
+ for (uint32_t ti = 0; res == DB_OK && ti < m_table_count; ti++) {
+ if (m_tables[ti]->version() > version) {
+ // entire table is new
+ res = this->create_table(m_tables[ti]);
+ } else {
+ // table is same version, so check for new columns
+ for (uint32_t ci = 0; res == DB_OK && ci < m_tables[ti]->column_count(); ci++) {
+ if (m_tables[ti]->column(ci)->version() < version) {
+ // this should never happen
+ fprintf(stderr, "Error: internal error with schema versioning."
+ " Column %s is older than its table %s. \n",
+ m_tables[ti]->column(ci)->name(), m_tables[ti]->name());
+ }
+ if (m_tables[ti]->column(ci)->version() > version) {
+ // column is new
+ res = this->sql_once(m_tables[ti]->alter_add_column(ci));
+ if (res != DB_OK) {
+ fprintf(stderr, "Error: sql error trying to upgrade (alter)"
+ " table: %s column: %s : %s\n",
+ m_tables[ti]->name(), m_tables[ti]->column(ci)->name(),
+ m_error);
+ }
+ }
+ }
+ }
+ }
+
+ if (res == DB_OK) {
+ this->commit_transaction();
+ } else {
+ this->rollback_transaction();
+ }
+
+ return res;
+}
+
+int Database::upgrade_internal_schema(uint32_t version) {
+ int res = DB_OK;
+
+ if (version == 0) {
+ res = this->sql_once(this->m_information_table->create());
+ }
+
+ return res;
+}
+
+int Database::init_internal_schema() {
+ this->m_information_table = new Table("database_information");
+ ADD_TABLE(this->m_information_table);
+ ADD_PK(m_information_table, "id");
+ ADD_INDEX(m_information_table, "variable", TYPE_TEXT, true);
+ ADD_TEXT(m_information_table, "value");
+ return DB_OK;
+}
+
+int Database::initial_data() {
+ // load our initial config data
+ return this->insert(m_information_table, "schema_version", "0");
+}
+
+int Database::get_information_value(const char* variable, char*** value) {
+ return this->get_value("get_information_value",
+ (void**)value,
+ this->m_information_table,
+ this->m_information_table->column(2), // value
+ 1,
+ this->m_information_table->column(1), // variable
+ '=', variable);
+}
+
+int Database::update_information_value(const char* variable, const char* value) {
+ int res = SQLITE_OK;
+ uint64_t* c;
+ res = this->count("count_info_var",
+ (void**)&c,
+ this->m_information_table,
+ 1,
+ this->m_information_table->column(1), // variable
+ '=', variable);
+
+ if (*c > 0) {
+ res = this->update_value("update_information_value",
+ this->m_information_table,
+ this->m_information_table->column(2), // value
+ (void**)&value,
+ 1,
+ this->m_information_table->column(1), // variable
+ '=', variable);
+ } else {
+ res = this->insert(m_information_table, variable, value);
+ }
+
+ return res;
+}
+
+bool Database::has_information_table() {
+ int res = sqlite3_exec(this->m_db,
+ "SELECT count(*) FROM database_information;",
+ NULL, NULL, NULL);
+ return res == SQLITE_OK;
+}
+
+uint32_t Database::get_schema_version() {
+ int res = SQLITE_OK;
+ char** vertxt = NULL;
+ res = this->get_information_value("schema_version", &vertxt);
+ if (res == SQLITE_ROW) {
+ uint32_t version = (uint32_t)strtoul(*vertxt, NULL, 10);
+ free(*vertxt);
+ return version;
+ } else {
+ // lack of information table/value means we are
+ // upgrading an old database
+ return 0;
+ }
+}
+
+int Database::set_schema_version(uint32_t version) {
+ IF_DEBUG("set_schema_version %u \n", version);
+ int res = DB_OK;
+ char* vertxt;
+ asprintf(&vertxt, "%u", version);
+ if (!vertxt) return DB_ERROR;
+ res = this->update_information_value("schema_version", vertxt);
+ free(vertxt);
+ return res;
+}
+
size_t Database::store_column(sqlite3_stmt* stmt, int column, uint8_t* output) {
size_t used;
int type = sqlite3_column_type(stmt, column);
@@ -643,7 +861,7 @@
*used = current - output;
}
}
-
+
return res;
}
Modified: trunk/darwinup/Database.h
===================================================================
--- trunk/darwinup/Database.h 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Database.h 2010-03-12 22:20:40 UTC (rev 773)
@@ -67,19 +67,21 @@
#define FOUND(x) ((x & DB_FOUND) && !(x & DB_ERROR))
// Schema creation macros
+#define SCHEMA_VERSION(v) this->schema_version(v);
+#define ADD_TABLE(t) assert(this->add_table(t)==0);
#define ADD_COLUMN(table, name, type, index, pk, unique) \
- assert(table->add_column(new Column(name, type, index, pk, unique))==0);
+ assert(table->add_column(new Column(name, type, index, pk, unique), this->schema_version())==0);
#define ADD_INDEX(table, name, type, unique) \
- assert(table->add_column(new Column(name, type, true, false, unique))==0);
+ assert(table->add_column(new Column(name, type, true, false, unique), this->schema_version())==0);
#define ADD_PK(table, name) \
assert(table->add_column(new Column(name, TYPE_INTEGER, \
- false, true, false))==0);
+ false, true, false), this->schema_version())==0);
#define ADD_TEXT(table, name) \
- assert(table->add_column(new Column(name, TYPE_TEXT))==0);
+ assert(table->add_column(new Column(name, TYPE_TEXT), this->schema_version())==0);
#define ADD_INTEGER(table, name) \
- assert(table->add_column(new Column(name, TYPE_INTEGER))==0);
+ assert(table->add_column(new Column(name, TYPE_INTEGER), this->schema_version())==0);
#define ADD_BLOB(table, name) \
- assert(table->add_column(new Column(name, TYPE_BLOB))==0);
+ assert(table->add_column(new Column(name, TYPE_BLOB), this->schema_version())==0);
/**
@@ -92,14 +94,22 @@
Database(const char* path);
virtual ~Database();
+ // public setter/getter of class attr
+ uint32_t schema_version();
+ void schema_version(uint32_t v);
+
/**
* init_schema is called during db connection.
* Projects implementing a Database derived class
* should use Table::add_column() or the ADD_*
* macros in their init_schema() to define their schema
*/
- virtual void init_schema();
+ virtual int init_schema();
+ // called after tables are created so clients can load
+ // initial sets of data
+ virtual int post_table_creation();
+
const char* path();
const char* error();
int connect();
@@ -168,17 +178,38 @@
protected:
+ // pre- and post- connection work
+ int pre_connect();
+ int post_connect();
+
+ int upgrade_schema(uint32_t version);
+ int upgrade_internal_schema(uint32_t version);
+ int init_internal_schema();
+ int initial_data();
+
+ int get_information_value(const char* variable, char*** value);
+ int update_information_value(const char* variable, const char* value);
+
+ // get and set version info in actual database
+ bool has_information_table();
+ uint32_t get_schema_version();
+ int set_schema_version(uint32_t version);
+
// execute query with printf-style format, does not cache statement
- int sql_once(const char* fmt, ...);
+ int sql_once(const char* fmt, ...);
// cache statement with name, execute query with printf-style format
- int sql(const char* name, const char* fmt, ...);
- int execute(sqlite3_stmt* stmt);
+ int sql(const char* name, const char* fmt, ...);
+ int execute(sqlite3_stmt* stmt);
- int add_table(Table*);
+ int add_table(Table*);
// test if database has had its tables created
bool is_empty();
+ // create tables for the client
+ int create_table(Table* table);
int create_tables();
+ // create tables for ourselves
+ int create_internal_tables();
// bind all table columns from va_list
int bind_all_columns(sqlite3_stmt* stmt, Table* table, va_list args);
@@ -201,7 +232,11 @@
char* m_path;
sqlite3* m_db;
-
+
+ uint32_t m_schema_version;
+ Table* m_information_table;
+ sqlite3_stmt* m_get_information_value;
+
Table** m_tables;
uint32_t m_table_count;
uint32_t m_table_max;
Modified: trunk/darwinup/Depot.cpp
===================================================================
--- trunk/darwinup/Depot.cpp 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Depot.cpp 2010-03-12 22:20:40 UTC (rev 773)
@@ -39,6 +39,7 @@
#include <copyfile.h>
#include <errno.h>
#include <fcntl.h>
+#include <grp.h>
#include <libgen.h>
#include <limits.h>
#include <stdio.h>
@@ -54,6 +55,7 @@
m_database_path = NULL;
m_archives_path = NULL;
m_downloads_path = NULL;
+ m_build = NULL;
m_db = NULL;
m_lock_fd = -1;
m_is_locked = 0;
@@ -64,6 +66,7 @@
m_lock_fd = -1;
m_is_locked = 0;
m_depot_mode = 0750;
+ m_build = NULL;
asprintf(&m_prefix, "%s", prefix);
join_path(&m_depot_path, m_prefix, "/.DarwinDepot");
@@ -100,18 +103,28 @@
}
int Depot::create_storage() {
+ uid_t uid = getuid();
+ struct group *gs = getgrnam("admin");
+ gid_t gid = gs->gr_gid;
+
int res = mkdir(m_depot_path, m_depot_mode);
+ res = chmod(m_depot_path, m_depot_mode);
+ res = chown(m_depot_path, uid, gid);
if (res && errno != EEXIST) {
perror(m_depot_path);
return res;
}
res = mkdir(m_archives_path, m_depot_mode);
+ res = chmod(m_archives_path, m_depot_mode);
+ res = chown(m_archives_path, uid, gid);
if (res && errno != EEXIST) {
perror(m_archives_path);
return res;
}
res = mkdir(m_downloads_path, m_depot_mode);
+ res = chmod(m_downloads_path, m_depot_mode);
+ res = chown(m_downloads_path, uid, gid);
if (res && errno != EEXIST) {
perror(m_downloads_path);
return res;
@@ -124,7 +137,8 @@
int res = 0;
// initialization requires all these paths to be set
- if (!(m_prefix && m_depot_path && m_database_path && m_archives_path && m_downloads_path)) {
+ if (!(m_prefix && m_depot_path && m_database_path &&
+ m_archives_path && m_downloads_path)) {
return -1;
}
@@ -138,14 +152,20 @@
if (res) return res;
res = this->lock(LOCK_SH);
if (res) return res;
- m_is_locked = 1;
+ m_is_locked = 1;
+ res = build_number_for_path(&m_build, m_prefix);
}
- int exists = is_regular_file(m_database_path);
- if (!exists && !writable) {
- // read-only mode requested but we have no database
- return -2;
+ struct stat sb;
+ res = stat(m_database_path, &sb);
+ if (!writable && res == -1 && (errno == ENOENT || errno == ENOTDIR)) {
+ // depot does not exist
+ return -2;
}
+ if (!writable && res == -1 && errno == EACCES) {
+ // permission denied
+ return -3;
+ }
res = this->connect();
@@ -256,7 +276,8 @@
if (archive) {
list[i] = archive;
} else {
- fprintf(stderr, "%s:%d: DB::make_archive returned NULL\n", __FILE__, __LINE__);
+ fprintf(stderr, "%s:%d: DB::make_archive returned NULL\n",
+ __FILE__, __LINE__);
res = -1;
break;
}
@@ -266,6 +287,37 @@
return list;
}
+Archive** Depot::get_superseded_archives(uint32_t* count) {
+ int res = DB_OK;
+ uint8_t** archlist;
+ res = this->m_db->get_archives(&archlist, count, false); // rollbacks cannot be superseded
+
+ Archive** list = (Archive**)malloc(sizeof(Archive*) * (*count));
+ if (!list) {
+ fprintf(stderr, "Error: ran out of memory in Depot::get_superseded_archives\n");
+ return NULL;
+ }
+
+ uint32_t i = 0;
+ uint32_t cur = i;
+ if (FOUND(res)) {
+ while (i < *count) {
+ Archive* archive = this->m_db->make_archive(archlist[i++]);
+ if (archive && this->is_superseded(archive)) {
+ list[cur++] = archive;
+ } else if (!archive) {
+ fprintf(stderr, "%s:%d: DB::make_archive returned NULL\n",
+ __FILE__, __LINE__);
+ res = -1;
+ break;
+ }
+ }
+ }
+ // adjust count based on our is_superseded filtering
+ *count = cur;
+ return list;
+}
+
uint64_t Depot::count_archives() {
extern uint32_t verbosity;
uint64_t c = this->m_db->count_archives((bool)(verbosity & VERBOSE_DEBUG));
@@ -308,7 +360,9 @@
}
-int Depot::analyze_stage(const char* path, Archive* archive, Archive* rollback, int* rollback_files) {
+int Depot::analyze_stage(const char* path, Archive* archive, Archive* rollback,
+ int* rollback_files) {
+ extern uint32_t dryrun;
int res = 0;
assert(archive != NULL);
assert(rollback != NULL);
@@ -336,7 +390,6 @@
char* actpath;
join_path(&actpath, this->prefix(), file->path());
File* actual = FileFactory(actpath);
-
File* preceding = this->file_preceded_by(file);
if (actual == NULL) {
@@ -394,6 +447,16 @@
}
}
}
+
+ // if file == actual, but actual != preceding, then an external
+ // process changed actual to be the same as what we are installing
+ // now (OS upgrade?). We do not need to save actual, but make
+ // a special state so the user knows what happened and does not
+ // get a ?.
+ if (actual_flags == FILE_INFO_IDENTICAL && preceding_flags != FILE_INFO_IDENTICAL) {
+ 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
@@ -417,9 +480,10 @@
join_path(&backup_dirpath, uuidpath, dir);
assert(backup_dirpath != NULL);
- res = mkdir_p(backup_dirpath);
+ 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);
+ fprintf(stderr, "%s:%d: %s: %s (%d)\n",
+ __FILE__, __LINE__, backup_dirpath, strerror(errno), errno);
} else {
res = 0;
}
@@ -433,7 +497,7 @@
*rollback_files += 1;
if (!this->has_file(rollback, actual)) {
IF_DEBUG("[analyze] insert rollback\n");
- res = this->insert(rollback, actual);
+ if (!dryrun) res = this->insert(rollback, actual);
}
assert(res == 0);
@@ -455,8 +519,9 @@
}
if (!this->has_file(rollback, parent)) {
- IF_DEBUG("[analyze] adding parent to rollback: %s \n", parent->path());
- res = this->insert(rollback, parent);
+ IF_DEBUG("[analyze] adding parent to rollback: %s \n",
+ parent->path());
+ if (!dryrun) res = this->insert(rollback, parent);
}
assert(res == 0);
pent = pent->fts_parent;
@@ -465,7 +530,7 @@
}
fprintf(stderr, "%c %s\n", state, file->path());
- res = this->insert(archive, file);
+ if (!dryrun) res = this->insert(archive, file);
assert(res == 0);
if (preceding && preceding != actual) delete preceding;
if (actual) delete actual;
@@ -543,7 +608,8 @@
IF_DEBUG("[backup] copyfile(%s, %s)\n", path, dstpath);
res = copyfile(path, dstpath, NULL, COPYFILE_ALL|COPYFILE_NOFOLLOW);
- if (res != 0) fprintf(stderr, "%s:%d: backup failed: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
+ if (res != 0) fprintf(stderr, "%s:%d: backup failed: %s: %s (%d)\n",
+ __FILE__, __LINE__, dstpath, strerror(errno), errno);
free(path);
free(dstpath);
free(uuidpath);
@@ -563,7 +629,8 @@
} else {
res = file->install_info(context->depot->m_prefix);
}
- if (res != 0) fprintf(stderr, "%s:%d: install failed: %s: %s (%d)\n", __FILE__, __LINE__, file->path(), strerror(errno), errno);
+ if (res != 0) fprintf(stderr, "%s:%d: install failed: %s: %s (%d)\n",
+ __FILE__, __LINE__, file->path(), strerror(errno), errno);
return res;
}
@@ -597,9 +664,15 @@
int Depot::install(Archive* archive) {
+ extern uint32_t dryrun;
int res = 0;
Archive* rollback = new RollbackArchive();
+ if (this->m_build) {
+ rollback->m_build = strdup(this->m_build);
+ archive->m_build = strdup(this->m_build);
+ }
+
assert(rollback != NULL);
assert(archive != NULL);
@@ -609,15 +682,15 @@
//
// The fun starts here
//
- if (res == 0) res = this->begin_transaction();
+ if (!dryrun && res == 0) res = this->begin_transaction();
//
// Insert the rollback archive before the new archive to install, thus keeping
// the chronology of the serial numbers correct. We may later choose to delete
// the rollback archive if we determine that it was not necessary.
//
- if (res == 0) res = this->insert(rollback);
- if (res == 0) res = this->insert(archive);
+ if (!dryrun && res == 0) res = this->insert(rollback);
+ if (!dryrun && res == 0) res = this->insert(archive);
//
// Create the stage directory and rollback backing store directories
@@ -627,7 +700,6 @@
char* rollback_path = rollback->create_directory(m_archives_path);
assert(rollback_path != NULL);
-
// Extract the archive into its backing store directory
if (res == 0) res = archive->extract(archive_path);
@@ -637,6 +709,16 @@
int rollback_files = 0;
if (res == 0) res = this->analyze_stage(archive_path, archive, rollback, &rollback_files);
+ // we can stop now if this is a dry run
+ if (dryrun) {
+ remove_directory(archive_path);
+ remove_directory(rollback_path);
+ free(rollback_path);
+ free(archive_path);
+ (void)this->lock(LOCK_SH);
+ return res;
+ }
+
// If no files were added to the rollback archive, delete the rollback archive.
if (res == 0 && rollback_files == 0) {
res = this->remove(rollback);
@@ -713,13 +795,30 @@
return res;
}
-int Depot::prune_archives() {
+// delete the unexpanded tarball from archives storage
+int Depot::prune_archive(Archive* archive) {
int res = 0;
+
+ // clean up database
res = this->m_db->delete_empty_archives();
+ if (res) {
+ fprintf(stderr, "Error: unable to prune archives from database.\n");
+ return res;
+ }
+
+ // clean up disk
+ char path[PATH_MAX];
+ char uuid[37];
+ uuid_unparse_upper(archive->uuid(), uuid);
+ if (res == 0) snprintf(path, PATH_MAX, "%s/%s.tar.bz2", m_archives_path, uuid);
+ if (res == 0) res = unlink(path);
+ if (res) perror(path);
+
return res;
}
int Depot::uninstall_file(File* file, void* ctx) {
+ extern uint32_t dryrun;
InstallContext* context = (InstallContext*)ctx;
int res = 0;
char state = ' ';
@@ -737,9 +836,12 @@
IF_DEBUG("[uninstall] actual path is %s\n", actpath);
File* actual = FileFactory(actpath);
uint32_t flags = File::compare(file, actual);
-
- if (actual != NULL && flags != FILE_INFO_IDENTICAL) {
- // XXX: probably not the desired behavior
+
+ if (actual == NULL) {
+ IF_DEBUG("[uninstall] actual file missing, "
+ "possibly due to parent being removed already\n");
+ state = '!';
+ } else if (flags != FILE_INFO_IDENTICAL) {
IF_DEBUG("[uninstall] changes since install; skipping\n");
} else {
File* superseded = context->depot->file_superseded_by(file);
@@ -750,7 +852,7 @@
if (INFO_TEST(preceding->info(), FILE_INFO_NO_ENTRY)) {
state = 'R';
IF_DEBUG("[uninstall] removing file\n");
- if (actual && res == 0) res = actual->remove();
+ if (!dryrun && actual && res == 0) res = actual->remove();
} else {
// copy the preceding file back out to the system
// if it's different from what's already there
@@ -758,11 +860,17 @@
if (INFO_TEST(flags, FILE_INFO_DATA_DIFFERS)) {
state = 'U';
IF_DEBUG("[uninstall] restoring\n");
- if (res == 0) res = preceding->install(context->depot->m_archives_path, context->depot->m_prefix);
+ if (!dryrun && res == 0) {
+ 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) ||
INFO_TEST(flags, FILE_INFO_UID_DIFFERS)) {
- if (res == 0) res = preceding->install_info(context->depot->m_prefix);
+ state = 'M';
+ if (!dryrun && res == 0) {
+ res = preceding->install_info(context->depot->m_prefix);
+ }
} else {
IF_DEBUG("[uninstall] no changes; leaving in place\n");
}
@@ -770,7 +878,9 @@
uint32_t info = preceding->info();
if (INFO_TEST(info, FILE_INFO_NO_ENTRY | FILE_INFO_ROLLBACK_DATA) &&
!INFO_TEST(info, FILE_INFO_BASE_SYSTEM)) {
- if (res == 0) res = context->files_to_remove->add(preceding->serial());
+ if (!dryrun && res == 0) {
+ res = context->files_to_remove->add(preceding->serial());
+ }
}
delete preceding;
} else {
@@ -781,7 +891,8 @@
fprintf(stderr, "%c %s\n", state, file->path());
- if (res != 0) fprintf(stderr, "%s:%d: uninstall failed: %s\n", __FILE__, __LINE__, file->path());
+ if (res != 0) fprintf(stderr, "%s:%d: uninstall failed: %s\n",
+ __FILE__, __LINE__, file->path());
free(actpath);
return res;
@@ -789,6 +900,8 @@
int Depot::uninstall(Archive* archive) {
extern uint32_t verbosity;
+ extern uint32_t force;
+ extern uint32_t dryrun;
int res = 0;
assert(archive != NULL);
@@ -804,38 +917,67 @@
return -1;
}
+ /**
+ * require -f to force uninstalling an archive installed on top of an older
+ * base system since the rollback archive we'll use will potentially damage
+ * the base system.
+ */
+ if (!force &&
+ this->m_build &&
+ archive->build() &&
+ (strcmp(this->m_build, archive->build()) != 0)) {
+ fprintf(stderr,
+ "-------------------------------------------------------------------------------\n"
+ "The %s root was installed on a different base OS build (%s). The current \n"
+ "OS build is %s. Uninstalling a root that was installed on a different OS \n"
+ "build has the potential to damage your OS install due to the fact that the \n"
+ "rollback data is from the wrong OS version.\n\n"
+ " You must use the force (-f) option to make this potentially unsafe operation \n"
+ "happen.\n"
+ "-------------------------------------------------------------------------------\n",
+ archive->name(), archive->build(), m_build);
+ return 9999;
+ }
+
res = this->lock(LOCK_EX);
if (res != 0) return res;
- // XXX: this may be superfluous
- // uninstall_file should be smart enough to do a mtime check...
- if (res == 0) res = this->prune_directories();
+ if (!dryrun) {
+ // XXX: this may be superfluous
+ // uninstall_file should be smart enough to do a mtime check...
+ if (res == 0) res = this->prune_directories();
- // We do this here to get an exclusive lock on the database.
- if (res == 0) res = this->begin_transaction();
- if (res == 0) res = m_db->deactivate_archive(serial);
- if (res == 0) res = this->commit_transaction();
-
+ // We do this here to get an exclusive lock on the database.
+ if (res == 0) res = this->begin_transaction();
+ if (res == 0) res = m_db->deactivate_archive(serial);
+ if (res == 0) res = this->commit_transaction();
+ }
+
InstallContext context(this, archive);
if (res == 0) res = this->iterate_files(archive, &Depot::uninstall_file, &context);
- if (res == 0) res = this->begin_transaction();
- uint32_t i;
- for (i = 0; i < context.files_to_remove->count; ++i) {
- uint64_t serial = context.files_to_remove->values[i];
- if (res == 0) res = m_db->delete_file(serial);
- }
- if (res == 0) res = this->commit_transaction();
+ if (!dryrun) {
+ if (res == 0) res = this->begin_transaction();
+ uint32_t i;
+ for (i = 0; i < context.files_to_remove->count; ++i) {
+ uint64_t serial = context.files_to_remove->values[i];
+ if (res == 0) res = m_db->delete_file(serial);
+ }
+ if (res == 0) res = this->commit_transaction();
- if (res == 0) res = this->begin_transaction();
- if (res == 0) res = this->remove(archive);
- if (res == 0) res = this->commit_transaction();
+ if (res == 0) res = this->begin_transaction();
+ if (res == 0) res = this->remove(archive);
+ if (res == 0) res = this->commit_transaction();
- // delete all of the expanded archive backing stores to save disk space
- if (res == 0) res = this->prune_directories();
+ // delete all of the expanded archive backing stores to save disk space
+ if (res == 0) res = this->prune_directories();
- if (res == 0) res = prune_archives();
-
+ if (res == 0) res = this->prune_archive(archive);
+ }
+
+ if (res == 0) fprintf(stdout, "Uninstalled archive: %llu %s \n",
+ archive->serial(), archive->name());
+
(void)this->lock(LOCK_SH);
return res;
@@ -858,14 +1000,22 @@
return 0;
}
+void Depot::archive_header() {
+ fprintf(stdout, "%-6s %-36s %-12s %-7s %s\n",
+ "Serial", "UUID", "Date", "Build", "Name");
+ fprintf(stdout, "====== ==================================== "
+ "============ ======= =================\n");
+}
+
+
int Depot::verify(Archive* archive) {
int res = 0;
- fprintf(stdout, "%-6s %-36s %-23s %s\n", "Serial", "UUID", "Date Installed", "Name");
- fprintf(stdout, "====== ==================================== ======================= =================\n");
+ this->archive_header();
list_archive(archive, stdout);
- fprintf(stdout, "=======================================================================================\n");
+ hr();
if (res == 0) res = this->iterate_files(archive, &Depot::verify_file, NULL);
- fprintf(stdout, "=======================================================================================\n\n");
+ hr();
+ fprintf(stdout, "\n");
return res;
}
@@ -879,18 +1029,51 @@
struct tm local;
time_t seconds = archive->date_installed();
localtime_r(&seconds, &local);
- strftime(date, sizeof(date), "%F %T %Z", &local);
+ strftime(date, sizeof(date), "%b %e %H:%M", &local);
- fprintf((FILE*)context, "%-6llu %-36s %-23s %s\n", serial, uuid, date, archive->name());
+ fprintf((FILE*)context, "%-6llu %-36s %-12s %-7s %s\n",
+ serial, uuid, date, (archive->build()?archive->build():""), archive->name());
return 0;
}
int Depot::list() {
+ return this->list(0, NULL);
+}
+
+int Depot::list(int count, char** args) {
int res = 0;
- fprintf(stdout, "%-6s %-36s %-23s %s\n", "Serial", "UUID", "Date Installed", "Name");
- fprintf(stdout, "====== ==================================== ======================= =================\n");
- if (res == 0) res = this->iterate_archives(&Depot::list_archive, stdout);
+
+ this->archive_header();
+
+ // handle the default case of "all"
+ if (count == 0) return this->iterate_archives(&Depot::list_archive, stdout);
+
+ Archive** list;
+ Archive* archive;
+ uint32_t archcnt;
+ for (int i = 0; res == 0 && i < count; i++) {
+ list = NULL;
+ archive = NULL;
+ archcnt = 0;
+ // check for special keywords
+ if (strncasecmp(args[i], "all", 3) == 0) {
+ list = this->get_all_archives(&archcnt);
+ } else if (strncasecmp(args[i], "superseded", 10) == 0) {
+ list = this->get_superseded_archives(&archcnt);
+ }
+ if (archcnt) {
+ // loop over special keyword results
+ for (uint32_t j = 0; res == 0 && j < archcnt; j++) {
+ res = this->list_archive(list[j], stdout);
+ }
+ } else {
+ // arg is a single-archive specifier
+ archive = this->get_archive(args[i]);
+ if (archive) res = this->list_archive(archive, stdout);
+ }
+ }
+
return res;
}
@@ -903,12 +1086,12 @@
int Depot::files(Archive* archive) {
int res = 0;
- fprintf(stdout, "%-6s %-36s %-23s %s\n", "Serial", "UUID", "Date Installed", "Name");
- fprintf(stdout, "====== ==================================== ======================= =================\n");
+ this->archive_header();
list_archive(archive, stdout);
- fprintf(stdout, "=======================================================================================\n");
+ hr();
if (res == 0) res = this->iterate_files(archive, &Depot::print_file, stdout);
- fprintf(stdout, "=======================================================================================\n\n");
+ hr();
+ fprintf(stdout, "\n");
return res;
}
@@ -916,9 +1099,10 @@
Depot* depot = (Depot*)context;
int res = 0;
list_archive(archive, stdout);
- fprintf(stdout, "=======================================================================================\n");
+ hr();
if (res == 0) res = depot->iterate_files(archive, &Depot::print_file, stdout);
- fprintf(stdout, "=======================================================================================\n\n");
+ hr();
+ fprintf(stdout, "\n");
return res;
}
@@ -926,8 +1110,7 @@
extern uint32_t verbosity;
verbosity = 0xFFFFFFFF; // dump is intrinsically a debug command
int res = 0;
- fprintf(stdout, "%-6s %-36s %-23s %s\n", "Serial", "UUID", "Date Installed", "Name");
- fprintf(stdout, "====== ==================================== ======================= =================\n");
+ this->archive_header();
if (res == 0) res = this->iterate_archives(&Depot::dump_archive, this);
return res;
}
@@ -967,16 +1150,16 @@
fprintf(stderr, "The following archive%s in an inconsistent state and must be uninstalled "
"before proceeding:\n\n", inactive->count > 1 ? "s are" : " is");
uint32_t i;
- fprintf(stderr, "%-6s %-36s %-23s %s\n", "Serial", "UUID", "Date Installed", "Name");
- fprintf(stderr, "====== ==================================== ======================= =================\n");
+ this->archive_header();
for (i = 0; i < inactive->count; ++i) {
Archive* archive = this->archive(inactive->values[i]);
if (archive) {
- list_archive(archive, stderr);
+ list_archive(archive, stdout);
delete archive;
}
}
- fprintf(stderr, "\nWould you like to uninstall %s now? [y/n] ", inactive->count > 1 ? "them" : "it");
+ fprintf(stderr, "\nWould you like to uninstall %s now? [y/n] ",
+ inactive->count > 1 ? "them" : "it");
int c = getchar();
fprintf(stderr, "\n");
if (c == 'y' || c == 'Y') {
@@ -1009,6 +1192,39 @@
int Depot::is_locked() { return m_is_locked; }
+bool Depot::is_superseded(Archive* archive) {
+ int res = DB_OK;
+ uint8_t** filelist;
+ uint8_t* data;
+ uint32_t count;
+ res = this->m_db->get_files(&filelist, &count, archive);
+ if (FOUND(res)) {
+ for (uint32_t i=0; i < count; i++) {
+ File* file = this->m_db->make_file(filelist[i]);
+
+ // check for being superseded by a root
+ res = this->m_db->get_next_file(&data, file, FILE_SUPERSEDED);
+ this->m_db->free_file(data);
+ if (FOUND(res)) continue;
+
+ // check for being superseded by external changes
+ char* actpath;
+ join_path(&actpath, this->prefix(), file->path());
+ File* actual = FileFactory(actpath);
+ free(actpath);
+ uint32_t flags = File::compare(file, actual);
+
+ // not found in database and no changes on disk,
+ // so file is the current version of actual
+ if (flags == FILE_INFO_IDENTICAL) return false;
+
+ // something external changed contents of actual,
+ // so we consider this file superseded (by OS upgrade?)
+ }
+ }
+ return true;
+}
+
int Depot::lock(int operation) {
int res = 0;
if (m_lock_fd == -1) {
@@ -1041,9 +1257,10 @@
// Don't insert an archive that is already in the database
assert(archive->serial() == 0);
archive->m_serial = m_db->insert_archive(archive->uuid(),
- archive->info(),
- archive->name(),
- archive->date_installed());
+ archive->info(),
+ archive->name(),
+ archive->date_installed(),
+ archive->build());
return archive->m_serial == 0;
}
@@ -1133,6 +1350,8 @@
if (strncasecmp(arg, "all", 3) == 0) {
list = this->get_all_archives(&count);
+ } else if (strncasecmp(arg, "superseded", 10) == 0) {
+ list = this->get_superseded_archives(&count);
} else {
// make a list of 1 Archive
list = (Archive**)malloc(sizeof(Archive*));
Modified: trunk/darwinup/Depot.h
===================================================================
--- trunk/darwinup/Depot.h 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Depot.h 2010-03-12 22:20:40 UTC (rev 773)
@@ -79,12 +79,14 @@
// returns a list of Archive*. Caller must free the list.
Archive** get_all_archives(uint32_t *count);
+ Archive** get_superseded_archives(uint32_t *count);
uint64_t count_archives();
int dump();
static int dump_archive(Archive* archive, void* context);
int list();
+ int list(int count, char** args);
static int list_archive(Archive* archive, void* context);
int install(const char* path);
@@ -112,7 +114,10 @@
// test if the depot is currently locked
int is_locked();
+ bool is_superseded(Archive* archive);
+ void archive_header();
+
protected:
// Serialize access to the Depot via flock(2).
@@ -139,16 +144,16 @@
int remove(File* file);
int analyze_stage(const char* path, Archive* archive, Archive* rollback, int* rollback_files);
+
+ // removes expand and unexpanded files from archives path
int prune_directories();
+ int prune_archive(Archive* archive);
- // 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);
int check_consistency();
-
+
DarwinupDatabase* m_db;
mode_t m_depot_mode;
@@ -157,6 +162,7 @@
char* m_database_path;
char* m_archives_path;
char* m_downloads_path;
+ char* m_build;
int m_lock_fd;
int m_is_locked;
};
Modified: trunk/darwinup/Table.cpp
===================================================================
--- trunk/darwinup/Table.cpp 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Table.cpp 2010-03-12 22:20:40 UTC (rev 773)
@@ -54,7 +54,8 @@
m_delete_sql = NULL;
m_prepared_insert = NULL;
m_prepared_update = NULL;
- m_prepared_delete = NULL;
+ m_prepared_delete = NULL;
+ m_version = 0;
}
Table::~Table() {
@@ -89,12 +90,16 @@
return m_name;
}
+uint32_t Table::version() {
+ return m_version;
+}
+
int Table::set_custom_create(const char* sql) {
this->m_custom_create_sql = strdup(sql);
return this->m_custom_create_sql == 0;
}
-int Table::add_column(Column* c) {
+int Table::add_column(Column* c, uint32_t schema_version) {
// accumulate offsets for columns in m_columns_size
c->m_offset = this->m_columns_size;
this->m_columns_size += c->size();
@@ -109,7 +114,7 @@
m_column_max *= REALLOC_FACTOR;
}
m_columns[m_column_count++] = c;
-
+ c->m_version = schema_version;
return 0;
}
@@ -189,7 +194,7 @@
bool comma = false; // flag we set to start adding commas
// calculate the length of the sql statement
- size_t size = 27 + 5*m_column_count;
+ size_t size = 28 + 5*m_column_count + strlen(m_name);
for (i=0; i<m_column_count; i++) {
size += strlen(m_columns[i]->name());
}
@@ -241,7 +246,7 @@
bool comma = false; // flag we set to start adding commas
// calculate the length of the sql statement
- size_t size = 27 + 5*m_column_count;
+ size_t size = 28 + 5*m_column_count + strlen(m_name);
for (i=0; i<m_column_count; i++) {
size += strlen(m_columns[i]->name());
}
@@ -273,6 +278,8 @@
}
strlcat(m_insert_sql, ");", size);
+ IF_SQL("insert sql: %s \n", m_insert_sql);
+
// prepare
int res = sqlite3_prepare_v2(db, m_insert_sql, strlen(m_insert_sql), &m_prepared_insert, NULL);
if (res != SQLITE_OK) {
@@ -471,6 +478,11 @@
return (const char*)m_create_sql;
}
+const char* Table::alter_add_column(uint32_t index) {
+ if (m_columns[index]) return m_columns[index]->alter(m_name);
+ return NULL;
+}
+
int Table::where_va_columns(uint32_t count, char* query, size_t size,
size_t* used, va_list args) {
char tmpstr[256];
Modified: trunk/darwinup/Table.h
===================================================================
--- trunk/darwinup/Table.h 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Table.h 2010-03-12 22:20:40 UTC (rev 773)
@@ -44,12 +44,13 @@
virtual ~Table();
const char* name();
+ uint32_t version();
// Add custom SQL to table initialization
int set_custom_create(const char* sql);
// Column handling
- int add_column(Column*);
+ int add_column(Column*, uint32_t schema_version);
Column* column(uint32_t index);
// get the result record offset for column at index
int offset(uint32_t index);
@@ -95,6 +96,7 @@
protected:
const char* create();
+ const char* alter_add_column(uint32_t index);
int where_va_columns(uint32_t count, char* query, size_t size,
size_t* used, va_list args);
@@ -106,6 +108,7 @@
void dump_results(FILE* f);
char* m_name;
+ uint32_t m_version; // schema version this was added
char* m_create_sql;
char* m_custom_create_sql;
Modified: trunk/darwinup/Utils.cpp
===================================================================
--- trunk/darwinup/Utils.cpp 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Utils.cpp 2010-03-12 22:20:40 UTC (rev 773)
@@ -31,16 +31,6 @@
*/
#include "Utils.h"
-#include <assert.h>
-#include <errno.h>
-#include <libgen.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <spawn.h>
-#include <sys/stat.h>
extern char** environ;
@@ -147,16 +137,54 @@
}
int exec_with_args(const char** args) {
+ return exec_with_args_fa(args, NULL);
+}
+
+int exec_with_args_pipe(const char** args, int fd) {
int res = 0;
+ posix_spawn_file_actions_t fa;
+
+ res = posix_spawn_file_actions_init(&fa);
+ if (res) {
+ fprintf(stderr, "Error: unable to initialize file actions: %d \n", res);
+ return res;
+ }
+
+ res = posix_spawn_file_actions_adddup2(&fa, fd, 1); // pipe stdout
+ if (res) {
+ fprintf(stderr, "Error: (%d) unable to add dup2 for %d \n", res, fd);
+ return res;
+ }
+
+ res = posix_spawn_file_actions_addclose(&fa, 2); // close stderr
+ if (res) {
+ fprintf(stderr, "Error: (%d) unable to add close for stderr.\n", res);
+ return res;
+ }
+
+ res = posix_spawn_file_actions_addclose(&fa, 0); // close stdin
+ if (res) {
+ fprintf(stderr, "Error: (%d) unable to add close for stdin.\n", res);
+ return res;
+ }
+
+ res = exec_with_args_fa(args, &fa);
+ posix_spawn_file_actions_destroy(&fa);
+
+ return res;
+}
+
+int exec_with_args_fa(const char** args, posix_spawn_file_actions_t* fa) {
+ int res = 0;
pid_t pid;
int status;
- IF_DEBUG("Spawning %s \n", args[0]);
+ IF_DEBUG("Spawn: %s \n", args[0]);
- res = posix_spawn(&pid, args[0], NULL, NULL, (char**)args, environ);
+ res = posix_spawn(&pid, args[0], fa, NULL, (char**)args, environ);
if (res != 0) fprintf(stderr, "Error: Failed to spawn %s: %s (%d)\n", args[0], strerror(res), res);
- IF_DEBUG("Running %s on pid %d \n", args[0], (int)pid);
+ IF_DEBUG("Running: %s on pid %d \n", args[0], (int)pid);
do {
res = waitpid(pid, &status, 0);
@@ -169,7 +197,7 @@
}
}
- IF_DEBUG("Done running %s \n", args[0]);
+ IF_DEBUG("Done: %s \n", args[0]);
return res;
}
@@ -246,6 +274,118 @@
return NULL;
}
+int find_base_system_path(char** output, const char* path) {
+ // find the first /System as we walk up path
+ char system[PATH_MAX];
+ char parent[PATH_MAX];
+ strlcpy(parent, path, PATH_MAX);
+ int res = -1;
+ struct stat sb;
+ while (res) {
+ // walk up path
+ snprintf(system, PATH_MAX, "%s%sSystem",
+ parent, (parent[1] == '\0' ? "" : "/"));
+ res = stat(system, &sb);
+ if (parent[1] == '\0') {
+ // we hit the top of the filesystem
+ break;
+ }
+ if (res) snprintf(parent, PATH_MAX, "%s", dirname(parent));
+ }
+ if (res) {
+ fprintf(stderr, "Error: (%d) unable to find base system path.\n", res);
+ return res;
+ }
+
+ asprintf(output, "%s", parent);
+ return 0;
+}
+
+int update_dyld_shared_cache(const char* path) {
+ extern uint32_t verbosity;
+ int res;
+ char* base;
+ res = find_base_system_path(&base, path);
+ if (res) return res;
+
+ if (verbosity) {
+ fprintf(stdout, "Updating dyld shared cache for %s ... ", base);
+ fflush(stdout);
+ }
+
+ // exec the tool from our target system
+ char* toolpath;
+ join_path(&toolpath, base, "/usr/bin/update_dyld_shared_cache");
+
+ const char* args[] = {
+ toolpath,
+ "-root", base,
+ NULL
+ };
+ res = exec_with_args(args);
+
+ if (verbosity) fprintf(stdout, "Done updating dyld shared cache\n");
+
+ free(toolpath);
+ free(base);
+ return res;
+}
+
+int build_number_for_path(char** build, const char* path) {
+ int res = 0;
+ char system[PATH_MAX];
+ char* base;
+
+ *build = (char*)calloc(1, 16);
+
+ // find the version plist for our target path
+ find_base_system_path(&base, path);
+ if (!base) return 1;
+ snprintf(system, PATH_MAX, "%s/System/Library/CoreServices/SystemVersion.plist", base);
+ free(base);
+
+ struct stat sb;
+ res = stat(system, &sb);
+ if (res) {
+ snprintf(*build, 16, " ");
+ return 1;
+ }
+
+ // read version plist to get build number
+ const char* args[] = {
+ "/usr/libexec/PlistBuddy",
+ "-c", "Print ProductBuildVersion",
+ system,
+ NULL
+ };
+ int pfd[2];
+ res = pipe(pfd);
+ if (res) {
+ fprintf(stderr, "Error: (%d) failed to create pipe.\n", res);
+ return res;
+ }
+ exec_with_args_pipe(args, pfd[1]);
+
+ // read from the pipe
+ close(pfd[1]);
+ res = 1;
+ while (res > 0 && res < 15) {
+ res = read(pfd[0], *build, 15);
+ // strip newline
+ if (res > 1 && (*build)[res-1] == '\n') (*build)[res-1] = '\0';
+ }
+ close(pfd[0]);
+
+ if (res == 0) return res; // success
+
+ if (res == -1) {
+ fprintf(stderr, "Error: failed to read build from plist.\n");
+ return res;
+ }
+
+ return -1;
+}
+
void __data_hex(FILE* f, uint8_t* data, uint32_t size) {
if (!size) return;
for (uint32_t i=0; i < size; i++) {
@@ -263,3 +403,8 @@
fprintf(f, "\n");
}
+void hr() {
+ fprintf(stdout, "=============================================="
+ "=======================================\n");
+}
+
Modified: trunk/darwinup/Utils.h
===================================================================
--- trunk/darwinup/Utils.h 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/Utils.h 2010-03-12 22:20:40 UTC (rev 773)
@@ -36,14 +36,25 @@
#include <stdint.h>
#include <sys/types.h>
#include <fts.h>
-
#include <stdarg.h>
#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <spawn.h>
+#include <sys/stat.h>
-const uint32_t VERBOSE = 0x1;
+
+const uint32_t VERBOSE = 0x1;
const uint32_t VERBOSE_DEBUG = 0x2;
+const uint32_t VERBOSE_SQL = 0x4;
#define IF_DEBUG(...) do { extern uint32_t verbosity; if (verbosity & VERBOSE_DEBUG) fprintf(stderr, "DEBUG: " __VA_ARGS__); } while (0)
+#define IF_SQL(...) do { extern uint32_t verbosity; if (verbosity & VERBOSE_SQL) fprintf(stderr, "DEBUG: " __VA_ARGS__); } while (0)
int fts_compare(const FTSENT **a, const FTSENT **b);
int ftsent_filename(FTSENT* ent, char* filename, size_t bufsiz);
@@ -54,7 +65,10 @@
int is_url_path(const char* path);
int is_userhost_path(const char* path);
int has_suffix(const char* str, const char* sfx);
+
int exec_with_args(const char** args);
+int exec_with_args_pipe(const char** args, int fd);
+int exec_with_args_fa(const char** args, posix_spawn_file_actions_t* fa);
int join_path(char** out, const char* p1, const char* p2);
int compact_slashes(char* orig, int slashes);
@@ -62,8 +76,15 @@
char* fetch_url(const char* srcpath, const char* dstpath);
char* fetch_userhost(const char* srcpath, const char* dstpath);
+int find_base_system_path(char** output, const char* path);
+int update_dyld_shared_cache(const char* path);
+int build_number_for_path(char** build, const char* path);
+
void __data_hex(FILE* f, uint8_t* data, uint32_t size);
+// print a horizontal line to stdout
+void hr();
+
inline int INFO_TEST(uint32_t word, uint32_t flag) { return ((word & flag) != 0); }
inline int INFO_SET(uint32_t word, uint32_t flag) { return (word | flag); }
inline int INFO_CLR(uint32_t word, uint32_t flag) { return (word & (~flag)); }
Modified: trunk/darwinup/main.cpp
===================================================================
--- trunk/darwinup/main.cpp 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/darwinup/main.cpp 2010-03-12 22:20:40 UTC (rev 773)
@@ -45,17 +45,19 @@
void usage(char* progname) {
fprintf(stderr, "usage: %s [-v] [-p DIR] [command] [args] \n", progname);
- fprintf(stderr, "version: 15 \n");
+ fprintf(stderr, "version: 16 \n");
fprintf(stderr, " \n");
fprintf(stderr, "options: \n");
- fprintf(stderr, " -f force operation to succeed at all costs \n");
- fprintf(stderr, " -p DIR operate on roots under DIR (default: /) \n");
- fprintf(stderr, " -v verbose (use -vv for extra verbosity) \n");
+ fprintf(stderr, " -d do not update dyld cache \n");
+ fprintf(stderr, " -f force operation to succeed at all costs \n");
+ fprintf(stderr, " -n dry run \n");
+ fprintf(stderr, " -p DIR operate on roots under DIR (default: /) \n");
+ fprintf(stderr, " -v verbose (use -vv for extra verbosity) \n");
fprintf(stderr, " \n");
fprintf(stderr, "commands: \n");
fprintf(stderr, " files <archive> \n");
fprintf(stderr, " install <path> \n");
- fprintf(stderr, " list \n");
+ fprintf(stderr, " list [archive] \n");
fprintf(stderr, " uninstall <archive> \n");
fprintf(stderr, " upgrade <path> \n");
fprintf(stderr, " verify <archive> \n");
@@ -71,13 +73,15 @@
fprintf(stderr, " tar, tar.gz, tar.bz2 \n");
fprintf(stderr, " xar, zip \n");
fprintf(stderr, " \n");
- fprintf(stderr, "<archive> is one of: \n");
- fprintf(stderr, " <serial> the Serial number \n");
- fprintf(stderr, " <uuid> the UUID \n");
- fprintf(stderr, " <name> the last root installed with that name \n");
- fprintf(stderr, " newest the newest (last) root installed \n");
- fprintf(stderr, " oldest the oldest root installed \n");
- fprintf(stderr, " all all installed roots \n");
+ fprintf(stderr, "archive is one of: \n");
+ fprintf(stderr, " <serial> the Serial number \n");
+ fprintf(stderr, " <uuid> the UUID \n");
+ fprintf(stderr, " <name> the last root installed with that name \n");
+ fprintf(stderr, " newest the newest (last) root installed \n");
+ fprintf(stderr, " oldest the oldest root installed \n");
+ fprintf(stderr, " superseded all roots that have been fully replaced \n");
+ fprintf(stderr, " by newer roots \n");
+ fprintf(stderr, " all all installed roots \n");
fprintf(stderr, " \n");
exit(1);
}
@@ -85,20 +89,28 @@
// our globals
uint32_t verbosity;
uint32_t force;
+uint32_t dryrun;
int main(int argc, char* argv[]) {
char* progname = strdup(basename(argv[0]));
-
char* path = NULL;
+ bool update_dyld = true;
int ch;
- while ((ch = getopt(argc, argv, "fp:vh")) != -1) {
+ while ((ch = getopt(argc, argv, "dfnp:vh")) != -1) {
switch (ch) {
+ case 'd':
+ update_dyld = false;
+ break;
case 'f':
IF_DEBUG("forcing operations\n");
force = 1;
break;
+ case 'n':
+ IF_DEBUG("dry run\n");
+ dryrun = 1;
+ break;
case 'p':
if (optarg[0] != '/') {
fprintf(stderr, "Error: -p option must be an absolute path\n");
@@ -129,54 +141,67 @@
if (!path) {
asprintf(&path, "/");
}
-
+
Depot* depot = new Depot(path);
- // commands with no arguments
- if (argc == 1) {
- if (strcmp(argv[0], "list") == 0) {
- res = depot->initialize(false);
- if (res == -2) {
- fprintf(stdout, "Nothing has been installed yet.\n");
- exit(0);
- }
- if (res == 0) depot->list();
- } else if (strcmp(argv[0], "dump") == 0) {
+ // list handles args optional and in special ways
+ if (strcmp(argv[0], "list") == 0) {
+ res = depot->initialize(false);
+ if (res == -2) {
+ // we are not asking to write,
+ // but no depot exists yet either,
+ // so print an empty list
+ depot->archive_header();
+ exit(0);
+ }
+ if (res == -3) {
+ // permission denied when trying to read
+ // the depot
+ fprintf(stderr, "Permission denied when trying to read the database.\n");
+ exit(6);
+ }
+ if (res == 0) depot->list(argc-1, (char**)(argv+1));
+ } else if (argc == 1) {
+ // other commands which take no arguments
+ if (strcmp(argv[0], "dump") == 0) {
if (depot->initialize(false)) exit(11);
depot->dump();
} else {
usage(progname);
}
- }
-
- // loop over arguments
- for (int i = 1; i < argc; i++) {
- if (strcmp(argv[0], "install") == 0) {
- if (i==1 && depot->initialize(true)) exit(13);
- res = depot->install(argv[i]);
- } else if (strcmp(argv[0], "upgrade") == 0) {
- if (i==1 && depot->initialize(true)) exit(14);
- // find most recent matching archive by name
- Archive* old = depot->get_archive(basename(argv[i]));
- if (!old) {
- fprintf(stderr, "Error: unable to find a matching root to upgrade.\n");
- res = 5;
+ } else {
+ // loop over arguments
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[0], "install") == 0) {
+ if (i==1 && depot->initialize(true)) exit(13);
+ res = depot->install(argv[i]);
+ if (update_dyld && res == 0) res = update_dyld_shared_cache(path);
+ } else if (strcmp(argv[0], "upgrade") == 0) {
+ if (i==1 && depot->initialize(true)) exit(14);
+ // find most recent matching archive by name
+ Archive* old = depot->get_archive(basename(argv[i]));
+ if (!old) {
+ fprintf(stderr, "Error: unable to find a matching root to upgrade.\n");
+ res = 5;
+ }
+ // install new archive
+ if (res == 0) res = depot->install(argv[i]);
+ // uninstall old archive
+ if (res == 0) res = depot->uninstall(old);
+ if (update_dyld && res == 0) res = update_dyld_shared_cache(path);
+ } else if (strcmp(argv[0], "files") == 0) {
+ if (i==1 && depot->initialize(false)) exit(12);
+ res = depot->process_archive(argv[0], argv[i]);
+ } else if (strcmp(argv[0], "uninstall") == 0) {
+ if (i==1 && depot->initialize(true)) exit(15);
+ res = depot->process_archive(argv[0], argv[i]);
+ if (update_dyld && res == 0) res = update_dyld_shared_cache(path);
+ } else if (strcmp(argv[0], "verify") == 0) {
+ if (i==1 && depot->initialize(true)) exit(16);
+ res = depot->process_archive(argv[0], argv[i]);
+ } else {
+ usage(progname);
}
- // install new archive
- if (res == 0) res = depot->install(argv[i]);
- // uninstall old archive
- if (res == 0) res = depot->uninstall(old);
- } else if (strcmp(argv[0], "files") == 0) {
- if (i==1 && depot->initialize(false)) exit(12);
- res = depot->process_archive(argv[0], argv[i]);
- } else if (strcmp(argv[0], "uninstall") == 0) {
- if (i==1 && depot->initialize(true)) exit(15);
- res = depot->process_archive(argv[0], argv[i]);
- } else if (strcmp(argv[0], "verify") == 0) {
- if (i==1 && depot->initialize(true)) exit(16);
- res = depot->process_archive(argv[0], argv[i]);
- } else {
- usage(progname);
}
}
Modified: trunk/testing/darwinup/run-tests.sh
===================================================================
--- trunk/testing/darwinup/run-tests.sh 2010-03-12 17:31:03 UTC (rev 772)
+++ trunk/testing/darwinup/run-tests.sh 2010-03-12 22:20:40 UTC (rev 773)
@@ -11,6 +11,7 @@
DEST=$PREFIX/dest
DESTTAR=dest.tar.gz
+DARWINUP="darwinup -dvvv -p $DEST "
DIFF="diff -x .DarwinDepot -x broken -qru"
ROOTS="root root2 root3"
@@ -44,22 +45,22 @@
for R in $ROOTS;
do
echo "INFO: Installing $R ...";
- darwinup -vv -p $DEST install $PREFIX/$R
- UUID=$(darwinup -p $DEST list | head -3 | tail -1 | awk '{print $1}')
+ $DARWINUP install $PREFIX/$R
+ UUID=$($DARWINUP list | head -3 | tail -1 | awk '{print $1}')
echo "INFO: Uninstalling $R ...";
- darwinup -vv -p $DEST uninstall $UUID
+ $DARWINUP uninstall $UUID
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
done
echo "========== TEST: Multiple argument test ==========";
-darwinup -vv -p $DEST install $PREFIX/root{,2,3}
-LINES=$(darwinup -p $DEST list | wc -l)
+$DARWINUP install $PREFIX/root{,2,3}
+LINES=$($DARWINUP list | wc -l)
if [ $LINES -lt 5 ]; then
echo "Failed multiple argument test."
exit 1;
fi
-darwinup -vv -p $DEST uninstall all
+$DARWINUP uninstall all
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
@@ -68,13 +69,13 @@
for R in $ROOTS;
do
echo "INFO: Installing $R ...";
- darwinup -vv -p $DEST install $PREFIX/$R
+ $DARWINUP install $PREFIX/$R
done
for R in $ROOTS;
do
- UUID=$(darwinup -p $DEST list | head -3 | tail -1 | awk '{print $1}')
+ UUID=$($DARWINUP list | head -3 | tail -1 | awk '{print $1}')
echo "INFO: Uninstalling $UUID ...";
- darwinup -vv -p $DEST uninstall $UUID
+ $DARWINUP uninstall $UUID
done
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
@@ -83,13 +84,13 @@
for R in $ROOTS;
do
echo "INFO: Installing $R ...";
- darwinup -vv -p $DEST install $PREFIX/$R
+ $DARWINUP install $PREFIX/$R
done
for R in $ROOTS;
do
- UUID=$(darwinup -p $DEST list | grep $R$ | awk '{print $1}')
+ UUID=$($DARWINUP list | grep $R$ | awk '{print $1}')
echo "INFO: Uninstalling $UUID ...";
- darwinup -vv -p $DEST uninstall $UUID
+ $DARWINUP uninstall $UUID
done
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
@@ -98,13 +99,13 @@
for R in $ROOTS;
do
echo "INFO: Installing $R ...";
- darwinup -vv -p $DEST install $PREFIX/$R
+ $DARWINUP install $PREFIX/$R
done
for R in root2 root3 root;
do
- UUID=$(darwinup -p $DEST list | grep $R$ | awk '{print $1}')
+ UUID=$($DARWINUP list | grep $R$ | awk '{print $1}')
echo "INFO: Uninstalling $UUID ...";
- darwinup -vv -p $DEST uninstall $UUID
+ $DARWINUP uninstall $UUID
done
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
@@ -113,45 +114,45 @@
for R in root3 root2 root;
do
echo "INFO: Installing $R ...";
- darwinup -vv -p $DEST install $PREFIX/$R
+ $DARWINUP install $PREFIX/$R
done
for R in root3 root2 root;
do
- UUID=$(darwinup -p $DEST list | grep $R$ | awk '{print $1}')
+ UUID=$($DARWINUP list | grep $R$ | awk '{print $1}')
echo "INFO: Uninstalling $UUID ...";
- darwinup -vv -p $DEST uninstall $UUID
+ $DARWINUP uninstall $UUID
done
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
echo "========== TEST: trying large roots ==========";
echo "INFO: installing 300files";
-darwinup -vv -p $DEST install $PREFIX/300files.tbz2
-darwinup -vv -p $DEST uninstall 300files.tbz2
+$DARWINUP install $PREFIX/300files.tbz2
+$DARWINUP uninstall 300files.tbz2
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
echo "INFO: installing 300dir";
-darwinup -vv -p $DEST install $PREFIX/300dirs.tbz2
-darwinup -vv -p $DEST uninstall 300dirs.tbz2
+$DARWINUP install $PREFIX/300dirs.tbz2
+$DARWINUP uninstall 300dirs.tbz2
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
echo "INFO: installing both 300files and 300dirs";
-darwinup -vv -p $DEST install $PREFIX/300dirs.tbz2
-darwinup -vv -p $DEST install $PREFIX/300files.tbz2
-darwinup -vv -p $DEST uninstall 300dirs.tbz2
-darwinup -vv -p $DEST uninstall 300files.tbz2
+$DARWINUP install $PREFIX/300dirs.tbz2
+$DARWINUP install $PREFIX/300files.tbz2
+$DARWINUP uninstall 300dirs.tbz2
+$DARWINUP uninstall 300files.tbz2
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$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
+$DARWINUP install $PREFIX/root5
+$DARWINUP 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
+$DARWINUP install $PREFIX/root7
+$DARWINUP uninstall root6
+$DARWINUP uninstall root5
+$DARWINUP uninstall root7
stat $DEST/d/file
rm $DEST/d/file
rmdir $DEST/d
@@ -159,32 +160,32 @@
$DIFF $ORIG $DEST 2>&1
echo "========== TEST: Deep rollback while saving user data =========="
-darwinup -vv -p $DEST install $PREFIX/deep-rollback.cpgz
+$DARWINUP install $PREFIX/deep-rollback.cpgz
echo "modified" >> $DEST/d1/d2/d3/d4/d5/d6/file
-darwinup -vv -p $DEST install $PREFIX/deep-rollback.cpgz
-darwinup -vv -p $DEST uninstall newest
-darwinup -vv -p $DEST uninstall newest
+$DARWINUP install $PREFIX/deep-rollback.cpgz
+$DARWINUP uninstall newest
+$DARWINUP uninstall newest
stat $DEST/d1/d2/d3/d4/d5/d6/file
rm $DEST/d1/d2/d3/d4/d5/d6/file
rm -rf $DEST/d1
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
-darwinup -vv -p $DEST install $PREFIX/deep-rollback.cpgz
-darwinup -vv -p $DEST install $PREFIX/deep-rollback-2.xar
-darwinup -vv -p $DEST uninstall all
+$DARWINUP install $PREFIX/deep-rollback.cpgz
+$DARWINUP install $PREFIX/deep-rollback-2.xar
+$DARWINUP uninstall all
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
echo "========== TEST: Testing broken symlink handling =========="
-darwinup -vv -p $DEST install $PREFIX/symlinks
-darwinup -vv -p $DEST uninstall symlinks
+$DARWINUP install $PREFIX/symlinks
+$DARWINUP uninstall symlinks
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
-darwinup -vv -p $DEST install $PREFIX/symlink_update
+$DARWINUP install $PREFIX/symlink_update
stat -L $DEST/broken
-darwinup -vv -p $DEST uninstall newest
+$DARWINUP uninstall newest
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
@@ -194,7 +195,7 @@
#
set +e
echo "========== TEST: Trying a root that will fail due to object change =========="
-darwinup -vv -p $DEST install $PREFIX/root4
+$DARWINUP install $PREFIX/root4
if [ $? -ne 1 ]; then exit 1; fi
echo "DIFF: diffing original test files to dest (should be no diffs) ..."
$DIFF $ORIG $DEST 2>&1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20100312/bdf24aed/attachment-0001.html>
More information about the darwinbuild-changes
mailing list