]> git.proxmox.com Git - libgit2.git/commitdiff
Teach `git_patch_from_diff` about parsed diffs
authorEdward Thomson <ethomson@github.com>
Wed, 24 Aug 2016 04:38:39 +0000 (23:38 -0500)
committerEdward Thomson <ethomson@github.com>
Wed, 24 Aug 2016 14:08:57 +0000 (09:08 -0500)
Ensure that `git_patch_from_diff` can return the patch for parsed diffs,
not just generate a patch for a generated diff.

src/diff.h
src/diff_generate.c
src/diff_parse.c
src/diff_parse.h [new file with mode: 0644]
src/patch.c
src/patch_generate.c
src/patch_generate.h
src/patch_parse.c
src/patch_parse.h
tests/diff/parse.c

index 2c0e52ca21d49cf1737d8e38958e498360922a26..5750d2a0903922570d19608ae6542e81b9783f0d 100644 (file)
@@ -8,6 +8,7 @@
 #define INCLUDE_diff_h__
 
 #include "git2/diff.h"
+#include "git2/patch.h"
 #include "git2/sys/diff.h"
 #include "git2/oid.h"
 
@@ -44,6 +45,7 @@ struct git_diff {
        int (*pfxcomp)(const char *str, const char *pfx);
        int (*entrycomp)(const void *a, const void *b);
 
+       int (*patch_fn)(git_patch **out, git_diff *diff, size_t idx);
        void (*free_fn)(git_diff *diff);
 };
 
index a996bf156a2ec55254afdb70f773e1a53fcf8885..06f9b19c74a3598176b54526f3df8ee9b530c7ec 100644 (file)
@@ -7,6 +7,7 @@
 #include "common.h"
 #include "diff.h"
 #include "diff_generate.h"
+#include "patch_generate.h"
 #include "fileops.h"
 #include "config.h"
 #include "attr_file.h"
@@ -414,6 +415,7 @@ static git_diff_generated *diff_generated_alloc(
        diff->base.repo = repo;
        diff->base.old_src = old_iter->type;
        diff->base.new_src = new_iter->type;
+       diff->base.patch_fn = git_patch_generated_from_diff;
        diff->base.free_fn = diff_generated_free;
        memcpy(&diff->base.opts, &dflt, sizeof(git_diff_options));
 
index ffdc8df88857cd3c4c5b8cca946e96f2249eae95..e640063af2918a1ab451d27dd09f763d6a48ddcd 100644 (file)
@@ -6,15 +6,10 @@
  */
 #include "common.h"
 #include "diff.h"
+#include "diff_parse.h"
 #include "patch.h"
 #include "patch_parse.h"
 
-typedef struct {
-       struct git_diff base;
-
-       git_vector patches;
-} git_diff_parsed;
-
 static void diff_parsed_free(git_diff *d)
 {
        git_diff_parsed *diff = (git_diff_parsed *)d;
@@ -47,6 +42,7 @@ static git_diff_parsed *diff_parsed_alloc(void)
        diff->base.strncomp = git__strncmp;
        diff->base.pfxcomp = git__prefixcmp;
        diff->base.entrycomp = git_diff__entry_cmp;
+       diff->base.patch_fn = git_patch_parsed_from_diff;
        diff->base.free_fn = diff_parsed_free;
 
        git_pool_init(&diff->base.pool, 1);
diff --git a/src/diff_parse.h b/src/diff_parse.h
new file mode 100644 (file)
index 0000000..c47d4cb
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_diff_parse_h__
+#define INCLUDE_diff_parse_h__
+
+#include "diff.h"
+
+typedef struct {
+       struct git_diff base;
+
+       git_vector patches;
+} git_diff_parsed;
+
+#endif
index e14ffa9c01f4c0930d806a3f850667c6068df41d..ad24b07147c1d00c942cc2c1cdc46175fd17ad88 100644 (file)
@@ -194,6 +194,12 @@ int git_patch_get_line_in_hunk(
        return 0;
 }
 
+int git_patch_from_diff(git_patch **out, git_diff *diff, size_t idx)
+{
+       assert(out && diff && diff->patch_fn);
+       return diff->patch_fn(out, diff, idx);
+}
+
 static void git_patch__free(git_patch *patch)
 {
        if (patch->free_fn)
index feac4f67a295c4691e4ad6a38933a6929f0d6390..927786a437b1876900742aa787722b6b780e9dc0 100644 (file)
@@ -746,7 +746,7 @@ int git_patch_from_buffers(
        return patch_from_sources(out, &osrc, &nsrc, opts);
 }
 
-int git_patch_from_diff(
+int git_patch_generated_from_diff(
        git_patch **patch_ptr, git_diff *diff, size_t idx)
 {
        int error = 0;
index bb26a76e54bffc9e2102f137b919838538f5112e..2e89b5c4dc576fbe9e58fac6678fb887a0caf5f8 100644 (file)
@@ -42,6 +42,8 @@ extern void git_patch_generated_old_data(
        char **, size_t *, git_patch_generated *);
 extern void git_patch_generated_new_data(
        char **, size_t *, git_patch_generated *);
+extern int git_patch_generated_from_diff(
+       git_patch **, git_diff *, size_t);
 
 typedef struct git_patch_generated_output git_patch_generated_output;
 
index 82d2d3e2ecac7e7b9aa4f2ee20178768e1e1ef02..44bcf8f758796e655575df36e49125ee8e1a57dd 100644 (file)
@@ -7,6 +7,7 @@
 #include "git2/patch.h"
 #include "patch.h"
 #include "patch_parse.h"
+#include "diff_parse.h"
 #include "path.h"
 
 #define parse_err(...) \
@@ -1025,6 +1026,20 @@ void git_patch_parse_ctx_free(git_patch_parse_ctx *ctx)
        GIT_REFCOUNT_DEC(ctx, patch_parse_ctx_free);
 }
 
+int git_patch_parsed_from_diff(git_patch **out, git_diff *d, size_t idx)
+{
+       git_diff_parsed *diff = (git_diff_parsed *)d;
+       git_patch *p;
+
+       if ((p = git_vector_get(&diff->patches, idx)) == NULL)
+               return -1;
+
+       GIT_REFCOUNT_INC(p);
+       *out = p;
+
+       return 0;
+}
+
 static void patch_parsed__free(git_patch *p)
 {
        git_patch_parsed *patch = (git_patch_parsed *)p;
index da56dad7c70b3c40f9a7a4439a1b4b46ce630b9c..99eb4587be1f2e665b385b47cfc7edea9c4db078 100644 (file)
@@ -51,4 +51,6 @@ extern int git_patch_parse(
        git_patch **out,
        git_patch_parse_ctx *ctx);
 
+extern int git_patch_parsed_from_diff(git_patch **, git_diff *, size_t);
+
 #endif
index 83000a92daa2b162c39b05e63aac45ec5fadc71e..a06813d1bb77914399c064c3d471d003db051f81 100644 (file)
@@ -2,6 +2,7 @@
 #include "patch.h"
 #include "patch_parse.h"
 #include "diff_helpers.h"
+#include "../src/diff.h"
 
 #include "../patch/patch_common.h"
 
@@ -151,3 +152,47 @@ void test_diff_parse__can_parse_generated_diff(void)
                GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED | GIT_DIFF_FIND_EXACT_MATCH_ONLY);
 }
 
+void test_diff_parse__get_patch_from_diff(void)
+{
+       git_repository *repo;
+       git_diff *computed, *parsed;
+       git_tree *a, *b;
+       git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+       git_buf computed_buf = GIT_BUF_INIT;
+       git_patch *patch_computed, *patch_parsed;
+
+       repo = cl_git_sandbox_init("diff");
+
+       opts.flags = GIT_DIFF_SHOW_BINARY;
+
+       cl_assert((a = resolve_commit_oid_to_tree(repo,
+               "d70d245ed97ed2aa596dd1af6536e4bfdb047b69")) != NULL);
+       cl_assert((b = resolve_commit_oid_to_tree(repo,
+               "7a9e0b02e63179929fed24f0a3e0f19168114d10")) != NULL);
+
+       cl_git_pass(git_diff_tree_to_tree(&computed, repo, a, b, &opts));
+       cl_git_pass(git_diff_to_buf(&computed_buf,
+               computed, GIT_DIFF_FORMAT_PATCH));
+       cl_git_pass(git_patch_from_diff(&patch_computed, computed, 0));
+
+       cl_git_pass(git_diff_from_buffer(&parsed,
+               computed_buf.ptr, computed_buf.size));
+       cl_git_pass(git_patch_from_diff(&patch_parsed, parsed, 0));
+
+       cl_assert_equal_i(
+               git_patch_num_hunks(patch_computed),
+               git_patch_num_hunks(patch_parsed));
+
+       git_patch_free(patch_computed);
+       git_patch_free(patch_parsed);
+
+       git_tree_free(a);
+       git_tree_free(b);
+
+       git_diff_free(computed);
+       git_diff_free(parsed);
+
+       git_buf_free(&computed_buf);
+
+       cl_git_sandbox_cleanup();
+}