<pre style='margin:0'>
Joshua Root (jmroot) pushed a commit to branch master
in repository macports-base.

</pre>
<p><a href="https://github.com/macports/macports-base/commit/5cc31193f8da6fe8008118dbf218da91d4367a35">https://github.com/macports/macports-base/commit/5cc31193f8da6fe8008118dbf218da91d4367a35</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new 5cc3119  Allow searching registry for ports with a null attribute
</span>5cc3119 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit 5cc31193f8da6fe8008118dbf218da91d4367a35
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Wed Mar 7 05:13:02 2018 +1100

<span style='display:block; white-space:pre;color:#404040;'>    Allow searching registry for ports with a null attribute
</span>---
 src/cregistry/entry.c           |  15 +++---
 src/cregistry/entry.h           |   2 +-
 src/registry2.0/entry.c         | 103 +++++++++++++++++++++++++++++-----------
 src/registry2.0/tests/entry.tcl |   4 +-
 4 files changed, 86 insertions(+), 38 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/entry.c b/src/cregistry/entry.c
</span><span style='display:block; white-space:pre;color:#808080;'>index f82e885..63e18c6 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -396,23 +396,19 @@ static int reg_all_entries(reg_registry* reg, char* query, int query_len,
</span>  * @param [in] keys      a list of keys to search by
  * @param [in] vals      a list of values to search by, matching keys
  * @param [in] key_count the number of key/value pairs passed
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * @param [in] strategy  strategy to use (one of the `reg_strategy_*` constants)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param [in] strategies  strategies to use (one of the `reg_strategy_*` constants)
</span>  * @param [out] entries  a list of matching entries
  * @param [out] errPtr   on error, a description of the error that occurred
  * @return               the number of entries if success; false if failure
  */
 int reg_entry_search(reg_registry* reg, char** keys, char** vals, int key_count,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        int strategy, reg_entry*** entries, reg_error* errPtr) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int *strategies, reg_entry*** entries, reg_error* errPtr) {
</span>     int i;
     char* kwd = " WHERE ";
     char* query;
     size_t query_len, query_space;
     int result;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    /* get the strategy */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    char* op = reg_strategy_op(strategy, errPtr);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (op == NULL) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        return -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char* op;
</span>     /* build the query */
     query = strdup("SELECT id FROM registry.ports");
     if (!query) {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -420,6 +416,11 @@ int reg_entry_search(reg_registry* reg, char** keys, char** vals, int key_count,
</span>     }
     query_len = query_space = strlen(query);
     for (i=0; i<key_count; i++) {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* get the strategy */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        op = reg_strategy_op(strategies[i], errPtr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (op == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span>         char* 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)) {
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/entry.h b/src/cregistry/entry.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 67bbf5f..756a774 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/entry.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/entry.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -53,7 +53,7 @@ int reg_entry_delete(reg_entry* entry, reg_error* errPtr);
</span> void reg_entry_free(reg_entry* entry);
 
 int reg_entry_search(reg_registry* reg, char** keys, char** vals, int key_count,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        int strategy, reg_entry*** entries, reg_error* errPtr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int* strategies, reg_entry*** entries, reg_error* errPtr);
</span> 
 int reg_entry_imaged(reg_registry* reg, const char* name, const char* version,
         const char* revision, const char* variants, reg_entry*** entries,
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/entry.c b/src/registry2.0/entry.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 0647816..c337cc7 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -235,6 +235,7 @@ static strategy_type strategies[] = {
</span>     { "-exact",  reg_strategy_exact },
     { "-glob",   reg_strategy_glob },
     { "-regexp", reg_strategy_regexp },
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    { "-null",   reg_strategy_null },
</span>     { "--",      reg_strategy_exact },
     { NULL, 0 }
 };
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -244,11 +245,11 @@ static strategy_type strategies[] = {
</span>  *
  * Searches the registry for ports for which each key's value is equal to the
  * given value. To find all ports, call `entry search` with no key-value pairs.
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * Can be given an option of -exact, -glob, or -regexp to specify the matching
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * strategy; defaults to exact.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Can be given an option of -exact, -glob, -regexp or -null to specify the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * matching strategy; defaults to exact.
</span>  */
 static int entry_search(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    int i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int i, j;
</span>     reg_registry* reg = registry_for(interp, reg_attached);
     if ((objc > 2) && ((Tcl_GetString(objv[2])[0] == '-')
                 ? (objc % 2 == 0) : (objc % 2 == 1))) {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -259,47 +260,93 @@ static int entry_search(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
</span>     } else {
         char** keys;
         char** vals;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        int key_count = objc/2 - 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int* strats;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int key_count = 0;
</span>         reg_entry** entries;
         reg_error error;
         int entry_count;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        int start;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        int strategy;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        /* try to use strategy */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (objc > 2 && Tcl_GetString(objv[2])[0] == '-') {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            int strat_index;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if (Tcl_GetIndexFromObjStruct(interp, objv[2], strategies,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        sizeof(strategy_type), "option", 0, &strat_index)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    == TCL_ERROR) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            strategy = strategies[strat_index].strategy;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            start = 3;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            strategy = reg_strategy_exact;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            start = 2;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        /* ensure that valid search keys were used */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        for (i=start; i<objc; i+=2) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            int index;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        for (i = 2; i < objc;) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            int index, strat_index, val_length;
</span>             if (Tcl_GetIndexFromObj(interp, objv[i], entry_props, "search key",
                         0, &index) != TCL_OK) {
                 return TCL_ERROR;
             }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            /* we ate the key value */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            i++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            /* check whether there's a strategy */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (Tcl_GetString(objv[i])[0] == '-'
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    && Tcl_GetIndexFromObjStruct(interp, objv[i], strategies,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        sizeof(strategy_type), "option", 0, &strat_index)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    != TCL_ERROR) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                /* this key has a strategy specified, eat the strategy parameter */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                i++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if (strategies[strat_index].strategy != reg_strategy_null) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    /* this key must also have a value */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    if (Tcl_GetStringFromObj(objv[i], &val_length) == NULL
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            || val_length == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        Tcl_WrongNumArgs(interp, 2, objv,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                "search ?key ?options? value ...?");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    i++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                /* this key must also have a value */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if (Tcl_GetStringFromObj(objv[i], &val_length) == NULL
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        || val_length == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    Tcl_WrongNumArgs(interp, 2, objv,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            "search ?key ?options? value ...?");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                i++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            key_count++;
</span>         }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>         keys = malloc(key_count * sizeof(char*));
         vals = malloc(key_count * sizeof(char*));
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (!keys || !vals) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        strats = malloc(key_count * sizeof(int));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (!keys || !vals || !strats) {
</span>             return TCL_ERROR;
         }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        for (i=0; i<key_count; i+=1) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            keys[i] = Tcl_GetString(objv[2*i+start]);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            vals[i] = Tcl_GetString(objv[2*i+start+1]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        for (i = 2, j = 0; i < objc && j < key_count; j++) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            int strat_index;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            keys[j] = Tcl_GetString(objv[i++]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            /* try to get the strategy */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (Tcl_GetString(objv[i])[0] == '-'
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    && Tcl_GetIndexFromObjStruct(interp, objv[i], strategies,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        sizeof(strategy_type), "option", 0, &strat_index)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    != TCL_ERROR) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                /* this key has a strategy specified */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                i++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                strats[j] = strategies[strat_index].strategy;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                /* use default strategy */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                strats[j] = reg_strategy_exact;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (strats[j] != reg_strategy_null) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                vals[j] = Tcl_GetString(objv[i++]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                vals[j] = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span>         }
         entry_count = reg_entry_search(reg, keys, vals, key_count,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                strategy, &entries, &error);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                strats, &entries, &error);
</span>         free(keys);
         free(vals);
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        free(strats);
</span>         if (entry_count >= 0) {
             int retval;
             Tcl_Obj* resultObj;
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/tests/entry.tcl b/src/registry2.0/tests/entry.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 5666fa1..b93d6f4 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/tests/entry.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/tests/entry.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -71,8 +71,8 @@ proc main {pextlibname} {
</span>         # enough to ignore the zeroes
         test_set {[registry::entry search name vim version 7.1.2]} {$vim2 $vim3}
         test_set {[registry::entry search variants {}]} {$vim2 $zlib}
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        test_set {[registry::entry search -glob name vi*]} {$vim1 $vim2 $vim3}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        test_set {[registry::entry search -regexp name {zlib|pcre}]} \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        test_set {[registry::entry search name -glob vi*]} {$vim1 $vim2 $vim3}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        test_set {[registry::entry search name -regexp {zlib|pcre}]} \
</span>             {$zlib $pcre}
     }
 
</pre><pre style='margin:0'>

</pre>