From: Junio C Hamano Date: Sat, 23 Jan 2010 00:08:10 +0000 (-0800) Subject: Merge branch 'jl/submodule-diff' X-Git-Tag: v1.7.0-rc0~21 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/c6ec7efdd4c63f5c53184651cb05748e7bc71075?hp=-c Merge branch 'jl/submodule-diff' * jl/submodule-diff: Performance optimization for detection of modified submodules git status: Show uncommitted submodule changes too when enabled Teach diff that modified submodule directory is dirty Show submodules as modified when they contain a dirty work tree --- c6ec7efdd4c63f5c53184651cb05748e7bc71075 diff --combined diff.c index 5d71314587,8986873c0e..160dbfd718 --- a/diff.c +++ b/diff.c @@@ -2029,9 -2029,14 +2029,14 @@@ static int populate_from_stdin(struct d static int diff_populate_gitlink(struct diff_filespec *s, int size_only) { int len; - char *data = xmalloc(100); + char *data = xmalloc(100), *dirty = ""; + + /* Are we looking at the work tree? */ + if (!s->sha1_valid && s->dirty_submodule) + dirty = "-dirty"; + len = snprintf(data, 100, - "Subproject commit %s\n", sha1_to_hex(s->sha1)); + "Subproject commit %s%s\n", sha1_to_hex(s->sha1), dirty); s->data = data; s->size = len; s->should_free = 1; @@@ -2294,7 -2299,7 +2299,7 @@@ static void run_external_diff(const cha } *arg = NULL; fflush(NULL); - retval = run_command_v_opt(spawn_arg, 0); + retval = run_command_v_opt(spawn_arg, RUN_USING_SHELL); remove_tempfile(); if (retval) { fprintf(stderr, "external diff died, stopping at %s.\n", name); @@@ -3714,7 -3719,7 +3719,7 @@@ int diff_result_code(struct diff_option void diff_addremove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, - const char *concatpath) + const char *concatpath, unsigned dirty_submodule) { struct diff_filespec *one, *two; @@@ -3746,8 -3751,10 +3751,10 @@@ if (addremove != '+') fill_filespec(one, sha1, mode); - if (addremove != '-') + if (addremove != '-') { fill_filespec(two, sha1, mode); + two->dirty_submodule = dirty_submodule; + } diff_queue(&diff_queued_diff, one, two); if (!DIFF_OPT_TST(options, DIFF_FROM_CONTENTS)) @@@ -3758,7 -3765,8 +3765,8 @@@ void diff_change(struct diff_options *o unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *concatpath) + const char *concatpath, + unsigned old_dirty_submodule, unsigned new_dirty_submodule) { struct diff_filespec *one, *two; @@@ -3771,6 -3779,8 +3779,8 @@@ const unsigned char *tmp_c; tmp = old_mode; old_mode = new_mode; new_mode = tmp; tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c; + tmp = old_dirty_submodule; old_dirty_submodule = new_dirty_submodule; + new_dirty_submodule = tmp; } if (options->prefix && @@@ -3781,6 -3791,8 +3791,8 @@@ two = alloc_filespec(concatpath); fill_filespec(one, old_sha1, old_mode); fill_filespec(two, new_sha1, new_mode); + one->dirty_submodule = old_dirty_submodule; + two->dirty_submodule = new_dirty_submodule; diff_queue(&diff_queued_diff, one, two); if (!DIFF_OPT_TST(options, DIFF_FROM_CONTENTS)) @@@ -3818,7 -3830,6 +3830,7 @@@ static char *run_textconv(const char *p *arg = NULL; memset(&child, 0, sizeof(child)); + child.use_shell = 1; child.argv = argv; child.out = -1; if (start_command(&child) != 0 || diff --combined revision.c index f3b82d97bc,769cfd4251..4e1a299bfb --- a/revision.c +++ b/revision.c @@@ -268,7 -268,7 +268,7 @@@ static int tree_difference = REV_TREE_S static void file_add_remove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, - const char *fullpath) + const char *fullpath, unsigned dirty_submodule) { int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD; @@@ -281,7 -281,8 +281,8 @@@ static void file_change(struct diff_opt unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *fullpath) + const char *fullpath, + unsigned old_dirty_submodule, unsigned new_dirty_submodule) { tree_difference = REV_TREE_DIFFERENT; DIFF_OPT_SET(options, HAS_CHANGES); @@@ -1161,22 -1162,13 +1162,22 @@@ static int handle_revision_opt(struct r revs->verbose_header = 1; } else if (!strcmp(arg, "--pretty")) { revs->verbose_header = 1; + revs->pretty_given = 1; get_commit_format(arg+8, revs); } else if (!prefixcmp(arg, "--pretty=") || !prefixcmp(arg, "--format=")) { revs->verbose_header = 1; + revs->pretty_given = 1; get_commit_format(arg+9, revs); + } else if (!strcmp(arg, "--show-notes")) { + revs->show_notes = 1; + revs->show_notes_given = 1; + } else if (!strcmp(arg, "--no-notes")) { + revs->show_notes = 0; + revs->show_notes_given = 1; } else if (!strcmp(arg, "--oneline")) { revs->verbose_header = 1; get_commit_format("oneline", revs); + revs->pretty_given = 1; revs->abbrev_commit = 1; } else if (!strcmp(arg, "--graph")) { revs->topo_order = 1; diff --combined submodule.c index 3007f7d5a6,3f851deb6a..f657bee379 --- a/submodule.c +++ b/submodule.c @@@ -4,8 -4,9 +4,9 @@@ #include "diff.h" #include "commit.h" #include "revision.h" + #include "run-command.h" -int add_submodule_odb(const char *path) +static int add_submodule_odb(const char *path) { struct strbuf objects_directory = STRBUF_INIT; struct alternate_object_database *alt_odb; @@@ -112,3 -113,51 +113,51 @@@ void show_submodule_summary(FILE *f, co } strbuf_release(&sb); } + + int is_submodule_modified(const char *path) + { + int len; + struct child_process cp; + const char *argv[] = { + "status", + "--porcelain", + NULL, + }; + char *env[3]; + struct strbuf buf = STRBUF_INIT; + + strbuf_addf(&buf, "%s/.git/", path); + if (!is_directory(buf.buf)) { + strbuf_release(&buf); + /* The submodule is not checked out, so it is not modified */ + return 0; + + } + strbuf_reset(&buf); + + strbuf_addf(&buf, "GIT_WORK_TREE=%s", path); + env[0] = strbuf_detach(&buf, NULL); + strbuf_addf(&buf, "GIT_DIR=%s/.git", path); + env[1] = strbuf_detach(&buf, NULL); + env[2] = NULL; + + memset(&cp, 0, sizeof(cp)); + cp.argv = argv; + cp.env = (const char *const *)env; + cp.git_cmd = 1; + cp.no_stdin = 1; + cp.out = -1; + if (start_command(&cp)) + die("Could not run git status --porcelain"); + + len = strbuf_read(&buf, cp.out, 1024); + close(cp.out); + + if (finish_command(&cp)) + die("git status --porcelain failed"); + + free(env[0]); + free(env[1]); + strbuf_release(&buf); + return len != 0; + } diff --combined wt-status.c index 65feb29f2e,deaac93d17..5807fc3211 --- a/wt-status.c +++ b/wt-status.c @@@ -343,7 -343,7 +343,7 @@@ static void wt_status_collect_untracked DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES; setup_standard_excludes(&dir); - fill_directory(&dir, NULL); + fill_directory(&dir, s->pathspec); for (i = 0; i < dir.nr; i++) { struct dir_entry *ent = dir.entries[i]; if (!cache_name_is_other(ent->name, ent->len)) @@@ -459,7 -459,7 +459,7 @@@ static void wt_status_print_changed(str wt_status_print_trailer(s); } - static void wt_status_print_submodule_summary(struct wt_status *s) + static void wt_status_print_submodule_summary(struct wt_status *s, int uncommitted) { struct child_process sm_summary; char summary_limit[64]; @@@ -468,11 -468,11 +468,11 @@@ const char *argv[] = { "submodule", "summary", - "--cached", + uncommitted ? "--files" : "--cached", "--for-status", "--summary-limit", summary_limit, - s->amend ? "HEAD^" : "HEAD", + uncommitted ? NULL : (s->amend ? "HEAD^" : "HEAD"), NULL }; @@@ -580,8 -580,10 +580,10 @@@ void wt_status_print(struct wt_status * wt_status_print_updated(s); wt_status_print_unmerged(s); wt_status_print_changed(s); - if (s->submodule_summary) - wt_status_print_submodule_summary(s); + if (s->submodule_summary) { + wt_status_print_submodule_summary(s, 0); /* staged */ + wt_status_print_submodule_summary(s, 1); /* unstaged */ + } if (s->show_untracked_files) wt_status_print_untracked(s); else if (s->commitable)