Commit 74ded024 by Russell Belfer

Add "as_path" parameters to blob and buffer diffs

This adds parameters to the four functions that allow for blob-to-
blob and blob-to-buffer differencing (either via callbacks or by
making a git_diff_patch object).  These parameters let you say
that filename we should pretend the blob has while doing the diff.
If you pass NULL, there should be no change from the existing
behavior, which is to skip using attributes for file type checks
and just look at content.  With the parameters, you can plug into
the new diff driver functionality and get binary or non-binary
behavior, plus function context regular expressions, etc.

This commit also fixes things so that the git_diff_delta that is
generated by these functions will actually be populated with the
data that we know about the blobs (or buffers) so you can use it
appropriately.  It also fixes a bug in generating patches from
the git_diff_patch objects created via these functions.

Lastly, there is one other behavior change that may matter.  If
there is no difference between the two blobs, these functions no
longer generate any diff callbacks / patches unless you have
passed in GIT_DIFF_INCLUDE_UNMODIFIED.  This is pretty natural,
but could potentially change the behavior of existing usage.
parent c09810ee
...@@ -983,7 +983,9 @@ GIT_EXTERN(int) git_diff_patch_to_str( ...@@ -983,7 +983,9 @@ GIT_EXTERN(int) git_diff_patch_to_str(
* `GIT_DIFF_FORCE_TEXT` of course). * `GIT_DIFF_FORCE_TEXT` of course).
* *
* @param old_blob Blob for old side of diff, or NULL for empty blob * @param old_blob Blob for old side of diff, or NULL for empty blob
* @param old_as_path Treat old blob as if it had this filename; can be NULL
* @param new_blob Blob for new side of diff, or NULL for empty blob * @param new_blob Blob for new side of diff, or NULL for empty blob
* @param new_as_path Treat new blob as if it had this filename; can be NULL
* @param options Options for diff, or NULL for default options * @param options Options for diff, or NULL for default options
* @param file_cb Callback for "file"; made once if there is a diff; can be NULL * @param file_cb Callback for "file"; made once if there is a diff; can be NULL
* @param hunk_cb Callback for each hunk in diff; can be NULL * @param hunk_cb Callback for each hunk in diff; can be NULL
...@@ -993,7 +995,9 @@ GIT_EXTERN(int) git_diff_patch_to_str( ...@@ -993,7 +995,9 @@ GIT_EXTERN(int) git_diff_patch_to_str(
*/ */
GIT_EXTERN(int) git_diff_blobs( GIT_EXTERN(int) git_diff_blobs(
const git_blob *old_blob, const git_blob *old_blob,
const char *old_as_path,
const git_blob *new_blob, const git_blob *new_blob,
const char *new_as_path,
const git_diff_options *options, const git_diff_options *options,
git_diff_file_cb file_cb, git_diff_file_cb file_cb,
git_diff_hunk_cb hunk_cb, git_diff_hunk_cb hunk_cb,
...@@ -1010,14 +1014,18 @@ GIT_EXTERN(int) git_diff_blobs( ...@@ -1010,14 +1014,18 @@ GIT_EXTERN(int) git_diff_blobs(
* *
* @param out The generated patch; NULL on error * @param out The generated patch; NULL on error
* @param old_blob Blob for old side of diff, or NULL for empty blob * @param old_blob Blob for old side of diff, or NULL for empty blob
* @param old_as_path Treat old blob as if it had this filename; can be NULL
* @param new_blob Blob for new side of diff, or NULL for empty blob * @param new_blob Blob for new side of diff, or NULL for empty blob
* @param new_as_path Treat new blob as if it had this filename; can be NULL
* @param options Options for diff, or NULL for default options * @param options Options for diff, or NULL for default options
* @return 0 on success or error code < 0 * @return 0 on success or error code < 0
*/ */
GIT_EXTERN(int) git_diff_patch_from_blobs( GIT_EXTERN(int) git_diff_patch_from_blobs(
git_diff_patch **out, git_diff_patch **out,
const git_blob *old_blob, const git_blob *old_blob,
const char *old_as_path,
const git_blob *new_blob, const git_blob *new_blob,
const char *new_as_path,
const git_diff_options *opts); const git_diff_options *opts);
/** /**
...@@ -1033,8 +1041,10 @@ GIT_EXTERN(int) git_diff_patch_from_blobs( ...@@ -1033,8 +1041,10 @@ GIT_EXTERN(int) git_diff_patch_from_blobs(
* the reverse, with GIT_DELTA_REMOVED and blob content removed. * the reverse, with GIT_DELTA_REMOVED and blob content removed.
* *
* @param old_blob Blob for old side of diff, or NULL for empty blob * @param old_blob Blob for old side of diff, or NULL for empty blob
* @param old_as_path Treat old blob as if it had this filename; can be NULL
* @param buffer Raw data for new side of diff, or NULL for empty * @param buffer Raw data for new side of diff, or NULL for empty
* @param buffer_len Length of raw data for new side of diff * @param buffer_len Length of raw data for new side of diff
* @param buffer_as_path Treat buffer as if it had this filename; can be NULL
* @param options Options for diff, or NULL for default options * @param options Options for diff, or NULL for default options
* @param file_cb Callback for "file"; made once if there is a diff; can be NULL * @param file_cb Callback for "file"; made once if there is a diff; can be NULL
* @param hunk_cb Callback for each hunk in diff; can be NULL * @param hunk_cb Callback for each hunk in diff; can be NULL
...@@ -1044,8 +1054,10 @@ GIT_EXTERN(int) git_diff_patch_from_blobs( ...@@ -1044,8 +1054,10 @@ GIT_EXTERN(int) git_diff_patch_from_blobs(
*/ */
GIT_EXTERN(int) git_diff_blob_to_buffer( GIT_EXTERN(int) git_diff_blob_to_buffer(
const git_blob *old_blob, const git_blob *old_blob,
const char *old_as_path,
const char *buffer, const char *buffer,
size_t buffer_len, size_t buffer_len,
const char *buffer_as_path,
const git_diff_options *options, const git_diff_options *options,
git_diff_file_cb file_cb, git_diff_file_cb file_cb,
git_diff_hunk_cb hunk_cb, git_diff_hunk_cb hunk_cb,
...@@ -1062,16 +1074,20 @@ GIT_EXTERN(int) git_diff_blob_to_buffer( ...@@ -1062,16 +1074,20 @@ GIT_EXTERN(int) git_diff_blob_to_buffer(
* *
* @param out The generated patch; NULL on error * @param out The generated patch; NULL on error
* @param old_blob Blob for old side of diff, or NULL for empty blob * @param old_blob Blob for old side of diff, or NULL for empty blob
* @param old_as_path Treat old blob as if it had this filename; can be NULL
* @param buffer Raw data for new side of diff, or NULL for empty * @param buffer Raw data for new side of diff, or NULL for empty
* @param buffer_len Length of raw data for new side of diff * @param buffer_len Length of raw data for new side of diff
* @param buffer_as_path Treat buffer as if it had this filename; can be NULL
* @param options Options for diff, or NULL for default options * @param options Options for diff, or NULL for default options
* @return 0 on success or error code < 0 * @return 0 on success or error code < 0
*/ */
GIT_EXTERN(int) git_diff_patch_from_blob_and_buffer( GIT_EXTERN(int) git_diff_patch_from_blob_and_buffer(
git_diff_patch **out, git_diff_patch **out,
const git_blob *old_blob, const git_blob *old_blob,
const char *buf, const char *old_as_path,
size_t buflen, const char *buffer,
size_t buffer_len,
const char *buffer_as_path,
const git_diff_options *opts); const git_diff_options *opts);
......
...@@ -15,8 +15,9 @@ ...@@ -15,8 +15,9 @@
/* expanded information for one side of a delta */ /* expanded information for one side of a delta */
typedef struct { typedef struct {
git_repository *repo; git_repository *repo;
git_diff_file file; git_diff_file *file;
git_diff_driver *driver; git_diff_driver *driver;
uint32_t flags;
uint32_t opts_flags; uint32_t opts_flags;
git_off_t opts_max_size; git_off_t opts_max_size;
git_iterator_type_t src; git_iterator_type_t src;
...@@ -34,14 +35,16 @@ extern int git_diff_file_content__init_from_blob( ...@@ -34,14 +35,16 @@ extern int git_diff_file_content__init_from_blob(
git_diff_file_content *fc, git_diff_file_content *fc,
git_repository *repo, git_repository *repo,
const git_diff_options *opts, const git_diff_options *opts,
const git_blob *blob); const git_blob *blob,
git_diff_file *as_file);
extern int git_diff_file_content__init_from_raw( extern int git_diff_file_content__init_from_raw(
git_diff_file_content *fc, git_diff_file_content *fc,
git_repository *repo, git_repository *repo,
const git_diff_options *opts, const git_diff_options *opts,
const char *buf, const char *buf,
size_t buflen); size_t buflen,
git_diff_file *as_file);
/* this loads the blob/file-on-disk as needed */ /* this loads the blob/file-on-disk as needed */
extern int git_diff_file_content__load(git_diff_file_content *fc); extern int git_diff_file_content__load(git_diff_file_content *fc);
......
...@@ -21,14 +21,15 @@ static int diff_print_info_init( ...@@ -21,14 +21,15 @@ static int diff_print_info_init(
diff_print_info *pi, diff_print_info *pi,
git_buf *out, git_diff_list *diff, git_diff_data_cb cb, void *payload) git_buf *out, git_diff_list *diff, git_diff_data_cb cb, void *payload)
{ {
assert(diff && diff->repo);
pi->diff = diff; pi->diff = diff;
pi->print_cb = cb; pi->print_cb = cb;
pi->payload = payload; pi->payload = payload;
pi->buf = out; pi->buf = out;
if (git_repository__cvar(&pi->oid_strlen, diff->repo, GIT_CVAR_ABBREV) < 0) if (!diff || !diff->repo)
pi->oid_strlen = GIT_ABBREV_DEFAULT;
else if (git_repository__cvar(
&pi->oid_strlen, diff->repo, GIT_CVAR_ABBREV) < 0)
return -1; return -1;
pi->oid_strlen += 1; /* for NUL byte */ pi->oid_strlen += 1; /* for NUL byte */
...@@ -82,6 +83,8 @@ static int diff_print_one_compact( ...@@ -82,6 +83,8 @@ static int diff_print_one_compact(
diff_print_info *pi = data; diff_print_info *pi = data;
git_buf *out = pi->buf; git_buf *out = pi->buf;
char old_suffix, new_suffix, code = git_diff_status_char(delta->status); char old_suffix, new_suffix, code = git_diff_status_char(delta->status);
int (*strcomp)(const char *, const char *) =
pi->diff ? pi->diff->strcomp : git__strcmp;
GIT_UNUSED(progress); GIT_UNUSED(progress);
...@@ -94,7 +97,7 @@ static int diff_print_one_compact( ...@@ -94,7 +97,7 @@ static int diff_print_one_compact(
git_buf_clear(out); git_buf_clear(out);
if (delta->old_file.path != delta->new_file.path && if (delta->old_file.path != delta->new_file.path &&
pi->diff->strcomp(delta->old_file.path,delta->new_file.path) != 0) strcomp(delta->old_file.path,delta->new_file.path) != 0)
git_buf_printf(out, "%c\t%s%c -> %s%c\n", code, git_buf_printf(out, "%c\t%s%c -> %s%c\n", code,
delta->old_file.path, old_suffix, delta->new_file.path, new_suffix); delta->old_file.path, old_suffix, delta->new_file.path, new_suffix);
else if (delta->old_file.mode != delta->new_file.mode && else if (delta->old_file.mode != delta->new_file.mode &&
...@@ -229,10 +232,11 @@ static int diff_print_patch_file( ...@@ -229,10 +232,11 @@ static int diff_print_patch_file(
const git_diff_delta *delta, float progress, void *data) const git_diff_delta *delta, float progress, void *data)
{ {
diff_print_info *pi = data; diff_print_info *pi = data;
const char *oldpfx = pi->diff->opts.old_prefix; const char *oldpfx = pi->diff ? pi->diff->opts.old_prefix : NULL;
const char *oldpath = delta->old_file.path; const char *oldpath = delta->old_file.path;
const char *newpfx = pi->diff->opts.new_prefix; const char *newpfx = pi->diff ? pi->diff->opts.new_prefix : NULL;
const char *newpath = delta->new_file.path; const char *newpath = delta->new_file.path;
uint32_t opts_flags = pi->diff ? pi->diff->opts.flags : GIT_DIFF_NORMAL;
GIT_UNUSED(progress); GIT_UNUSED(progress);
...@@ -240,17 +244,17 @@ static int diff_print_patch_file( ...@@ -240,17 +244,17 @@ static int diff_print_patch_file(
delta->status == GIT_DELTA_UNMODIFIED || delta->status == GIT_DELTA_UNMODIFIED ||
delta->status == GIT_DELTA_IGNORED || delta->status == GIT_DELTA_IGNORED ||
(delta->status == GIT_DELTA_UNTRACKED && (delta->status == GIT_DELTA_UNTRACKED &&
(pi->diff->opts.flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0)) (opts_flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0))
return 0; return 0;
if (!oldpfx) if (!oldpfx)
oldpfx = DIFF_OLD_PREFIX_DEFAULT; oldpfx = DIFF_OLD_PREFIX_DEFAULT;
if (!newpfx) if (!newpfx)
newpfx = DIFF_NEW_PREFIX_DEFAULT; newpfx = DIFF_NEW_PREFIX_DEFAULT;
git_buf_clear(pi->buf); git_buf_clear(pi->buf);
git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", oldpfx, delta->old_file.path, newpfx, delta->new_file.path); git_buf_printf(pi->buf, "diff --git %s%s %s%s\n",
oldpfx, delta->old_file.path, newpfx, delta->new_file.path);
if (diff_print_oid_range(pi, delta) < 0) if (diff_print_oid_range(pi, delta) < 0)
return -1; return -1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment