Skip to content

Commit ce8a6ec

Browse files
committed
Merge branch 'backfill-revs' into cache-server
2 parents 8744a80 + 01dc31b commit ce8a6ec

File tree

5 files changed

+279
-8
lines changed

5 files changed

+279
-8
lines changed

Documentation/git-backfill.adoc

Lines changed: 3 additions & 0 deletions
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
--------
6870
linkgit:git-clone[1].
71+
linkgit:git-rev-list[1].
6972

7073
GIT
7174
---

builtin/backfill.c

Lines changed: 13 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)
@@ -80,7 +81,6 @@ static int fill_missing_blobs(const char *path UNUSED,
8081

8182
static int do_backfill(struct backfill_context *ctx)
8283
{
83-
struct rev_info revs;
8484
struct path_walk_info info = PATH_WALK_INFO_INIT;
8585
int ret;
8686

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

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

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

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

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

111112
path_walk_info_clear(&info);
112-
release_revisions(&revs);
113113
return ret;
114114
}
115115

@@ -121,6 +121,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
121121
.current_batch = OID_ARRAY_INIT,
122122
.min_batch_size = 50000,
123123
.sparse = 0,
124+
.revs = REV_INFO_INIT,
124125
};
125126
struct option options[] = {
126127
OPT_UNSIGNED(0, "min-batch-size", &ctx.min_batch_size,
@@ -134,7 +135,12 @@ 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);
138144

139145
repo_config(repo, git_default_config, NULL);
140146

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

144150
result = do_backfill(&ctx);
145151
backfill_context_clear(&ctx);
152+
release_revisions(&ctx.revs);
146153
return result;
147154
}

path-walk.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ struct path_walk_context {
6262
*/
6363
struct prio_queue path_stack;
6464
struct strset path_stack_pushed;
65+
66+
unsigned exact_pathspecs:1;
6567
};
6668

6769
static int compare_by_type(const void *one, const void *two, void *cb_data)
@@ -206,6 +208,49 @@ static int add_tree_entries(struct path_walk_context *ctx,
206208
match != MATCHED)
207209
continue;
208210
}
211+
if (ctx->revs->prune_data.nr && ctx->exact_pathspecs) {
212+
struct pathspec *pd = &ctx->revs->prune_data;
213+
bool found = false;
214+
215+
for (int i = 0; i < pd->nr; i++) {
216+
struct pathspec_item *item = &pd->items[i];
217+
218+
/*
219+
* Is this path a parent directory of
220+
* the pathspec item?
221+
*/
222+
if (path.len < (size_t)item->len &&
223+
!strncmp(path.buf, item->match, path.len) &&
224+
item->match[path.len - 1] == '/') {
225+
found = true;
226+
break;
227+
}
228+
229+
/*
230+
* Or, is the pathspec an exact match?
231+
*/
232+
if (path.len == (size_t)item->len &&
233+
!strcmp(path.buf, item->match)) {
234+
found = true;
235+
break;
236+
}
237+
238+
/*
239+
* Or, is the pathspec a directory prefix
240+
* match?
241+
*/
242+
if (path.len > (size_t)item->len &&
243+
!strncmp(path.buf, item->match, item->len) &&
244+
path.buf[item->len] == '/') {
245+
found = true;
246+
break;
247+
}
248+
}
249+
250+
/* Skip paths that do not match the prefix. */
251+
if (!found)
252+
continue;
253+
}
209254

210255
add_path_to_list(ctx, path.buf, type, &entry.oid,
211256
!(o->flags & UNINTERESTING));
@@ -274,6 +319,13 @@ static int walk_path(struct path_walk_context *ctx,
274319
return 0;
275320
}
276321

322+
if (list->type == OBJ_BLOB &&
323+
ctx->revs->prune_data.nr &&
324+
!match_pathspec(ctx->repo->index, &ctx->revs->prune_data,
325+
path, strlen(path), 0,
326+
NULL, 0))
327+
return 0;
328+
277329
/* Evaluate function pointer on this data, if requested. */
278330
if ((list->type == OBJ_TREE && ctx->info->trees) ||
279331
(list->type == OBJ_BLOB && ctx->info->blobs) ||
@@ -481,6 +533,15 @@ int walk_objects_by_path(struct path_walk_info *info)
481533
if (info->tags)
482534
info->revs->tag_objects = 1;
483535

536+
if (ctx.revs->prune_data.nr) {
537+
struct pathspec *pd = &ctx.revs->prune_data;
538+
539+
if (!pd->has_wildcard && !pd->magic)
540+
ctx.exact_pathspecs = 1;
541+
else
542+
ctx.revs->prune = 0;
543+
}
544+
484545
/* Insert a single list for the root tree into the paths. */
485546
CALLOC_ARRAY(root_tree_list, 1);
486547
root_tree_list->type = OBJ_TREE;

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)