diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/common.c | 42 | ||||
-rw-r--r-- | examples/common.h | 25 | ||||
-rw-r--r-- | examples/diff.c | 112 | ||||
-rw-r--r-- | examples/for-each-ref.c | 1 | ||||
-rw-r--r-- | examples/general.c | 6 | ||||
-rw-r--r-- | examples/index-pack.c | 16 | ||||
-rw-r--r-- | examples/status.c | 6 |
7 files changed, 147 insertions, 61 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 724a5c04f..bba83217b 100644 --- a/examples/common.h +++ b/examples/common.h @@ -12,10 +12,25 @@ * <http://creativecommons.org/publicdomain/zero/1.0/>. */ +#include <sys/types.h> +#include <sys/stat.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <git2.h> +#include <fcntl.h> + +#ifdef _WIN32 +# include <io.h> +# include <Windows.h> +# define open _open +# define read _read +# define close _close +# define ssize_t int +# define sleep(a) Sleep(a * 1000) +#else +# include <unistd.h> +#endif #ifndef PRIuZ /* Define the printf format specifer to use for size_t output */ @@ -65,6 +80,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); @@ -90,7 +113,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; diff --git a/examples/for-each-ref.c b/examples/for-each-ref.c index eea73d2fc..900792c12 100644 --- a/examples/for-each-ref.c +++ b/examples/for-each-ref.c @@ -1,5 +1,4 @@ #include <git2.h> -#include <stdio.h> #include "common.h" static int show_ref(git_reference *ref, void *data) diff --git a/examples/general.c b/examples/general.c index 4bd1dac23..ddc53c3e8 100644 --- a/examples/general.c +++ b/examples/general.c @@ -36,6 +36,8 @@ * [pg]: https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain */ +#include "common.h" + /** * ### Includes * @@ -43,9 +45,7 @@ * that you need. It should be the only thing you need to include in order * to compile properly and get all the libgit2 API. */ -#include <git2.h> -#include <stdio.h> -#include <string.h> +#include "git2.h" static void oid_parsing(git_oid *out); static void object_database(git_repository *repo, git_oid *oid); diff --git a/examples/index-pack.c b/examples/index-pack.c index 0941e09e7..2181f43f3 100644 --- a/examples/index-pack.c +++ b/examples/index-pack.c @@ -1,21 +1,5 @@ #include "common.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#ifdef _WIN32 -# include <io.h> -# include <Windows.h> - -# define open _open -# define read _read -# define close _close - -#define ssize_t int -#else -# include <unistd.h> -#endif - /* * This could be run in the main loop whilst the application waits for * the indexing to finish in a worker thread diff --git a/examples/status.c b/examples/status.c index 38e5120e8..979ab7c97 100644 --- a/examples/status.c +++ b/examples/status.c @@ -13,12 +13,6 @@ */ #include "common.h" -#ifdef _WIN32 -# include <Windows.h> -# define sleep(a) Sleep(a * 1000) -#else -# include <unistd.h> -#endif /** * This example demonstrates the use of the libgit2 status APIs, |