1
#include "builtin.h"
2
+#include "git-compat-util.h"
3
#include "config.h"
4
#include "parse-options.h"
5
#include "repository.h"
6
+#include "commit.h"
7
+#include "hex.h"
8
+#include "tree.h"
9
+#include "tree-walk.h"
10
#include "object.h"
11
+#include "object-store-ll.h"
12
+#include "oid-array.h"
13
+#include "oidset.h"
14
+#include "promisor-remote.h"
15
+#include "strmap.h"
16
+#include "string-list.h"
17
+#include "revision.h"
18
+#include "trace2.h"
19
+#include "progress.h"
20
+#include "packfile.h"
21
+#include "path-walk.h"
22
23
static const char * const builtin_backfill_usage[] = {
24
N_("git backfill [<options>]"),
25
NULL
26
};
27
28
+struct backfill_context {
29
+ struct repository *repo;
30
+ struct oid_array current_batch;
31
+ size_t min_batch_size;
32
+};
33
+
34
+static void backfill_context_clear(struct backfill_context *ctx)
35
+{
36
+ oid_array_clear(&ctx->current_batch);
37
+}
38
+
39
+static void download_batch(struct backfill_context *ctx)
40
+{
41
+ promisor_remote_get_direct(ctx->repo,
42
+ ctx->current_batch.oid,
43
+ ctx->current_batch.nr);
44
+ oid_array_clear(&ctx->current_batch);
45
+
46
+ /*
47
+ * We likely have a new packfile. Add it to the packed list to
48
+ * avoid possible duplicate downloads of the same objects.
49
+ */
50
+ reprepare_packed_git(ctx->repo);
51
+}
52
+
53
+static int fill_missing_blobs(const char *path UNUSED,
54
+ struct oid_array *list,
55
+ enum object_type type,
56
+ void *data)
57
+{
58
+ struct backfill_context *ctx = data;
59
+
60
+ if (type != OBJ_BLOB)
61
+ return 0;
62
+
63
+ for (size_t i = 0; i < list->nr; i++) {
64
+ if (!has_object(ctx->repo, &list->oid[i],
65
+ OBJECT_INFO_FOR_PREFETCH))
66
+ oid_array_append(&ctx->current_batch, &list->oid[i]);
67
+ }
68
+
69
+ if (ctx->current_batch.nr >= ctx->min_batch_size)
70
+ download_batch(ctx);
71
+
72
+ return 0;
73
+}
74
+
75
+static int do_backfill(struct backfill_context *ctx)
76
+{
77
+ struct rev_info revs;
78
+ struct path_walk_info info = PATH_WALK_INFO_INIT;
79
+ int ret;
80
+
81
+ repo_init_revisions(ctx->repo, &revs, "");
82
+ handle_revision_arg("HEAD", &revs, 0, 0);
83
+
84
+ info.blobs = 1;
85
+ info.tags = info.commits = info.trees = 0;
86
+
87
+ info.revs = &revs;
88
+ info.path_fn = fill_missing_blobs;
89
+ info.path_fn_data = ctx;
90
+
91
+ ret = walk_objects_by_path(&info);
92
+
93
+ /* Download the objects that did not fill a batch. */
94
+ if (!ret)
95
+ download_batch(ctx);
96
+
97
+ path_walk_info_clear(&info);
98
+ release_revisions(&revs);
99
+ return ret;
100
+}
101
+
102
int cmd_backfill(int argc, const char **argv, const char *prefix, struct repository *repo)
103
{
104
+ int result;
105
+ struct backfill_context ctx = {
106
+ .repo = repo,
107
+ .current_batch = OID_ARRAY_INIT,
108
+ .min_batch_size = 50000,
109
+ };
110
struct option options[] = {
111
OPT_END(),
112
};
118
119
repo_config(repo, git_default_config, NULL);
120
25
- die(_("not implemented"));
26
-
27
- return 0;
121
+ result = do_backfill(&ctx);
122
+ backfill_context_clear(&ctx);
123
+ return result;
124
}