mirror of
https://github.com/git-for-windows/git.git
synced 2026-06-11 08:30:32 -05:00
The `object:type` filter accepts only objects of a single type; it is
the second member of the object-info-only filter family that bitmap
traversal already supports.
Like `blob:none` and `tree:0`, it can be evaluated with nothing more
than the object's type, which is exactly the granularity path-walk's
existing info->{commits,trees,blobs,tags} flags already control.
Map `LOFC_OBJECT_TYPE` in `prepare_filters()` by AND-ing each flag
against the filtered type. A single `object:type=X` filter
applied to the default info (all flags = 1) leaves `info->X = 1` and
all the others 0, which is what we want.
Using an AND rather than straight assignment prepares us for a
subsequent change to implement combined object filters.
The path-walk machinery is mostly already wired for the per-type
distinction:
- `walk_path()` calls `path_fn` for a batch only when the corresponding
`info->X` flag is set, so unwanted types are silently not reported.
- `add_tree_entries()` skips tree entries of type `OBJ_BLOB` when
`info->blobs` is unset, so we don't even allocate paths for them.
- The commit-walk loop short-circuits the root-tree fetch when
`!info->trees && !info->blobs`, so commit-only filters don't descend
into trees at all.
But there are a couple of side effects of the "trees off, blobs on" case
that need fixing:
1. 'setup_pending_objects()' previously skipped pending trees as soon
as `info->trees` was zero. For 'object:type=blob' the call site
needs those pending trees: a lightweight tag pointing to a tree, or
an annotated tag whose peeled target is a tree, can both reach
blobs that are otherwise unreachable from any commit's root tree.
Loosen the gate to "if (!info->trees && !info->blobs) continue" and
similarly retrieve the root_tree_list whenever either trees or
blobs are wanted.
2. The revision machinery's `handle_commit()` drops pending trees when
`revs->tree_objects` is zero (see the 'OBJ_TREE' handler in
revision.c), so by the time path-walk sees the pending list
after `prepare_revision_walk()` the tree-bearing pendings would
already be gone. Fix this by setting
revs->tree_objects = info->trees || info->blobs
so pending trees survive `prepare_revision_walk()` whenever we
need to walk into them. Path-walk still resets tree_objects to
zero immediately after `prepare_revision_walk()` returns, so the
rev-walk itself never enumerates trees redundantly with
path-walk's own descent.
Add coverage in t6601 for each of the four `object:type` values. The
'object:type=blob' test in particular asserts that file2 and child/file
(both reachable only through tag-pointed trees) show up in the output,
exercising the pending-tree fix.
Update Documentation/git-pack-objects.adoc to add object:type to
the list of supported --filter forms.
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
119 lines
3.6 KiB
C
119 lines
3.6 KiB
C
/*
|
|
* path-walk.h : Methods and structures for walking the object graph in batches
|
|
* by the paths that can reach those objects.
|
|
*/
|
|
#include "object.h" /* Required for 'enum object_type'. */
|
|
|
|
struct rev_info;
|
|
struct oid_array;
|
|
struct pattern_list;
|
|
|
|
/**
|
|
* The type of a function pointer for the method that is called on a list of
|
|
* objects reachable at a given path.
|
|
*/
|
|
typedef int (*path_fn)(const char *path,
|
|
struct oid_array *oids,
|
|
enum object_type type,
|
|
void *data);
|
|
|
|
struct path_walk_info {
|
|
/**
|
|
* revs provides the definitions for the commit walk, including
|
|
* which commits are UNINTERESTING or not. This structure is
|
|
* expected to be owned by the caller.
|
|
*/
|
|
struct rev_info *revs;
|
|
|
|
/**
|
|
* The caller wishes to execute custom logic on objects reachable at a
|
|
* given path. Every reachable object will be visited exactly once, and
|
|
* the first path to see an object wins. This may not be a stable choice.
|
|
*/
|
|
path_fn path_fn;
|
|
void *path_fn_data;
|
|
|
|
/**
|
|
* Initialize which object types the path_fn should be called on. This
|
|
* could also limit the walk to skip blobs if not set.
|
|
*
|
|
* Note: even when 'blobs' or 'trees' is disabled, objects that are
|
|
* directly requested as pending objects will still be emitted to
|
|
* path_fn. Only objects discovered during the tree walk are filtered by
|
|
* these flags.
|
|
*/
|
|
int commits;
|
|
int trees;
|
|
int blobs;
|
|
int tags;
|
|
|
|
/**
|
|
* If 'strict_types' is 0, then direct object requests will no longer
|
|
* override the object type restrictions.
|
|
*/
|
|
int strict_types;
|
|
|
|
/**
|
|
* If non-zero, specifies a maximum blob size. Blobs with a
|
|
* size equal to or greater than this limit will not be
|
|
* emitted unless included in 'pending'.
|
|
*/
|
|
unsigned long blob_limit;
|
|
|
|
/**
|
|
* When 'prune_all_uninteresting' is set and a path has all objects
|
|
* marked as UNINTERESTING, then the path-walk will not visit those
|
|
* objects. It will not call path_fn on those objects and will not
|
|
* walk the children of such trees.
|
|
*/
|
|
int prune_all_uninteresting;
|
|
|
|
/**
|
|
* When 'edge_aggressive' is set, then the revision walk will use
|
|
* the '--object-edge-aggressive' option to mark even more objects
|
|
* as uninteresting.
|
|
*/
|
|
int edge_aggressive;
|
|
|
|
/**
|
|
* Specify a sparse-checkout definition to match our paths to. Do not
|
|
* walk outside of this sparse definition. If the patterns are in
|
|
* cone mode, then the search may prune directories that are outside
|
|
* of the cone. If not in cone mode, then all tree paths will be
|
|
* explored but the path_fn will only be called when the path matches
|
|
* the sparse-checkout patterns.
|
|
*
|
|
* When 'pl_sparse_trees' is zero, the sparse patterns only restrict
|
|
* blobs and all trees are included in the walk output. This matches
|
|
* the behavior of the sparse:oid object filter. When nonzero, trees
|
|
* are also pruned by the sparse patterns (as used by backfill).
|
|
*/
|
|
struct pattern_list *pl;
|
|
int pl_sparse_trees;
|
|
};
|
|
|
|
#define PATH_WALK_INFO_INIT { \
|
|
.blobs = 1, \
|
|
.trees = 1, \
|
|
.commits = 1, \
|
|
.tags = 1, \
|
|
}
|
|
|
|
void path_walk_info_init(struct path_walk_info *info);
|
|
void path_walk_info_clear(struct path_walk_info *info);
|
|
|
|
/**
|
|
* Given the configuration of 'info', walk the commits based on 'info->revs' and
|
|
* call 'info->path_fn' on each discovered path.
|
|
*
|
|
* Returns nonzero on an error.
|
|
*/
|
|
int walk_objects_by_path(struct path_walk_info *info);
|
|
|
|
struct list_objects_filter_options;
|
|
/**
|
|
* Given a set of options for filtering objects, return 1 if the options
|
|
* are compatible with the path-walk API and 0 otherwise.
|
|
*/
|
|
int path_walk_filter_compatible(struct list_objects_filter_options *options);
|