aboutsummaryrefslogblamecommitdiff
path: root/src/jobs.c
blob: 7893632aab4c88ea146a931cb61752d764d0d373 (plain) (tree)

















































































































































































                                                                             
#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;
}