commit d1f6d47b18456c7e66b2076c063fa2a3d0fa5d40 from: Stefan Sperling date: Mon Feb 04 10:17:36 2019 UTC add support for diffing fileindex against an on-disk directory tree commit - f44ffd20bad62e47d8f239070f4143fbfb01f914 commit + d1f6d47b18456c7e66b2076c063fa2a3d0fa5d40 blob - 752d2285ffeb5502e3de750d609292c97be7170d blob + d25609a3f601da3cf62c0f3979ad43288f7f1af4 --- lib/fileindex.c +++ lib/fileindex.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -688,6 +689,99 @@ got_fileindex_diff_tree(struct got_fileindex *fileinde struct got_fileindex_entry *min; min = RB_MIN(got_fileindex_tree, &fileindex->entries); return diff_fileindex_tree(fileindex, &min, tree, "", repo, cb, cb_arg); +} + +static const struct got_error * +diff_fileindex_dir(struct got_fileindex *, struct got_fileindex_entry **, DIR *, + const char *, struct got_repository *, struct got_fileindex_diff_dir_cb *, + void *); + +static const struct got_error * +walk_dir(struct dirent **next, struct got_fileindex *fileindex, + struct got_fileindex_entry **ie, struct dirent *de, const char *path, + DIR *dir, struct got_repository *repo, + struct got_fileindex_diff_dir_cb *cb, void *cb_arg) +{ + const struct got_error *err = NULL; + + if (de->d_type == DT_DIR) { + char *subpath; + DIR *subdir; + + if (asprintf(&subpath, "%s%s%s", path, + path[0] == '\0' ? "" : "/", de->d_name) == -1) + return got_error_from_errno(); + + subdir = opendir(subpath); + if (subdir == NULL) { + free(subpath); + return got_error_from_errno(); + } + + err = diff_fileindex_dir(fileindex, ie, subdir, subpath, repo, + cb, cb_arg); + free(subpath); + closedir(subdir); + if (err) + return err; + } + + *next = readdir(dir); + return NULL; +} + +static const struct got_error * +diff_fileindex_dir(struct got_fileindex *fileindex, + struct got_fileindex_entry **ie, DIR *dir, const char *path, + struct got_repository *repo, struct got_fileindex_diff_dir_cb *cb, + void *cb_arg) +{ + const struct got_error *err = NULL; + struct dirent *de = NULL; + size_t path_len = strlen(path); + struct got_fileindex_entry *next; + + de = readdir(dir); + do { + if (de && *ie) { + int cmp = cmp_entries((*ie)->path, path, path_len, + de->d_name); + if (cmp == 0) { + err = cb->diff_old_new(cb_arg, *ie, de, path); + if (err) + break; + *ie = walk_fileindex(fileindex, *ie); + err = walk_dir(&de, fileindex, ie, de, path, + dir, repo, cb, cb_arg); + } else if (cmp < 0 ) { + next = walk_fileindex(fileindex, *ie); + err = cb->diff_old(cb_arg, *ie, path); + if (err) + break; + *ie = next; + } else { + err = cb->diff_new(cb_arg, de, path); + if (err) + break; + err = walk_dir(&de, fileindex, ie, de, path, + dir, repo, cb, cb_arg); + } + if (err) + break; + } + } while ((*ie && got_path_is_child((*ie)->path, path, path_len)) || de); + + return err; } +const struct got_error * +got_fileindex_diff_dir(struct got_fileindex *fileindex, DIR *dir, + struct got_repository *repo, struct got_fileindex_diff_dir_cb *cb, + void *cb_arg) +{ + struct got_fileindex_entry *min; + min = RB_MIN(got_fileindex_tree, &fileindex->entries); + return diff_fileindex_dir(fileindex, &min, dir, "", repo, cb, cb_arg); +} + RB_GENERATE(got_fileindex_tree, got_fileindex_entry, entry, got_fileindex_cmp); blob - 0336dd74296c652ed6ed0980e9a8ed007949c02d blob + 12d5ee251aa65405386153ccd88feb5b09106790 --- lib/got_lib_fileindex.h +++ lib/got_lib_fileindex.h @@ -125,7 +125,20 @@ struct got_fileindex_diff_tree_cb { got_fileindex_diff_tree_old_cb diff_old; got_fileindex_diff_tree_new_cb diff_new; }; - const struct got_error *got_fileindex_diff_tree(struct got_fileindex *, struct got_tree_object *, struct got_repository *, struct got_fileindex_diff_tree_cb *, void *); + +typedef const struct got_error *(*got_fileindex_diff_dir_old_new_cb)(void *, + struct got_fileindex_entry *, struct dirent *, const char *); +typedef const struct got_error *(*got_fileindex_diff_dir_old_cb)(void *, + struct got_fileindex_entry *, const char *); +typedef const struct got_error *(*got_fileindex_diff_dir_new_cb)(void *, + struct dirent *, const char *); +struct got_fileindex_diff_dir_cb { + got_fileindex_diff_dir_old_new_cb diff_old_new; + got_fileindex_diff_dir_old_cb diff_old; + got_fileindex_diff_dir_new_cb diff_new; +}; +const struct got_error *got_fileindex_diff_dir(struct got_fileindex *, DIR *, + struct got_repository *, struct got_fileindex_diff_dir_cb *, void *); blob - 62fe586f6049080b787658189ede0445af34e6b9 blob + 1d33ed029c59827d2854d7d3565d3fdfe6c5ed7e --- lib/worktree.c +++ lib/worktree.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include