lucy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nwelln...@apache.org
Subject [lucy-commits] [4/4] git commit: Add field 'prereqs' to .cfp parcel definition
Date Wed, 12 Mar 2014 12:36:39 GMT
Add field 'prereqs' to .cfp parcel definition

The value is a hash where the keys are parcel names and the values are
version strings:

    "prereqs": {
        "ParcelA": "v1.2.1",
        "ParcelB": "v4.0.3"
    }


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/59ddf3ee
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/59ddf3ee
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/59ddf3ee

Branch: refs/heads/explicit-dependencies
Commit: 59ddf3ee65d712ccbb5f1deb57752624edf6da65
Parents: 5580e4a
Author: Nick Wellnhofer <wellnhofer@aevum.de>
Authored: Tue Mar 11 18:25:44 2014 +0100
Committer: Nick Wellnhofer <wellnhofer@aevum.de>
Committed: Wed Mar 12 13:31:55 2014 +0100

----------------------------------------------------------------------
 compiler/src/CFCParcel.c     | 82 +++++++++++++++++++++++++++++++++++++++
 compiler/src/CFCParcel.h     | 12 ++++++
 compiler/src/CFCTestParcel.c | 42 +++++++++++++++++++-
 3 files changed, 135 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/59ddf3ee/compiler/src/CFCParcel.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParcel.c b/compiler/src/CFCParcel.c
index 2b3bead..5ca9500 100644
--- a/compiler/src/CFCParcel.c
+++ b/compiler/src/CFCParcel.c
@@ -29,6 +29,11 @@
 #include "CFCVersion.h"
 #include "CFCUtil.h"
 
+struct CFCPrereq {
+    char *name;
+    CFCVersion *version;
+};
+
 struct CFCParcel {
     CFCBase base;
     char *name;
@@ -43,6 +48,8 @@ struct CFCParcel {
     size_t num_dependent_parcels;
     char **inherited_parcels;
     size_t num_inherited_parcels;
+    CFCPrereq **prereqs;
+    size_t num_prereqs;
 };
 
 static CFCParcel *default_parcel = NULL;
@@ -58,6 +65,9 @@ typedef struct JSONNode {
     size_t num_kids;
 } JSONNode;
 
+static void
+S_set_prereqs(CFCParcel *self, JSONNode *node, const char *path);
+
 static JSONNode*
 S_parse_json_for_parcel(const char *json);
 
@@ -251,6 +261,10 @@ CFCParcel_init(CFCParcel *self, const char *name, const char *cnick,
     self->inherited_parcels = (char**)CALLOCATE(1, sizeof(char*));
     self->num_inherited_parcels = 0;
 
+    // Initialize prereqs.
+    self->prereqs = (CFCPrereq**)CALLOCATE(1, sizeof(CFCPrereq*));
+    self->num_prereqs = 0;
+
     return self;
 }
 
@@ -266,6 +280,7 @@ S_new_from_json(const char *json, const char *path, int is_included) {
     const char *name     = NULL;
     const char *nickname = NULL;
     CFCVersion *version  = NULL;
+    JSONNode   *prereqs  = NULL;
     for (size_t i = 0, max = parsed->num_kids; i < max; i += 2) {
         JSONNode *key   = parsed->kids[i];
         JSONNode *value = parsed->kids[i + 1];
@@ -292,6 +307,12 @@ S_new_from_json(const char *json, const char *path, int is_included)
{
             }
             version = CFCVersion_new(value->string);
         }
+        else if (strcmp(key->string, "prereqs") == 0) {
+            if (value->type != JSON_HASH) {
+                CFCUtil_die("'prereqs' must be a hash (filepath %s)", path);
+            }
+            prereqs = value;
+        }
         else {
             CFCUtil_die("Unrecognized key: '%s' (filepath '%s')",
                         key->string, path);
@@ -304,12 +325,51 @@ S_new_from_json(const char *json, const char *path, int is_included)
{
         CFCUtil_die("Missing required key 'version' (filepath '%s')", path);
     }
     CFCParcel *self = CFCParcel_new(name, nickname, version, is_included);
+    if (prereqs) {
+        S_set_prereqs(self, prereqs, path);
+    }
     CFCBase_decref((CFCBase*)version);
 
     S_destroy_json(parsed);
     return self;
 }
 
+static void
+S_set_prereqs(CFCParcel *self, JSONNode *node, const char *path) {
+    size_t num_prereqs = node->num_kids / 2;
+    CFCPrereq **prereqs
+        = (CFCPrereq**)MALLOCATE((num_prereqs + 1) * sizeof(CFCPrereq*));
+
+    for (size_t i = 0; i < num_prereqs; ++i) {
+        CFCPrereq *prereq = (CFCPrereq*)MALLOCATE(sizeof(CFCPrereq));
+
+        JSONNode *key = node->kids[2*i];
+        if (key->type != JSON_STRING) {
+            CFCUtil_die("Prereq key must be a string (filepath '%s')", path);
+        }
+        prereq->name = CFCUtil_strdup(key->string);
+
+        JSONNode *value = node->kids[2*i+1];
+        if (value->type == JSON_STRING) {
+            prereq->version = CFCVersion_new(value->string);
+        }
+        else if (value->type == JSON_NULL) {
+            prereq->version = CFCVersion_new("v0");
+        }
+        else {
+            CFCUtil_die("Invalid prereq value (filepath '%s')", path);
+        }
+
+        prereqs[i] = prereq;
+    }
+    prereqs[num_prereqs] = NULL;
+
+    // Assume that prereqs are empty.
+    FREEMEM(self->prereqs);
+    self->prereqs     = prereqs;
+    self->num_prereqs = num_prereqs;
+}
+
 CFCParcel*
 CFCParcel_new_from_json(const char *json, int is_included) {
     return S_new_from_json(json, "[NULL]", is_included);
@@ -341,6 +401,13 @@ CFCParcel_destroy(CFCParcel *self) {
         FREEMEM(self->inherited_parcels[i]);
     }
     FREEMEM(self->inherited_parcels);
+    for (size_t i = 0; self->prereqs[i]; ++i) {
+        CFCPrereq *prereq = self->prereqs[i];
+        FREEMEM(prereq->name);
+        CFCBase_decref((CFCBase*)prereq->version);
+        FREEMEM(prereq);
+    }
+    FREEMEM(self->prereqs);
     CFCBase_destroy((CFCBase*)self);
 }
 
@@ -474,6 +541,21 @@ CFCParcel_inherited_parcels(CFCParcel *self) {
     return parcels;
 }
 
+CFCPrereq**
+CFCParcel_get_prereqs(CFCParcel *self) {
+    return self->prereqs;
+}
+
+const char*
+CFCPrereq_get_name(CFCPrereq *self) {
+    return self->name;
+}
+
+CFCVersion*
+CFCPrereq_get_version(CFCPrereq *self) {
+    return self->version;
+}
+
 /*****************************************************************************
  * The hack JSON parser coded up below is only meant to parse Clownfish parcel
  * file content.  It is limited in its capabilities because so little is legal

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/59ddf3ee/compiler/src/CFCParcel.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParcel.h b/compiler/src/CFCParcel.h
index d5cdb5f..aed1b57 100644
--- a/compiler/src/CFCParcel.h
+++ b/compiler/src/CFCParcel.h
@@ -37,6 +37,7 @@ extern "C" {
 #endif
 
 typedef struct CFCParcel CFCParcel;
+typedef struct CFCPrereq CFCPrereq;
 struct CFCVersion;
 
 /** Return the parcel which has been registered for <code>name</code>.
@@ -143,6 +144,17 @@ CFCParcel_dependent_parcels(CFCParcel *self);
 CFCParcel**
 CFCParcel_inherited_parcels(CFCParcel *self);
 
+/** Return a NULL-terminated array of all prerequisites.
+ */
+CFCPrereq**
+CFCParcel_get_prereqs(CFCParcel *self);
+
+const char*
+CFCPrereq_get_name(CFCPrereq *self);
+
+struct CFCVersion*
+CFCPrereq_get_version(CFCPrereq *self);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/59ddf3ee/compiler/src/CFCTestParcel.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestParcel.c b/compiler/src/CFCTestParcel.c
index d91a271..7aa96cb 100644
--- a/compiler/src/CFCTestParcel.c
+++ b/compiler/src/CFCTestParcel.c
@@ -33,7 +33,7 @@ S_run_tests(CFCTest *test);
 
 const CFCTestBatch CFCTEST_BATCH_PARCEL = {
     "Clownfish::CFC::Model::Parcel",
-    12,
+    20,
     S_run_tests
 };
 
@@ -101,6 +101,46 @@ S_run_tests(CFCTest *test) {
         CFCBase_decref((CFCBase*)parcel);
     }
 
+    {
+        const char *json =
+            "        {\n"
+            "            \"name\": \"Crustacean\",\n"
+            "            \"version\": \"v0.1.0\",\n"
+            "            \"prereqs\": {\n"
+            "                \"Clownfish\": null,\n"
+            "                \"Arthropod\": \"v30.104.5\"\n"
+            "            }\n"
+            "        }\n";
+        CFCParcel *parcel = CFCParcel_new_from_json(json, false);
+
+        CFCPrereq **prereqs = CFCParcel_get_prereqs(parcel);
+        OK(test, prereqs != NULL, "prereqs");
+
+        CFCPrereq *cfish = prereqs[0];
+        OK(test, cfish != NULL, "prereqs[0]");
+        const char *cfish_name = CFCPrereq_get_name(cfish);
+        STR_EQ(test, cfish_name, "Clownfish", "prereqs[0] name");
+        CFCVersion *v0            = CFCVersion_new("v0");
+        CFCVersion *cfish_version = CFCPrereq_get_version(cfish);
+        INT_EQ(test, CFCVersion_compare_to(cfish_version, v0), 0,
+               "prereqs[0] version");
+
+        CFCPrereq *apod = prereqs[1];
+        OK(test, apod != NULL, "prereqs[1]");
+        const char *apod_name = CFCPrereq_get_name(apod);
+        STR_EQ(test, apod_name, "Arthropod", "prereqs[1] name");
+        CFCVersion *v30_104_5    = CFCVersion_new("v30.104.5");
+        CFCVersion *apod_version = CFCPrereq_get_version(apod);
+        INT_EQ(test, CFCVersion_compare_to(apod_version, v30_104_5), 0,
+               "prereqs[1] version");
+
+        OK(test, prereqs[2] == NULL, "prereqs[2]");
+
+        CFCBase_decref((CFCBase*)v30_104_5);
+        CFCBase_decref((CFCBase*)v0);
+        CFCBase_decref((CFCBase*)parcel);
+    }
+
     CFCParcel_reap_singletons();
 }
 


Mime
View raw message