aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/evanix.c51
-rw-r--r--src/jobs.c32
-rw-r--r--src/meson.build9
-rw-r--r--src/nix.c42
-rw-r--r--src/solver_highs.c14
5 files changed, 126 insertions, 22 deletions
diff --git a/src/evanix.c b/src/evanix.c
index 92f9596..25bbd8e 100644
--- a/src/evanix.c
+++ b/src/evanix.c
@@ -1,10 +1,12 @@
#include <errno.h>
#include <getopt.h>
+#include <nix/nix_api_value.h>
#include <stdlib.h>
#include <string.h>
#include "build.h"
#include "evanix.h"
+#include "nix.h"
#include "queue.h"
#include "solver_conformity.h"
#include "solver_highs.h"
@@ -52,6 +54,8 @@ static int evanix(char *expr);
static int evanix_free(struct evanix_opts_t *opts);
static int opts_read(struct evanix_opts_t *opts, char **expr, int argc,
char *argv[]);
+static int evanix_opts_system_set(struct evanix_opts_t *opts,
+ nix_c_context *nix_ctx);
/* This function returns errno on failure, consistent with the POSIX threads
* functions, rather than returning -errno. */
@@ -71,13 +75,42 @@ static int evanix_build_thread_create(struct build_thread *build_thread)
return 0;
}
+static int evanix_opts_system_set(struct evanix_opts_t *opts,
+ nix_c_context *nix_ctx)
+{
+ nix_err nix_ret;
+
+ if (opts->system)
+ return 0;
+
+ nix_ret = nix_setting_get(nix_ctx, "system", _nix_get_string_strdup,
+ &opts->system);
+ if (nix_ret != NIX_OK) {
+ print_err("%s", nix_err_msg(NULL, nix_ctx, NULL));
+ return -EPERM;
+ } else if (opts->system == NULL) {
+ return -EPERM;
+ }
+
+ return 0;
+}
+
static int evanix(char *expr)
{
+ nix_c_context *nix_ctx = NULL;
struct queue_thread *queue_thread = NULL;
struct build_thread *build_thread = NULL;
FILE *jobs_stream = NULL; /* nix-eval-jobs stdout */
int ret = 0;
+ ret = _nix_init(&nix_ctx);
+ if (ret < 0)
+ goto out_free;
+
+ ret = evanix_opts_system_set(&evanix_opts, nix_ctx);
+ if (ret < 0)
+ goto out_free;
+
ret = jobs_init(&jobs_stream, expr);
if (ret < 0)
goto out_free;
@@ -127,6 +160,7 @@ static int evanix(char *expr)
}
out_free:
+ nix_c_context_free(nix_ctx);
fclose(jobs_stream);
queue_thread_free(queue_thread);
free(build_thread);
@@ -182,7 +216,13 @@ static int opts_read(struct evanix_opts_t *opts, char **expr, int argc,
opts->isdryrun = true;
break;
case 's':
- opts->system = optarg;
+ opts->system = strdup(optarg);
+ if (opts->system == NULL) {
+ print_err("%s", strerror(errno));
+ ret = -errno;
+ goto out_free_evanix;
+ }
+
break;
case 'r':
opts->solver_report = true;
@@ -194,7 +234,8 @@ static int opts_read(struct evanix_opts_t *opts, char **expr, int argc,
"Try 'evanix --help' for more "
"information.\n",
c);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_free_evanix;
}
ret = sqlite3_open_v2(optarg, &opts->statistics.db,
@@ -212,7 +253,8 @@ static int opts_read(struct evanix_opts_t *opts, char **expr, int argc,
NULL);
if (ret != SQLITE_OK) {
print_err("%s", "Failed to prepare sql");
- return -EPERM;
+ ret = -EPERM;
+ goto out_free_evanix;
}
break;
@@ -351,11 +393,12 @@ static int evanix_free(struct evanix_opts_t *opts)
{
int ret;
+ free(opts->system);
+
if (opts->statistics.statement) {
sqlite3_finalize(opts->statistics.statement);
opts->statistics.statement = NULL;
}
-
if (opts->statistics.db) {
ret = sqlite3_close(opts->statistics.db);
if (ret != SQLITE_OK) {
diff --git a/src/jobs.c b/src/jobs.c
index ee9c77f..fa2e267 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -12,11 +12,12 @@
#include "jobs.h"
#include "util.h"
+#define NIX_STORE_PATH "/nix/store/"
+
#ifndef NIX_EVAL_JOBS_PATH
#warning "NIX_EVAL_JOBS_PATH not defined, evanix will rely on PATH instead"
#define NIX_EVAL_JOBS_PATH nix - eval - jobs
#endif
-
#define XSTR(x) STR(x)
#define STR(x) #x
#pragma message "NIX_EVAL_JOBS_PATH=" XSTR(NIX_EVAL_JOBS_PATH)
@@ -224,6 +225,9 @@ int job_cost(struct job *job)
int ret;
char *pname;
+ if (job->insubstituters)
+ return 0;
+
if (!evanix_opts.max_time)
return 1;
@@ -419,14 +423,20 @@ static int job_read_cache(struct job *job)
nlines = 0;
for (bool in_fetched_block = false;
getline(&line, &n, nix_build_stream) >= 0; nlines++) {
+ trimmed = trim(line);
+
if (strstr(line, "will be built")) {
continue;
} else if (strstr(line, "will be fetched")) {
in_fetched_block = true;
continue;
+ } else if (strncmp(trimmed, NIX_STORE_PATH,
+ sizeof(NIX_STORE_PATH) - 1)) {
+ /* TODO: use libstore instead
+ * */
+ continue;
}
- trimmed = trim(line);
j = job_search(job, trimmed);
if (j == NULL) {
ret = job_new(&dep_job, NULL, trimmed, NULL, job);
@@ -498,16 +508,14 @@ int job_read(FILE *stream, struct job **job)
goto out_free;
}
- if (evanix_opts.system != NULL) {
- temp = cJSON_GetObjectItemCaseSensitive(root, "system");
- if (!cJSON_IsString(temp)) {
- ret = JOB_READ_JSON_INVAL;
- goto out_free;
- }
- if (strcmp(evanix_opts.system, temp->valuestring)) {
- ret = JOB_READ_SYS_MISMATCH;
- goto out_free;
- }
+ temp = cJSON_GetObjectItemCaseSensitive(root, "system");
+ if (!cJSON_IsString(temp)) {
+ ret = JOB_READ_JSON_INVAL;
+ goto out_free;
+ }
+ if (strcmp(evanix_opts.system, temp->valuestring)) {
+ ret = JOB_READ_SYS_MISMATCH;
+ goto out_free;
}
temp = cJSON_GetObjectItemCaseSensitive(root, "name");
diff --git a/src/meson.build b/src/meson.build
index 03f045b..8a4158a 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -11,10 +11,17 @@ e = executable(
'solver_conformity.c',
'solver_highs.c',
'solver_sjf.c',
+ 'nix.c',
+ ],
+
+ dependencies: [
+ cjson_dep,
+ highs_dep,
+ sqlite_dep,
+ nix_store_dep
],
include_directories: evanix_inc,
- dependencies: [ cjson_dep, highs_dep, sqlite_dep ],
install: true,
c_args: [f'-DNIX_EVAL_JOBS_PATH=@NIX_EVAL_JOBS_PATH@'],
)
diff --git a/src/nix.c b/src/nix.c
new file mode 100644
index 0000000..f1b3a5a
--- /dev/null
+++ b/src/nix.c
@@ -0,0 +1,42 @@
+#include <errno.h>
+#include <string.h>
+
+#include "nix.h"
+#include "util.h"
+
+void _nix_get_string_strdup(const char *str, unsigned n, void *user_data)
+{
+ char **s = user_data;
+
+ *s = strndup(str, n);
+ if (*s == NULL)
+ print_err("%s", strerror(errno));
+}
+
+int _nix_init(nix_c_context **nix_ctx)
+{
+ nix_err nix_ret;
+ nix_c_context *nc;
+ int ret = 0;
+
+ nc = nix_c_context_create();
+ if (nix_ctx == NULL) {
+ print_err("%s", "Failed to create nix context");
+ return -EPERM;
+ }
+
+ nix_ret = nix_libstore_init(nc);
+ if (nix_ret != NIX_OK) {
+ print_err("%s", nix_err_msg(NULL, nc, NULL));
+ ret = -EPERM;
+ goto out_free_nc;
+ }
+
+out_free_nc:
+ if (ret < 0)
+ nix_c_context_free(nc);
+ else
+ *nix_ctx = nc;
+
+ return ret;
+}
diff --git a/src/solver_highs.c b/src/solver_highs.c
index e3b6a1f..b641e54 100644
--- a/src/solver_highs.c
+++ b/src/solver_highs.c
@@ -14,6 +14,7 @@ static int solver_highs_unwrapped(double *solution, struct job_clist *q,
{
HighsInt precedence_index[2];
double precedence_value[2];
+ int num_non_zero;
struct job *j;
int ret;
@@ -80,24 +81,27 @@ static int solver_highs_unwrapped(double *solution, struct job_clist *q,
ret = -errno;
goto out_free_col_profit;
}
- for (size_t i = 0; i < jobid->filled; i++)
- constraint_index[i] = i;
-
constraint_value = malloc(jobid->filled * sizeof(*constraint_value));
if (constraint_value == NULL) {
print_err("%s", strerror(errno));
ret = -errno;
goto out_free_col_profit;
}
+
+ num_non_zero = 0;
for (size_t i = 0; i < jobid->filled; i++) {
ret = job_cost(jobid->jobs[i]);
if (ret < 0)
return ret;
+ else if (ret == 0)
+ continue;
- constraint_value[i] = ret;
+ constraint_value[num_non_zero] = ret;
+ constraint_index[num_non_zero] = i;
+ num_non_zero++;
}
- ret = Highs_addRow(highs, 0, resources, jobid->filled, constraint_index,
+ ret = Highs_addRow(highs, 0, resources, num_non_zero, constraint_index,
constraint_value);
if (ret != kHighsStatusOk) {
print_err("%s", "highs did not return kHighsStatusOk");