teach log --no-walk=unsorted, which avoids sorting

When 'git log' is passed the --no-walk option, no revision walk takes
place, naturally. Perhaps somewhat surprisingly, however, the provided
revisions still get sorted by commit date. So e.g 'git log --no-walk
HEAD HEAD~1' and 'git log --no-walk HEAD~1 HEAD' give the same result
(unless the two revisions share the commit date, in which case they
will retain the order given on the command line). As the commit that
introduced --no-walk (8e64006 (Teach revision machinery about
--no-walk, 2007-07-24)) points out, the sorting is intentional, to
allow things like

 git log --abbrev-commit --pretty=oneline --decorate --all --no-walk

to show all refs in order by commit date.

But there are also other cases where the sorting is not wanted, such
as

 <command producing revisions in order> |
       git log --oneline --no-walk --stdin

To accomodate both cases, leave the decision of whether or not to sort
up to the caller, by allowing --no-walk={sorted,unsorted}, defaulting
to 'sorted' for backward-compatibility reasons.

Signed-off-by: Martin von Zweigbergk <martinvonz@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Martin von Zweigbergk 2012-08-28 23:15:54 -07:00 committed by Junio C Hamano
parent 0ce2e396ee
commit ca92e59e30
6 changed files with 39 additions and 8 deletions

View File

@ -619,9 +619,14 @@ These options are mostly targeted for packing of git repositories.
Only useful with '--objects'; print the object IDs that are not
in packs.
--no-walk::
--no-walk[=(sorted|unsorted)]::
Only show the given revs, but do not traverse their ancestors.
Only show the given commits, but do not traverse their ancestors.
This has no effect if a range is specified. If the argument
"unsorted" is given, the commits are show in the order they were
given on the command line. Otherwise (if "sorted" or no argument
was given), the commits are show in reverse chronological order
by commit time.
--do-walk::

View File

@ -454,7 +454,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
init_revisions(&rev, prefix);
rev.diff = 1;
rev.always_show_header = 1;
rev.no_walk = 1;
rev.no_walk = REVISION_WALK_NO_WALK_SORTED;
rev.diffopt.stat_width = -1; /* Scale to real terminal size */
memset(&opt, 0, sizeof(opt));

View File

@ -193,7 +193,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
struct setup_revision_opt s_r_opt;
opts->revs = xmalloc(sizeof(*opts->revs));
init_revisions(opts->revs, NULL);
opts->revs->no_walk = 1;
opts->revs->no_walk = REVISION_WALK_NO_WALK_SORTED;
if (argc < 2)
usage_with_options(usage_str, options);
memset(&s_r_opt, 0, sizeof(s_r_opt));

View File

@ -1294,7 +1294,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
!strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk") ||
!strcmp(arg, "--bisect") || !prefixcmp(arg, "--glob=") ||
!prefixcmp(arg, "--branches=") || !prefixcmp(arg, "--tags=") ||
!prefixcmp(arg, "--remotes="))
!prefixcmp(arg, "--remotes=") || !prefixcmp(arg, "--no-walk="))
{
unkv[(*unkc)++] = arg;
return 1;
@ -1687,7 +1687,18 @@ static int handle_revision_pseudo_opt(const char *submodule,
} else if (!strcmp(arg, "--not")) {
*flags ^= UNINTERESTING;
} else if (!strcmp(arg, "--no-walk")) {
revs->no_walk = 1;
revs->no_walk = REVISION_WALK_NO_WALK_SORTED;
} else if (!prefixcmp(arg, "--no-walk=")) {
/*
* Detached form ("--no-walk X" as opposed to "--no-walk=X")
* not allowed, since the argument is optional.
*/
if (!strcmp(arg + 10, "sorted"))
revs->no_walk = REVISION_WALK_NO_WALK_SORTED;
else if (!strcmp(arg + 10, "unsorted"))
revs->no_walk = REVISION_WALK_NO_WALK_UNSORTED;
else
return error("invalid argument to --no-walk");
} else if (!strcmp(arg, "--do-walk")) {
revs->no_walk = 0;
} else {
@ -2091,10 +2102,11 @@ int prepare_revision_walk(struct rev_info *revs)
}
e++;
}
commit_list_sort_by_date(&revs->commits);
if (!revs->leak_pending)
free(list);
if (revs->no_walk != REVISION_WALK_NO_WALK_UNSORTED)
commit_list_sort_by_date(&revs->commits);
if (revs->no_walk)
return 0;
if (revs->limited)

View File

@ -41,6 +41,10 @@ struct rev_cmdline_info {
} *rev;
};
#define REVISION_WALK_WALK 0
#define REVISION_WALK_NO_WALK_SORTED 1
#define REVISION_WALK_NO_WALK_UNSORTED 2
struct rev_info {
/* Starting list */
struct commit_list *commits;
@ -62,7 +66,7 @@ struct rev_info {
/* Traversal flags */
unsigned int dense:1,
prune:1,
no_walk:1,
no_walk:2,
show_all:1,
remove_empty_trees:1,
simplify_history:1,

View File

@ -178,11 +178,21 @@ test_expect_success 'git log --no-walk <commits> sorts by commit time' '
test_cmp expect actual
'
test_expect_success 'git log --no-walk=sorted <commits> sorts by commit time' '
git log --no-walk=sorted --oneline 5d31159 804a787 394ef78 > actual &&
test_cmp expect actual
'
cat > expect << EOF
5d31159 fourth
804a787 sixth
394ef78 fifth
EOF
test_expect_success 'git log --no-walk=unsorted <commits> leaves list of commits as given' '
git log --no-walk=unsorted --oneline 5d31159 804a787 394ef78 > actual &&
test_cmp expect actual
'
test_expect_success 'git show <commits> leaves list of commits as given' '
git show --oneline -s 5d31159 804a787 394ef78 > actual &&
test_cmp expect actual