[27520] trunk/base/src

source_changes at macosforge.org source_changes at macosforge.org
Mon Aug 6 13:12:36 PDT 2007


Revision: 27520
          http://trac.macosforge.org/projects/macports/changeset/27520
Author:   sfiera at macports.org
Date:     2007-08-06 13:12:35 -0700 (Mon, 06 Aug 2007)

Log Message:
-----------
Moving to base/src/cregistry--doesn't yet build as cregistry isn't linked in

Modified Paths:
--------------
    trunk/base/src/Makefile.in
    trunk/base/src/registry2.0/Makefile
    trunk/base/src/registry2.0/registry.c
    trunk/base/src/registry2.0/registry.h
    trunk/base/src/registry2.0/util.h

Added Paths:
-----------
    trunk/base/src/cregistry/
    trunk/base/src/cregistry/Makefile
    trunk/base/src/cregistry/entry.c
    trunk/base/src/cregistry/entry.h
    trunk/base/src/cregistry/registry.c
    trunk/base/src/cregistry/registry.h
    trunk/base/src/cregistry/sql.c
    trunk/base/src/cregistry/sql.h

Removed Paths:
-------------
    trunk/base/src/registry2.0/centry.c
    trunk/base/src/registry2.0/centry.h
    trunk/base/src/registry2.0/creg.c
    trunk/base/src/registry2.0/creg.h
    trunk/base/src/registry2.0/sql.c
    trunk/base/src/registry2.0/sql.h

Modified: trunk/base/src/Makefile.in
===================================================================
--- trunk/base/src/Makefile.in	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/Makefile.in	2007-08-06 20:12:35 UTC (rev 27520)
@@ -1,4 +1,5 @@
 TCLPKG=		@OUR_INCLUDED_PACKAGES@ \
+			cregistry \
 			macports1.0 \
 			port1.0 \
 			package1.0 \

Added: trunk/base/src/cregistry/Makefile
===================================================================
--- trunk/base/src/cregistry/Makefile	                        (rev 0)
+++ trunk/base/src/cregistry/Makefile	2007-08-06 20:12:35 UTC (rev 27520)
@@ -0,0 +1,16 @@
+OBJS=       registry.o entry.o sql.o
+
+include ../../Mk/macports.autoconf.mk
+include ../../Mk/macports.tea.mk
+
+.PHONY: test
+
+test:: ${SHLIB_NAME}
+	${TCLSH} tests/entry.tcl ${SHLIB_NAME}
+
+all:: ${OBJS}
+
+clean::
+	rm -f ${OBJS} so_locations
+
+distclean:: clean

Copied: trunk/base/src/cregistry/entry.c (from rev 27519, trunk/base/src/registry2.0/centry.c)
===================================================================
--- trunk/base/src/cregistry/entry.c	                        (rev 0)
+++ trunk/base/src/cregistry/entry.c	2007-08-06 20:12:35 UTC (rev 27520)
@@ -0,0 +1,700 @@
+/*
+ * entry.c
+ * $Id: $
+ *
+ * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <sqlite3.h>
+
+#include <cregistry/entry.h>
+#include <cregistry/registry.h>
+
+/**
+ * Concatenates `src` to string `dst`.
+ *
+ * Simple concatenation. Only guaranteed to work with strings that have been
+ * allocated with `malloc`. Amortizes cost of expanding string buffer for O(N)
+ * concatenation and such. Uses `memcpy` in favor of `strcpy` in hopes it will
+ * perform a bit better. If passing in a static string to dst, make sure
+ * dst_space starts at dst_len. Also make sure dst_space is never 0 (so don't
+ * use "" as the starter string, allocate some space);
+ */
+void reg_strcat(char** dst, int* dst_len, int* dst_space, char* src) {
+    int src_len = strlen(src);
+    if (*dst_len + src_len >= *dst_space) {
+        char* old_dst = *dst;
+        char* new_dst = malloc(*dst_space * 2 * sizeof(char));
+        *dst_space *= 2;
+        memcpy(new_dst, old_dst, *dst_len);
+        *dst = new_dst;
+        free(old_dst);
+    }
+    memcpy(&((*dst)[*dst_len]), src, src_len+1);
+    *dst_len += src_len;
+}
+
+/**
+ * Appends `src` to the list `dst`.
+ *
+ * It's like `reg_strcat`, except `src` represents an element and not a sequence
+ * of `char`s.
+ */
+static void reg_listcat(void*** dst, int* dst_len, int* dst_space, void* src) {
+    if (*dst_len == *dst_space) {
+        void** old_dst = *dst;
+        void** new_dst = malloc(*dst_space * 2 * sizeof(void*));
+        *dst_space *= 2;
+        memcpy(new_dst, old_dst, *dst_len);
+        *dst = new_dst;
+        free(old_dst);
+    }
+    (*dst)[*dst_len] = src;
+    (*dst_len)++;
+}
+
+/**
+ * Returns the operator to use for the given strategy.
+ */
+static char* reg_strategy_op(int strategy, reg_error* errPtr) {
+    switch (strategy) {
+        case 0:
+            return "=";
+        case 1:
+            return " GLOB ";
+        case 2:
+            return " REGEXP ";
+        default:
+            errPtr->code = "registry::invalid-strategy";
+            errPtr->description = "invalid matching strategy specified";
+            errPtr->free = NULL;
+            return NULL;
+    }
+}
+
+static int reg_stmt_to_entry(void* userdata, void** entry, void* stmt,
+        reg_error* errPtr UNUSED) {
+    if (sqlite3_column_type(stmt, 1) == SQLITE_NULL) {
+        reg_entry* e = malloc(sizeof(reg_entry));
+        e->db = (sqlite3*)userdata;
+        e->id = sqlite3_column_int64(stmt, 0);
+        e->saved = 0;
+        e->proc = NULL;
+        *entry = e;
+    } else {
+        *entry = *(reg_entry**)sqlite3_column_blob(stmt, 1);
+    }
+    return 1;
+}
+
+static int reg_save_addresses(sqlite3* db, reg_entry** entries,
+        int entry_count, reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    int i;
+    char* query = "INSERT INTO entries (id, address) VALUES (?, ?)";
+    /* avoid unnecessarily making queries */
+    for (i=0; i<entry_count; i++) {
+        if (!entries[i]->saved) {
+            break;
+        }
+    }
+    if (i == entry_count) {
+        return 1;
+    }
+    /* BEGIN */
+    if (sqlite3_prepare(db, query, -1, &stmt, NULL)
+                == SQLITE_OK) {
+        for (i=0; i<entry_count; i++) {
+            if (entries[i]->saved) {
+                continue;
+            }
+            if ((sqlite3_bind_int64(stmt, 1, entries[i]->id) == SQLITE_OK)
+                    && (sqlite3_bind_blob(stmt, 2, &entries[i],
+                            sizeof(reg_entry*), SQLITE_TRANSIENT) == SQLITE_OK)
+                    && (sqlite3_step(stmt) == SQLITE_DONE)) {
+                sqlite3_reset(stmt);
+            } else {
+                sqlite3_finalize(stmt);
+                reg_sqlite_error(db, errPtr, query);
+            }
+        }
+        sqlite3_finalize(stmt);
+        return 1;
+    } else {
+        sqlite3_finalize(stmt);
+        reg_sqlite_error(db, errPtr, query);
+    }
+    return 0;
+}
+
+/**
+ * registry::entry create portname version revision variants epoch ?name?
+ *
+ * Unlike the old registry::new_entry, revision, variants, and epoch are all
+ * required. That's OK because there's only one place this function is called,
+ * and it's called with all of them there.
+ */
+reg_entry* reg_entry_create(sqlite3* db, char* name, char* version,
+        char* revision, char* variants, char* epoch, reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    char* query = "INSERT INTO registry.ports "
+        "(name, version, revision, variants, epoch) VALUES (?, ?, ?, ?, ?)";
+    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 2, version, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 3, revision, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 4, variants, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 5, epoch, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_step(stmt) == SQLITE_DONE)) {
+        char* query = "INSERT INTO entries (id, address) VALUES (?, ?)";
+        reg_entry* entry = malloc(sizeof(reg_entry));
+        entry->id = sqlite3_last_insert_rowid(db);
+        entry->db = db;
+        entry->proc = NULL;
+        sqlite3_finalize(stmt);
+        if ((sqlite3_prepare(db, query, -1, &stmt, NULL)
+                == SQLITE_OK)
+                && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)
+                && (sqlite3_bind_blob(stmt, 2, &entry, sizeof(reg_entry*),
+                        SQLITE_TRANSIENT) == SQLITE_OK)
+                && (sqlite3_step(stmt) == SQLITE_DONE)) {
+            return entry;
+        } else {
+            reg_sqlite_error(db, errPtr, query);
+        }
+        free(entry);
+        return NULL;
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        sqlite3_finalize(stmt);
+        return NULL;
+    }
+}
+
+reg_entry* reg_entry_open(sqlite3* db, char* name, char* version,
+        char* revision, char* variants, char* epoch, reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    char* query = "SELECT registry.ports.id, entries.address "
+        "FROM registry.ports LEFT OUTER JOIN entries USING (id) "
+        "WHERE name=? AND version=? AND revision=? AND variants=? AND epoch=?";
+    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 2, version, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 3, revision, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 4, variants, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 5, epoch, -1, SQLITE_STATIC)
+                == SQLITE_OK)) {
+        int r = sqlite3_step(stmt);
+        reg_entry* entry;
+        switch (r) {
+            case SQLITE_ROW:
+                if (reg_stmt_to_entry(db, (void**)&entry, stmt, errPtr)) {
+                    sqlite3_finalize(stmt);
+                    if (reg_save_addresses(db, &entry, 1, errPtr)) {
+                        return entry;
+                    }
+                }
+            case SQLITE_DONE:
+                errPtr->code = "registry::not-found";
+                errPtr->description = "no matching port found";
+                errPtr->free = NULL;
+                break;
+            default:
+                reg_sqlite_error(db, errPtr, query);
+                break;
+        }
+        sqlite3_finalize(stmt);
+        return NULL;
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        sqlite3_finalize(stmt);
+        return NULL;
+    }
+}
+
+/**
+ * deletes an entry; still needs to be freed
+ */
+int reg_entry_delete(sqlite3* db, reg_entry* entry, reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    char* query = "DELETE FROM registry.ports WHERE id=?";
+    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+            && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)
+            && (sqlite3_step(stmt) == SQLITE_DONE)) {
+        if (sqlite3_changes(db) > 0) {
+            sqlite3_finalize(stmt);
+            query = "DELETE FROM entries WHERE id=?";
+            if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+                    && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)
+                    && (sqlite3_step(stmt) == SQLITE_DONE)) {
+                sqlite3_finalize(stmt);
+                return 1;
+            }
+        } else {
+            errPtr->code = "registry::invalid-entry";
+            errPtr->description = "an invalid entry was passed";
+            errPtr->free = NULL;
+        }
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+    }
+    sqlite3_finalize(stmt);
+    return 0;
+}
+
+/*
+ * Frees the entries in `entries`.
+ */
+void reg_entry_free(sqlite3* db UNUSED, reg_entry* entry) {
+    sqlite3_stmt* stmt;
+    if (entry->proc != NULL) {
+        free(entry->proc);
+    }
+    free(entry);
+    sqlite3_prepare(entry->db, "DELETE FROM entries WHERE address=?", -1, &stmt,
+            NULL);
+    sqlite3_bind_blob(stmt, 1, &entry, sizeof(reg_entry*), SQLITE_TRANSIENT);
+    sqlite3_step(stmt);
+}
+
+static int reg_all_objects(sqlite3* db, char* query, int query_len,
+        void*** objects, cast_function* fn, free_function* del,
+        reg_error* errPtr) {
+    int r;
+    reg_entry* entry;
+    void** results = malloc(10*sizeof(void*));
+    int result_count = 0;
+    int result_space = 10;
+    sqlite3_stmt* stmt;
+    if (sqlite3_prepare(db, query, query_len, &stmt, NULL) == SQLITE_OK) {
+        do {
+            int i;
+            r = sqlite3_step(stmt);
+            switch (r) {
+                case SQLITE_ROW:
+                    if (fn(db, (void**)&entry, stmt, errPtr)) {
+                        reg_listcat(&results, &result_count, &result_space,
+                                entry);
+                        continue;
+                    } else {
+                        int i;
+                        sqlite3_finalize(stmt);
+                        for (i=0; i<result_count; i++) {
+                            del(NULL, results[i]);
+                        }
+                        free(results);
+                        return -1;
+                    }
+                case SQLITE_DONE:
+                    break;
+                default:
+                    for (i=0; i<result_count; i++) {
+                        del(NULL, results[i]);
+                    }
+                    free(results);
+                    sqlite3_finalize(stmt);
+                    reg_sqlite_error(db, errPtr, query);
+                    return -1;
+            }
+        } while (r != SQLITE_DONE);
+        *objects = results;
+        return result_count;
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        free(results);
+        return -1;
+    }
+}
+
+/*
+ * Searches the registry for ports for which each key's value is equal to the
+ * given value. To find all ports, pass 0 key-value pairs.
+ *
+ * Vulnerable to SQL-injection attacks in the `keys` field. Pass it valid keys,
+ * please.
+ */
+int reg_entry_search(sqlite3* db, char** keys, char** vals, int key_count,
+        int strategy, reg_entry*** entries, reg_error* errPtr) {
+    int i;
+    char* kwd = " WHERE ";
+    char* query;
+    int query_len = 32;
+    int query_space = 32;
+    int result;
+    /* get the strategy */
+    char* op = reg_strategy_op(strategy, errPtr);
+    if (op == NULL) {
+        return -1;
+    }
+    /* build the query */
+    query = strdup("SELECT registry.ports.id, entries.address "
+            "FROM registry.ports LEFT OUTER JOIN entries USING (id)");
+    for (i=0; i<key_count; i+=1) {
+        char* cond = sqlite3_mprintf("%s%s%s'%q'", kwd, keys[i], op, vals[i]);
+        reg_strcat(&query, &query_len, &query_space, cond);
+        sqlite3_free(cond);
+        kwd = " AND ";
+    }
+    /* do the query */
+    result = reg_all_objects(db, query, query_len, (void***)entries,
+            reg_stmt_to_entry, (free_function*)reg_entry_free, errPtr);
+    if (result > 0) {
+        if (!reg_save_addresses(db, *entries, result, errPtr)) {
+            free(entries);
+            return 0;
+        }
+    }
+    free(query);
+    return result;
+}
+
+/**
+ * TODO: fix this to return ports where state=active too
+ * TODO: add more arguments (epoch, revision, variants), maybe
+ */
+int reg_entry_installed(sqlite3* db, char* name, char* version, 
+        reg_entry*** entries, reg_error* errPtr) {
+    char* format;
+    char* query;
+    int result;
+    char* select = "SELECT registry.ports.id, entries.address FROM "
+        "registry.ports LEFT OUTER JOIN entries USING (id)";
+    if (name == NULL) {
+        format = "%s WHERE (state='installed' OR state='active')";
+    } else if (version == NULL) {
+        format = "%s WHERE (state='installed' OR state='active') AND name='%q'";
+    } else {
+        format = "%s WHERE (state='installed' OR state='active') AND name='%q' "
+            "AND version='%q'";
+    }
+    query = sqlite3_mprintf(format, select, name, version);
+    result = reg_all_objects(db, query, -1, (void***)entries,
+            reg_stmt_to_entry, (free_function*)reg_entry_free, errPtr);
+    if (result > 0) {
+        if (!reg_save_addresses(db, *entries, result, errPtr)) {
+            free(entries);
+            return 0;
+        }
+    }
+    sqlite3_free(query);
+    return result;
+}
+
+/**
+ */
+int reg_entry_active(sqlite3* db, char* name, reg_entry*** entries,
+        reg_error* errPtr) {
+    char* format;
+    char* query;
+    int result;
+    char* select = "SELECT registry.ports.id, entries.address FROM "
+        "registry.ports LEFT OUTER JOIN entries USING (id)";
+    if (name == NULL) {
+        format = "%s WHERE state='active'";
+    } else {
+        format = "%s WHERE state='active' AND name='%q'";
+    }
+    query = sqlite3_mprintf(format, select, name);
+    result = reg_all_objects(db, query, -1, (void***)entries,
+            reg_stmt_to_entry, (free_function*)reg_entry_free, errPtr);
+    if (result > 0) {
+        if (!reg_save_addresses(db, *entries, result, errPtr)) {
+            free(entries);
+            return 0;
+        }
+    }
+    sqlite3_free(query);
+    return result;
+}
+
+int reg_entry_owner(sqlite3* db, char* path, reg_entry** entry,
+        reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    reg_entry* result;
+    char* query = "SELECT registry.files.id, entries.address "
+        "FROM registry.files LEFT OUTER JOIN entries USING (id) "
+        "WHERE path=?";
+    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC)
+                == SQLITE_OK)) {
+        int r = sqlite3_step(stmt);
+        switch (r) {
+            case SQLITE_ROW:
+                if (reg_stmt_to_entry(db, (void**)&result, stmt, errPtr)) {
+                    sqlite3_finalize(stmt);
+                    if (reg_save_addresses(db, &result, 1, errPtr)) {
+                        *entry = result;
+                        return 1;
+                    }
+                }
+            case SQLITE_DONE:
+                sqlite3_finalize(stmt);
+                *entry = NULL;
+                return 1;
+            default:
+                /* barf */
+                sqlite3_finalize(stmt);
+                return 0;
+        }
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        sqlite3_finalize(stmt);
+        return 0;
+    }
+}
+
+int reg_entry_propget(sqlite3* db, reg_entry* entry, char* key, char** value,
+        reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    char* query = sqlite3_mprintf("SELECT %q FROM registry.ports "
+            "WHERE id=%lld", key, entry->id);
+    if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
+        int r = sqlite3_step(stmt);
+        switch (r) {
+            case SQLITE_ROW:
+                *value = strdup(sqlite3_column_text(stmt, 0));
+                sqlite3_finalize(stmt);
+                return 1;
+            case SQLITE_DONE:
+                errPtr->code = "registry::invalid-entry";
+                errPtr->description = "an invalid entry was passed";
+                errPtr->free = NULL;
+                sqlite3_finalize(stmt);
+                return 0;
+            default:
+                reg_sqlite_error(db, errPtr, query);
+                sqlite3_finalize(stmt);
+                return 0;
+        }
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        return 0;
+    }
+}
+
+int reg_entry_propset(sqlite3* db, reg_entry* entry, char* key, char* value,
+        reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    char* query = sqlite3_mprintf("UPDATE registry.ports SET %q = '%q' "
+            "WHERE id=%lld", key, value, entry->id);
+    if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
+        int r = sqlite3_step(stmt);
+        switch (r) {
+            case SQLITE_DONE:
+                sqlite3_finalize(stmt);
+                return 1;
+            default:
+                switch (sqlite3_reset(stmt)) {
+                    case SQLITE_CONSTRAINT:
+                        errPtr->code = "registry::constraint";
+                        errPtr->description = "a constraint was disobeyed";
+                        errPtr->free = NULL;
+                        sqlite3_finalize(stmt);
+                        return 0;
+                    default:
+                        reg_sqlite_error(db, errPtr, query);
+                        sqlite3_finalize(stmt);
+                        return 0;
+                }
+        }
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        return 0;
+    }
+}
+
+int reg_entry_map(sqlite3* db, reg_entry* entry, char** files, int file_count,
+        reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    char* query = "INSERT INTO registry.files (id, path) VALUES (?, ?)";
+    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+            && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)) {
+        int i;
+        for (i=0; i<file_count; i++) {
+            if (sqlite3_bind_text(stmt, 2, files[i], -1, SQLITE_STATIC)
+                    == SQLITE_OK) {
+                int r = sqlite3_step(stmt);
+                switch (r) {
+                    case SQLITE_DONE:
+                        sqlite3_reset(stmt);
+                        continue;
+                    case SQLITE_ERROR:
+                        switch (sqlite3_reset(stmt)) {
+                            case SQLITE_CONSTRAINT:
+                                errPtr->code = "registry::already-owned";
+                                errPtr->description = "mapped file is already "
+                                    "owned by another entry";
+                                errPtr->free = NULL;
+                                sqlite3_finalize(stmt);
+                                return i;
+                            default:
+                                reg_sqlite_error(db, errPtr, query);
+                                sqlite3_finalize(stmt);
+                                return i;
+                        }
+                }
+            } else {
+                reg_sqlite_error(db, errPtr, query);
+                sqlite3_finalize(stmt);
+                return i;
+            }
+        }
+        sqlite3_finalize(stmt);
+        return file_count;
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        sqlite3_finalize(stmt);
+        return 0;
+    }
+}
+
+int reg_entry_unmap(sqlite3* db, reg_entry* entry, char** files, int file_count,
+        reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    char* query = "DELETE FROM registry.files WHERE id=? AND path=?";
+    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+            && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)) {
+        int i;
+        for (i=0; i<file_count; i++) {
+            if (sqlite3_bind_text(stmt, 2, files[i], -1, SQLITE_STATIC)
+                    == SQLITE_OK) {
+                int r = sqlite3_step(stmt);
+                switch (r) {
+                    case SQLITE_DONE:
+                        if (sqlite3_changes(db) == 0) {
+                            errPtr->code = "registry::not-owned";
+                            errPtr->description = "this entry does not own the "
+                                "given file";
+                            errPtr->free = NULL;
+                            sqlite3_finalize(stmt);
+                            return i;
+                        } else {
+                            sqlite3_reset(stmt);
+                            continue;
+                        }
+                    default:
+                        reg_sqlite_error(db, errPtr, query);
+                        sqlite3_finalize(stmt);
+                        return i;
+                }
+            } else {
+                reg_sqlite_error(db, errPtr, query);
+                sqlite3_finalize(stmt);
+                return i;
+            }
+        }
+        sqlite3_finalize(stmt);
+        return file_count;
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        sqlite3_finalize(stmt);
+        return 0;
+    }
+}
+
+int reg_entry_files(sqlite3* db, reg_entry* entry, char*** files,
+        reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    char* query = "SELECT path FROM registry.files WHERE id=? ORDER BY path";
+    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+            && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)) {
+        char** result = malloc(10*sizeof(char*));
+        int result_count = 0;
+        int result_space = 10;
+        int r;
+        do {
+            char* element;
+            int i;
+            r = sqlite3_step(stmt);
+            switch (r) {
+                case SQLITE_ROW:
+                    element = strdup(sqlite3_column_text(stmt, 0));
+                    reg_listcat((void*)&result, &result_count, &result_space,
+                            element);
+                    break;
+                case SQLITE_DONE:
+                    break;
+                default:
+                    for (i=0; i<result_count; i++) {
+                        free(result[i]);
+                    }
+                    free(result);
+                    reg_sqlite_error(db, errPtr, query);
+                    sqlite3_finalize(stmt);
+                    return -1;
+            }
+        } while (r != SQLITE_DONE);
+        sqlite3_finalize(stmt);
+        *files = result;
+        return result_count;
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        sqlite3_finalize(stmt);
+        return -1;
+    }
+}
+
+int reg_all_entries(sqlite3* db, reg_entry*** entries, reg_error* errPtr) {
+    reg_entry* entry;
+    void** results = malloc(10*sizeof(void*));
+    int result_count = 0;
+    int result_space = 10;
+    sqlite3_stmt* stmt;
+    char* query = "SELECT address FROM entries";
+    if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
+        int r;
+        do {
+            r = sqlite3_step(stmt);
+            switch (r) {
+                case SQLITE_ROW:
+                    entry = *(reg_entry**)sqlite3_column_blob(stmt, 0);
+                    reg_listcat(&results, &result_count, &result_space, entry);
+                    break;
+                case SQLITE_DONE:
+                    break;
+                default:
+                    reg_sqlite_error(db, errPtr, query);
+                    free(results);
+                    return -1;
+            }
+        } while (r != SQLITE_DONE);
+    }
+    *entries = (reg_entry**)results;
+    return result_count;
+}

Copied: trunk/base/src/cregistry/entry.h (from rev 27519, trunk/base/src/registry2.0/centry.h)
===================================================================
--- trunk/base/src/cregistry/entry.h	                        (rev 0)
+++ trunk/base/src/cregistry/entry.h	2007-08-06 20:12:35 UTC (rev 27520)
@@ -0,0 +1,82 @@
+/*
+ * entry.h
+ * $Id: $
+ *
+ * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _CENTRY_H
+#define _CENTRY_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sqlite3.h>
+#include <cregistry/registry.h>
+
+typedef struct {
+    sqlite_int64 id; /* rowid in database */
+    sqlite3* db; /* database */
+    int saved; /* have we recorded &entry in database? */
+    char* proc; /* name of Tcl proc, if using Tcl */
+} reg_entry;
+
+reg_entry* reg_entry_create(sqlite3* db, char* name, char* version,
+        char* revision, char* variants, char* epoch, reg_error* errPtr);
+
+reg_entry* reg_entry_open(sqlite3* db, char* name, char* version,
+        char* revision, char* variants, char* epoch, reg_error* errPtr);
+
+int reg_entry_delete(sqlite3* db, reg_entry* entry, reg_error* errPtr);
+
+void reg_entry_free(sqlite3* db, reg_entry* entry);
+
+int reg_entry_search(sqlite3* db, char** keys, char** vals, int key_count,
+        int strategy, reg_entry*** entries, reg_error* errPtr);
+
+int reg_entry_installed(sqlite3* db, char* name, char* version, 
+        reg_entry*** entries, reg_error* errPtr);
+
+int reg_entry_active(sqlite3* db, char* name, reg_entry*** entries,
+        reg_error* errPtr);
+
+int reg_entry_owner(sqlite3* db, char* path, reg_entry** entry,
+        reg_error* errPtr);
+
+int reg_entry_propget(sqlite3* db, reg_entry* entry, char* key, char** value,
+        reg_error* errPtr);
+int reg_entry_propset(sqlite3* db, reg_entry* entry, char* key, char* value,
+        reg_error* errPtr);
+
+int reg_entry_map(sqlite3* db, reg_entry* entry, char** files, int file_count,
+        reg_error* errPtr);
+int reg_entry_unmap(sqlite3* db, reg_entry* entry, char** files, int file_count,
+        reg_error* errPtr);
+
+int reg_entry_files(sqlite3* db, reg_entry* entry, char*** files,
+        reg_error* errPtr);
+
+int reg_all_entries(sqlite3* db, reg_entry*** entries, reg_error* errPtr);
+
+#endif /* _CENTRY_H */

Copied: trunk/base/src/cregistry/registry.c (from rev 27519, trunk/base/src/registry2.0/creg.c)
===================================================================
--- trunk/base/src/cregistry/registry.c	                        (rev 0)
+++ trunk/base/src/cregistry/registry.c	2007-08-06 20:12:35 UTC (rev 27520)
@@ -0,0 +1,162 @@
+/*
+ * registry.c
+ * $Id: $
+ *
+ * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sqlite3.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <cregistry/entry.h>
+#include <cregistry/sql.h>
+
+void reg_error_destruct(reg_error* errPtr) {
+    if (errPtr->free) {
+        errPtr->free(errPtr->description);
+    }
+}
+
+/**
+ * Sets `errPtr` according to the last error in `db`.
+ */
+void reg_sqlite_error(sqlite3* db, reg_error* errPtr, char* query) {
+    errPtr->code = "registry::sqlite-error";
+    errPtr->free = (reg_error_destructor*)sqlite3_free;
+    if (query == NULL) {
+        errPtr->description = sqlite3_mprintf("sqlite error: %s",
+                sqlite3_errmsg(db));
+    } else {
+        errPtr->description = sqlite3_mprintf("sqlite error: %s while "
+                "executing query: %s", sqlite3_errmsg(db), query);
+    }
+}
+
+int reg_open(sqlite3** dbPtr, reg_error* errPtr) {
+    if (sqlite3_open(NULL, dbPtr) == SQLITE_OK) {
+        if (init_db(*dbPtr, errPtr)) {
+            return 1;
+        } else {
+            sqlite3_close(*dbPtr);
+            *dbPtr = NULL;
+        }
+    } else {
+        reg_sqlite_error(*dbPtr, errPtr, NULL);
+        sqlite3_close(*dbPtr);
+        *dbPtr = NULL;
+    }
+    return 0;
+}
+
+int reg_close(sqlite3* db, reg_error* errPtr) {
+    if (sqlite3_close((sqlite3*)db) == SQLITE_OK) {
+        return 1;
+    } else {
+        errPtr->code = "registry::not-closed";
+        errPtr->description = sqlite3_mprintf("error: registry db not closed "
+                "correctly (%s)\n", sqlite3_errmsg((sqlite3*)db));
+        errPtr->free = (reg_error_destructor*)sqlite3_free;
+        return 0;
+    }
+}
+
+int reg_attach(sqlite3* db, const char* path, reg_error* errPtr) {
+    struct stat sb;
+    int needsInit = 0; /* registry doesn't yet exist */
+    int canWrite = 1; /* can write to this location */
+    if (stat(path, &sb) != 0) {
+        if (errno == ENOENT) {
+            needsInit = 1;
+        } else {
+            canWrite = 0;
+        }
+    }
+    if (!needsInit || canWrite) {
+        sqlite3_stmt* stmt;
+        char* query = sqlite3_mprintf("ATTACH DATABASE '%q' AS registry", path);
+        if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+                && (sqlite3_step(stmt) == SQLITE_DONE)) {
+            sqlite3_finalize(stmt);
+            if (!needsInit || (create_tables(db, errPtr))) {
+                return 1;
+            }
+        } else {
+            reg_sqlite_error(db, errPtr, query);
+            sqlite3_finalize(stmt);
+        }
+    } else {
+        errPtr->code = "registry::cannot-init";
+        errPtr->description = sqlite3_mprintf("port registry doesn't exist at \"%q\" and couldn't write to this location", path);
+        errPtr->free = (reg_error_destructor*)sqlite3_free;
+    }
+    return 0;
+}
+
+int reg_detach(sqlite3* db, reg_error* errPtr) {
+    sqlite3_stmt* stmt;
+    char* query = "DETACH DATABASE registry";
+    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
+            && (sqlite3_step(stmt) == SQLITE_DONE)) {
+        sqlite3_finalize(stmt);
+        query = "SELECT address FROM entries";
+        if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
+            int r;
+            reg_entry* entry;
+            do {
+                r = sqlite3_step(stmt);
+                switch (r) {
+                    case SQLITE_ROW:
+                        entry = *(reg_entry**)sqlite3_column_blob(stmt, 0);
+                        reg_entry_free(db, entry);
+                        break;
+                    case SQLITE_DONE:
+                        break;
+                    default:
+                        reg_sqlite_error(db, errPtr, query);
+                        return 0;
+                }
+            } while (r != SQLITE_DONE);
+        }
+        sqlite3_finalize(stmt);
+        query = "DELETE FROM entries";
+        if ((sqlite3_prepare(db, query, -1, &stmt, NULL) != SQLITE_OK)
+                || (sqlite3_step(stmt) != SQLITE_DONE)) {
+            sqlite3_finalize(stmt);
+            return 0;
+        }
+        return 1;
+    } else {
+        reg_sqlite_error(db, errPtr, query);
+        sqlite3_finalize(stmt);
+        return 0;
+    }
+}
+

Copied: trunk/base/src/cregistry/registry.h (from rev 27519, trunk/base/src/registry2.0/creg.h)
===================================================================
--- trunk/base/src/cregistry/registry.h	                        (rev 0)
+++ trunk/base/src/cregistry/registry.h	2007-08-06 20:12:35 UTC (rev 27520)
@@ -0,0 +1,58 @@
+/*
+ * registry.h
+ * $Id: $
+ *
+ * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _CREG_H
+#define _CREG_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sqlite3.h>
+
+typedef void reg_error_destructor(const char* description);
+
+typedef struct {
+    char* code;
+    const char* description;
+    reg_error_destructor* free;
+} reg_error;
+
+void reg_sqlite_error(sqlite3* db, reg_error* errPtr, char* query);
+void reg_error_destruct(reg_error* errPtr);
+
+typedef int (cast_function)(void* userdata, void** dst, void* src,
+        reg_error* errPtr);
+typedef void (free_function)(void* userdata, void* item);
+
+int reg_open(sqlite3** dbPtr, reg_error* errPtr);
+int reg_close(sqlite3* db, reg_error* errPtr);
+
+int reg_attach(sqlite3* db, const char* path, reg_error* errPtr);
+int reg_detach(sqlite3* db, reg_error* errPtr);
+
+#endif /* _CREG_H */

Copied: trunk/base/src/cregistry/sql.c (from rev 27519, trunk/base/src/registry2.0/sql.c)
===================================================================
--- trunk/base/src/cregistry/sql.c	                        (rev 0)
+++ trunk/base/src/cregistry/sql.c	2007-08-06 20:12:35 UTC (rev 27520)
@@ -0,0 +1,300 @@
+/*
+ * sql.c
+ * $Id: $
+ *
+ * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tcl.h>
+#include <sqlite3.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <cregistry/registry.h>
+#include <cregistry/sql.h>
+
+/**
+ * Executes a null-terminated list of queries.
+ *
+ * Pass it a list of queries, it'll execute them. This is mainly intended for
+ * initialization, when you have a number of standard queries to execute.
+ */
+int do_queries(sqlite3* db, char** queries, reg_error* errPtr) {
+    char** query;
+    for (query = queries; *query != NULL; query++) {
+        sqlite3_stmt* stmt;
+        if ((sqlite3_prepare(db, *query, -1, &stmt, NULL) != SQLITE_OK)
+                || (sqlite3_step(stmt) != SQLITE_DONE)) {
+            reg_sqlite_error(db, errPtr, *query);
+            sqlite3_finalize(stmt);
+            return 0;
+        }
+        sqlite3_finalize(stmt);
+    }
+    return 1;
+}
+
+/**
+ * REGEXP function for sqlite3.
+ *
+ * Takes two arguments; the first is the value and the second the pattern. If
+ * the pattern is invalid, errors out. Otherwise, returns true if the value
+ * matches the pattern and false otherwise.
+ *
+ * This function is available in sqlite3 as the REGEXP operator.
+ */
+static void sql_regexp(sqlite3_context* context, int argc UNUSED,
+        sqlite3_value** argv) {
+    const char* value = sqlite3_value_text(argv[0]);
+    const char* pattern = sqlite3_value_text(argv[1]);
+    switch (Tcl_RegExpMatch(NULL, value, pattern)) {
+        case 0:
+            sqlite3_result_int(context, 0);
+            break;
+        case 1:
+            sqlite3_result_int(context, 1);
+            break;
+        case -1:
+            sqlite3_result_error(context, "invalid pattern", -1);
+            break;
+    }
+}
+
+/**
+ * NOW function for sqlite3.
+ *
+ * Takes no arguments. Returns the unix timestamp of now.
+ */
+static void sql_now(sqlite3_context* context, int argc UNUSED,
+        sqlite3_value** argv UNUSED) {
+    sqlite3_result_int(context, time(NULL));
+}
+
+static int rpm_vercomp (const char *versionA, int lengthA, const char *versionB,
+        int lengthB) {
+    const char *endA, *endB;
+	const char *ptrA, *ptrB;
+	const char *eptrA, *eptrB;
+
+    if (lengthA < 0)
+        lengthA = strlen(versionA);
+    if (lengthB < 0)
+        lengthB = strlen(versionB);
+
+	/* if versions equal, return zero */
+	if(lengthA == lengthB && !strncmp(versionA, versionB, lengthA))
+		return 0;
+
+	ptrA = versionA;
+	ptrB = versionB;
+    endA = versionA + lengthA;
+    endB = versionB + lengthB;
+	while (ptrA != endA && ptrB != endB) {
+		/* skip all non-alphanumeric characters */
+		while (ptrA != endB && !isalnum(*ptrA))
+			ptrA++;
+		while (ptrB != endB && !isalnum(*ptrB))
+			ptrB++;
+
+		eptrA = ptrA;
+		eptrB = ptrB;
+
+		/* Somewhat arbitrary rules as per RPM's implementation.
+		 * This code could be more clever, but we're aiming
+		 * for clarity instead. */
+
+		/* If versionB's segment is not a digit segment, but
+		 * versionA's segment IS a digit segment, return 1.
+		 * (Added for redhat compatibility. See redhat bugzilla
+		 * #50977 for details) */
+		if (!isdigit(*ptrB)) {
+			if (isdigit(*ptrA))
+				return 1;
+		}
+
+		/* Otherwise, if the segments are of different types,
+		 * return -1 */
+
+		if ((isdigit(*ptrA) && isalpha(*ptrB)) || (isalpha(*ptrA) && isdigit(*ptrB)))
+			return -1;
+
+		/* Find the first segment composed of entirely alphabetical
+		 * or numeric members */
+		if (isalpha(*ptrA)) {
+			while (eptrA != endA && isalpha(*eptrA))
+				eptrA++;
+
+			while (eptrB != endB && isalpha(*eptrB))
+				eptrB++;
+		} else {
+			int countA = 0, countB = 0;
+			while (eptrA != endA && isdigit(*eptrA)) {
+				countA++;
+				eptrA++;
+			}
+			while (eptrB != endB && isdigit(*eptrB)) {
+				countB++;
+				eptrB++;
+			}
+
+			/* skip leading '0' characters */
+			while (ptrA != eptrA && *ptrA == '0') {
+				ptrA++;
+				countA--;
+			}
+			while (ptrB != eptrB && *ptrB == '0') {
+				ptrB++;
+				countB--;
+			}
+
+			/* If A is longer than B, return 1 */
+			if (countA > countB)
+				return 1;
+
+			/* If B is longer than A, return -1 */
+			if (countB > countA)
+				return -1;
+		}
+		/* Compare strings lexicographically */
+		while (ptrA != eptrA && ptrB != eptrB && *ptrA == *ptrB) {
+				ptrA++;
+				ptrB++;
+		}
+		if (ptrA != eptrA && ptrB != eptrB)
+			return *ptrA - *ptrB;
+
+		ptrA = eptrA;
+		ptrB = eptrB;
+	}
+
+	/* If both pointers are null, all alphanumeric
+	 * characters were identical and only seperating
+	 * characters differed. According to RPM, these
+	 * version strings are equal */
+	if (ptrA == endA && ptrB == endB)
+		return 0;
+
+	/* If A has unchecked characters, return 1
+	 * Otherwise, if B has remaining unchecked characters,
+	 * return -1 */
+	if (ptrA != endA)
+		return 1;
+	else
+		return -1;
+}
+
+/**
+ * VERSION collation for sqlite3.
+ *
+ * This function collates text according to pextlib's rpm-vercomp function. This
+ * allows direct comparison and sorting of version columns, such as port.version
+ * and port.revision.
+ *
+ * TODO: share rpm-vercomp properly with pextlib. Currently it's copy-pasted in.
+ */
+static int sql_version(void* userdata UNUSED, int alen, const void* a, int blen,
+        const void* b) {
+    return rpm_vercomp((const char*)a, alen, (const char*)b, blen);
+}
+
+/**
+ * Creates tables in the registry.
+ *
+ * This function is called upon an uninitialized database to create the tables
+ * needed to record state between invocations of `port`.
+ */
+int create_tables(sqlite3* db, reg_error* errPtr) {
+    static char* queries[] = {
+        "BEGIN",
+
+        /* metadata table */
+        "CREATE TABLE registry.metadata (key UNIQUE, value)",
+        "INSERT INTO registry.metadata (key, value) VALUES ('version', 1.000)",
+        "INSERT INTO registry.metadata (key, value) VALUES ('created', NOW())",
+
+        /* ports table */
+        "CREATE TABLE registry.ports ("
+            "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+            "name, portfile, url, location, epoch, version COLLATE VERSION, "
+            "revision COLLATE VERSION, variants, state, date, "
+            "UNIQUE (name, epoch, version, revision, variants), "
+            "UNIQUE (url, epoch, version, revision, variants)"
+            ")",
+        "CREATE INDEX registry.port_name ON ports "
+            "(name, epoch, version, revision, variants)",
+        "CREATE INDEX registry.port_url ON ports "
+            "(url, epoch, version, revision, variants)",
+        "CREATE INDEX registry.port_state ON ports (state)",
+
+        /* file map */
+        "CREATE TABLE registry.files (id, path UNIQUE, mtime)",
+        "CREATE INDEX registry.file_port ON files (id)",
+
+        "END",
+        NULL
+    };
+    return do_queries(db, queries, errPtr);
+}
+
+/**
+ * Initializes database connection.
+ *
+ * This function creates all the temporary tables used by the registry. It also
+ * registers the user functions and collations declared in "sql.h", making them
+ * available.
+ */
+int init_db(sqlite3* db, reg_error* errPtr) {
+    static char* queries[] = {
+        "BEGIN",
+
+        /* items cache */
+        "CREATE TEMPORARY TABLE items (refcount, proc UNIQUE, name, url, path, "
+            "worker, options, variants)",
+
+        /* indexes list */
+        "CREATE TEMPORARY TABLE indexes (file, name, attached)",
+
+        /* entry addresses */
+        "CREATE TEMPORARY TABLE entries (id, address)",
+
+        "END",
+        NULL
+    };
+
+    /* I'm not error-checking these. I don't think I need to. */
+    sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, NULL, sql_regexp,
+            NULL, NULL);
+    sqlite3_create_function(db, "NOW", 0, SQLITE_ANY, NULL, sql_now, NULL,
+            NULL);
+
+    sqlite3_create_collation(db, "VERSION", SQLITE_UTF8, NULL, sql_version);
+
+    return do_queries(db, queries, errPtr);
+}
+

Copied: trunk/base/src/cregistry/sql.h (from rev 27519, trunk/base/src/registry2.0/sql.h)
===================================================================
--- trunk/base/src/cregistry/sql.h	                        (rev 0)
+++ trunk/base/src/cregistry/sql.h	2007-08-06 20:12:35 UTC (rev 27520)
@@ -0,0 +1,42 @@
+/*
+ * sql.h
+ * $Id: $
+ *
+ * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SQL_H
+#define _SQL_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sqlite3.h>
+
+#include <cregistry/registry.h>
+
+int create_tables(sqlite3* db, reg_error* errPtr);
+int init_db(sqlite3* db, reg_error* errPtr);
+
+#endif /* _SQL_H */

Modified: trunk/base/src/registry2.0/Makefile
===================================================================
--- trunk/base/src/registry2.0/Makefile	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/Makefile	2007-08-06 20:12:35 UTC (rev 27520)
@@ -1,5 +1,4 @@
-OBJS=       registry.o util.o sql.o \
-			creg.o centry.o \
+OBJS=       registry.o util.o \
 			entry.o entryobj.o
 			#graph.o graphobj.o
 SHLIB_NAME= registry${SHLIB_SUFFIX}

Deleted: trunk/base/src/registry2.0/centry.c
===================================================================
--- trunk/base/src/registry2.0/centry.c	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/centry.c	2007-08-06 20:12:35 UTC (rev 27520)
@@ -1,700 +0,0 @@
-/*
- * centry.c
- * $Id: $
- *
- * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-#include <sqlite3.h>
-
-#include "centry.h"
-#include "creg.h"
-
-/**
- * Concatenates `src` to string `dst`.
- *
- * Simple concatenation. Only guaranteed to work with strings that have been
- * allocated with `malloc`. Amortizes cost of expanding string buffer for O(N)
- * concatenation and such. Uses `memcpy` in favor of `strcpy` in hopes it will
- * perform a bit better. If passing in a static string to dst, make sure
- * dst_space starts at dst_len. Also make sure dst_space is never 0 (so don't
- * use "" as the starter string, allocate some space);
- */
-void reg_strcat(char** dst, int* dst_len, int* dst_space, char* src) {
-    int src_len = strlen(src);
-    if (*dst_len + src_len >= *dst_space) {
-        char* old_dst = *dst;
-        char* new_dst = malloc(*dst_space * 2 * sizeof(char));
-        *dst_space *= 2;
-        memcpy(new_dst, old_dst, *dst_len);
-        *dst = new_dst;
-        free(old_dst);
-    }
-    memcpy(&((*dst)[*dst_len]), src, src_len+1);
-    *dst_len += src_len;
-}
-
-/**
- * Appends `src` to the list `dst`.
- *
- * It's like `reg_strcat`, except `src` represents an element and not a sequence
- * of `char`s.
- */
-static void reg_listcat(void*** dst, int* dst_len, int* dst_space, void* src) {
-    if (*dst_len == *dst_space) {
-        void** old_dst = *dst;
-        void** new_dst = malloc(*dst_space * 2 * sizeof(void*));
-        *dst_space *= 2;
-        memcpy(new_dst, old_dst, *dst_len);
-        *dst = new_dst;
-        free(old_dst);
-    }
-    (*dst)[*dst_len] = src;
-    (*dst_len)++;
-}
-
-/**
- * Returns the operator to use for the given strategy.
- */
-static char* reg_strategy_op(int strategy, reg_error* errPtr) {
-    switch (strategy) {
-        case 0:
-            return "=";
-        case 1:
-            return " GLOB ";
-        case 2:
-            return " REGEXP ";
-        default:
-            errPtr->code = "registry::invalid-strategy";
-            errPtr->description = "invalid matching strategy specified";
-            errPtr->free = NULL;
-            return NULL;
-    }
-}
-
-static int reg_stmt_to_entry(void* userdata, void** entry, void* stmt,
-        reg_error* errPtr UNUSED) {
-    if (sqlite3_column_type(stmt, 1) == SQLITE_NULL) {
-        reg_entry* e = malloc(sizeof(reg_entry));
-        e->db = (sqlite3*)userdata;
-        e->id = sqlite3_column_int64(stmt, 0);
-        e->saved = 0;
-        e->proc = NULL;
-        *entry = e;
-    } else {
-        *entry = *(reg_entry**)sqlite3_column_blob(stmt, 1);
-    }
-    return 1;
-}
-
-static int reg_save_addresses(sqlite3* db, reg_entry** entries,
-        int entry_count, reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    int i;
-    char* query = "INSERT INTO entries (id, address) VALUES (?, ?)";
-    /* avoid unnecessarily making queries */
-    for (i=0; i<entry_count; i++) {
-        if (!entries[i]->saved) {
-            break;
-        }
-    }
-    if (i == entry_count) {
-        return 1;
-    }
-    /* BEGIN */
-    if (sqlite3_prepare(db, query, -1, &stmt, NULL)
-                == SQLITE_OK) {
-        for (i=0; i<entry_count; i++) {
-            if (entries[i]->saved) {
-                continue;
-            }
-            if ((sqlite3_bind_int64(stmt, 1, entries[i]->id) == SQLITE_OK)
-                    && (sqlite3_bind_blob(stmt, 2, &entries[i],
-                            sizeof(reg_entry*), SQLITE_TRANSIENT) == SQLITE_OK)
-                    && (sqlite3_step(stmt) == SQLITE_DONE)) {
-                sqlite3_reset(stmt);
-            } else {
-                sqlite3_finalize(stmt);
-                reg_sqlite_error(db, errPtr, query);
-            }
-        }
-        sqlite3_finalize(stmt);
-        return 1;
-    } else {
-        sqlite3_finalize(stmt);
-        reg_sqlite_error(db, errPtr, query);
-    }
-    return 0;
-}
-
-/**
- * registry::entry create portname version revision variants epoch ?name?
- *
- * Unlike the old registry::new_entry, revision, variants, and epoch are all
- * required. That's OK because there's only one place this function is called,
- * and it's called with all of them there.
- */
-reg_entry* reg_entry_create(sqlite3* db, char* name, char* version,
-        char* revision, char* variants, char* epoch, reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    char* query = "INSERT INTO registry.ports "
-        "(name, version, revision, variants, epoch) VALUES (?, ?, ?, ?, ?)";
-    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC)
-                == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 2, version, -1, SQLITE_STATIC)
-                == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 3, revision, -1, SQLITE_STATIC)
-                == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 4, variants, -1, SQLITE_STATIC)
-                == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 5, epoch, -1, SQLITE_STATIC)
-                == SQLITE_OK)
-            && (sqlite3_step(stmt) == SQLITE_DONE)) {
-        char* query = "INSERT INTO entries (id, address) VALUES (?, ?)";
-        reg_entry* entry = malloc(sizeof(reg_entry));
-        entry->id = sqlite3_last_insert_rowid(db);
-        entry->db = db;
-        entry->proc = NULL;
-        sqlite3_finalize(stmt);
-        if ((sqlite3_prepare(db, query, -1, &stmt, NULL)
-                == SQLITE_OK)
-                && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)
-                && (sqlite3_bind_blob(stmt, 2, &entry, sizeof(reg_entry*),
-                        SQLITE_TRANSIENT) == SQLITE_OK)
-                && (sqlite3_step(stmt) == SQLITE_DONE)) {
-            return entry;
-        } else {
-            reg_sqlite_error(db, errPtr, query);
-        }
-        free(entry);
-        return NULL;
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        sqlite3_finalize(stmt);
-        return NULL;
-    }
-}
-
-reg_entry* reg_entry_open(sqlite3* db, char* name, char* version,
-        char* revision, char* variants, char* epoch, reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    char* query = "SELECT registry.ports.id, entries.address "
-        "FROM registry.ports LEFT OUTER JOIN entries USING (id) "
-        "WHERE name=? AND version=? AND revision=? AND variants=? AND epoch=?";
-    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC)
-                == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 2, version, -1, SQLITE_STATIC)
-                == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 3, revision, -1, SQLITE_STATIC)
-                == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 4, variants, -1, SQLITE_STATIC)
-                == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 5, epoch, -1, SQLITE_STATIC)
-                == SQLITE_OK)) {
-        int r = sqlite3_step(stmt);
-        reg_entry* entry;
-        switch (r) {
-            case SQLITE_ROW:
-                if (reg_stmt_to_entry(db, (void**)&entry, stmt, errPtr)) {
-                    sqlite3_finalize(stmt);
-                    if (reg_save_addresses(db, &entry, 1, errPtr)) {
-                        return entry;
-                    }
-                }
-            case SQLITE_DONE:
-                errPtr->code = "registry::not-found";
-                errPtr->description = "no matching port found";
-                errPtr->free = NULL;
-                break;
-            default:
-                reg_sqlite_error(db, errPtr, query);
-                break;
-        }
-        sqlite3_finalize(stmt);
-        return NULL;
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        sqlite3_finalize(stmt);
-        return NULL;
-    }
-}
-
-/**
- * deletes an entry; still needs to be freed
- */
-int reg_entry_delete(sqlite3* db, reg_entry* entry, reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    char* query = "DELETE FROM registry.ports WHERE id=?";
-    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-            && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)
-            && (sqlite3_step(stmt) == SQLITE_DONE)) {
-        if (sqlite3_changes(db) > 0) {
-            sqlite3_finalize(stmt);
-            query = "DELETE FROM entries WHERE id=?";
-            if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-                    && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)
-                    && (sqlite3_step(stmt) == SQLITE_DONE)) {
-                sqlite3_finalize(stmt);
-                return 1;
-            }
-        } else {
-            errPtr->code = "registry::invalid-entry";
-            errPtr->description = "an invalid entry was passed";
-            errPtr->free = NULL;
-        }
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-    }
-    sqlite3_finalize(stmt);
-    return 0;
-}
-
-/*
- * Frees the entries in `entries`.
- */
-void reg_entry_free(sqlite3* db UNUSED, reg_entry* entry) {
-    sqlite3_stmt* stmt;
-    if (entry->proc != NULL) {
-        free(entry->proc);
-    }
-    free(entry);
-    sqlite3_prepare(entry->db, "DELETE FROM entries WHERE address=?", -1, &stmt,
-            NULL);
-    sqlite3_bind_blob(stmt, 1, &entry, sizeof(reg_entry*), SQLITE_TRANSIENT);
-    sqlite3_step(stmt);
-}
-
-static int reg_all_objects(sqlite3* db, char* query, int query_len,
-        void*** objects, cast_function* fn, free_function* del,
-        reg_error* errPtr) {
-    int r;
-    reg_entry* entry;
-    void** results = malloc(10*sizeof(void*));
-    int result_count = 0;
-    int result_space = 10;
-    sqlite3_stmt* stmt;
-    if (sqlite3_prepare(db, query, query_len, &stmt, NULL) == SQLITE_OK) {
-        do {
-            int i;
-            r = sqlite3_step(stmt);
-            switch (r) {
-                case SQLITE_ROW:
-                    if (fn(db, (void**)&entry, stmt, errPtr)) {
-                        reg_listcat(&results, &result_count, &result_space,
-                                entry);
-                        continue;
-                    } else {
-                        int i;
-                        sqlite3_finalize(stmt);
-                        for (i=0; i<result_count; i++) {
-                            del(NULL, results[i]);
-                        }
-                        free(results);
-                        return -1;
-                    }
-                case SQLITE_DONE:
-                    break;
-                default:
-                    for (i=0; i<result_count; i++) {
-                        del(NULL, results[i]);
-                    }
-                    free(results);
-                    sqlite3_finalize(stmt);
-                    reg_sqlite_error(db, errPtr, query);
-                    return -1;
-            }
-        } while (r != SQLITE_DONE);
-        *objects = results;
-        return result_count;
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        free(results);
-        return -1;
-    }
-}
-
-/*
- * Searches the registry for ports for which each key's value is equal to the
- * given value. To find all ports, pass 0 key-value pairs.
- *
- * Vulnerable to SQL-injection attacks in the `keys` field. Pass it valid keys,
- * please.
- */
-int reg_entry_search(sqlite3* db, char** keys, char** vals, int key_count,
-        int strategy, reg_entry*** entries, reg_error* errPtr) {
-    int i;
-    char* kwd = " WHERE ";
-    char* query;
-    int query_len = 32;
-    int query_space = 32;
-    int result;
-    /* get the strategy */
-    char* op = reg_strategy_op(strategy, errPtr);
-    if (op == NULL) {
-        return -1;
-    }
-    /* build the query */
-    query = strdup("SELECT registry.ports.id, entries.address "
-            "FROM registry.ports LEFT OUTER JOIN entries USING (id)");
-    for (i=0; i<key_count; i+=1) {
-        char* cond = sqlite3_mprintf("%s%s%s'%q'", kwd, keys[i], op, vals[i]);
-        reg_strcat(&query, &query_len, &query_space, cond);
-        sqlite3_free(cond);
-        kwd = " AND ";
-    }
-    /* do the query */
-    result = reg_all_objects(db, query, query_len, (void***)entries,
-            reg_stmt_to_entry, (free_function*)reg_entry_free, errPtr);
-    if (result > 0) {
-        if (!reg_save_addresses(db, *entries, result, errPtr)) {
-            free(entries);
-            return 0;
-        }
-    }
-    free(query);
-    return result;
-}
-
-/**
- * TODO: fix this to return ports where state=active too
- * TODO: add more arguments (epoch, revision, variants), maybe
- */
-int reg_entry_installed(sqlite3* db, char* name, char* version, 
-        reg_entry*** entries, reg_error* errPtr) {
-    char* format;
-    char* query;
-    int result;
-    char* select = "SELECT registry.ports.id, entries.address FROM "
-        "registry.ports LEFT OUTER JOIN entries USING (id)";
-    if (name == NULL) {
-        format = "%s WHERE (state='installed' OR state='active')";
-    } else if (version == NULL) {
-        format = "%s WHERE (state='installed' OR state='active') AND name='%q'";
-    } else {
-        format = "%s WHERE (state='installed' OR state='active') AND name='%q' "
-            "AND version='%q'";
-    }
-    query = sqlite3_mprintf(format, select, name, version);
-    result = reg_all_objects(db, query, -1, (void***)entries,
-            reg_stmt_to_entry, (free_function*)reg_entry_free, errPtr);
-    if (result > 0) {
-        if (!reg_save_addresses(db, *entries, result, errPtr)) {
-            free(entries);
-            return 0;
-        }
-    }
-    sqlite3_free(query);
-    return result;
-}
-
-/**
- */
-int reg_entry_active(sqlite3* db, char* name, reg_entry*** entries,
-        reg_error* errPtr) {
-    char* format;
-    char* query;
-    int result;
-    char* select = "SELECT registry.ports.id, entries.address FROM "
-        "registry.ports LEFT OUTER JOIN entries USING (id)";
-    if (name == NULL) {
-        format = "%s WHERE state='active'";
-    } else {
-        format = "%s WHERE state='active' AND name='%q'";
-    }
-    query = sqlite3_mprintf(format, select, name);
-    result = reg_all_objects(db, query, -1, (void***)entries,
-            reg_stmt_to_entry, (free_function*)reg_entry_free, errPtr);
-    if (result > 0) {
-        if (!reg_save_addresses(db, *entries, result, errPtr)) {
-            free(entries);
-            return 0;
-        }
-    }
-    sqlite3_free(query);
-    return result;
-}
-
-int reg_entry_owner(sqlite3* db, char* path, reg_entry** entry,
-        reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    reg_entry* result;
-    char* query = "SELECT registry.files.id, entries.address "
-        "FROM registry.files LEFT OUTER JOIN entries USING (id) "
-        "WHERE path=?";
-    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-            && (sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC)
-                == SQLITE_OK)) {
-        int r = sqlite3_step(stmt);
-        switch (r) {
-            case SQLITE_ROW:
-                if (reg_stmt_to_entry(db, (void**)&result, stmt, errPtr)) {
-                    sqlite3_finalize(stmt);
-                    if (reg_save_addresses(db, &result, 1, errPtr)) {
-                        *entry = result;
-                        return 1;
-                    }
-                }
-            case SQLITE_DONE:
-                sqlite3_finalize(stmt);
-                *entry = NULL;
-                return 1;
-            default:
-                /* barf */
-                sqlite3_finalize(stmt);
-                return 0;
-        }
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        sqlite3_finalize(stmt);
-        return 0;
-    }
-}
-
-int reg_entry_propget(sqlite3* db, reg_entry* entry, char* key, char** value,
-        reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    char* query = sqlite3_mprintf("SELECT %q FROM registry.ports "
-            "WHERE id=%lld", key, entry->id);
-    if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
-        int r = sqlite3_step(stmt);
-        switch (r) {
-            case SQLITE_ROW:
-                *value = strdup(sqlite3_column_text(stmt, 0));
-                sqlite3_finalize(stmt);
-                return 1;
-            case SQLITE_DONE:
-                errPtr->code = "registry::invalid-entry";
-                errPtr->description = "an invalid entry was passed";
-                errPtr->free = NULL;
-                sqlite3_finalize(stmt);
-                return 0;
-            default:
-                reg_sqlite_error(db, errPtr, query);
-                sqlite3_finalize(stmt);
-                return 0;
-        }
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        return 0;
-    }
-}
-
-int reg_entry_propset(sqlite3* db, reg_entry* entry, char* key, char* value,
-        reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    char* query = sqlite3_mprintf("UPDATE registry.ports SET %q = '%q' "
-            "WHERE id=%lld", key, value, entry->id);
-    if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
-        int r = sqlite3_step(stmt);
-        switch (r) {
-            case SQLITE_DONE:
-                sqlite3_finalize(stmt);
-                return 1;
-            default:
-                switch (sqlite3_reset(stmt)) {
-                    case SQLITE_CONSTRAINT:
-                        errPtr->code = "registry::constraint";
-                        errPtr->description = "a constraint was disobeyed";
-                        errPtr->free = NULL;
-                        sqlite3_finalize(stmt);
-                        return 0;
-                    default:
-                        reg_sqlite_error(db, errPtr, query);
-                        sqlite3_finalize(stmt);
-                        return 0;
-                }
-        }
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        return 0;
-    }
-}
-
-int reg_entry_map(sqlite3* db, reg_entry* entry, char** files, int file_count,
-        reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    char* query = "INSERT INTO registry.files (id, path) VALUES (?, ?)";
-    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-            && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)) {
-        int i;
-        for (i=0; i<file_count; i++) {
-            if (sqlite3_bind_text(stmt, 2, files[i], -1, SQLITE_STATIC)
-                    == SQLITE_OK) {
-                int r = sqlite3_step(stmt);
-                switch (r) {
-                    case SQLITE_DONE:
-                        sqlite3_reset(stmt);
-                        continue;
-                    case SQLITE_ERROR:
-                        switch (sqlite3_reset(stmt)) {
-                            case SQLITE_CONSTRAINT:
-                                errPtr->code = "registry::already-owned";
-                                errPtr->description = "mapped file is already "
-                                    "owned by another entry";
-                                errPtr->free = NULL;
-                                sqlite3_finalize(stmt);
-                                return i;
-                            default:
-                                reg_sqlite_error(db, errPtr, query);
-                                sqlite3_finalize(stmt);
-                                return i;
-                        }
-                }
-            } else {
-                reg_sqlite_error(db, errPtr, query);
-                sqlite3_finalize(stmt);
-                return i;
-            }
-        }
-        sqlite3_finalize(stmt);
-        return file_count;
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        sqlite3_finalize(stmt);
-        return 0;
-    }
-}
-
-int reg_entry_unmap(sqlite3* db, reg_entry* entry, char** files, int file_count,
-        reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    char* query = "DELETE FROM registry.files WHERE id=? AND path=?";
-    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-            && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)) {
-        int i;
-        for (i=0; i<file_count; i++) {
-            if (sqlite3_bind_text(stmt, 2, files[i], -1, SQLITE_STATIC)
-                    == SQLITE_OK) {
-                int r = sqlite3_step(stmt);
-                switch (r) {
-                    case SQLITE_DONE:
-                        if (sqlite3_changes(db) == 0) {
-                            errPtr->code = "registry::not-owned";
-                            errPtr->description = "this entry does not own the "
-                                "given file";
-                            errPtr->free = NULL;
-                            sqlite3_finalize(stmt);
-                            return i;
-                        } else {
-                            sqlite3_reset(stmt);
-                            continue;
-                        }
-                    default:
-                        reg_sqlite_error(db, errPtr, query);
-                        sqlite3_finalize(stmt);
-                        return i;
-                }
-            } else {
-                reg_sqlite_error(db, errPtr, query);
-                sqlite3_finalize(stmt);
-                return i;
-            }
-        }
-        sqlite3_finalize(stmt);
-        return file_count;
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        sqlite3_finalize(stmt);
-        return 0;
-    }
-}
-
-int reg_entry_files(sqlite3* db, reg_entry* entry, char*** files,
-        reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    char* query = "SELECT path FROM registry.files WHERE id=? ORDER BY path";
-    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-            && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)) {
-        char** result = malloc(10*sizeof(char*));
-        int result_count = 0;
-        int result_space = 10;
-        int r;
-        do {
-            char* element;
-            int i;
-            r = sqlite3_step(stmt);
-            switch (r) {
-                case SQLITE_ROW:
-                    element = strdup(sqlite3_column_text(stmt, 0));
-                    reg_listcat((void*)&result, &result_count, &result_space,
-                            element);
-                    break;
-                case SQLITE_DONE:
-                    break;
-                default:
-                    for (i=0; i<result_count; i++) {
-                        free(result[i]);
-                    }
-                    free(result);
-                    reg_sqlite_error(db, errPtr, query);
-                    sqlite3_finalize(stmt);
-                    return -1;
-            }
-        } while (r != SQLITE_DONE);
-        sqlite3_finalize(stmt);
-        *files = result;
-        return result_count;
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        sqlite3_finalize(stmt);
-        return -1;
-    }
-}
-
-int reg_all_entries(sqlite3* db, reg_entry*** entries, reg_error* errPtr) {
-    reg_entry* entry;
-    void** results = malloc(10*sizeof(void*));
-    int result_count = 0;
-    int result_space = 10;
-    sqlite3_stmt* stmt;
-    char* query = "SELECT address FROM entries";
-    if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
-        int r;
-        do {
-            r = sqlite3_step(stmt);
-            switch (r) {
-                case SQLITE_ROW:
-                    entry = *(reg_entry**)sqlite3_column_blob(stmt, 0);
-                    reg_listcat(&results, &result_count, &result_space, entry);
-                    break;
-                case SQLITE_DONE:
-                    break;
-                default:
-                    reg_sqlite_error(db, errPtr, query);
-                    free(results);
-                    return -1;
-            }
-        } while (r != SQLITE_DONE);
-    }
-    *entries = (reg_entry**)results;
-    return result_count;
-}

Deleted: trunk/base/src/registry2.0/centry.h
===================================================================
--- trunk/base/src/registry2.0/centry.h	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/centry.h	2007-08-06 20:12:35 UTC (rev 27520)
@@ -1,86 +0,0 @@
-/*
- * centry.h
- * $Id: $
- *
- * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _CENTRY_H
-#define _CENTRY_H
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sqlite3.h>
-#include "creg.h"
-
-typedef struct {
-    sqlite_int64 id; /* rowid in database */
-    sqlite3* db; /* database */
-    int saved; /* have we recorded &entry in database? */
-    char* proc; /* name of Tcl proc, if using Tcl */
-} reg_entry;
-
-typedef int (cast_function)(void* userdata, void** dst, void* src,
-        reg_error* errPtr);
-typedef void (free_function)(void* userdata, void* item);
-
-reg_entry* reg_entry_create(sqlite3* db, char* name, char* version,
-        char* revision, char* variants, char* epoch, reg_error* errPtr);
-
-reg_entry* reg_entry_open(sqlite3* db, char* name, char* version,
-        char* revision, char* variants, char* epoch, reg_error* errPtr);
-
-int reg_entry_delete(sqlite3* db, reg_entry* entry, reg_error* errPtr);
-
-void reg_entry_free(sqlite3* db, reg_entry* entry);
-
-int reg_entry_search(sqlite3* db, char** keys, char** vals, int key_count,
-        int strategy, reg_entry*** entries, reg_error* errPtr);
-
-int reg_entry_installed(sqlite3* db, char* name, char* version, 
-        reg_entry*** entries, reg_error* errPtr);
-
-int reg_entry_active(sqlite3* db, char* name, reg_entry*** entries,
-        reg_error* errPtr);
-
-int reg_entry_owner(sqlite3* db, char* path, reg_entry** entry,
-        reg_error* errPtr);
-
-int reg_entry_propget(sqlite3* db, reg_entry* entry, char* key, char** value,
-        reg_error* errPtr);
-int reg_entry_propset(sqlite3* db, reg_entry* entry, char* key, char* value,
-        reg_error* errPtr);
-
-int reg_entry_map(sqlite3* db, reg_entry* entry, char** files, int file_count,
-        reg_error* errPtr);
-int reg_entry_unmap(sqlite3* db, reg_entry* entry, char** files, int file_count,
-        reg_error* errPtr);
-
-int reg_entry_files(sqlite3* db, reg_entry* entry, char*** files,
-        reg_error* errPtr);
-
-int reg_all_entries(sqlite3* db, reg_entry*** entries, reg_error* errPtr);
-
-#endif /* _CENTRY_H */

Deleted: trunk/base/src/registry2.0/creg.c
===================================================================
--- trunk/base/src/registry2.0/creg.c	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/creg.c	2007-08-06 20:12:35 UTC (rev 27520)
@@ -1,165 +0,0 @@
-/*
- * reg.c
- * $Id: $
- *
- * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sqlite3.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include "graph.h"
-#include "item.h"
-#include "entry.h"
-#include "util.h"
-#include "sql.h"
-
-void reg_error_destruct(reg_error* errPtr) {
-    if (errPtr->free) {
-        errPtr->free(errPtr->description);
-    }
-}
-
-/**
- * Sets `errPtr` according to the last error in `db`.
- */
-void reg_sqlite_error(sqlite3* db, reg_error* errPtr, char* query) {
-    errPtr->code = "registry::sqlite-error";
-    errPtr->free = (reg_error_destructor*)sqlite3_free;
-    if (query == NULL) {
-        errPtr->description = sqlite3_mprintf("sqlite error: %s",
-                sqlite3_errmsg(db));
-    } else {
-        errPtr->description = sqlite3_mprintf("sqlite error: %s while "
-                "executing query: %s", sqlite3_errmsg(db), query);
-    }
-}
-
-int reg_open(sqlite3** dbPtr, reg_error* errPtr) {
-    if (sqlite3_open(NULL, dbPtr) == SQLITE_OK) {
-        if (init_db(*dbPtr, errPtr)) {
-            return 1;
-        } else {
-            sqlite3_close(*dbPtr);
-            *dbPtr = NULL;
-        }
-    } else {
-        reg_sqlite_error(*dbPtr, errPtr, NULL);
-        sqlite3_close(*dbPtr);
-        *dbPtr = NULL;
-    }
-    return 0;
-}
-
-int reg_close(sqlite3* db, reg_error* errPtr) {
-    if (sqlite3_close((sqlite3*)db) == SQLITE_OK) {
-        return 1;
-    } else {
-        errPtr->code = "registry::not-closed";
-        errPtr->description = sqlite3_mprintf("error: registry db not closed "
-                "correctly (%s)\n", sqlite3_errmsg((sqlite3*)db));
-        errPtr->free = (reg_error_destructor*)sqlite3_free;
-        return 0;
-    }
-}
-
-int reg_attach(sqlite3* db, const char* path, reg_error* errPtr) {
-    struct stat sb;
-    int needsInit = 0; /* registry doesn't yet exist */
-    int canWrite = 1; /* can write to this location */
-    if (stat(path, &sb) != 0) {
-        if (errno == ENOENT) {
-            needsInit = 1;
-        } else {
-            canWrite = 0;
-        }
-    }
-    if (!needsInit || canWrite) {
-        sqlite3_stmt* stmt;
-        char* query = sqlite3_mprintf("ATTACH DATABASE '%q' AS registry", path);
-        if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-                && (sqlite3_step(stmt) == SQLITE_DONE)) {
-            sqlite3_finalize(stmt);
-            if (!needsInit || (create_tables(db, errPtr))) {
-                return 1;
-            }
-        } else {
-            reg_sqlite_error(db, errPtr, query);
-            sqlite3_finalize(stmt);
-        }
-    } else {
-        errPtr->code = "registry::cannot-init";
-        errPtr->description = sqlite3_mprintf("port registry doesn't exist at \"%q\" and couldn't write to this location", path);
-        errPtr->free = (reg_error_destructor*)sqlite3_free;
-    }
-    return 0;
-}
-
-int reg_detach(sqlite3* db, reg_error* errPtr) {
-    sqlite3_stmt* stmt;
-    char* query = "DETACH DATABASE registry";
-    if ((sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK)
-            && (sqlite3_step(stmt) == SQLITE_DONE)) {
-        sqlite3_finalize(stmt);
-        query = "SELECT address FROM entries";
-        if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
-            int r;
-            reg_entry* entry;
-            do {
-                r = sqlite3_step(stmt);
-                switch (r) {
-                    case SQLITE_ROW:
-                        entry = *(reg_entry**)sqlite3_column_blob(stmt, 0);
-                        reg_entry_free(db, entry);
-                        break;
-                    case SQLITE_DONE:
-                        break;
-                    default:
-                        reg_sqlite_error(db, errPtr, query);
-                        return 0;
-                }
-            } while (r != SQLITE_DONE);
-        }
-        sqlite3_finalize(stmt);
-        query = "DELETE FROM entries";
-        if ((sqlite3_prepare(db, query, -1, &stmt, NULL) != SQLITE_OK)
-                || (sqlite3_step(stmt) != SQLITE_DONE)) {
-            sqlite3_finalize(stmt);
-            return 0;
-        }
-        return 1;
-    } else {
-        reg_sqlite_error(db, errPtr, query);
-        sqlite3_finalize(stmt);
-        return 0;
-    }
-}
-

Deleted: trunk/base/src/registry2.0/creg.h
===================================================================
--- trunk/base/src/registry2.0/creg.h	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/creg.h	2007-08-06 20:12:35 UTC (rev 27520)
@@ -1,55 +0,0 @@
-/*
- * creg.h
- * $Id: $
- *
- * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _CREG_H
-#define _CREG_H
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sqlite3.h>
-
-typedef void reg_error_destructor(const char* description);
-
-typedef struct {
-    char* code;
-    const char* description;
-    reg_error_destructor* free;
-} reg_error;
-
-void reg_sqlite_error(sqlite3* db, reg_error* errPtr, char* query);
-
-void reg_error_destruct(reg_error* errPtr);
-
-int reg_open(sqlite3** dbPtr, reg_error* errPtr);
-int reg_close(sqlite3* db, reg_error* errPtr);
-
-int reg_attach(sqlite3* db, const char* path, reg_error* errPtr);
-int reg_detach(sqlite3* db, reg_error* errPtr);
-
-#endif /* _CREG_H */

Modified: trunk/base/src/registry2.0/registry.c
===================================================================
--- trunk/base/src/registry2.0/registry.c	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/registry.c	2007-08-06 20:12:35 UTC (rev 27520)
@@ -35,11 +35,13 @@
 #include <tcl.h>
 #include <sqlite3.h>
 
+#include <cregistry/registry.h>
+#include <cregistry/entry.h>
+
 #include "graph.h"
 #include "item.h"
 #include "entry.h"
 #include "util.h"
-#include "sql.h"
 
 int registry_failed(Tcl_Interp* interp, reg_error* errPtr) {
     Tcl_Obj* result = Tcl_NewStringObj(errPtr->description, -1);

Modified: trunk/base/src/registry2.0/registry.h
===================================================================
--- trunk/base/src/registry2.0/registry.h	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/registry.h	2007-08-06 20:12:35 UTC (rev 27520)
@@ -34,7 +34,7 @@
 
 #include <tcl.h>
 #include <sqlite3.h>
-#include <centry.h>
+#include <cregistry/entry.h>
 
 sqlite3* registry_db(Tcl_Interp* interp, int attached);
 int registry_failed(Tcl_Interp* interp, reg_error* errPtr);

Deleted: trunk/base/src/registry2.0/sql.c
===================================================================
--- trunk/base/src/registry2.0/sql.c	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/sql.c	2007-08-06 20:12:35 UTC (rev 27520)
@@ -1,300 +0,0 @@
-/*
- * sql.c
- * $Id: $
- *
- * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <tcl.h>
-#include <sqlite3.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-
-#include "creg.h"
-#include "util.h"
-
-/**
- * Executes a null-terminated list of queries.
- *
- * Pass it a list of queries, it'll execute them. This is mainly intended for
- * initialization, when you have a number of standard queries to execute.
- */
-int do_queries(sqlite3* db, char** queries, reg_error* errPtr) {
-    char** query;
-    for (query = queries; *query != NULL; query++) {
-        sqlite3_stmt* stmt;
-        if ((sqlite3_prepare(db, *query, -1, &stmt, NULL) != SQLITE_OK)
-                || (sqlite3_step(stmt) != SQLITE_DONE)) {
-            reg_sqlite_error(db, errPtr, *query);
-            sqlite3_finalize(stmt);
-            return 0;
-        }
-        sqlite3_finalize(stmt);
-    }
-    return 1;
-}
-
-/**
- * REGEXP function for sqlite3.
- *
- * Takes two arguments; the first is the value and the second the pattern. If
- * the pattern is invalid, errors out. Otherwise, returns true if the value
- * matches the pattern and false otherwise.
- *
- * This function is available in sqlite3 as the REGEXP operator.
- */
-static void sql_regexp(sqlite3_context* context, int argc UNUSED,
-        sqlite3_value** argv) {
-    const char* value = sqlite3_value_text(argv[0]);
-    const char* pattern = sqlite3_value_text(argv[1]);
-    switch (Tcl_RegExpMatch(NULL, value, pattern)) {
-        case 0:
-            sqlite3_result_int(context, 0);
-            break;
-        case 1:
-            sqlite3_result_int(context, 1);
-            break;
-        case -1:
-            sqlite3_result_error(context, "invalid pattern", -1);
-            break;
-    }
-}
-
-/**
- * NOW function for sqlite3.
- *
- * Takes no arguments. Returns the unix timestamp of now.
- */
-static void sql_now(sqlite3_context* context, int argc UNUSED,
-        sqlite3_value** argv UNUSED) {
-    sqlite3_result_int(context, time(NULL));
-}
-
-static int rpm_vercomp (const char *versionA, int lengthA, const char *versionB,
-        int lengthB) {
-    const char *endA, *endB;
-	const char *ptrA, *ptrB;
-	const char *eptrA, *eptrB;
-
-    if (lengthA < 0)
-        lengthA = strlen(versionA);
-    if (lengthB < 0)
-        lengthB = strlen(versionB);
-
-	/* if versions equal, return zero */
-	if(lengthA == lengthB && !strncmp(versionA, versionB, lengthA))
-		return 0;
-
-	ptrA = versionA;
-	ptrB = versionB;
-    endA = versionA + lengthA;
-    endB = versionB + lengthB;
-	while (ptrA != endA && ptrB != endB) {
-		/* skip all non-alphanumeric characters */
-		while (ptrA != endB && !isalnum(*ptrA))
-			ptrA++;
-		while (ptrB != endB && !isalnum(*ptrB))
-			ptrB++;
-
-		eptrA = ptrA;
-		eptrB = ptrB;
-
-		/* Somewhat arbitrary rules as per RPM's implementation.
-		 * This code could be more clever, but we're aiming
-		 * for clarity instead. */
-
-		/* If versionB's segment is not a digit segment, but
-		 * versionA's segment IS a digit segment, return 1.
-		 * (Added for redhat compatibility. See redhat bugzilla
-		 * #50977 for details) */
-		if (!isdigit(*ptrB)) {
-			if (isdigit(*ptrA))
-				return 1;
-		}
-
-		/* Otherwise, if the segments are of different types,
-		 * return -1 */
-
-		if ((isdigit(*ptrA) && isalpha(*ptrB)) || (isalpha(*ptrA) && isdigit(*ptrB)))
-			return -1;
-
-		/* Find the first segment composed of entirely alphabetical
-		 * or numeric members */
-		if (isalpha(*ptrA)) {
-			while (eptrA != endA && isalpha(*eptrA))
-				eptrA++;
-
-			while (eptrB != endB && isalpha(*eptrB))
-				eptrB++;
-		} else {
-			int countA = 0, countB = 0;
-			while (eptrA != endA && isdigit(*eptrA)) {
-				countA++;
-				eptrA++;
-			}
-			while (eptrB != endB && isdigit(*eptrB)) {
-				countB++;
-				eptrB++;
-			}
-
-			/* skip leading '0' characters */
-			while (ptrA != eptrA && *ptrA == '0') {
-				ptrA++;
-				countA--;
-			}
-			while (ptrB != eptrB && *ptrB == '0') {
-				ptrB++;
-				countB--;
-			}
-
-			/* If A is longer than B, return 1 */
-			if (countA > countB)
-				return 1;
-
-			/* If B is longer than A, return -1 */
-			if (countB > countA)
-				return -1;
-		}
-		/* Compare strings lexicographically */
-		while (ptrA != eptrA && ptrB != eptrB && *ptrA == *ptrB) {
-				ptrA++;
-				ptrB++;
-		}
-		if (ptrA != eptrA && ptrB != eptrB)
-			return *ptrA - *ptrB;
-
-		ptrA = eptrA;
-		ptrB = eptrB;
-	}
-
-	/* If both pointers are null, all alphanumeric
-	 * characters were identical and only seperating
-	 * characters differed. According to RPM, these
-	 * version strings are equal */
-	if (ptrA == endA && ptrB == endB)
-		return 0;
-
-	/* If A has unchecked characters, return 1
-	 * Otherwise, if B has remaining unchecked characters,
-	 * return -1 */
-	if (ptrA != endA)
-		return 1;
-	else
-		return -1;
-}
-
-/**
- * VERSION collation for sqlite3.
- *
- * This function collates text according to pextlib's rpm-vercomp function. This
- * allows direct comparison and sorting of version columns, such as port.version
- * and port.revision.
- *
- * TODO: share rpm-vercomp properly with pextlib. Currently it's copy-pasted in.
- */
-static int sql_version(void* userdata UNUSED, int alen, const void* a, int blen,
-        const void* b) {
-    return rpm_vercomp((const char*)a, alen, (const char*)b, blen);
-}
-
-/**
- * Creates tables in the registry.
- *
- * This function is called upon an uninitialized database to create the tables
- * needed to record state between invocations of `port`.
- */
-int create_tables(sqlite3* db, reg_error* errPtr) {
-    static char* queries[] = {
-        "BEGIN",
-
-        /* metadata table */
-        "CREATE TABLE registry.metadata (key UNIQUE, value)",
-        "INSERT INTO registry.metadata (key, value) VALUES ('version', 1.000)",
-        "INSERT INTO registry.metadata (key, value) VALUES ('created', NOW())",
-
-        /* ports table */
-        "CREATE TABLE registry.ports ("
-            "id INTEGER PRIMARY KEY AUTOINCREMENT,"
-            "name, portfile, url, location, epoch, version COLLATE VERSION, "
-            "revision COLLATE VERSION, variants, state, date, "
-            "UNIQUE (name, epoch, version, revision, variants), "
-            "UNIQUE (url, epoch, version, revision, variants)"
-            ")",
-        "CREATE INDEX registry.port_name ON ports "
-            "(name, epoch, version, revision, variants)",
-        "CREATE INDEX registry.port_url ON ports "
-            "(url, epoch, version, revision, variants)",
-        "CREATE INDEX registry.port_state ON ports (state)",
-
-        /* file map */
-        "CREATE TABLE registry.files (id, path UNIQUE, mtime)",
-        "CREATE INDEX registry.file_port ON files (id)",
-
-        "END",
-        NULL
-    };
-    return do_queries(db, queries, errPtr);
-}
-
-/**
- * Initializes database connection.
- *
- * This function creates all the temporary tables used by the registry. It also
- * registers the user functions and collations declared in "sql.h", making them
- * available.
- */
-int init_db(sqlite3* db, reg_error* errPtr) {
-    static char* queries[] = {
-        "BEGIN",
-
-        /* items cache */
-        "CREATE TEMPORARY TABLE items (refcount, proc UNIQUE, name, url, path, "
-            "worker, options, variants)",
-
-        /* indexes list */
-        "CREATE TEMPORARY TABLE indexes (file, name, attached)",
-
-        /* entry addresses */
-        "CREATE TEMPORARY TABLE entries (id, address)",
-
-        "END",
-        NULL
-    };
-
-    /* I'm not error-checking these. I don't think I need to. */
-    sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, NULL, sql_regexp,
-            NULL, NULL);
-    sqlite3_create_function(db, "NOW", 0, SQLITE_ANY, NULL, sql_now, NULL,
-            NULL);
-
-    sqlite3_create_collation(db, "VERSION", SQLITE_UTF8, NULL, sql_version);
-
-    return do_queries(db, queries, errPtr);
-}
-

Deleted: trunk/base/src/registry2.0/sql.h
===================================================================
--- trunk/base/src/registry2.0/sql.h	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/sql.h	2007-08-06 20:12:35 UTC (rev 27520)
@@ -1,42 +0,0 @@
-/*
- * sql.h
- * $Id: $
- *
- * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _SQL_H
-#define _SQL_H
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sqlite3.h>
-
-#include "creg.h"
-
-int create_tables(sqlite3* db, reg_error* errPtr);
-int init_db(sqlite3* db, reg_error* errPtr);
-
-#endif /* _SQL_H */

Modified: trunk/base/src/registry2.0/util.h
===================================================================
--- trunk/base/src/registry2.0/util.h	2007-08-06 20:12:26 UTC (rev 27519)
+++ trunk/base/src/registry2.0/util.h	2007-08-06 20:12:35 UTC (rev 27520)
@@ -35,7 +35,7 @@
 #include <tcl.h>
 #include <sqlite3.h>
 
-#include "centry.h"
+#include <cregistry/registry.h>
 
 typedef struct {
     char* option;

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20070806/6351e9a7/attachment.html


More information about the macports-changes mailing list