Skip to content

Commit

Permalink
Add the --submodule option to the diff option family
Browse files Browse the repository at this point in the history
When you use the option --submodule=log you can see the submodule
summaries inlined in the diff, instead of not-quite-helpful SHA-1 pairs.

The format imitates what "git submodule summary" shows.

To do that, <path>/.git/objects/ is added to the alternate object
databases (if that directory exists).

This option was requested by Jens Lehmann at the GitTogether in Berlin.

Signed-off-by: Johannes Schindelin <[email protected]>
Signed-off-by: Jens Lehmann <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
dscho authored and gitster committed Oct 20, 2009
1 parent dbc1b1f commit 752c0c2
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Documentation/diff-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ endif::git-format-patch[]
Show only names and status of changed files. See the description
of the `--diff-filter` option on what the status letters mean.

--submodule[=<format>]::
Chose the output format for submodule differences. <format> can be one of
'short' and 'log'. 'short' just shows pairs of commit names, this format
is used when this option is not given. 'log' is the default value for this
option and lists the commits in that commit range like the 'summary'
option of linkgit:git-submodule[1] does.

--color::
Show colored diff.

Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ LIB_H += sideband.h
LIB_H += sigchain.h
LIB_H += strbuf.h
LIB_H += string-list.h
LIB_H += submodule.h
LIB_H += tag.h
LIB_H += transport.h
LIB_H += tree.h
Expand Down Expand Up @@ -546,6 +547,7 @@ LIB_OBJS += sideband.o
LIB_OBJS += sigchain.o
LIB_OBJS += strbuf.o
LIB_OBJS += string-list.o
LIB_OBJS += submodule.o
LIB_OBJS += symlinks.o
LIB_OBJS += tag.o
LIB_OBJS += trace.o
Expand Down
18 changes: 18 additions & 0 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "utf8.h"
#include "userdiff.h"
#include "sigchain.h"
#include "submodule.h"

#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
Expand Down Expand Up @@ -1453,6 +1454,17 @@ static void builtin_diff(const char *name_a,
const char *a_prefix, *b_prefix;
const char *textconv_one = NULL, *textconv_two = NULL;

if (DIFF_OPT_TST(o, SUBMODULE_LOG) &&
(!one->mode || S_ISGITLINK(one->mode)) &&
(!two->mode || S_ISGITLINK(two->mode))) {
const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
show_submodule_summary(o->file, one ? one->path : two->path,
one->sha1, two->sha1,
del, add, reset);
return;
}

if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
textconv_one = get_textconv(one);
textconv_two = get_textconv(two);
Expand Down Expand Up @@ -2640,6 +2652,12 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
else if (!strcmp(arg, "--ignore-submodules"))
DIFF_OPT_SET(options, IGNORE_SUBMODULES);
else if (!strcmp(arg, "--submodule"))
DIFF_OPT_SET(options, SUBMODULE_LOG);
else if (!prefixcmp(arg, "--submodule=")) {
if (!strcmp(arg + 12, "log"))
DIFF_OPT_SET(options, SUBMODULE_LOG);
}

/* misc options */
else if (!strcmp(arg, "-z"))
Expand Down
3 changes: 3 additions & 0 deletions diff.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
#define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19)
#define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20)
#define DIFF_OPT_ALLOW_TEXTCONV (1 << 21)

#define DIFF_OPT_SUBMODULE_LOG (1 << 23)

#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
#define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag)
Expand Down
113 changes: 113 additions & 0 deletions submodule.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include "cache.h"
#include "submodule.h"
#include "dir.h"
#include "diff.h"
#include "commit.h"
#include "revision.h"

int add_submodule_odb(const char *path)
{
struct strbuf objects_directory = STRBUF_INIT;
struct alternate_object_database *alt_odb;

strbuf_addf(&objects_directory, "%s/.git/objects/", path);
if (!is_directory(objects_directory.buf))
return -1;

/* avoid adding it twice */
for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
if (alt_odb->name - alt_odb->base == objects_directory.len &&
!strncmp(alt_odb->base, objects_directory.buf,
objects_directory.len))
return 0;

alt_odb = xmalloc(objects_directory.len + 42 + sizeof(*alt_odb));
alt_odb->next = alt_odb_list;
strcpy(alt_odb->base, objects_directory.buf);
alt_odb->name = alt_odb->base + objects_directory.len;
alt_odb->name[2] = '/';
alt_odb->name[40] = '\0';
alt_odb->name[41] = '\0';
alt_odb_list = alt_odb;
prepare_alt_odb();
return 0;
}

void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
const char *del, const char *add, const char *reset)
{
struct rev_info rev;
struct commit *commit, *left = left, *right;
struct commit_list *merge_bases, *list;
const char *message = NULL;
struct strbuf sb = STRBUF_INIT;
static const char *format = " %m %s";
int fast_forward = 0, fast_backward = 0;

if (is_null_sha1(two))
message = "(submodule deleted)";
else if (add_submodule_odb(path))
message = "(not checked out)";
else if (is_null_sha1(one))
message = "(new submodule)";
else if (!(left = lookup_commit_reference(one)) ||
!(right = lookup_commit_reference(two)))
message = "(commits not present)";

if (!message) {
init_revisions(&rev, NULL);
setup_revisions(0, NULL, &rev, NULL);
rev.left_right = 1;
rev.first_parent_only = 1;
left->object.flags |= SYMMETRIC_LEFT;
add_pending_object(&rev, &left->object, path);
add_pending_object(&rev, &right->object, path);
merge_bases = get_merge_bases(left, right, 1);
if (merge_bases) {
if (merge_bases->item == left)
fast_forward = 1;
else if (merge_bases->item == right)
fast_backward = 1;
}
for (list = merge_bases; list; list = list->next) {
list->item->object.flags |= UNINTERESTING;
add_pending_object(&rev, &list->item->object,
sha1_to_hex(list->item->object.sha1));
}
if (prepare_revision_walk(&rev))
message = "(revision walker failed)";
}

strbuf_addf(&sb, "Submodule %s %s..", path,
find_unique_abbrev(one, DEFAULT_ABBREV));
if (!fast_backward && !fast_forward)
strbuf_addch(&sb, '.');
strbuf_addf(&sb, "%s", find_unique_abbrev(two, DEFAULT_ABBREV));
if (message)
strbuf_addf(&sb, " %s\n", message);
else
strbuf_addf(&sb, "%s:\n", fast_backward ? " (rewind)" : "");
fwrite(sb.buf, sb.len, 1, f);

if (!message) {
while ((commit = get_revision(&rev))) {
strbuf_setlen(&sb, 0);
if (commit->object.flags & SYMMETRIC_LEFT) {
if (del)
strbuf_addstr(&sb, del);
}
else if (add)
strbuf_addstr(&sb, add);
format_commit_message(commit, format, &sb,
rev.date_mode);
if (reset)
strbuf_addstr(&sb, reset);
strbuf_addch(&sb, '\n');
fprintf(f, "%s", sb.buf);
}
clear_commit_marks(left, ~0);
clear_commit_marks(right, ~0);
}
strbuf_release(&sb);
}
8 changes: 8 additions & 0 deletions submodule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef SUBMODULE_H
#define SUBMODULE_H

void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
const char *del, const char *add, const char *reset);

#endif

0 comments on commit 752c0c2

Please sign in to comment.