diff --git a/.cache/clangd/index/XD.c.CF9B5320BE29FE6C.idx b/.cache/clangd/index/XD.c.CF9B5320BE29FE6C.idx new file mode 100644 index 0000000..7699412 Binary files /dev/null and b/.cache/clangd/index/XD.c.CF9B5320BE29FE6C.idx differ diff --git a/Makefile b/Makefile index 66be544..0027568 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,13 @@ include config.mk # flags and incs PKGS = $(GITLIB) -CFLAGS = -DVERSION=\"$(VERSION)\" -Wall -pedantic -O3 $(GIT) $(GITHASH) $(ERR) $(PERF) $(EXPLAIN) +CFLAGS = -DVERSION=\"$(VERSION)\" -Wall -pedantic -O3 $(GIT) $(ERR) $(EXPLAIN) LIBS = `$(PKG_CONFIG) --libs --cflags $(PKGS)` all: XD -XD: XD.o hash.o helpers.o +XD: XD.o $(CC) *.o $(CFLAGS) $(LIBS) -o $@ +XD.o: XD.c clean: rm -f XD *.o diff --git a/XD.1 b/XD.1 index d7a147d..380bff6 100644 --- a/XD.1 +++ b/XD.1 @@ -12,12 +12,9 @@ .Sh DESCRIPTION .Nm Displays information using a smiley face like so: :) -.Nm -does some special caching to run as fast as possible but there's only so much -that can be done without relying on an external daemon. Therefore when new -changes are made in very large repositories it may take a few seconds to -determine if there are any changes. To interpret XD's output refer to the -following tables (or +to interpret it refer to the following tables: +Displays information using a smiley face. +to interpret XD's output refer to the following tables (or .Nm \fB-e\fR): .Ss Eyes diff --git a/XD.c b/XD.c index de8d694..c5af3cd 100644 --- a/XD.c +++ b/XD.c @@ -1,9 +1,7 @@ -#include #include #include #include #include -#include #ifdef ERR #include @@ -18,11 +16,42 @@ #include #endif -#include "helpers.h" -#include "hash.h" - #define P(X) fwrite(X, 1, 1, stdout) +#if defined(ERR) || defined(EXPLAIN) +void +l(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } +} +#endif + +#ifdef ERR +#define L(...) l(__VA_ARGS__) +#else +#define L(...) +#endif + +#ifdef EXPLAIN +static int explain = 0; +#define E(...) if (explain) { \ + l(__VA_ARGS__); \ + } else +#else +#define E(...) +#endif + #ifdef GIT /** * @brief search all parent directories for a git repo @@ -32,7 +61,6 @@ char *find_git_repo(void) { - PS(); char path[PATH_MAX] = ".", fstr[PATH_MAX], *rpath, *res; struct stat s; FILE *f; @@ -42,7 +70,6 @@ char rpath = realpath(path, NULL); if (!rpath) { L("realpath: %s", strerror(errno)); - PE(); return NULL; } for (i = c = 0; i < strlen(rpath); i++) { @@ -59,26 +86,22 @@ char /* if there seems to be a git directory return the directory it was found in */ if (stat(path, &s) == 0) { if (S_ISDIR(s.st_mode)) { - PE(); return realpath(path, NULL); } else if (S_ISREG(s.st_mode)) { /* we do some special magic here to check if we're in a submodule */ f = fopen(path, "r"); if (!f) { L("fopen: %s", strerror(errno)); - PE(); return NULL; } res = fgets(fstr, PATH_MAX, f); fclose(f); if (!res) { L("fgets: %s", strerror(errno)); - PE(); return NULL; } if (strncmp(fstr, "gitdir: ", strlen("gitdir: ")) == 0) { fstr[strlen(fstr) - 1] = '\0'; - PE(); return realpath(fstr + strlen("gitdir: "), NULL); } } @@ -89,7 +112,6 @@ char memset(&path[strlen(path) - 2], 0, 2); } - PE(); return NULL; } @@ -101,13 +123,11 @@ char git_repository *init_git(void) { - PS(); char *buf; git_repository *repo; /* check for a repo before loading libgit2 */ if ((buf = find_git_repo()) == NULL) { - PE(); return NULL; } @@ -123,20 +143,17 @@ git_repository /* initialize the git library and repository */ if (git_libgit2_init() < 0) { L("Failed to initalize libgit2, proceeding without git functionality enabled."); - PE(); return NULL; } if (git_repository_open(&repo, buf) < 0) { L("Failed to open git repo: %s", git_error_last()->message); free(buf); - PE(); return NULL; } /* get rid of object containing git repo path and return the repo */ free(buf); - PE(); return repo; } @@ -149,24 +166,20 @@ git_repository int has_stashes(git_repository *repo) { - PS(); git_reference *stash = NULL; int e; e = git_reference_lookup(&stash, repo, "refs/stash"); if (e == GIT_ENOTFOUND) { - PE(); return 0; } else if (e < 0) { L("Error looking up stash reference: %s", git_error_last()->message); - PE(); return 0; } else { e = 1; } git_reference_free(stash); - PE(); return e; } @@ -179,45 +192,27 @@ has_stashes(git_repository *repo) int has_untracked(git_repository *repo) { - PS(); git_status_options opts = GIT_STATUS_OPTIONS_INIT; git_status_list *list = NULL; - repohash *storedhash; - uint64_t newhash = generate_hash(repo); int r = 0; - #ifdef GITHASH - if ((storedhash = read_hash(repo)) - && storedhash->hash == newhash) { - r = storedhash->changes; - free(storedhash); - PE(); - return r; - } - #endif - - /* if we need to regen the hash then we need to do a hard check on the real - * git repository */ - opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; + /* FIXME: this is really slow in large git repos :( */ + opts.show = GIT_STATUS_SHOW_WORKDIR_ONLY; opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | - GIT_STATUS_OPT_UPDATE_INDEX | GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH; if (git_status_list_new(&list, repo, &opts) < 0) { L("Error checking for untracked changes: %s", git_error_last()->message); - PE(); return 0; } /* if any changes are found return 1 */ - r = git_status_list_entrycount(list) > 0; - #ifdef GITHASH - write_hash(repo, (repohash){ .hash = newhash, .changes = r }); - #endif + if (git_status_list_entrycount(list) > 0) { + r = 1; + } git_status_list_free(list); - PE(); return r; } @@ -230,7 +225,6 @@ has_untracked(git_repository *repo) int has_staged(git_repository *repo) { - PS(); git_status_entry entry; git_status_list *list = NULL; git_status_options opts = GIT_STATUS_OPTIONS_INIT; @@ -241,7 +235,6 @@ has_staged(git_repository *repo) if (git_status_list_new(&list, repo, &opts) < 0) { L("Error checking for staged changes: %s", git_error_last()->message); - PE(); return 0; } @@ -260,7 +253,6 @@ has_staged(git_repository *repo) } git_status_list_free(list); - PE(); return r; } #endif @@ -268,20 +260,17 @@ has_staged(git_repository *repo) inline unsigned numcat(unsigned x, unsigned y) { - PS(); unsigned pow = 10; while(y >= pow) { pow *= 10; } - PE(); return (x * pow) + y; } int str_to_int(char *str) { - PS(); int res = -1; char *c; @@ -293,20 +282,17 @@ str_to_int(char *str) } } - PE(); return res; } int main(int argc, char *argv[]) { - PS(); int code = -1; /* print version information */ if (argc > 1 && strcmp(argv[1], "-v") == 0) { printf("XD [number] %s\n", VERSION); - PE(); return 0; #ifdef EXPLAIN } else if (argc > 1 && strcmp(argv[1], "-e") == 0) { @@ -358,7 +344,6 @@ main(int argc, char *argv[]) code = str_to_int(argv[argc - 1]); if (code < 0) { L("Return code, %d, not valid", code); - PE(); exit(1); } } @@ -392,6 +377,5 @@ main(int argc, char *argv[]) P("|"); /* no code info */ } - PE(); return code; } diff --git a/config.mk b/config.mk index 2614a75..b7f4032 100644 --- a/config.mk +++ b/config.mk @@ -1,4 +1,4 @@ -VERSION := `git describe --tags --dirty` +VERSION = `git describe --tags --abbrev=0` PKG_CONFIG = pkg-config @@ -7,21 +7,15 @@ PREFIX = /usr/local MANDIR = $(PREFIX)/share/man GIT = -GITHASH = GITLIB = # comment to disable git support GIT = -DGIT -GITHASH = -DGITHASH GITLIB = libgit2 ERR = # uncomment to enable errors # ERR = -DERR -PERF = -# uncomment to enable performance logging -# PERF = -DPERF - EXPLAIN = # comment to disable explinations EXPLAIN = -DEXPLAIN @@ -30,25 +24,15 @@ EXPLAIN = -DEXPLAIN ifneq ($(GIT),) VERSION := $(VERSION)"\\nlibgit2 "`$(PKG_CONFIG) --modversion $(GITLIB)` endif -ifeq ($(GITHASH),) - VERSION := $(VERSION)"\\ngit hashing disabled" +ifeq ($(ERR),) + VERSION := $(VERSION)"\\nerrors disabled" else - VERSION := $(VERSION)"\\ngit hashing enabled" + VERSION := $(VERSION)"\\nerrors enabled" endif ifeq ($(EXPLAIN),) VERSION := $(VERSION)"\\nexplinations disabled" else VERSION := $(VERSION)"\\nexplinations enabled" endif -ifeq ($(ERR),) - VERSION := $(VERSION)"\\nerrors disabled" -else - VERSION := $(VERSION)"\\nerrors enabled" -endif -ifeq ($(PERF),) - VERSION := $(VERSION)"\\nperformance logging disabled" -else - VERSION := $(VERSION)"\\nperformance logging enabled" -endif CC = cc diff --git a/hash.c b/hash.c deleted file mode 100644 index 5403d50..0000000 --- a/hash.c +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hash.h" -#include "helpers.h" - -#ifdef GITHASH -static uint64_t -murmur64(uint64_t k) -{ - PS(); - k ^= k >> 33; - k *= 0xff51afd7ed558ccdLLU; - k ^= k >> 33; - k *= 0xc4ceb9fe1a85ec53LLU; - k ^= k >> 33; - - PE(); - return k; -} - -uint64_t -generate_hash(git_repository *repo) -{ - PS(); - struct stat dir, index; - char path[PATH_MAX] = { 0 }; - - const char *gitpath = git_repository_path(repo); - if (strlen(gitpath) + strlen("/..") > PATH_MAX - 1) { - L("strlen: %s", strerror(errno)); - PE(); - return -1; - } - - strcat(path, gitpath); - if (stat(path, &index) < 0) { - PE(); - return -1; - } - strcat(path, "/.."); - if (stat(path, &dir) < 0) { - PE(); - return -1; - } - PE(); - return murmur64(dir.st_mtim.tv_nsec ^ index.st_mtim.tv_nsec); -} - -repohash -*read_hash(git_repository *repo) -{ - PS(); - FILE *f; - uint64_t data; - uint8_t changes; - repohash *hash = malloc(sizeof(repohash)); - char path[PATH_MAX] = { 0 }; - - const char *gitpath = git_repository_path(repo); - if (strlen(gitpath) + strlen(XD_HASH_PATH) > PATH_MAX - 1) { - L("strlen: %s", strerror(errno)); - PE(); - return NULL; - } - strcat(path, gitpath); - strcat(path, XD_HASH_PATH); - - f = fopen(path, "r"); - if (!f) { - L("fopen: %s", strerror(errno)); - PE(); - return NULL; - } - - if (fread(&data, sizeof(uint64_t), 1, f) != 1) { - L("fread: %s", strerror(errno)); - PE(); - return NULL; - } - - if (fseek(f, sizeof(uint64_t), SEEK_SET) < 0) { - L("fseek: %s", strerror(errno)); - PE(); - return NULL; - } - - if (fread(&changes, sizeof(uint8_t), 1, f) != 1) { - L("fread: %s", strerror(errno)); - PE(); - return NULL; - } - fclose(f); - - hash->hash = data; - hash->changes = changes; - PE(); - return hash; -} - -int -write_hash(git_repository *repo, repohash hash) -{ - PS(); - FILE *f; - char path[PATH_MAX] = { 0 }; - - const char *gitpath = git_repository_path(repo); - if (strlen(gitpath) + strlen(XD_HASH_PATH) > PATH_MAX - 1) { - L("strlen: %s", strerror(errno)); - PE(); - return 1; - } - strcat(path, gitpath); - strcat(path, XD_HASH_PATH); - - f = fopen(path, "wb"); - if (!f) { - L("fopen: %s", strerror(errno)); - PE(); - return 1; - } - - if (fwrite(&hash.hash, sizeof(uint64_t), 1, f) != 1) { - L("fwrite: %s", strerror(errno)); - PE(); - return 1; - } - - if (fseek(f, sizeof(uint64_t), SEEK_SET) < 0) { - L("fseek: %s", strerror(errno)); - PE(); - return 1; - } - - if (fwrite(&hash.changes, sizeof(uint8_t), 1, f) != 1) { - L("fwrite: %s", strerror(errno)); - PE(); - return 1; - } - - fclose(f); - PE(); - return 0; -} -#endif diff --git a/hash.h b/hash.h deleted file mode 100644 index a78cd99..0000000 --- a/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include -#include - -#ifdef GIT -typedef struct { - uint64_t hash; - bool changes; -} repohash; - -#define XD_HASH_PATH "/XDhash" -/** - * @brief generate a hash from the repository state - * - * @param repo the git repository - * @return the hash - */ -uint64_t generate_hash(git_repository *repo); - -/** - * @brief read the hash from the git repo - * - * @param repo the git repository - * @return the hash - */ -repohash *read_hash(git_repository *repo); - -/** - * @brief write a new hash to the repository - * - * @param repo the repository - * @param hash the hash to write - */ -int write_hash(git_repository *repo, repohash hash); -#endif diff --git a/helpers.c b/helpers.c deleted file mode 100644 index e3ef987..0000000 --- a/helpers.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include - -#include "helpers.h" - -#ifdef EXPLAIN -int explain = 0; -#endif - -#if defined(ERR) || defined(EXPLAIN) -void -l(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } -} -#endif diff --git a/helpers.h b/helpers.h deleted file mode 100644 index b106667..0000000 --- a/helpers.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#if defined(ERR) || defined(EXPLAIN) -void l(const char *fmt, ...); -#endif - -#ifdef ERR -#define L(...) l(__VA_ARGS__) -#else -#define L(...) -#endif - -#ifdef EXPLAIN -extern int explain; -#define E(...) if (explain) { \ - l(__VA_ARGS__); \ - } else -#else -#define E(...) -#endif - -#ifdef PERF -#define PS() long __start = clock() -#define PE() l("%s: %fs", __func__, ((double) (clock() - __start)) / CLOCKS_PER_SEC) -#else -#define PS() -#define PE() -#endif