summaryrefslogtreecommitdiff
path: root/src/jobs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/jobs.c')
-rw-r--r--src/jobs.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/jobs.c b/src/jobs.c
new file mode 100644
index 0000000..7893632
--- /dev/null
+++ b/src/jobs.c
@@ -0,0 +1,178 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cjson/cJSON.h>
+
+#include "jobs.h"
+#include "util.h"
+
+static int job_output_insert(struct job *j, char *name, char *store_path);
+
+int job_read(FILE *stream, struct job **job)
+{
+ int ret;
+ cJSON *root, *temp, *input_drvs, *array;
+ struct job *dep_job;
+ char *name = NULL;
+ char *out_name = NULL;
+ char *drv_path = NULL;
+
+ ret = json_streaming_read(stream, &root);
+ if (ret < 0)
+ return ret;
+
+ temp = cJSON_GetObjectItemCaseSensitive(root, "name");
+ if (!cJSON_IsString(temp)) {
+ ret = -EPERM;
+ goto out_free;
+ }
+ name = strdup(temp->valuestring);
+ if (name == NULL) {
+ ret = -EPERM;
+ goto out_free;
+ }
+
+ temp = cJSON_GetObjectItemCaseSensitive(root, "drvPath");
+ if (!cJSON_IsString(temp)) {
+ ret = -EPERM;
+ goto out_free;
+ }
+ drv_path = strdup(temp->valuestring);
+ if (drv_path == NULL) {
+ ret = -EPERM;
+ goto out_free;
+ }
+
+ ret = job_new(job, name, drv_path);
+ if (ret < 0)
+ goto out_free;
+
+ input_drvs = cJSON_GetObjectItemCaseSensitive(root, "inputDrvs");
+ for (temp = input_drvs; temp != NULL; temp = temp->next) {
+ array = cJSON_GetObjectItemCaseSensitive(temp, temp->string);
+ if (!cJSON_IsArray(array)) {
+ ret = -EPERM;
+ job_free(*job);
+ goto out_free;
+ }
+
+ drv_path = strdup(temp->string);
+ if (drv_path == NULL) {
+ ret = -EPERM;
+ job_free(*job);
+ goto out_free;
+ }
+
+ ret = job_new(&dep_job, NULL, drv_path);
+ if (ret < 0) {
+ ret = -EPERM;
+ job_free(*job);
+ goto out_free;
+ }
+
+ for (; array != NULL; array = array->next) {
+ out_name = strdup(array->string);
+ ret = job_output_insert(dep_job, out_name, NULL);
+ if (ret < 0) {
+ job_free(*job);
+ job_free(dep_job);
+ goto out_free;
+ }
+ }
+
+ LIST_INSERT_HEAD(&(*job)->deps, dep_job, dlist);
+ drv_path = NULL;
+ }
+
+out_free:
+ cJSON_Delete(root);
+
+ if (ret < 0) {
+ print_err("%s", "Invalid JSON");
+ free(name);
+ free(drv_path);
+ }
+ return ret;
+}
+
+void output_free(struct output *output)
+{
+ if (output == NULL)
+ return;
+
+ free(output->name);
+ free(output->store_path);
+
+ free(output);
+}
+
+void job_free(struct job *job)
+{
+ struct job *j;
+ struct output *o;
+
+ if (job == NULL)
+ return;
+
+ free(job->name);
+ free(job->drv_path);
+ free(job);
+ LIST_FOREACH (o, &job->outputs, dlist)
+ output_free(o);
+
+ LIST_FOREACH (j, &job->deps, dlist)
+ job_free(j);
+}
+
+static int job_output_insert(struct job *j, char *name, char *store_path)
+{
+ struct output *o;
+
+ o = malloc(sizeof(*o));
+ if (o == NULL) {
+ print_err("%s", strerror(errno));
+ return -errno;
+ }
+
+ o->name = name;
+ o->store_path = store_path;
+ LIST_INSERT_HEAD(&j->outputs, o, dlist);
+
+ return 0;
+}
+
+int job_new(struct job **j, char *name, char *drv_path)
+{
+ struct job *job;
+
+ job = malloc(sizeof(*job));
+ if (*j == NULL) {
+ print_err("%s", strerror(errno));
+ return -errno;
+ }
+
+ job->name = name;
+ job->drv_path = drv_path;
+ LIST_INIT(&job->deps);
+ LIST_INIT(&job->outputs);
+
+ *j = job;
+ return 0;
+}
+
+int jobs_init(FILE **stream)
+{
+ int ret;
+
+ /* TODO: proproperly handle args */
+ char *const args[] = {
+ "--flake",
+ "github:sinanmohd/evanix#packages.x86_64-linux.evanix",
+ };
+
+ /* the package is wrapProgram-ed with nix-eval-jobs */
+ ret = vpopen(stream, "nix-eval-jobs", args);
+ return ret;
+}