Skip to content

Commit 8813596

Browse files
committed
Merge branch 'ah/log-no-graph'
"git log --graph --graph" used to leak a graph structure, and there was no way to countermand "--graph" that appear earlier on the command line. A "--no-graph" option has been added and resource leakage has been plugged. * ah/log-no-graph: log: add a --no-graph option log: fix memory leak if --graph is passed multiple times
2 parents ebb866a + 087c745 commit 8813596

File tree

7 files changed

+105
-4
lines changed

7 files changed

+105
-4
lines changed

builtin/blame.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
934934
parse_revision_opt(&revs, &ctx, options, blame_opt_usage);
935935
}
936936
parse_done:
937+
revision_opts_finish(&revs);
937938
no_whole_file_rename = !revs.diffopt.flags.follow_renames;
938939
xdl_opts |= revs.diffopt.xdl_opts & XDF_INDENT_HEURISTIC;
939940
revs.diffopt.flags.follow_renames = 0;

builtin/shortlog.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
388388
parse_revision_opt(&rev, &ctx, options, shortlog_usage);
389389
}
390390
parse_done:
391+
revision_opts_finish(&rev);
391392
argc = parse_options_end(&ctx);
392393

393394
if (nongit && argc > 1) {

graph.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,18 @@ struct git_graph *graph_init(struct rev_info *opt)
401401
return graph;
402402
}
403403

404+
void graph_clear(struct git_graph *graph)
405+
{
406+
if (!graph)
407+
return;
408+
409+
free(graph->columns);
410+
free(graph->new_columns);
411+
free(graph->mapping);
412+
free(graph->old_mapping);
413+
free(graph);
414+
}
415+
404416
static void graph_update_state(struct git_graph *graph, enum graph_state s)
405417
{
406418
graph->prev_state = graph->state;

graph.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ void graph_set_column_colors(const char **colors, unsigned short colors_max);
139139
*/
140140
struct git_graph *graph_init(struct rev_info *opt);
141141

142+
/*
143+
* Free a struct git_graph.
144+
*/
145+
void graph_clear(struct git_graph *graph);
146+
142147
/*
143148
* Update a git_graph with a new commit.
144149
* This will cause the graph to begin outputting lines for the new commit

revision.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2434,9 +2434,11 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
24342434
revs->pretty_given = 1;
24352435
revs->abbrev_commit = 1;
24362436
} else if (!strcmp(arg, "--graph")) {
2437-
revs->topo_order = 1;
2438-
revs->rewrite_parents = 1;
2437+
graph_clear(revs->graph);
24392438
revs->graph = graph_init(revs);
2439+
} else if (!strcmp(arg, "--no-graph")) {
2440+
graph_clear(revs->graph);
2441+
revs->graph = NULL;
24402442
} else if (!strcmp(arg, "--encode-email-headers")) {
24412443
revs->encode_email_headers = 1;
24422444
} else if (!strcmp(arg, "--no-encode-email-headers")) {
@@ -2533,8 +2535,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
25332535
unkv[(*unkc)++] = arg;
25342536
return opts;
25352537
}
2536-
if (revs->graph && revs->track_linear)
2537-
die(_("options '%s' and '%s' cannot be used together"), "--show-linear-break", "--graph");
25382538

25392539
return 1;
25402540
}
@@ -2553,6 +2553,17 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
25532553
ctx->argc -= n;
25542554
}
25552555

2556+
void revision_opts_finish(struct rev_info *revs)
2557+
{
2558+
if (revs->graph && revs->track_linear)
2559+
die(_("options '%s' and '%s' cannot be used together"), "--show-linear-break", "--graph");
2560+
2561+
if (revs->graph) {
2562+
revs->topo_order = 1;
2563+
revs->rewrite_parents = 1;
2564+
}
2565+
}
2566+
25562567
static int for_each_bisect_ref(struct ref_store *refs, each_ref_fn fn,
25572568
void *cb_data, const char *term)
25582569
{
@@ -2795,6 +2806,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
27952806
break;
27962807
}
27972808
}
2809+
revision_opts_finish(revs);
27982810

27992811
if (prune_data.nr) {
28002812
/*

revision.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
377377
#define REVARG_COMMITTISH 02
378378
int handle_revision_arg(const char *arg, struct rev_info *revs,
379379
int flags, unsigned revarg_opt);
380+
void revision_opts_finish(struct rev_info *revs);
380381

381382
/**
382383
* Reset the flags used by the revision walking api. You can use this to do

t/t4202-log.sh

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,75 @@ test_expect_success 'log --graph with --name-only' '
16841684
test_cmp_graph --name-only tangle..reach
16851685
'
16861686

1687+
test_expect_success '--no-graph countermands --graph' '
1688+
git log >expect &&
1689+
git log --graph --no-graph >actual &&
1690+
test_cmp expect actual
1691+
'
1692+
1693+
test_expect_success '--graph countermands --no-graph' '
1694+
git log --graph >expect &&
1695+
git log --no-graph --graph >actual &&
1696+
test_cmp expect actual
1697+
'
1698+
1699+
test_expect_success '--no-graph does not unset --topo-order' '
1700+
git log --topo-order >expect &&
1701+
git log --topo-order --no-graph >actual &&
1702+
test_cmp expect actual
1703+
'
1704+
1705+
test_expect_success '--no-graph does not unset --parents' '
1706+
git log --parents >expect &&
1707+
git log --parents --no-graph >actual &&
1708+
test_cmp expect actual
1709+
'
1710+
1711+
test_expect_success '--reverse and --graph conflict' '
1712+
test_must_fail git log --reverse --graph 2>stderr &&
1713+
test_i18ngrep "cannot be used together" stderr
1714+
'
1715+
1716+
test_expect_success '--reverse --graph --no-graph works' '
1717+
git log --reverse >expect &&
1718+
git log --reverse --graph --no-graph >actual &&
1719+
test_cmp expect actual
1720+
'
1721+
1722+
test_expect_success '--show-linear-break and --graph conflict' '
1723+
test_must_fail git log --show-linear-break --graph 2>stderr &&
1724+
test_i18ngrep "cannot be used together" stderr
1725+
'
1726+
1727+
test_expect_success '--show-linear-break --graph --no-graph works' '
1728+
git log --show-linear-break >expect &&
1729+
git log --show-linear-break --graph --no-graph >actual &&
1730+
test_cmp expect actual
1731+
'
1732+
1733+
test_expect_success '--no-walk and --graph conflict' '
1734+
test_must_fail git log --no-walk --graph 2>stderr &&
1735+
test_i18ngrep "cannot be used together" stderr
1736+
'
1737+
1738+
test_expect_success '--no-walk --graph --no-graph works' '
1739+
git log --no-walk >expect &&
1740+
git log --no-walk --graph --no-graph >actual &&
1741+
test_cmp expect actual
1742+
'
1743+
1744+
test_expect_success '--walk-reflogs and --graph conflict' '
1745+
test_must_fail git log --walk-reflogs --graph 2>stderr &&
1746+
(test_i18ngrep "cannot combine" stderr ||
1747+
test_i18ngrep "cannot be used together" stderr)
1748+
'
1749+
1750+
test_expect_success '--walk-reflogs --graph --no-graph works' '
1751+
git log --walk-reflogs >expect &&
1752+
git log --walk-reflogs --graph --no-graph >actual &&
1753+
test_cmp expect actual
1754+
'
1755+
16871756
test_expect_success 'dotdot is a parent directory' '
16881757
mkdir -p a/b &&
16891758
( echo sixth && echo fifth ) >expect &&

0 commit comments

Comments
 (0)