[88376] trunk/base
cal at macports.org
cal at macports.org
Thu Dec 29 16:17:51 PST 2011
Revision: 88376
http://trac.macports.org/changeset/88376
Author: cal at macports.org
Date: 2011-12-29 16:17:49 -0800 (Thu, 29 Dec 2011)
Log Message:
-----------
Merge from ^/branches/gsoc11-rev-upgrade
Modified Paths:
--------------
trunk/base/configure
trunk/base/configure.ac
trunk/base/doc/port.1
trunk/base/src/Makefile.in
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
trunk/base/src/macports1.0/macports.tcl
trunk/base/src/pextlib1.0/Pextlib.c
trunk/base/src/port/port.tcl
trunk/base/src/port1.0/port_autoconf.tcl.in
trunk/base/src/registry2.0/Makefile
trunk/base/src/registry2.0/entry.c
trunk/base/src/registry2.0/portimage.tcl
trunk/base/src/registry2.0/portuninstall.tcl
trunk/base/src/registry2.0/receipt_flat.tcl
trunk/base/src/registry2.0/registry.c
trunk/base/src/registry2.0/registry.tcl
trunk/base/src/registry2.0/util.c
trunk/base/src/registry2.0/util.h
Added Paths:
-----------
trunk/base/src/cregistry/file.c
trunk/base/src/cregistry/file.h
trunk/base/src/cregistry/util.c
trunk/base/src/cregistry/util.h
trunk/base/src/machista1.0/
trunk/base/src/registry2.0/file.c
trunk/base/src/registry2.0/file.h
trunk/base/src/registry2.0/fileobj.c
trunk/base/src/registry2.0/fileobj.h
trunk/base/tests/test/svn-and-patchsites/
Removed Paths:
-------------
trunk/base/tests/test/svn-and-patchsites/
Property Changed:
----------------
trunk/base/
trunk/base/portmgr/fedora/macports.spec
trunk/base/src/machista1.0/tests/
trunk/base/src/pextlib1.0/sha2.c
trunk/base/src/pextlib1.0/sha2.h
trunk/base/src/pextlib1.0/sha256cmd.c
trunk/base/src/pextlib1.0/sha256cmd.h
trunk/base/src/registry2.0/receipt_sqlite.tcl
Property changes on: trunk/base
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/gsoc08-privileges/base:37343-46937
/branches/gsoc09-logging/base:51231-60371
/branches/universal-sanity/base:51872-52323
/branches/variant-descs-14482/base:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes:45682-46060
/users/perry/base-select:44044-44692
+ /branches/gsoc08-privileges/base:37343-46937
/branches/gsoc09-logging/base:51231-60371
/branches/gsoc11-rev-upgrade/base:78828-88375
/branches/universal-sanity/base:51872-52323
/branches/variant-descs-14482/base:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes:45682-46060
/users/perry/base-select:44044-44692
Modified: trunk/base/configure
===================================================================
--- trunk/base/configure 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/configure 2011-12-30 00:17:49 UTC (rev 88376)
@@ -679,6 +679,7 @@
TAR_CMD
TAR_Q
SED_EXT
+SWIG
OPEN
XAR
PAX
@@ -844,6 +845,7 @@
XZ
XAR
OPEN
+SWIG
OBJCPP
CPP'
ac_subdirs_all='src/thread2.6'
@@ -1530,6 +1532,7 @@
XZ path to xz command
XAR path to xar command
OPEN path to open command
+ SWIG path to swig command
OBJCPP Objective C preprocessor
CPP C preprocessor
@@ -5784,7 +5787,48 @@
fi
+# Extract the first word of "swig", so it can be a program name with args.
+set dummy swig; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_SWIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $SWIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_SWIG="$SWIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_SWIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+ test -z "$ac_cv_path_SWIG" && ac_cv_path_SWIG="$PATH:/usr/local/bin"
+ ;;
+esac
+fi
+SWIG=$ac_cv_path_SWIG
+if test -n "$SWIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG" >&5
+$as_echo "$SWIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
# Define some precious variables allowing user to override PATH for some programs
@@ -5804,6 +5848,7 @@
+
# Extract the first word of "sed", so it can be a program name with args.
set dummy sed; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -9740,7 +9785,7 @@
# Output
-ac_config_files="$ac_config_files Doxyfile Makefile Mk/macports.autoconf.mk doc/base.mtree doc/prefix.mtree doc/macosx.mtree doc/macports.conf doc/pubkeys.conf portmgr/freebsd/Makefile src/Makefile src/macports1.0/macports_autoconf.tcl src/port1.0/port_autoconf.tcl src/registry2.0/registry_autoconf.tcl src/programs/Makefile src/macports1.0/macports_fastload.tcl setupenv.bash"
+ac_config_files="$ac_config_files Doxyfile Makefile Mk/macports.autoconf.mk doc/base.mtree doc/prefix.mtree doc/macosx.mtree doc/macports.conf doc/pubkeys.conf portmgr/freebsd/Makefile src/Makefile src/machista1.0/Makefile src/macports1.0/macports_autoconf.tcl src/port1.0/port_autoconf.tcl src/registry2.0/registry_autoconf.tcl src/programs/Makefile src/macports1.0/macports_fastload.tcl setupenv.bash"
ac_config_files="$ac_config_files src/pkg_mkindex.sh"
@@ -10460,6 +10505,7 @@
"doc/pubkeys.conf") CONFIG_FILES="$CONFIG_FILES doc/pubkeys.conf" ;;
"portmgr/freebsd/Makefile") CONFIG_FILES="$CONFIG_FILES portmgr/freebsd/Makefile" ;;
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+ "src/machista1.0/Makefile") CONFIG_FILES="$CONFIG_FILES src/machista1.0/Makefile" ;;
"src/macports1.0/macports_autoconf.tcl") CONFIG_FILES="$CONFIG_FILES src/macports1.0/macports_autoconf.tcl" ;;
"src/port1.0/port_autoconf.tcl") CONFIG_FILES="$CONFIG_FILES src/port1.0/port_autoconf.tcl" ;;
"src/registry2.0/registry_autoconf.tcl") CONFIG_FILES="$CONFIG_FILES src/registry2.0/registry_autoconf.tcl" ;;
Modified: trunk/base/configure.ac
===================================================================
--- trunk/base/configure.ac 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/configure.ac 2011-12-30 00:17:49 UTC (rev 88376)
@@ -126,6 +126,7 @@
AC_PATH_PROG(PAX, [pax], [])
AC_PATH_PROG(XAR, [xar], [])
AC_PATH_PROG(OPEN, [open], [])
+AC_PATH_PROG(SWIG, [swig], [$PATH:/usr/local/bin])
# Define some precious variables allowing user to override PATH for some programs
AC_ARG_VAR(MTREE, [path to mtree command])
@@ -144,6 +145,7 @@
AC_ARG_VAR(XZ, [path to xz command])
AC_ARG_VAR(XAR, [path to xar command])
AC_ARG_VAR(OPEN, [path to open command])
+AC_ARG_VAR(SWIG, [path to swig command])
MP_SED_EXTENDED_REGEXP
MP_TAR_FAST_READ
@@ -368,6 +370,7 @@
doc/pubkeys.conf
portmgr/freebsd/Makefile
src/Makefile
+ src/machista1.0/Makefile
src/macports1.0/macports_autoconf.tcl
src/port1.0/port_autoconf.tcl
src/registry2.0/registry_autoconf.tcl
Modified: trunk/base/doc/port.1
===================================================================
--- trunk/base/doc/port.1 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/doc/port.1 2011-12-30 00:17:49 UTC (rev 88376)
@@ -492,6 +492,24 @@
upgrade will not normally rebuild a port only to change the selected
variants; you can either specify --enforce-variants, or deactivate the port and reinstall it
with different variants.
+.Pp
+After the upgrade MacPorts will automatically run \fBrev-upgrade\fP to check for
+broken ports that need to be rebuilt. If there are known problems with
+\fBrev-upgrade\fP or other reasons why you would want to avoid running this
+step, you can disable it by running \fBport upgrade\fP with the
+\fB--no-rev-upgrade\fP switch:
+.Pp
+.Dl "port upgrade --no-rev-upgrade outdated"
+.Ss rev-upgrade
+Manually check for broken binaries and rebuild ports containing broken binaries.
+\fBrev-upgrade\fP is usually automatically run after each upgrade, unless you
+specify the \fB--no-rev-upgrade\fP option.
+.Pp
+\fBrev-upgrade\fP can run more checks against a special loadcommand in Mach-O
+binaries that should always be referencing the file itself. This check is most
+helpful for maintainers to check whether their ports have been built correctly.
+It is disabled by default and can be enabled by passing \fB--id-loadcmd-check\fP
+to \fBrev-upgrade\fP.
.Ss clean
Clean the files used for building
.Ar portname .
Property changes on: trunk/base/portmgr/fedora/macports.spec
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/gsoc08-privileges/base/portmgr/fedora/macports.spec:37343-46937
/branches/universal-sanity/base/portmgr/fedora/macports.spec:51872-52323
/branches/variant-descs-14482/base/portmgr/fedora/macports.spec:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/trunk/base/portmgr/fedora/macports.spec.in:30388-57826
/users/perry/base-bugs_and_notes/portmgr/fedora/macports.spec:45682-46060
/users/perry/base-select/portmgr/fedora/macports.spec:44044-44692
+ /branches/gsoc08-privileges/base/portmgr/fedora/macports.spec:37343-46937
/branches/gsoc11-rev-upgrade/base/portmgr/fedora/macports.spec:78828-88375
/branches/universal-sanity/base/portmgr/fedora/macports.spec:51872-52323
/branches/variant-descs-14482/base/portmgr/fedora/macports.spec:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/trunk/base/portmgr/fedora/macports.spec.in:30388-57826
/users/perry/base-bugs_and_notes/portmgr/fedora/macports.spec:45682-46060
/users/perry/base-select/portmgr/fedora/macports.spec:44044-44692
Modified: trunk/base/src/Makefile.in
===================================================================
--- trunk/base/src/Makefile.in 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/Makefile.in 2011-12-30 00:17:49 UTC (rev 88376)
@@ -5,7 +5,8 @@
package1.0 \
pextlib1.0 \
registry2.0 \
- darwintracelib1.0
+ darwintracelib1.0 \
+ machista1.0
SUBDIR= ${TCLPKG} port programs
all::
Modified: trunk/base/src/cregistry/Makefile
===================================================================
--- trunk/base/src/cregistry/Makefile 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/cregistry/Makefile 2011-12-30 00:17:49 UTC (rev 88376)
@@ -1,6 +1,6 @@
# $Id$
-OBJS = registry.o entry.o sql.o vercomp.o
+OBJS = registry.o entry.o sql.o vercomp.o util.o file.o
STLIB_NAME = cregistry.a
RANLIB = ranlib
Modified: trunk/base/src/cregistry/entry.c
===================================================================
--- trunk/base/src/cregistry/entry.c 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/cregistry/entry.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -34,10 +34,11 @@
#include "entry.h"
#include "registry.h"
#include "sql.h"
+#include "util.h"
-#include <string.h>
-#include <stdlib.h>
#include <sqlite3.h>
+#include <stdlib.h>
+#include <string.h>
/*
* TODO: possibly, allow reg_entry_search to take different matching strategies
@@ -53,9 +54,6 @@
* always have very discrete values. These could be more efficiently dealt
* with as integers.
*
- * TODO: move the utility functions to util.h or something. Not important until
- * there are more types in the registry than entry, though.
- *
* TODO: considering a "weak" flag in registry.files. The meaning of this would
* be "I wish for my version of this file to be activated when I am, but
* not to be deactivated when I am; nor should other ports be prevented
@@ -69,85 +67,6 @@
*/
/**
- * 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.
- *
- * @param [in,out] dst a reference to a null-terminated string
- * @param [in,out] dst_len number of characters currently in `dst`
- * @param [in,out] dst_space number of characters `dst` can hold
- * @param [in] src string to concatenate to `dst`
- */
-static int reg_strcat(char** dst, size_t* dst_len, size_t* dst_space, char* src) {
- size_t src_len = strlen(src);
- size_t result_len = *dst_len + src_len;
- if (result_len > *dst_space) {
- char* new_dst;
- *dst_space *= 2;
- if (*dst_space < result_len) {
- *dst_space = result_len;
- }
- new_dst = realloc(*dst, *dst_space * sizeof(char) + 1);
- if (!new_dst)
- return 0;
- else
- *dst = new_dst;
- }
- memcpy(*dst + *dst_len, src, src_len+1);
- *dst_len = result_len;
- return 1;
-}
-
-/**
- * Appends element `src` to the list `dst`. It's like `reg_strcat`, except `src`
- * represents a single element and not a sequence of `char`s.
- *
- * @param [in,out] dst a reference to a list of pointers
- * @param [in,out] dst_len number of elements currently in `dst`
- * @param [in,out] dst_space number of elements `dst` can hold
- * @param [in] src elements to append to `dst`
- */
-static int reg_listcat(void*** dst, int* dst_len, int* dst_space, void* src) {
- if (*dst_len == *dst_space) {
- void** new_dst;
- *dst_space *= 2;
- new_dst = realloc(*dst, *dst_space * sizeof(void*));
- if (!new_dst)
- return 0;
- else
- *dst = new_dst;
- }
- (*dst)[*dst_len] = src;
- (*dst_len)++;
- return 1;
-}
-
-/**
- * Returns an expression to use for the given strategy. This should be passed as
- * the `fmt` argument of `sqlite3_mprintf`, with the key and value following.
- *
- * @param [in] strategy a strategy (one of the `reg_strategy_*` constants)
- * @param [out] errPtr on error, a description of the error that occurred
- * @return a sqlite3 expression if success; NULL if failure
- */
-static char* reg_strategy_op(reg_strategy strategy, reg_error* errPtr) {
- switch (strategy) {
- case reg_strategy_exact:
- return "%q = '%q'";
- case reg_strategy_glob:
- return "%q GLOB '%q'";
- case reg_strategy_regexp:
- return "REGEXP(%q, '%q')";
- default:
- errPtr->code = REG_INVALID;
- errPtr->description = "invalid matching strategy specified";
- errPtr->free = NULL;
- return NULL;
- }
-}
-
-/**
* Converts a `sqlite3_stmt` into a `reg_entry`. The first column of the stmt's
* row must be the id of an entry; the second either `SQLITE_NULL` or the
* address of the entry in memory.
@@ -159,7 +78,7 @@
* @return true if success; false if failure
*/
static int reg_stmt_to_entry(void* userdata, void** entry, void* stmt,
- reg_error* errPtr UNUSED) {
+ void* calldata UNUSED, reg_error* errPtr UNUSED) {
int is_new;
reg_registry* reg = (reg_registry*)userdata;
sqlite_int64 id = sqlite3_column_int64(stmt, 0);
@@ -262,6 +181,7 @@
char* revision, char* variants, char* epoch, reg_error* errPtr) {
sqlite3_stmt* stmt = NULL;
reg_entry* entry = NULL;
+ int lower_bound = 0;
char* query;
if (strlen(epoch) > 0) {
query = "SELECT id FROM registry.ports WHERE name=? AND version=? "
@@ -286,7 +206,7 @@
r = sqlite3_step(stmt);
switch (r) {
case SQLITE_ROW:
- reg_stmt_to_entry(reg, (void**)&entry, stmt, errPtr);
+ reg_stmt_to_entry(reg, (void**)&entry, stmt, &lower_bound, errPtr);
break;
case SQLITE_DONE:
errPtr->code = REG_NOT_FOUND;
@@ -416,72 +336,6 @@
}
/**
- * Convenience method for returning all objects of a given type from the
- * registry.
- *
- * @param [in] reg registry to select objects 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 objects selected
- * @param [in] fn a function to convert sqlite3_stmts to the desired type
- * @param [in] del a function to delete the desired type of object
- * @param [out] errPtr on error, a description of the error that occurred
- * @return the number of objects if success; negative if failure
- */
-static int reg_all_objects(reg_registry* reg, char* query, int query_len,
- void*** objects, cast_function* fn, free_function* del,
- reg_error* errPtr) {
- void** results = malloc(10*sizeof(void*));
- int result_count = 0;
- int result_space = 10;
- sqlite3_stmt* stmt = NULL;
- if (!results || !fn) {
- return -1;
- }
- if (sqlite3_prepare(reg->db, query, query_len, &stmt, NULL) == SQLITE_OK) {
- int r;
- reg_entry* entry;
- do {
- r = sqlite3_step(stmt);
- switch (r) {
- case SQLITE_ROW:
- if (fn(reg, (void**)&entry, stmt, errPtr)) {
- if (!reg_listcat(&results, &result_count, &result_space, entry)) {
- r = SQLITE_ERROR;
- }
- } else {
- r = SQLITE_ERROR;
- }
- break;
- case SQLITE_DONE:
- case SQLITE_BUSY:
- break;
- default:
- reg_sqlite_error(reg->db, errPtr, query);
- break;
- }
- } while (r == SQLITE_ROW || r == SQLITE_BUSY);
- sqlite3_finalize(stmt);
- if (r == SQLITE_DONE) {
- *objects = results;
- return result_count;
- } else if (del) {
- int i;
- for (i=0; i<result_count; i++) {
- del(NULL, results[i]);
- }
- }
- } else {
- if (stmt) {
- sqlite3_finalize(stmt);
- }
- reg_sqlite_error(reg->db, errPtr, query);
- }
- free(results);
- return -1;
-}
-
-/**
* Type-safe version of `reg_all_objects` for `reg_entry`.
*
* @param [in] reg registry to select entries from
@@ -493,8 +347,9 @@
*/
static int reg_all_entries(reg_registry* reg, char* query, int query_len,
reg_entry*** objects, reg_error* errPtr) {
+ int lower_bound = 0;
return reg_all_objects(reg, query, query_len, (void***)objects,
- reg_stmt_to_entry, NULL, errPtr);
+ reg_stmt_to_entry, &lower_bound, NULL, errPtr);
}
/**
@@ -640,6 +495,7 @@
int result = 0;
sqlite3_stmt* stmt = NULL;
char* query = "SELECT id FROM registry.files WHERE actual_path=? AND active";
+ int lower_bound = 0;
if ((sqlite3_prepare(reg->db, query, -1, &stmt, NULL) == SQLITE_OK)
&& (sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC)
== SQLITE_OK)) {
@@ -649,7 +505,7 @@
switch (r) {
case SQLITE_ROW:
result = reg_stmt_to_entry(reg, (void**)entry, stmt,
- errPtr);
+ &lower_bound, errPtr);
break;
case SQLITE_DONE:
*entry = NULL;
Modified: trunk/base/src/cregistry/entry.h
===================================================================
--- trunk/base/src/cregistry/entry.h 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/cregistry/entry.h 2011-12-30 00:17:49 UTC (rev 88376)
@@ -36,12 +36,6 @@
#include <sqlite3.h>
-typedef enum {
- reg_strategy_exact = 1,
- reg_strategy_glob = 2,
- reg_strategy_regexp = 3
-} reg_strategy;
-
typedef struct {
sqlite_int64 id; /* rowid in database */
reg_registry* reg; /* associated registry */
Copied: trunk/base/src/cregistry/file.c (from rev 88375, branches/gsoc11-rev-upgrade/base/src/cregistry/file.c)
===================================================================
--- trunk/base/src/cregistry/file.c (rev 0)
+++ trunk/base/src/cregistry/file.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -0,0 +1,353 @@
+/*
+ * file.c
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2011 Clemens Lang <cal 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 "file.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_file`. The first column of the stmt's
+ * row must be the id of a file; the second column must be the path of a file;
+ * the third either `SQLITE_NULL` or the address of the entry in memory.
+ *
+ * @param [in] userdata sqlite3 database
+ * @param [out] file file 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_file(void* userdata, void** file, void* stmt,
+ void* calldata UNUSED, reg_error* errPtr UNUSED) {
+ int is_new;
+ reg_registry* reg = (reg_registry*)userdata;
+ reg_file_pk key;
+ Tcl_HashEntry* hash;
+ char* hashkey;
+
+ key.id = sqlite3_column_int64(stmt, 0);
+ key.path = strdup((const char*) sqlite3_column_text(stmt, 1));
+ if (!key.path) {
+ return 0;
+ }
+
+ hashkey = sqlite3_mprintf("%lld:%s", key.id, key.path);
+ if (!hashkey) {
+ free(key.path);
+ return 0;
+ }
+ hash = Tcl_CreateHashEntry(®->open_files,
+ hashkey, &is_new);
+ sqlite3_free(hashkey);
+
+ if (is_new) {
+ reg_file* f = malloc(sizeof(reg_file));
+ if (!f) {
+ free(key.path);
+ return 0;
+ }
+ f->reg = reg;
+ f->key = key;
+ f->proc = NULL;
+ *file = f;
+ Tcl_SetHashValue(hash, f);
+ } else {
+ free(key.path);
+ *file = Tcl_GetHashValue(hash);
+ }
+ return 1;
+}
+
+/**
+ * Opens an existing file in the registry.
+ *
+ * @param [in] reg registry to open entry in
+ * @param [in] id port id in the dabatase
+ * @param [in] path file path in the database
+ * @param [out] errPtr on error, a description of the error that occures
+ * @return the file if success, NULL if failure
+ */
+reg_file* reg_file_open(reg_registry* reg, char* id, char* name,
+ reg_error* errPtr) {
+ sqlite3_stmt* stmt = NULL;
+ reg_file* file = NULL;
+ char* query = "SELECT id, path FROM registry.files WHERE id=? AND path=?";
+ int lower_bound = 0;
+
+ if ((sqlite3_prepare(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)) {
+ int r;
+ do {
+ r = sqlite3_step(stmt);
+ switch (r) {
+ case SQLITE_ROW:
+ reg_stmt_to_file(reg, (void**)&file, stmt, &lower_bound,
+ errPtr);
+ break;
+ case SQLITE_DONE:
+ errPtr->code = REG_NOT_FOUND;
+ errPtr->description = sqlite3_mprintf("no matching file found for: "
+ "id=%s, name=%s", id, name);
+ 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 file;
+}
+
+/**
+ * Type-safe version of `reg_all_objects` for `reg_file`.
+ *
+ * @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 files selected
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return the number of entries if success; negative if failure
+ */
+static int reg_all_files(reg_registry* reg, char* query, int query_len,
+ reg_file*** objects, reg_error* errPtr) {
+ int lower_bound = 0;
+ return reg_all_objects(reg, query, query_len, (void***)objects,
+ reg_stmt_to_file, &lower_bound, NULL, errPtr);
+}
+
+/**
+ * Searches the registry for files for which each key's value is equal to the
+ * given value. To find all files, 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] files a list of matching files
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return the number of entries if success; false if failure
+ */
+int reg_file_search(reg_registry* reg, char** keys, char** vals, int* strats,
+ int key_count, reg_file*** files, reg_error* errPtr) {
+ int i;
+ char* kwd = " WHERE ";
+ char* query;
+ size_t query_len, query_space;
+ int result;
+
+ /* build the query */
+ query = strdup("SELECT id, path FROM registry.files");
+ 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_files(reg, query, -1, files, errPtr);
+ free(query);
+ return result;
+}
+
+/**
+ * Gets a named property of a file. That property can be set using
+ * `reg_file_propset`. The property named must be one that exists in the table
+ * and must not be one with internal meaning such as `id`.
+ *
+ * @param [in] file file 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_file_propget(reg_file* file, char* key, char** value,
+ reg_error* errPtr) {
+ reg_registry* reg = file->reg;
+ int result = 0;
+ sqlite3_stmt* stmt = NULL;
+ char* query;
+ const char *text;
+ query = sqlite3_mprintf("SELECT %q FROM registry.files WHERE id=%lld "
+ "AND path='%q'", key, file->key.id, file->key.path);
+ if (sqlite3_prepare(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 file 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 a file. That property can be later retrieved using
+ * `reg_file_propget`. The property named must be one that exists in the table
+ * and must not be one with internal meaning such as `id`.
+ *
+ * @param [in] file file 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_file_propset(reg_file* file, char* key, char* value,
+ reg_error* errPtr) {
+ reg_registry* reg = file->reg;
+ int result = 0;
+ sqlite3_stmt* stmt = NULL;
+ char* query;
+ query = sqlite3_mprintf("UPDATE registry.files SET %q = '%q' WHERE id=%lld "
+ "AND path='%q'", key, value, file->key.id, file->key.path);
+ if (sqlite3_prepare(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:
+ continue;
+ 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;
+}
+
+/**
+ * Fetches a list of all open files
+ *
+ * @param [in] reg registry to fetch files from
+ * @param [out] files a list of open files
+ * @return the number of open entries, -1 on error
+ */
+int reg_all_open_files(reg_registry* reg, reg_file*** files) {
+ reg_file* file;
+ int file_count = 0;
+ int file_space = 10;
+ Tcl_HashEntry* hash;
+ Tcl_HashSearch search;
+ *files = malloc(10 * sizeof(void*));
+ if (!*files) {
+ return -1;
+ }
+ for (hash = Tcl_FirstHashEntry(®->open_files, &search); hash != NULL;
+ hash = Tcl_NextHashEntry(&search)) {
+ file = Tcl_GetHashValue(hash);
+ if (!reg_listcat((void***)files, &file_count, &file_space, file)) {
+ free(*files);
+ return -1;
+ }
+ }
+ return file_count;
+}
+
Copied: trunk/base/src/cregistry/file.h (from rev 88375, branches/gsoc11-rev-upgrade/base/src/cregistry/file.h)
===================================================================
--- trunk/base/src/cregistry/file.h (rev 0)
+++ trunk/base/src/cregistry/file.h 2011-12-30 00:17:49 UTC (rev 88376)
@@ -0,0 +1,66 @@
+/*
+ * file.h
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2011 Clemens Lang <cal 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 _CFILE_H
+#define _CFILE_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "registry.h"
+
+#include <sqlite3.h>
+
+typedef struct {
+ /* rowid and path form the primary key */
+ /* unfortunately, we don't have a surrogate key in this db */
+ sqlite_int64 id; /* rowid in the database */
+ char* path; /* path in the database */
+} reg_file_pk;
+
+typedef struct {
+ reg_file_pk key;
+ reg_registry* reg; /* associated registry */
+ char* proc; /* name of Tcl proc, if using Tcl */
+} reg_file;
+
+reg_file* reg_file_open(reg_registry* reg, char* id, char* path,
+ reg_error* errPtr);
+
+int reg_file_search(reg_registry* reg, char** keys, char** vals, int* strats,
+ int key_count, reg_file*** files, reg_error* errPtr);
+
+int reg_file_propget(reg_file* file, char* key, char** value,
+ reg_error* errPtr);
+int reg_file_propset(reg_file* file, char* key, char* value,
+ reg_error* errPtr);
+
+int reg_all_open_files(reg_registry* reg, reg_file*** files);
+
+#endif /* _CFILE_H */
Modified: trunk/base/src/cregistry/registry.c
===================================================================
--- trunk/base/src/cregistry/registry.c 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/cregistry/registry.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -1,6 +1,7 @@
/*
* registry.c
* $Id$
+ * vim:expandtab:tw=80
*
* Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
* All rights reserved.
@@ -31,6 +32,7 @@
#endif
#include "entry.h"
+#include "file.h"
#include "sql.h"
#include <stdio.h>
@@ -214,6 +216,8 @@
if (initialized || (create_tables(reg->db, errPtr))) {
Tcl_InitHashTable(®->open_entries,
sizeof(sqlite_int64)/sizeof(int));
+ Tcl_InitHashTable(®->open_files,
+ TCL_STRING_KEYS);
reg->status |= reg_attached;
result = 1;
}
@@ -224,6 +228,10 @@
reg_sqlite_error(reg->db, errPtr, query);
}
} while (r == SQLITE_BUSY);
+
+ if (result) {
+ result &= update_db(reg->db, errPtr);
+ }
} else {
reg_sqlite_error(reg->db, errPtr, query);
}
@@ -275,6 +283,15 @@
free(entry);
}
Tcl_DeleteHashTable(®->open_entries);
+ for (curr = Tcl_FirstHashEntry(®->open_files, &search);
+ curr != NULL; curr = Tcl_NextHashEntry(&search)) {
+ reg_file* file = Tcl_GetHashValue(curr);
+
+ free(file->proc);
+ free(file->key.path);
+ free(file);
+ }
+ Tcl_DeleteHashTable(®->open_files);
reg->status &= ~reg_attached;
result = 1;
break;
Modified: trunk/base/src/cregistry/registry.h
===================================================================
--- trunk/base/src/cregistry/registry.h 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/cregistry/registry.h 2011-12-30 00:17:49 UTC (rev 88376)
@@ -1,5 +1,6 @@
/*
* registry.h
+ * vim:tw=80:expandtab
* $Id$
*
* Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
@@ -56,7 +57,7 @@
void reg_throw(reg_error* errPtr, char* code, char* fmt, ...);
typedef int (cast_function)(void* userdata, void** dst, void* src,
- reg_error* errPtr);
+ void* calldata, reg_error* errPtr);
typedef void (free_function)(void* userdata, void* item);
enum {
@@ -70,6 +71,7 @@
sqlite3* db;
int status;
Tcl_HashTable open_entries;
+ Tcl_HashTable open_files;
} reg_registry;
int reg_open(reg_registry** regPtr, reg_error* errPtr);
Modified: trunk/base/src/cregistry/sql.c
===================================================================
--- trunk/base/src/cregistry/sql.c 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/cregistry/sql.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -34,8 +34,9 @@
#include "sql.h"
#include "vercomp.h"
+#include <sqlite3.h>
+#include <string.h>
#include <tcl.h>
-#include <sqlite3.h>
#include <time.h>
/**
@@ -108,7 +109,7 @@
/* 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 ('version', 1.100)",
"INSERT INTO registry.metadata (key, value) VALUES ('created', strftime('%s', 'now'))",
/* ports table */
@@ -130,11 +131,12 @@
/* file map */
"CREATE TABLE registry.files (id INTEGER, path TEXT, actual_path TEXT, "
- "active INT, mtime DATETIME, md5sum TEXT, editable INT, "
+ "active INT, mtime DATETIME, md5sum TEXT, editable INT, binary BOOL, "
"FOREIGN KEY(id) REFERENCES ports(id))",
"CREATE INDEX registry.file_port ON files (id)",
"CREATE INDEX registry.file_path ON files(path)",
"CREATE INDEX registry.file_actual ON files(actual_path)",
+ "CREATE INDEX registry.file_binary ON files(binary)",
/* dependency map */
"CREATE TABLE registry.dependencies (id INTEGER, name TEXT, variants TEXT, "
@@ -148,6 +150,57 @@
}
/**
+ * Updates the database if necessary. This function queries the current database version
+ * from the metadata table and executes SQL to update the schema to newer versions if needed.
+ * After that, this function updates the database version number
+ *
+ * @param [in] db database to update
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return true if success; false if failure
+ */
+int update_db(sqlite3* db, reg_error* errPtr) {
+ const char* version;
+ char* query = "SELECT value FROM registry.metadata WHERE key = 'version'";
+ sqlite3_stmt *stmt = NULL;
+
+ if ((sqlite3_prepare(db, query, -1, &stmt, NULL) != SQLITE_OK)
+ || (sqlite3_step(stmt) != SQLITE_ROW)) {
+ goto reg_err_out;
+ }
+ if (NULL == (version = (const char *)sqlite3_column_text(stmt, 0))) {
+ goto reg_err_out;
+ }
+ /* can't call rpm_vercomp directly, because it is static, but can call sql_version */
+ if (sql_version(NULL, strlen(version), version, strlen("1.1"), "1.1") < 0) {
+ /* conversion necessary, add binary field and index to files table */
+ static char* version_1_1_queries[] = {
+ "BEGIN",
+
+ "ALTER TABLE registry.files ADD COLUMN binary BOOL",
+ "CREATE INDEX registry.file_binary ON files(binary)",
+
+ "UPDATE registry.metadata SET value = '1.100' WHERE key = 'version'",
+
+ "COMMIT"
+ };
+
+ if (!do_queries(db, version_1_1_queries, errPtr)) {
+ goto err_out;
+ }
+
+ /* TODO: Walk the file tree and set the binary field */
+ }
+ sqlite3_finalize(stmt);
+ return 1;
+
+reg_err_out:
+ reg_sqlite_error(db, errPtr, query);
+err_out:
+ sqlite3_finalize(stmt);
+ return 0;
+}
+
+/**
* Initializes database connection. This function creates all the temporary
* tables used by the registry. It also registers the user functions and
* collations declared here, making them available.
Modified: trunk/base/src/cregistry/sql.h
===================================================================
--- trunk/base/src/cregistry/sql.h 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/cregistry/sql.h 2011-12-30 00:17:49 UTC (rev 88376)
@@ -38,5 +38,6 @@
int create_tables(sqlite3* db, reg_error* errPtr);
int init_db(sqlite3* db, reg_error* errPtr);
+int update_db(sqlite3* db, reg_error* errPtr);
#endif /* _SQL_H */
Copied: trunk/base/src/cregistry/util.c (from rev 88375, branches/gsoc11-rev-upgrade/base/src/cregistry/util.c)
===================================================================
--- trunk/base/src/cregistry/util.c (rev 0)
+++ trunk/base/src/cregistry/util.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -0,0 +1,182 @@
+/*
+ * util.c
+ * vim:tw=80:expandtab
+ * $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.
+ */
+
+#include "util.h"
+
+#include <stdlib.h>
+#include <string.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.
+ *
+ * @param [in,out] dst a reference to a null-terminated string
+ * @param [in,out] dst_len number of characters currently in `dst`
+ * @param [in,out] dst_space number of characters `dst` can hold
+ * @param [in] src string to concatenate to `dst`
+ */
+int reg_strcat(char** dst, size_t* dst_len, size_t* dst_space, char* src) {
+ size_t src_len = strlen(src);
+ size_t result_len = *dst_len + src_len;
+ if (result_len > *dst_space) {
+ char* new_dst;
+ *dst_space *= 2;
+ if (*dst_space < result_len) {
+ *dst_space = result_len;
+ }
+ new_dst = realloc(*dst, *dst_space * sizeof(char) + 1);
+ if (!new_dst)
+ return 0;
+ else
+ *dst = new_dst;
+ }
+ memcpy(*dst + *dst_len, src, src_len+1);
+ *dst_len = result_len;
+ return 1;
+}
+
+/**
+ * Appends element `src` to the list `dst`. It's like `reg_strcat`, except `src`
+ * represents a single element and not a sequence of `char`s.
+ *
+ * @param [in,out] dst a reference to a list of pointers
+ * @param [in,out] dst_len number of elements currently in `dst`
+ * @param [in,out] dst_space number of elements `dst` can hold
+ * @param [in] src elements to append to `dst`
+ */
+int reg_listcat(void*** dst, int* dst_len, int* dst_space, void* src) {
+ if (*dst_len == *dst_space) {
+ void** new_dst;
+ *dst_space *= 2;
+ new_dst = realloc(*dst, *dst_space * sizeof(void*));
+ if (!new_dst)
+ return 0;
+ else
+ *dst = new_dst;
+ }
+ (*dst)[*dst_len] = src;
+ (*dst_len)++;
+ return 1;
+}
+
+/**
+ * Returns an expression to use for the given strategy. This should be passed as
+ * the `fmt` argument of `sqlite3_mprintf`, with the key and value following.
+ *
+ * @param [in] strategy a strategy (one of the `reg_strategy_*` constants)
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return a sqlite3 expression if success; NULL if failure
+ */
+char* reg_strategy_op(reg_strategy strategy, reg_error* errPtr) {
+ switch (strategy) {
+ case reg_strategy_exact:
+ return "%q = '%q'";
+ case reg_strategy_glob:
+ return "%q GLOB '%q'";
+ case reg_strategy_regexp:
+ return "REGEXP(%q, '%q')";
+ case reg_strategy_null:
+ return "%q IS NULL";
+ default:
+ errPtr->code = REG_INVALID;
+ errPtr->description = "invalid matching strategy specified";
+ errPtr->free = NULL;
+ return NULL;
+ }
+}
+
+/**
+ * Convenience method for returning all objects of a given type from the
+ * registry.
+ *
+ * @param [in] reg registry to select objects 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 objects selected
+ * @param [in] fn a function to convert sqlite3_stmts to the desired type
+ * @param [in] del a function to delete the desired type of object
+ * @param [out] errPtr on error, a description of the error that occurred
+ * @return the number of objects if success; negative if failure
+ */
+int reg_all_objects(reg_registry* reg, char* query, int query_len,
+ void*** objects, cast_function* fn, void* castcalldata,
+ free_function* del, reg_error* errPtr) {
+ void** results = malloc(10*sizeof(void*));
+ int result_count = 0;
+ int result_space = 10;
+ sqlite3_stmt* stmt = NULL;
+ if (!results || !fn) {
+ return -1;
+ }
+ if (sqlite3_prepare(reg->db, query, query_len, &stmt, NULL) == SQLITE_OK) {
+ int r;
+ void* row;
+ do {
+ r = sqlite3_step(stmt);
+ switch (r) {
+ case SQLITE_ROW:
+ if (fn(reg, &row, stmt, castcalldata, errPtr)) {
+ if (!reg_listcat(&results, &result_count, &result_space, row)) {
+ r = SQLITE_ERROR;
+ }
+ } else {
+ r = SQLITE_ERROR;
+ }
+ break;
+ case SQLITE_DONE:
+ break;
+ case SQLITE_BUSY:
+ continue;
+ default:
+ reg_sqlite_error(reg->db, errPtr, query);
+ break;
+ }
+ } while (r == SQLITE_ROW || r == SQLITE_BUSY);
+ sqlite3_finalize(stmt);
+ if (r == SQLITE_DONE) {
+ *objects = results;
+ return result_count;
+ } else if (del) {
+ int i;
+ for (i=0; i<result_count; i++) {
+ del(NULL, results[i]);
+ }
+ }
+ } else {
+ if (stmt) {
+ sqlite3_finalize(stmt);
+ }
+ reg_sqlite_error(reg->db, errPtr, query);
+ }
+ free(results);
+ return -1;
+}
+
Copied: trunk/base/src/cregistry/util.h (from rev 88375, branches/gsoc11-rev-upgrade/base/src/cregistry/util.h)
===================================================================
--- trunk/base/src/cregistry/util.h (rev 0)
+++ trunk/base/src/cregistry/util.h 2011-12-30 00:17:49 UTC (rev 88376)
@@ -0,0 +1,53 @@
+/*
+ * util.h
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2011 Clemens Lang <cal 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 _CUTIL_H
+#define _CUTIL_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "registry.h"
+
+typedef enum {
+ reg_strategy_exact = 1,
+ reg_strategy_glob = 2,
+ reg_strategy_regexp = 3,
+ reg_strategy_null = 4
+} reg_strategy;
+
+int reg_strcat(char** dst, size_t* dst_len, size_t* dst_space, char* src);
+int reg_listcat(void*** dst, int* dst_len, int* dst_space, void* src);
+int reg_all_objects(reg_registry* reg, char* query, int query_len,
+ void*** objects, cast_function* fn, void* castcalldata,
+ free_function* del, reg_error* errPtr);
+char* reg_strategy_op(reg_strategy strategy, reg_error* errPtr);
+
+#endif /* _CUTIL_H */
+
Property changes on: trunk/base/src/machista1.0
___________________________________________________________________
Added: svn:ignore
+ machista.dylib
pkgIndex.tcl
Makefile
Modified: trunk/base/src/macports1.0/macports.tcl
===================================================================
--- trunk/base/src/macports1.0/macports.tcl 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/macports1.0/macports.tcl 2011-12-30 00:17:49 UTC (rev 88376)
@@ -37,6 +37,7 @@
package require macports_dlist 1.0
package require macports_index 1.0
package require macports_util 1.0
+package require machista 1.0
namespace eval macports {
namespace export bootstrap_options user_options portinterp_options open_mports ui_priorities port_phases
@@ -69,6 +70,8 @@
variable ui_priorities "error warn msg notice info debug any"
variable port_phases "any fetch checksum"
variable current_phase "main"
+
+ variable ui_prefix "---> "
}
# Provided UI instantiations
@@ -1702,7 +1705,7 @@
}
}
- ui_msg -nonewline "---> Computing dependencies for [_mportkey $mport subport]"
+ ui_msg -nonewline "$macports::ui_prefix Computing dependencies for [_mportkey $mport subport]"
if {[macports::ui_isset ports_debug]} {
# play nice with debug messages
ui_msg ""
@@ -1722,7 +1725,7 @@
# print the dep list
if {[llength $dlist] > 0} {
- set depstring "---> Dependencies to be installed:"
+ set depstring "$macports::ui_prefix Dependencies to be installed:"
foreach ditem $dlist {
append depstring " [ditem_key $ditem provides]"
}
@@ -2969,7 +2972,7 @@
ui_debug "MacPorts sources location: $mp_source_path"
# sync the MacPorts sources
- ui_msg "---> Updating MacPorts base sources using rsync"
+ ui_msg "$macports::ui_prefix Updating MacPorts base sources using rsync"
if { [catch { system "$rsync_path $rsync_options rsync://${rsync_server}/${rsync_dir} $mp_source_path" } result ] } {
return -code error "Error synchronizing MacPorts sources: $result"
}
@@ -3042,7 +3045,7 @@
# syncing ports tree.
if {![info exists options(ports_selfupdate_nosync)] || $options(ports_selfupdate_nosync) != "yes"} {
- ui_msg "---> Updating the ports tree"
+ ui_msg "$macports::ui_prefix Updating the ports tree"
if {$comp > 0} {
# updated portfiles potentially need new base to parse - tell sync to try to
# use prefabricated PortIndex files and signal if it couldn't
@@ -3055,9 +3058,9 @@
if {$use_the_force_luke == "yes" || $comp > 0} {
if {[info exists options(ports_dryrun)] && $options(ports_dryrun) == "yes"} {
- ui_msg "---> MacPorts base is outdated, selfupdate would install $macports_version_new (dry run)"
+ ui_msg "$macports::ui_prefix MacPorts base is outdated, selfupdate would install $macports_version_new (dry run)"
} else {
- ui_msg "---> MacPorts base is outdated, installing new version $macports_version_new"
+ ui_msg "$macports::ui_prefix MacPorts base is outdated, installing new version $macports_version_new"
# get installation user/group and permissions
set owner [file attributes ${prefix} -owner]
@@ -3107,9 +3110,9 @@
}
}
} elseif {$comp < 0} {
- ui_msg "---> MacPorts base is probably trunk or a release candidate"
+ ui_msg "$macports::ui_prefix MacPorts base is probably trunk or a release candidate"
} else {
- ui_msg "---> MacPorts base is already the latest version"
+ ui_msg "$macports::ui_prefix MacPorts base is already the latest version"
}
# set the MacPorts sources to the right owner
@@ -3158,6 +3161,7 @@
if {!$orig_nodeps} {
unset -nocomplain macports::global_options(ports_nodeps)
}
+
return $status
}
@@ -3176,6 +3180,16 @@
set is_dryrun yes
}
+ # Is this a rev-upgrade-called run?
+ set is_revupgrade no
+ if {[macports::global_option_isset ports_revupgrade]} {
+ set is_revupgrade yes
+ }
+ set is_revupgrade_second_run no
+ if {[macports::global_option_isset ports_revupgrade_second_run]} {
+ set is_revupgrade_second_run yes
+ }
+
# check if the port is in tree
if {[catch {mportlookup $portname} result]} {
global errorInfo
@@ -3369,7 +3383,7 @@
# at this point we need to check if a different port will be replacing this one
if {[info exists portinfo(replaced_by)] && ![info exists options(ports_upgrade_no-replace)]} {
- ui_msg "---> $portname is replaced by $portinfo(replaced_by)"
+ ui_msg "$macports::ui_prefix $portname is replaced by $portinfo(replaced_by)"
if {[catch {mportlookup $portinfo(replaced_by)} result]} {
global errorInfo
ui_debug "$errorInfo"
@@ -3431,6 +3445,11 @@
|| [_mportkey $workername "{os.major}"] != $os_major_installed)} {
ui_debug "platform mismatch ... upgrading!"
set build_override 1
+ } elseif {$is_revupgrade_second_run} {
+ set build_override 1
+ } elseif {$is_revupgrade} {
+ # in the first run of rev-upgrade, only activate possibly already existing files and check for missing dependencies
+ set will_install yes
} else {
if {[info exists portinfo(canonical_active_variants)] && $portinfo(canonical_active_variants) != $oldvariant} {
if {[llength $variationslist] > 0} {
@@ -3447,13 +3466,15 @@
set will_build no
# avoid building again unnecessarily
- if {$will_install && ([info exists options(ports_upgrade_force)] || $build_override == 1
- || ![registry::entry_exists $newname $version_in_tree $revision_in_tree $portinfo(canonical_active_variants)])} {
+ if {$will_install &&
+ ([info exists options(ports_upgrade_force)]
+ || $build_override == 1
+ || ![registry::entry_exists $newname $version_in_tree $revision_in_tree $portinfo(canonical_active_variants)])} {
set will_build yes
}
# first upgrade dependencies
- if {![info exists options(ports_nodeps)]} {
+ if {![info exists options(ports_nodeps)] && !$is_revupgrade} {
set status [_upgrade_dependencies portinfo depscache variationslist options $will_build]
if {$status != 0 && $status != 2 && ![ui_isset ports_processall]} {
catch {mportclose $workername}
@@ -3810,3 +3831,406 @@
return "/tmp"
}
}
+
+proc macports::revupgrade {opts} {
+ set run_loop 1
+ array set broken_port_counts {}
+ while {$run_loop == 1} {
+ set run_loop [revupgrade_scanandrebuild broken_port_counts $opts]
+ }
+ return 0;
+}
+
+# returns 1 if ports were rebuilt and revupgrade_scanandrebuild should be called again
+proc revupgrade_scanandrebuild {broken_port_counts_name opts} {
+ upvar $broken_port_counts_name broken_port_counts
+ array set options $opts
+
+ set files [registry::file search active 1 binary -null]
+ if {[llength $files] > 0} {
+ set files_count [llength $files]
+ registry::write {
+ try {
+ ui_msg -nonewline "$macports::ui_prefix Updating database of binaries"
+ set i 1
+ foreach f $files {
+ if {![macports::ui_isset ports_debug]} {
+ ui_msg -nonewline "\r$macports::ui_prefix Updating database of binaries: [expr $i * 100 / $files_count]%"
+ flush stdout
+ }
+ ui_debug "Updating binary flag for file $i of [llength $files]: [$f path]"
+ incr i
+ $f binary [fileIsBinary [$f path]]
+ }
+ } catch {*} {
+ ui_error "Updating database of binaries failed"
+ throw
+ }
+ }
+ ui_msg ""
+ }
+
+ set broken_files {};
+ set binaries [registry::file search active 1 binary 1]
+ ui_msg -nonewline "$macports::ui_prefix Scanning binaries for linking errors"
+ if {[llength $binaries] > 0} {
+ set handle [machista::create_handle]
+ if {$handle == "NULL"} {
+ error "Error creating libmachista handle"
+ }
+ array unset files_warned_about
+ array set files_warned_about [list]
+
+ set i 1
+ set binary_count [llength $binaries]
+ foreach b $binaries {
+ if {![macports::ui_isset ports_debug]} {
+ ui_msg -nonewline "\r$macports::ui_prefix Scanning binaries for linking errors: [expr $i * 100 / $binary_count]%"
+ flush stdout
+ }
+ #ui_debug "$i/[llength $binaries]: [$b path]"
+ incr i
+
+ set resultlist [machista::parse_file $handle [$b path]]
+ set returncode [lindex $resultlist 0]
+ set result [lindex $resultlist 1]
+
+ if {$returncode != $machista::SUCCESS} {
+ if {$returncode == $machista::EMAGIC} {
+ # not a Mach-O file
+ # ignore silently, these are only static libs anyway
+ #ui_debug "Error parsing file [$b path]: [machista::strerror $returncode]"
+ } else {
+ if {![macports::ui_isset ports_debug]} {
+ ui_msg ""
+ }
+ ui_warn "Error parsing file [$b path]: [machista::strerror $returncode]"
+ }
+ continue;
+ }
+
+ set architecture [$result cget -mt_archs]
+ while {$architecture != "NULL"} {
+ if {[info exists options(ports_rev-upgrade_id-loadcmd-check)] && $options(ports_rev-upgrade_id-loadcmd-check) == "yes"} {
+ if {[$architecture cget -mat_install_name] != "NULL" && [$architecture cget -mat_install_name] != ""} {
+ # check if this lib's install name actually refers to this file itself
+ # if this is not the case software linking against this library might have erroneous load commands
+ if {0 == [catch {set idloadcmdpath [revupgrade_handle_special_paths [$b path] [$architecture cget -mat_install_name]]}]} {
+ if {[string index $idloadcmdpath 0] != "/"} {
+ set port [registry::entry owner [$b path]]
+ if {$port != ""} {
+ set portname [$port name]
+ } else {
+ set portname "<unknown-port>"
+ }
+ if {![macports::ui_isset ports_debug]} {
+ ui_msg ""
+ }
+ ui_warn "ID load command in [$b path], arch [machista::get_arch_name [$architecture cget -mat_arch]] (belonging to port $portname) contains relative path"
+ } elseif {![file exists $idloadcmdpath]} {
+ set port [registry::entry owner [$b path]]
+ if {$port != ""} {
+ set portname [$port name]
+ } else {
+ set portname "<unknown-port>"
+ }
+ if {![macports::ui_isset ports_debug]} {
+ ui_msg ""
+ }
+ ui_warn "ID load command in [$b path], arch [machista::get_arch_name [$architecture cget -mat_arch]] refers to non-existant file $idloadcmdpath"
+ ui_warn "This is probably a bug in the $portname port and might cause problems in libraries linking against this file"
+ } else {
+
+ set hash_this [sha256 file [$b path]]
+ set hash_idloadcmd [sha256 file $idloadcmdpath]
+
+ if {$hash_this != $hash_idloadcmd} {
+ set port [registry::entry owner [$b path]]
+ if {$port != ""} {
+ set portname [$port name]
+ } else {
+ set portname "<unknown-port>"
+ }
+ if {![macports::ui_isset ports_debug]} {
+ ui_msg ""
+ }
+ ui_warn "ID load command in [$b path], arch [machista::get_arch_name [$architecture cget -mat_arch]] refers to file $idloadcmdpath, which is a different file"
+ ui_warn "This is probably a bug in the $portname port and might cause problems in libraries linking against this file"
+ }
+ }
+ }
+ }
+ }
+ set loadcommand [$architecture cget -mat_loadcmds]
+
+ while {$loadcommand != "NULL"} {
+ if {0 != [catch {set filepath [revupgrade_handle_special_paths [$b path] [$loadcommand cget -mlt_install_name]]}]} {
+ set loadcommand [$loadcommand cget -next]
+ continue;
+ }
+
+ set libresultlist [machista::parse_file $handle $filepath]
+ set libreturncode [lindex $libresultlist 0]
+ set libresult [lindex $libresultlist 1]
+
+ if {$libreturncode != $machista::SUCCESS} {
+ if {![info exists files_warned_about($filepath)]} {
+ if {![macports::ui_isset ports_debug]} {
+ ui_msg ""
+ }
+ ui_warn "Could not open $filepath: [machista::strerror $libreturncode]"
+ set files_warned_about($filepath) yes
+ }
+ if {$libreturncode == $machista::EFILE} {
+ ui_debug "Marking [$b path] as broken"
+ lappend broken_files [$b path]
+ }
+ set loadcommand [$loadcommand cget -next]
+ continue;
+ }
+
+ set libarchitecture [$libresult cget -mt_archs]
+ set libarch_found false;
+ while {$libarchitecture != "NULL"} {
+ if {[$architecture cget -mat_arch] != [$libarchitecture cget -mat_arch]} {
+ set libarchitecture [$libarchitecture cget -next]
+ continue;
+ }
+
+ if {[$loadcommand cget -mlt_version] != [$libarchitecture cget -mat_version] && [$loadcommand cget -mlt_comp_version] > [$libarchitecture cget -mat_comp_version]} {
+ if {![macports::ui_isset ports_debug]} {
+ ui_msg ""
+ }
+ ui_warn "Incompatible library version of file [$loadcommand cget -mlt_install_name]: Expected [$loadcommand cget -mlt_comp_version], but got [$libarchitecture cget -mat_comp_version]"
+ ui_debug "Marking [$b path] as broken"
+ lappend broken_files [$b path]
+ }
+
+ set libarch_found true;
+ break;
+ }
+
+ if {$libarch_found == false} {
+ ui_debug "Missing architecture [machista::get_arch_name [$architecture cget -mat_arch]] in file $filepath"
+ if {[path_is_in_prefix $filepath]} {
+ ui_debug "Marking [$b path] as broken"
+ lappend broken_files [$b path]
+ } else {
+ ui_debug "Missing architecture [machista::get_arch_name [$architecture cget -mat_arch]] in file outside prefix referenced from [$b path]"
+ # ui_debug " How did you get that compiled anyway?"
+ }
+ }
+ set loadcommand [$loadcommand cget -next]
+ }
+
+ set architecture [$architecture cget -next]
+ }
+ }
+ ui_msg ""
+
+ machista::destroy_handle $handle
+
+ if {[llength $broken_files] == 0} {
+ ui_msg "$macports::ui_prefix No broken files found. :)"
+ return 0;
+ }
+ ui_msg "$macports::ui_prefix Found [llength $broken_files] broken file(s), matching files to ports"
+ set broken_ports {}
+ set broken_files [lsort -unique $broken_files]
+ foreach file $broken_files {
+ set port [registry::entry owner $file]
+ if {$port == ""} {
+ ui_error "Broken file $file doesn't belong to any port."
+ }
+ lappend broken_ports $port
+ }
+ set broken_ports [lsort -unique $broken_ports]
+
+ foreach port $broken_ports {
+ if {![info exists broken_port_counts([$port name])]} {
+ set broken_port_counts([$port name]) 0
+ }
+ incr broken_port_counts([$port name])
+ if {$broken_port_counts([$port name]) > 3} {
+ ui_error "Port [$port name] is still broken after rebuiling it more than 3 times. You might want to file a bug for this."
+ error "Port [$port name] still broken after rebuilding [expr $broken_port_counts([$port name]) - 1] time(s)"
+ }
+ }
+
+ ui_msg "$macports::ui_prefix Found [llength $broken_ports] broken port(s), determining rebuild order"
+ # broken_ports are the nodes in our graph
+ # now we need adjacents
+ foreach port $broken_ports {
+ # initialize with empty list
+ set adjlist($port) {}
+ set revadjlist($port) {}
+ }
+
+ array set visited {}
+ foreach port $broken_ports {
+ # stack of broken nodes we've come across
+ set stack {}
+ lappend stack $port
+
+ # build graph
+ if {![info exists visited($port)]} {
+ revupgrade_buildgraph $port stack adjlist revadjlist visited
+ }
+ }
+
+ set unsorted_ports $broken_ports
+ set topsort_ports {}
+ while {[llength $unsorted_ports] > 0} {
+ foreach port $unsorted_ports {
+ if {[llength $adjlist($port)] == 0} {
+ # this node has no further dependencies
+ # add it to topsorted list
+ lappend topsort_ports $port
+ # remove from unsorted list
+ set index [lsearch -exact $unsorted_ports $port]
+ set unsorted_ports [lreplace $unsorted_ports $index $index]
+
+ # remove edges
+ foreach target $revadjlist($port) {
+ set index [lsearch -exact $adjlist($target) $port]
+ set adjlist($target) [lreplace $adjlist($target) $index $index]
+ }
+ }
+ }
+ }
+
+ ui_msg "$macports::ui_prefix Rebuilding in order"
+ foreach port $topsort_ports {
+ ui_msg " [$port name] @[$port version] [$port variants][$port negated_variants]"
+ }
+
+ # shared depscache for all ports that are going to be rebuilt
+ array set depscache {}
+ set status 0
+ foreach port $topsort_ports {
+ if {![info exists depscache(port:[$port name])]} {
+
+ # convert variations into the format macports::upgrade needs
+ set minusvariant [lrange [split [$port negated_variants] "-"] 1 end]
+ set plusvariant [lrange [split [$port variants] "+"] 1 end]
+ set variants [list]
+ foreach v $minusvariant {
+ lappend variants $v "-"
+ }
+ foreach v $plusvariant {
+ lappend variants $v "+"
+ }
+ array unset variations
+ array set variations $variants
+
+ # set rev-upgrade options and nodeps if this is not the first run
+ set macports::global_options(ports_revupgrade) "yes"
+ unset -nocomplain macports::global_options(ports_nodeps)
+ unset -nocomplain macports::global_options(ports_revupgrade_second_run)
+ unset -nocomplain macports::global_options(ports_source_only)
+ if {$broken_port_counts([$port name]) > 1} {
+ set macports::global_options(ports_revupgrade_second_run) yes
+ set macports::global_options(ports_nodeps) yes
+ # build from source only until the buildbot has some method of rev-upgrade, too
+ set macports::global_options(ports_source_only) yes
+ }
+
+ # call macports::upgrade with ports_revupgrade option to rebuild the port
+ set status [macports::upgrade [$port name] "port:[$port name]" \
+ [array get variations] [array get macports::global_options] depscache]
+ if {$status != 0} {
+ error "Error rebuilding [$port name]"
+ }
+ }
+ }
+
+ if {[info exists options(ports_dryrun)] && $options(ports_dryrun) == "yes"} {
+ ui_warn "If this was no dry run, rev-upgrade would now run the checks again to find unresolved and newly created problems"
+ return 0
+ }
+ return 1
+ }
+
+ return 0
+}
+
+# Return whether a path is in the macports prefix
+# Usage: path_is_in_prefix path_to_test
+# Returns true if the path is in the prefix, false otherwise
+proc path_is_in_prefix {path} {
+ if {[string first $macports::prefix $path] == 0} {
+ return yes
+ }
+ if {[string first $macports::applications_dir $path] == 0} {
+ return yes
+ }
+ return no
+}
+
+# Function to replace macros in loadcommand paths with their proper values (which are usually determined at load time)
+# Usage: revupgrade_handle_special_paths name_of_file path_from_loadcommand
+# Returns the corrected path on success or an error in case of failure.
+# Note that we can't reliably replace @executable_path, because it's only clear when executing a file where it was executed from.
+# Replacing @rpath does not work yet, but it might be possible to get it working using the rpath attribute in the file containing the
+# loadcommand
+proc revupgrade_handle_special_paths {fname path} {
+ set corrected_path $path
+
+ set loaderpath_idx [string first "@loader_path" $corrected_path]
+ if {$loaderpath_idx != -1} {
+ set corrected_path [string replace $corrected_path $loaderpath_idx $loaderpath_idx+11 [file dirname $fname]]
+ }
+
+ set executablepath_idx [string first "@executable_path" $corrected_path]
+ if {$executablepath_idx != -1} {
+ ui_debug "Ignoring loadcommand containing @exectuable_path in $fname"
+ error "@exectuable_path in loadcommand"
+ }
+
+ set rpath_idx [string first "@rpath" $corrected_path]
+ if {$rpath_idx != -1} {
+ ui_debug "Ignoring loadcommand containing @rpath in $fname"
+ error "@rpath in loadcommand"
+ }
+
+ return $corrected_path
+}
+
+# Recursively build the dependency graph between broken ports
+# Usage: revupgrade_buildgraph start_port name_of_stack name_of_adjacency_list name_of_reverse_adjacency_list name_of_visited_map
+proc revupgrade_buildgraph {port stackname adjlistname revadjlistname visitedname} {
+ upvar $stackname stack
+ upvar $adjlistname adjlist
+ upvar $revadjlistname revadjlist
+ upvar $visitedname visited
+
+ ui_debug "Processing port [$port name] @[$port epoch]:[$port version]_[$port revision] [$port variants] [$port negated_variants]"
+ set dependent_ports [$port dependents]
+ foreach dep $dependent_ports {
+ if {[info exists visited($dep)]} {
+ continue
+ }
+ set visited($dep) true
+ set is_broken_port false
+
+ if {[info exists adjlist($dep)]} {
+ #ui_debug "Dependency [$dep name] is broken, adding edge from [[lindex $stack 0] name] to [$dep name]"
+ #ui_debug "Making [$dep name] new head of stack"
+ # $dep is one of the broken ports
+ # add an edge to the last broken port in the DFS
+ lappend revadjlist([lindex $stack 0]) $dep
+ lappend adjlist($dep) [lindex $stack 0]
+ # make this port the new last broken port by prepending it to the stack
+ set stack [linsert $stack 0 $dep]
+
+ set is_broken_port true
+ }
+ revupgrade_buildgraph $dep stack adjlist revadjlist visited
+ if {$is_broken_port} {
+ #ui_debug "Removing [$dep name] from stack"
+ # remove $dep from the stack
+ set stack [lrange $stack 1 end]
+ }
+ }
+}
+
Modified: trunk/base/src/pextlib1.0/Pextlib.c
===================================================================
--- trunk/base/src/pextlib1.0/Pextlib.c 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/pextlib1.0/Pextlib.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -46,6 +46,7 @@
#include <grp.h>
#include <limits.h>
#include <pwd.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -53,6 +54,11 @@
#include <strings.h>
#include <unistd.h>
+#ifdef __MACH__
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+#endif
+
#include <tcl.h>
#include "Pextlib.h"
@@ -93,147 +99,147 @@
static char *
ui_escape(const char *source)
{
- char *d, *dest;
- const char *s;
- size_t dlen;
+ char *d, *dest;
+ const char *s;
+ size_t dlen;
- s = source;
- dlen = strlen(source) * 2 + 1;
- d = dest = malloc(dlen);
- if (dest == NULL) {
- return NULL;
- }
- while(*s != '\0') {
- switch(*s) {
- case '\\':
- case '}':
- case '{':
- *d = '\\';
- d++;
- *d = *s;
- d++;
- s++;
- break;
- case '\n':
- s++;
- break;
- default:
- *d = *s;
- d++;
- s++;
- break;
- }
- }
- *d = '\0';
- return dest;
+ s = source;
+ dlen = strlen(source) * 2 + 1;
+ d = dest = malloc(dlen);
+ if (dest == NULL) {
+ return NULL;
+ }
+ while(*s != '\0') {
+ switch(*s) {
+ case '\\':
+ case '}':
+ case '{':
+ *d = '\\';
+ d++;
+ *d = *s;
+ d++;
+ s++;
+ break;
+ case '\n':
+ s++;
+ break;
+ default:
+ *d = *s;
+ d++;
+ s++;
+ break;
+ }
+ }
+ *d = '\0';
+ return dest;
}
int
ui_info(Tcl_Interp *interp, char *mesg)
{
- const char ui_proc_start[] = "ui_info [subst -nocommands -novariables {";
- const char ui_proc_end[] = "}]";
- char *script, *string;
- size_t scriptlen, len, remaining;
- int rval;
+ const char ui_proc_start[] = "ui_info [subst -nocommands -novariables {";
+ const char ui_proc_end[] = "}]";
+ char *script, *string;
+ size_t scriptlen, len, remaining;
+ int rval;
- string = ui_escape(mesg);
- if (string == NULL)
- return TCL_ERROR;
+ string = ui_escape(mesg);
+ if (string == NULL)
+ return TCL_ERROR;
- len = strlen(string);
- scriptlen = sizeof(ui_proc_start) + len + sizeof(ui_proc_end) - 1;
- script = malloc(scriptlen);
- if (script == NULL)
- return TCL_ERROR;
+ len = strlen(string);
+ scriptlen = sizeof(ui_proc_start) + len + sizeof(ui_proc_end) - 1;
+ script = malloc(scriptlen);
+ if (script == NULL)
+ return TCL_ERROR;
- memcpy(script, ui_proc_start, sizeof(ui_proc_start));
- remaining = scriptlen - sizeof(ui_proc_start);
- strncat(script, string, remaining);
- remaining -= len;
- strncat(script, ui_proc_end, remaining);
- free(string);
- rval = Tcl_EvalEx(interp, script, -1, 0);
- free(script);
- return rval;
+ memcpy(script, ui_proc_start, sizeof(ui_proc_start));
+ remaining = scriptlen - sizeof(ui_proc_start);
+ strncat(script, string, remaining);
+ remaining -= len;
+ strncat(script, ui_proc_end, remaining);
+ free(string);
+ rval = Tcl_EvalEx(interp, script, -1, 0);
+ free(script);
+ return rval;
}
int StrsedCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
- char *pattern, *string, *res;
- int range[2];
- Tcl_Obj *tcl_result;
+ char *pattern, *string, *res;
+ int range[2];
+ Tcl_Obj *tcl_result;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 1, objv, "string pattern");
- return TCL_ERROR;
- }
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string pattern");
+ return TCL_ERROR;
+ }
- string = Tcl_GetString(objv[1]);
- pattern = Tcl_GetString(objv[2]);
- res = strsed(string, pattern, range);
- if (!res) {
- Tcl_SetResult(interp, "strsed failed", TCL_STATIC);
- return TCL_ERROR;
- }
- tcl_result = Tcl_NewStringObj(res, -1);
- Tcl_SetObjResult(interp, tcl_result);
- free(res);
- return TCL_OK;
+ string = Tcl_GetString(objv[1]);
+ pattern = Tcl_GetString(objv[2]);
+ res = strsed(string, pattern, range);
+ if (!res) {
+ Tcl_SetResult(interp, "strsed failed", TCL_STATIC);
+ return TCL_ERROR;
+ }
+ tcl_result = Tcl_NewStringObj(res, -1);
+ Tcl_SetObjResult(interp, tcl_result);
+ free(res);
+ return TCL_OK;
}
int ExistsuserCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
- Tcl_Obj *tcl_result;
- struct passwd *pwent;
- char *user;
+ Tcl_Obj *tcl_result;
+ struct passwd *pwent;
+ char *user;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "user");
- return TCL_ERROR;
- }
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "user");
+ return TCL_ERROR;
+ }
- user = strdup(Tcl_GetString(objv[1]));
- if (isdigit(*(user)))
- pwent = getpwuid(strtol(user, 0, 0));
- else
- pwent = getpwnam(user);
- free(user);
+ user = strdup(Tcl_GetString(objv[1]));
+ if (isdigit(*(user)))
+ pwent = getpwuid(strtol(user, 0, 0));
+ else
+ pwent = getpwnam(user);
+ free(user);
- if (pwent == NULL)
- tcl_result = Tcl_NewIntObj(0);
- else
- tcl_result = Tcl_NewIntObj(pwent->pw_uid);
+ if (pwent == NULL)
+ tcl_result = Tcl_NewIntObj(0);
+ else
+ tcl_result = Tcl_NewIntObj(pwent->pw_uid);
- Tcl_SetObjResult(interp, tcl_result);
- return TCL_OK;
+ Tcl_SetObjResult(interp, tcl_result);
+ return TCL_OK;
}
int ExistsgroupCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
- Tcl_Obj *tcl_result;
- struct group *grent;
- char *group;
+ Tcl_Obj *tcl_result;
+ struct group *grent;
+ char *group;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "groupname");
- return TCL_ERROR;
- }
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "groupname");
+ return TCL_ERROR;
+ }
- group = strdup(Tcl_GetString(objv[1]));
- if (isdigit(*(group)))
- grent = getgrgid(strtol(group, 0, 0));
- else
- grent = getgrnam(group);
- free(group);
+ group = strdup(Tcl_GetString(objv[1]));
+ if (isdigit(*(group)))
+ grent = getgrgid(strtol(group, 0, 0));
+ else
+ grent = getgrnam(group);
+ free(group);
- if (grent == NULL)
- tcl_result = Tcl_NewIntObj(0);
- else
- tcl_result = Tcl_NewIntObj(grent->gr_gid);
+ if (grent == NULL)
+ tcl_result = Tcl_NewIntObj(0);
+ else
+ tcl_result = Tcl_NewIntObj(grent->gr_gid);
- Tcl_SetObjResult(interp, tcl_result);
- return TCL_OK;
+ Tcl_SetObjResult(interp, tcl_result);
+ return TCL_OK;
}
/* Find the first unused UID > 500
@@ -241,81 +247,81 @@
but UIDs < 500 are reserved by Apple */
int NextuidCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc UNUSED, Tcl_Obj *CONST objv[] UNUSED)
{
- Tcl_Obj *tcl_result;
- int cur;
+ Tcl_Obj *tcl_result;
+ int cur;
- cur = MIN_USABLE_UID;
+ cur = MIN_USABLE_UID;
- while (getpwuid(cur) != NULL) {
- cur++;
- }
+ while (getpwuid(cur) != NULL) {
+ cur++;
+ }
- tcl_result = Tcl_NewIntObj(cur);
- Tcl_SetObjResult(interp, tcl_result);
- return TCL_OK;
+ tcl_result = Tcl_NewIntObj(cur);
+ Tcl_SetObjResult(interp, tcl_result);
+ return TCL_OK;
}
/* Just as with NextuidCmd, return the first unused gid > 500 */
int NextgidCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc UNUSED, Tcl_Obj *CONST objv[] UNUSED)
{
- Tcl_Obj *tcl_result;
- int cur;
+ Tcl_Obj *tcl_result;
+ int cur;
- cur = MIN_USABLE_GID;
+ cur = MIN_USABLE_GID;
- while (getgrgid(cur) != NULL) {
- cur++;
- }
+ while (getgrgid(cur) != NULL) {
+ cur++;
+ }
- tcl_result = Tcl_NewIntObj(cur);
- Tcl_SetObjResult(interp, tcl_result);
- return TCL_OK;
+ tcl_result = Tcl_NewIntObj(cur);
+ Tcl_SetObjResult(interp, tcl_result);
+ return TCL_OK;
}
int UmaskCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc UNUSED, Tcl_Obj *CONST objv[] UNUSED)
{
- Tcl_Obj *tcl_result;
- char *tcl_mask, *p;
- const size_t stringlen = 5; /* 4 digits & \0 */
- int i;
- mode_t *set;
- mode_t newmode;
- mode_t oldmode;
+ Tcl_Obj *tcl_result;
+ char *tcl_mask, *p;
+ const size_t stringlen = 5; /* 4 digits & \0 */
+ int i;
+ mode_t *set;
+ mode_t newmode;
+ mode_t oldmode;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "mode");
- return TCL_ERROR;
- }
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "mode");
+ return TCL_ERROR;
+ }
- tcl_mask = Tcl_GetString(objv[1]);
- if ((set = setmode(tcl_mask)) == NULL) {
- Tcl_SetResult(interp, "Invalid umask mode", TCL_STATIC);
- return TCL_ERROR;
- }
+ tcl_mask = Tcl_GetString(objv[1]);
+ if ((set = setmode(tcl_mask)) == NULL) {
+ Tcl_SetResult(interp, "Invalid umask mode", TCL_STATIC);
+ return TCL_ERROR;
+ }
- newmode = getmode(set, 0);
- free(set);
+ newmode = getmode(set, 0);
+ free(set);
- oldmode = umask(newmode);
+ oldmode = umask(newmode);
- tcl_mask = calloc(1, stringlen); /* 4 digits & \0 */
- if (!tcl_mask) {
- return TCL_ERROR;
- }
+ tcl_mask = calloc(1, stringlen); /* 4 digits & \0 */
+ if (!tcl_mask) {
+ return TCL_ERROR;
+ }
- /* Totally gross and cool */
- p = tcl_mask + stringlen - 1;
- for (i = stringlen - 1; i > 0; i--) {
- p--;
- *p = (oldmode & 7) + '0';
- oldmode >>= 3;
- }
+ /* Totally gross and cool */
+ p = tcl_mask + stringlen - 1;
+ for (i = stringlen - 1; i > 0; i--) {
+ p--;
+ *p = (oldmode & 7) + '0';
+ oldmode >>= 3;
+ }
- tcl_result = Tcl_NewStringObj(p, -1);
- free(tcl_mask);
+ tcl_result = Tcl_NewStringObj(p, -1);
+ free(tcl_mask);
- Tcl_SetObjResult(interp, tcl_result);
- return TCL_OK;
+ Tcl_SetObjResult(interp, tcl_result);
+ return TCL_OK;
}
/**
@@ -464,10 +470,107 @@
return TCL_OK;
}
+#ifdef __MACH__
+/**
+ * Tcl function to determine whether a file given by path is binary (in terms of being Mach-O)
+ * Defined on Mac-Systems only, because the necessary headers are only available there.
+ *
+ * Synopsis: fileIsBinary filename
+ */
+static int fileIsBinaryCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+ const char *path;
+ FILE *file;
+ uint32_t magic;
+ struct stat st;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "filename");
+ return TCL_ERROR;
+ }
+
+ path = Tcl_GetString(objv[1]);
+ if (-1 == lstat(path, &st)) {
+ /* an error occured */
+ Tcl_SetErrno(errno);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "lstat(", path, "):", (char *)Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+ if (!S_ISREG(st.st_mode)) {
+ /* not a regular file, haven't seen directories which are binaries yet */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+ return TCL_OK;
+ }
+ if (NULL == (file = fopen(path, "r"))) {
+ Tcl_SetErrno(errno);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "fopen(", path, "): ", (char *)Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+ if (1 != fread(&magic, sizeof(uint32_t), 1, file)) {
+ if (feof(file)) {
+ fclose(file);
+ /* file is shorter than 4 byte, probably not a binary */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+ return TCL_OK;
+ }
+ /* error while reading */
+ Tcl_SetErrno(errno);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "fread(&magic, 4, 1, ", path, "): ", (char *)Tcl_PosixError(interp), NULL);
+ fclose(file);
+ return TCL_ERROR;
+ }
+ if (magic == MH_MAGIC || magic == MH_MAGIC_64) {
+ fclose(file);
+ /* this is a mach-o file */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(true));
+ return TCL_OK;
+ }
+ if (magic == htonl(FAT_MAGIC)) {
+ uint32_t archcount;
+ /* either universal binary or java class (FAT_MAGIC == 0xcafebabe)
+ see /use/share/file/magic/cafebabe for an explanation of what I'm doing here */
+ if (1 != fread(&archcount, sizeof(uint32_t), 1, file)) {
+ if (feof(file)) {
+ fclose(file);
+ /* file shorter than 8 byte, probably not a binary either */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+ return TCL_OK;
+ }
+ /* error while reading */
+ Tcl_SetErrno(errno);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "fread(&archcount, 4, 1, ", path, "): ", (char *)Tcl_PosixError(interp), NULL);
+ fclose(file);
+ return TCL_ERROR;
+ }
+
+ /* universal binary header is always big endian */
+ archcount = ntohl(archcount);
+ if (archcount > 0 && archcount < 20) {
+ fclose(file);
+ /* universal binary */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(true));
+ return TCL_OK;
+ }
+
+ fclose(file);
+ /* probably java class */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+ return TCL_OK;
+ }
+ fclose(file);
+
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+ return TCL_OK;
+}
+#endif
+
int Pextlib_Init(Tcl_Interp *interp)
{
- if (Tcl_InitStubs(interp, "8.4", 0) == NULL)
- return TCL_ERROR;
+ if (Tcl_InitStubs(interp, "8.4", 0) == NULL)
+ return TCL_ERROR;
Tcl_CreateObjCommand(interp, "system", SystemCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "flock", FlockCmd, NULL, NULL);
@@ -501,30 +604,33 @@
Tcl_CreateObjCommand(interp, "unsetenv", UnsetEnvCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "lchown", lchownCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "realpath", RealpathCmd, NULL, NULL);
+#ifdef __MACH__
+ Tcl_CreateObjCommand(interp, "fileIsBinary", fileIsBinaryCmd, NULL, NULL);
+#endif
- Tcl_CreateObjCommand(interp, "readline", ReadlineCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "rl_history", RLHistoryCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "readline", ReadlineCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "rl_history", RLHistoryCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "getuid", getuidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "geteuid", geteuidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "getgid", getgidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "getegid", getegidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "setuid", setuidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "seteuid", seteuidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "setgid", setgidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "setegid", setegidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "name_to_uid", name_to_uidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "uid_to_name", uid_to_nameCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "uname_to_gid", uname_to_gidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "name_to_gid", name_to_gidCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "gid_to_name", gid_to_nameCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "getuid", getuidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "geteuid", geteuidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "getgid", getgidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "getegid", getegidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "setuid", setuidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "seteuid", seteuidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "setgid", setgidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "setegid", setegidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "name_to_uid", name_to_uidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "uid_to_name", uid_to_nameCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "uname_to_gid", uname_to_gidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "name_to_gid", name_to_gidCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "gid_to_name", gid_to_nameCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "tracelib", TracelibCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "isatty", IsattyCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "term_get_size", TermGetSizeCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "tracelib", TracelibCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "isatty", IsattyCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "term_get_size", TermGetSizeCmd, NULL, NULL);
- if (Tcl_PkgProvide(interp, "Pextlib", "1.0") != TCL_OK)
- return TCL_ERROR;
+ if (Tcl_PkgProvide(interp, "Pextlib", "1.0") != TCL_OK)
+ return TCL_ERROR;
- return TCL_OK;
+ return TCL_OK;
}
Property changes on: trunk/base/src/pextlib1.0/sha2.c
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/gsoc08-privileges/base/src/pextlib1.0/sha2.c:37343-46937
/branches/universal-sanity/base/src/pextlib1.0/sha2.c:51872-52323
/branches/variant-descs-14482/base/src/pextlib1.0/sha2.c:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/pextlib1.0/sha2.c:45682-46060
/users/perry/base-select/src/pextlib1.0/sha2.c:44044-44692
+ /branches/gsoc08-privileges/base/src/pextlib1.0/sha2.c:37343-46937
/branches/gsoc11-rev-upgrade/base/src/pextlib1.0/sha2.c:78828-88375
/branches/universal-sanity/base/src/pextlib1.0/sha2.c:51872-52323
/branches/variant-descs-14482/base/src/pextlib1.0/sha2.c:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/pextlib1.0/sha2.c:45682-46060
/users/perry/base-select/src/pextlib1.0/sha2.c:44044-44692
Property changes on: trunk/base/src/pextlib1.0/sha2.h
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/gsoc08-privileges/base/src/pextlib1.0/sha2.h:37343-46937
/branches/universal-sanity/base/src/pextlib1.0/sha2.h:51872-52323
/branches/variant-descs-14482/base/src/pextlib1.0/sha2.h:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/pextlib1.0/sha2.h:45682-46060
/users/perry/base-select/src/pextlib1.0/sha2.h:44044-44692
+ /branches/gsoc08-privileges/base/src/pextlib1.0/sha2.h:37343-46937
/branches/gsoc11-rev-upgrade/base/src/pextlib1.0/sha2.h:78828-88375
/branches/universal-sanity/base/src/pextlib1.0/sha2.h:51872-52323
/branches/variant-descs-14482/base/src/pextlib1.0/sha2.h:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/pextlib1.0/sha2.h:45682-46060
/users/perry/base-select/src/pextlib1.0/sha2.h:44044-44692
Property changes on: trunk/base/src/pextlib1.0/sha256cmd.c
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/gsoc08-privileges/base/src/pextlib1.0/rmd160cmd.c:37343-46937
/branches/gsoc09-logging/base/src/pextlib1.0/sha256cmd.c:51231-60371
/branches/universal-sanity/base/src/pextlib1.0/rmd160cmd.c:51872-52323
/branches/variant-descs-14482/base/src/pextlib1.0/rmd160cmd.c:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/pextlib1.0/rmd160cmd.c:45682-46060
/users/perry/base-select/src/pextlib1.0/rmd160cmd.c:44044-44692
+ /branches/gsoc08-privileges/base/src/pextlib1.0/rmd160cmd.c:37343-46937
/branches/gsoc09-logging/base/src/pextlib1.0/sha256cmd.c:51231-60371
/branches/gsoc11-rev-upgrade/base/src/pextlib1.0/sha256cmd.c:78828-88375
/branches/universal-sanity/base/src/pextlib1.0/rmd160cmd.c:51872-52323
/branches/variant-descs-14482/base/src/pextlib1.0/rmd160cmd.c:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/pextlib1.0/rmd160cmd.c:45682-46060
/users/perry/base-select/src/pextlib1.0/rmd160cmd.c:44044-44692
Property changes on: trunk/base/src/pextlib1.0/sha256cmd.h
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/gsoc08-privileges/base/src/pextlib1.0/rmd160cmd.h:37343-46937
/branches/gsoc09-logging/base/src/pextlib1.0/sha256cmd.h:51231-60371
/branches/universal-sanity/base/src/pextlib1.0/rmd160cmd.h:51872-52323
/branches/variant-descs-14482/base/src/pextlib1.0/rmd160cmd.h:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/pextlib1.0/rmd160cmd.h:45682-46060
/users/perry/base-select/src/pextlib1.0/rmd160cmd.h:44044-44692
+ /branches/gsoc08-privileges/base/src/pextlib1.0/rmd160cmd.h:37343-46937
/branches/gsoc09-logging/base/src/pextlib1.0/sha256cmd.h:51231-60371
/branches/gsoc11-rev-upgrade/base/src/pextlib1.0/sha256cmd.h:78828-88375
/branches/universal-sanity/base/src/pextlib1.0/rmd160cmd.h:51872-52323
/branches/variant-descs-14482/base/src/pextlib1.0/rmd160cmd.h:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/pextlib1.0/rmd160cmd.h:45682-46060
/users/perry/base-select/src/pextlib1.0/rmd160cmd.h:44044-44692
Modified: trunk/base/src/port/port.tcl
===================================================================
--- trunk/base/src/port/port.tcl 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/port/port.tcl 2011-12-30 00:17:49 UTC (rev 88376)
@@ -2572,6 +2572,7 @@
if {[require_portlist portlist] || ([prefix_unwritable] && ![macports::global_option_isset ports_dryrun])} {
return 1
}
+
# shared depscache for all ports in the list
array set depscache {}
set status 0
@@ -2587,12 +2588,25 @@
if {$status != 0} {
print_tickets_url
+ } else {
+ array set options $opts
+ if {![info exists options(ports_upgrade_no-rev-upgrade)]} {
+ set status [action_revupgrade $action $portlist $opts]
+ }
}
return $status
}
+proc action_revupgrade { action portlist opts } {
+ set status [macports::revupgrade $opts]
+ if {$status != 0} {
+ print_tickets_url
+ }
+ return $status
+}
+
proc action_version { action portlist opts } {
puts "Version: [macports::version]"
return 0
@@ -3984,6 +3998,7 @@
unsetrequested [list action_setrequested [ACTION_ARGS_PORTS]] \
\
upgrade [list action_upgrade [ACTION_ARGS_PORTS]] \
+ rev-upgrade [list action_revupgrade [ACTION_ARGS_NONE]] \
\
version [list action_version [ACTION_ARGS_NONE]] \
platform [list action_platform [ACTION_ARGS_NONE]] \
@@ -4146,13 +4161,14 @@
lint {nitpick}
select {list set show}
log {{phase 1} {level 1}}
- upgrade {force enforce-variants no-replace}
+ upgrade {force enforce-variants no-replace no-rev-upgrade}
+ rev-upgrade {id-loadcmd-check}
}
##
# Checks whether the given option is valid
#
-# œparam action for which action
+# @param action for which action
# @param option the prefix of the option to check
# @return list of pairs {name argc} for all matching options
proc cmd_option_matches {action option} {
Modified: trunk/base/src/port1.0/port_autoconf.tcl.in
===================================================================
--- trunk/base/src/port1.0/port_autoconf.tcl.in 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/port1.0/port_autoconf.tcl.in 2011-12-30 00:17:49 UTC (rev 88376)
@@ -68,6 +68,7 @@
variable tar_path "@TAR@"
variable tar_q "@TAR_Q@"
variable hdiutil_path "@HDIUTIL@"
+ variable swig_path "@SIWG@"
variable have_launchd "@HAVE_LAUNCHD@"
variable launchctl_path "@LAUNCHCTL@"
variable install_command "@INSTALL@"
Modified: trunk/base/src/registry2.0/Makefile
===================================================================
--- trunk/base/src/registry2.0/Makefile 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/registry2.0/Makefile 2011-12-30 00:17:49 UTC (rev 88376)
@@ -3,6 +3,7 @@
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 \
../cregistry/cregistry.a
#graph.o graphobj.o
Modified: trunk/base/src/registry2.0/entry.c
===================================================================
--- trunk/base/src/registry2.0/entry.c 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/registry2.0/entry.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -35,6 +35,8 @@
#include <tcl.h>
#include <sqlite3.h>
+#include <cregistry/util.h>
+
#include "entry.h"
#include "entryobj.h"
#include "registry.h"
@@ -112,7 +114,7 @@
variants, epoch, &error);
if (entry != NULL) {
Tcl_Obj* result;
- if (entry_to_obj(interp, &result, entry, &error)) {
+ if (entry_to_obj(interp, &result, entry, NULL, &error)) {
Tcl_SetObjResult(interp, result);
return TCL_OK;
}
@@ -192,7 +194,7 @@
variants, epoch, &error);
if (entry != NULL) {
Tcl_Obj* result;
- if (entry_to_obj(interp, &result, entry, &error)) {
+ if (entry_to_obj(interp, &result, entry, NULL, &error)) {
Tcl_SetObjResult(interp, result);
return TCL_OK;
}
@@ -209,7 +211,7 @@
*/
static int entry_close(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
if (objc != 3) {
- Tcl_WrongNumArgs(interp, 1, objv, "delete entry");
+ Tcl_WrongNumArgs(interp, 1, objv, "close entry");
return TCL_ERROR;
} else {
reg_error error;
@@ -455,7 +457,7 @@
return TCL_OK;
} else {
Tcl_Obj* result;
- if (entry_to_obj(interp, &result, entry, &error)) {
+ if (entry_to_obj(interp, &result, entry, NULL, &error)) {
Tcl_SetObjResult(interp, result);
return TCL_OK;
}
Copied: trunk/base/src/registry2.0/file.c (from rev 88375, branches/gsoc11-rev-upgrade/base/src/registry2.0/file.c)
===================================================================
--- trunk/base/src/registry2.0/file.c (rev 0)
+++ trunk/base/src/registry2.0/file.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -0,0 +1,292 @@
+/*
+ * file.c
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2011 Clemens Lang <cal 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 <sqlite3.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tcl.h>
+
+#include <cregistry/file.h>
+#include <cregistry/util.h>
+
+#include "file.h"
+#include "fileobj.h"
+#include "registry.h"
+#include "util.h"
+
+/**
+ * Converts a command name into a `reg_file`.
+ *
+ * @param [in] interp Tcl interpreter to check within
+ * @param [in] name name of file to get
+ * @param [out] errPtr description of error if the file can't be found
+ * @return a file, or NULL if one couldn't be found
+ * @see get_object
+ */
+static reg_file* get_file(Tcl_Interp* interp, char* name, reg_error* errPtr) {
+ return (reg_file*)get_object(interp, name, "file", file_obj_cmd, errPtr);
+}
+
+/**
+ * Removes the file 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 file object command.
+ *
+ * @param [in] clientData address of a reg_file to remove
+ */
+void delete_file(ClientData clientData) {
+ reg_file* file = (reg_file*)clientData;
+ free(file->proc);
+ free(file->key.path);
+ file->proc = NULL;
+}
+
+/**
+ * registry::file open portid path
+ *
+ * Opens a file matching the given parameters.
+ */
+static int file_open(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
+ reg_registry* reg = registry_for(interp, reg_attached);
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "open portid path");
+ return TCL_ERROR;
+ } else if (reg == NULL) {
+ return TCL_ERROR;
+ } else {
+ char* id = Tcl_GetString(objv[2]);
+ char* path = Tcl_GetString(objv[3]);
+ reg_error error;
+ reg_file* file = reg_file_open(reg, id, path, &error);
+ if (file != NULL) {
+ Tcl_Obj* result;
+ if (file_to_obj(interp, &result, file, NULL, &error)) {
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ }
+ }
+ return registry_failed(interp, &error);
+ }
+ return TCL_ERROR;
+}
+
+/**
+ * registry::file close file
+ *
+ * Closes a file. It will remain in the registry.
+ */
+static int file_close(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "close file");
+ return TCL_ERROR;
+ } else {
+ reg_error error;
+ char* proc = Tcl_GetString(objv[2]);
+ reg_file* file = get_file(interp, proc, &error);
+ if (file == 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::file search ?key value ...?
+ *
+ * Searches the registry for files for which each key's value is equal to the
+ * given value. To find all files, call `file 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 file_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_file** files;
+ reg_error error;
+ int file_count;
+ for (i = 2; i < objc;) {
+ int index, strat_index, val_length;
+ if (Tcl_GetIndexFromObj(interp, objv[i], file_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;
+ }
+ }
+ file_count = reg_file_search(reg, keys, vals, strats, key_count,
+ &files, &error);
+ free(keys);
+ free(vals);
+ free(strats);
+ if (file_count >= 0) {
+ int retval;
+ Tcl_Obj* resultObj;
+ Tcl_Obj** objs;
+ if (list_file_to_obj(interp, &objs, files, file_count, &error)){
+ resultObj = Tcl_NewListObj(file_count, objs);
+ Tcl_SetObjResult(interp, resultObj);
+ free(objs);
+ retval = TCL_OK;
+ } else {
+ retval = registry_failed(interp, &error);
+ }
+ free(files);
+ return retval;
+ }
+ return registry_failed(interp, &error);
+ }
+}
+
+typedef struct {
+ char* name;
+ int (*function)(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
+} file_cmd_type;
+
+static file_cmd_type file_cmds[] = {
+ /* Global commands */
+ { "open", file_open },
+ { "close", file_close },
+ { "search", file_search },
+ { NULL, NULL }
+};
+
+/*
+ * registry::file cmd ?arg ...?
+ *
+ * Commands manipulating file entries in the registry. This can be called `registry::file`
+ */
+int file_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], file_cmds,
+ sizeof(file_cmd_type), "cmd", 0, &cmd_index) == TCL_OK) {
+ file_cmd_type* cmd = &file_cmds[cmd_index];
+ return cmd->function(interp, objc, objv);
+ }
+ return TCL_ERROR;
+}
Copied: trunk/base/src/registry2.0/file.h (from rev 88375, branches/gsoc11-rev-upgrade/base/src/registry2.0/file.h)
===================================================================
--- trunk/base/src/registry2.0/file.h (rev 0)
+++ trunk/base/src/registry2.0/file.h 2011-12-30 00:17:49 UTC (rev 88376)
@@ -0,0 +1,44 @@
+/*
+ * file.h
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2011 Clemens Lang <cal 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 _FILE_H
+#define _FILE_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tcl.h>
+
+void delete_file(ClientData clientData);
+
+int file_cmd(ClientData clientData UNUSED, Tcl_Interp* interp, int objc,
+ Tcl_Obj* CONST objv[]);
+
+#endif /* _FILE_H */
+
Copied: trunk/base/src/registry2.0/fileobj.c (from rev 88375, branches/gsoc11-rev-upgrade/base/src/registry2.0/fileobj.c)
===================================================================
--- trunk/base/src/registry2.0/fileobj.c (rev 0)
+++ trunk/base/src/registry2.0/fileobj.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -0,0 +1,142 @@
+/*
+ * fileobj.c
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2011 Clemens Lang <cal 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 <tcl.h>
+#include <sqlite3.h>
+
+#include "fileobj.h"
+#include "registry.h"
+#include "util.h"
+
+const char* file_props[] = {
+ "path",
+ "actual_path",
+ "active",
+ "mtime",
+ "md5sum",
+ "editable",
+ "binary",
+ NULL
+};
+
+/* ${file} prop ?value? */
+static int file_obj_prop(Tcl_Interp* interp, reg_file* file, int objc,
+ Tcl_Obj* CONST objv[]) {
+ int index;
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?value?");
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ /* ${file} 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], file_props, "prop", 0, &index)
+ == TCL_OK) {
+ char* key = Tcl_GetString(objv[1]);
+ char* value;
+ reg_error error;
+ if (reg_file_propget(file, 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 {
+ /* ${file} 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], file_props, "prop", 0, &index)
+ == TCL_OK) {
+ char* key = Tcl_GetString(objv[1]);
+ char* value = Tcl_GetString(objv[2]);
+ reg_error error;
+ if (reg_file_propset(file, key, value, &error)) {
+ return TCL_OK;
+ }
+ return registry_failed(interp, &error);
+ }
+ return TCL_ERROR;
+ }
+}
+
+typedef struct {
+ char* name;
+ int (*function)(Tcl_Interp* interp, reg_file* file, int objc,
+ Tcl_Obj* CONST objv[]);
+} file_obj_cmd_type;
+
+static file_obj_cmd_type file_cmds[] = {
+ /* keys */
+ { "path", file_obj_prop },
+ { "actual_path", file_obj_prop },
+ { "active", file_obj_prop },
+ { "mtime", file_obj_prop },
+ { "md5sum", file_obj_prop },
+ { "editable", file_obj_prop },
+ { "binary", file_obj_prop },
+ { NULL, NULL }
+};
+
+/* ${file} cmd ?arg ...? */
+/* This function implements the command that will be called when a file
+ * created by `registry::file` 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 file_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], file_cmds,
+ sizeof(file_obj_cmd_type), "cmd", 0, &cmd_index) == TCL_OK) {
+ file_obj_cmd_type* cmd = &file_cmds[cmd_index];
+ return cmd->function(interp, (reg_file*)clientData, objc, objv);
+ }
+ return TCL_ERROR;
+}
+
Copied: trunk/base/src/registry2.0/fileobj.h (from rev 88375, branches/gsoc11-rev-upgrade/base/src/registry2.0/fileobj.h)
===================================================================
--- trunk/base/src/registry2.0/fileobj.h (rev 0)
+++ trunk/base/src/registry2.0/fileobj.h 2011-12-30 00:17:49 UTC (rev 88376)
@@ -0,0 +1,44 @@
+/*
+ * fileobj.h
+ * vim:tw=80:expandtab
+ * $Id$
+ *
+ * Copyright (c) 2011 Clemens Lang <cal 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 _FILE_OBJ_CMD_H
+#define _FILE_OBJ_CMD_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tcl.h>
+#include <sqlite3.h>
+
+extern const char* file_props[];
+
+int file_obj_cmd(ClientData clientData, Tcl_Interp* interp, int objc,
+ Tcl_Obj* CONST objv[]);
+
+#endif /* _FILE_OBJ_CMD_H */
Modified: trunk/base/src/registry2.0/portimage.tcl
===================================================================
--- trunk/base/src/registry2.0/portimage.tcl 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/registry2.0/portimage.tcl 2011-12-30 00:17:49 UTC (rev 88376)
@@ -88,7 +88,7 @@
set noexec $options(ports_activate_no-exec)
}
if {![info exists registry_open]} {
- registry::open [file join ${macports::registry.path} registry registry.db]
+ registry::open [::file join ${macports::registry.path} registry registry.db]
set registry_open yes
}
set todeactivate [list]
@@ -116,7 +116,7 @@
if { ![string equal [$requested installtype] "image"] } {
return -code error "Image error: ${name} @${specifier} not installed as an image."
}
- if {![file isfile $location]} {
+ if {![::file isfile $location]} {
return -code error "Image error: Can't find image file $location"
}
if { [string equal [$requested state] "installed"] } {
@@ -158,7 +158,7 @@
set force 0
}
if {![info exists registry_open]} {
- registry::open [file join ${macports::registry.path} registry registry.db]
+ registry::open [::file join ${macports::registry.path} registry registry.db]
set registry_open yes
}
@@ -249,7 +249,7 @@
## @param [in] dstfile path to activate file to
## @return 1 if file needs to be explicitly deleted if we have to roll back, 0 otherwise
proc _activate_file {srcfile dstfile} {
- if {[catch {set filetype [file type $srcfile]} result]} {
+ if {[catch {set filetype [::file type $srcfile]} result]} {
# this can happen if the archive was built on case-sensitive and we're case-insensitive
# we know any existing dstfile is ours because we checked for conflicts earlier
if {![catch {file type $dstfile}]} {
@@ -264,23 +264,23 @@
# Don't recursively copy directories
ui_debug "activating directory: $dstfile"
# Don't do anything if the directory already exists.
- if { ![file isdirectory $dstfile] } {
- file mkdir $dstfile
+ if { ![::file isdirectory $dstfile] } {
+ ::file mkdir $dstfile
# fix attributes on the directory.
if {[getuid] == 0} {
- eval file attributes {$dstfile} [file attributes $srcfile]
+ eval ::file attributes {$dstfile} [::file attributes $srcfile]
} else {
# not root, so can't set owner/group
- eval file attributes {$dstfile} -permissions [file attributes $srcfile -permissions]
+ eval ::file attributes {$dstfile} -permissions [::file attributes $srcfile -permissions]
}
# set mtime on installed element
- file mtime $dstfile [file mtime $srcfile]
+ ::file mtime $dstfile [::file mtime $srcfile]
}
return 0
}
default {
ui_debug "activating file: $dstfile"
- file rename $srcfile $dstfile
+ ::file rename $srcfile $dstfile
return 1
}
}
@@ -290,7 +290,7 @@
# returns: path to the extracted directory
proc extract_archive_to_tmpdir {location} {
global macports::registry.path
- set extractdir [mkdtemp [file dirname $location]/mpextractXXXXXXXX]
+ set extractdir [mkdtemp [::file dirname $location]/mpextractXXXXXXXX]
set startpwd [pwd]
try {
@@ -305,7 +305,7 @@
set unarchive.pre_args {}
set unarchive.args {}
set unarchive.pipe_cmd ""
- set unarchive.type [file extension $location]
+ set unarchive.type [::file extension $location]
switch -regex ${unarchive.type} {
cp(io|gz) {
set pax "pax"
@@ -413,7 +413,7 @@
}
system $cmdstring
} catch {*} {
- file delete -force $extractdir
+ ::file delete -force $extractdir
throw
} finally {
cd $startpwd
@@ -451,7 +451,7 @@
# To be able to install links, we test if we can lstat the file to
# figure out if the source file exists (file exists will return
# false for symlinks on files that do not exist)
- if { [catch {file lstat $srcfile dummystatvar}] } {
+ if { [catch {::file lstat $srcfile dummystatvar}] } {
throw registry::image-error "Image error: Source file $srcfile does not appear to exist (cannot lstat it). Unable to activate port [$port name]."
}
@@ -474,10 +474,10 @@
# if we're forcing the activation, then we move any existing
# files to a backup file, both in the filesystem and in the
# registry
- if { ![catch {file type $file}] } {
+ if { ![catch {::file type $file}] } {
set bakfile "${file}${baksuffix}"
ui_warn "File $file already exists. Moving to: $bakfile."
- file rename -force -- $file $bakfile
+ ::file rename -force -- $file $bakfile
lappend backups $file
}
if { $owner != {} } {
@@ -490,7 +490,7 @@
# the registry
if { $owner != {} && $owner != $port } {
throw registry::image-error "Image error: $file is being used by the active [$owner name] port. Please deactivate this port first, or use 'port -f activate [$port name]' to force the activation."
- } elseif { $owner == {} && ![catch {file type $file}] } {
+ } elseif { $owner == {} && ![catch {::file type $file}] } {
throw registry::image-error "Image error: $file already exists and does not belong to a registered port. Unable to activate port [$port name]. Use 'port -f activate [$port name]' to force the activation."
}
}
@@ -504,10 +504,10 @@
# subpaths. We do need, nevertheless, all sub paths to make sure
# we'll set the directory attributes properly for all
# directories.
- set directory [file dirname $file]
+ set directory [::file dirname $file]
while { [lsearch -exact $files $directory] == -1 } {
lappend files $directory
- set directory [file dirname $directory]
+ set directory [::file dirname $directory]
}
# Also add the filename to the imagefile list.
@@ -555,7 +555,7 @@
# locations, then rethrow the error. Transaction rollback will take care
# of this in the registry.
foreach file $backups {
- file rename -force -- "${file}${baksuffix}" $file
+ ::file rename -force -- "${file}${baksuffix}" $file
}
# reactivate deactivated ports
foreach entry [array names todeactivate] {
@@ -564,10 +564,10 @@
}
}
# remove temp image dir
- file delete -force $extracted_dir
+ ::file delete -force $extracted_dir
throw
}
- file delete -force $extracted_dir
+ ::file delete -force $extracted_dir
}
# These directories should not be removed during deactivation even if they are empty.
@@ -576,7 +576,7 @@
array set precious_dirs { /Library/LaunchDaemons 1 /Library/LaunchAgents 1 }
proc _deactivate_file {dstfile} {
- if {[catch {file type $dstfile} filetype]} {
+ if {[catch {::file type $dstfile} filetype]} {
ui_debug "$dstfile does not exist"
return
}
@@ -589,7 +589,7 @@
variable precious_dirs
if {![info exists precious_dirs($dstfile)]} {
ui_debug "deactivating directory: $dstfile"
- file delete -- $dstfile
+ ::file delete -- $dstfile
} else {
ui_debug "directory $dstfile does not belong to us"
}
@@ -598,7 +598,7 @@
}
} else {
ui_debug "deactivating file: $dstfile"
- file delete -- $dstfile
+ ::file delete -- $dstfile
}
}
@@ -606,7 +606,7 @@
set files [list]
foreach file $imagefiles {
- if { [file exists $file] || (![catch {file type $file}] && [file type $file] == "link") } {
+ if { [::file exists $file] || (![catch {::file type $file}] && [::file type $file] == "link") } {
# Normalize the file path to avoid removing the intermediate
# symlinks (remove the empty directories instead)
# Remark: paths in the registry may be not normalized.
@@ -617,14 +617,14 @@
# belong to any port.
# The custom realpath proc is necessary because file normalize
# does not resolve symlinks on OS X < 10.6
- set directory [realpath [file dirname $file]]
- lappend files [file join $directory [file tail $file]]
+ set directory [realpath [::file dirname $file]]
+ lappend files [::file join $directory [::file tail $file]]
# Split out the filename's subpaths and add them to the image list
# as well.
while { [lsearch -exact $files $directory] == -1 } {
lappend files $directory
- set directory [file dirname $directory]
+ set directory [::file dirname $directory]
}
} else {
ui_debug "$file does not exist."
Modified: trunk/base/src/registry2.0/portuninstall.tcl
===================================================================
--- trunk/base/src/registry2.0/portuninstall.tcl 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/registry2.0/portuninstall.tcl 2011-12-30 00:17:49 UTC (rev 88376)
@@ -215,7 +215,7 @@
file delete $imagefile
# Try to delete the port's image dir; will fail if there are more image
# files so just ignore the failure
- catch {file delete [file dirname $imagefile]}
+ catch {file delete [::file dirname $imagefile]}
registry::entry delete $port
}
Modified: trunk/base/src/registry2.0/receipt_flat.tcl
===================================================================
--- trunk/base/src/registry2.0/receipt_flat.tcl 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/registry2.0/receipt_flat.tcl 2011-12-30 00:17:49 UTC (rev 88376)
@@ -75,7 +75,7 @@
# regex match case
if {$portversion == 0} {
- set x [glob -nocomplain -directory [file join ${macports::registry.path} receipts] -- ${portname}-*]
+ set x [glob -nocomplain -directory [::file join ${macports::registry.path} receipts] -- ${portname}-*]
if {[string length $x]} {
set matchfile [lindex $x 0]
# Remove trailing .bz2, if any.
@@ -84,7 +84,7 @@
set matchfile ""
}
} else {
- set matchfile [file join ${macports::registry.path} receipts ${portname}-${portversion}]
+ set matchfile [::file join ${macports::registry.path} receipts ${portname}-${portversion}]
}
# Might as well bail out early if no file to match
@@ -92,7 +92,7 @@
return ""
}
- if {[file exists $matchfile] || [file exists ${matchfile}.bz2]} {
+ if {[::file exists $matchfile] || [::file exists ${matchfile}.bz2]} {
return $matchfile
}
return ""
@@ -110,11 +110,11 @@
return $ref_index($name,$version,$revision,$variants)
}
- set receipt_path [file join ${macports::registry.path} receipts ${name}]
+ set receipt_path [::file join ${macports::registry.path} receipts ${name}]
# If the receipt path ${name} doesn't exist, then the receipt probably is
# in the old HEAD format.
- if { ![file isdirectory $receipt_path] } {
+ if { ![::file isdirectory $receipt_path] } {
set receipt_file [get_head_entry_receipt_path $name $version]
if {![string length $receipt_file]} {
@@ -127,7 +127,7 @@
# Extract the version from the path.
if { $version == "" } {
- set theFileName [file tail $receipt_file]
+ set theFileName [::file tail $receipt_file]
regexp "^$name-(.*)\$" $theFileName match version
}
} else {
@@ -137,7 +137,7 @@
# version given to us. How should we handle this?
set x [glob -nocomplain -directory ${receipt_path} *]
if { [string length $x] } {
- set v [lindex [file split [lindex $x 0]] end]
+ set v [lindex [::file split [lindex $x 0]] end]
regexp {([-_a-zA-Z0-9\.]+)_([0-9]*)([+-_a-zA-Z0-9]*)$} $v match version revision variants
} else {
return -code error "Registry error: ${name} not registered as installed."
@@ -148,15 +148,15 @@
return -code error "Registry error: ${name} @${version}_${revision}${variants} not registered as installed."
}
- set receipt_path [file join ${macports::registry.path} receipts ${name} ${version}_${revision}${variants}]
+ set receipt_path [::file join ${macports::registry.path} receipts ${name} ${version}_${revision}${variants}]
- set receipt_file [file join ${receipt_path} receipt]
+ set receipt_file [::file join ${receipt_path} receipt]
}
- if { [file exists ${receipt_file}.bz2] && [file exists ${registry::autoconf::bzip2_path}] } {
+ if { [::file exists ${receipt_file}.bz2] && [::file exists ${registry::autoconf::bzip2_path}] } {
set receipt_file ${receipt_file}.bz2
set receipt_contents [exec ${registry::autoconf::bzip2_path} -d -c ${receipt_file}]
- } elseif { [file exists ${receipt_file}] } {
+ } elseif { [::file exists ${receipt_file}] } {
set receipt_handle [open ${receipt_file} r]
set receipt_contents [read $receipt_handle]
close $receipt_handle
@@ -177,7 +177,7 @@
convert_entry_from_HEAD $name $version $revision $variants $receipt_contents $ref
# move the old receipt
- set convertedDirPath [file join ${macports::registry.path} receipts_converted]
+ set convertedDirPath [::file join ${macports::registry.path} receipts_converted]
file mkdir $convertedDirPath
file rename -- $receipt_file $convertedDirPath
} elseif {[string match "# Version: *" $receipt_contents]} {
@@ -274,15 +274,15 @@
foreach file $contents {
if {[llength $file]} {
set theFilePath [lindex $file 0]
- if {[file isfile $theFilePath]} {
- set previousPort [file_registered $theFilePath]
+ if {[::file isfile $theFilePath]} {
+ set previousPort [::file_registered $theFilePath]
if {$previousPort != 0} {
ui_warn "Conflict detected for file $theFilePath between $previousPort and $name."
}
if {[catch {register_file $theFilePath $name}]} {
ui_warn "An error occurred while adding $theFilePath to the file_map database."
}
- } elseif {![file exists $theFilePath]} {
+ } elseif {![::file exists $theFilePath]} {
ui_warn "Port $name refers to $theFilePath which doesn't exist."
}
lappend theActualContents $file
@@ -314,10 +314,10 @@
set receipt_contents [array get receipt_$ref]
- set receipt_path [file join ${macports::registry.path} receipts ${name} ${version}_${revision}${variants}]
- set receipt_file [file join ${receipt_path} receipt]
+ set receipt_path [::file join ${macports::registry.path} receipts ${name} ${version}_${revision}${variants}]
+ set receipt_file [::file join ${receipt_path} receipt]
- if { ![file isdirectory ${receipt_path}] } {
+ if { ![::file isdirectory ${receipt_path}] } {
file mkdir ${receipt_path}
}
@@ -326,15 +326,15 @@
puts $receipt_handle $receipt_contents
close $receipt_handle
- if { [file exists ${receipt_file}] } {
+ if { [::file exists ${receipt_file}] } {
file delete -force -- "${receipt_file}"
- } elseif { [file exists ${receipt_file}.bz2] } {
+ } elseif { [::file exists ${receipt_file}.bz2] } {
file delete -force -- "${receipt_file}.bz2"
}
file rename -force -- "${receipt_file}.tmp" "${receipt_file}"
- if { [file exists ${receipt_file}] && [file exists ${registry::autoconf::bzip2_path}] && ![info exists registry.nobzip] } {
+ if { [::file exists ${receipt_file}] && [::file exists ${registry::autoconf::bzip2_path}] && ![info exists registry.nobzip] } {
system "${registry::autoconf::bzip2_path} -f ${receipt_file}"
}
@@ -345,12 +345,12 @@
proc entry_exists {name version {revision 0} {variants ""}} {
global macports::registry.path
- set receipt_path [file join ${macports::registry.path} receipts ${name} ${version}_${revision}${variants}]
- set receipt_file [file join ${receipt_path} receipt]
+ set receipt_path [::file join ${macports::registry.path} receipts ${name} ${version}_${revision}${variants}]
+ set receipt_file [::file join ${receipt_path} receipt]
- if { [file exists $receipt_file] } {
+ if { [::file exists $receipt_file] } {
return 1
- } elseif { [file exists ${receipt_file}.bz2] } {
+ } elseif { [::file exists ${receipt_file}.bz2] } {
return 1
}
@@ -361,7 +361,7 @@
proc entry_exists_for_name {name} {
global macports::registry.path
- set receipt_path [file join ${macports::registry.path} receipts ${name}]
+ set receipt_path [::file join ${macports::registry.path} receipts ${name}]
if {[llength [glob -nocomplain -directory $receipt_path */receipt{,.bz2}]] > 0} {
return 1
@@ -417,14 +417,14 @@
array unset ref_index "$name,$version,$revision,$variants"
}
- set receipt_path [file join ${macports::registry.path} receipts ${name} ${version}_${revision}${variants}]
- if { [file exists ${receipt_path}] } {
+ set receipt_path [::file join ${macports::registry.path} receipts ${name} ${version}_${revision}${variants}]
+ if { [::file exists ${receipt_path}] } {
# remove port receipt directory
ui_debug "deleting directory: ${receipt_path}"
file delete -force -- ${receipt_path}
# remove port receipt parent directory (if empty)
- set receipt_dir [file join ${macports::registry.path} receipts ${name}]
- if { [file isdirectory ${receipt_dir}] } {
+ set receipt_dir [::file join ${macports::registry.path} receipts ${name}]
+ if { [::file isdirectory ${receipt_dir}] } {
# 0 item means empty.
if { [llength [readdir ${receipt_dir}]] == 0 } {
ui_debug "deleting directory: ${receipt_dir}"
@@ -449,12 +449,12 @@
proc installed {{name ""} {version ""}} {
global macports::registry.path
- set query_path [file join ${macports::registry.path} receipts]
+ set query_path [::file join ${macports::registry.path} receipts]
if { $name == "" } {
- set query_path [file join ${query_path} *]
+ set query_path [::file join ${query_path} *]
if { $version == "" } {
- set query_path [file join ${query_path} *]
+ set query_path [::file join ${query_path} *]
}
# [PG] Huh?
} else {
@@ -462,32 +462,32 @@
# returned with the correct case even if it's wrong when given. To get the
# correct case on a case-insensitive FS, we have to list the directory and
# compare against each entry.
- set name_path [file join ${query_path} *]
+ set name_path [::file join ${query_path} *]
set name_entries [glob -nocomplain -types d ${name_path}]
foreach entry $name_entries {
- set basename [file tail $entry]
+ set basename [::file tail $entry]
if {[string equal -nocase $basename $name]} {
set name $basename
break
}
}
- set query_path [file join ${query_path} ${name}]
+ set query_path [::file join ${query_path} ${name}]
if { $version != "" } {
- set query_path [file join ${query_path} ${version}]
+ set query_path [::file join ${query_path} ${version}]
} else {
- set query_path [file join ${query_path} *]
+ set query_path [::file join ${query_path} *]
}
}
set x [glob -nocomplain -types d ${query_path}]
set rlist [list]
foreach p $x {
- if {![file isfile [file join $p receipt.bz2]] && ![file isfile [file join $p receipt]]} {
+ if {![::file isfile [::file join $p receipt.bz2]] && ![::file isfile [::file join $p receipt]]} {
continue
}
set plist [list]
- regexp {([-_a-zA-Z0-9\.]+)_([0-9]*)([+-_a-zA-Z0-9]*)$} [lindex [file split $p] end] match version revision variants
- lappend plist [lindex [file split $p] end-1]
+ regexp {([-_a-zA-Z0-9\.]+)_([0-9]*)([+-_a-zA-Z0-9]*)$} [lindex [::file split $p] end] match version revision variants
+ lappend plist [lindex [::file split $p] end-1]
lappend plist $version
lappend plist $revision
lappend plist $variants
@@ -496,13 +496,13 @@
# append the ports in old HEAD format.
if { $name == "" } {
- set query_path [file join ${macports::registry.path} receipts *]
+ set query_path [::file join ${macports::registry.path} receipts *]
} else {
- set query_path [file join ${macports::registry.path} receipts ${name}-*]
+ set query_path [::file join ${macports::registry.path} receipts ${name}-*]
}
set receiptglob [glob -nocomplain -types f ${query_path}]
foreach receipt_file $receiptglob {
- set theFileName [file tail $receipt_file]
+ set theFileName [::file tail $receipt_file]
# Remark: these regexes do not always work.
set theName ""
@@ -539,14 +539,14 @@
global macports::registry.path
variable file_map
- set receipt_path [file join ${macports::registry.path} receipts]
- set map_file [file join ${receipt_path} file_map]
+ set receipt_path [::file join ${macports::registry.path} receipts]
+ set map_file [::file join ${receipt_path} file_map]
# Don't reopen it (it actually would deadlock us), unless it was open r/o.
# and we want it r/w.
if { [info exists file_map] } {
if { $readonly == 0 } {
- if {[filemap isreadonly file_map]} {
+ if {[::filemap isreadonly file_map]} {
filemap close file_map
filemap open file_map ${map_file}.db
}
@@ -556,11 +556,11 @@
set old_filemap [list]
- if { ![file exists ${map_file}.db] } {
+ if { ![::file exists ${map_file}.db] } {
# Convert to new format
- if { [file exists ${map_file}.bz2] && [file exists ${registry::autoconf::bzip2_path}] } {
+ if { [::file exists ${map_file}.bz2] && [::file exists ${registry::autoconf::bzip2_path}] } {
set old_filemap [exec ${registry::autoconf::bzip2_path} -d -c ${map_file}.bz2]
- } elseif { [file exists $map_file] } {
+ } elseif { [::file exists $map_file] } {
set map_handle [open ${map_file} r]
set old_filemap [read $map_handle]
close $map_handle
@@ -608,8 +608,8 @@
open_file_map 1
- if {[filemap exists file_map $file]} {
- return [filemap get file_map $file]
+ if {[::filemap exists file_map $file]} {
+ return [::filemap get file_map $file]
} else {
return 0
}
@@ -630,7 +630,7 @@
open_file_map 1
- set files [filemap list file_map $name]
+ set files [::filemap list file_map $name]
if { [llength $files] > 0 } {
return $files
@@ -641,7 +641,7 @@
# Convert the port and retry.
open_entry $name
- set files [filemap list file_map $name]
+ set files [::filemap list file_map $name]
return $files
} else {
@@ -662,7 +662,7 @@
open_file_map
- if { [file type $file] == "link" } {
+ if { [::file type $file] == "link" } {
ui_debug "Adding link to file_map: $file for: $port"
} else {
ui_debug "Adding file to file_map: $file for: $port"
@@ -684,7 +684,7 @@
foreach f $files {
set file [lindex $f 0]
- if { [file type $file] == "link" } {
+ if { [::file type $file] == "link" } {
ui_debug "Adding link to file_map: $file for: $port"
} else {
ui_debug "Adding file to file_map: $file for: $port"
@@ -743,13 +743,13 @@
global macports::registry.path
variable dep_map
- set receipt_path [file join ${macports::registry.path} receipts]
+ set receipt_path [::file join ${macports::registry.path} receipts]
- set map_file [file join ${receipt_path} dep_map]
+ set map_file [::file join ${receipt_path} dep_map]
- if { [file exists ${map_file}.bz2] && [file exists ${registry::autoconf::bzip2_path}] } {
+ if { [::file exists ${map_file}.bz2] && [::file exists ${registry::autoconf::bzip2_path}] } {
set dep_map [exec ${registry::autoconf::bzip2_path} -d -c ${map_file}.bz2]
- } elseif { [file exists ${map_file}] } {
+ } elseif { [::file exists ${map_file}] } {
set map_handle [open ${map_file} r]
set dep_map [read $map_handle]
close $map_handle
@@ -837,9 +837,9 @@
global macports::registry.path
variable dep_map
- set receipt_path [file join ${macports::registry.path} receipts]
+ set receipt_path [::file join ${macports::registry.path} receipts]
- set map_file [file join ${receipt_path} dep_map]
+ set map_file [::file join ${receipt_path} dep_map]
set map_handle [open ${map_file}.tmp w 0644]
puts $map_handle $dep_map
@@ -850,7 +850,7 @@
file rename -- ${map_file}.tmp ${map_file}
- if { [file exists ${map_file}] && [file exists ${registry::autoconf::bzip2_path}] && ![info exists registry.nobzip] } {
+ if { [::file exists ${map_file}] && [::file exists ${registry::autoconf::bzip2_path}] && ![info exists registry.nobzip] } {
system "${registry::autoconf::bzip2_path} -f ${map_file}"
}
Property changes on: trunk/base/src/registry2.0/receipt_sqlite.tcl
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/gsoc08-privileges/base/src/registry1.0/receipt_sqlite.tcl:37343-46937
/branches/gsoc09-logging/base/src/registry1.0/receipt_sqlite.tcl:51231-60371
/branches/universal-sanity/base/src/registry1.0/receipt_sqlite.tcl:51872-52323
/branches/variant-descs-14482/base/src/registry1.0/receipt_sqlite.tcl:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/registry1.0/receipt_sqlite.tcl:45682-46060
/users/perry/base-select/src/registry1.0/receipt_sqlite.tcl:44044-44692
+ /branches/gsoc08-privileges/base/src/registry1.0/receipt_sqlite.tcl:37343-46937
/branches/gsoc09-logging/base/src/registry1.0/receipt_sqlite.tcl:51231-60371
/branches/gsoc11-rev-upgrade/base/src/registry2.0/receipt_sqlite.tcl:78828-88375
/branches/universal-sanity/base/src/registry1.0/receipt_sqlite.tcl:51872-52323
/branches/variant-descs-14482/base/src/registry1.0/receipt_sqlite.tcl:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes/src/registry1.0/receipt_sqlite.tcl:45682-46060
/users/perry/base-select/src/registry1.0/receipt_sqlite.tcl:44044-44692
Modified: trunk/base/src/registry2.0/registry.c
===================================================================
--- trunk/base/src/registry2.0/registry.c 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/registry2.0/registry.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -38,12 +38,14 @@
#include <cregistry/registry.h>
#include <cregistry/entry.h>
+#include <cregistry/file.h>
-#include "registry.h"
+#include "entry.h"
+#include "entryobj.h"
+#include "file.h"
#include "graph.h"
#include "item.h"
-#include "entry.h"
-#include "entryobj.h"
+#include "registry.h"
#include "util.h"
int registry_failed(Tcl_Interp* interp, reg_error* errPtr) {
@@ -54,6 +56,8 @@
return TCL_ERROR;
}
+/* we don't need delete_file_list and restore_file_list unless we allow deletion
+ of files via the file interface */
static void delete_entry_list(ClientData list, Tcl_Interp* interp UNUSED) {
entry_list* curr = *(entry_list**)list;
while (curr) {
@@ -80,8 +84,11 @@
int registry_tcl_detach(Tcl_Interp* interp, reg_registry* reg,
reg_error* errPtr) {
reg_entry** entries;
- int entry_count = reg_all_open_entries(reg, &entries);
+ reg_file** files;
+ int entry_count;
+ int file_count;
int i;
+ entry_count = reg_all_open_entries(reg, &entries);
if (entry_count == -1) {
return 0;
}
@@ -91,6 +98,16 @@
}
}
free(entries);
+ file_count = reg_all_open_files(reg, &files);
+ if (file_count == -1) {
+ return 0;
+ }
+ for (i = 0; i < file_count; i++) {
+ if (files[i]->proc) {
+ Tcl_DeleteCommand(interp, files[i]->proc);
+ }
+ }
+ free(files);
if (!reg_detach(reg, errPtr)) {
return registry_failed(interp, errPtr);
}
@@ -319,6 +336,7 @@
/* Tcl_CreateObjCommand(interp, "registry::graph", GraphCmd, NULL, NULL); */
/* 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);
if (Tcl_PkgProvide(interp, "registry2", "2.0") != TCL_OK) {
return TCL_ERROR;
}
Modified: trunk/base/src/registry2.0/registry.tcl
===================================================================
--- trunk/base/src/registry2.0/registry.tcl 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/registry2.0/registry.tcl 2011-12-30 00:17:49 UTC (rev 88376)
@@ -320,7 +320,7 @@
# (we won't store the md5 of the target of links since it's meaningless
# and $statvar(mode) tells us that links are links).
if {![catch {file lstat $fname statvar}]} {
- if {[file isfile $fname] && [file type $fname] != "link"} {
+ if {[::file isfile $fname] && [::file type $fname] != "link"} {
if {[catch {md5 file $fname} md5sum] == 0} {
# Create a line that matches md5(1)'s output
# for backwards compatibility
@@ -347,7 +347,7 @@
set rval [list]
foreach file $flist {
if {[string index $file 0] != "/"} {
- set file [file join $prefix $file]
+ set file [::file join $prefix $file]
}
lappend rval [fileinfo_for_file $file]
}
@@ -396,9 +396,9 @@
if {$nlocked > 1} {
return
}
- set lockpath [file join ${registry.path} registry .registry.lock]
+ set lockpath [::file join ${registry.path} registry .registry.lock]
if {![info exists lockfd]} {
- if {![file writable [file dirname $lockpath]]} {
+ if {![::file writable [::file dirname $lockpath]]} {
# skip locking, registry can't be modified anyway
return
}
Modified: trunk/base/src/registry2.0/util.c
===================================================================
--- trunk/base/src/registry2.0/util.c 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/registry2.0/util.c 2011-12-30 00:17:49 UTC (rev 88376)
@@ -36,6 +36,7 @@
#include "util.h"
#include "entryobj.h"
+#include "fileobj.h"
/**
* Generates a unique proc name starting with prefix.
@@ -45,24 +46,28 @@
* Tcl interp context. This behavior is similar to that of the builtin
* `interp create` command, and is intended to generate names for created
* objects of a similar nature.
- *
- * TODO: add a int* parameter so that functions which need large numbers of
- * unique names can keep track of the lower bound between calls,thereby turning
- * N^2 to N. It'll be alchemy for the 21st century.
*/
-char* unique_name(Tcl_Interp* interp, char* prefix) {
+char* unique_name(Tcl_Interp* interp, char* prefix, int* lower_bound) {
int result_size = strlen(prefix) + TCL_INTEGER_SPACE + 1;
char* result = malloc(result_size);
Tcl_CmdInfo info;
int i;
if (!result)
return NULL;
- for (i=0; ; i++) {
+ if (lower_bound == NULL) {
+ i = 0;
+ } else {
+ i = *lower_bound;
+ }
+ for (; ; i++) {
snprintf(result, result_size, "%s%d", prefix, i);
if (Tcl_GetCommandInfo(interp, result, &info) == 0) {
break;
}
}
+ if (lower_bound != NULL) {
+ *lower_bound = i + 1;
+ }
return result;
}
@@ -175,18 +180,39 @@
reg_error* errPtr) {
if (set_object(interp, name, entry, "entry", entry_obj_cmd, NULL,
errPtr)) {
- int size = strlen(name) + 1;
- entry->proc = malloc(size*sizeof(char));
+ entry->proc = strdup(name);
if (!entry->proc) {
return 0;
}
- memcpy(entry->proc, name, size);
return 1;
}
return 0;
}
/**
+ * Sets a given name to be a file object.
+ *
+ * @param [in] interp Tcl interpreter to create the file within
+ * @param [in] name name to associate the given file with
+ * @param [in] file file 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_file(Tcl_Interp* interp, char* name, reg_file* file,
+ reg_error* errPtr) {
+ if (set_object(interp, name, file, "file", file_obj_cmd, NULL,
+ errPtr)) {
+ file->proc = strdup(name);
+ if (!file->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
@@ -204,47 +230,6 @@
}
}
-/**
- * Sets the result of the interpreter to all objects returned by a query.
- *
- * This function executes `query` on `db` It expects that the query will return
- * records of a single column, `rowid`. It will then use `prefix` to construct
- * unique names for these records, and call `setter` to construct their proc
- * objects. The result of `interp` will be set to a list of all such objects.
- *
- * If TCL_OK is returned, then a list is in the result. If TCL_ERROR is, then an
- * error is there.
- */
-int all_objects(Tcl_Interp* interp, sqlite3* db, char* query, char* prefix,
- set_object_function* setter) {
- sqlite3_stmt* stmt;
- if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
- Tcl_Obj* result = Tcl_NewListObj(0, NULL);
- Tcl_SetObjResult(interp, result);
- while (sqlite3_step(stmt) == SQLITE_ROW) {
- sqlite_int64 rowid = sqlite3_column_int64(stmt, 0);
- char* name = unique_name(interp, prefix);
- if (!name) {
- return TCL_ERROR;
- }
- if (setter(interp, name, rowid) == TCL_OK) {
- Tcl_Obj* element = Tcl_NewStringObj(name, -1);
- Tcl_ListObjAppendElement(interp, result, element);
- free(name);
- } else {
- free(name);
- return TCL_ERROR;
- }
- }
- sqlite3_finalize(stmt);
- return TCL_OK;
- } else {
- sqlite3_finalize(stmt);
- set_sqlite_result(interp, db, query);
- return TCL_ERROR;
- }
-}
-
const char* string_or_null(Tcl_Obj* obj) {
const char* string = Tcl_GetString(obj);
if (string[0] == '\0') {
@@ -254,15 +239,16 @@
}
}
-int recast(void* userdata, cast_function* fn, free_function* del, void*** outv,
- void** inv, int inc, reg_error* errPtr) {
+int recast(void* userdata, cast_function* fn, void* castcalldata,
+ free_function* del, void*** outv, void** inv, int inc,
+ reg_error* errPtr) {
void** result = malloc(inc*sizeof(void*));
int i;
if (!result) {
return 0;
}
for (i=0; i<inc; i++) {
- if (!fn(userdata, &result[i], inv[i], errPtr)) {
+ if (!fn(userdata, &result[i], inv[i], castcalldata, errPtr)) {
if (del != NULL) {
for ( ; i>=0; i--) {
del(userdata, result[i]);
@@ -277,9 +263,9 @@
}
int entry_to_obj(Tcl_Interp* interp, Tcl_Obj** obj, reg_entry* entry,
- reg_error* errPtr) {
+ int* lower_bound, reg_error* errPtr) {
if (entry->proc == NULL) {
- char* name = unique_name(interp, "::registry::entry");
+ char* name = unique_name(interp, "::registry::entry", lower_bound);
if (!name) {
return 0;
}
@@ -293,26 +279,51 @@
return 1;
}
+int file_to_obj(Tcl_Interp* interp, Tcl_Obj** obj, reg_file* file,
+ int* lower_bound, reg_error* errPtr) {
+ if (file->proc == NULL) {
+ char* name = unique_name(interp, "::registry::file", lower_bound);
+ if (!name) {
+ return 0;
+ }
+ if (!set_file(interp, name, file, errPtr)) {
+ free(name);
+ return 0;
+ }
+ free(name);
+ }
+ *obj = Tcl_NewStringObj(file->proc, -1);
+ return 1;
+}
+
int list_entry_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
reg_entry** entries, int entry_count, reg_error* errPtr) {
- return recast(interp, (cast_function*)entry_to_obj, NULL, (void***)objs,
- (void**)entries, entry_count, errPtr);
+ int lower_bound = 0;
+ return recast(interp, (cast_function*)entry_to_obj, &lower_bound, NULL,
+ (void***)objs, (void**)entries, entry_count, errPtr);
}
+int list_file_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
+ reg_file** files, int file_count, reg_error* errPtr) {
+ int lower_bound = 0;
+ return recast(interp, (cast_function*)file_to_obj, &lower_bound, NULL,
+ (void***)objs, (void**)files, file_count, errPtr);
+}
+
static int obj_to_string(void* userdata UNUSED, char** string, Tcl_Obj* obj,
- reg_error* errPtr UNUSED) {
+ void* param UNUSED, reg_error* errPtr UNUSED) {
*string = Tcl_GetString(obj);
return 1;
}
int list_obj_to_string(char*** strings, Tcl_Obj** objv, int objc,
reg_error* errPtr) {
- return recast(NULL, (cast_function*)obj_to_string, NULL, (void***)strings,
+ return recast(NULL, (cast_function*)obj_to_string, NULL, NULL, (void***)strings,
(void**)objv, objc, errPtr);
}
static int string_to_obj(void* userdata UNUSED, Tcl_Obj** obj, char* string,
- reg_error* errPtr UNUSED) {
+ void* param UNUSED, reg_error* errPtr UNUSED) {
*obj = Tcl_NewStringObj(string, -1);
return 1;
}
@@ -323,6 +334,6 @@
int list_string_to_obj(Tcl_Obj*** objv, char** strings, int objc,
reg_error* errPtr) {
- return recast(NULL, (cast_function*)string_to_obj, (free_function*)free_obj,
+ return recast(NULL, (cast_function*)string_to_obj, NULL, (free_function*)free_obj,
(void***)objv, (void**)strings, objc, errPtr);
}
Modified: trunk/base/src/registry2.0/util.h
===================================================================
--- trunk/base/src/registry2.0/util.h 2011-12-29 23:34:47 UTC (rev 88375)
+++ trunk/base/src/registry2.0/util.h 2011-12-30 00:17:49 UTC (rev 88376)
@@ -37,6 +37,7 @@
#include <cregistry/registry.h>
#include <cregistry/entry.h>
+#include <cregistry/file.h>
typedef struct {
char* option;
@@ -45,7 +46,7 @@
#define END_FLAGS 0
-char* unique_name(Tcl_Interp* interp, char* prefix);
+char* unique_name(Tcl_Interp* interp, char* prefix, int* lower_bound);
int parse_flags(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[], int* start,
option_spec options[], int* flags);
@@ -56,23 +57,25 @@
Tcl_ObjCmdProc* proc, Tcl_CmdDeleteProc* deleteProc, reg_error* errPtr);
int set_entry(Tcl_Interp* interp, char* name, reg_entry* entry,
reg_error* errPtr);
+int set_file(Tcl_Interp* interp, char* name, reg_file* file,
+ reg_error* errPtr);
void set_sqlite_result(Tcl_Interp* interp, sqlite3* db, const char* query);
-typedef int set_object_function(Tcl_Interp* interp, char* name,
- sqlite_int64 rowid);
-int all_objects(Tcl_Interp* interp, sqlite3* db, char* query, char* prefix,
- set_object_function* setter);
-
const char* string_or_null(Tcl_Obj* obj);
-int recast(void* userdata, cast_function* fn, free_function* del, void*** outv,
- void** inv, int inc, reg_error* errPtr);
+int recast(void* userdata, cast_function* fn, void* castcalldata,
+ free_function* del, void*** outv, void** inv, int inc,
+ reg_error* errPtr);
int entry_to_obj(Tcl_Interp* interp, Tcl_Obj** obj, reg_entry* entry,
- reg_error* errPtr);
+ int* lower_bound, reg_error* errPtr);
int list_entry_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
reg_entry** entries, int entry_count, reg_error* errPtr);
+int file_to_obj(Tcl_Interp* interp, Tcl_Obj** ibj, reg_file* file,
+ 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);
void free_strings(void* userdata UNUSED, char** strings, int count);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20111229/70d9d928/attachment-0001.html>
More information about the macports-changes
mailing list