Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2021-07-28 23:17:58 +0300
committerJunio C Hamano <gitster@pobox.com>2021-07-28 23:17:58 +0300
commitc9d6d8a1938f86594b33785a8228d9f35ad457c8 (patch)
tree2b658bf0a8be2b3c2a736e6e4032acdb778da1aa
parent01369fdfd3d0deec41c55306dae42f00dfbfa582 (diff)
parentd1ed8d6cee57c91ec770a8a183ed40c3ec867ac1 (diff)
Merge branch 'jk/log-decorate-optim'
Optimize "git log" for cases where we wasted cycles to load ref decoration data that may not be needed. * jk/log-decorate-optim: load_ref_decorations(): fix decoration with tags add_ref_decoration(): rename s/type/deco_type/ load_ref_decorations(): avoid parsing non-tag objects object.h: add lookup_object_by_type() function object.h: expand docstring for lookup_unknown_object() log: avoid loading decorations for userformats that don't need it pretty.h: update and expand docstring for userformat_find_requirements()
-rw-r--r--builtin/log.c3
-rw-r--r--log-tree.c24
-rw-r--r--object.c18
-rw-r--r--object.h20
-rw-r--r--pretty.c4
-rw-r--r--pretty.h8
-rw-r--r--reachable.c18
-rwxr-xr-xt/t4202-log.sh14
8 files changed, 77 insertions, 32 deletions
diff --git a/builtin/log.c b/builtin/log.c
index 516a1142dd..3d7717ba5c 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -245,6 +245,9 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
rev->abbrev_commit = 0;
}
+ if (rev->commit_format == CMIT_FMT_USERFORMAT && !w.decorate)
+ decoration_style = 0;
+
if (decoration_style) {
const struct string_list *config_exclude =
repo_config_get_value_multi(the_repository,
diff --git a/log-tree.c b/log-tree.c
index 7b823786c2..6dc4412268 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -134,7 +134,8 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,
int flags, void *cb_data)
{
struct object *obj;
- enum decoration_type type = DECORATION_NONE;
+ enum object_type objtype;
+ enum decoration_type deco_type = DECORATION_NONE;
struct decoration_filter *filter = (struct decoration_filter *)cb_data;
if (filter && !ref_filter_match(refname, filter))
@@ -155,28 +156,29 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,
return 0;
}
- obj = parse_object(the_repository, oid);
- if (!obj)
+ objtype = oid_object_info(the_repository, oid, NULL);
+ if (objtype < 0)
return 0;
+ obj = lookup_object_by_type(the_repository, oid, objtype);
if (starts_with(refname, "refs/heads/"))
- type = DECORATION_REF_LOCAL;
+ deco_type = DECORATION_REF_LOCAL;
else if (starts_with(refname, "refs/remotes/"))
- type = DECORATION_REF_REMOTE;
+ deco_type = DECORATION_REF_REMOTE;
else if (starts_with(refname, "refs/tags/"))
- type = DECORATION_REF_TAG;
+ deco_type = DECORATION_REF_TAG;
else if (!strcmp(refname, "refs/stash"))
- type = DECORATION_REF_STASH;
+ deco_type = DECORATION_REF_STASH;
else if (!strcmp(refname, "HEAD"))
- type = DECORATION_REF_HEAD;
+ deco_type = DECORATION_REF_HEAD;
- add_name_decoration(type, refname, obj);
+ add_name_decoration(deco_type, refname, obj);
while (obj->type == OBJ_TAG) {
+ if (!obj->parsed)
+ parse_object(the_repository, &obj->oid);
obj = ((struct tag *)obj)->tagged;
if (!obj)
break;
- if (!obj->parsed)
- parse_object(the_repository, &obj->oid);
add_name_decoration(DECORATION_REF_TAG, refname, obj);
}
return 0;
diff --git a/object.c b/object.c
index 2b3c075a15..4e85955a94 100644
--- a/object.c
+++ b/object.c
@@ -185,6 +185,24 @@ struct object *lookup_unknown_object(struct repository *r, const struct object_i
return obj;
}
+struct object *lookup_object_by_type(struct repository *r,
+ const struct object_id *oid,
+ enum object_type type)
+{
+ switch (type) {
+ case OBJ_COMMIT:
+ return (struct object *)lookup_commit(r, oid);
+ case OBJ_TREE:
+ return (struct object *)lookup_tree(r, oid);
+ case OBJ_TAG:
+ return (struct object *)lookup_tag(r, oid);
+ case OBJ_BLOB:
+ return (struct object *)lookup_blob(r, oid);
+ default:
+ die("BUG: unknown object type %d", type);
+ }
+}
+
struct object *parse_object_buffer(struct repository *r, const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p)
{
struct object *obj;
diff --git a/object.h b/object.h
index 8bca310713..3b38c9cc98 100644
--- a/object.h
+++ b/object.h
@@ -144,9 +144,27 @@ struct object *parse_object_or_die(const struct object_id *oid, const char *name
*/
struct object *parse_object_buffer(struct repository *r, const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p);
-/** Returns the object, with potentially excess memory allocated. **/
+/*
+ * Allocate and return an object struct, even if you do not know the type of
+ * the object. The returned object may have its "type" field set to a real type
+ * (if somebody previously called lookup_blob(), etc), or it may be set to
+ * OBJ_NONE. In the latter case, subsequent calls to lookup_blob(), etc, will
+ * set the type field as appropriate.
+ *
+ * Use this when you do not know the expected type of an object and want to
+ * avoid parsing it for efficiency reasons. Try to avoid it otherwise; it
+ * may allocate excess memory, since the returned object must be as large as
+ * the maximum struct of any type.
+ */
struct object *lookup_unknown_object(struct repository *r, const struct object_id *oid);
+/*
+ * Dispatch to the appropriate lookup_blob(), lookup_commit(), etc, based on
+ * "type".
+ */
+struct object *lookup_object_by_type(struct repository *r, const struct object_id *oid,
+ enum object_type type);
+
struct object_list *object_list_insert(struct object *item,
struct object_list **list_p);
diff --git a/pretty.c b/pretty.c
index b1ecd039ce..9631529c10 100644
--- a/pretty.c
+++ b/pretty.c
@@ -1735,6 +1735,10 @@ static size_t userformat_want_item(struct strbuf *sb, const char *placeholder,
case 'S':
w->source = 1;
break;
+ case 'd':
+ case 'D':
+ w->decorate = 1;
+ break;
}
return 0;
}
diff --git a/pretty.h b/pretty.h
index f034609e4d..2f16acd213 100644
--- a/pretty.h
+++ b/pretty.h
@@ -65,12 +65,16 @@ static inline int cmit_fmt_is_mail(enum cmit_fmt fmt)
return (fmt == CMIT_FMT_EMAIL || fmt == CMIT_FMT_MBOXRD);
}
+/*
+ * Examine the user-specified format given by "fmt" (or if NULL, the global one
+ * previously saved by get_commit_format()), and set flags based on which items
+ * the format will need when it is expanded.
+ */
struct userformat_want {
unsigned notes:1;
unsigned source:1;
+ unsigned decorate:1;
};
-
-/* Set the flag "w->notes" if there is placeholder %N in "fmt". */
void userformat_find_requirements(const char *fmt, struct userformat_want *w);
/*
diff --git a/reachable.c b/reachable.c
index c59847257a..84e3d0d75e 100644
--- a/reachable.c
+++ b/reachable.c
@@ -159,24 +159,6 @@ int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
FOR_EACH_OBJECT_LOCAL_ONLY);
}
-static void *lookup_object_by_type(struct repository *r,
- const struct object_id *oid,
- enum object_type type)
-{
- switch (type) {
- case OBJ_COMMIT:
- return lookup_commit(r, oid);
- case OBJ_TREE:
- return lookup_tree(r, oid);
- case OBJ_TAG:
- return lookup_tag(r, oid);
- case OBJ_BLOB:
- return lookup_blob(r, oid);
- default:
- die("BUG: unknown object type %d", type);
- }
-}
-
static int mark_object_seen(const struct object_id *oid,
enum object_type type,
int exclude,
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 39e746fbcb..9dfead936b 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -1915,6 +1915,20 @@ test_expect_success '--exclude-promisor-objects does not BUG-crash' '
test_must_fail git log --exclude-promisor-objects source-a
'
+test_expect_success 'log --decorate includes all levels of tag annotated tags' '
+ git checkout -b branch &&
+ git commit --allow-empty -m "new commit" &&
+ git tag lightweight HEAD &&
+ git tag -m annotated annotated HEAD &&
+ git tag -m double-0 double-0 HEAD &&
+ git tag -m double-1 double-1 double-0 &&
+ cat >expect <<-\EOF &&
+ HEAD -> branch, tag: lightweight, tag: double-1, tag: double-0, tag: annotated
+ EOF
+ git log -1 --format="%D" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'log --end-of-options' '
git update-ref refs/heads/--source HEAD &&
git log --end-of-options --source >actual &&