Merge pull request #940 from scunz/diff_sm Diff: Show submodule diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
diff --git a/src/diff.c b/src/diff.c
index 77cbc3c..7a0051a 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -448,7 +448,11 @@ static int oid_for_workdir_item(
return -1;
/* calculate OID for file if possible*/
- if (S_ISLNK(item->mode))
+ if (S_ISGITLINK(item->mode)) {
+ /* Don't bother to figure out an oid for a submodule. We won't use it anyway. */
+ memset(oid, 0, sizeof(*oid));
+ result = 0;
+ } else if (S_ISLNK(item->mode))
result = git_odb__hashlink(oid, full_path.ptr);
else if (!git__is_sizet(item->file_size)) {
giterr_set(GITERR_OS, "File size overflow for 32-bit systems");
@@ -561,8 +565,11 @@ static int maybe_modified(
else if (git_submodule_ignore(sub) == GIT_SUBMODULE_IGNORE_ALL)
status = GIT_DELTA_UNMODIFIED;
else {
- /* TODO: support other GIT_SUBMODULE_IGNORE values */
- status = GIT_DELTA_UNMODIFIED;
+ unsigned int sm_status = 0;
+ if (git_submodule_status(&sm_status, sub) < 0)
+ return -1;
+ status = GIT_SUBMODULE_STATUS_IS_UNMODIFIED(sm_status)
+ ? GIT_DELTA_UNMODIFIED : GIT_DELTA_MODIFIED;
}
}
}
diff --git a/src/diff_output.c b/src/diff_output.c
index 8a099a4..f5f6c38 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -7,6 +7,7 @@
#include "common.h"
#include "git2/attr.h"
#include "git2/oid.h"
+#include "git2/submodule.h"
#include "diff_output.h"
#include <ctype.h>
#include "fileops.h"
@@ -212,6 +213,22 @@ static int get_blob_content(
if (git_oid_iszero(&file->oid))
return 0;
+ if (file->mode == GIT_FILEMODE_COMMIT)
+ {
+ char oidstr[GIT_OID_HEXSZ+1];
+ git_buf content = GIT_BUF_INIT;
+
+ git_oid_fmt(oidstr, &file->oid);
+ oidstr[GIT_OID_HEXSZ] = 0;
+ git_buf_printf(&content, "Subproject commit %s\n", oidstr );
+
+ map->data = git_buf_detach(&content);
+ map->len = strlen(map->data);
+
+ file->flags |= GIT_DIFF_FILE_FREE_DATA;
+ return 0;
+ }
+
if (!file->size) {
git_odb *odb;
size_t len;
@@ -250,6 +267,47 @@ static int get_blob_content(
return diff_delta_is_binary_by_content(ctxt, delta, file, map);
}
+static int get_workdir_sm_content(
+ diff_context *ctxt,
+ git_diff_file *file,
+ git_map *map)
+{
+ int error = 0;
+ git_buf content = GIT_BUF_INIT;
+ git_submodule* sm = NULL;
+ const git_oid* sm_head = NULL;
+ unsigned int sm_status = 0;
+ const char* sm_status_text = "";
+ char oidstr[GIT_OID_HEXSZ+1];
+
+ if ((error = git_submodule_lookup(&sm, ctxt->repo, file->path)) < 0) {
+ return error;
+ }
+
+ if ((sm_head = git_submodule_head_oid(sm)) == NULL) {
+ giterr_set(GITERR_SUBMODULE, "Cannot find head of submodule '%s'", file->path);
+ return -1;
+ }
+
+ if ((error = git_submodule_status(&sm_status, sm)) < 0) {
+ return -1;
+ }
+ if (!GIT_SUBMODULE_STATUS_IS_UNMODIFIED(sm_status)) {
+ sm_status_text = "-dirty";
+ }
+
+ git_oid_fmt(oidstr, sm_head);
+ oidstr[GIT_OID_HEXSZ] = 0;
+ git_buf_printf(&content, "Subproject commit %s%s\n", oidstr, sm_status_text );
+
+ map->data = git_buf_detach(&content);
+ map->len = strlen(map->data);
+
+ file->flags |= GIT_DIFF_FILE_FREE_DATA;
+
+ return 0;
+}
+
static int get_workdir_content(
diff_context *ctxt,
git_diff_delta *delta,
@@ -260,6 +318,9 @@ static int get_workdir_content(
git_buf path = GIT_BUF_INIT;
const char *wd = git_repository_workdir(ctxt->repo);
+ if (file->mode == GIT_FILEMODE_COMMIT)
+ return get_workdir_sm_content(ctxt, file, map);
+
if (git_buf_joinpath(&path, wd, file->path) < 0)
return -1;
@@ -1038,14 +1099,14 @@ static int print_patch_file(
if (git_buf_oom(pi->buf))
return -1;
- if (pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf)))
+ if (pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf)))
{
giterr_clear();
return GIT_EUSER;
}
- if (delta->binary != 1)
- return 0;
+ if (delta->binary != 1)
+ return 0;
git_buf_clear(pi->buf);
git_buf_printf(