-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathnode_check.c
More file actions
140 lines (119 loc) · 3.57 KB
/
Copy pathnode_check.c
File metadata and controls
140 lines (119 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#ifndef _AMALGAMATE_
#include "script.h"
#include "env.h"
#include "log.h"
#include "pool.h"
#include "paths.h"
#include "spawn.h"
#include "deps.h"
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#endif
static void _check_stdout_handler(char *buf, size_t buflen, struct spawn *s) {
fprintf(stdout, "%s", buf);
}
static void _check_stderr_handler(char *buf, size_t buflen, struct spawn *s) {
fprintf(stderr, "%s", buf);
}
static void _check_on_env_value(struct node_resolve *nr, const char *key, const char *val) {
struct unit *unit = nr->user_data;
akassert(unit->n);
if (g_env.verbose) {
akinfo("%s %s=%s", unit->rel_path, key, val);
}
node_env_set(unit->n, key, val);
}
static void _check_on_resolve(struct node_resolve *r) {
struct unit *unit = r->user_data;
struct node *n = unit->n;
const char *path = unit->impl;
// Good, now add dependency on itself
struct deps deps;
int rc = deps_open(r->deps_path_tmp, 0, &deps);
if (rc) {
node_fatal(rc, unit->n, "Failed to open depencency file: %s", r->deps_path_tmp);
}
struct spawn *s = spawn_create(path, unit);
spawn_set_stdout_handler(s, _check_stdout_handler);
spawn_set_stderr_handler(s, _check_stderr_handler);
for (struct node *nn = n->child; nn; nn = nn->next) {
if (node_is_can_be_value(nn)) {
spawn_arg_add(s, node_value(nn));
}
}
rc = spawn_do(s);
if (rc) {
node_fatal(rc, n, "%s", path);
} else {
int code = spawn_exit_code(s);
if (code != 0) {
node_fatal(AK_ERROR_EXTERNAL_COMMAND, n, "%s: %d", path, code);
}
}
spawn_destroy(s);
deps_add(&deps, DEPS_TYPE_FILE, 0, path, 0);
for (int i = 0; i < r->node_val_deps.num; ++i) {
struct node *nv = *(struct node**) ulist_get(&r->node_val_deps, i);
const char *val = node_value(nv);
if (val) {
deps_add(&deps, DEPS_TYPE_NODE_VALUE, 0, val, i);
}
}
deps_close(&deps);
}
static char* _resolve_check_path(struct pool *pool, struct node *n, const char *script, struct unit **out_u) {
*out_u = 0;
char buf[PATH_MAX];
for (int i = (int) g_env.stack_units.num - 1; i >= 0; --i) {
struct unit_ctx *c = (struct unit_ctx*) ulist_get(&g_env.stack_units, i);
struct unit *u = c->unit;
snprintf(buf, sizeof(buf), "%s/.autark/%s", u->dir, script);
if (path_is_exist(buf)) {
*out_u = u;
return pool_strdup(pool, buf);
}
}
node_fatal(AK_ERROR_FAIL, n, "Check script not found: %s", script);
return 0;
}
static void _check_script(struct node *n) {
const char *script = node_value(n);
if (g_env.verbose) {
node_info(n->parent, "%s", script);
}
struct unit *parent = 0;
struct pool *pool = pool_create(on_unit_pool_destroy);
char *path = _resolve_check_path(pool, n, script, &parent);
const char *vpath = pool_printf(pool, "%s/.autark/%s", parent->dir, n->vfile);
struct unit *unit = unit_create(vpath, 0, pool);
unit->n = n;
unit->impl = path;
unit_push(unit, n);
struct node_resolve r = {
.n = n,
.mode = NODE_RESOLVE_ENV_ALWAYS,
.path = n->vfile,
.user_data = unit,
.on_env_value = _check_on_env_value,
.on_resolve = _check_on_resolve,
.node_val_deps = { .usize = sizeof(struct node*) },
};
for (struct node *nn = n->child; nn; nn = nn->next) {
if (node_is_value_may_be_dep_saved(nn, 0)) {
ulist_push(&r.node_val_deps, &nn);
}
}
node_resolve(&r);
unit_pop();
pool_destroy(pool);
}
static void _check_init(struct node *n) {
for (struct node *nn = n->child; nn; nn = nn->next) {
_check_script(nn);
}
}
int node_check_setup(struct node *n) {
n->init = _check_init;
return 0;
}