Skip to content

Commit d4703fd

Browse files
committed
Merge branch 'ds/backfill-revs' into next
`git backfill` learned to accept revision and pathspec arguments. * ds/backfill-revs: t5620: test backfill's unknown argument handling path-walk: support wildcard pathspecs for blob filtering backfill: work with prefix pathspecs backfill: accept revision arguments t5620: prepare branched repo for revision tests revision: include object-name.h
2 parents 0a8c60e + 46d1f4c commit d4703fd

7 files changed

Lines changed: 280 additions & 10 deletions

File tree

Documentation/git-backfill.adoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,12 @@ OPTIONS
6363
current sparse-checkout. If the sparse-checkout feature is enabled,
6464
then `--sparse` is assumed and can be disabled with `--no-sparse`.
6565

66+
You may also specify the commit limiting options from linkgit:git-rev-list[1].
67+
6668
SEE ALSO
6769
--------
68-
linkgit:git-clone[1].
70+
linkgit:git-clone[1],
71+
linkgit:git-rev-list[1]
6972

7073
GIT
7174
---

builtin/backfill.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct backfill_context {
3535
struct oid_array current_batch;
3636
size_t min_batch_size;
3737
int sparse;
38+
struct rev_info revs;
3839
};
3940

4041
static void backfill_context_clear(struct backfill_context *ctx)
@@ -79,7 +80,6 @@ static int fill_missing_blobs(const char *path UNUSED,
7980

8081
static int do_backfill(struct backfill_context *ctx)
8182
{
82-
struct rev_info revs;
8383
struct path_walk_info info = PATH_WALK_INFO_INIT;
8484
int ret;
8585

@@ -91,13 +91,14 @@ static int do_backfill(struct backfill_context *ctx)
9191
}
9292
}
9393

94-
repo_init_revisions(ctx->repo, &revs, "");
95-
handle_revision_arg("HEAD", &revs, 0, 0);
94+
/* Walk from HEAD if otherwise unspecified. */
95+
if (!ctx->revs.pending.nr)
96+
add_head_to_pending(&ctx->revs);
9697

9798
info.blobs = 1;
9899
info.tags = info.commits = info.trees = 0;
99100

100-
info.revs = &revs;
101+
info.revs = &ctx->revs;
101102
info.path_fn = fill_missing_blobs;
102103
info.path_fn_data = ctx;
103104

@@ -108,7 +109,6 @@ static int do_backfill(struct backfill_context *ctx)
108109
download_batch(ctx);
109110

110111
path_walk_info_clear(&info);
111-
release_revisions(&revs);
112112
return ret;
113113
}
114114

@@ -120,6 +120,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
120120
.current_batch = OID_ARRAY_INIT,
121121
.min_batch_size = 50000,
122122
.sparse = 0,
123+
.revs = REV_INFO_INIT,
123124
};
124125
struct option options[] = {
125126
OPT_UNSIGNED(0, "min-batch-size", &ctx.min_batch_size,
@@ -134,7 +135,15 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
134135
builtin_backfill_usage, options);
135136

136137
argc = parse_options(argc, argv, prefix, options, builtin_backfill_usage,
137-
0);
138+
PARSE_OPT_KEEP_UNKNOWN_OPT |
139+
PARSE_OPT_KEEP_ARGV0 |
140+
PARSE_OPT_KEEP_DASHDASH);
141+
142+
repo_init_revisions(repo, &ctx.revs, prefix);
143+
argc = setup_revisions(argc, argv, &ctx.revs, NULL);
144+
145+
if (argc > 1)
146+
die(_("unrecognized argument: %s"), argv[1]);
138147

139148
repo_config(repo, git_default_config, NULL);
140149

@@ -143,5 +152,6 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
143152

144153
result = do_backfill(&ctx);
145154
backfill_context_clear(&ctx);
155+
release_revisions(&ctx.revs);
146156
return result;
147157
}

path-walk.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "list-objects.h"
1212
#include "object.h"
1313
#include "oid-array.h"
14+
#include "path.h"
1415
#include "prio-queue.h"
1516
#include "repository.h"
1617
#include "revision.h"
@@ -62,6 +63,8 @@ struct path_walk_context {
6263
*/
6364
struct prio_queue path_stack;
6465
struct strset path_stack_pushed;
66+
67+
unsigned exact_pathspecs:1;
6568
};
6669

6770
static int compare_by_type(const void *one, const void *two, void *cb_data)
@@ -206,6 +209,33 @@ static int add_tree_entries(struct path_walk_context *ctx,
206209
match != MATCHED)
207210
continue;
208211
}
212+
if (ctx->revs->prune_data.nr && ctx->exact_pathspecs) {
213+
struct pathspec *pd = &ctx->revs->prune_data;
214+
bool found = false;
215+
int did_strip_suffix = strbuf_strip_suffix(&path, "/");
216+
217+
218+
for (int i = 0; i < pd->nr; i++) {
219+
struct pathspec_item *item = &pd->items[i];
220+
221+
/*
222+
* Continue if either is a directory prefix
223+
* of the other.
224+
*/
225+
if (dir_prefix(path.buf, item->match) ||
226+
dir_prefix(item->match, path.buf)) {
227+
found = true;
228+
break;
229+
}
230+
}
231+
232+
if (did_strip_suffix)
233+
strbuf_addch(&path, '/');
234+
235+
/* Skip paths that do not match the prefix. */
236+
if (!found)
237+
continue;
238+
}
209239

210240
add_path_to_list(ctx, path.buf, type, &entry.oid,
211241
!(o->flags & UNINTERESTING));
@@ -274,6 +304,13 @@ static int walk_path(struct path_walk_context *ctx,
274304
return 0;
275305
}
276306

307+
if (list->type == OBJ_BLOB &&
308+
ctx->revs->prune_data.nr &&
309+
!match_pathspec(ctx->repo->index, &ctx->revs->prune_data,
310+
path, strlen(path), 0,
311+
NULL, 0))
312+
return 0;
313+
277314
/* Evaluate function pointer on this data, if requested. */
278315
if ((list->type == OBJ_TREE && ctx->info->trees) ||
279316
(list->type == OBJ_BLOB && ctx->info->blobs) ||
@@ -481,6 +518,12 @@ int walk_objects_by_path(struct path_walk_info *info)
481518
if (info->tags)
482519
info->revs->tag_objects = 1;
483520

521+
if (ctx.revs->prune_data.nr) {
522+
if (!ctx.revs->prune_data.has_wildcard &&
523+
!ctx.revs->prune_data.magic)
524+
ctx.exact_pathspecs = 1;
525+
}
526+
484527
/* Insert a single list for the root tree into the paths. */
485528
CALLOC_ARRAY(root_tree_list, 1);
486529
root_tree_list->type = OBJ_TREE;

path.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static void strbuf_cleanup_path(struct strbuf *sb)
5656
strbuf_remove(sb, 0, path - sb->buf);
5757
}
5858

59-
static int dir_prefix(const char *buf, const char *dir)
59+
int dir_prefix(const char *buf, const char *dir)
6060
{
6161
size_t len = strlen(dir);
6262
return !strncmp(buf, dir, len) &&

path.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ const char *repo_submodule_path_replace(struct repository *repo,
112112
const char *fmt, ...)
113113
__attribute__((format (printf, 4, 5)));
114114

115+
/*
116+
* Given a directory name 'dir' (not ending with a trailing '/'),
117+
* determine if 'buf' is equal to 'dir' or has prefix 'dir'+'/'.
118+
*/
119+
int dir_prefix(const char *buf, const char *dir);
120+
115121
void report_linked_checkout_garbage(struct repository *r);
116122

117123
/*

revision.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "commit.h"
55
#include "grep.h"
66
#include "notes.h"
7+
#include "object-name.h"
78
#include "oidset.h"
89
#include "pretty.h"
910
#include "diff.h"

0 commit comments

Comments
 (0)