Merge branch 'jn/gitweb-blame' into pu
[git/spearce.git] / builtin-rev-cache.c
blob4c1766d7f3047349f2404e8165c947297748e443
1 #include "cache.h"
2 #include "object.h"
3 #include "commit.h"
4 #include "diff.h"
5 #include "revision.h"
6 #include "rev-cache.h"
7 #include "list-objects.h"
9 unsigned long default_ignore_size = 50 * 1024 * 1024; /* 50mb */
11 /* porcelain for rev-cache.c */
12 static int handle_add(int argc, const char *argv[]) /* args beyond this command */
14 struct rev_info revs;
15 struct rev_cache_info rci;
16 char dostdin = 0;
17 unsigned int flags = 0;
18 int i, retval;
19 unsigned char cache_sha1[20];
20 struct commit_list *starts = 0, *ends = 0;
21 struct commit *commit;
23 init_revisions(&revs, 0);
24 init_rev_cache_info(&rci);
26 for (i = 0; i < argc; i++) {
27 if (!strcmp(argv[i], "--stdin"))
28 dostdin = 1;
29 else if (!strcmp(argv[i], "--fresh") || !strcmp(argv[i], "--incremental"))
30 starts_from_slices(&revs, UNINTERESTING, 0, 0);
31 else if (!strcmp(argv[i], "--not"))
32 flags ^= UNINTERESTING;
33 else if (!strcmp(argv[i], "--legs"))
34 rci.legs = 1;
35 else if (!strcmp(argv[i], "--no-objects"))
36 rci.objects = 0;
37 else if (!strcmp(argv[i], "--all")) {
38 const char *args[2];
39 int argn = 0;
41 args[argn++] = "rev-list";
42 args[argn++] = "--all";
43 setup_revisions(argn, args, &revs, 0);
44 } else
45 handle_revision_arg(argv[i], &revs, flags, 1);
48 if (dostdin) {
49 char line[1000];
51 flags = 0;
52 while (fgets(line, sizeof(line), stdin)) {
53 int len = strlen(line);
54 while (len && (line[len - 1] == '\n' || line[len - 1] == '\r'))
55 line[--len] = 0;
57 if (!len)
58 break;
60 if (!strcmp(line, "--not"))
61 flags ^= UNINTERESTING;
62 else
63 handle_revision_arg(line, &revs, flags, 1);
67 retval = make_cache_slice(&rci, &revs, &starts, &ends, cache_sha1);
68 if (retval < 0)
69 return retval;
71 printf("%s\n", sha1_to_hex(cache_sha1));
73 fprintf(stderr, "endpoints:\n");
74 while ((commit = pop_commit(&starts)))
75 fprintf(stderr, "S %s\n", sha1_to_hex(commit->object.sha1));
76 while ((commit = pop_commit(&ends)))
77 fprintf(stderr, "E %s\n", sha1_to_hex(commit->object.sha1));
79 return 0;
82 static void show_commit(struct commit *commit, void *data)
84 printf("%s\n", sha1_to_hex(commit->object.sha1));
87 static void show_object(struct object *obj, const struct name_path *path, const char *last)
89 printf("%s\n", sha1_to_hex(obj->sha1));
92 static int test_rev_list(int argc, const char *argv[])
94 struct rev_info revs;
95 unsigned int flags = 0;
96 int i;
98 init_revisions(&revs, 0);
100 for (i = 0; i < argc; i++) {
101 if (!strcmp(argv[i], "--not"))
102 flags ^= UNINTERESTING;
103 else if (!strcmp(argv[i], "--objects"))
104 revs.tree_objects = revs.blob_objects = 1;
105 else
106 handle_revision_arg(argv[i], &revs, flags, 1);
109 setup_revisions(0, 0, &revs, 0);
110 revs.topo_order = 1;
111 revs.lifo = 1;
112 prepare_revision_walk(&revs);
114 traverse_commit_list(&revs, show_commit, show_object, 0);
116 return 0;
119 static int handle_walk(int argc, const char *argv[])
121 struct commit *commit;
122 struct rev_info revs;
123 struct commit_list *queue, *work, **qp;
124 unsigned char *sha1p, *sha1pt;
125 unsigned long date = 0;
126 unsigned int flags = 0;
127 int retval, slop = 5, i;
129 init_revisions(&revs, 0);
131 for (i = 0; i < argc; i++) {
132 if (!strcmp(argv[i], "--not"))
133 flags ^= UNINTERESTING;
134 else if (!strcmp(argv[i], "--objects"))
135 revs.tree_objects = revs.blob_objects = 1;
136 else
137 handle_revision_arg(argv[i], &revs, flags, 1);
140 work = 0;
141 sha1p = 0;
142 for (i = 0; i < revs.pending.nr; i++) {
143 commit = lookup_commit(revs.pending.objects[i].item->sha1);
145 sha1pt = get_cache_slice(commit);
146 if (!sha1pt)
147 die("%s: not in a cache slice", sha1_to_hex(commit->object.sha1));
149 if (!i)
150 sha1p = sha1pt;
151 else if (sha1p != sha1pt)
152 die("walking porcelain is /per/ cache slice; commits cannot be spread out amoung several");
154 insert_by_date(commit, &work);
157 if (!sha1p)
158 die("nothing to traverse!");
160 queue = 0;
161 qp = &queue;
162 commit = pop_commit(&work);
163 retval = traverse_cache_slice(&revs, sha1p, commit, &date, &slop, &qp, &work);
164 if (retval < 0)
165 return retval;
167 fprintf(stderr, "queue:\n");
168 while ((commit = pop_commit(&queue)) != 0) {
169 printf("%s\n", sha1_to_hex(commit->object.sha1));
172 fprintf(stderr, "work:\n");
173 while ((commit = pop_commit(&work)) != 0) {
174 printf("%s\n", sha1_to_hex(commit->object.sha1));
177 fprintf(stderr, "pending:\n");
178 for (i = 0; i < revs.pending.nr; i++) {
179 struct object *obj = revs.pending.objects[i].item;
180 const char *name = revs.pending.objects[i].name;
182 /* unfortunately, despite our careful generation, object duplication *is* a possibility...
183 * (eg. same object introduced into two different branches) */
184 if (obj->flags & SEEN)
185 continue;
187 printf("%s %s\n", sha1_to_hex(revs.pending.objects[i].item->sha1), name);
188 obj->flags |= SEEN;
191 return 0;
194 static int handle_fuse(int argc, const char *argv[])
196 struct rev_info revs;
197 struct rev_cache_info rci;
198 const char *args[5];
199 int i, argn = 0;
200 char add_all = 0;
202 init_revisions(&revs, 0);
203 init_rev_cache_info(&rci);
204 args[argn++] = "rev-list";
206 for (i = 0; i < argc; i++) {
207 if (!strcmp(argv[i], "--all")) {
208 args[argn++] = "--all";
209 setup_revisions(argn, args, &revs, 0);
210 add_all = 1;
211 } else if (!strcmp(argv[i], "--no-objects"))
212 rci.objects = 0;
213 else if (!strncmp(argv[i], "--ignore-size", 13)) {
214 unsigned long sz;
216 if (argv[i][13] == '=')
217 git_parse_ulong(argv[i] + 14, &sz);
218 else
219 sz = default_ignore_size;
221 rci.ignore_size = sz;
222 } else
223 continue;
226 if (!add_all)
227 starts_from_slices(&revs, 0, 0, 0);
229 return fuse_cache_slices(&rci, &revs);
232 static int handle_index(int argc, const char *argv[])
234 return regenerate_cache_index(0);
237 static int handle_alt(int argc, const char *argv[])
239 if (argc < 1)
240 return -1;
242 return make_cache_slice_pointer(0, argv[0]);
245 static int handle_help(void)
247 char *usage = "\
248 usage:\n\
249 git-rev-cache COMMAND [options] [<commit-id>...]\n\
250 commands:\n\
251 add - add revisions to the cache. reads commit ids from stdin, \n\
252 formatted as: START START ... --not END END ...\n\
253 options:\n\
254 --all use all branch heads as starts\n\
255 --fresh/--incremental exclude everything already in a cache slice\n\
256 --stdin also read commit ids from stdin (same form\n\
257 as cmd)\n\
258 --legs ensure branch is entirely self-contained\n\
259 --no-objects don't add non-commit objects to slice\n\
260 walk - walk a cache slice based on set of commits; formatted as add\n\
261 options:\n\
262 --objects include non-commit objects in traversals\n\
263 fuse - coalesce cache slices into a single cache.\n\
264 options:\n\
265 --all include all objects in repository\n\
266 --no-objects don't add non-commit objects to slice\n\
267 --ignore-size[=N] ignore slices of size >= N; defaults to ~5MB\n\
268 index - regnerate the cache index.";
270 puts(usage);
272 return 0;
275 static int rev_cache_config(const char *k, const char *v, void *cb)
277 /* this could potentially be related to pack.windowmemory, but we want a max around 50mb,
278 * and .windowmemory is often >700mb, with *large* variations */
279 if (!strcmp(k, "revcache.ignoresize")) {
280 int t;
282 t = git_config_ulong(k, v);
283 if (t)
284 default_ignore_size = t;
287 return 0;
290 int cmd_rev_cache(int argc, const char *argv[], const char *prefix)
292 const char *arg;
293 int r;
295 git_config(git_default_config, NULL);
296 git_config(rev_cache_config, NULL);
298 if (argc > 1)
299 arg = argv[1];
300 else
301 arg = "";
303 argc -= 2;
304 argv += 2;
305 if (!strcmp(arg, "add"))
306 r = handle_add(argc, argv);
307 else if (!strcmp(arg, "fuse"))
308 r = handle_fuse(argc, argv);
309 else if (!strcmp(arg, "walk"))
310 r = handle_walk(argc, argv);
311 else if (!strcmp(arg, "index"))
312 r = handle_index(argc, argv);
313 else if (!strcmp(arg, "test"))
314 r = test_rev_list(argc, argv);
315 else if (!strcmp(arg, "alt"))
316 r = handle_alt(argc, argv);
317 else
318 return handle_help();
320 fprintf(stderr, "final return value: %d\n", r);
322 return 0;