Skip to content

Commit 56e7aaf

Browse files
authored
Merge pull request libgit2#5125 from albfan/wip/albfan/diff_buffers
Compare buffers in diff example
2 parents eea128b + 960d2a0 commit 56e7aaf

File tree

7 files changed

+147
-61
lines changed

7 files changed

+147
-61
lines changed

examples/common.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414

1515
#include <assert.h>
1616
#include <stdio.h>
17+
#include <sys/types.h>
18+
#include <sys/stat.h>
19+
#ifdef _WIN32
20+
# include <io.h>
21+
#else
22+
# include <fcntl.h>
23+
# include <unistd.h>
24+
#endif
1725
#include <string.h>
1826
#include <errno.h>
1927

@@ -391,3 +399,37 @@ int cred_acquire_cb(git_cred **out,
391399
free(pubkey);
392400
return error;
393401
}
402+
403+
char *read_file(const char *path)
404+
{
405+
ssize_t total = 0;
406+
char *buf = NULL;
407+
struct stat st;
408+
int fd = -1;
409+
410+
if ((fd = open(path, O_RDONLY)) < 0 || fstat(fd, &st) < 0)
411+
goto out;
412+
413+
if ((buf = malloc(st.st_size + 1)) == NULL)
414+
goto out;
415+
416+
while (total < st.st_size) {
417+
ssize_t bytes = read(fd, buf + total, st.st_size - total);
418+
if (bytes <= 0) {
419+
if (errno == EAGAIN || errno == EINTR)
420+
continue;
421+
free(buf);
422+
buf = NULL;
423+
goto out;
424+
}
425+
total += bytes;
426+
}
427+
428+
buf[total] = '\0';
429+
430+
out:
431+
if (fd >= 0)
432+
close(fd);
433+
return buf;
434+
}
435+

examples/common.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,25 @@
1212
* <http://creativecommons.org/publicdomain/zero/1.0/>.
1313
*/
1414

15+
#include <sys/types.h>
16+
#include <sys/stat.h>
1517
#include <stdio.h>
1618
#include <string.h>
1719
#include <stdlib.h>
1820
#include <git2.h>
21+
#include <fcntl.h>
22+
23+
#ifdef _WIN32
24+
# include <io.h>
25+
# include <Windows.h>
26+
# define open _open
27+
# define read _read
28+
# define close _close
29+
# define ssize_t int
30+
# define sleep(a) Sleep(a * 1000)
31+
#else
32+
# include <unistd.h>
33+
#endif
1934

2035
#ifndef PRIuZ
2136
/* 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);
6479
*/
6580
extern void check_lg2(int error, const char *message, const char *extra);
6681

82+
/**
83+
* Read a file into a buffer
84+
*
85+
* @param path The path to the file that shall be read
86+
* @return NUL-terminated buffer if the file was successfully read, NULL-pointer otherwise
87+
*/
88+
extern char *read_file(const char *path);
89+
6790
/**
6891
* Exit the program, printing error to stderr
6992
*/
@@ -90,7 +113,7 @@ struct args_info {
90113
/**
91114
* Check current `args` entry against `opt` string. If it matches
92115
* exactly, take the next arg as a string; if it matches as a prefix with
93-
* an equal sign, take the remainder as a string; if value not supplied,
116+
* an equal sign, take the remainder as a string; if value not supplied,
94117
* default value `def` will be given. otherwise return 0.
95118
*/
96119
extern int optional_str_arg(

examples/diff.c

Lines changed: 78 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct opts {
5252
git_diff_options diffopts;
5353
git_diff_find_options findopts;
5454
int color;
55+
int no_index;
5556
int cache;
5657
int output;
5758
git_diff_format_t format;
@@ -66,14 +67,16 @@ static void parse_opts(struct opts *o, int argc, char *argv[]);
6667
static int color_printer(
6768
const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*);
6869
static void diff_print_stats(git_diff *diff, struct opts *o);
70+
static void compute_diff_no_index(git_diff **diff, struct opts *o);
6971

7072
int lg2_diff(git_repository *repo, int argc, char *argv[])
7173
{
7274
git_tree *t1 = NULL, *t2 = NULL;
7375
git_diff *diff;
76+
7477
struct opts o = {
7578
GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT,
76-
-1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "."
79+
-1, -1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "."
7780
};
7881

7982
parse_opts(&o, argc, argv);
@@ -86,49 +89,54 @@ int lg2_diff(git_repository *repo, int argc, char *argv[])
8689
* * &lt;sha1&gt;
8790
* * --cached
8891
* * --nocache (don't use index data in diff at all)
92+
* * --no-index &lt;file1&gt; &lt;file2&gt;
8993
* * nothing
9094
*
9195
* Currently ranged arguments like &lt;sha1&gt;..&lt;sha2&gt; and &lt;sha1&gt;...&lt;sha2&gt;
9296
* are not supported in this example
9397
*/
9498

95-
if (o.treeish1)
96-
treeish_to_tree(&t1, repo, o.treeish1);
97-
if (o.treeish2)
98-
treeish_to_tree(&t2, repo, o.treeish2);
99-
100-
if (t1 && t2)
101-
check_lg2(
102-
git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts),
103-
"diff trees", NULL);
104-
else if (o.cache != CACHE_NORMAL) {
105-
if (!t1)
106-
treeish_to_tree(&t1, repo, "HEAD");
99+
if (o.no_index >= 0) {
100+
compute_diff_no_index(&diff, &o);
101+
} else {
102+
if (o.treeish1)
103+
treeish_to_tree(&t1, repo, o.treeish1);
104+
if (o.treeish2)
105+
treeish_to_tree(&t2, repo, o.treeish2);
107106

108-
if (o.cache == CACHE_NONE)
107+
if (t1 && t2)
108+
check_lg2(
109+
git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts),
110+
"diff trees", NULL);
111+
else if (o.cache != CACHE_NORMAL) {
112+
if (!t1)
113+
treeish_to_tree(&t1, repo, "HEAD");
114+
115+
if (o.cache == CACHE_NONE)
116+
check_lg2(
117+
git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts),
118+
"diff tree to working directory", NULL);
119+
else
120+
check_lg2(
121+
git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts),
122+
"diff tree to index", NULL);
123+
}
124+
else if (t1)
109125
check_lg2(
110-
git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts),
126+
git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts),
111127
"diff tree to working directory", NULL);
112128
else
113129
check_lg2(
114-
git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts),
115-
"diff tree to index", NULL);
116-
}
117-
else if (t1)
118-
check_lg2(
119-
git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts),
120-
"diff tree to working directory", NULL);
121-
else
122-
check_lg2(
123-
git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts),
124-
"diff index to working directory", NULL);
130+
git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts),
131+
"diff index to working directory", NULL);
125132

126-
/** Apply rename and copy detection if requested. */
133+
/** Apply rename and copy detection if requested. */
127134

128-
if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0)
129-
check_lg2(
130-
git_diff_find_similar(diff, &o.findopts),
131-
"finding renames and copies", NULL);
135+
if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0)
136+
check_lg2(
137+
git_diff_find_similar(diff, &o.findopts),
138+
"finding renames and copies", NULL);
139+
}
132140

133141
/** Generate simple output using libgit2 display helper. */
134142

@@ -158,6 +166,38 @@ int lg2_diff(git_repository *repo, int argc, char *argv[])
158166
return 0;
159167
}
160168

169+
static void compute_diff_no_index(git_diff **diff, struct opts *o) {
170+
git_patch *patch = NULL;
171+
char *file1_str = NULL;
172+
char *file2_str = NULL;
173+
git_buf buf = {0};
174+
175+
if (!o->treeish1 || !o->treeish2) {
176+
usage("two files should be provided as arguments", NULL);
177+
}
178+
file1_str = read_file(o->treeish1);
179+
if (file1_str == NULL) {
180+
usage("file cannot be read", o->treeish1);
181+
}
182+
file2_str = read_file(o->treeish2);
183+
if (file2_str == NULL) {
184+
usage("file cannot be read", o->treeish2);
185+
}
186+
check_lg2(
187+
git_patch_from_buffers(&patch, file1_str, strlen(file1_str), o->treeish1, file2_str, strlen(file2_str), o->treeish2, &o->diffopts),
188+
"patch buffers", NULL);
189+
check_lg2(
190+
git_patch_to_buf(&buf, patch),
191+
"patch to buf", NULL);
192+
check_lg2(
193+
git_diff_from_buffer(diff, buf.ptr, buf.size),
194+
"diff from patch", NULL);
195+
git_patch_free(patch);
196+
git_buf_dispose(&buf);
197+
free(file1_str);
198+
free(file2_str);
199+
}
200+
161201
static void usage(const char *message, const char *arg)
162202
{
163203
if (message && arg)
@@ -223,9 +263,10 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
223263
o->output |= OUTPUT_DIFF;
224264
o->format = GIT_DIFF_FORMAT_PATCH;
225265
}
226-
else if (!strcmp(a, "--cached"))
266+
else if (!strcmp(a, "--cached")) {
227267
o->cache = CACHE_ONLY;
228-
else if (!strcmp(a, "--nocache"))
268+
if (o->no_index >= 0) usage("--cached and --no-index are incompatible", NULL);
269+
} else if (!strcmp(a, "--nocache"))
229270
o->cache = CACHE_NONE;
230271
else if (!strcmp(a, "--name-only") || !strcmp(a, "--format=name"))
231272
o->format = GIT_DIFF_FORMAT_NAME_ONLY;
@@ -238,7 +279,10 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
238279
o->format = GIT_DIFF_FORMAT_RAW;
239280
o->diffopts.id_abbrev = 40;
240281
}
241-
else if (!strcmp(a, "--color"))
282+
else if (!strcmp(a, "--no-index")) {
283+
o->no_index = 0;
284+
if (o->cache == CACHE_ONLY) usage("--cached and --no-index are incompatible", NULL);
285+
} else if (!strcmp(a, "--color"))
242286
o->color = 0;
243287
else if (!strcmp(a, "--no-color"))
244288
o->color = -1;

examples/for-each-ref.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include <git2.h>
2-
#include <stdio.h>
32
#include "common.h"
43

54
static int show_ref(git_reference *ref, void *data)

examples/general.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@
3636
* [pg]: https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain
3737
*/
3838

39+
#include "common.h"
40+
3941
/**
4042
* ### Includes
4143
*
4244
* Including the `git2.h` header will include all the other libgit2 headers
4345
* that you need. It should be the only thing you need to include in order
4446
* to compile properly and get all the libgit2 API.
4547
*/
46-
#include <git2.h>
47-
#include <stdio.h>
48-
#include <string.h>
48+
#include "git2.h"
4949

5050
static void oid_parsing(git_oid *out);
5151
static void object_database(git_repository *repo, git_oid *oid);

examples/index-pack.c

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,5 @@
11
#include "common.h"
22

3-
#include <sys/types.h>
4-
#include <sys/stat.h>
5-
#include <fcntl.h>
6-
#ifdef _WIN32
7-
# include <io.h>
8-
# include <Windows.h>
9-
10-
# define open _open
11-
# define read _read
12-
# define close _close
13-
14-
#define ssize_t int
15-
#else
16-
# include <unistd.h>
17-
#endif
18-
193
/*
204
* This could be run in the main loop whilst the application waits for
215
* the indexing to finish in a worker thread

examples/status.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@
1313
*/
1414

1515
#include "common.h"
16-
#ifdef _WIN32
17-
# include <Windows.h>
18-
# define sleep(a) Sleep(a * 1000)
19-
#else
20-
# include <unistd.h>
21-
#endif
2216

2317
/**
2418
* This example demonstrates the use of the libgit2 status APIs,

0 commit comments

Comments
 (0)