[117407] trunk/base
jmr at macports.org
jmr at macports.org
Tue Feb 25 10:28:14 PST 2014
Revision: 117407
https://trac.macports.org/changeset/117407
Author: jmr at macports.org
Date: 2014-02-25 10:28:14 -0800 (Tue, 25 Feb 2014)
Log Message:
-----------
store portgroups in the registry, so they can always be used by the portfiles, especially when a portgroup only exists in a non-default source.
move portfiles out of the db and into the filesystem, and deduplicate them (for when the same version is installed with different variants)
Modified Paths:
--------------
trunk/base/Makefile.in
trunk/base/portmgr/dmg/postflight
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/macports1.0/macports.tcl
trunk/base/src/macports1.0/tests/macports.test
trunk/base/src/pextlib1.0/tracelib.c
trunk/base/src/port1.0/portinstall.tcl
trunk/base/src/port1.0/portutil.tcl
trunk/base/src/registry2.0/Makefile
trunk/base/src/registry2.0/entryobj.c
trunk/base/src/registry2.0/portuninstall.tcl
trunk/base/src/registry2.0/registry.c
trunk/base/src/registry2.0/registry.h
trunk/base/src/registry2.0/registry_util.tcl
trunk/base/src/registry2.0/util.c
trunk/base/src/registry2.0/util.h
Added Paths:
-----------
trunk/base/src/cregistry/portgroup.c
trunk/base/src/cregistry/portgroup.h
trunk/base/src/dedup_portfiles.tcl
trunk/base/src/registry2.0/portgroup.c
trunk/base/src/registry2.0/portgroup.h
trunk/base/src/registry2.0/portgroupobj.c
trunk/base/src/registry2.0/portgroupobj.h
Modified: trunk/base/Makefile.in
===================================================================
--- trunk/base/Makefile.in 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/Makefile.in 2014-02-25 18:28:14 UTC (rev 117407)
@@ -94,6 +94,7 @@
$(TCLSH) src/upgrade_sources_conf_default.tcl "${prefix}"
# Convert image directories (and direct mode installs) to image archives
$(TCLSH) src/images_to_archives.tcl "${macports_tcl_dir}"
+ $(TCLSH) src/dedup_portfiles.tcl "${macports_tcl_dir}"
endif
ifndef SELFUPDATING
@echo ""; echo "Congratulations, you have successfully installed the MacPorts system. To get the Portfiles and update the system, add ${prefix}/bin to your PATH and run:"; echo ""
Modified: trunk/base/portmgr/dmg/postflight
===================================================================
--- trunk/base/portmgr/dmg/postflight 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/portmgr/dmg/postflight 2014-02-25 18:28:14 UTC (rev 117407)
@@ -74,6 +74,7 @@
# Convert image directories (and direct mode installs) to image archives
echo "Updating port image format..."
${TCLSH} ${SCRIPT_DIR}/images_to_archives.tcl ${MACPORTS_TCL_DIR}
+ ${TCLSH} ${SCRIPT_DIR}/dedup_portfiles.tcl ${MACPORTS_TCL_DIR}
echo "Synchronizing the MacPorts installation with the project's rsync server..."
if ! ${BINPATH}/port -v selfupdate; then
Modified: trunk/base/src/cregistry/Makefile
===================================================================
--- trunk/base/src/cregistry/Makefile 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/cregistry/Makefile 2014-02-25 18:28:14 UTC (rev 117407)
@@ -1,6 +1,6 @@
# $Id$
-OBJS = registry.o entry.o sql.o vercomp.o util.o file.o
+OBJS = registry.o entry.o sql.o vercomp.o util.o file.o portgroup.o
STLIB_NAME = cregistry.a
RANLIB = ranlib
Modified: trunk/base/src/cregistry/entry.c
===================================================================
--- trunk/base/src/cregistry/entry.c 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/cregistry/entry.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -2,7 +2,7 @@
* entry.c
* $Id$
*
- * Copyright (c) 2010-2011 The MacPorts Project
+ * Copyright (c) 2010-2011, 2014 The MacPorts Project
* Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
* All rights reserved.
*
@@ -31,6 +31,7 @@
#include <config.h>
#endif
+#include "portgroup.h"
#include "entry.h"
#include "registry.h"
#include "sql.h"
@@ -246,9 +247,11 @@
sqlite3_stmt* ports = NULL;
sqlite3_stmt* files = NULL;
sqlite3_stmt* dependencies = NULL;
+ sqlite3_stmt* portgroups = NULL;
char* ports_query = "DELETE FROM registry.ports WHERE id=?";
char* files_query = "DELETE FROM registry.files WHERE id=?";
char* dependencies_query = "DELETE FROM registry.dependencies WHERE id=?";
+ char* portgroups_query = "DELETE FROM registry.portgroups WHERE id=?";
if ((sqlite3_prepare_v2(reg->db, ports_query, -1, &ports, NULL) == SQLITE_OK)
&& (sqlite3_bind_int64(ports, 1, entry->id) == SQLITE_OK)
&& (sqlite3_prepare_v2(reg->db, files_query, -1, &files, NULL)
@@ -256,7 +259,10 @@
&& (sqlite3_bind_int64(files, 1, entry->id) == SQLITE_OK)
&& (sqlite3_prepare_v2(reg->db, dependencies_query, -1, &dependencies,
NULL) == SQLITE_OK)
- && (sqlite3_bind_int64(dependencies, 1, entry->id) == SQLITE_OK)) {
+ && (sqlite3_bind_int64(dependencies, 1, entry->id) == SQLITE_OK)
+ && (sqlite3_prepare_v2(reg->db, portgroups_query, -1, &portgroups,
+ NULL) == SQLITE_OK)
+ && (sqlite3_bind_int64(portgroups, 1, entry->id) == SQLITE_OK)) {
int r;
do {
r = sqlite3_step(ports);
@@ -271,7 +277,20 @@
r = sqlite3_step(dependencies);
switch (r) {
case SQLITE_DONE:
- result = 1;
+ do {
+ r = sqlite3_step(portgroups);
+ switch (r) {
+ case SQLITE_DONE:
+ result = 1;
+ break;
+ case SQLITE_BUSY:
+ break;
+ case SQLITE_ERROR:
+ reg_sqlite_error(reg->db,
+ errPtr, NULL);
+ break;
+ }
+ } while (r == SQLITE_BUSY);
break;
case SQLITE_BUSY:
break;
@@ -315,6 +334,9 @@
if (dependencies) {
sqlite3_finalize(dependencies);
}
+ if (portgroups) {
+ sqlite3_finalize(portgroups);
+ }
return result;
}
@@ -670,6 +692,73 @@
}
/**
+ * Associates a portgroup with given port.
+ *
+ * @param [in] entry the entry to map the portgroup to
+ * @param [in] name the portgroup name (e.g. "muniversal")
+ * @param [in] version the portgroup version (e.g. "1.0")
+ * @param [in] sha256 the sha256 hash of the portgroup file
+ * @param [in] size the size of the portgroup file in bytes
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return true if success; false if failure
+ */
+int reg_entry_addgroup(reg_entry* entry, char* name, char *version,
+ char *sha256, sqlite_int64 size, reg_error* errPtr) {
+ reg_registry* reg = entry->reg;
+ int result = 1;
+ sqlite3_stmt* stmt = NULL;
+ char* insert = "INSERT INTO registry.portgroups (id, name, version, size, sha256) "
+ "VALUES (?, ?, ?, ?, ?)";
+ if ((sqlite3_prepare_v2(reg->db, insert, -1, &stmt, NULL) == SQLITE_OK)
+ && (sqlite3_bind_int64(stmt, 1, entry->id) == SQLITE_OK)
+ && (sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC) == SQLITE_OK)
+ && (sqlite3_bind_text(stmt, 3, version, -1, SQLITE_STATIC) == SQLITE_OK)
+ && (sqlite3_bind_int64(stmt, 4, size) == SQLITE_OK)
+ && (sqlite3_bind_text(stmt, 5, sha256, -1, SQLITE_STATIC) == SQLITE_OK)) {
+ int r;
+ do {
+ r = sqlite3_step(stmt);
+ switch (r) {
+ case SQLITE_DONE:
+ sqlite3_reset(stmt);
+ break;
+ case SQLITE_BUSY:
+ break;
+ default:
+ reg_sqlite_error(reg->db, errPtr, insert);
+ result = 0;
+ break;
+ }
+ } while (r == SQLITE_BUSY);
+ } else {
+ reg_sqlite_error(reg->db, errPtr, insert);
+ result = 0;
+ }
+ if (stmt) {
+ sqlite3_finalize(stmt);
+ }
+ return result;
+}
+
+/**
+ * Gets a list of portgroups that are used by this port.
+ *
+ * @param [in] entry a port
+ * @param [out] portgroups a list of portgroups used by the given port
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return true if success; false if failure
+ */
+int reg_entry_getgroups(reg_entry* entry, reg_portgroup*** portgroups, reg_error* errPtr) {
+ reg_registry* reg = entry->reg;
+ char* query = sqlite3_mprintf("SELECT ROWID FROM portgroups "
+ "WHERE id=%lld",
+ entry->id);
+ int result = reg_all_portgroups(reg, query, -1, portgroups, errPtr);
+ sqlite3_free(query);
+ return result;
+}
+
+/**
* Maps files to the given port in the filemap. The list of files must not
* contain files that are already mapped to the given port.
*
Modified: trunk/base/src/cregistry/entry.h
===================================================================
--- trunk/base/src/cregistry/entry.h 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/cregistry/entry.h 2014-02-25 18:28:14 UTC (rev 117407)
@@ -71,6 +71,11 @@
int reg_entry_propset(reg_entry* entry, char* key, char* value,
reg_error* errPtr);
+int reg_entry_addgroup(reg_entry* entry, char* name, char *version,
+ char *sha256, sqlite_int64 size, reg_error* errPtr);
+int reg_entry_getgroups(reg_entry* entry, reg_portgroup*** portgroups,
+ reg_error* errPtr);
+
int reg_entry_map(reg_entry* entry, char** files, int file_count,
reg_error* errPtr);
int reg_entry_unmap(reg_entry* entry, char** files, int file_count,
Added: trunk/base/src/cregistry/portgroup.c
===================================================================
--- trunk/base/src/cregistry/portgroup.c (rev 0)
+++ trunk/base/src/cregistry/portgroup.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -0,0 +1,318 @@
+/*
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2014 The MacPorts Project
+ * 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 "portgroup.h"
+#include "util.h"
+#include "registry.h"
+#include "sql.h"
+
+#include <sqlite3.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Converts a `sqlite3_stmt` into a `reg_portgroup`. The first column of the stmt's
+ * row must be the id of a portgroup; the second either `SQLITE_NULL` or the
+ * address of the entry in memory.
+ *
+ * @param [in] userdata sqlite3 database
+ * @param [out] portgroup portgroup described by `stmt`
+ * @param [in] stmt `sqlite3_stmt` with appropriate columns
+ * @param [out] errPtr unused
+ * @return true if success; false if failure
+ */
+static int reg_stmt_to_portgroup(void* userdata, void** portgroup, void* stmt,
+ void* calldata UNUSED, reg_error* errPtr UNUSED) {
+ int is_new;
+ reg_registry* reg = (reg_registry*)userdata;
+ sqlite_int64 id = sqlite3_column_int64(stmt, 0);
+ Tcl_HashEntry* hash = Tcl_CreateHashEntry(®->open_portgroups,
+ (const char*)&id, &is_new);
+ if (is_new) {
+ reg_portgroup* p = malloc(sizeof(reg_portgroup));
+ if (!p) {
+ return 0;
+ }
+ p->reg = reg;
+ p->id = id;
+ p->proc = NULL;
+ *portgroup = p;
+ Tcl_SetHashValue(hash, p);
+ } else {
+ *portgroup = Tcl_GetHashValue(hash);
+ }
+ return 1;
+}
+
+/**
+ * Type-safe version of `reg_all_objects` for `reg_portgroup`.
+ *
+ * @param [in] reg registry to select entries from
+ * @param [in] query the select query to execute
+ * @param [in] query_len length of the query (or -1 for automatic)
+ * @param [out] objects the portgroups selected
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return the number of entries if success; negative if failure
+ */
+int reg_all_portgroups(reg_registry* reg, char* query, int query_len,
+ reg_portgroup*** objects, reg_error* errPtr) {
+ int lower_bound = 0;
+ return reg_all_objects(reg, query, query_len, (void***)objects,
+ reg_stmt_to_portgroup, &lower_bound, NULL, errPtr);
+}
+
+/**
+ * Searches the registry for portgroups for which each key's value is equal to the
+ * given value. To find all portgroups, pass a key_count of 0.
+ *
+ * Bad keys should cause sqlite3 errors but not permit SQL injection attacks.
+ * Pass it good keys anyway.
+ *
+ * @param [in] reg registry to search in
+ * @param [in] keys a list of keys to search by
+ * @param [in] vals a list of values to search by, matching keys
+ * @param [in] strats a list of strategies to use when searching
+ * @param [in] key_count the number of key/value pairs passed
+ * @param [out] portgroups a list of matching portgroups
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return the number of entries if success; false if failure
+ */
+int reg_portgroup_search(reg_registry* reg, char** keys, char** vals, int* strats,
+ int key_count, reg_portgroup*** portgroups, reg_error* errPtr) {
+ int i;
+ char* kwd = " WHERE ";
+ char* query;
+ size_t query_len, query_space;
+ int result;
+
+ /* build the query */
+ query = strdup("SELECT ROWID FROM registry.portgroups");
+ if (!query) {
+ return -1;
+ }
+ query_len = query_space = strlen(query);
+
+ for (i = 0; i < key_count; i++) {
+ char* op;
+ char* cond;
+
+ /* get the strategy */
+ if ((op = reg_strategy_op(strats[i], errPtr)) == NULL) {
+ free(query);
+ return -1;
+ }
+
+ cond = sqlite3_mprintf(op, keys[i], vals[i]);
+ if (!cond || !reg_strcat(&query, &query_len, &query_space, kwd)
+ || !reg_strcat(&query, &query_len, &query_space, cond)) {
+ free(query);
+ return -1;
+ }
+ sqlite3_free(cond);
+ kwd = " AND ";
+ }
+
+ /* do the query */
+ result = reg_all_portgroups(reg, query, -1, portgroups, errPtr);
+ free(query);
+ return result;
+}
+
+/**
+ * Gets a named property of a portgroup. That property can be set using
+ * `reg_portgroup_propset`. The property named must be one that exists in the table
+ * and must not be one with internal meaning such as `id` or `state`.
+ *
+ * @param [in] portgroup portgroup to get property from
+ * @param [in] key property to get
+ * @param [out] value the value of the property
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return true if success; false if failure
+ */
+int reg_portgroup_propget(reg_portgroup* portgroup, char* key, char** value,
+ reg_error* errPtr) {
+ reg_registry* reg = portgroup->reg;
+ int result = 0;
+ sqlite3_stmt* stmt = NULL;
+ char* query;
+ const char *text;
+ query = sqlite3_mprintf("SELECT %q FROM registry.portgroups WHERE ROWID=%lld", key,
+ portgroup->id);
+ if (sqlite3_prepare_v2(reg->db, query, -1, &stmt, NULL) == SQLITE_OK) {
+ int r;
+ do {
+ r = sqlite3_step(stmt);
+ switch (r) {
+ case SQLITE_ROW:
+ text = (const char*)sqlite3_column_text(stmt, 0);
+ if (text) {
+ *value = strdup(text);
+ result = 1;
+ } else {
+ reg_sqlite_error(reg->db, errPtr, query);
+ }
+ break;
+ case SQLITE_DONE:
+ errPtr->code = REG_INVALID;
+ errPtr->description = "an invalid portgroup was passed";
+ errPtr->free = NULL;
+ break;
+ case SQLITE_BUSY:
+ continue;
+ default:
+ reg_sqlite_error(reg->db, errPtr, query);
+ break;
+ }
+ } while (r == SQLITE_BUSY);
+ } else {
+ reg_sqlite_error(reg->db, errPtr, query);
+ }
+ if (stmt) {
+ sqlite3_finalize(stmt);
+ }
+ sqlite3_free(query);
+ return result;
+}
+
+/**
+ * Sets a named property of an portgroup. That property can be later retrieved using
+ * `reg_portgroup_propget`. The property named must be one that exists in the table
+ * and must not be one with internal meaning such as `id` or `state`. If `name`,
+ * `epoch`, `version`, `revision`, or `variants` is set, it could trigger a
+ * conflict if another port with the same combination of values for those
+ * columns exists.
+ *
+ * @param [in] portgroup portgroup to set property for
+ * @param [in] key property to set
+ * @param [in] value the desired value of the property
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return true if success; false if failure
+ */
+int reg_portgroup_propset(reg_portgroup* portgroup, char* key, char* value,
+ reg_error* errPtr) {
+ reg_registry* reg = portgroup->reg;
+ int result = 0;
+ sqlite3_stmt* stmt = NULL;
+ char* query;
+ query = sqlite3_mprintf("UPDATE registry.ports SET %q = '%q' WHERE ROWID=%lld",
+ key, value, portgroup->id);
+ if (sqlite3_prepare_v2(reg->db, query, -1, &stmt, NULL) == SQLITE_OK) {
+ int r;
+ do {
+ r = sqlite3_step(stmt);
+ switch (r) {
+ case SQLITE_DONE:
+ result = 1;
+ break;
+ case SQLITE_BUSY:
+ break;
+ default:
+ if (sqlite3_reset(stmt) == SQLITE_CONSTRAINT) {
+ errPtr->code = REG_CONSTRAINT;
+ errPtr->description = "a constraint was disobeyed";
+ errPtr->free = NULL;
+ } else {
+ reg_sqlite_error(reg->db, errPtr, query);
+ }
+ break;
+ }
+ } while (r == SQLITE_BUSY);
+ } else {
+ reg_sqlite_error(reg->db, errPtr, query);
+ }
+ if (stmt) {
+ sqlite3_finalize(stmt);
+ }
+ sqlite3_free(query);
+ return result;
+}
+
+/**
+ * Opens an existing portgroup in the registry.
+ *
+ * @param [in] reg registry to open portgroup in
+ * @param [in] id id of entry referencing portgroup
+ * @param [in] name name of portgroup
+ * @param [in] version version of portgroup
+ * @param [in] size size of portgroup
+ * @param [in] sha256 sha256 of portgroup
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return the portgroup if success; NULL if failure
+ */
+reg_portgroup* reg_portgroup_open(reg_registry* reg, char *id, char* name, char* version,
+ char* size, char* sha256, reg_error* errPtr) {
+ sqlite3_stmt* stmt = NULL;
+ reg_portgroup* portgroup = NULL;
+ int lower_bound = 0;
+ char* query;
+ query = "SELECT ROWID FROM registry.portgroups WHERE id=? AND name=? AND version=? "
+ "AND size=? AND sha256=?";
+ if ((sqlite3_prepare_v2(reg->db, query, -1, &stmt, NULL) == SQLITE_OK)
+ && (sqlite3_bind_text(stmt, 1, id, -1, SQLITE_STATIC)
+ == SQLITE_OK)
+ && (sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC)
+ == SQLITE_OK)
+ && (sqlite3_bind_text(stmt, 3, version, -1, SQLITE_STATIC)
+ == SQLITE_OK)
+ && (sqlite3_bind_text(stmt, 4, size, -1, SQLITE_STATIC)
+ == SQLITE_OK)
+ && (sqlite3_bind_text(stmt, 5, sha256, -1, SQLITE_STATIC)
+ == SQLITE_OK)) {
+ int r;
+ do {
+ r = sqlite3_step(stmt);
+ switch (r) {
+ case SQLITE_ROW:
+ reg_stmt_to_portgroup(reg, (void**)&portgroup, stmt, &lower_bound, errPtr);
+ break;
+ case SQLITE_DONE:
+ errPtr->code = REG_NOT_FOUND;
+ errPtr->description = sqlite3_mprintf("no matching portgroup found for: " \
+ "id=%s, name=%s, version=%s, size=%s, sha256=%s", \
+ id, name, version, size, sha256);
+ errPtr->free = (reg_error_destructor*) sqlite3_free;
+ break;
+ case SQLITE_BUSY:
+ continue;
+ default:
+ reg_sqlite_error(reg->db, errPtr, query);
+ break;
+ }
+ } while (r == SQLITE_BUSY);
+ } else {
+ reg_sqlite_error(reg->db, errPtr, query);
+ }
+ if (stmt) {
+ sqlite3_finalize(stmt);
+ }
+ return portgroup;
+}
Added: trunk/base/src/cregistry/portgroup.h
===================================================================
--- trunk/base/src/cregistry/portgroup.h (rev 0)
+++ trunk/base/src/cregistry/portgroup.h 2014-02-25 18:28:14 UTC (rev 117407)
@@ -0,0 +1,56 @@
+/*
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2014 The MacPorts Project
+ * 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 _CPORTGROUP_H
+#define _CPORTGROUP_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "registry.h"
+
+#include <sqlite3.h>
+
+typedef struct {
+ sqlite_int64 id; /* rowid in the database */
+ reg_registry* reg; /* associated registry */
+ char* proc; /* name of Tcl proc, if using Tcl */
+} reg_portgroup;
+
+int reg_portgroup_search(reg_registry* reg, char** keys, char** vals, int* strats,
+ int key_count, reg_portgroup*** portgroups, reg_error* errPtr);
+int reg_all_portgroups(reg_registry* reg, char* query, int query_len,
+ reg_portgroup*** objects, reg_error* errPtr);
+reg_portgroup* reg_portgroup_open(reg_registry* reg, char *id, char* name, char* version,
+ char* size, char* sha256, reg_error* errPtr);
+int reg_portgroup_propget(reg_portgroup* portgroup, char* key, char** value,
+ reg_error* errPtr);
+int reg_portgroup_propset(reg_portgroup* portgroup, char* key, char* value,
+ reg_error* errPtr);
+
+#endif /* _CPORTGROUP_H */
Modified: trunk/base/src/cregistry/registry.c
===================================================================
--- trunk/base/src/cregistry/registry.c 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/cregistry/registry.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -4,7 +4,7 @@
* vim:expandtab:tw=80
*
* Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * Copyright (c) 2012 The MacPorts Project
+ * Copyright (c) 2012, 2014 The MacPorts Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include <config.h>
#endif
+#include "portgroup.h"
#include "entry.h"
#include "file.h"
#include "sql.h"
@@ -208,6 +209,8 @@
sizeof(sqlite_int64)/sizeof(int));
Tcl_InitHashTable(®->open_files,
TCL_STRING_KEYS);
+ Tcl_InitHashTable(®->open_portgroups,
+ sizeof(sqlite_int64)/sizeof(int));
reg->status |= reg_attached;
result = 1;
}
Modified: trunk/base/src/cregistry/registry.h
===================================================================
--- trunk/base/src/cregistry/registry.h 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/cregistry/registry.h 2014-02-25 18:28:14 UTC (rev 117407)
@@ -4,7 +4,7 @@
* $Id$
*
* Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * Copyright (c) 2012 The MacPorts Project
+ * Copyright (c) 2012, 2014 The MacPorts Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,6 +73,7 @@
int status;
Tcl_HashTable open_entries;
Tcl_HashTable open_files;
+ Tcl_HashTable open_portgroups;
} reg_registry;
int reg_open(reg_registry** regPtr, reg_error* errPtr);
Modified: trunk/base/src/cregistry/sql.c
===================================================================
--- trunk/base/src/cregistry/sql.c 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/cregistry/sql.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -3,7 +3,7 @@
* $Id$
*
* Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * Copyright (c) 2012 The MacPorts Project
+ * Copyright (c) 2012, 2014 The MacPorts Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -129,13 +129,13 @@
/* metadata table */
"CREATE TABLE registry.metadata (key UNIQUE, value)",
- "INSERT INTO registry.metadata (key, value) VALUES ('version', 1.100)",
+ "INSERT INTO registry.metadata (key, value) VALUES ('version', 1.200)",
"INSERT INTO registry.metadata (key, value) VALUES ('created', strftime('%s', 'now'))",
/* ports table */
"CREATE TABLE registry.ports ("
- "id INTEGER PRIMARY KEY AUTOINCREMENT, "
- "name TEXT COLLATE NOCASE, portfile CLOB, url TEXT, "
+ "id INTEGER PRIMARY KEY, "
+ "name TEXT COLLATE NOCASE, portfile TEXT, url TEXT, "
"location TEXT, epoch INTEGER, version TEXT COLLATE VERSION, "
"revision INTEGER, variants TEXT, negated_variants TEXT, "
"state TEXT, date DATETIME, installtype TEXT, archs TEXT, "
@@ -163,6 +163,11 @@
"FOREIGN KEY(id) REFERENCES ports(id))",
"CREATE INDEX registry.dep_name ON dependencies (name)",
+ /* portgroups table */
+ "CREATE TABLE registry.portgroups (id INTEGER, "
+ "name TEXT, version TEXT COLLATE VERSION, size INTEGER, sha256 TEXT, "
+ "FOREIGN KEY(id) REFERENCES ports(id))",
+
"COMMIT",
NULL
};
@@ -321,6 +326,36 @@
continue;
}
+ if (sql_version(NULL, -1, version, -1, "1.2") < 0) {
+ /* We need to add the portgroup table and move the portfiles out
+ of the db and into the filesystem. The latter is way easier to do
+ from Tcl, so here we'll just flag that it needs to be done. */
+ static char* version_1_2_queries[] = {
+ /* portgroups table */
+ "CREATE TABLE registry.portgroups (id INTEGER, "
+ "name TEXT, version TEXT COLLATE VERSION, size INTEGER, sha256 TEXT, "
+ "FOREIGN KEY(id) REFERENCES ports(id))",
+
+ "UPDATE registry.metadata SET value = '1.200' WHERE key = 'version'",
+
+ "INSERT INTO registry.metadata (key, value) VALUES ('portfiles_update_needed', 1)",
+
+ "COMMIT",
+ NULL
+ };
+
+ sqlite3_finalize(stmt);
+ stmt = NULL;
+
+ if (!do_queries(db, version_1_2_queries, errPtr)) {
+ rollback_db(db);
+ return 0;
+ }
+
+ did_update = 1;
+ continue;
+ }
+
/* add new versions here, but remember to:
* - finalize the version query statement and set stmt to NULL
* - do _not_ use "BEGIN" in your query list, since a transaction has
Added: trunk/base/src/dedup_portfiles.tcl
===================================================================
--- trunk/base/src/dedup_portfiles.tcl (rev 0)
+++ trunk/base/src/dedup_portfiles.tcl 2014-02-25 18:28:14 UTC (rev 117407)
@@ -0,0 +1,47 @@
+#!/usr/bin/env tclsh
+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
+# $Id$
+
+# move portfiles from sqlite db to filesystem, while deduplicating
+# Takes one argument, which should be TCL_PACKAGE_DIR.
+
+source [file join [lindex $argv 0] macports1.0 macports_fastload.tcl]
+package require macports 1.0
+package require registry2 2.0
+package require Pextlib 1.0
+
+umask 022
+
+array set ui_options {ports_verbose yes}
+
+mportinit ui_options
+
+if {[registry::metadata get portfiles_update_needed] == 1} {
+ set portfiles_dir [file join ${macports::registry.path} registry portfiles]
+
+ registry::write {
+ set installed_ports [registry::entry imaged]
+ foreach portref $installed_ports {
+ set portfile_contents [$portref portfile]
+ if {$portfile_contents ne "" && $portfile_contents ne "0"} {
+ set portfile_partial_dir [file join $portfiles_dir [$portref name]-[$portref version]_[$portref revision]]
+ file mkdir $portfile_partial_dir
+ set portfile_temp_path ${portfile_partial_dir}/Portfile
+ set fd [open $portfile_temp_path w]
+ puts $fd $portfile_contents
+ close $fd
+
+ set hash_size [sha256 file $portfile_temp_path]-[file size $portfile_temp_path]
+ set portfile_dir [file join $portfile_partial_dir $hash_size]
+ file mkdir $portfile_dir
+ file rename -force $portfile_temp_path $portfile_dir
+ file mtime ${portfile_dir}/Portfile [$portref date]
+
+ $portref portfile $hash_size
+ }
+ }
+ registry::metadata del portfiles_update_needed
+ }
+}
+
+exit 0
Property changes on: trunk/base/src/dedup_portfiles.tcl
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:keywords
+ Id
Added: svn:eol-style
+ native
Modified: trunk/base/src/macports1.0/macports.tcl
===================================================================
--- trunk/base/src/macports1.0/macports.tcl 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/macports1.0/macports.tcl 2014-02-25 18:28:14 UTC (rev 117407)
@@ -1363,12 +1363,12 @@
}
foreach {opt val} $options {
- $workername eval set user_options($opt) $val
- $workername eval set $opt $val
+ $workername eval [list set user_options($opt) $val]
+ $workername eval [list set $opt $val]
}
foreach {var val} $variations {
- $workername eval set variations($var) $val
+ $workername eval [list set variations($var) $val]
}
}
@@ -1715,12 +1715,7 @@
proc mportopen_installed {name version revision variants options} {
global macports::registry.path
set regref [lindex [registry::entry imaged $name $version $revision $variants] 0]
- set portfile_dir [file join ${registry.path} registry portfiles $name ${version}_${revision}$variants]
- file mkdir $portfile_dir
- set fd [open ${portfile_dir}/Portfile w]
- puts $fd [$regref portfile]
- close $fd
- file mtime ${portfile_dir}/Portfile [$regref date]
+ set portfile_dir [file join ${registry.path} registry portfiles ${name}-${version}_${revision} [$regref portfile]]
set variations {}
set minusvariant [lrange [split [$regref negated_variants] -] 1 end]
@@ -1732,23 +1727,17 @@
lappend variations $v -
}
lappend options subport $name
- return [mportopen file://${portfile_dir}/ $options $variations]
-}
-# mportclose_installed
-# close mport opened with mportopen_installed and clean up associated files
-proc mportclose_installed {mport} {
- global macports::registry.path
- foreach key {subport version revision portvariants} {
- set $key [_mportkey $mport $key]
+ # find portgroups in registry
+ set pgdirlist [list]
+ foreach pg [$regref groups_used] {
+ lappend pgdirlist [file join ${registry.path} registry portgroups [$pg sha256]-[$pg size]]
}
- mportclose $mport
- set portfiles_dir [file join ${registry.path} registry portfiles $subport]
- set portfile [file join $portfiles_dir ${version}_${revision}$portvariants Portfile]
- file delete -force $portfile [file dirname $portfile]
- if {[llength [glob -nocomplain -directory $portfiles_dir *]] == 0} {
- file delete -force $portfiles_dir
+ if {$pgdirlist ne {}} {
+ lappend options _portgroup_search_dirs $pgdirlist
}
+
+ return [mportopen file://${portfile_dir}/ $options $variations]
}
# Traverse a directory with ports, calling a function on the path of ports
Modified: trunk/base/src/macports1.0/tests/macports.test
===================================================================
--- trunk/base/src/macports1.0/tests/macports.test 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/macports1.0/tests/macports.test 2014-02-25 18:28:14 UTC (rev 117407)
@@ -153,10 +153,10 @@
return "FAIL: installed port not opened"
}
- if {[catch {mportclose_installed $res}] != 0} {
+ if {[catch {mportclose $res}] != 0} {
return "FAIL: cannot close port"
}
- if {[catch {mportclose_installed $res}] != 1} {
+ if {[catch {mportclose $res}] != 1} {
return "FAIL: installed port not closed"
}
return "Installed port open successful."
@@ -702,10 +702,6 @@
# test mportopen
-# Covered by mportopen_installed
-# test mportclose_installed
-
-
test mporttraverse {
Mport traverse unit test. Uses 3rd column of the Portfile.
} -setup {
Modified: trunk/base/src/pextlib1.0/tracelib.c
===================================================================
--- trunk/base/src/pextlib1.0/tracelib.c 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/pextlib1.0/tracelib.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -56,6 +56,7 @@
#include <sys/un.h>
#include <unistd.h>
+#include <cregistry/portgroup.h>
#include <cregistry/entry.h>
#include <registry2.0/registry.h>
Modified: trunk/base/src/port1.0/portinstall.tcl
===================================================================
--- trunk/base/src/port1.0/portinstall.tcl 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/port1.0/portinstall.tcl 2014-02-25 18:28:14 UTC (rev 117407)
@@ -307,7 +307,7 @@
homepage depends_run package-install workdir workpath \
worksrcdir UI_PREFIX destroot revision maintainers user_options \
portvariants negated_variants targets depends_lib PortInfo epoch license \
- os.platform os.major portarchivetype installPlist
+ os.platform os.major portarchivetype installPlist registry.path porturl
set oldpwd [pwd]
if {$oldpwd eq ""} {
@@ -373,11 +373,40 @@
# register files
$regref map $installPlist
}
-
+
# store portfile
- set fd [open [file join ${portpath} Portfile]]
- $regref portfile [read $fd]
- close $fd
+ set portfile_path [file join $portpath Portfile]
+ set portfile_sha256 [sha256 file $portfile_path]
+ set portfile_size [file size $portfile_path]
+ set portfile_reg_dir [file join ${registry.path} registry portfiles ${subport}-${version}_${revision} ${portfile_sha256}-${portfile_size}]
+ file mkdir $portfile_reg_dir
+ set portfile_reg_path ${portfile_reg_dir}/Portfile
+ if {![file isfile $portfile_reg_path] || [file size $portfile_reg_path] != $portfile_size || [sha256 file $portfile_reg_path] ne $portfile_sha256} {
+ file copy -force $portfile_path $portfile_reg_dir
+ }
+ $regref portfile ${portfile_sha256}-${portfile_size}
+
+ # store portgroups
+ if {[info exists PortInfo(portgroups)]} {
+ foreach pg $PortInfo(portgroups) {
+ set pgname [lindex $pg 0]
+ set pgversion [lindex $pg 1]
+ set groupFile [getportresourcepath $porturl "port1.0/group/${pgname}-${pgversion}.tcl"]
+ if {[file isfile $groupFile]} {
+ set pgsha256 [sha256 file $groupFile]
+ set pgsize [file size $groupFile]
+ set pg_reg_dir [file join ${registry.path} registry portgroups ${pgsha256}-${pgsize}]
+ set pg_reg_path ${pg_reg_dir}/${pgname}-${pgversion}.tcl
+ if {![file isfile $pg_reg_path] || [file size $pg_reg_path] != $pgsize || [sha256 file $pg_reg_path] ne $pgsha256} {
+ file mkdir $pg_reg_dir
+ file copy -force $groupFile $pg_reg_dir
+ }
+ $regref addgroup $pgname $pgversion $pgsha256 $pgsize
+ } else {
+ ui_debug "install_main: no portgroup ${pgname}-${pgversion}.tcl found"
+ }
+ }
+ }
}
_cd $oldpwd
Modified: trunk/base/src/port1.0/portutil.tcl
===================================================================
--- trunk/base/src/port1.0/portutil.tcl 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/port1.0/portutil.tcl 2014-02-25 18:28:14 UTC (rev 117407)
@@ -2569,12 +2569,12 @@
# Use a specified group/version.
proc PortGroup {group version} {
- global porturl PortInfo
+ global porturl PortInfo _portgroup_search_dirs
lappend PortInfo(portgroups) [list $group $version]
- if {[info exists portutil::portgroup_search_dirs]} {
- foreach dir $portutil::portgroup_search_dirs {
+ if {[info exists _portgroup_search_dirs]} {
+ foreach dir $_portgroup_search_dirs {
set groupFile ${dir}/${group}-${version}.tcl
if {[file exists $groupFile]} {
uplevel "source $groupFile"
Modified: trunk/base/src/registry2.0/Makefile
===================================================================
--- trunk/base/src/registry2.0/Makefile 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/registry2.0/Makefile 2014-02-25 18:28:14 UTC (rev 117407)
@@ -3,7 +3,8 @@
SRCS = registry.tcl registry_autoconf.tcl registry_util.tcl receipt_flat.tcl receipt_sqlite.tcl portimage.tcl portuninstall.tcl
OBJS = registry.o util.o \
entry.o entryobj.o \
- file.o fileobj.o
+ file.o fileobj.o \
+ portgroup.o portgroupobj.o
#graph.o graphobj.o
SHLIB_NAME= registry${SHLIB_SUFFIX}
Modified: trunk/base/src/registry2.0/entryobj.c
===================================================================
--- trunk/base/src/registry2.0/entryobj.c 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/registry2.0/entryobj.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -356,6 +356,59 @@
}
}
+static int entry_obj_add_portgroup(Tcl_Interp* interp, reg_entry* entry, int objc,
+ Tcl_Obj* CONST objv[]) {
+ reg_registry* reg = registry_for(interp, reg_attached);
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 1, objv, "addgroup name version sha256 size");
+ return TCL_ERROR;
+ } else if (reg == NULL) {
+ return TCL_ERROR;
+ } else {
+ reg_error error;
+ char* name = Tcl_GetString(objv[2]);
+ char* version = Tcl_GetString(objv[3]);
+ char* sha256 = Tcl_GetString(objv[4]);
+ Tcl_WideInt tclsize;
+ Tcl_GetWideIntFromObj(interp, objv[5], &tclsize);
+ sqlite_int64 size = (sqlite_int64)tclsize;
+ if (reg_entry_addgroup(entry, name, version, sha256, size, &error)) {
+ return TCL_OK;
+ }
+ return registry_failed(interp, &error);
+ }
+}
+
+static int entry_obj_get_portgroups(Tcl_Interp* interp, reg_entry* entry, int objc,
+ Tcl_Obj* CONST objv[]) {
+ reg_registry* reg = registry_for(interp, reg_attached);
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "groups_used");
+ return TCL_ERROR;
+ } else if (reg == NULL) {
+ return TCL_ERROR;
+ } else {
+ reg_portgroup** portgroups;
+ reg_error error;
+ int portgroup_count = reg_entry_getgroups(entry, &portgroups, &error);
+ if (portgroup_count >= 0) {
+ Tcl_Obj** objs;
+ int retval = TCL_ERROR;
+ if (list_portgroup_to_obj(interp, &objs, portgroups, portgroup_count, &error)){
+ Tcl_Obj* result = Tcl_NewListObj(portgroup_count, objs);
+ Tcl_SetObjResult(interp, result);
+ free(objs);
+ retval = TCL_OK;
+ } else {
+ retval = registry_failed(interp, &error);
+ }
+ free(portgroups);
+ return retval;
+ }
+ return registry_failed(interp, &error);
+ }
+}
+
typedef struct {
char* name;
int (*function)(Tcl_Interp* interp, reg_entry* entry, int objc,
@@ -391,6 +444,9 @@
{ "dependents", entry_obj_dependents },
{ "dependencies", entry_obj_dependencies },
{ "depends", entry_obj_depends },
+ /* portgroups */
+ { "addgroup", entry_obj_add_portgroup },
+ { "groups_used", entry_obj_get_portgroups },
{ NULL, NULL }
};
Added: trunk/base/src/registry2.0/portgroup.c
===================================================================
--- trunk/base/src/registry2.0/portgroup.c (rev 0)
+++ trunk/base/src/registry2.0/portgroup.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -0,0 +1,294 @@
+/*
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2014 The MacPorts Project
+ * 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 <sqlite3.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tcl.h>
+
+#include <cregistry/portgroup.h>
+#include <cregistry/util.h>
+
+#include "portgroup.h"
+#include "portgroupobj.h"
+#include "registry.h"
+#include "util.h"
+
+/**
+ * Converts a command name into a `reg_portgroup`.
+ *
+ * @param [in] interp Tcl interpreter to check within
+ * @param [in] name name of portgroup to get
+ * @param [out] errPtr description of error if the portgroup can't be found
+ * @return a portgroup, or NULL if one couldn't be found
+ * @see get_object
+ */
+static reg_portgroup* get_portgroup(Tcl_Interp* interp, char* name, reg_error* errPtr) {
+ return (reg_portgroup*)get_object(interp, name, "portgroup", portgroup_obj_cmd, errPtr);
+}
+
+/**
+ * Removes the portgroup from the Tcl interpreter. Doesn't actually delete it since
+ * that's the registry's job. This is written to be used as the
+ * `Tcl_CmdDeleteProc` for an portgroup object command.
+ *
+ * @param [in] clientData address of a reg_portgroup to remove
+ */
+void delete_portgroup(ClientData clientData) {
+ reg_portgroup* portgroup = (reg_portgroup*)clientData;
+ free(portgroup->proc);
+ portgroup->proc = NULL;
+}
+
+/**
+ * registry::portgroup open id name version size sha256
+ *
+ * Opens a portgroup matching the given parameters.
+ */
+static int portgroup_open(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
+ reg_registry* reg = registry_for(interp, reg_attached);
+ if (objc != 7) {
+ Tcl_WrongNumArgs(interp, 1, objv, "open id name version size sha256");
+ return TCL_ERROR;
+ } else if (reg == NULL) {
+ return TCL_ERROR;
+ } else {
+ char* id = Tcl_GetString(objv[2]);
+ char* name = Tcl_GetString(objv[3]);
+ char* version = Tcl_GetString(objv[4]);
+ char* size = Tcl_GetString(objv[5]);
+ char* sha256 = Tcl_GetString(objv[6]);
+
+ reg_error error;
+ reg_portgroup* portgroup = reg_portgroup_open(reg, id, name, version, size, sha256, &error);
+ if (portgroup != NULL) {
+ Tcl_Obj* result;
+ if (portgroup_to_obj(interp, &result, portgroup, NULL, &error)) {
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ }
+ }
+ return registry_failed(interp, &error);
+ }
+ return TCL_ERROR;
+}
+
+/**
+ * registry::portgroup close portgroup
+ *
+ * Closes a portgroup. It will remain in the registry.
+ */
+static int portgroup_close(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "close portgroup");
+ return TCL_ERROR;
+ } else {
+ reg_error error;
+ char* proc = Tcl_GetString(objv[2]);
+ reg_portgroup* portgroup = get_portgroup(interp, proc, &error);
+ if (portgroup == NULL) {
+ return registry_failed(interp, &error);
+ } else {
+ Tcl_DeleteCommand(interp, proc);
+ return TCL_OK;
+ }
+ }
+}
+
+typedef struct {
+ char* name;
+ reg_strategy strategy;
+} strategy_type;
+
+static strategy_type strategies[] = {
+ { "-exact", reg_strategy_exact },
+ { "-glob", reg_strategy_glob },
+ { "-regexp", reg_strategy_regexp },
+ { "-null", reg_strategy_null },
+ { "--", reg_strategy_exact },
+ { NULL, 0 }
+};
+
+/*
+ * registry::portgroup search ?key value ...?
+ *
+ * Searches the registry for portgroups for which each key's value is equal to the
+ * given value. To find all portgroups, call `portgroup search` with no key-value pairs.
+ * For each key, can be given an option of -exact, -glob, -regexp or -null to
+ * specify the matching strategy; defaults to exact.
+ */
+static int portgroup_search(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
+ int i, j;
+ reg_registry* reg = registry_for(interp, reg_attached);
+ if (reg == NULL) {
+ return TCL_ERROR;
+ } else {
+ char** keys;
+ char** vals;
+ int* strats;
+ int key_count = 0;
+ reg_portgroup** portgroups;
+ reg_error error;
+ int portgroup_count;
+ for (i = 2; i < objc;) {
+ int index, strat_index, val_length;
+ if (Tcl_GetIndexFromObj(interp, objv[i], portgroup_props, "search key",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /* we ate the key value */
+ i++;
+
+ /* check whether there's a strategy */
+ if (Tcl_GetString(objv[i])[0] == '-'
+ && Tcl_GetIndexFromObjStruct(interp, objv[i], strategies,
+ sizeof(strategy_type), "option", 0, &strat_index)
+ != TCL_ERROR) {
+ /* this key has a strategy specified, eat the strategy parameter */
+ i++;
+
+ if (strategies[strat_index].strategy != reg_strategy_null) {
+ /* this key must also have a value */
+
+ if (Tcl_GetStringFromObj(objv[i], &val_length) == NULL
+ || val_length == 0) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "search ?key ?options? value ...?");
+ return TCL_ERROR;
+ }
+
+ i++;
+ }
+ } else {
+ /* this key must also have a value */
+
+ if (Tcl_GetStringFromObj(objv[i], &val_length) == NULL
+ || val_length == 0) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "search ?key ?options? value ...?");
+ return TCL_ERROR;
+ }
+
+ i++;
+ }
+
+ key_count++;
+ }
+
+ keys = malloc(key_count * sizeof(char*));
+ vals = malloc(key_count * sizeof(char*));
+ strats = malloc(key_count * sizeof(int));
+ if (!keys || !vals || !strats) {
+ return TCL_ERROR;
+ }
+ for (i = 2, j = 0; i < objc && j < key_count; j++) {
+ int strat_index;
+
+ keys[j] = Tcl_GetString(objv[i++]);
+
+ /* try to get the strategy */
+ if (Tcl_GetString(objv[i])[0] == '-'
+ && Tcl_GetIndexFromObjStruct(interp, objv[i], strategies,
+ sizeof(strategy_type), "option", 0, &strat_index)
+ != TCL_ERROR) {
+ /* this key has a strategy specified */
+ i++;
+
+ strats[j] = strategies[strat_index].strategy;
+ } else {
+ /* use default strategy */
+ strats[j] = reg_strategy_exact;
+ }
+
+ if (strats[j] != reg_strategy_null) {
+ vals[j] = Tcl_GetString(objv[i++]);
+ } else {
+ vals[j] = NULL;
+ }
+ }
+ portgroup_count = reg_portgroup_search(reg, keys, vals, strats, key_count,
+ &portgroups, &error);
+ free(keys);
+ free(vals);
+ free(strats);
+ if (portgroup_count >= 0) {
+ int retval;
+ Tcl_Obj* resultObj;
+ Tcl_Obj** objs;
+ if (list_portgroup_to_obj(interp, &objs, portgroups, portgroup_count, &error)){
+ resultObj = Tcl_NewListObj(portgroup_count, objs);
+ Tcl_SetObjResult(interp, resultObj);
+ free(objs);
+ retval = TCL_OK;
+ } else {
+ retval = registry_failed(interp, &error);
+ }
+ free(portgroups);
+ return retval;
+ }
+ return registry_failed(interp, &error);
+ }
+}
+
+typedef struct {
+ char* name;
+ int (*function)(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
+} portgroup_cmd_type;
+
+static portgroup_cmd_type portgroup_cmds[] = {
+ /* Global commands */
+ { "open", portgroup_open },
+ { "close", portgroup_close },
+ { "search", portgroup_search },
+ { NULL, NULL }
+};
+
+/*
+ * registry::portgroup cmd ?arg ...?
+ *
+ * Commands manipulating portgroup entries in the registry. This can be called `registry::portgroup`
+ */
+int portgroup_cmd(ClientData clientData UNUSED, Tcl_Interp* interp, int objc,
+ Tcl_Obj* CONST objv[]) {
+ int cmd_index;
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], portgroup_cmds,
+ sizeof(portgroup_cmd_type), "cmd", 0, &cmd_index) == TCL_OK) {
+ portgroup_cmd_type* cmd = &portgroup_cmds[cmd_index];
+ return cmd->function(interp, objc, objv);
+ }
+ return TCL_ERROR;
+}
Added: trunk/base/src/registry2.0/portgroup.h
===================================================================
--- trunk/base/src/registry2.0/portgroup.h (rev 0)
+++ trunk/base/src/registry2.0/portgroup.h 2014-02-25 18:28:14 UTC (rev 117407)
@@ -0,0 +1,42 @@
+/*
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2014 The MacPorts Project
+ * 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 _PORTGROUP_H
+#define _PORTGROUP_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tcl.h>
+
+void delete_portgroup(ClientData clientData);
+
+int portgroup_cmd(ClientData clientData UNUSED, Tcl_Interp* interp, int objc,
+ Tcl_Obj* CONST objv[]);
+
+#endif /* _PORTGROUP_H */
Added: trunk/base/src/registry2.0/portgroupobj.c
===================================================================
--- trunk/base/src/registry2.0/portgroupobj.c (rev 0)
+++ trunk/base/src/registry2.0/portgroupobj.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -0,0 +1,135 @@
+/*
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2014 The MacPorts Project
+ * 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 <tcl.h>
+#include <sqlite3.h>
+
+#include "portgroupobj.h"
+#include "registry.h"
+#include "util.h"
+
+const char* portgroup_props[] = {
+ "name",
+ "version",
+ "size",
+ "sha256",
+ NULL
+};
+
+/* ${portgroup} prop ?value? */
+static int portgroup_obj_prop(Tcl_Interp* interp, reg_portgroup* portgroup, int objc,
+ Tcl_Obj* CONST objv[]) {
+ int index;
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?value?");
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ /* ${portgroup} prop; return the current value */
+ reg_registry* reg = registry_for(interp, reg_attached);
+ if (reg == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], portgroup_props, "prop", 0, &index)
+ == TCL_OK) {
+ char* key = Tcl_GetString(objv[1]);
+ char* value;
+ reg_error error;
+ if (reg_portgroup_propget(portgroup, key, &value, &error)) {
+ Tcl_Obj* result = Tcl_NewStringObj(value, -1);
+ Tcl_SetObjResult(interp, result);
+ free(value);
+ return TCL_OK;
+ }
+ return registry_failed(interp, &error);
+ }
+ return TCL_ERROR;
+ } else {
+ /* ${portgroup} prop name value; set a new value */
+ reg_registry* reg = registry_for(interp, reg_attached);
+ if (reg == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], portgroup_props, "prop", 0, &index)
+ == TCL_OK) {
+ char* key = Tcl_GetString(objv[1]);
+ char* value = Tcl_GetString(objv[2]);
+ reg_error error;
+ if (reg_portgroup_propset(portgroup, key, value, &error)) {
+ return TCL_OK;
+ }
+ return registry_failed(interp, &error);
+ }
+ return TCL_ERROR;
+ }
+}
+
+typedef struct {
+ char* name;
+ int (*function)(Tcl_Interp* interp, reg_portgroup* portgroup, int objc,
+ Tcl_Obj* CONST objv[]);
+} portgroup_obj_cmd_type;
+
+static portgroup_obj_cmd_type portgroup_cmds[] = {
+ /* keys */
+ { "name", portgroup_obj_prop },
+ { "version", portgroup_obj_prop },
+ { "size", portgroup_obj_prop },
+ { "sha256", portgroup_obj_prop },
+ { NULL, NULL }
+};
+
+/* ${portgroup} cmd ?arg ...? */
+/* This function implements the command that will be called when a portgroup
+ * created by `registry::portgroup` is used as a procedure. Since all data is kept
+ * in a temporary sqlite3 database that is created for the current interpreter,
+ * none of the sqlite3 functions used have any error checking. That should be a
+ * safe assumption, since nothing outside of registry:: should ever have the
+ * chance to touch it.
+ */
+int portgroup_obj_cmd(ClientData clientData, Tcl_Interp* interp, int objc,
+ Tcl_Obj* CONST objv[]) {
+ int cmd_index;
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], portgroup_cmds,
+ sizeof(portgroup_obj_cmd_type), "cmd", 0, &cmd_index) == TCL_OK) {
+ portgroup_obj_cmd_type* cmd = &portgroup_cmds[cmd_index];
+ return cmd->function(interp, (reg_portgroup*)clientData, objc, objv);
+ }
+ return TCL_ERROR;
+}
+
Added: trunk/base/src/registry2.0/portgroupobj.h
===================================================================
--- trunk/base/src/registry2.0/portgroupobj.h (rev 0)
+++ trunk/base/src/registry2.0/portgroupobj.h 2014-02-25 18:28:14 UTC (rev 117407)
@@ -0,0 +1,43 @@
+/*
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2014 The MacPorts Project
+ * 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 _PORTGROUP_OBJ_CMD_H
+#define _PORTGROUP_OBJ_CMD_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tcl.h>
+#include <sqlite3.h>
+
+extern const char* portgroup_props[];
+
+int portgroup_obj_cmd(ClientData clientData, Tcl_Interp* interp, int objc,
+ Tcl_Obj* CONST objv[]);
+
+#endif /* _PORTGROUP_OBJ_CMD_H */
Modified: trunk/base/src/registry2.0/portuninstall.tcl
===================================================================
--- trunk/base/src/registry2.0/portuninstall.tcl 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/registry2.0/portuninstall.tcl 2014-02-25 18:28:14 UTC (rev 117407)
@@ -53,7 +53,7 @@
proc uninstall {portname {version ""} {revision ""} {variants 0} {optionslist ""}} {
global uninstall.force uninstall.nochecksum UI_PREFIX \
- macports::portimagefilepath
+ macports::portimagefilepath macports::registry.path
array set options $optionslist
if {[info exists options(subport)]} {
# don't want this set when calling registry::run_target
@@ -156,7 +156,7 @@
# look up deps from the saved portfile if possible
if {![catch {set mport [mportopen_installed [$port name] [$port version] [$port revision] [$port variants] $optionslist]}]} {
array set depportinfo [mportinfo $mport]
- mportclose_installed $mport
+ mportclose $mport
foreach type $deptypes {
if {[info exists depportinfo($type)]} {
foreach dep $depportinfo($type) {
@@ -217,9 +217,37 @@
# files so just ignore the failure
catch {file delete [::file dirname $imagefile]}
+ # We want to delete the portfile if not referenced by any other ports
+ set portfile [$ref portfile]
+
+ # and likewise the portgroups
+ set portgroups [list]
+ foreach pg [$ref groups_used] {
+ lappend portgroups [list [$pg name] [$pg version] [$pg size] [$pg sha256]]
+ }
+
registry::write {
registry::entry delete $port
}
+
+ set portfile_path [file join ${registry.path} registry portfiles ${portname}-${version}_${revision} $portfile]
+ if {[registry::entry search portfile $portfile] eq {}} {
+ file delete -force $portfile_path
+ catch {file delete [file dirname $portfile_path]}
+ }
+
+ set reg_portgroups_dir [file join ${registry.path} registry portgroups]
+ foreach pg $portgroups {
+ set pgname [lindex $pg 0]
+ set pgversion [lindex $pg 1]
+ set pgsize [lindex $pg 2]
+ set pgsha256 [lindex $pg 3]
+ if {[registry::portgroup search name $pgname version $pgversion size $pgsize sha256 $pgsha256] eq {}} {
+ set pg_reg_dir [file join $reg_portgroups_dir ${pgsha256}-${pgsize}]
+ file delete -force ${pg_reg_dir}/${pgname}-${pgversion}.tcl
+ catch {file delete $pg_reg_dir}
+ }
+ }
}
# uninstall dependencies if requested
Modified: trunk/base/src/registry2.0/registry.c
===================================================================
--- trunk/base/src/registry2.0/registry.c 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/registry2.0/registry.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -3,7 +3,7 @@
* $Id$
*
* Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
- * Copyright (c) 2012 The MacPorts Project
+ * Copyright (c) 2012, 2014 The MacPorts Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
#include <tcl.h>
#include <cregistry/registry.h>
+#include <cregistry/portgroup.h>
#include <cregistry/entry.h>
#include <cregistry/file.h>
@@ -46,6 +47,7 @@
#include "file.h"
#include "graph.h"
#include "item.h"
+#include "portgroup.h"
#include "registry.h"
#include "util.h"
@@ -389,6 +391,7 @@
/* Tcl_CreateObjCommand(interp, "registry::item", item_cmd, NULL, NULL); */
Tcl_CreateObjCommand(interp, "registry::entry", entry_cmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "registry::file", file_cmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "registry::portgroup", portgroup_cmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "registry::metadata", metadata_cmd, NULL, NULL);
if (Tcl_PkgProvide(interp, "registry2", "2.0") != TCL_OK) {
return TCL_ERROR;
Modified: trunk/base/src/registry2.0/registry.h
===================================================================
--- trunk/base/src/registry2.0/registry.h 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/registry2.0/registry.h 2014-02-25 18:28:14 UTC (rev 117407)
@@ -34,6 +34,7 @@
#include <tcl.h>
#include <sqlite3.h>
+#include <cregistry/portgroup.h>
#include <cregistry/entry.h>
typedef struct _entry_list {
Modified: trunk/base/src/registry2.0/registry_util.tcl
===================================================================
--- trunk/base/src/registry2.0/registry_util.tcl 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/registry2.0/registry_util.tcl 2014-02-25 18:28:14 UTC (rev 117407)
@@ -103,7 +103,7 @@
if {[catch {set result [mportexec $mport $target]} result] || $result != 0} {
global errorInfo
ui_debug "$errorInfo"
- catch {mportclose_installed $mport}
+ catch {mportclose $mport}
ui_warn "Failed to execute portfile from registry for $portspec"
switch $target {
activate {
@@ -127,7 +127,7 @@
if {(![info exists keeplogs] || !$keeplogs) && $target ne "activate"} {
catch {mportexec $mport clean}
}
- mportclose_installed $mport
+ mportclose $mport
return 1
}
} else {
Modified: trunk/base/src/registry2.0/util.c
===================================================================
--- trunk/base/src/registry2.0/util.c 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/registry2.0/util.c 2014-02-25 18:28:14 UTC (rev 117407)
@@ -38,6 +38,7 @@
#include "util.h"
#include "entryobj.h"
#include "fileobj.h"
+#include "portgroupobj.h"
/**
* Generates a unique proc name starting with prefix.
@@ -214,6 +215,29 @@
}
/**
+ * Sets a given name to be a portgroup object.
+ *
+ * @param [in] interp Tcl interpreter to create the portgroup within
+ * @param [in] name name to associate the given portgroup with
+ * @param [in] portgroup portgroup to associate with the given name
+ * @param [out] errPtr description of error if it couldn't be set
+ * @return true if success; false if failure
+ * @see set_object
+ */
+int set_portgroup(Tcl_Interp* interp, char* name, reg_portgroup* portgroup,
+ reg_error* errPtr) {
+ if (set_object(interp, name, portgroup, "portgroup", portgroup_obj_cmd, NULL,
+ errPtr)) {
+ portgroup->proc = strdup(name);
+ if (!portgroup->proc) {
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/**
* Reports a sqlite3 error to Tcl.
*
* Queries the database for the most recent error message and sets it as the
@@ -297,6 +321,23 @@
return 1;
}
+int portgroup_to_obj(Tcl_Interp* interp, Tcl_Obj** obj, reg_portgroup* portgroup,
+ int* lower_bound, reg_error* errPtr) {
+ if (portgroup->proc == NULL) {
+ char* name = unique_name(interp, "::registry::portgroup", lower_bound);
+ if (!name) {
+ return 0;
+ }
+ if (!set_portgroup(interp, name, portgroup, errPtr)) {
+ free(name);
+ return 0;
+ }
+ free(name);
+ }
+ *obj = Tcl_NewStringObj(portgroup->proc, -1);
+ return 1;
+}
+
int list_entry_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
reg_entry** entries, int entry_count, reg_error* errPtr) {
int lower_bound = 0;
@@ -311,6 +352,13 @@
(void***)objs, (void**)files, file_count, errPtr);
}
+int list_portgroup_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
+ reg_portgroup** portgroups, int portgroup_count, reg_error* errPtr) {
+ int lower_bound = 0;
+ return recast(interp, (cast_function*)portgroup_to_obj, &lower_bound, NULL,
+ (void***)objs, (void**)portgroups, portgroup_count, errPtr);
+}
+
static int obj_to_string(void* userdata UNUSED, char** string, Tcl_Obj* obj,
void* param UNUSED, reg_error* errPtr UNUSED) {
*string = Tcl_GetString(obj);
Modified: trunk/base/src/registry2.0/util.h
===================================================================
--- trunk/base/src/registry2.0/util.h 2014-02-25 16:10:21 UTC (rev 117406)
+++ trunk/base/src/registry2.0/util.h 2014-02-25 18:28:14 UTC (rev 117407)
@@ -37,6 +37,7 @@
#include <sqlite3.h>
#include <cregistry/registry.h>
+#include <cregistry/portgroup.h>
#include <cregistry/entry.h>
#include <cregistry/file.h>
@@ -60,6 +61,8 @@
reg_error* errPtr);
int set_file(Tcl_Interp* interp, char* name, reg_file* file,
reg_error* errPtr);
+int set_portgroup(Tcl_Interp* interp, char* name, reg_portgroup* portgroup,
+ reg_error* errPtr);
void set_sqlite_result(Tcl_Interp* interp, sqlite3* db, const char* query);
@@ -77,6 +80,10 @@
int* lower_bound, reg_error* errPtr);
int list_file_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
reg_file** files, int file_count, reg_error* errPtr);
+int portgroup_to_obj(Tcl_Interp* interp, Tcl_Obj** ibj, reg_portgroup* portgroup,
+ int* lower_bound, reg_error* errPtr);
+int list_portgroup_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
+ reg_portgroup** portgroups, int portgroup_count, reg_error* errPtr);
void free_strings(void* userdata UNUSED, char** strings, int count);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/macports-changes/attachments/20140225/887f6c26/attachment-0001.html>
More information about the macports-changes
mailing list