diff options
-rw-r--r-- | src/diff.c | 13 | ||||
-rw-r--r-- | src/diff_output.c | 67 |
2 files changed, 74 insertions, 6 deletions
diff --git a/src/diff.c b/src/diff.c index 77cbc3ca7..7a0051ae3 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 8a099a433..f5f6c381e 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( |