static int install_local_packages() { if (-1 == fs_exists("./package.json")) { logger_error("error", "Missing package.json"); return 1; } char *json = fs_read("./package.json"); if (NULL == json) return 1; clib_package_t *pkg = clib_package_new(json, opts.verbose); if (NULL == pkg) goto e1; int rc = clib_package_install_dependencies(pkg, opts.dir, opts.verbose); if (-1 == rc) goto e2; if (opts.dev) { rc = clib_package_install_development(pkg, opts.dir, opts.verbose); if (-1 == rc) goto e2; } free(json); clib_package_free(pkg); return 0; e2: clib_package_free(pkg); e1: free(json); return 1; }
static inline int install_packages(list_t *list, const char *dir, int verbose) { if (!list || !dir) return 0; list_node_t *node; list_iterator_t *it = list_iterator_new(list, LIST_HEAD); while ((node = list_iterator_next(it))) { clib_package_dependency_t *dep = node->val; char *slug = clib_package_slug(dep->author, dep->name, dep->version); clib_package_t *pkg = clib_package_new_from_slug(slug, verbose); free(slug); if (NULL == pkg) { return -1; } int rc = clib_package_install(pkg, dir, verbose); clib_package_free(pkg); if (-1 == rc) { list_iterator_destroy(it); return -1; } } list_iterator_destroy(it); return 0; }
static inline int install_packages(list_t *list, const char *dir, int verbose) { list_node_t *node = NULL; list_iterator_t *iterator = NULL; int rc = -1; if (!list || !dir) goto cleanup; iterator = list_iterator_new(list, LIST_HEAD); if (NULL == iterator) goto cleanup; while ((node = list_iterator_next(iterator))) { clib_package_dependency_t *dep = NULL; char *slug = NULL; clib_package_t *pkg = NULL; int error = 1; dep = (clib_package_dependency_t *) node->val; slug = clib_package_slug(dep->author, dep->name, dep->version); if (NULL == slug) goto loop_cleanup; pkg = clib_package_new_from_slug(slug, verbose); if (NULL == pkg) goto loop_cleanup; if (-1 == clib_package_install(pkg, dir, verbose)) goto loop_cleanup; error = 0; loop_cleanup: if (slug) free(slug); if (pkg) clib_package_free(pkg); if (error) { list_iterator_destroy(iterator); iterator = NULL; rc = -1; goto cleanup; } } rc = 0; cleanup: if (iterator) list_iterator_destroy(iterator); return rc; }
static int install_package(const char *slug) { int rc; clib_package_t *pkg = clib_package_new_from_slug(slug, opts.verbose); if (NULL == pkg) return -1; if (pkg->install) { rc = executable(pkg); goto done; } rc = clib_package_install(pkg, opts.dir, opts.verbose); if (0 == rc && opts.dev) { rc = clib_package_install_development(pkg, opts.dir, opts.verbose); } done: clib_package_free(pkg); return rc; }
clib_package_t * clib_package_new(const char *json, int verbose) { if (!json) return NULL; clib_package_t *pkg = malloc(sizeof(clib_package_t)); if (!pkg) return NULL; JSON_Value *root = json_parse_string(json); if (!root) { clib_package_free(pkg); return NULL; } JSON_Object *json_object = json_value_get_object(root); if (!json_object) { if (verbose) clib_package_error("error", "unable to parse json"); json_value_free(root); clib_package_free(pkg); return NULL; } pkg->json = str_copy(json); pkg->name = json_object_get_string_safe(json_object, "name"); pkg->repo = NULL; pkg->repo = json_object_get_string_safe(json_object, "repo"); if (NULL != pkg->repo) { pkg->author = clib_package_parse_author(pkg->repo); // repo name may not be the package's name. for example: // stephenmathieson/str-replace.c -> str-replace pkg->repo_name = clib_package_parse_name(pkg->repo); // TODO support npm-style "repository"? } else { if (verbose) clib_package_warn("warning", "missing repo in package.json"); pkg->author = NULL; pkg->repo_name = NULL; } 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"); JSON_Array *src = json_object_get_array(json_object, "src"); if (src) { pkg->src = list_new(); if (!pkg->src) { json_value_free(root); clib_package_free(pkg); return NULL; } for (size_t i = 0; i < json_array_get_count(src); i++) { char *file = json_array_get_string_safe(src, i); if (!file) break; // TODO fail? list_node_t *node = list_node_new(file); list_rpush(pkg->src, node); } } else { pkg->src = NULL; } JSON_Object *deps = json_object_get_object(json_object, "dependencies"); pkg->dependencies = parse_package_deps(deps); JSON_Object *devs = json_object_get_object(json_object, "development"); pkg->development = parse_package_deps(devs); json_value_free(root); return pkg; }
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; }
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; }