diff options
author | Vicent Marti <vicent@github.com> | 2014-02-28 09:40:17 +0100 |
---|---|---|
committer | Vicent Marti <vicent@github.com> | 2014-02-28 09:40:17 +0100 |
commit | 06d41826b6f85d83e68973e0565978b6b3e8976f (patch) | |
tree | 74ca53d8808a16090bb4df867b38c4a07444f8e1 /src | |
parent | 1574d3884f020c072f68c08785e199732e438e34 (diff) | |
parent | 6789b7a75d1e24a7f4ce34628c6b4561517f0b73 (diff) | |
download | libgit2-06d41826b6f85d83e68973e0565978b6b3e8976f.tar.gz |
Merge pull request #2146 from libgit2/rb/diff-b2b
Add git_diff_buffers and git_patch_from_buffers
Diffstat (limited to 'src')
-rw-r--r-- | src/diff_file.c | 49 | ||||
-rw-r--r-- | src/diff_file.h | 20 | ||||
-rw-r--r-- | src/diff_patch.c | 230 |
3 files changed, 138 insertions, 161 deletions
diff --git a/src/diff_file.c b/src/diff_file.c index fb5d674f7..7dabf8d6f 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -127,57 +127,38 @@ int git_diff_file_content__init_from_diff( return diff_file_content_init_common(fc, &diff->opts); } -int git_diff_file_content__init_from_blob( +int git_diff_file_content__init_from_src( git_diff_file_content *fc, git_repository *repo, const git_diff_options *opts, - const git_blob *blob, + const git_diff_file_content_src *src, git_diff_file *as_file) { memset(fc, 0, sizeof(*fc)); fc->repo = repo; fc->file = as_file; - fc->blob = blob; + fc->blob = src->blob; - if (!blob) { + if (!src->blob && !src->buf) { fc->flags |= GIT_DIFF_FLAG__NO_DATA; } else { fc->flags |= GIT_DIFF_FLAG__LOADED; fc->file->flags |= GIT_DIFF_FLAG_VALID_ID; - fc->file->size = git_blob_rawsize(blob); fc->file->mode = GIT_FILEMODE_BLOB; - git_oid_cpy(&fc->file->id, git_blob_id(blob)); - fc->map.len = (size_t)fc->file->size; - fc->map.data = (char *)git_blob_rawcontent(blob); - } + if (src->blob) { + fc->file->size = git_blob_rawsize(src->blob); + git_oid_cpy(&fc->file->id, git_blob_id(src->blob)); - return diff_file_content_init_common(fc, opts); -} + fc->map.len = (size_t)fc->file->size; + fc->map.data = (char *)git_blob_rawcontent(src->blob); + } else { + fc->file->size = src->buflen; + git_odb_hash(&fc->file->id, src->buf, src->buflen, GIT_OBJ_BLOB); -int git_diff_file_content__init_from_raw( - git_diff_file_content *fc, - git_repository *repo, - const git_diff_options *opts, - const char *buf, - size_t buflen, - git_diff_file *as_file) -{ - memset(fc, 0, sizeof(*fc)); - fc->repo = repo; - fc->file = as_file; - - if (!buf) { - fc->flags |= GIT_DIFF_FLAG__NO_DATA; - } else { - fc->flags |= GIT_DIFF_FLAG__LOADED; - fc->file->flags |= GIT_DIFF_FLAG_VALID_ID; - fc->file->size = buflen; - fc->file->mode = GIT_FILEMODE_BLOB; - git_odb_hash(&fc->file->id, buf, buflen, GIT_OBJ_BLOB); - - fc->map.len = buflen; - fc->map.data = (char *)buf; + fc->map.len = src->buflen; + fc->map.data = (char *)src->buf; + } } return diff_file_content_init_common(fc, opts); diff --git a/src/diff_file.h b/src/diff_file.h index 84bf255aa..4d290ad43 100644 --- a/src/diff_file.h +++ b/src/diff_file.h @@ -31,19 +31,21 @@ extern int git_diff_file_content__init_from_diff( size_t delta_index, bool use_old); -extern int git_diff_file_content__init_from_blob( - git_diff_file_content *fc, - git_repository *repo, - const git_diff_options *opts, - const git_blob *blob, - git_diff_file *as_file); +typedef struct { + const git_blob *blob; + const void *buf; + size_t buflen; + const char *as_path; +} git_diff_file_content_src; + +#define GIT_DIFF_FILE_CONTENT_SRC__BLOB(BLOB,PATH) { (BLOB),NULL,0,(PATH) } +#define GIT_DIFF_FILE_CONTENT_SRC__BUF(BUF,LEN,PATH) { NULL,(BUF),(LEN),(PATH) } -extern int git_diff_file_content__init_from_raw( +extern int git_diff_file_content__init_from_src( git_diff_file_content *fc, git_repository *repo, const git_diff_options *opts, - const char *buf, - size_t buflen, + const git_diff_file_content_src *src, git_diff_file *as_file); /* this loads the blob/file-on-disk as needed */ diff --git a/src/diff_patch.c b/src/diff_patch.c index ecae3a8ed..dd8b73938 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -5,6 +5,7 @@ * a Linking Exception. For full terms see the included COPYING file. */ #include "common.h" +#include "git2/blob.h" #include "diff.h" #include "diff_file.h" #include "diff_driver.h" @@ -334,38 +335,45 @@ static int diff_single_generate(diff_patch_with_delta *pd, git_xdiff_output *xo) return error; } -static int diff_patch_from_blobs( +static int diff_patch_from_sources( diff_patch_with_delta *pd, git_xdiff_output *xo, - const git_blob *old_blob, - const char *old_path, - const git_blob *new_blob, - const char *new_path, + git_diff_file_content_src *oldsrc, + git_diff_file_content_src *newsrc, const git_diff_options *opts) { int error = 0; git_repository *repo = - new_blob ? git_object_owner((const git_object *)new_blob) : - old_blob ? git_object_owner((const git_object *)old_blob) : NULL; + oldsrc->blob ? git_blob_owner(oldsrc->blob) : + newsrc->blob ? git_blob_owner(newsrc->blob) : NULL; + git_diff_file *lfile = &pd->delta.old_file, *rfile = &pd->delta.new_file; + git_diff_file_content *ldata = &pd->patch.ofile, *rdata = &pd->patch.nfile; GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); if (opts && (opts->flags & GIT_DIFF_REVERSE) != 0) { - const git_blob *tmp_blob; - const char *tmp_path; - tmp_blob = old_blob; old_blob = new_blob; new_blob = tmp_blob; - tmp_path = old_path; old_path = new_path; new_path = tmp_path; + void *tmp = lfile; lfile = rfile; rfile = tmp; + tmp = ldata; ldata = rdata; rdata = tmp; } pd->patch.delta = &pd->delta; - pd->delta.old_file.path = old_path; - pd->delta.new_file.path = new_path; + if (!oldsrc->as_path) { + if (newsrc->as_path) + oldsrc->as_path = newsrc->as_path; + else + oldsrc->as_path = newsrc->as_path = "file"; + } + else if (!newsrc->as_path) + newsrc->as_path = oldsrc->as_path; + + lfile->path = oldsrc->as_path; + rfile->path = newsrc->as_path; - if ((error = git_diff_file_content__init_from_blob( - &pd->patch.ofile, repo, opts, old_blob, &pd->delta.old_file)) < 0 || - (error = git_diff_file_content__init_from_blob( - &pd->patch.nfile, repo, opts, new_blob, &pd->delta.new_file)) < 0) + if ((error = git_diff_file_content__init_from_src( + ldata, repo, opts, oldsrc, lfile)) < 0 || + (error = git_diff_file_content__init_from_src( + rdata, repo, opts, newsrc, rfile)) < 0) return error; return diff_single_generate(pd, xo); @@ -400,11 +408,9 @@ static int diff_patch_with_delta_alloc( return 0; } -int git_diff_blobs( - const git_blob *old_blob, - const char *old_path, - const git_blob *new_blob, - const char *new_path, +static int diff_from_sources( + git_diff_file_content_src *oldsrc, + git_diff_file_content_src *newsrc, const git_diff_options *opts, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, @@ -420,26 +426,19 @@ int git_diff_blobs( &xo.output, opts, file_cb, hunk_cb, data_cb, payload); git_xdiff_init(&xo, opts); - if (!old_path && new_path) - old_path = new_path; - else if (!new_path && old_path) - new_path = old_path; - memset(&pd, 0, sizeof(pd)); - error = diff_patch_from_blobs( - &pd, &xo, old_blob, old_path, new_blob, new_path, opts); + + error = diff_patch_from_sources(&pd, &xo, oldsrc, newsrc, opts); git_patch_free(&pd.patch); return error; } -int git_patch_from_blobs( +static int patch_from_sources( git_patch **out, - const git_blob *old_blob, - const char *old_path, - const git_blob *new_blob, - const char *new_path, + git_diff_file_content_src *oldsrc, + git_diff_file_content_src *newsrc, const git_diff_options *opts) { int error = 0; @@ -449,17 +448,15 @@ int git_patch_from_blobs( assert(out); *out = NULL; - if (diff_patch_with_delta_alloc(&pd, &old_path, &new_path) < 0) - return -1; + if ((error = diff_patch_with_delta_alloc( + &pd, &oldsrc->as_path, &newsrc->as_path)) < 0) + return error; memset(&xo, 0, sizeof(xo)); diff_output_to_patch(&xo.output, &pd->patch); git_xdiff_init(&xo, opts); - error = diff_patch_from_blobs( - pd, &xo, old_blob, old_path, new_blob, new_path, opts); - - if (!error) + if (!(error = diff_patch_from_sources(pd, &xo, oldsrc, newsrc, opts))) *out = (git_patch *)pd; else git_patch_free((git_patch *)pd); @@ -467,46 +464,38 @@ int git_patch_from_blobs( return error; } -static int diff_patch_from_blob_and_buffer( - diff_patch_with_delta *pd, - git_xdiff_output *xo, +int git_diff_blobs( const git_blob *old_blob, const char *old_path, - const char *buf, - size_t buflen, - const char *buf_path, - const git_diff_options *opts) + const git_blob *new_blob, + const char *new_path, + const git_diff_options *opts, + git_diff_file_cb file_cb, + git_diff_hunk_cb hunk_cb, + git_diff_line_cb data_cb, + void *payload) { - int error = 0; - git_repository *repo = - old_blob ? git_object_owner((const git_object *)old_blob) : NULL; - - GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); - - pd->patch.delta = &pd->delta; - - if (opts && (opts->flags & GIT_DIFF_REVERSE) != 0) { - pd->delta.old_file.path = buf_path; - pd->delta.new_file.path = old_path; - - if (!(error = git_diff_file_content__init_from_raw( - &pd->patch.ofile, repo, opts, buf, buflen, &pd->delta.old_file))) - error = git_diff_file_content__init_from_blob( - &pd->patch.nfile, repo, opts, old_blob, &pd->delta.new_file); - } else { - pd->delta.old_file.path = old_path; - pd->delta.new_file.path = buf_path; - - if (!(error = git_diff_file_content__init_from_blob( - &pd->patch.ofile, repo, opts, old_blob, &pd->delta.old_file))) - error = git_diff_file_content__init_from_raw( - &pd->patch.nfile, repo, opts, buf, buflen, &pd->delta.new_file); - } - - if (error < 0) - return error; + git_diff_file_content_src osrc = + GIT_DIFF_FILE_CONTENT_SRC__BLOB(old_blob, old_path); + git_diff_file_content_src nsrc = + GIT_DIFF_FILE_CONTENT_SRC__BLOB(new_blob, new_path); + return diff_from_sources( + &osrc, &nsrc, opts, file_cb, hunk_cb, data_cb, payload); +} - return diff_single_generate(pd, xo); +int git_patch_from_blobs( + git_patch **out, + const git_blob *old_blob, + const char *old_path, + const git_blob *new_blob, + const char *new_path, + const git_diff_options *opts) +{ + git_diff_file_content_src osrc = + GIT_DIFF_FILE_CONTENT_SRC__BLOB(old_blob, old_path); + git_diff_file_content_src nsrc = + GIT_DIFF_FILE_CONTENT_SRC__BLOB(new_blob, new_path); + return patch_from_sources(out, &osrc, &nsrc, opts); } int git_diff_blob_to_buffer( @@ -521,27 +510,12 @@ int git_diff_blob_to_buffer( git_diff_line_cb data_cb, void *payload) { - int error = 0; - diff_patch_with_delta pd; - git_xdiff_output xo; - - memset(&xo, 0, sizeof(xo)); - diff_output_init( - &xo.output, opts, file_cb, hunk_cb, data_cb, payload); - git_xdiff_init(&xo, opts); - - if (!old_path && buf_path) - old_path = buf_path; - else if (!buf_path && old_path) - buf_path = old_path; - - memset(&pd, 0, sizeof(pd)); - error = diff_patch_from_blob_and_buffer( - &pd, &xo, old_blob, old_path, buf, buflen, buf_path, opts); - - git_patch_free(&pd.patch); - - return error; + git_diff_file_content_src osrc = + GIT_DIFF_FILE_CONTENT_SRC__BLOB(old_blob, old_path); + git_diff_file_content_src nsrc = + GIT_DIFF_FILE_CONTENT_SRC__BUF(buf, buflen, buf_path); + return diff_from_sources( + &osrc, &nsrc, opts, file_cb, hunk_cb, data_cb, payload); } int git_patch_from_blob_and_buffer( @@ -553,29 +527,49 @@ int git_patch_from_blob_and_buffer( const char *buf_path, const git_diff_options *opts) { - int error = 0; - diff_patch_with_delta *pd; - git_xdiff_output xo; - - assert(out); - *out = NULL; - - if (diff_patch_with_delta_alloc(&pd, &old_path, &buf_path) < 0) - return -1; - - memset(&xo, 0, sizeof(xo)); - diff_output_to_patch(&xo.output, &pd->patch); - git_xdiff_init(&xo, opts); - - error = diff_patch_from_blob_and_buffer( - pd, &xo, old_blob, old_path, buf, buflen, buf_path, opts); + git_diff_file_content_src osrc = + GIT_DIFF_FILE_CONTENT_SRC__BLOB(old_blob, old_path); + git_diff_file_content_src nsrc = + GIT_DIFF_FILE_CONTENT_SRC__BUF(buf, buflen, buf_path); + return patch_from_sources(out, &osrc, &nsrc, opts); +} - if (!error) - *out = (git_patch *)pd; - else - git_patch_free((git_patch *)pd); +int git_diff_buffers( + const void *old_buf, + size_t old_len, + const char *old_path, + const void *new_buf, + size_t new_len, + const char *new_path, + const git_diff_options *opts, + git_diff_file_cb file_cb, + git_diff_hunk_cb hunk_cb, + git_diff_line_cb data_cb, + void *payload) +{ + git_diff_file_content_src osrc = + GIT_DIFF_FILE_CONTENT_SRC__BUF(old_buf, old_len, old_path); + git_diff_file_content_src nsrc = + GIT_DIFF_FILE_CONTENT_SRC__BUF(new_buf, new_len, new_path); + return diff_from_sources( + &osrc, &nsrc, opts, file_cb, hunk_cb, data_cb, payload); +} - return error; +int git_patch_from_buffers( + git_patch **out, + const void *old_buf, + size_t old_len, + const char *old_path, + const char *new_buf, + size_t new_len, + const char *new_path, + const git_diff_options *opts) +{ + git_diff_file_content_src osrc = + GIT_DIFF_FILE_CONTENT_SRC__BUF(old_buf, old_len, old_path); + git_diff_file_content_src nsrc = + GIT_DIFF_FILE_CONTENT_SRC__BUF(new_buf, new_len, new_path); + return patch_from_sources(out, &osrc, &nsrc, opts); } int git_patch_from_diff( |