summaryrefslogblamecommitdiff
path: root/src/jobs.c
blob: 0f5ef67c23c4699950dd3e6ac72a964a212059e9 (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                        
                                               


                                                                          
 
                                              
 

                           
 

                                 
 

                     
 







                                                                         

         


                                                
 













                                                                       

                                            


                                      
                                             

                                       





                                                        




                                                            

                                               


                                              

                                                                         




                                                  
                                
                                









                                                             

         










                                                            

                                       


                                      
                                                  

                                       


                                      
                                                                 

                                     


                                      

                                

         
         
                      
                               
                               
         

                 

 
                                            
 
                    
 



                              
 

























































                                                                   











                              
 




                                              

                  

 




                                                       
                          


















                                                 
                                
                          

                                                                





                                                               
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <cjson/cJSON.h>

#include "jobs.h"
#include "util.h"

static void output_free(struct output *output);
static int job_output_insert(struct job *j, char *name, char *store_path);
static int job_read_inputdrvs(struct job *job, cJSON *input_drvs);
static int job_read_outputs(struct job *job, cJSON *outputs);

static void output_free(struct output *output)
{
	if (output == NULL)
		return;

	free(output->name);
	free(output->store_path);

	free(output);
}

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

static int job_read_inputdrvs(struct job *job, cJSON *input_drvs)
{
	cJSON *array;

	int ret = 0;
	struct job *dep_job = NULL;
	char *drv_path = NULL;
	char *out_name = NULL;

	for (cJSON *i = input_drvs; i != NULL; i = i->next) {
		array = cJSON_GetObjectItemCaseSensitive(i, i->string);
		if (!cJSON_IsArray(array)) {
			ret = -EPERM;
			goto out_free;
		}

		drv_path = strdup(i->string);
		if (drv_path == NULL) {
			ret = -EPERM;
			goto out_free;
		}

		ret = job_new(&dep_job, NULL, drv_path);
		if (ret < 0) {
			ret = -EPERM;
			goto out_free;
		}

		for (; array != NULL; array = array->next) {
			out_name = strdup(array->string);
			if (out_name == NULL) {
				ret = -EPERM;
				goto out_free;
			}

			ret = job_output_insert(dep_job, out_name, NULL);
			if (ret < 0) {
				job_free(dep_job);
				goto out_free;
			}
		}

		drv_path = NULL;
		out_name = NULL;
		dep_job = NULL;

		LIST_INSERT_HEAD(&job->deps, dep_job, dlist);
	}

out_free:
	if (ret < 0) {
		job_free(dep_job);
		free(drv_path);
		free(out_name);
	}

	return ret;
}

static int job_read_outputs(struct job *job, cJSON *outputs)
{
	int ret = 0;
	char *out_name = NULL;
	char *out_path = NULL;

	for (cJSON *i = outputs; i != NULL; i = i->next) {
		out_name = strdup(i->string);
		if (out_name == NULL) {
			ret = -EPERM;
			goto out_free;
		}

		out_path = strdup(i->valuestring);
		if (out_path == NULL) {
			ret = -EPERM;
			goto out_free;
		}

		ret = job_output_insert(job, out_name, out_path);
		if (ret < 0) {
			ret = -EPERM;
			goto out_free;
		}

		out_path = NULL;
		out_name = NULL;
	}

out_free:
	if (ret < 0) {
		free(out_name);
		free(out_path);
	}

	return 0;
}

int job_read(FILE *stream, struct job **job)
{
	cJSON *temp;

	int ret = 0;
	cJSON *root = NULL;
	char *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;

	temp = cJSON_GetObjectItemCaseSensitive(root, "inputDrvs");
	if (!cJSON_IsObject(temp)) {
		ret = -EPERM;
		goto out_free;
	}
	ret = job_read_inputdrvs(*job, temp);
	if (ret < 0)
		goto out_free;

	temp = cJSON_GetObjectItemCaseSensitive(root, "outputs");
	if (!cJSON_IsObject(temp)) {
		ret = -EPERM;
		goto out_free;
	}
	ret = job_read_outputs(*job, temp);
	if (ret < 0)
		goto out_free;

out_free:
	cJSON_Delete(root);
	if (ret < 0) {
		print_err("%s", "Invalid JSON");

		free(name);
		free(drv_path);
	}

	return ret;
}

void job_free(struct job *job)
{
	struct job *j;
	struct output *o;

	if (job == NULL)
		return;

	free(job->name);
	free(job->drv_path);

	LIST_FOREACH (o, &job->outputs, dlist)
		output_free(o);

	LIST_FOREACH (j, &job->deps, dlist)
		job_free(j);

	free(job);
}

int job_new(struct job **j, char *name, char *drv_path)
{
	struct job *job;

	job = malloc(sizeof(*job));
	if (job == 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[] = {
		"nix-eval-jobs",
		"--flake",
		"github:sinanmohd/evanix#packages.x86_64-linux",
		NULL,
	};

	/* the package is wrapProgram-ed with nix-eval-jobs  */
	ret = vpopen(stream, "nix-eval-jobs", args);
	return ret;
}