summaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
authorSadeep Madurange <sadeep@asciimx.com>2026-03-12 23:06:40 +0800
committerSadeep Madurange <sadeep@asciimx.com>2026-03-12 23:06:40 +0800
commitb200dd2a15365007b5ea64dff4df3e29273b2212 (patch)
tree1e5430f44c7de2378298945a42847f7a3ebfa8ec /main.c
parentc76dfbea014f756d08bf8d1abed3daaed5f87809 (diff)
downloadcvn-b200dd2a15365007b5ea64dff4df3e29273b2212.tar.gz
Use diff for status.
Diffstat (limited to 'main.c')
-rw-r--r--main.c227
1 files changed, 40 insertions, 187 deletions
diff --git a/main.c b/main.c
index 32232c5..cdf1340 100644
--- a/main.c
+++ b/main.c
@@ -1,30 +1,20 @@
#include <err.h>
#include <errno.h>
-#include <fcntl.h>
#include <ftw.h>
-#include <sha1.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/wait.h>
-#include "mem.h"
-#include "stack.h"
+#define PATCH_DIR ".cvn"
+#define BASE PATCH_DIR "/base"
-#define CVN ".cvn"
-#define INDEX CVN "/index"
-
-#define MAX_DEPTH 256
-#define HASH_INPUT_LEN 4096
-#define HASH_LEN SHA1_DIGEST_LENGTH
+#define EXCLUDE_PATHS ".cvnignore"
static inline void init(int argc, char *argv[]);
static inline void status(int argc, char *argv[]);
-static inline void scan_index(void);
-static inline void scan_wtree(void);
-static inline int ignore(const char *path);
-
struct command {
char *name;
void (*func)(int argc, char *argv[]);
@@ -54,7 +44,7 @@ int main(int argc, char *argv[])
static inline void init(int argc, char *argv[])
{
- int opt, fd;
+ int opt;
char *branch;
optind = 1;
@@ -68,191 +58,54 @@ static inline void init(int argc, char *argv[])
}
}
- if (mkdir(CVN, 0755) == -1) {
+ if (mkdir(PATCH_DIR, 0755) == -1) {
if (errno != EEXIST)
err(1, "Failed to create repository");
}
- if ((fd = open(INDEX, O_WRONLY | O_CREAT | O_EXCL, 0644)) == -1) {
+ if (mkdir(BASE, 0755) == -1) {
if (errno != EEXIST)
- err(1, "Failed to create index");
- } else
- close(fd);
+ err(1, "Failed to create base directory.");
+ }
- printf("Initialized repository in %s\n", CVN);
+ printf("Ready\n");
}
static inline void status(int argc, char *argv[])
{
- scan_index();
- scan_wtree();
-}
-
-static inline void scan_index(void)
-{
- int fd;
- FILE *fp;
- char *line;
- size_t len;
+ pid_t pid;
+ int status;
+ int pipefd[2];
+ char buf[1024];
ssize_t bytes_read;
- if ((fd = open(INDEX, O_RDONLY)) == -1)
- err(1, "Failed to open index");
-
- if (!(fp = fdopen(fd, "r")))
- err(1, "fdopen");
-
- while ((bytes_read = getline(&line, &len, fp)) != -1) {
- printf("idx: %s (%zu)\n", line, bytes_read);
- }
-
- if (bytes_read == -1 && ferror(fp))
- err(1, "Failed to read %s", INDEX);
-}
-
-struct hashed_file {
- char *name;
- uint8_t hash[HASH_LEN];
-};
-
-static char hash_input[HASH_INPUT_LEN];
-static struct stack *hash_at_level[MAX_DEPTH] = {0};
-
-static inline void print_hash(const uint8_t hash[HASH_LEN],
- const char *path)
-{
- printf("0x");
- for (int i = 0; i < HASH_LEN; i++)
- printf("%02x", hash[i]);
- printf(": %s\n", path);
-}
-
-static inline void insert_hash(size_t level, const char *filename,
- const uint8_t *hash)
-{
- struct stack *st;
- struct hashed_file *hf;
-
- if (level >= 0) {
- hf = MALLOC(sizeof(struct hashed_file));
- hf->name = strdup(filename);
- memcpy(hf->hash, hash, HASH_LEN);
- st = hash_at_level[level];
- if (st)
- push(st, (void *)hf);
- else {
- st = MALLOC(sizeof(struct stack));
- stack_alloc(st);
- push(st, (void *)hf);
- hash_at_level[level] = st;
+ if (pipe(pipefd) == -1)
+ err(1, "pipe()");
+
+ if ((pid = fork()) == -1)
+ err(1, "fork()");
+
+ if (pid == 0) {
+ close(pipefd[0]);
+ dup2(pipefd[1], STDOUT_FILENO);
+ close(pipefd[1]);
+ if (access(EXCLUDE_PATHS, F_OK) == 0) {
+ char *args[] = {"diff", "-x", PATCH_DIR, "-X",
+ EXCLUDE_PATHS, "-rq", BASE, ".", NULL};
+ execvp("diff", args);
+ } else {
+ char *args[] = {"diff", "-x", PATCH_DIR, "-rq", BASE, ".", NULL};
+ execvp("diff", args);
}
- }
-}
-
-void hash_file(const char *path, uint8_t *hash)
-{
- int fd;
- SHA1_CTX ctx;
- ssize_t bytes_read;
-
- if ((fd = open(path, O_RDONLY)) == -1)
- err(1, "Failed to open %s", path);
-
- SHA1Init(&ctx);
- while ((bytes_read = read(fd, hash_input, sizeof(hash_input))) > 0)
- SHA1Update(&ctx, hash_input, (size_t)bytes_read);
- if (bytes_read == -1)
- err(1, "Failed to read %s", path);
-
- SHA1Final(hash, &ctx);
- close(fd);
-}
-
-void hash_path(const char *path, uint8_t *hash)
-{
- SHA1_CTX ctx;
- ssize_t lnk_len;
-
- lnk_len = readlink(path, hash_input, HASH_INPUT_LEN - 1);
- if (lnk_len == -1)
- err(1, "readlink failed for %s", path);
- hash_input[lnk_len] = '\0';
-
- SHA1Init(&ctx);
- SHA1Update(&ctx, hash_input, lnk_len);
- SHA1Final(hash, &ctx);
-}
-
-int compare_items(const void *a, const void *b) {
- const void *pa = *(const void **)a;
- const void *pb = *(const void **)b;
-
- const struct hashed_file *hfa = (const struct hashed_file *)pa;
- const struct hashed_file *hfb = (const struct hashed_file *)pb;
-
- return strcmp(hfb->name, hfa->name);
-}
-
-static inline void hash_dir(size_t level, uint8_t *hash)
-{
- SHA1_CTX ctx;
- struct stack *st;
- struct hashed_file *hf;
-
- st = hash_at_level[level];
- if (st && st->len > 0) {
- SHA1Init(&ctx);
- qsort(st->items, st->len, sizeof(st->items[0]), compare_items);
- while (st->len > 0) {
- hf = pop(st);
- SHA1Update(&ctx, hf->hash, HASH_LEN);
- free(hf->name);
- free(hf);
+ err(1, "execvp");
+ } else {
+ waitpid(pid, &status, 0);
+ close(pipefd[1]);
+ while ((bytes_read = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) {
+ buf[bytes_read] = '\0';
+ printf("%s", buf);
}
- SHA1Final(hash, &ctx);
- stack_free(st);
- hash_at_level[level] = NULL;
- }
-}
-
-int compute_hash(const char * path, const struct stat *st,
- int tflag, struct FTW *ftwbuf)
-{
- int level;
- mode_t mode;
- unsigned char hash[HASH_LEN];
-
- const char *filename = path + ftwbuf->base;
- if (ignore(path))
- return 0;
-
- mode = st->st_mode;
- level = ftwbuf->level;
-
- if (tflag == FTW_F) {
- if (S_ISREG(mode))
- hash_file(path, hash);
- else if (S_ISLNK(mode))
- hash_path(path, hash);
- } else if (tflag == FTW_DP) {
- hash_dir(level, hash);
+ close(pipefd[0]);
+ wait(NULL);
}
-
- insert_hash(level - 1, filename, hash);
- print_hash(hash, path);
- return 0;
}
-
-static inline void scan_wtree(void)
-{
- if (nftw(".", compute_hash, MAX_DEPTH, FTW_DEPTH | FTW_PHYS) == -1)
- err(1, "nftw");
-}
-
-static inline int ignore(const char *path)
-{
- return memcmp(path, "./.cvn", 6) == 0 ||
- strcmp(path, "./cvn") == 0 ||
- strcmp(path, ".") == 0;
-}
-