From b200dd2a15365007b5ea64dff4df3e29273b2212 Mon Sep 17 00:00:00 2001 From: Sadeep Madurange Date: Thu, 12 Mar 2026 23:06:40 +0800 Subject: Use diff for status. --- main.c | 227 ++++++++++++----------------------------------------------------- 1 file changed, 40 insertions(+), 187 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 32232c5..cdf1340 100644 --- a/main.c +++ b/main.c @@ -1,30 +1,20 @@ #include #include -#include #include -#include #include #include #include #include +#include -#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; -} - -- cgit v1.2.3