core: As an experiment, handle running from a subdirectory (generally out/debug or out/release, since people tend to do that). Remove unused File.stat().
Some checks failed
Build Tilde Friends / Build-All (push) Failing after 4m49s
Some checks failed
Build Tilde Friends / Build-All (push) Failing after 4m49s
This commit is contained in:
parent
916aa5abbd
commit
192a81ede7
105
src/file.js.c
105
src/file.js.c
@ -18,21 +18,8 @@
|
||||
|
||||
static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||
static JSValue _file_read_file_zip(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||
static JSValue _file_stat(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||
static JSValue _file_stat_zip(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||
static JSValue _file_write_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||
|
||||
static double _time_spec_to_double(const uv_timespec_t* time_spec);
|
||||
static void _file_on_stat_complete(uv_fs_t* request);
|
||||
|
||||
typedef struct file_stat_t
|
||||
{
|
||||
void* _task;
|
||||
JSContext* _context;
|
||||
promiseid_t _promise;
|
||||
uv_fs_t _request;
|
||||
} file_stat_t;
|
||||
|
||||
typedef struct fs_req_t
|
||||
{
|
||||
uv_fs_t fs;
|
||||
@ -45,12 +32,11 @@ void tf_file_register(JSContext* context)
|
||||
{
|
||||
JSValue global = JS_GetGlobalObject(context);
|
||||
JSValue file = JS_NewObject(context);
|
||||
void* task = JS_GetContextOpaque(context);
|
||||
tf_task_t* task = JS_GetContextOpaque(context);
|
||||
const char* zip = tf_task_get_zip_path(task);
|
||||
JS_SetPropertyStr(context, global, "File", file);
|
||||
JS_SetPropertyStr(context, file, "readFile", JS_NewCFunction(context, zip ? _file_read_file_zip : _file_read_file, "readFile", 1));
|
||||
JS_SetPropertyStr(context, file, "writeFile", JS_NewCFunction(context, _file_write_file, "writeFile", 2));
|
||||
JS_SetPropertyStr(context, file, "stat", JS_NewCFunction(context, zip ? _file_stat_zip : _file_stat, "stat", 1));
|
||||
JS_FreeValue(context, global);
|
||||
}
|
||||
|
||||
@ -123,7 +109,7 @@ static void _file_write_open_callback(uv_fs_t* req)
|
||||
|
||||
static JSValue _file_write_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
void* task = JS_GetContextOpaque(context);
|
||||
tf_task_t* task = JS_GetContextOpaque(context);
|
||||
const char* file_name = JS_ToCString(context, argv[0]);
|
||||
|
||||
size_t size;
|
||||
@ -224,8 +210,16 @@ static void _file_read_open_callback(uv_fs_t* req)
|
||||
|
||||
static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
void* task = JS_GetContextOpaque(context);
|
||||
tf_task_t* task = JS_GetContextOpaque(context);
|
||||
const char* file_name = JS_ToCString(context, argv[0]);
|
||||
const char* actual = file_name;
|
||||
if (tf_task_get_root_path(task))
|
||||
{
|
||||
size_t size = strlen(tf_task_get_root_path(task)) + strlen(file_name) + 2;
|
||||
char* buffer = alloca(size);
|
||||
snprintf(buffer, size, "%s/%s", tf_task_get_root_path(task), file_name);
|
||||
actual = buffer;
|
||||
}
|
||||
|
||||
promiseid_t promise = -1;
|
||||
JSValue promise_value = tf_task_allocate_promise(task, &promise);
|
||||
@ -239,7 +233,7 @@ static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int ar
|
||||
.size = k_file_read_max,
|
||||
};
|
||||
memset(req + 1, 0, k_file_read_max);
|
||||
int result = uv_fs_open(tf_task_get_loop(task), &req->fs, file_name, UV_FS_O_RDONLY, 0, _file_read_open_callback);
|
||||
int result = uv_fs_open(tf_task_get_loop(task), &req->fs, actual, UV_FS_O_RDONLY, 0, _file_read_open_callback);
|
||||
if (result < 0)
|
||||
{
|
||||
tf_task_reject_promise(task, promise, JS_ThrowInternalError(context, "Failed to open %s for read: %s", file_name, uv_strerror(result)));
|
||||
@ -365,81 +359,6 @@ static JSValue _file_read_file_zip(JSContext* context, JSValueConst this_val, in
|
||||
return promise_value;
|
||||
}
|
||||
|
||||
static JSValue _file_stat(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
void* task = JS_GetContextOpaque(context);
|
||||
const char* path = JS_ToCString(context, argv[0]);
|
||||
promiseid_t promise = -1;
|
||||
JSValue promise_value = tf_task_allocate_promise(task, &promise);
|
||||
|
||||
file_stat_t* data = tf_malloc(sizeof(file_stat_t));
|
||||
data->_task = task;
|
||||
data->_promise = promise;
|
||||
data->_request.data = data;
|
||||
data->_context = context;
|
||||
|
||||
int result = uv_fs_stat(tf_task_get_loop(task), &data->_request, path, _file_on_stat_complete);
|
||||
if (result)
|
||||
{
|
||||
tf_task_reject_promise(task, promise, JS_NewInt32(context, result));
|
||||
uv_fs_req_cleanup(&data->_request);
|
||||
tf_free(data);
|
||||
}
|
||||
JS_FreeCString(context, path);
|
||||
return promise_value;
|
||||
}
|
||||
|
||||
static JSValue _file_stat_zip(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
void* task = JS_GetContextOpaque(context);
|
||||
promiseid_t promise = -1;
|
||||
JSValue promise_value = tf_task_allocate_promise(task, &promise);
|
||||
|
||||
file_stat_t* data = tf_malloc(sizeof(file_stat_t));
|
||||
data->_task = task;
|
||||
data->_promise = promise;
|
||||
data->_request.data = data;
|
||||
data->_context = context;
|
||||
|
||||
/* Ignore the requested path and stat the zip itself. */
|
||||
int result = uv_fs_stat(tf_task_get_loop(task), &data->_request, tf_task_get_zip_path(task), _file_on_stat_complete);
|
||||
if (result)
|
||||
{
|
||||
tf_task_reject_promise(task, promise, JS_NewInt32(context, result));
|
||||
uv_fs_req_cleanup(&data->_request);
|
||||
tf_free(data);
|
||||
}
|
||||
return promise_value;
|
||||
}
|
||||
|
||||
static double _time_spec_to_double(const uv_timespec_t* time_spec)
|
||||
{
|
||||
return time_spec->tv_sec + (double)(time_spec->tv_nsec) / 1e9;
|
||||
}
|
||||
|
||||
static void _file_on_stat_complete(uv_fs_t* request)
|
||||
{
|
||||
file_stat_t* data = (file_stat_t*)(request->data);
|
||||
JSContext* context = data->_context;
|
||||
|
||||
if (request->result)
|
||||
{
|
||||
tf_task_reject_promise(data->_task, data->_promise, JS_NewInt32(context, request->result));
|
||||
}
|
||||
else
|
||||
{
|
||||
JSValue result = JS_NewObject(context);
|
||||
JS_SetPropertyStr(context, result, "mtime", JS_NewFloat64(context, _time_spec_to_double(&request->statbuf.st_mtim)));
|
||||
JS_SetPropertyStr(context, result, "ctime", JS_NewFloat64(context, _time_spec_to_double(&request->statbuf.st_ctim)));
|
||||
JS_SetPropertyStr(context, result, "atime", JS_NewFloat64(context, _time_spec_to_double(&request->statbuf.st_atim)));
|
||||
JS_SetPropertyStr(context, result, "size", JS_NewFloat64(context, request->statbuf.st_size));
|
||||
tf_task_resolve_promise(data->_task, data->_promise, result);
|
||||
JS_FreeValue(context, result);
|
||||
}
|
||||
uv_fs_req_cleanup(request);
|
||||
tf_free(data);
|
||||
}
|
||||
|
||||
typedef struct _stat_t
|
||||
{
|
||||
uv_fs_t request;
|
||||
|
@ -783,13 +783,20 @@ typedef struct _http_file_t
|
||||
char etag[512];
|
||||
} http_file_t;
|
||||
|
||||
static bool _ends_with(const char* a, const char* suffix)
|
||||
{
|
||||
size_t alen = strlen(a);
|
||||
size_t suffixlen = strlen(suffix);
|
||||
return alen >= suffixlen && strcmp(a + alen - suffixlen, suffix) == 0;
|
||||
}
|
||||
|
||||
static void _httpd_endpoint_static_read(tf_task_t* task, const char* path, int result, const void* data, void* user_data)
|
||||
{
|
||||
http_file_t* file = user_data;
|
||||
tf_http_request_t* request = file->request;
|
||||
if (result >= 0)
|
||||
{
|
||||
if (strcmp(path, "core/tfrpc.js") == 0)
|
||||
if (strcmp(path, "core/tfrpc.js") == 0 || _ends_with(path, "core/tfrpc.js"))
|
||||
{
|
||||
const char* content_type = _ext_to_content_type(strrchr(path, '.'), true);
|
||||
const char* headers[] = {
|
||||
@ -931,9 +938,10 @@ static void _httpd_endpoint_static(tf_http_request_t* request)
|
||||
}
|
||||
|
||||
tf_task_t* task = request->user_data;
|
||||
size_t size = strlen(file_path) + strlen(after) + 1;
|
||||
const char* root_path = tf_task_get_root_path(task);
|
||||
size_t size = (root_path ? strlen(root_path) + 1 : 0) + strlen(file_path) + strlen(after) + 1;
|
||||
char* path = alloca(size);
|
||||
snprintf(path, size, "%s%s", file_path, after);
|
||||
snprintf(path, size, "%s%s%s%s", root_path ? root_path : "", root_path ? "/" : "", file_path, after);
|
||||
tf_http_request_ref(request);
|
||||
tf_file_stat(task, path, _httpd_endpoint_static_stat, request);
|
||||
}
|
||||
|
65
src/main.c
65
src/main.c
@ -1256,6 +1256,47 @@ static int _tf_run_task(const tf_run_args_t* args, int index)
|
||||
snprintf(db_path_buffer, sizeof(db_path_buffer), "%s.%d", args->db_path, index);
|
||||
db_path = db_path_buffer;
|
||||
}
|
||||
|
||||
char* cwd = NULL;
|
||||
if (!args->zip)
|
||||
{
|
||||
size_t cwd_size = 1;
|
||||
uv_cwd((char[1]) { 0 }, &cwd_size);
|
||||
cwd = alloca(cwd_size);
|
||||
if (uv_cwd(cwd, &cwd_size) == 0)
|
||||
{
|
||||
size_t test_path_size = cwd_size + strlen("/core/core.js");
|
||||
char* test_path = alloca(test_path_size);
|
||||
|
||||
uv_loop_t* loop = tf_task_get_loop(task);
|
||||
uv_fs_t req = { 0 };
|
||||
while (true)
|
||||
{
|
||||
snprintf(test_path, test_path_size, "%s/core/core.js", cwd);
|
||||
int r = uv_fs_access(loop, &req, test_path, 0000, NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
if (r != UV_ENOENT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
char* slash = strrchr(cwd, '/');
|
||||
if (slash)
|
||||
{
|
||||
*slash = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
tf_printf("Using %s as the working directory.\n", cwd);
|
||||
}
|
||||
if (!*cwd)
|
||||
{
|
||||
cwd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
tf_task_set_db_path(task, db_path);
|
||||
tf_task_activate(task);
|
||||
tf_ssb_set_verbose(tf_task_get_ssb(task), args->verbose);
|
||||
@ -1266,13 +1307,33 @@ static int _tf_run_task(const tf_run_args_t* args, int index)
|
||||
{
|
||||
tf_ssb_import_from_zip(tf_task_get_ssb(task), args->zip, "core", "apps");
|
||||
}
|
||||
else if (cwd)
|
||||
{
|
||||
size_t apps_path_size = strlen(cwd) + strlen("/apps") + 1;
|
||||
char* apps_path = alloca(apps_path_size);
|
||||
snprintf(apps_path, apps_path_size, "%s/apps", cwd);
|
||||
tf_ssb_import(tf_task_get_ssb(task), "core", apps_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_ssb_import(tf_task_get_ssb(task), "core", "apps");
|
||||
}
|
||||
}
|
||||
tf_ssb_set_main_thread(tf_task_get_ssb(task), true);
|
||||
if (tf_task_execute(task, args->script))
|
||||
const char* script = args->script;
|
||||
if (!script && cwd)
|
||||
{
|
||||
size_t script_size = strlen(cwd) + strlen("/core/core.js") + 1;
|
||||
char* script_buffer = alloca(script_size);
|
||||
snprintf(script_buffer, script_size, "%s/core/core.js", cwd);
|
||||
script = script_buffer;
|
||||
}
|
||||
else if (!script)
|
||||
{
|
||||
script = "core/core.js";
|
||||
}
|
||||
tf_task_set_root_path(task, cwd);
|
||||
if (tf_task_execute(task, script))
|
||||
{
|
||||
tf_task_run(task);
|
||||
result = 0;
|
||||
@ -1356,7 +1417,6 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
|
||||
const char* default_db_path = _get_db_path();
|
||||
tf_run_args_t args = {
|
||||
.count = 1,
|
||||
.script = "core/core.js",
|
||||
.http_port = 12345,
|
||||
.https_port = 12346,
|
||||
.ssb_port = 8008,
|
||||
@ -1787,7 +1847,6 @@ void tf_run_thread_start(const char* zip_path)
|
||||
tf_run_thread_data_t* data = tf_malloc(sizeof(tf_run_thread_data_t));
|
||||
tf_run_args_t args = {
|
||||
.count = 1,
|
||||
.script = "core/core.js",
|
||||
.http_port = 12345,
|
||||
.https_port = 12346,
|
||||
.ssb_port = 8008,
|
||||
|
22
src/task.c
22
src/task.c
@ -155,6 +155,7 @@ typedef struct _tf_task_t
|
||||
int _https_port;
|
||||
char _db_path[256];
|
||||
char _zip_path[256];
|
||||
char _root_path[256];
|
||||
unzFile _zip;
|
||||
const char* _args;
|
||||
|
||||
@ -363,7 +364,16 @@ static const char* _task_loadFile(tf_task_t* task, const char* fileName, size_t*
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE* file = fopen(fileName, "rb");
|
||||
const char* actual = fileName;
|
||||
if (*task->_root_path)
|
||||
{
|
||||
size_t size = strlen(task->_root_path) + strlen(fileName) + 2;
|
||||
char* buffer = alloca(size);
|
||||
snprintf(buffer, size, "%s/%s", task->_root_path, fileName);
|
||||
actual = fileName;
|
||||
}
|
||||
tf_printf("opening %s\n", actual);
|
||||
FILE* file = fopen(actual, "rb");
|
||||
if (file)
|
||||
{
|
||||
fseek(file, 0, SEEK_END);
|
||||
@ -2015,11 +2025,21 @@ void tf_task_set_zip_path(tf_task_t* task, const char* zip_path)
|
||||
}
|
||||
}
|
||||
|
||||
void tf_task_set_root_path(tf_task_t* task, const char* path)
|
||||
{
|
||||
snprintf(task->_root_path, sizeof(task->_root_path), "%s", path ? path : "");
|
||||
}
|
||||
|
||||
const char* tf_task_get_zip_path(tf_task_t* task)
|
||||
{
|
||||
return task->_zip ? task->_zip_path : NULL;
|
||||
}
|
||||
|
||||
const char* tf_task_get_root_path(tf_task_t* task)
|
||||
{
|
||||
return *task->_root_path ? task->_root_path : NULL;
|
||||
}
|
||||
|
||||
void tf_task_set_args(tf_task_t* task, const char* args)
|
||||
{
|
||||
task->_args = args;
|
||||
|
16
src/task.h
16
src/task.h
@ -112,12 +112,26 @@ void tf_task_set_db_path(tf_task_t* task, const char* path);
|
||||
void tf_task_set_zip_path(tf_task_t* task, const char* path);
|
||||
|
||||
/**
|
||||
** Get the path to the zipp file being used for static data.
|
||||
** Set the path to the root of the project directory for data.
|
||||
** @param task The task.
|
||||
** @param path The file path or NULL.
|
||||
*/
|
||||
void tf_task_set_root_path(tf_task_t* task, const char* path);
|
||||
|
||||
/**
|
||||
** Get the path to the zip file being used for static data.
|
||||
** @param task The task.
|
||||
** @return The zip file path or NULL.
|
||||
*/
|
||||
const char* tf_task_get_zip_path(tf_task_t* task);
|
||||
|
||||
/**
|
||||
** Get the path to use for reading loose files.
|
||||
** @param task The task.
|
||||
** @return The path or NULL.
|
||||
*/
|
||||
const char* tf_task_get_root_path(tf_task_t* task);
|
||||
|
||||
/**
|
||||
** Set arbitrary named arguments that will be made available to the task.
|
||||
** @param task The task.
|
||||
|
Loading…
x
Reference in New Issue
Block a user