From cc02eba1d357dde0132593649c67a194750fe37d Mon Sep 17 00:00:00 2001
From: sinanmohd <sinan@sinanmohd.com>
Date: Tue, 25 Jun 2024 10:09:51 +0530
Subject: jobs: check cache status of derivations

---
 include/jobs.h |  2 ++
 src/jobs.c     | 39 ++++++++++++++++++++++++++++++++++++++-
 src/queue.c    |  3 ++-
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/include/jobs.h b/include/jobs.h
index 2357680..11f6b01 100644
--- a/include/jobs.h
+++ b/include/jobs.h
@@ -11,6 +11,7 @@ struct output {
 struct job {
 	char *name, *drv_path;
 	bool transitive;
+	bool insubstituters;
 
 	size_t outputs_size, outputs_filled;
 	struct output **outputs;
@@ -30,6 +31,7 @@ typedef enum {
 	JOB_READ_EOF = 1,
 	JOB_READ_EVAL_ERR = 2,
 	JOB_READ_JSON_INVAL = 3,
+	JOB_READ_CACHED = 4,
 } job_read_state_t;
 int job_read(FILE *stream, struct job **jobs);
 
diff --git a/src/jobs.c b/src/jobs.c
index 22d2b1c..d303fed 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -1,4 +1,5 @@
 #include <errno.h>
+#include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -204,6 +205,32 @@ static int job_read_outputs(struct job *job, cJSON *outputs)
 	return 0;
 }
 
+static int job_read_cache(struct job *job, cJSON *is_cached)
+{
+	int ret;
+
+	if (cJSON_IsFalse(is_cached)) {
+		job->insubstituters = false;
+		return JOB_READ_SUCCESS;
+	}
+
+	for (size_t i = 0; i < job->outputs_filled; i++) {
+		ret = access(job->outputs[i]->store_path, F_OK);
+		if (ret == 0)
+			continue;
+
+		if (errno == ENOENT || errno == ENOTDIR) {
+			job->insubstituters = true;
+			return JOB_READ_SUCCESS;
+		} else {
+			print_err("%s", strerror(errno));
+			return --errno;
+		}
+	}
+
+	return JOB_READ_CACHED;
+}
+
 int job_read(FILE *stream, struct job **job)
 {
 	cJSON *temp;
@@ -263,6 +290,15 @@ int job_read(FILE *stream, struct job **job)
 	if (ret < 0)
 		goto out_free;
 
+	temp = cJSON_GetObjectItemCaseSensitive(root, "isCached");
+	if (!cJSON_IsBool(temp)) {
+		ret = JOB_READ_JSON_INVAL;
+		goto out_free;
+	}
+	ret = job_read_cache(j, temp);
+	if (ret < 0)
+		goto out_free;
+
 out_free:
 	cJSON_Delete(root);
 	if (ret != JOB_READ_SUCCESS)
@@ -366,11 +402,12 @@ out_free_job:
 int jobs_init(FILE **stream, char *expr)
 {
 	size_t argindex;
-	char *args[4];
+	char *args[5];
 	int ret;
 
 	argindex = 0;
 	args[argindex++] = "nix-eval-jobs";
+	args[argindex++] = "--check-cache-status";
 	if (evanix_opts.isflake)
 		args[argindex++] = "--flake";
 	args[argindex++] = expr;
diff --git a/src/queue.c b/src/queue.c
index d895ebc..a5b4d6a 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -66,7 +66,8 @@ void *queue_thread_entry(void *queue_thread)
 			ret = 0;
 			break;
 		} else if (ret == JOB_READ_EVAL_ERR ||
-			   ret == JOB_READ_JSON_INVAL) {
+			   ret == JOB_READ_JSON_INVAL ||
+			   ret == JOB_READ_CACHED) {
 			continue;
 		} else if (ret == JOB_READ_SUCCESS) {
 			queue_push(qt->queue, job);
-- 
cgit v1.2.3