summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@github.com>2022-02-11 18:00:11 -0500
committerEdward Thomson <ethomson@github.com>2022-02-11 18:00:11 -0500
commit458547bd397473fd7664484510a075c18a7b55ab (patch)
tree0bafd5184e04a49a68149fc80eb66270f0935273
parente651cb1463b971e67eeed0ae2a7c75fb8c547bcc (diff)
downloadlibgit2-458547bd397473fd7664484510a075c18a7b55ab.tar.gz
diff: provide a flag for whether size is known
Much like we may produce diffs that do not have valid object IDs because we don't know them (yet), we may also produce diffs that do not have valid sizes. Previously, we used a `0` size to indicate unknown, but this is obviously deficient since we could _know_ that a file is 0 bytes. Create a new flag that indicates that we positively know the size of the file.
-rw-r--r--include/git2/diff.h3
-rw-r--r--src/diff_generate.c24
-rw-r--r--src/diff_generate.h4
-rw-r--r--src/diff_tform.c3
-rw-r--r--src/oid.h3
5 files changed, 34 insertions, 3 deletions
diff --git a/include/git2/diff.h b/include/git2/diff.h
index 9424ffd06..3839f0033 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -207,7 +207,8 @@ typedef enum {
GIT_DIFF_FLAG_BINARY = (1u << 0), /**< file(s) treated as binary data */
GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /**< file(s) treated as text data */
GIT_DIFF_FLAG_VALID_ID = (1u << 2), /**< `id` value is known correct */
- GIT_DIFF_FLAG_EXISTS = (1u << 3) /**< file exists at this side of the delta */
+ GIT_DIFF_FLAG_EXISTS = (1u << 3), /**< file exists at this side of the delta */
+ GIT_DIFF_FLAG_VALID_SIZE = (1u << 4) /**< file size value is known correct */
} git_diff_flag_t;
/**
diff --git a/src/diff_generate.c b/src/diff_generate.c
index dca16d51a..cfaefba66 100644
--- a/src/diff_generate.c
+++ b/src/diff_generate.c
@@ -117,6 +117,26 @@ static bool diff_pathspec_match(
matched_pathspec, NULL);
}
+static void diff_delta__flag_known_size(git_diff_file *file)
+{
+ /*
+ * If we don't know the ID, that can only come from the workdir
+ * iterator, which means we *do* know the file size. This is a
+ * leaky abstraction, but alas. Otherwise, we test against the
+ * empty blob id.
+ */
+ if (file->size ||
+ !(file->flags & GIT_DIFF_FLAG_VALID_ID) ||
+ git_oid_equal(&file->id, &git_oid__empty_blob_sha1))
+ file->flags |= GIT_DIFF_FLAG_VALID_SIZE;
+}
+
+static void diff_delta__flag_known_sizes(git_diff_delta *delta)
+{
+ diff_delta__flag_known_size(&delta->old_file);
+ diff_delta__flag_known_size(&delta->new_file);
+}
+
static int diff_delta__from_one(
git_diff_generated *diff,
git_delta_t status,
@@ -182,6 +202,8 @@ static int diff_delta__from_one(
if (has_old || !git_oid_is_zero(&delta->new_file.id))
delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
+ diff_delta__flag_known_sizes(delta);
+
return diff_insert_delta(diff, delta, matched_pathspec);
}
@@ -244,6 +266,8 @@ static int diff_delta__from_two(
delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
}
+ diff_delta__flag_known_sizes(delta);
+
return diff_insert_delta(diff, delta, matched_pathspec);
}
diff --git a/src/diff_generate.h b/src/diff_generate.h
index f39bf6b2a..b782f29c6 100644
--- a/src/diff_generate.h
+++ b/src/diff_generate.h
@@ -119,8 +119,10 @@ GIT_INLINE(int) git_diff_file__resolve_zero_size(
git_odb_free(odb);
- if (!error)
+ if (!error) {
file->size = (git_object_size_t)len;
+ file->flags |= GIT_DIFF_FLAG_VALID_SIZE;
+ }
return error;
}
diff --git a/src/diff_tform.c b/src/diff_tform.c
index f9836d245..913d649b0 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -460,7 +460,8 @@ static int similarity_init(
info->blob = NULL;
git_str_init(&info->data, 0);
- if (info->file->size > 0 || info->src == GIT_ITERATOR_WORKDIR)
+ if ((info->file->flags & GIT_DIFF_FLAG_VALID_SIZE) ||
+ info->src == GIT_ITERATOR_WORKDIR)
return 0;
return git_diff_file__resolve_zero_size(
diff --git a/src/oid.h b/src/oid.h
index df434b2bf..09fe14fa8 100644
--- a/src/oid.h
+++ b/src/oid.h
@@ -11,6 +11,9 @@
#include "git2/oid.h"
+static git_oid git_oid__empty_blob_sha1 =
+ {{ 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,
+ 0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 }};
static git_oid git_oid__empty_tree_sha1 =
{{ 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 }};