You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2014/03/12 13:36:38 UTC
[lucy-commits] [3/4] git commit: Verify prerequisite parcels
Verify prerequisite parcels
Recursively check that all prerequisite parcels were found and match the
required version. All visited parcels are marked with a 'required' flag.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/3e08f203
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/3e08f203
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/3e08f203
Branch: refs/heads/explicit-dependencies
Commit: 3e08f203a9d148c119122f8956b690a2e77a5338
Parents: 59ddf3e
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue Mar 11 20:06:34 2014 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed Mar 12 13:31:55 2014 +0100
----------------------------------------------------------------------
compiler/src/CFCHierarchy.c | 24 ++++++++++++++++++++++
compiler/src/CFCParcel.c | 43 ++++++++++++++++++++++++++++++++++++++-
compiler/src/CFCParcel.h | 12 +++++++++++
compiler/src/CFCTestParcel.c | 35 +++++++++++++++++++++++++++++--
4 files changed, 111 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e08f203/compiler/src/CFCHierarchy.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCHierarchy.c b/compiler/src/CFCHierarchy.c
index c5ce5ec..af03016 100644
--- a/compiler/src/CFCHierarchy.c
+++ b/compiler/src/CFCHierarchy.c
@@ -67,6 +67,9 @@ static void
S_parse_parcel_files(const char *path, void *context);
static void
+S_check_prereqs(void);
+
+static void
S_do_make_path(const char *path);
static void
@@ -189,6 +192,7 @@ CFCHierarchy_add_include_dir(CFCHierarchy *self, const char *include_dir) {
void
CFCHierarchy_build(CFCHierarchy *self) {
+ // Read .cfp files.
CFCParseParcelFilesContext context;
context.is_included = false;
for (size_t i = 0; self->sources[i] != NULL; i++) {
@@ -198,15 +202,21 @@ CFCHierarchy_build(CFCHierarchy *self) {
for (size_t i = 0; self->includes[i] != NULL; i++) {
CFCUtil_walk(self->includes[i], S_parse_parcel_files, &context);
}
+
+ S_check_prereqs();
+
+ // Read .cfh files.
for (size_t i = 0; self->sources[i] != NULL; i++) {
S_parse_cf_files(self, self->sources[i], 0);
}
for (size_t i = 0; self->includes[i] != NULL; i++) {
S_parse_cf_files(self, self->includes[i], 1);
}
+
for (int i = 0; self->classes[i] != NULL; i++) {
CFCClass_resolve_types(self->classes[i], self->classes);
}
+
S_connect_classes(self);
for (size_t i = 0; self->trees[i] != NULL; i++) {
CFCClass_grow_tree(self->trees[i]);
@@ -251,6 +261,20 @@ S_parse_parcel_files(const char *path, void *arg) {
}
static void
+S_check_prereqs() {
+ CFCParcel **parcels = CFCParcel_all_parcels();
+
+ for (int i = 0; parcels[i]; ++i) {
+ CFCParcel *parcel = parcels[i];
+ if (!CFCParcel_included(parcel)) {
+ CFCParcel_check_prereqs(parcel);
+ }
+ }
+
+ FREEMEM(parcels);
+}
+
+static void
S_find_cfh(const char *path, void *context) {
char ***cfh_ptr = (char***)context;
char **cfh_list = *cfh_ptr;
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e08f203/compiler/src/CFCParcel.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParcel.c b/compiler/src/CFCParcel.c
index 5ca9500..5217ff0 100644
--- a/compiler/src/CFCParcel.c
+++ b/compiler/src/CFCParcel.c
@@ -44,6 +44,7 @@ struct CFCParcel {
char *PREFIX;
char *privacy_sym;
int is_included;
+ int is_required;
char **dependent_parcels;
size_t num_dependent_parcels;
char **inherited_parcels;
@@ -252,8 +253,9 @@ CFCParcel_init(CFCParcel *self, const char *name, const char *cnick,
}
self->privacy_sym[privacy_sym_len] = '\0';
- // Set is_included.
+ // Initialize flags.
self->is_included = is_included;
+ self->is_required = false;
// Initialize dependencies.
self->dependent_parcels = (char**)CALLOCATE(1, sizeof(char*));
@@ -470,6 +472,11 @@ CFCParcel_included(CFCParcel *self) {
return self->is_included;
}
+int
+CFCParcel_required(CFCParcel *self) {
+ return self->is_required;
+}
+
void
CFCParcel_add_dependent_parcel(CFCParcel *self, CFCParcel *dependent) {
const char *name = CFCParcel_get_name(self);
@@ -546,6 +553,40 @@ CFCParcel_get_prereqs(CFCParcel *self) {
return self->prereqs;
}
+void
+CFCParcel_check_prereqs(CFCParcel *self) {
+ // This is essentially a depth-first search of the dependency graph.
+
+ if (self->is_required) { return; }
+ self->is_required = true;
+
+ const char *name = CFCParcel_get_name(self);
+
+ for (int i = 0; self->prereqs[i]; ++i) {
+ CFCPrereq *prereq = self->prereqs[i];
+
+ const char *req_name = CFCPrereq_get_name(prereq);
+ CFCParcel *req_parcel = CFCParcel_fetch(req_name);
+ if (!req_parcel) {
+ // TODO: Add include path to error message.
+ CFCUtil_die("Parcel '%s' required by '%s' not found", req_name,
+ name);
+ }
+
+ CFCVersion *version = req_parcel->version;
+ CFCVersion *req_version = CFCPrereq_get_version(prereq);
+ if (CFCVersion_compare_to(version, req_version) < 0) {
+ const char *vstring = CFCVersion_get_vstring(version);
+ const char *req_vstring = CFCVersion_get_vstring(req_version);
+ CFCUtil_die("Version %s of parcel '%s' required by '%s' is lower"
+ " than required version %s",
+ vstring, req_name, name, req_vstring);
+ }
+
+ CFCParcel_check_prereqs(req_parcel);
+ }
+}
+
const char*
CFCPrereq_get_name(CFCPrereq *self) {
return self->name;
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e08f203/compiler/src/CFCParcel.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParcel.h b/compiler/src/CFCParcel.h
index aed1b57..b64d8e2 100644
--- a/compiler/src/CFCParcel.h
+++ b/compiler/src/CFCParcel.h
@@ -121,6 +121,12 @@ CFCParcel_get_privacy_sym(CFCParcel *self);
int
CFCParcel_included(CFCParcel *self);
+/** Return true if the parcel is required. This is only valid after all
+ * prerequisites were checked.
+ */
+int
+CFCParcel_required(CFCParcel *self);
+
/** Add another Parcel that the Parcel depends on.
*/
void
@@ -149,6 +155,12 @@ CFCParcel_inherited_parcels(CFCParcel *self);
CFCPrereq**
CFCParcel_get_prereqs(CFCParcel *self);
+/** Recursively verify that all prerequisite parcels are present in the
+ * required version. Mark all needed parcels including 'self' as required.
+ */
+void
+CFCParcel_check_prereqs(CFCParcel *self);
+
const char*
CFCPrereq_get_name(CFCPrereq *self);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e08f203/compiler/src/CFCTestParcel.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestParcel.c b/compiler/src/CFCTestParcel.c
index 7aa96cb..f160cc8 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",
- 20,
+ 23,
S_run_tests
};
@@ -99,6 +99,7 @@ S_run_tests(CFCTest *test) {
CFCBase_decref((CFCBase*)thing);
CFCBase_decref((CFCBase*)parcel);
+ CFCParcel_reap_singletons();
}
{
@@ -141,6 +142,36 @@ S_run_tests(CFCTest *test) {
CFCBase_decref((CFCBase*)parcel);
}
- CFCParcel_reap_singletons();
+ {
+ CFCParcel *foo = CFCParcel_new("Foo", NULL, NULL, true);
+ CFCParcel_register(foo);
+
+ CFCVersion *cfish_version = CFCVersion_new("v0.8.7");
+ CFCParcel *cfish
+ = CFCParcel_new("Clownfish", NULL, cfish_version, true);
+ CFCParcel_register(cfish);
+
+ const char *crust_json =
+ " {\n"
+ " \"name\": \"Crustacean\",\n"
+ " \"version\": \"v0.1.0\",\n"
+ " \"prereqs\": {\n"
+ " \"Clownfish\": \"v0.8.5\",\n"
+ " }\n"
+ " }\n";
+ CFCParcel *crust = CFCParcel_new_from_json(crust_json, false);
+ CFCParcel_register(crust);
+
+ CFCParcel_check_prereqs(crust);
+ INT_EQ(test, CFCParcel_required(foo), false, "parcel not required");
+ INT_EQ(test, CFCParcel_required(cfish), true, "prereq required");
+ INT_EQ(test, CFCParcel_required(crust), true, "self required");
+
+ CFCBase_decref((CFCBase*)crust);
+ CFCBase_decref((CFCBase*)cfish_version);
+ CFCBase_decref((CFCBase*)cfish);
+ CFCBase_decref((CFCBase*)foo);
+ CFCParcel_reap_singletons();
+ }
}