summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/diff_output.c44
-rw-r--r--tests-clar/diff/tree.c82
-rw-r--r--tests-clar/diff/workdir.c91
-rw-r--r--tests-clar/resources/diff/.gitted/HEAD1
-rw-r--r--tests-clar/resources/diff/.gitted/config6
-rw-r--r--tests-clar/resources/diff/.gitted/description1
-rw-r--r--tests-clar/resources/diff/.gitted/indexbin0 -> 225 bytes
-rw-r--r--tests-clar/resources/diff/.gitted/info/exclude6
-rw-r--r--tests-clar/resources/diff/.gitted/logs/HEAD2
-rw-r--r--tests-clar/resources/diff/.gitted/logs/refs/heads/master2
-rw-r--r--tests-clar/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7bin0 -> 730 bytes
-rw-r--r--tests-clar/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847bin0 -> 1108 bytes
-rw-r--r--tests-clar/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989bin0 -> 1110 bytes
-rw-r--r--tests-clar/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10bin0 -> 160 bytes
-rw-r--r--tests-clar/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693bin0 -> 922 bytes
-rw-r--r--tests-clar/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c1
-rw-r--r--tests-clar/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455bin0 -> 86 bytes
-rw-r--r--tests-clar/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b691
-rw-r--r--tests-clar/resources/diff/.gitted/refs/heads/master1
-rw-r--r--tests-clar/resources/diff/another.txt38
-rw-r--r--tests-clar/resources/diff/readme.txt36
21 files changed, 299 insertions, 13 deletions
diff --git a/src/diff_output.c b/src/diff_output.c
index ea40c3355..50e3cc1de 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -1204,13 +1204,17 @@ static int diffiter_hunk_cb(
if (info->last_hunk)
info->last_hunk->next = hunk;
info->last_hunk = hunk;
+ info->last_line = NULL;
memcpy(&hunk->range, range, sizeof(hunk->range));
iter->hunk_count++;
- if (iter->hunk_head == NULL)
- iter->hunk_curr = iter->hunk_head = hunk;
+ /* adding first hunk to list */
+ if (iter->hunk_head == NULL) {
+ iter->hunk_head = hunk;
+ iter->hunk_curr = NULL;
+ }
return 0;
}
@@ -1345,9 +1349,14 @@ int git_diff_iterator_num_hunks_in_file(git_diff_iterator *iter)
int git_diff_iterator_num_lines_in_hunk(git_diff_iterator *iter)
{
int error = diffiter_do_diff_file(iter);
- if (!error && iter->hunk_curr)
- error = iter->hunk_curr->line_count;
- return error;
+ if (error)
+ return error;
+
+ if (iter->hunk_curr)
+ return iter->hunk_curr->line_count;
+ if (iter->hunk_head)
+ return iter->hunk_head->line_count;
+ return 0;
}
int git_diff_iterator_next_file(
@@ -1386,7 +1395,7 @@ int git_diff_iterator_next_file(
}
if (iter->ctxt.delta == NULL) {
- iter->hunk_curr = NULL;
+ iter->hunk_curr = iter->hunk_head = NULL;
iter->line_curr = NULL;
}
@@ -1409,11 +1418,13 @@ int git_diff_iterator_next_hunk(
return error;
if (iter->hunk_curr == NULL) {
- if (range_ptr) *range_ptr = NULL;
- if (header) *header = NULL;
- if (header_len) *header_len = 0;
- iter->line_curr = NULL;
- return GIT_ITEROVER;
+ if (iter->hunk_head == NULL)
+ goto no_more_hunks;
+ iter->hunk_curr = iter->hunk_head;
+ } else {
+ if (iter->hunk_curr->next == NULL)
+ goto no_more_hunks;
+ iter->hunk_curr = iter->hunk_curr->next;
}
range = &iter->hunk_curr->range;
@@ -1436,9 +1447,16 @@ int git_diff_iterator_next_hunk(
}
iter->line_curr = iter->hunk_curr->line_head;
- iter->hunk_curr = iter->hunk_curr->next;
return error;
+
+no_more_hunks:
+ if (range_ptr) *range_ptr = NULL;
+ if (header) *header = NULL;
+ if (header_len) *header_len = 0;
+ iter->line_curr = NULL;
+
+ return GIT_ITEROVER;
}
int git_diff_iterator_next_line(
@@ -1453,7 +1471,7 @@ int git_diff_iterator_next_line(
return error;
/* if the user has not called next_hunk yet, call it implicitly (OK?) */
- if (iter->hunk_curr == iter->hunk_head) {
+ if (iter->hunk_curr == NULL) {
error = git_diff_iterator_next_hunk(NULL, NULL, NULL, iter);
if (error)
return error;
diff --git a/tests-clar/diff/tree.c b/tests-clar/diff/tree.c
index 3003374a5..f5e72cadc 100644
--- a/tests-clar/diff/tree.c
+++ b/tests-clar/diff/tree.c
@@ -256,3 +256,85 @@ void test_diff_tree__merge(void)
git_diff_list_free(diff1);
}
+
+void test_diff_tree__larger_hunks(void)
+{
+ const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69";
+ const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10";
+ git_tree *a, *b;
+ git_diff_options opts = {0};
+ git_diff_list *diff = NULL;
+ git_diff_iterator *iter = NULL;
+ git_diff_delta *delta;
+ diff_expects exp;
+ int error, num_files = 0;
+
+ g_repo = cl_git_sandbox_init("diff");
+
+ cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL);
+ cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL);
+
+ opts.context_lines = 1;
+ opts.interhunk_lines = 0;
+
+ memset(&exp, 0, sizeof(exp));
+
+ cl_git_pass(git_diff_tree_to_tree(g_repo, &opts, a, b, &diff));
+ cl_git_pass(git_diff_iterator_new(&iter, diff));
+
+ /* this should be exact */
+ cl_assert(git_diff_iterator_progress(iter) == 0.0f);
+
+ /* You wouldn't actually structure an iterator loop this way, but
+ * I have here for testing purposes of the return value
+ */
+ while (!(error = git_diff_iterator_next_file(&delta, iter))) {
+ git_diff_range *range;
+ const char *header;
+ size_t header_len;
+ int actual_hunks = 0, num_hunks;
+ float expected_progress;
+
+ num_files++;
+
+ expected_progress = (float)num_files / 2.0f;
+ cl_assert(expected_progress == git_diff_iterator_progress(iter));
+
+ num_hunks = git_diff_iterator_num_hunks_in_file(iter);
+
+ while (!(error = git_diff_iterator_next_hunk(
+ &range, &header, &header_len, iter)))
+ {
+ int actual_lines = 0;
+ int num_lines = git_diff_iterator_num_lines_in_hunk(iter);
+ char origin;
+ const char *line;
+ size_t line_len;
+
+ while (!(error = git_diff_iterator_next_line(
+ &origin, &line, &line_len, iter)))
+ {
+ actual_lines++;
+ }
+
+ cl_assert_equal_i(GIT_ITEROVER, error);
+ cl_assert_equal_i(actual_lines, num_lines);
+
+ actual_hunks++;
+ }
+
+ cl_assert_equal_i(GIT_ITEROVER, error);
+ cl_assert_equal_i(actual_hunks, num_hunks);
+ }
+
+ cl_assert_equal_i(GIT_ITEROVER, error);
+ cl_assert_equal_i(2, num_files);
+ cl_assert(git_diff_iterator_progress(iter) == 1.0f);
+
+ git_diff_iterator_free(iter);
+ git_diff_list_free(diff);
+ diff = NULL;
+
+ git_tree_free(a);
+ git_tree_free(b);
+}
diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c
index eac7eb87d..40a888544 100644
--- a/tests-clar/diff/workdir.c
+++ b/tests-clar/diff/workdir.c
@@ -670,3 +670,94 @@ void test_diff_workdir__eof_newline_changes(void)
*
* Expect 13 files, 0 ADD, 4 DEL, 4 MOD, 1 IGN, 4 UNTR
*/
+
+
+void test_diff_workdir__larger_hunks(void)
+{
+ const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69";
+ const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10";
+ git_tree *a, *b;
+ git_diff_options opts = {0};
+ int i, error;
+
+ g_repo = cl_git_sandbox_init("diff");
+
+ cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL);
+ cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL);
+
+ opts.context_lines = 1;
+ opts.interhunk_lines = 0;
+
+ for (i = 0; i <= 2; ++i) {
+ git_diff_list *diff = NULL;
+ git_diff_iterator *iter = NULL;
+ git_diff_delta *delta;
+ int num_files = 0;
+
+ /* okay, this is a bit silly, but oh well */
+ switch (i) {
+ case 0:
+ cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
+ break;
+ case 1:
+ cl_git_pass(git_diff_workdir_to_tree(g_repo, &opts, a, &diff));
+ break;
+ case 2:
+ cl_git_pass(git_diff_workdir_to_tree(g_repo, &opts, b, &diff));
+ break;
+ }
+
+ cl_git_pass(git_diff_iterator_new(&iter, diff));
+
+ cl_assert(git_diff_iterator_progress(iter) == 0.0f);
+
+ while (!(error = git_diff_iterator_next_file(&delta, iter))) {
+ git_diff_range *range;
+ const char *header;
+ size_t header_len;
+ int actual_hunks = 0, num_hunks;
+ float expected_progress;
+
+ num_files++;
+
+ expected_progress = (float)num_files / 2.0f;
+ cl_assert(expected_progress == git_diff_iterator_progress(iter));
+
+ num_hunks = git_diff_iterator_num_hunks_in_file(iter);
+
+ while (!(error = git_diff_iterator_next_hunk(
+ &range, &header, &header_len, iter)))
+ {
+ int actual_lines = 0;
+ int num_lines = git_diff_iterator_num_lines_in_hunk(iter);
+ char origin;
+ const char *line;
+ size_t line_len;
+
+ while (!(error = git_diff_iterator_next_line(
+ &origin, &line, &line_len, iter)))
+ {
+ actual_lines++;
+ }
+
+ cl_assert_equal_i(GIT_ITEROVER, error);
+ cl_assert_equal_i(actual_lines, num_lines);
+
+ actual_hunks++;
+ }
+
+ cl_assert_equal_i(GIT_ITEROVER, error);
+ cl_assert_equal_i(actual_hunks, num_hunks);
+ }
+
+ cl_assert_equal_i(GIT_ITEROVER, error);
+ cl_assert_equal_i(2, num_files);
+ cl_assert(git_diff_iterator_progress(iter) == 1.0f);
+
+ git_diff_iterator_free(iter);
+ git_diff_list_free(diff);
+ }
+
+ git_tree_free(a);
+ git_tree_free(b);
+}
diff --git a/tests-clar/resources/diff/.gitted/HEAD b/tests-clar/resources/diff/.gitted/HEAD
new file mode 100644
index 000000000..cb089cd89
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests-clar/resources/diff/.gitted/config b/tests-clar/resources/diff/.gitted/config
new file mode 100644
index 000000000..77a27ef1d
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/config
@@ -0,0 +1,6 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+ ignorecase = false
diff --git a/tests-clar/resources/diff/.gitted/description b/tests-clar/resources/diff/.gitted/description
new file mode 100644
index 000000000..498b267a8
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/tests-clar/resources/diff/.gitted/index b/tests-clar/resources/diff/.gitted/index
new file mode 100644
index 000000000..e1071874e
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/index
Binary files differ
diff --git a/tests-clar/resources/diff/.gitted/info/exclude b/tests-clar/resources/diff/.gitted/info/exclude
new file mode 100644
index 000000000..a5196d1be
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests-clar/resources/diff/.gitted/logs/HEAD b/tests-clar/resources/diff/.gitted/logs/HEAD
new file mode 100644
index 000000000..8c6f6fd18
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/logs/HEAD
@@ -0,0 +1,2 @@
+0000000000000000000000000000000000000000 d70d245ed97ed2aa596dd1af6536e4bfdb047b69 Russell Belfer <rb@github.com> 1347559804 -0700 commit (initial): initial commit
+d70d245ed97ed2aa596dd1af6536e4bfdb047b69 7a9e0b02e63179929fed24f0a3e0f19168114d10 Russell Belfer <rb@github.com> 1347560491 -0700 commit: some changes
diff --git a/tests-clar/resources/diff/.gitted/logs/refs/heads/master b/tests-clar/resources/diff/.gitted/logs/refs/heads/master
new file mode 100644
index 000000000..8c6f6fd18
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/logs/refs/heads/master
@@ -0,0 +1,2 @@
+0000000000000000000000000000000000000000 d70d245ed97ed2aa596dd1af6536e4bfdb047b69 Russell Belfer <rb@github.com> 1347559804 -0700 commit (initial): initial commit
+d70d245ed97ed2aa596dd1af6536e4bfdb047b69 7a9e0b02e63179929fed24f0a3e0f19168114d10 Russell Belfer <rb@github.com> 1347560491 -0700 commit: some changes
diff --git a/tests-clar/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7 b/tests-clar/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7
new file mode 100644
index 000000000..94f9a676d
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7
Binary files differ
diff --git a/tests-clar/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 b/tests-clar/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847
new file mode 100644
index 000000000..9fed523dc
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847
Binary files differ
diff --git a/tests-clar/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 b/tests-clar/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989
new file mode 100644
index 000000000..d7df4d6a1
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989
Binary files differ
diff --git a/tests-clar/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10 b/tests-clar/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10
new file mode 100644
index 000000000..9bc25eb34
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10
Binary files differ
diff --git a/tests-clar/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693 b/tests-clar/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693
new file mode 100644
index 000000000..2fd266be6
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693
Binary files differ
diff --git a/tests-clar/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c b/tests-clar/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c
new file mode 100644
index 000000000..7598b5914
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c
@@ -0,0 +1 @@
+x+)JMU07g040031QH/H-+(a)[wz {j%;ʊRSrS4W4そN+a \ No newline at end of file
diff --git a/tests-clar/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455 b/tests-clar/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455
new file mode 100644
index 000000000..86ebe04fe
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455
Binary files differ
diff --git a/tests-clar/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 b/tests-clar/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69
new file mode 100644
index 000000000..99304c4aa
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69
@@ -0,0 +1 @@
+x !m_RB:XkVpWp 9{ ,^z#7JygԚA i1Y2VyR)𢒨'm[;-lO_#%v8 \ No newline at end of file
diff --git a/tests-clar/resources/diff/.gitted/refs/heads/master b/tests-clar/resources/diff/.gitted/refs/heads/master
new file mode 100644
index 000000000..a83afc38b
--- /dev/null
+++ b/tests-clar/resources/diff/.gitted/refs/heads/master
@@ -0,0 +1 @@
+7a9e0b02e63179929fed24f0a3e0f19168114d10
diff --git a/tests-clar/resources/diff/another.txt b/tests-clar/resources/diff/another.txt
new file mode 100644
index 000000000..d0e0bae4d
--- /dev/null
+++ b/tests-clar/resources/diff/another.txt
@@ -0,0 +1,38 @@
+Git is fast. With Git, nearly all operations are performed locally, giving
+it an huge speed advantage on centralized systems that constantly have to
+communicate with a server somewh3r3.
+
+For testing, large AWS instances were set up in the same availability
+zone. Git and SVN were installed on both machines, the Ruby repository was
+copied to both Git and SVN servers, and common operations were performed on
+both.
+
+In some cases the commands don't match up exactly. Here, matching on the
+lowest common denominator was attempted. For example, the 'commit' tests
+also include the time to push for Git, though most of the time you would not
+actually be pushing to the server immediately after a commit where the two
+commands cannot be separated in SVN.
+
+Note that this is the best case scenario for SVN - a server with no load
+with an 80MB/s bandwidth connection to the client machine. Nearly all of
+these times would be even worse for SVN if that connection was slower, while
+many of the Git times would not be affected.
+
+Clearly, in many of these common version control operations, Git is one or
+two orders of magnitude faster than SVN, even under ideal conditions for
+SVN.
+
+Let's see how common operations stack up against Subversion, a common
+centralized version control system that is similar to CVS or
+Perforce. Smaller is faster.
+
+One place where Git is slower is in the initial clone operation. Here, Git
+One place where Git is slower is in the initial clone operation. Here, Git
+One place where Git is slower is in the initial clone operation. Here, Git
+seen in the above charts, it's not considerably slower for an operation that
+is only performed once.
+
+It's also interesting to note that the size of the data on the client side
+is very similar even though Git also has every version of every file for the
+entire history of the project. This illustrates how efficient it is at
+compressing and storing data on the client side. \ No newline at end of file
diff --git a/tests-clar/resources/diff/readme.txt b/tests-clar/resources/diff/readme.txt
new file mode 100644
index 000000000..beedf288d
--- /dev/null
+++ b/tests-clar/resources/diff/readme.txt
@@ -0,0 +1,36 @@
+The Git feature that r3ally mak3s it stand apart from n3arly 3v3ry other SCM
+out there is its branching model.
+
+Git allows and encourages you to have multiple local branches that can be
+entirely independent of each other. The creation, merging, and deletion of
+those lines of development takes seconds.
+
+Git allows and encourages you to have multiple local branches that can be
+entirely independent of each other. The creation, merging, and deletion of
+those lines of development takes seconds.
+
+This means that you can do things like:
+
+Role-Bas3d Codelin3s. Have a branch that always contains only what goes to
+production, another that you merge work into for testing, and several
+smaller ones for day to day work.
+
+Feature Based Workflow. Create new branches for each new feature you're
+working on so you can seamlessly switch back and forth between them, then
+delete each branch when that feature gets merged into your main line.
+
+Disposable Experimentation. Create a branch to experiment in, realize it's
+not going to work, and just delete it - abandoning the work—with nobody else
+ever seeing it (even if you've pushed other branches in the meantime).
+
+Notably, when you push to a remote repository, you do not have to push all
+share it with others.
+
+Git allows and encourages you to have multiple local branches that can be
+entirely independent of each other. The creation, merging, and deletion of
+those lines of development takes seconds.
+
+There are ways to accomplish some of this with other systems, but the work
+involved is much more difficult and error-prone. Git makes this process
+incredibly easy and it changes the way most developers work when they learn
+it.!