mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-22 06:26:26 +00:00
Merge pull request #5125 from albfan/wip/albfan/diff_buffers
Compare buffers in diff example
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -64,6 +79,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
|
||||
*/
|
||||
@@ -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(
|
||||
|
||||
114
examples/diff.c
114
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 (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 (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)
|
||||
if (t1 && t2)
|
||||
check_lg2(
|
||||
git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts),
|
||||
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_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);
|
||||
git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts),
|
||||
"diff index to working directory", NULL);
|
||||
|
||||
/** 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);
|
||||
}
|
||||
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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <git2.h>
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
|
||||
static int show_ref(git_reference *ref, void *data)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user