зеркало из https://github.com/microsoft/git.git
Merge branch 'ps/rev-list-object-type-filter'
"git rev-list" learns the "--filter=object:type=<type>" option, which can be used to exclude objects of the given kind from the packfile generated by pack-objects. * ps/rev-list-object-type-filter: rev-list: allow filtering of provided items pack-bitmap: implement combined filter pack-bitmap: implement object type filter list-objects: implement object type filter list-objects: support filtering by tag and commit list-objects: move tag processing into its own function revision: mark commit parents as NOT_USER_GIVEN uploadpack.txt: document implication of `uploadpackfilter.allow`
This commit is contained in:
Коммит
8585d6c04a
|
@ -59,15 +59,16 @@ uploadpack.allowFilter::
|
|||
|
||||
uploadpackfilter.allow::
|
||||
Provides a default value for unspecified object filters (see: the
|
||||
below configuration variable).
|
||||
below configuration variable). If set to `true`, this will also
|
||||
enable all filters which get added in the future.
|
||||
Defaults to `true`.
|
||||
|
||||
uploadpackfilter.<filter>.allow::
|
||||
Explicitly allow or ban the object filter corresponding to
|
||||
`<filter>`, where `<filter>` may be one of: `blob:none`,
|
||||
`blob:limit`, `tree`, `sparse:oid`, or `combine`. If using
|
||||
combined filters, both `combine` and all of the nested filter
|
||||
kinds must be allowed. Defaults to `uploadpackfilter.allow`.
|
||||
`blob:limit`, `object:type`, `tree`, `sparse:oid`, or `combine`.
|
||||
If using combined filters, both `combine` and all of the nested
|
||||
filter kinds must be allowed. Defaults to `uploadpackfilter.allow`.
|
||||
|
||||
uploadpackfilter.tree.maxDepth::
|
||||
Only allow `--filter=tree:<n>` when `<n>` is no more than the value of
|
||||
|
|
|
@ -892,6 +892,9 @@ or units. n may be zero. The suffixes k, m, and g can be used to name
|
|||
units in KiB, MiB, or GiB. For example, 'blob:limit=1k' is the same
|
||||
as 'blob:limit=1024'.
|
||||
+
|
||||
The form '--filter=object:type=(tag|commit|tree|blob)' omits all objects
|
||||
which are not of the requested type.
|
||||
+
|
||||
The form '--filter=sparse:oid=<blob-ish>' uses a sparse-checkout
|
||||
specification contained in the blob (or blob-expression) '<blob-ish>'
|
||||
to omit blobs that would not be not required for a sparse checkout on
|
||||
|
@ -930,6 +933,11 @@ equivalent.
|
|||
--no-filter::
|
||||
Turn off any previous `--filter=` argument.
|
||||
|
||||
--filter-provided-objects::
|
||||
Filter the list of explicitly provided objects, which would otherwise
|
||||
always be printed even if they did not match any of the filters. Only
|
||||
useful with `--filter=`.
|
||||
|
||||
--filter-print-omitted::
|
||||
Only useful with `--filter=`; prints a list of the objects omitted
|
||||
by the filter. Object IDs are prefixed with a ``~'' character.
|
||||
|
|
|
@ -3516,7 +3516,7 @@ static int pack_options_allow_reuse(void)
|
|||
|
||||
static int get_object_list_from_bitmap(struct rev_info *revs)
|
||||
{
|
||||
if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options)))
|
||||
if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options, 0)))
|
||||
return -1;
|
||||
|
||||
if (pack_options_allow_reuse() &&
|
||||
|
|
|
@ -398,7 +398,8 @@ static inline int parse_missing_action_value(const char *value)
|
|||
}
|
||||
|
||||
static int try_bitmap_count(struct rev_info *revs,
|
||||
struct list_objects_filter_options *filter)
|
||||
struct list_objects_filter_options *filter,
|
||||
int filter_provided_objects)
|
||||
{
|
||||
uint32_t commit_count = 0,
|
||||
tag_count = 0,
|
||||
|
@ -433,7 +434,7 @@ static int try_bitmap_count(struct rev_info *revs,
|
|||
*/
|
||||
max_count = revs->max_count;
|
||||
|
||||
bitmap_git = prepare_bitmap_walk(revs, filter);
|
||||
bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
|
||||
if (!bitmap_git)
|
||||
return -1;
|
||||
|
||||
|
@ -450,7 +451,8 @@ static int try_bitmap_count(struct rev_info *revs,
|
|||
}
|
||||
|
||||
static int try_bitmap_traversal(struct rev_info *revs,
|
||||
struct list_objects_filter_options *filter)
|
||||
struct list_objects_filter_options *filter,
|
||||
int filter_provided_objects)
|
||||
{
|
||||
struct bitmap_index *bitmap_git;
|
||||
|
||||
|
@ -461,7 +463,7 @@ static int try_bitmap_traversal(struct rev_info *revs,
|
|||
if (revs->max_count >= 0)
|
||||
return -1;
|
||||
|
||||
bitmap_git = prepare_bitmap_walk(revs, filter);
|
||||
bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
|
||||
if (!bitmap_git)
|
||||
return -1;
|
||||
|
||||
|
@ -471,14 +473,15 @@ static int try_bitmap_traversal(struct rev_info *revs,
|
|||
}
|
||||
|
||||
static int try_bitmap_disk_usage(struct rev_info *revs,
|
||||
struct list_objects_filter_options *filter)
|
||||
struct list_objects_filter_options *filter,
|
||||
int filter_provided_objects)
|
||||
{
|
||||
struct bitmap_index *bitmap_git;
|
||||
|
||||
if (!show_disk_usage)
|
||||
return -1;
|
||||
|
||||
bitmap_git = prepare_bitmap_walk(revs, filter);
|
||||
bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
|
||||
if (!bitmap_git)
|
||||
return -1;
|
||||
|
||||
|
@ -499,6 +502,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||
int bisect_show_vars = 0;
|
||||
int bisect_find_all = 0;
|
||||
int use_bitmap_index = 0;
|
||||
int filter_provided_objects = 0;
|
||||
const char *show_progress = NULL;
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
|
@ -599,6 +603,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||
list_objects_filter_set_no_filter(&filter_options);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--filter-provided-objects")) {
|
||||
filter_provided_objects = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--filter-print-omitted")) {
|
||||
arg_print_omitted = 1;
|
||||
continue;
|
||||
|
@ -665,11 +673,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||
progress = start_delayed_progress(show_progress, 0);
|
||||
|
||||
if (use_bitmap_index) {
|
||||
if (!try_bitmap_count(&revs, &filter_options))
|
||||
if (!try_bitmap_count(&revs, &filter_options, filter_provided_objects))
|
||||
return 0;
|
||||
if (!try_bitmap_disk_usage(&revs, &filter_options))
|
||||
if (!try_bitmap_disk_usage(&revs, &filter_options, filter_provided_objects))
|
||||
return 0;
|
||||
if (!try_bitmap_traversal(&revs, &filter_options))
|
||||
if (!try_bitmap_traversal(&revs, &filter_options, filter_provided_objects))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -694,6 +702,16 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||
return show_bisect_vars(&info, reaches, all);
|
||||
}
|
||||
|
||||
if (filter_provided_objects) {
|
||||
struct commit_list *c;
|
||||
for (i = 0; i < revs.pending.nr; i++) {
|
||||
struct object_array_entry *pending = revs.pending.objects + i;
|
||||
pending->item->flags |= NOT_USER_GIVEN;
|
||||
}
|
||||
for (c = revs.commits; c; c = c->next)
|
||||
c->item->object.flags |= NOT_USER_GIVEN;
|
||||
}
|
||||
|
||||
if (arg_print_omitted)
|
||||
oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
|
||||
if (arg_missing_action == MA_PRINT)
|
||||
|
|
|
@ -29,6 +29,8 @@ const char *list_object_filter_config_name(enum list_objects_filter_choice c)
|
|||
return "tree";
|
||||
case LOFC_SPARSE_OID:
|
||||
return "sparse:oid";
|
||||
case LOFC_OBJECT_TYPE:
|
||||
return "object:type";
|
||||
case LOFC_COMBINE:
|
||||
return "combine";
|
||||
case LOFC__COUNT:
|
||||
|
@ -97,6 +99,19 @@ static int gently_parse_list_objects_filter(
|
|||
}
|
||||
return 1;
|
||||
|
||||
} else if (skip_prefix(arg, "object:type=", &v0)) {
|
||||
int type = type_from_string_gently(v0, strlen(v0), 1);
|
||||
if (type < 0) {
|
||||
strbuf_addf(errbuf, _("'%s' for 'object:type=<type>' is"
|
||||
"not a valid object type"), v0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
filter_options->object_type = type;
|
||||
filter_options->choice = LOFC_OBJECT_TYPE;
|
||||
|
||||
return 0;
|
||||
|
||||
} else if (skip_prefix(arg, "combine:", &v0)) {
|
||||
return parse_combine_filter(filter_options, v0, errbuf);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef LIST_OBJECTS_FILTER_OPTIONS_H
|
||||
#define LIST_OBJECTS_FILTER_OPTIONS_H
|
||||
|
||||
#include "cache.h"
|
||||
#include "parse-options.h"
|
||||
#include "string-list.h"
|
||||
|
||||
|
@ -13,6 +14,7 @@ enum list_objects_filter_choice {
|
|||
LOFC_BLOB_LIMIT,
|
||||
LOFC_TREE_DEPTH,
|
||||
LOFC_SPARSE_OID,
|
||||
LOFC_OBJECT_TYPE,
|
||||
LOFC_COMBINE,
|
||||
LOFC__COUNT /* must be last */
|
||||
};
|
||||
|
@ -54,6 +56,7 @@ struct list_objects_filter_options {
|
|||
char *sparse_oid_name;
|
||||
unsigned long blob_limit_value;
|
||||
unsigned long tree_exclude_depth;
|
||||
enum object_type object_type;
|
||||
|
||||
/* LOFC_COMBINE values */
|
||||
|
||||
|
|
|
@ -82,6 +82,16 @@ static enum list_objects_filter_result filter_blobs_none(
|
|||
default:
|
||||
BUG("unknown filter_situation: %d", filter_situation);
|
||||
|
||||
case LOFS_TAG:
|
||||
assert(obj->type == OBJ_TAG);
|
||||
/* always include all tag objects */
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
||||
case LOFS_COMMIT:
|
||||
assert(obj->type == OBJ_COMMIT);
|
||||
/* always include all commit objects */
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
||||
case LOFS_BEGIN_TREE:
|
||||
assert(obj->type == OBJ_TREE);
|
||||
/* always include all tree objects */
|
||||
|
@ -173,6 +183,16 @@ static enum list_objects_filter_result filter_trees_depth(
|
|||
default:
|
||||
BUG("unknown filter_situation: %d", filter_situation);
|
||||
|
||||
case LOFS_TAG:
|
||||
assert(obj->type == OBJ_TAG);
|
||||
/* always include all tag objects */
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
||||
case LOFS_COMMIT:
|
||||
assert(obj->type == OBJ_COMMIT);
|
||||
/* always include all commit objects */
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
||||
case LOFS_END_TREE:
|
||||
assert(obj->type == OBJ_TREE);
|
||||
filter_data->current_depth--;
|
||||
|
@ -267,6 +287,16 @@ static enum list_objects_filter_result filter_blobs_limit(
|
|||
default:
|
||||
BUG("unknown filter_situation: %d", filter_situation);
|
||||
|
||||
case LOFS_TAG:
|
||||
assert(obj->type == OBJ_TAG);
|
||||
/* always include all tag objects */
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
||||
case LOFS_COMMIT:
|
||||
assert(obj->type == OBJ_COMMIT);
|
||||
/* always include all commit objects */
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
||||
case LOFS_BEGIN_TREE:
|
||||
assert(obj->type == OBJ_TREE);
|
||||
/* always include all tree objects */
|
||||
|
@ -371,6 +401,16 @@ static enum list_objects_filter_result filter_sparse(
|
|||
default:
|
||||
BUG("unknown filter_situation: %d", filter_situation);
|
||||
|
||||
case LOFS_TAG:
|
||||
assert(obj->type == OBJ_TAG);
|
||||
/* always include all tag objects */
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
||||
case LOFS_COMMIT:
|
||||
assert(obj->type == OBJ_COMMIT);
|
||||
/* always include all commit objects */
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
||||
case LOFS_BEGIN_TREE:
|
||||
assert(obj->type == OBJ_TREE);
|
||||
dtype = DT_DIR;
|
||||
|
@ -505,6 +545,81 @@ static void filter_sparse_oid__init(
|
|||
filter->free_fn = filter_sparse_free;
|
||||
}
|
||||
|
||||
/*
|
||||
* A filter for list-objects to omit large blobs.
|
||||
* And to OPTIONALLY collect a list of the omitted OIDs.
|
||||
*/
|
||||
struct filter_object_type_data {
|
||||
enum object_type object_type;
|
||||
};
|
||||
|
||||
static enum list_objects_filter_result filter_object_type(
|
||||
struct repository *r,
|
||||
enum list_objects_filter_situation filter_situation,
|
||||
struct object *obj,
|
||||
const char *pathname,
|
||||
const char *filename,
|
||||
struct oidset *omits,
|
||||
void *filter_data_)
|
||||
{
|
||||
struct filter_object_type_data *filter_data = filter_data_;
|
||||
|
||||
switch (filter_situation) {
|
||||
default:
|
||||
BUG("unknown filter_situation: %d", filter_situation);
|
||||
|
||||
case LOFS_TAG:
|
||||
assert(obj->type == OBJ_TAG);
|
||||
if (filter_data->object_type == OBJ_TAG)
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
return LOFR_MARK_SEEN;
|
||||
|
||||
case LOFS_COMMIT:
|
||||
assert(obj->type == OBJ_COMMIT);
|
||||
if (filter_data->object_type == OBJ_COMMIT)
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
return LOFR_MARK_SEEN;
|
||||
|
||||
case LOFS_BEGIN_TREE:
|
||||
assert(obj->type == OBJ_TREE);
|
||||
|
||||
/*
|
||||
* If we only want to show commits or tags, then there is no
|
||||
* need to walk down trees.
|
||||
*/
|
||||
if (filter_data->object_type == OBJ_COMMIT ||
|
||||
filter_data->object_type == OBJ_TAG)
|
||||
return LOFR_SKIP_TREE;
|
||||
|
||||
if (filter_data->object_type == OBJ_TREE)
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
||||
return LOFR_MARK_SEEN;
|
||||
|
||||
case LOFS_BLOB:
|
||||
assert(obj->type == OBJ_BLOB);
|
||||
|
||||
if (filter_data->object_type == OBJ_BLOB)
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
return LOFR_MARK_SEEN;
|
||||
|
||||
case LOFS_END_TREE:
|
||||
return LOFR_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
static void filter_object_type__init(
|
||||
struct list_objects_filter_options *filter_options,
|
||||
struct filter *filter)
|
||||
{
|
||||
struct filter_object_type_data *d = xcalloc(1, sizeof(*d));
|
||||
d->object_type = filter_options->object_type;
|
||||
|
||||
filter->filter_data = d;
|
||||
filter->filter_object_fn = filter_object_type;
|
||||
filter->free_fn = free;
|
||||
}
|
||||
|
||||
/* A filter which only shows objects shown by all sub-filters. */
|
||||
struct combine_filter_data {
|
||||
struct subfilter *sub;
|
||||
|
@ -651,6 +766,7 @@ static filter_init_fn s_filters[] = {
|
|||
filter_blobs_limit__init,
|
||||
filter_trees_depth__init,
|
||||
filter_sparse_oid__init,
|
||||
filter_object_type__init,
|
||||
filter_combine__init,
|
||||
};
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ enum list_objects_filter_result {
|
|||
};
|
||||
|
||||
enum list_objects_filter_situation {
|
||||
LOFS_COMMIT,
|
||||
LOFS_TAG,
|
||||
LOFS_BEGIN_TREE,
|
||||
LOFS_END_TREE,
|
||||
LOFS_BLOB
|
||||
|
|
|
@ -213,6 +213,21 @@ static void process_tree(struct traversal_context *ctx,
|
|||
free_tree_buffer(tree);
|
||||
}
|
||||
|
||||
static void process_tag(struct traversal_context *ctx,
|
||||
struct tag *tag,
|
||||
const char *name)
|
||||
{
|
||||
enum list_objects_filter_result r;
|
||||
|
||||
r = list_objects_filter__filter_object(ctx->revs->repo, LOFS_TAG,
|
||||
&tag->object, NULL, NULL,
|
||||
ctx->filter);
|
||||
if (r & LOFR_MARK_SEEN)
|
||||
tag->object.flags |= SEEN;
|
||||
if (r & LOFR_DO_SHOW)
|
||||
ctx->show_object(&tag->object, name, ctx->show_data);
|
||||
}
|
||||
|
||||
static void mark_edge_parents_uninteresting(struct commit *commit,
|
||||
struct rev_info *revs,
|
||||
show_edge_fn show_edge)
|
||||
|
@ -334,8 +349,7 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx,
|
|||
if (obj->flags & (UNINTERESTING | SEEN))
|
||||
continue;
|
||||
if (obj->type == OBJ_TAG) {
|
||||
obj->flags |= SEEN;
|
||||
ctx->show_object(obj, name, ctx->show_data);
|
||||
process_tag(ctx, (struct tag *)obj, name);
|
||||
continue;
|
||||
}
|
||||
if (!path)
|
||||
|
@ -361,6 +375,12 @@ static void do_traverse(struct traversal_context *ctx)
|
|||
strbuf_init(&csp, PATH_MAX);
|
||||
|
||||
while ((commit = get_revision(ctx->revs)) != NULL) {
|
||||
enum list_objects_filter_result r;
|
||||
|
||||
r = list_objects_filter__filter_object(ctx->revs->repo,
|
||||
LOFS_COMMIT, &commit->object,
|
||||
NULL, NULL, ctx->filter);
|
||||
|
||||
/*
|
||||
* an uninteresting boundary commit may not have its tree
|
||||
* parsed yet, but we are not going to show them anyway
|
||||
|
@ -375,7 +395,11 @@ static void do_traverse(struct traversal_context *ctx)
|
|||
die(_("unable to load root tree for commit %s"),
|
||||
oid_to_hex(&commit->object.oid));
|
||||
}
|
||||
ctx->show_commit(commit, ctx->show_data);
|
||||
|
||||
if (r & LOFR_MARK_SEEN)
|
||||
commit->object.flags |= SEEN;
|
||||
if (r & LOFR_DO_SHOW)
|
||||
ctx->show_commit(commit, ctx->show_data);
|
||||
|
||||
if (ctx->revs->tree_blobs_in_commit_order)
|
||||
/*
|
||||
|
|
|
@ -783,9 +783,6 @@ static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git,
|
|||
eword_t mask;
|
||||
uint32_t i;
|
||||
|
||||
if (type != OBJ_BLOB && type != OBJ_TREE)
|
||||
BUG("filter_bitmap_exclude_type: unsupported type '%d'", type);
|
||||
|
||||
/*
|
||||
* The non-bitmap version of this filter never removes
|
||||
* objects which the other side specifically asked for,
|
||||
|
@ -915,6 +912,24 @@ static void filter_bitmap_tree_depth(struct bitmap_index *bitmap_git,
|
|||
OBJ_BLOB);
|
||||
}
|
||||
|
||||
static void filter_bitmap_object_type(struct bitmap_index *bitmap_git,
|
||||
struct object_list *tip_objects,
|
||||
struct bitmap *to_filter,
|
||||
enum object_type object_type)
|
||||
{
|
||||
if (object_type < OBJ_COMMIT || object_type > OBJ_TAG)
|
||||
BUG("filter_bitmap_object_type given invalid object");
|
||||
|
||||
if (object_type != OBJ_TAG)
|
||||
filter_bitmap_exclude_type(bitmap_git, tip_objects, to_filter, OBJ_TAG);
|
||||
if (object_type != OBJ_COMMIT)
|
||||
filter_bitmap_exclude_type(bitmap_git, tip_objects, to_filter, OBJ_COMMIT);
|
||||
if (object_type != OBJ_TREE)
|
||||
filter_bitmap_exclude_type(bitmap_git, tip_objects, to_filter, OBJ_TREE);
|
||||
if (object_type != OBJ_BLOB)
|
||||
filter_bitmap_exclude_type(bitmap_git, tip_objects, to_filter, OBJ_BLOB);
|
||||
}
|
||||
|
||||
static int filter_bitmap(struct bitmap_index *bitmap_git,
|
||||
struct object_list *tip_objects,
|
||||
struct bitmap *to_filter,
|
||||
|
@ -947,6 +962,24 @@ static int filter_bitmap(struct bitmap_index *bitmap_git,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (filter->choice == LOFC_OBJECT_TYPE) {
|
||||
if (bitmap_git)
|
||||
filter_bitmap_object_type(bitmap_git, tip_objects,
|
||||
to_filter,
|
||||
filter->object_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (filter->choice == LOFC_COMBINE) {
|
||||
int i;
|
||||
for (i = 0; i < filter->sub_nr; i++) {
|
||||
if (filter_bitmap(bitmap_git, tip_objects, to_filter,
|
||||
&filter->sub[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* filter choice not handled */
|
||||
return -1;
|
||||
}
|
||||
|
@ -957,7 +990,8 @@ static int can_filter_bitmap(struct list_objects_filter_options *filter)
|
|||
}
|
||||
|
||||
struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
|
||||
struct list_objects_filter_options *filter)
|
||||
struct list_objects_filter_options *filter,
|
||||
int filter_provided_objects)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
@ -1052,7 +1086,8 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
|
|||
if (haves_bitmap)
|
||||
bitmap_and_not(wants_bitmap, haves_bitmap);
|
||||
|
||||
filter_bitmap(bitmap_git, wants, wants_bitmap, filter);
|
||||
filter_bitmap(bitmap_git, (filter && filter_provided_objects) ? NULL : wants,
|
||||
wants_bitmap, filter);
|
||||
|
||||
bitmap_git->result = wants_bitmap;
|
||||
bitmap_git->haves = haves_bitmap;
|
||||
|
|
|
@ -52,7 +52,8 @@ void traverse_bitmap_commit_list(struct bitmap_index *,
|
|||
void test_bitmap_walk(struct rev_info *revs);
|
||||
int test_bitmap_commits(struct repository *r);
|
||||
struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
|
||||
struct list_objects_filter_options *filter);
|
||||
struct list_objects_filter_options *filter,
|
||||
int filter_provided_objects);
|
||||
int reuse_partial_packfile_from_bitmap(struct bitmap_index *,
|
||||
struct packed_git **packfile,
|
||||
uint32_t *entries,
|
||||
|
|
|
@ -223,7 +223,7 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
|
|||
cp.progress = progress;
|
||||
cp.count = 0;
|
||||
|
||||
bitmap_git = prepare_bitmap_walk(revs, NULL);
|
||||
bitmap_git = prepare_bitmap_walk(revs, NULL, 0);
|
||||
if (bitmap_git) {
|
||||
traverse_bitmap_commit_list(bitmap_git, revs, mark_object_seen);
|
||||
free_bitmap_index(bitmap_git);
|
||||
|
|
|
@ -1123,7 +1123,7 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
|
|||
mark_parents_uninteresting(p);
|
||||
if (p->object.flags & SEEN)
|
||||
continue;
|
||||
p->object.flags |= SEEN;
|
||||
p->object.flags |= (SEEN | NOT_USER_GIVEN);
|
||||
if (list)
|
||||
commit_list_insert_by_date(p, list);
|
||||
if (queue)
|
||||
|
@ -1165,7 +1165,7 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
|
|||
}
|
||||
p->object.flags |= left_flag;
|
||||
if (!(p->object.flags & SEEN)) {
|
||||
p->object.flags |= SEEN;
|
||||
p->object.flags |= (SEEN | NOT_USER_GIVEN);
|
||||
if (list)
|
||||
commit_list_insert_by_date(p, list);
|
||||
if (queue)
|
||||
|
|
|
@ -44,9 +44,6 @@
|
|||
/*
|
||||
* Indicates object was reached by traversal. i.e. not given by user on
|
||||
* command-line or stdin.
|
||||
* NEEDSWORK: NOT_USER_GIVEN doesn't apply to commits because we only support
|
||||
* filtering trees and blobs, but it may be useful to support filtering commits
|
||||
* in the future.
|
||||
*/
|
||||
#define NOT_USER_GIVEN (1u<<25)
|
||||
#define TRACK_LINEAR (1u<<26)
|
||||
|
|
|
@ -159,6 +159,78 @@ test_expect_success 'verify blob:limit=1m' '
|
|||
test_must_be_empty observed
|
||||
'
|
||||
|
||||
# Test object:type=<type> filter.
|
||||
|
||||
test_expect_success 'setup object-type' '
|
||||
test_create_repo object-type &&
|
||||
test_commit --no-tag -C object-type message blob &&
|
||||
git -C object-type tag tag -m tag-message
|
||||
'
|
||||
|
||||
test_expect_success 'verify object:type= fails with invalid type' '
|
||||
test_must_fail git -C object-type rev-list --objects --filter=object:type= HEAD &&
|
||||
test_must_fail git -C object-type rev-list --objects --filter=object:type=invalid HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'verify object:type=blob prints blob and commit' '
|
||||
git -C object-type rev-parse HEAD >expected &&
|
||||
printf "%s blob\n" $(git -C object-type rev-parse HEAD:blob) >>expected &&
|
||||
git -C object-type rev-list --objects --filter=object:type=blob HEAD >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'verify object:type=tree prints tree and commit' '
|
||||
(
|
||||
git -C object-type rev-parse HEAD &&
|
||||
printf "%s \n" $(git -C object-type rev-parse HEAD^{tree})
|
||||
) >expected &&
|
||||
git -C object-type rev-list --objects --filter=object:type=tree HEAD >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'verify object:type=commit prints commit' '
|
||||
git -C object-type rev-parse HEAD >expected &&
|
||||
git -C object-type rev-list --objects --filter=object:type=commit HEAD >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'verify object:type=tag prints tag' '
|
||||
(
|
||||
git -C object-type rev-parse HEAD &&
|
||||
printf "%s tag\n" $(git -C object-type rev-parse tag)
|
||||
) >expected &&
|
||||
git -C object-type rev-list --objects --filter=object:type=tag tag >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'verify object:type=blob prints only blob with --filter-provided-objects' '
|
||||
printf "%s blob\n" $(git -C object-type rev-parse HEAD:blob) >expected &&
|
||||
git -C object-type rev-list --objects \
|
||||
--filter=object:type=blob --filter-provided-objects HEAD >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'verify object:type=tree prints only tree with --filter-provided-objects' '
|
||||
printf "%s \n" $(git -C object-type rev-parse HEAD^{tree}) >expected &&
|
||||
git -C object-type rev-list --objects \
|
||||
--filter=object:type=tree HEAD --filter-provided-objects >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'verify object:type=commit prints only commit with --filter-provided-objects' '
|
||||
git -C object-type rev-parse HEAD >expected &&
|
||||
git -C object-type rev-list --objects \
|
||||
--filter=object:type=commit --filter-provided-objects HEAD >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'verify object:type=tag prints only tag with --filter-provided-objects' '
|
||||
printf "%s tag\n" $(git -C object-type rev-parse tag) >expected &&
|
||||
git -C object-type rev-list --objects \
|
||||
--filter=object:type=tag --filter-provided-objects tag >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
# Test sparse:path=<path> filter.
|
||||
# !!!!
|
||||
# NOTE: sparse:path filter support has been dropped for security reasons,
|
||||
|
|
|
@ -10,7 +10,8 @@ test_expect_success 'set up bitmapped repo' '
|
|||
test_commit much-larger-blob-one &&
|
||||
git repack -adb &&
|
||||
test_commit two &&
|
||||
test_commit much-larger-blob-two
|
||||
test_commit much-larger-blob-two &&
|
||||
git tag tag
|
||||
'
|
||||
|
||||
test_expect_success 'filters fallback to non-bitmap traversal' '
|
||||
|
@ -75,4 +76,69 @@ test_expect_success 'tree:1 filter' '
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'object:type filter' '
|
||||
git rev-list --objects --filter=object:type=tag tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter=object:type=tag tag >actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
git rev-list --objects --filter=object:type=commit tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter=object:type=commit tag >actual &&
|
||||
test_bitmap_traversal expect actual &&
|
||||
|
||||
git rev-list --objects --filter=object:type=tree tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter=object:type=tree tag >actual &&
|
||||
test_bitmap_traversal expect actual &&
|
||||
|
||||
git rev-list --objects --filter=object:type=blob tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter=object:type=blob tag >actual &&
|
||||
test_bitmap_traversal expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'object:type filter with --filter-provided-objects' '
|
||||
git rev-list --objects --filter-provided-objects --filter=object:type=tag tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter-provided-objects --filter=object:type=tag tag >actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
git rev-list --objects --filter-provided-objects --filter=object:type=commit tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter-provided-objects --filter=object:type=commit tag >actual &&
|
||||
test_bitmap_traversal expect actual &&
|
||||
|
||||
git rev-list --objects --filter-provided-objects --filter=object:type=tree tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter-provided-objects --filter=object:type=tree tag >actual &&
|
||||
test_bitmap_traversal expect actual &&
|
||||
|
||||
git rev-list --objects --filter-provided-objects --filter=object:type=blob tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter-provided-objects --filter=object:type=blob tag >actual &&
|
||||
test_bitmap_traversal expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'combine filter' '
|
||||
git rev-list --objects --filter=blob:limit=1000 --filter=object:type=blob tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter=blob:limit=1000 --filter=object:type=blob tag >actual &&
|
||||
test_bitmap_traversal expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'combine filter with --filter-provided-objects' '
|
||||
git rev-list --objects --filter-provided-objects --filter=blob:limit=1000 --filter=object:type=blob tag >expect &&
|
||||
git rev-list --use-bitmap-index \
|
||||
--objects --filter-provided-objects --filter=blob:limit=1000 --filter=object:type=blob tag >actual &&
|
||||
test_bitmap_traversal expect actual &&
|
||||
|
||||
git cat-file --batch-check="%(objecttype) %(objectsize)" <actual >objects &&
|
||||
while read objecttype objectsize
|
||||
do
|
||||
test "$objecttype" = blob || return 1
|
||||
test "$objectsize" -le 1000 || return 1
|
||||
done <objects
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
Загрузка…
Ссылка в новой задаче