# HG changeset patch # User June Park # Date 1767490152 28800 # Node ID f07abbcd2ec561d0f7de40ba9901604af5bb23e3 # Parent 1423044e3d58bd3a5554cef282ba135dc2618c43 [HgWeb] Will probably hold off on using it since it is not urgent. diff -r 1423044e3d58 -r f07abbcd2ec5 hg-web/main.c --- a/hg-web/main.c Sat Jan 03 10:48:11 2026 -0800 +++ b/hg-web/main.c Sat Jan 03 17:29:12 2026 -0800 @@ -269,6 +269,54 @@ return ApiGetFile(req, arena); } +Seobeo_Request_Entry* ApiHgWireProtocol(Seobeo_Request_Entry *req, Dowa_Arena *arena) +{ + Seobeo_Request_Entry *resp = NULL; + + void *cmd_kv = Dowa_HashMap_Get_Ptr(req, "query_cmd"); + const char *cmd = cmd_kv ? ((Seobeo_Request_Entry*)cmd_kv)->value : ""; + if (strlen(cmd) == 0) + { + Dowa_HashMap_Push_Arena(resp, "status", "404", arena); + return resp; + } + Seobeo_Log(SEOBEO_DEBUG, "cmd: %s\n", cmd); + + char command[MAX_PATH]; + snprintf(command, sizeof(command), "hg -R %s serve --stdio 2>&1", REPO_ROOT); + + FILE *hg_pipe = popen(command, "r+"); + if (!hg_pipe) { + Seobeo_Log(SEOBEO_DEBUG, "Failed to open pipe\n"); + return resp; + } + + // 2. Write the command + fprintf(hg_pipe, "capabilities\n"); + fflush(hg_pipe); + + // 3. Read the response + int buffer_size = 1024 * 1024 * 5; + char *output = Dowa_Arena_Allocate(arena, buffer_size); + if (fgets(output, buffer_size, hg_pipe) != NULL) { + Seobeo_Log(SEOBEO_DEBUG, "SUCCESS! Received: %s\n", output); + } else { + Seobeo_Log(SEOBEO_DEBUG, "FAILURE: No output received from hg.\n"); + } + + // 4. Close and check exit code + int status = pclose(hg_pipe); + Seobeo_Log(SEOBEO_DEBUG, "Process exited with status: %d\n", status); + + Seobeo_Log(SEOBEO_DEBUG, "body: %s\n", output); + + Dowa_HashMap_Push_Arena(resp, "status", "200", arena); + Dowa_HashMap_Push_Arena(resp, "content-type", "application/mercurial-0.2", arena); + Dowa_HashMap_Push_Arena(resp, "body", output, arena); + + return resp; +} + int main(void) { Seobeo_Router_Init(); @@ -276,6 +324,9 @@ Seobeo_Router_Register("GET", "/api/repo/file", ApiGetFile); Seobeo_Router_Register("GET", "/api/repo/readme", ApiGetReadme); + Seobeo_Router_Register("GET", "/repo", ApiHgWireProtocol); + Seobeo_Router_Register("POST", "/repo", ApiHgWireProtocol); + printf("Starting on Port 6970...\n"); printf("Repository: %s\n", REPO_ROOT); diff -r 1423044e3d58 -r f07abbcd2ec5 playground/main.c --- a/playground/main.c Sat Jan 03 10:48:11 2026 -0800 +++ b/playground/main.c Sat Jan 03 17:29:12 2026 -0800 @@ -1,33 +1,74 @@ #include #include -typedef struct { - float foo; - float bar; -} Values; +#define REPO_ROOT "/Users/mrjunejune/zenbu" + +#include +#include + +void run_hg_command(FILE *hg_pipe) { + char channel; + uint32_t net_len; + + while (fread(&channel, 1, 1, hg_pipe) == 1) { + // 1. Read the 4-byte length + fread(&net_len, 4, 1, hg_pipe); + uint32_t length = ntohl(net_len); -int capacity = 20; + // 2. If it's an 'o' (output), it's the data you want + if (channel == 'o' || channel == 'e') { + char *buf = malloc(length + 1); + fread(buf, 1, length, hg_pipe); + buf[length] = '\0'; + printf("%s", buf); // This is your capability string + free(buf); + } + // 3. IF THE CHANNEL IS 'r', THE COMMAND IS DONE. STOP HERE. + else if (channel == 'r') { + int32_t result; + // The 'r' channel payload is the 4-byte return code + fread(&result, 4, 1, hg_pipe); + printf("\nCommand finished with result: %d\n", ntohl(result)); + break; // <--- THIS IS YOUR EXIT + } + } +} int main() { - int a; - void *p = malloc(sizeof(Values) + (sizeof(int) * 20)); - int *b = (int *)(p + sizeof(Values)); - Values *c = (Values *)p; - c->foo = 10.0f; - c->bar = 12.0f; - for (int i = 0; i < 20; i++) - b[i] = i; + char command[512]; + snprintf(command, sizeof(command), "hg -R %s serve --stdio", REPO_ROOT); + printf("command: %s\n", command); + + FILE *hg_pipe = popen(command, "r+"); + if (!hg_pipe) + { + printf("Failed to open pipe\n"); + return -1; + } + + fprintf(hg_pipe, "capabilities\n"); + fflush(hg_pipe); - for (int i = 0; i < 20; i++) - printf("values is %i\n", b[i]); + run_hg_command(hg_pipe); + // char *output = malloc(sizeof(char) * 2048); + // char *curr = output; + // int c; + // int number_of_breakline = 0; + // while ((c = fgetc(hg_pipe)) != NULL) + // { + // *curr++ = c; + // printf("output: %s\n", output); + // if (c == '\n') + // number_of_breakline++; + // if (number_of_breakline == 2) + // break; + // printf("char: %c\n", c); + // } + pclose(hg_pipe); - printf("c->foo: %f\n", c->foo); - printf("c->bar: %f\n", c->bar); - - Values *d = (Values *)b - 1; - printf("d->foo: %f\n", d->foo); - printf("d->bar: %f\n", d->bar); return 0; } + +