Merge branch 'ds/decorate-filter-tweak'

The namespaces used by "log --decorate" from "refs/" hierarchy by
default has been tightened.

* ds/decorate-filter-tweak:
  fetch: use ref_namespaces during prefetch
  maintenance: stop writing log.excludeDecoration
  log: create log.initialDecorationSet=all
  log: add --clear-decorations option
  log: add default decoration filter
  log-tree: use ref_namespaces instead of if/else-if
  refs: use ref_namespaces for replace refs base
  refs: add array of ref namespaces
  t4207: test coloring of grafted decorations
  t4207: modernize test
  refs: allow "HEAD" as decoration filter
This commit is contained in:
Junio C Hamano 2022-08-29 14:55:10 -07:00
commit c068a3b8ee
22 changed files with 701 additions and 85 deletions

View File

@ -18,6 +18,11 @@ log.decorate::
names are shown. This is the same as the `--decorate` option
of the `git log`.
log.initialDecorationSet::
By default, `git log` only shows decorations for certain known ref
namespaces. If 'all' is specified, then show all refs as
decorations.
log.excludeDecoration::
Exclude the specified patterns from the log decorations. This is
similar to the `--decorate-refs-exclude` command-line option, but

View File

@ -45,13 +45,23 @@ OPTIONS
--decorate-refs=<pattern>::
--decorate-refs-exclude=<pattern>::
If no `--decorate-refs` is given, pretend as if all refs were
included. For each candidate, do not use it for decoration if it
For each candidate reference, do not use it for decoration if it
matches any patterns given to `--decorate-refs-exclude` or if it
doesn't match any of the patterns given to `--decorate-refs`. The
`log.excludeDecoration` config option allows excluding refs from
the decorations, but an explicit `--decorate-refs` pattern will
override a match in `log.excludeDecoration`.
+
If none of these options or config settings are given, then references are
used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,
`refs/stash/`, or `refs/tags/`.
--clear-decorations::
When specified, this option clears all previous `--decorate-refs`
or `--decorate-refs-exclude` options and relaxes the default
decoration filter to include all references. This option is
assumed if the config value `log.initialDecorationSet` is set to
`all`.
--source::
Print out the ref name given on the command line by which each

View File

@ -490,7 +490,9 @@ static void filter_prefetch_refspec(struct refspec *rs)
continue;
if (!rs->items[i].dst ||
(rs->items[i].src &&
!strncmp(rs->items[i].src, "refs/tags/", 10))) {
!strncmp(rs->items[i].src,
ref_namespace[NAMESPACE_TAGS].ref,
strlen(ref_namespace[NAMESPACE_TAGS].ref)))) {
int j;
free(rs->items[i].src);
@ -506,7 +508,7 @@ static void filter_prefetch_refspec(struct refspec *rs)
}
old_dst = rs->items[i].dst;
strbuf_addstr(&new_dst, "refs/prefetch/");
strbuf_addstr(&new_dst, ref_namespace[NAMESPACE_PREFETCH].ref);
/*
* If old_dst starts with "refs/", then place

View File

@ -910,12 +910,6 @@ static int fetch_remote(struct remote *remote, void *cbdata)
static int maintenance_task_prefetch(struct maintenance_run_opts *opts)
{
git_config_set_multivar_gently("log.excludedecoration",
"refs/prefetch/",
"refs/prefetch/",
CONFIG_FLAGS_FIXED_VALUE |
CONFIG_FLAGS_MULTI_REPLACE);
if (for_each_remote(fetch_remote, opts)) {
error(_("failed to prefetch remotes"));
return 1;

View File

@ -101,6 +101,20 @@ static int parse_decoration_style(const char *value)
return -1;
}
static int use_default_decoration_filter = 1;
static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
static int clear_decorations_callback(const struct option *opt,
const char *arg, int unset)
{
string_list_clear(&decorate_refs_include, 0);
string_list_clear(&decorate_refs_exclude, 0);
use_default_decoration_filter = 0;
return 0;
}
static int decorate_callback(const struct option *opt, const char *arg, int unset)
{
if (unset)
@ -162,18 +176,61 @@ static void cmd_log_init_defaults(struct rev_info *rev)
parse_date_format(default_date_mode, &rev->date_mode);
}
static void set_default_decoration_filter(struct decoration_filter *decoration_filter)
{
int i;
char *value = NULL;
struct string_list *include = decoration_filter->include_ref_pattern;
const struct string_list *config_exclude =
git_config_get_value_multi("log.excludeDecoration");
if (config_exclude) {
struct string_list_item *item;
for_each_string_list_item(item, config_exclude)
string_list_append(decoration_filter->exclude_ref_config_pattern,
item->string);
}
/*
* By default, decorate_all is disabled. Enable it if
* log.initialDecorationSet=all. Don't ever disable it by config,
* since the command-line takes precedent.
*/
if (use_default_decoration_filter &&
!git_config_get_string("log.initialdecorationset", &value) &&
!strcmp("all", value))
use_default_decoration_filter = 0;
free(value);
if (!use_default_decoration_filter ||
decoration_filter->exclude_ref_pattern->nr ||
decoration_filter->include_ref_pattern->nr ||
decoration_filter->exclude_ref_config_pattern->nr)
return;
/*
* No command-line or config options were given, so
* populate with sensible defaults.
*/
for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
if (!ref_namespace[i].decoration)
continue;
string_list_append(include, ref_namespace[i].ref);
}
}
static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
struct rev_info *rev, struct setup_revision_opt *opt)
{
struct userformat_want w;
int quiet = 0, source = 0, mailmap;
static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};
static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
struct decoration_filter decoration_filter = {&decorate_refs_include,
&decorate_refs_exclude,
&decorate_refs_exclude_config};
struct decoration_filter decoration_filter = {
.exclude_ref_pattern = &decorate_refs_exclude,
.include_ref_pattern = &decorate_refs_include,
.exclude_ref_config_pattern = &decorate_refs_exclude_config,
};
static struct revision_sources revision_sources;
const struct option builtin_log_options[] = {
@ -181,6 +238,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
OPT_BOOL(0, "source", &source, N_("show source")),
OPT_BOOL(0, "use-mailmap", &mailmap, N_("use mail map file")),
OPT_ALIAS(0, "mailmap", "use-mailmap"),
OPT_CALLBACK_F(0, "clear-decorations", NULL, NULL,
N_("clear all previously-defined decoration filters"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
clear_decorations_callback),
OPT_STRING_LIST(0, "decorate-refs", &decorate_refs_include,
N_("pattern"), N_("only decorate refs that match <pattern>")),
OPT_STRING_LIST(0, "decorate-refs-exclude", &decorate_refs_exclude,
@ -265,16 +326,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
}
if (decoration_style || rev->simplify_by_decoration) {
const struct string_list *config_exclude =
repo_config_get_value_multi(the_repository,
"log.excludeDecoration");
if (config_exclude) {
struct string_list_item *item;
for_each_string_list_item(item, config_exclude)
string_list_append(&decorate_refs_exclude_config,
item->string);
}
set_default_decoration_filter(&decoration_filter);
if (decoration_style)
rev->show_decorations = 1;

View File

@ -106,6 +106,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
size_t base_len;
int had_error = 0;
struct object_id oid;
const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
strbuf_addstr(&ref, git_replace_ref_base);
base_len = ref.len;
@ -147,6 +148,8 @@ static int check_ref_valid(struct object_id *object,
struct strbuf *ref,
int force)
{
const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
strbuf_reset(ref);
strbuf_addf(ref, "%s%s", git_replace_ref_base, oid_to_hex(object));
if (check_refname_format(ref->buf, 0))

View File

@ -1016,7 +1016,6 @@ void reset_shared_repository(void);
* commands that do not want replace references to be active.
*/
extern int read_replace_refs;
extern char *git_replace_ref_base;
/*
* These values are used to help identify parts of a repository to fsync.

View File

@ -56,7 +56,6 @@ const char *askpass_program;
const char *excludes_file;
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
int read_replace_refs = 1;
char *git_replace_ref_base;
enum eol core_eol = EOL_UNSET;
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
char *check_roundtrip_encoding = "SHIFT-JIS";
@ -162,6 +161,7 @@ const char *getenv_safe(struct strvec *argv, const char *name)
void setup_git_env(const char *git_dir)
{
char *git_replace_ref_base;
const char *shallow_file;
const char *replace_ref_base;
struct set_gitdir_args args = { NULL };
@ -182,9 +182,10 @@ void setup_git_env(const char *git_dir)
if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
read_replace_refs = 0;
replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
free(git_replace_ref_base);
git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
: "refs/replace/");
update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);
free(git_namespace);
git_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);

View File

@ -137,10 +137,12 @@ static int ref_filter_match(const char *refname,
static int add_ref_decoration(const char *refname, const struct object_id *oid,
int flags, void *cb_data)
{
int i;
struct object *obj;
enum object_type objtype;
enum decoration_type deco_type = DECORATION_NONE;
struct decoration_filter *filter = (struct decoration_filter *)cb_data;
const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
if (filter && !ref_filter_match(refname, filter))
return 0;
@ -165,16 +167,21 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,
return 0;
obj = lookup_object_by_type(the_repository, oid, objtype);
if (starts_with(refname, "refs/heads/"))
deco_type = DECORATION_REF_LOCAL;
else if (starts_with(refname, "refs/remotes/"))
deco_type = DECORATION_REF_REMOTE;
else if (starts_with(refname, "refs/tags/"))
deco_type = DECORATION_REF_TAG;
else if (!strcmp(refname, "refs/stash"))
deco_type = DECORATION_REF_STASH;
else if (!strcmp(refname, "HEAD"))
deco_type = DECORATION_REF_HEAD;
for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
struct ref_namespace_info *info = &ref_namespace[i];
if (!info->decoration)
continue;
if (info->exact) {
if (!strcmp(refname, info->ref)) {
deco_type = info->decoration;
break;
}
} else if (starts_with(refname, info->ref)) {
deco_type = info->decoration;
break;
}
}
add_name_decoration(deco_type, refname, obj);
while (obj->type == OBJ_TAG) {

View File

@ -1005,6 +1005,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
if (!notes_ref)
notes_ref = default_notes_ref();
update_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref));
if (!combine_notes)
combine_notes = combine_notes_concatenate;

95
refs.c
View File

@ -20,6 +20,7 @@
#include "repository.h"
#include "sigchain.h"
#include "date.h"
#include "commit.h"
/*
* List of all available backends
@ -56,6 +57,88 @@ static unsigned char refname_disposition[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
};
struct ref_namespace_info ref_namespace[] = {
[NAMESPACE_HEAD] = {
.ref = "HEAD",
.decoration = DECORATION_REF_HEAD,
.exact = 1,
},
[NAMESPACE_BRANCHES] = {
.ref = "refs/heads/",
.decoration = DECORATION_REF_LOCAL,
},
[NAMESPACE_TAGS] = {
.ref = "refs/tags/",
.decoration = DECORATION_REF_TAG,
},
[NAMESPACE_REMOTE_REFS] = {
/*
* The default refspec for new remotes copies refs from
* refs/heads/ on the remote into refs/remotes/<remote>/.
* As such, "refs/remotes/" has special handling.
*/
.ref = "refs/remotes/",
.decoration = DECORATION_REF_REMOTE,
},
[NAMESPACE_STASH] = {
/*
* The single ref "refs/stash" stores the latest stash.
* Older stashes can be found in the reflog.
*/
.ref = "refs/stash",
.exact = 1,
.decoration = DECORATION_REF_STASH,
},
[NAMESPACE_REPLACE] = {
/*
* This namespace allows Git to act as if one object ID
* points to the content of another. Unlike the other
* ref namespaces, this one can be changed by the
* GIT_REPLACE_REF_BASE environment variable. This
* .namespace value will be overwritten in setup_git_env().
*/
.ref = "refs/replace/",
.decoration = DECORATION_GRAFTED,
},
[NAMESPACE_NOTES] = {
/*
* The refs/notes/commit ref points to the tip of a
* parallel commit history that adds metadata to commits
* in the normal history. This ref can be overwritten
* by the core.notesRef config variable or the
* GIT_NOTES_REFS environment variable.
*/
.ref = "refs/notes/commit",
.exact = 1,
},
[NAMESPACE_PREFETCH] = {
/*
* Prefetch refs are written by the background 'fetch'
* maintenance task. It allows faster foreground fetches
* by advertising these previously-downloaded tips without
* updating refs/remotes/ without user intervention.
*/
.ref = "refs/prefetch/",
},
[NAMESPACE_REWRITTEN] = {
/*
* Rewritten refs are used by the 'label' command in the
* sequencer. These are particularly useful during an
* interactive rebase that uses the 'merge' command.
*/
.ref = "refs/rewritten/",
},
};
void update_ref_namespace(enum ref_namespace namespace, char *ref)
{
struct ref_namespace_info *info = &ref_namespace[namespace];
if (info->ref_updated)
free(info->ref);
info->ref = ref;
info->ref_updated = 1;
}
/*
* Try to read one refname component from the front of refname.
* Return the length of the component found, or -1 if the component is
@ -455,11 +538,16 @@ void normalize_glob_ref(struct string_list_item *item, const char *prefix,
if (*pattern == '/')
BUG("pattern must not start with '/'");
if (prefix) {
if (prefix)
strbuf_addstr(&normalized_pattern, prefix);
}
else if (!starts_with(pattern, "refs/"))
else if (!starts_with(pattern, "refs/") &&
strcmp(pattern, "HEAD"))
strbuf_addstr(&normalized_pattern, "refs/");
/*
* NEEDSWORK: Special case other symrefs such as REBASE_HEAD,
* MERGE_HEAD, etc.
*/
strbuf_addstr(&normalized_pattern, pattern);
strbuf_strip_suffix(&normalized_pattern, "/");
@ -1524,6 +1612,7 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
{
const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
return do_for_each_repo_ref(r, git_replace_ref_base, fn,
strlen(git_replace_ref_base),
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);

46
refs.h
View File

@ -2,6 +2,7 @@
#define REFS_H
#include "cache.h"
#include "commit.h"
struct object_id;
struct ref_store;
@ -930,4 +931,49 @@ struct ref_store *get_main_ref_store(struct repository *r);
struct ref_store *get_submodule_ref_store(const char *submodule);
struct ref_store *get_worktree_ref_store(const struct worktree *wt);
/*
* Some of the names specified by refs have special meaning to Git.
* Organize these namespaces in a comon 'ref_namespace' array for
* reference from multiple places in the codebase.
*/
struct ref_namespace_info {
char *ref;
enum decoration_type decoration;
/*
* If 'exact' is true, then we must match the 'ref' exactly.
* Otherwise, use a prefix match.
*
* 'ref_updated' is for internal use. It represents whether the
* 'ref' value was replaced from its original literal version.
*/
unsigned exact:1,
ref_updated:1;
};
enum ref_namespace {
NAMESPACE_HEAD,
NAMESPACE_BRANCHES,
NAMESPACE_TAGS,
NAMESPACE_REMOTE_REFS,
NAMESPACE_STASH,
NAMESPACE_REPLACE,
NAMESPACE_NOTES,
NAMESPACE_PREFETCH,
NAMESPACE_REWRITTEN,
/* Must be last */
NAMESPACE__COUNT
};
/* See refs.c for the contents of this array. */
extern struct ref_namespace_info ref_namespace[NAMESPACE__COUNT];
/*
* Some ref namespaces can be modified by config values or environment
* variables. Modify a namespace as specified by its ref_namespace key.
*/
void update_ref_namespace(enum ref_namespace namespace, char *ref);
#endif /* REFS_H */

View File

@ -352,6 +352,8 @@ log -GF -p --pickaxe-all master
log -IA -IB -I1 -I2 -p master
log --decorate --all
log --decorate=full --all
log --decorate --clear-decorations --all
log --decorate=full --clear-decorations --all
rev-list --parents HEAD
rev-list --children HEAD

View File

@ -20,7 +20,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
Rearranged lines in dir/sub
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000

View File

@ -0,0 +1,61 @@
$ git log --decorate=full --clear-decorations --all
commit b7e0bc69303b488b47deca799a7d723971dfa6cd (refs/heads/mode)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
update mode
commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (refs/heads/note)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
update mode (file2)
Notes:
note
commit cd4e72fd96faed3f0ba949dc42967430374e2290 (refs/heads/rearrange)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
Rearranged lines in dir/sub
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
Merge branch 'side'
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
Side
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
Third
commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
This is the second commit.
commit 444ac553ac7612cc88969031b02b3767fb8a353a (refs/heads/initial)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:00:00 2006 +0000
Initial
$

View File

@ -0,0 +1,61 @@
$ git log --decorate=full --decorate-all --all
commit b7e0bc69303b488b47deca799a7d723971dfa6cd (refs/heads/mode)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
update mode
commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (refs/heads/note)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
update mode (file2)
Notes:
note
commit cd4e72fd96faed3f0ba949dc42967430374e2290 (refs/heads/rearrange)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
Rearranged lines in dir/sub
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
Merge branch 'side'
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
Side
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
Third
commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
This is the second commit.
commit 444ac553ac7612cc88969031b02b3767fb8a353a (refs/heads/initial)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:00:00 2006 +0000
Initial
$

View File

@ -20,7 +20,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
Rearranged lines in dir/sub
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000

View File

@ -0,0 +1,61 @@
$ git log --decorate --clear-decorations --all
commit b7e0bc69303b488b47deca799a7d723971dfa6cd (mode)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
update mode
commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (note)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
update mode (file2)
Notes:
note
commit cd4e72fd96faed3f0ba949dc42967430374e2290 (rearrange)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
Rearranged lines in dir/sub
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
Merge branch 'side'
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
Side
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
Third
commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
This is the second commit.
commit 444ac553ac7612cc88969031b02b3767fb8a353a (initial)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:00:00 2006 +0000
Initial
$

View File

@ -0,0 +1,61 @@
$ git log --decorate --decorate-all --all
commit b7e0bc69303b488b47deca799a7d723971dfa6cd (mode)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
update mode
commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (note)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
update mode (file2)
Notes:
note
commit cd4e72fd96faed3f0ba949dc42967430374e2290 (rearrange)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
Rearranged lines in dir/sub
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
Merge branch 'side'
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
Side
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
Third
commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
This is the second commit.
commit 444ac553ac7612cc88969031b02b3767fb8a353a (initial)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:00:00 2006 +0000
Initial
$

View File

@ -704,9 +704,12 @@ test_expect_success 'set up more tangled history' '
git checkout -b tangle HEAD~6 &&
test_commit tangle-a tangle-a a &&
git merge main~3 &&
git update-ref refs/prefetch/merge HEAD &&
git merge side~1 &&
git update-ref refs/rewritten/merge HEAD &&
git checkout main &&
git merge tangle &&
git update-ref refs/hidden/tangle HEAD &&
git checkout -b reach &&
test_commit reach &&
git checkout main &&
@ -974,9 +977,9 @@ test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '
Merge-tag-reach (HEAD -> main)
reach (tag: reach, reach)
seventh (tag: seventh)
Merge-branch-tangle
Merge-branch-side-early-part-into-tangle (tangle)
tangle-a (tag: tangle-a)
Merge-branch-tangle (refs/hidden/tangle)
Merge-branch-side-early-part-into-tangle (refs/rewritten/merge, tangle)
Merge-branch-main-early-part-into-tangle (refs/prefetch/merge)
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs-exclude="*octopus*" \
@ -1025,6 +1028,115 @@ test_expect_success 'decorate-refs and simplify-by-decoration without output' '
test_cmp expect actual
'
test_expect_success 'decorate-refs-exclude HEAD' '
git log --decorate=full --oneline \
--decorate-refs-exclude="HEAD" >actual &&
! grep HEAD actual
'
test_expect_success 'decorate-refs focus from default' '
git log --decorate=full --oneline \
--decorate-refs="refs/heads" >actual &&
! grep HEAD actual
'
test_expect_success '--clear-decorations overrides defaults' '
cat >expect.default <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main)
Merge-tags-octopus-a-and-octopus-b
seventh (tag: refs/tags/seventh)
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
reach (tag: refs/tags/reach, refs/heads/reach)
Merge-branch-tangle
Merge-branch-side-early-part-into-tangle (refs/heads/tangle)
Merge-branch-main-early-part-into-tangle
tangle-a (tag: refs/tags/tangle-a)
Merge-branch-side
side-2 (tag: refs/tags/side-2, refs/heads/side)
side-1 (tag: refs/tags/side-1)
Second
sixth
fifth
fourth
third
second
initial
EOF
git log --decorate=full --pretty="tformat:%f%d" >actual &&
test_cmp expect.default actual &&
cat >expect.all <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main)
Merge-tags-octopus-a-and-octopus-b
seventh (tag: refs/tags/seventh)
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
reach (tag: refs/tags/reach, refs/heads/reach)
Merge-branch-tangle (refs/hidden/tangle)
Merge-branch-side-early-part-into-tangle (refs/rewritten/merge, refs/heads/tangle)
Merge-branch-main-early-part-into-tangle (refs/prefetch/merge)
tangle-a (tag: refs/tags/tangle-a)
Merge-branch-side
side-2 (tag: refs/tags/side-2, refs/heads/side)
side-1 (tag: refs/tags/side-1)
Second
sixth
fifth
fourth
third
second
initial
EOF
git log --decorate=full --pretty="tformat:%f%d" \
--clear-decorations >actual &&
test_cmp expect.all actual &&
git -c log.initialDecorationSet=all log \
--decorate=full --pretty="tformat:%f%d" >actual &&
test_cmp expect.all actual
'
test_expect_success '--clear-decorations clears previous exclusions' '
cat >expect.all <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main)
reach (tag: refs/tags/reach, refs/heads/reach)
Merge-tags-octopus-a-and-octopus-b
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
seventh (tag: refs/tags/seventh)
Merge-branch-tangle (refs/hidden/tangle)
Merge-branch-side-early-part-into-tangle (refs/rewritten/merge, refs/heads/tangle)
Merge-branch-main-early-part-into-tangle (refs/prefetch/merge)
tangle-a (tag: refs/tags/tangle-a)
side-2 (tag: refs/tags/side-2, refs/heads/side)
side-1 (tag: refs/tags/side-1)
initial
EOF
git log --decorate=full --pretty="tformat:%f%d" \
--simplify-by-decoration \
--decorate-refs-exclude="heads/octopus*" \
--decorate-refs="heads" \
--clear-decorations >actual &&
test_cmp expect.all actual &&
cat >expect.filtered <<-\EOF &&
Merge-tags-octopus-a-and-octopus-b
octopus-b (refs/heads/octopus-b)
octopus-a (refs/heads/octopus-a)
initial
EOF
git log --decorate=full --pretty="tformat:%f%d" \
--simplify-by-decoration \
--decorate-refs-exclude="heads/octopus" \
--decorate-refs="heads" \
--clear-decorations \
--decorate-refs-exclude="tags/" \
--decorate-refs="heads/octopus*" >actual &&
test_cmp expect.filtered actual
'
test_expect_success 'log.decorate config parsing' '
git log --oneline --decorate=full >expect.full &&
git log --oneline --decorate=short >expect.short &&
@ -2192,6 +2304,20 @@ test_expect_success 'log --decorate includes all levels of tag annotated tags' '
test_cmp expect actual
'
test_expect_success 'log --decorate does not include things outside filter' '
reflist="refs/prefetch refs/rebase-merge refs/bundle" &&
for ref in $reflist
do
git update-ref $ref/fake HEAD || return 1
done &&
git log --decorate=full --oneline >actual &&
# None of the refs are visible:
! grep /fake actual
'
test_expect_success 'log --end-of-options' '
git update-ref refs/heads/--source HEAD &&
git log --end-of-options --source >actual &&

View File

@ -3,7 +3,7 @@
# Copyright (c) 2010 Nazri Ramliy
#
test_description='Test for "git log --decorate" colors'
test_description='test "git log --decorate" colors'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
@ -17,6 +17,7 @@ test_expect_success setup '
git config color.decorate.remoteBranch red &&
git config color.decorate.tag "reverse bold yellow" &&
git config color.decorate.stash magenta &&
git config color.decorate.grafted black &&
git config color.decorate.HEAD cyan &&
c_reset="<RESET>" &&
@ -27,6 +28,7 @@ test_expect_success setup '
c_tag="<BOLD;REVERSE;YELLOW>" &&
c_stash="<MAGENTA>" &&
c_HEAD="<CYAN>" &&
c_grafted="<BLACK>" &&
test_commit A &&
git clone . other &&
@ -42,25 +44,79 @@ test_expect_success setup '
git stash save Changes to A.t
'
cat >expected <<EOF
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\
${c_reset}${c_branch}main${c_reset}${c_commit},\
${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit},\
${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A1${c_reset}${c_commit},\
${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\
On main: Changes to A.t
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
EOF
cmp_filtered_decorations () {
sed "s/$OID_REGEX/COMMIT_ID/" actual | test_decode_color >filtered &&
test_cmp expect filtered
}
# We want log to show all, but the second parent to refs/stash is irrelevant
# to this test since it does not contain any decoration, hence --first-parent
test_expect_success 'Commit Decorations Colored Correctly' '
git log --first-parent --abbrev=10 --all --decorate --oneline --color=always |
sed "s/[0-9a-f]\{10,10\}/COMMIT_ID/" |
test_decode_color >out &&
test_cmp expected out
test_expect_success 'commit decorations colored correctly' '
cat >expect <<-EOF &&
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \
${c_reset}${c_branch}main${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A1${c_reset}${c_commit}, \
${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_stash}refs/stash${c_reset}${c_commit})${c_reset} \
On main: Changes to A.t
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always --all >actual &&
cmp_filtered_decorations
'
test_expect_success 'test coloring with replace-objects' '
test_when_finished rm -rf .git/refs/replace* &&
test_commit C &&
test_commit D &&
git replace HEAD~1 HEAD~2 &&
cat >expect <<-EOF &&
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \
${c_reset}${c_branch}main${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: D${c_reset}${c_commit})${c_reset} D
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: C${c_reset}${c_commit}, \
${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&
cmp_filtered_decorations &&
git replace -d HEAD~1 &&
GIT_REPLACE_REF_BASE=refs/replace2/ git replace HEAD~1 HEAD~2 &&
GIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent \
--no-abbrev --decorate --oneline --color=always HEAD >actual &&
cmp_filtered_decorations
'
test_expect_success 'test coloring with grafted commit' '
test_when_finished rm -rf .git/refs/replace* &&
git replace --graft HEAD HEAD~2 &&
cat >expect <<-EOF &&
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \
${c_reset}${c_branch}main${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: D${c_reset}${c_commit}, \
${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&
cmp_filtered_decorations &&
git replace -d HEAD &&
GIT_REPLACE_REF_BASE=refs/replace2/ git replace --graft HEAD HEAD~2 &&
GIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent \
--no-abbrev --decorate --oneline --color=always HEAD >actual &&
cmp_filtered_decorations
'
test_done

View File

@ -162,7 +162,6 @@ test_expect_success 'prefetch multiple remotes' '
test_cmp_rev refs/remotes/remote1/one refs/prefetch/remotes/remote1/one &&
test_cmp_rev refs/remotes/remote2/two refs/prefetch/remotes/remote2/two &&
test_cmp_config refs/prefetch/ log.excludedecoration &&
git log --oneline --decorate --all >log &&
! grep "prefetch" log &&
@ -173,26 +172,6 @@ test_expect_success 'prefetch multiple remotes' '
test_subcommand git fetch remote2 $fetchargs <skip-remote1.txt
'
test_expect_success 'prefetch and existing log.excludeDecoration values' '
git config --unset-all log.excludeDecoration &&
git config log.excludeDecoration refs/remotes/remote1/ &&
git maintenance run --task=prefetch &&
git config --get-all log.excludeDecoration >out &&
grep refs/remotes/remote1/ out &&
grep refs/prefetch/ out &&
git log --oneline --decorate --all >log &&
! grep "prefetch" log &&
! grep "remote1" log &&
grep "remote2" log &&
# a second run does not change the config
git maintenance run --task=prefetch &&
git log --oneline --decorate --all >log2 &&
test_cmp log log2
'
test_expect_success 'loose-objects task' '
# Repack everything so we know the state of the object dir
git repack -adk &&