diff options
author | Alberto Fanjul <albertofanjul@gmail.com> | 2019-06-18 08:31:31 +0200 |
---|---|---|
committer | Alberto Fanjul <albertofanjul@gmail.com> | 2019-07-05 14:12:04 +0200 |
commit | 3be09b6c0295c834792d66c4d38d0e1a1c53e71c (patch) | |
tree | a08eff7f96bce9df22198547115d909c25dddb1b /examples | |
parent | 398412ccd3f982e2bc1de16d87bd00f27580c256 (diff) | |
download | libgit2-3be09b6c0295c834792d66c4d38d0e1a1c53e71c.tar.gz |
Compare buffers in diff example
Diffstat (limited to 'examples')
-rw-r--r-- | examples/common.c | 42 | ||||
-rw-r--r-- | examples/common.h | 10 | ||||
-rw-r--r-- | examples/diff.c | 112 |
3 files changed, 129 insertions, 35 deletions
diff --git a/examples/common.c b/examples/common.c index 4cd9f2bec..22807e129 100644 --- a/examples/common.c +++ b/examples/common.c @@ -14,6 +14,14 @@ #include <assert.h> #include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef _WIN32 +# include <io.h> +#else +# include <fcntl.h> +# include <unistd.h> +#endif #include <string.h> #include <errno.h> @@ -391,3 +399,37 @@ out: free(pubkey); return error; } + +char *read_file(const char *path) +{ + ssize_t total = 0; + char *buf = NULL; + struct stat st; + int fd = -1; + + if ((fd = open(path, O_RDONLY)) < 0 || fstat(fd, &st) < 0) + goto out; + + if ((buf = malloc(st.st_size + 1)) == NULL) + goto out; + + while (total < st.st_size) { + ssize_t bytes = read(fd, buf + total, st.st_size - total); + if (bytes <= 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + free(buf); + buf = NULL; + goto out; + } + total += bytes; + } + + buf[total] = '\0'; + +out: + if (fd >= 0) + close(fd); + return buf; +} + diff --git a/examples/common.h b/examples/common.h index c1d444e1d..204b17595 100644 --- a/examples/common.h +++ b/examples/common.h @@ -64,6 +64,14 @@ extern int lg2_tag(git_repository *repo, int argc, char **argv); extern void check_lg2(int error, const char *message, const char *extra); /** + * Read a file into a buffer + * + * @param path The path to the file that shall be read + * @return NUL-terminated buffer if the file was successfully read, NULL-pointer otherwise + */ +extern char *read_file(const char *path); + +/** * Exit the program, printing error to stderr */ extern void fatal(const char *message, const char *extra); @@ -89,7 +97,7 @@ struct args_info { /** * Check current `args` entry against `opt` string. If it matches * exactly, take the next arg as a string; if it matches as a prefix with - * an equal sign, take the remainder as a string; if value not supplied, + * an equal sign, take the remainder as a string; if value not supplied, * default value `def` will be given. otherwise return 0. */ extern int optional_str_arg( diff --git a/examples/diff.c b/examples/diff.c index e8ba918f6..9e2aa9c41 100644 --- a/examples/diff.c +++ b/examples/diff.c @@ -52,6 +52,7 @@ struct opts { git_diff_options diffopts; git_diff_find_options findopts; int color; + int no_index; int cache; int output; git_diff_format_t format; @@ -66,14 +67,16 @@ static void parse_opts(struct opts *o, int argc, char *argv[]); static int color_printer( const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); static void diff_print_stats(git_diff *diff, struct opts *o); +static void compute_diff_no_index(git_diff **diff, struct opts *o); int lg2_diff(git_repository *repo, int argc, char *argv[]) { git_tree *t1 = NULL, *t2 = NULL; git_diff *diff; + struct opts o = { GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT, - -1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "." + -1, -1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "." }; parse_opts(&o, argc, argv); @@ -86,49 +89,54 @@ int lg2_diff(git_repository *repo, int argc, char *argv[]) * * <sha1> * * --cached * * --nocache (don't use index data in diff at all) + * * --no-index <file1> <file2> * * nothing * * Currently ranged arguments like <sha1>..<sha2> and <sha1>...<sha2> * are not supported in this example */ - if (o.treeish1) - treeish_to_tree(&t1, repo, o.treeish1); - if (o.treeish2) - treeish_to_tree(&t2, repo, o.treeish2); - - if (t1 && t2) - check_lg2( - git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts), - "diff trees", NULL); - else if (o.cache != CACHE_NORMAL) { - if (!t1) - treeish_to_tree(&t1, repo, "HEAD"); + if (o.no_index >= 0) { + compute_diff_no_index(&diff, &o); + } else { + if (o.treeish1) + treeish_to_tree(&t1, repo, o.treeish1); + if (o.treeish2) + treeish_to_tree(&t2, repo, o.treeish2); - if (o.cache == CACHE_NONE) + if (t1 && t2) + check_lg2( + git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts), + "diff trees", NULL); + else if (o.cache != CACHE_NORMAL) { + if (!t1) + treeish_to_tree(&t1, repo, "HEAD"); + + if (o.cache == CACHE_NONE) + check_lg2( + git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts), + "diff tree to working directory", NULL); + else + check_lg2( + git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts), + "diff tree to index", NULL); + } + else if (t1) check_lg2( - git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts), + git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts), "diff tree to working directory", NULL); else check_lg2( - git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts), - "diff tree to index", NULL); - } - else if (t1) - check_lg2( - git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts), - "diff tree to working directory", NULL); - else - check_lg2( - git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts), - "diff index to working directory", NULL); + git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts), + "diff index to working directory", NULL); - /** Apply rename and copy detection if requested. */ + /** Apply rename and copy detection if requested. */ - if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0) - check_lg2( - git_diff_find_similar(diff, &o.findopts), - "finding renames and copies", NULL); + if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0) + check_lg2( + git_diff_find_similar(diff, &o.findopts), + "finding renames and copies", NULL); + } /** Generate simple output using libgit2 display helper. */ @@ -158,6 +166,38 @@ int lg2_diff(git_repository *repo, int argc, char *argv[]) return 0; } +static void compute_diff_no_index(git_diff **diff, struct opts *o) { + git_patch *patch = NULL; + char *file1_str = NULL; + char *file2_str = NULL; + git_buf buf = {0}; + + if (!o->treeish1 || !o->treeish2) { + usage("two files should be provided as arguments", NULL); + } + file1_str = read_file(o->treeish1); + if (file1_str == NULL) { + usage("file cannot be read", o->treeish1); + } + file2_str = read_file(o->treeish2); + if (file2_str == NULL) { + usage("file cannot be read", o->treeish2); + } + check_lg2( + git_patch_from_buffers(&patch, file1_str, strlen(file1_str), o->treeish1, file2_str, strlen(file2_str), o->treeish2, &o->diffopts), + "patch buffers", NULL); + check_lg2( + git_patch_to_buf(&buf, patch), + "patch to buf", NULL); + check_lg2( + git_diff_from_buffer(diff, buf.ptr, buf.size), + "diff from patch", NULL); + git_patch_free(patch); + git_buf_dispose(&buf); + free(file1_str); + free(file2_str); +} + static void usage(const char *message, const char *arg) { if (message && arg) @@ -223,9 +263,10 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) o->output |= OUTPUT_DIFF; o->format = GIT_DIFF_FORMAT_PATCH; } - else if (!strcmp(a, "--cached")) + else if (!strcmp(a, "--cached")) { o->cache = CACHE_ONLY; - else if (!strcmp(a, "--nocache")) + if (o->no_index >= 0) usage("--cached and --no-index are incompatible", NULL); + } else if (!strcmp(a, "--nocache")) o->cache = CACHE_NONE; else if (!strcmp(a, "--name-only") || !strcmp(a, "--format=name")) o->format = GIT_DIFF_FORMAT_NAME_ONLY; @@ -238,7 +279,10 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) o->format = GIT_DIFF_FORMAT_RAW; o->diffopts.id_abbrev = 40; } - else if (!strcmp(a, "--color")) + else if (!strcmp(a, "--no-index")) { + o->no_index = 0; + if (o->cache == CACHE_ONLY) usage("--cached and --no-index are incompatible", NULL); + } else if (!strcmp(a, "--color")) o->color = 0; else if (!strcmp(a, "--no-color")) o->color = -1; |