#include "describe/describe.h" #include "parse-repo.h" describe("parse_repo_owner", { char *owner = NULL; it("should return NULL when given an invalid slug", { assert(NULL == parse_repo_owner(NULL, NULL)); assert(NULL == parse_repo_owner("", NULL)); assert(NULL == parse_repo_owner("/", NULL)); assert(NULL == parse_repo_owner("/@master", NULL)); assert(NULL == parse_repo_owner("@master", NULL)); }); it("should support slugs with versions", { owner = parse_repo_owner("foo/bar@*", NULL); assert_str_equal("foo", owner); free(owner); owner = parse_repo_owner("foo/bar@baz", NULL); assert_str_equal("foo", owner); free(owner); owner = parse_repo_owner("foo/[email protected]", NULL); assert_str_equal("foo", owner); free(owner); }); it("should default to the fallback for valid slugs", { owner = parse_repo_owner("bar@*", "foo");
clib_package_t * clib_package_new_from_slug(const char *slug, int verbose) { char *author = NULL; char *name = NULL; char *version = NULL; char *url = NULL; char *json_url = NULL; char *repo = NULL; http_get_response_t *res = NULL; clib_package_t *pkg = NULL; // parse chunks if (!slug) goto error; if (!(author = parse_repo_owner(slug, DEFAULT_REPO_OWNER))) goto error; if (!(name = parse_repo_name(slug))) goto error; if (!(version = parse_repo_version(slug, DEFAULT_REPO_VERSION))) goto error; if (!(url = clib_package_url(author, name, version))) goto error; if (!(json_url = clib_package_file_url(url, "package.json"))) goto error; if (!(repo = clib_package_repo(author, name))) goto error; // fetch json if (verbose) logger_info("fetch", json_url); res = http_get(json_url); if (!res || !res->ok) { logger_error("error", "unable to fetch %s", json_url); goto error; } free(json_url); json_url = NULL; free(name); name = NULL; // build package pkg = clib_package_new(res->data, verbose); http_get_free(res); res = NULL; if (!pkg) goto error; // force version number if (pkg->version) { if (0 != strcmp(version, pkg->version)) { free(pkg->version); pkg->version = version; } else { free(version); } } else { pkg->version = version; } // force package author (don't know how this could fail) if (pkg->author) { if (0 != strcmp(author, pkg->author)) { free(pkg->author); pkg->author = author; } else { free(author); } } else { pkg->author = author; } // force package repo if (pkg->repo) { if (0 != strcmp(repo, pkg->repo)) { free(pkg->repo); pkg->repo = repo; } else { free(repo); } } else { pkg->repo = repo; } pkg->url = url; return pkg; error: if (author) free(author); if (name) free(name); if (version) free(version); if (url) free(url); if (json_url) free(json_url); if (repo) free(repo); if (res) http_get_free(res); if (pkg) clib_package_free(pkg); return NULL; }
char * clib_package_parse_author(const char *slug) { return parse_repo_owner(slug, DEFAULT_REPO_OWNER); }
clib_package_t * clib_package_new(const char *json, int verbose) { clib_package_t *pkg = NULL; JSON_Value *root = NULL; JSON_Object *json_object = NULL; JSON_Array *src = NULL; JSON_Object *deps = NULL; JSON_Object *devs = NULL; int error = 1; if (!json) goto cleanup; if (!(root = json_parse_string(json))) { logger_error("error", "unable to parse json"); goto cleanup; } if (!(json_object = json_value_get_object(root))) { logger_error("error", "invalid package.json"); goto cleanup; } if (!(pkg = malloc(sizeof(clib_package_t)))) goto cleanup; memset(pkg, '\0', sizeof(clib_package_t)); pkg->json = str_copy(json); pkg->name = json_object_get_string_safe(json_object, "name"); pkg->repo = json_object_get_string_safe(json_object, "repo"); pkg->version = json_object_get_string_safe(json_object, "version"); pkg->license = json_object_get_string_safe(json_object, "license"); pkg->description = json_object_get_string_safe(json_object, "description"); pkg->install = json_object_get_string_safe(json_object, "install"); // TODO npm-style "repository" (thlorenz/gumbo-parser.c#1) if (pkg->repo) { pkg->author = parse_repo_owner(pkg->repo, DEFAULT_REPO_OWNER); // repo name may not be package name (thing.c -> thing) pkg->repo_name = parse_repo_name(pkg->repo); } else { if (verbose) logger_warn("warning", "missing repo in package.json"); pkg->author = NULL; pkg->repo_name = NULL; } if ((src = json_object_get_array(json_object, "src"))) { if (!(pkg->src = list_new())) goto cleanup; pkg->src->free = free; for (unsigned int i = 0; i < json_array_get_count(src); i++) { char *file = json_array_get_string_safe(src, i); if (!file) goto cleanup; if (!(list_rpush(pkg->src, list_node_new(file)))) goto cleanup; } } else { pkg->src = NULL; } if ((deps = json_object_get_object(json_object, "dependencies"))) { if (!(pkg->dependencies = parse_package_deps(deps))) { goto cleanup; } } else { pkg->dependencies = NULL; } if ((devs = json_object_get_object(json_object, "development"))) { if (!(pkg->development = parse_package_deps(devs))) { goto cleanup; } } else { pkg->development = NULL; } error = 0; cleanup: if (root) json_value_free(root); if (error && pkg) { clib_package_free(pkg); pkg = NULL; } return pkg; }