changeset 108:f07abbcd2ec5

[HgWeb] Will probably hold off on using it since it is not urgent.
author June Park <parkjune1995@gmail.com>
date Sat, 03 Jan 2026 17:29:12 -0800
parents 1423044e3d58
children 1c446ab6f945
files hg-web/main.c playground/main.c
diffstat 2 files changed, 113 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- 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);
 
--- 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 <stdio.h>
 #include <stdlib.h>
 
-typedef struct {
-  float foo;
-  float bar;
-} Values;
+#define REPO_ROOT "/Users/mrjunejune/zenbu"
+
+#include <stdint.h>
+#include <arpa/inet.h>
+
+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;
 }
+
+