Skip to content

Commit 26fe16f

Browse files
committed
Merge branch 'cw/remote-object-info' into seen
A client component to talk with the object-info endpoint. * cw/remote-object-info: SQUASH??? coccicheck SQUASH??? ensure that coccicheck is happy SQUASH??? compilation fix cat-file: add --batch-command remote-object-info command cat-file: move parse_cmd and DEFAULT_FORMAT up transport: add object-info fallback to fetch transport: add client side capability to request object-info object-info: send attribute packet regardless of object ids object-store: add function to free object_info contents fetch-pack: move fetch default settings fetch-pack: refactor packet writing
2 parents 806363c + b88d83f commit 26fe16f

File tree

11 files changed

+724
-79
lines changed

11 files changed

+724
-79
lines changed

Documentation/git-cat-file.txt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ info <object>::
115115
Print object info for object reference `<object>`. This corresponds to the
116116
output of `--batch-check`.
117117

118+
remote-object-info <remote> [<object>]::
119+
Print object info for object references `<object>` at specified <remote>.
120+
This command may only be combined with `--buffer`.
121+
118122
flush::
119123
Used with `--buffer` to execute all preceding commands that were issued
120124
since the beginning or since the last flush was issued. When `--buffer`
@@ -245,21 +249,23 @@ newline. The available atoms are:
245249
The full hex representation of the object name.
246250

247251
`objecttype`::
248-
The type of the object (the same as `cat-file -t` reports).
252+
The type of the object (the same as `cat-file -t` reports). See
253+
`CAVEATS` below.
249254

250255
`objectsize`::
251256
The size, in bytes, of the object (the same as `cat-file -s`
252257
reports).
253258

254259
`objectsize:disk`::
255260
The size, in bytes, that the object takes up on disk. See the
256-
note about on-disk sizes in the `CAVEATS` section below.
261+
note about on-disk sizes in the `CAVEATS` section below. Not
262+
supported by `remote-object-info`.
257263

258264
`deltabase`::
259265
If the object is stored as a delta on-disk, this expands to the
260266
full hex representation of the delta base object name.
261267
Otherwise, expands to the null OID (all zeroes). See `CAVEATS`
262-
below.
268+
below. Not supported by `remote-object-info`.
263269

264270
`rest`::
265271
If this atom is used in the output string, input lines are split
@@ -346,6 +352,10 @@ directory name.
346352
CAVEATS
347353
-------
348354

355+
Note that since object type is currently not supported by the
356+
object-info command request, git fetches the entire object instead to
357+
get the object info.
358+
349359
Note that the sizes of objects on disk are reported accurately, but care
350360
should be taken in drawing conclusions about which refs or objects are
351361
responsible for disk usage. The size of a packed non-delta object may be

builtin/cat-file.c

Lines changed: 174 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#include "packfile.h"
1717
#include "object-store.h"
1818
#include "promisor-remote.h"
19+
#include "alias.h"
20+
#include "remote.h"
21+
#include "transport.h"
1922

2023
enum batch_mode {
2124
BATCH_MODE_CONTENTS,
@@ -32,9 +35,14 @@ struct batch_options {
3235
int unordered;
3336
int transform_mode; /* may be 'w' or 'c' for --filters or --textconv */
3437
const char *format;
38+
int use_remote_info;
3539
};
3640

41+
#define DEFAULT_FORMAT "%(objectname) %(objecttype) %(objectsize)"
42+
3743
static const char *force_path;
44+
static struct object_info *remote_object_info;
45+
static struct oid_array object_info_oids = OID_ARRAY_INIT;
3846

3947
static int filter_object(const char *path, unsigned mode,
4048
const struct object_id *oid,
@@ -423,48 +431,115 @@ static void batch_one_object(const char *obj_name,
423431
int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
424432
enum get_oid_result result;
425433

426-
result = get_oid_with_context(the_repository, obj_name,
427-
flags, &data->oid, &ctx);
428-
if (result != FOUND) {
429-
switch (result) {
430-
case MISSING_OBJECT:
431-
printf("%s missing\n", obj_name);
432-
break;
433-
case SHORT_NAME_AMBIGUOUS:
434-
printf("%s ambiguous\n", obj_name);
435-
break;
436-
case DANGLING_SYMLINK:
437-
printf("dangling %"PRIuMAX"\n%s\n",
438-
(uintmax_t)strlen(obj_name), obj_name);
439-
break;
440-
case SYMLINK_LOOP:
441-
printf("loop %"PRIuMAX"\n%s\n",
442-
(uintmax_t)strlen(obj_name), obj_name);
443-
break;
444-
case NOT_DIR:
445-
printf("notdir %"PRIuMAX"\n%s\n",
446-
(uintmax_t)strlen(obj_name), obj_name);
447-
break;
448-
default:
449-
BUG("unknown get_sha1_with_context result %d\n",
450-
result);
451-
break;
434+
if (!opt->use_remote_info) {
435+
result = get_oid_with_context(the_repository, obj_name,
436+
flags, &data->oid, &ctx);
437+
if (result != FOUND) {
438+
switch (result) {
439+
case MISSING_OBJECT:
440+
printf("%s missing\n", obj_name);
441+
break;
442+
case SHORT_NAME_AMBIGUOUS:
443+
printf("%s ambiguous\n", obj_name);
444+
break;
445+
case DANGLING_SYMLINK:
446+
printf("dangling %"PRIuMAX"\n%s\n",
447+
(uintmax_t)strlen(obj_name), obj_name);
448+
break;
449+
case SYMLINK_LOOP:
450+
printf("loop %"PRIuMAX"\n%s\n",
451+
(uintmax_t)strlen(obj_name), obj_name);
452+
break;
453+
case NOT_DIR:
454+
printf("notdir %"PRIuMAX"\n%s\n",
455+
(uintmax_t)strlen(obj_name), obj_name);
456+
break;
457+
default:
458+
BUG("unknown get_sha1_with_context result %d\n",
459+
result);
460+
break;
461+
}
462+
fflush(stdout);
463+
return;
452464
}
453-
fflush(stdout);
454-
return;
455-
}
456465

457-
if (ctx.mode == 0) {
458-
printf("symlink %"PRIuMAX"\n%s\n",
459-
(uintmax_t)ctx.symlink_path.len,
460-
ctx.symlink_path.buf);
461-
fflush(stdout);
462-
return;
466+
if (ctx.mode == 0) {
467+
printf("symlink %"PRIuMAX"\n%s\n",
468+
(uintmax_t)ctx.symlink_path.len,
469+
ctx.symlink_path.buf);
470+
fflush(stdout);
471+
return;
472+
}
463473
}
464474

465475
batch_object_write(obj_name, scratch, opt, data, NULL, 0);
466476
}
467477

478+
static int get_remote_info(struct batch_options *opt, int argc, const char **argv)
479+
{
480+
int retval = 0;
481+
size_t i;
482+
struct remote *remote = NULL;
483+
struct object_id oid;
484+
struct string_list object_info_options = STRING_LIST_INIT_NODUP;
485+
static struct transport *gtransport;
486+
char *format = DEFAULT_FORMAT;
487+
488+
if (opt->format)
489+
format = xstrdup(opt->format);
490+
491+
remote = remote_get(argv[0]);
492+
if (!remote)
493+
die(_("must supply valid remote when using --object-info"));
494+
oid_array_clear(&object_info_oids);
495+
for (i = 1; i < argc; i++) {
496+
if (get_oid(argv[i], &oid))
497+
die(_("malformed object id '%s'"), argv[i]);
498+
oid_array_append(&object_info_oids, &oid);
499+
}
500+
501+
gtransport = transport_get(remote, NULL);
502+
if (gtransport->smart_options) {
503+
size_t j;
504+
int include_size = 0, include_type = 0;
505+
506+
CALLOC_ARRAY(remote_object_info, object_info_oids.nr);
507+
gtransport->smart_options->object_info = 1;
508+
gtransport->smart_options->object_info_oids = &object_info_oids;
509+
/**
510+
* 'size' is the only option currently supported.
511+
* Other options that are passed in the format will default to a
512+
* standard fetch request rather than object-info.
513+
*/
514+
if (strstr(format, "%(objectsize)")) {
515+
string_list_append(&object_info_options, "size");
516+
include_size = 1;
517+
}
518+
if (strstr(format, "%(objecttype)")) {
519+
string_list_append(&object_info_options, "type");
520+
include_type = 1;
521+
}
522+
if (strstr(format, "%(objectsize:disk)"))
523+
die(_("objectsize:disk is currently not supported with remote-object-info"));
524+
if (strstr(format, "%(deltabase)"))
525+
die(_("deltabase is currently not supported with remote-object-info"));
526+
if (object_info_options.nr > 0) {
527+
gtransport->smart_options->object_info_options = &object_info_options;
528+
for (j = 0; j < object_info_oids.nr; j++) {
529+
if (include_size)
530+
remote_object_info[j].sizep = xcalloc(1, sizeof(long));
531+
if (include_type)
532+
remote_object_info[j].typep = xcalloc(1, sizeof(enum object_type));
533+
}
534+
gtransport->smart_options->object_info_data = &remote_object_info;
535+
retval = transport_fetch_refs(gtransport, NULL);
536+
}
537+
} else {
538+
retval = -1;
539+
}
540+
return retval;
541+
}
542+
468543
struct object_cb_data {
469544
struct batch_options *opt;
470545
struct expand_data *expand;
@@ -536,6 +611,7 @@ typedef void (*parse_cmd_fn_t)(struct batch_options *, const char *,
536611
struct queued_cmd {
537612
parse_cmd_fn_t fn;
538613
char *line;
614+
const char *name;
539615
};
540616

541617
static void parse_cmd_contents(struct batch_options *opt,
@@ -556,6 +632,56 @@ static void parse_cmd_info(struct batch_options *opt,
556632
batch_one_object(line, output, opt, data);
557633
}
558634

635+
static const struct parse_cmd {
636+
const char *name;
637+
parse_cmd_fn_t fn;
638+
unsigned takes_args;
639+
} commands[] = {
640+
{ "contents", parse_cmd_contents, 1},
641+
{ "info", parse_cmd_info, 1},
642+
{ "remote-object-info", parse_cmd_info, 1},
643+
{ "flush", NULL, 0},
644+
};
645+
646+
static void parse_remote_info(struct batch_options *opt,
647+
char *line,
648+
struct strbuf *output,
649+
struct expand_data *data,
650+
const struct parse_cmd *p_cmd,
651+
struct queued_cmd *q_cmd)
652+
{
653+
int count;
654+
size_t i;
655+
const char **argv;
656+
657+
count = split_cmdline(line, &argv);
658+
if (get_remote_info(opt, count, argv))
659+
goto cleanup;
660+
opt->use_remote_info = 1;
661+
data->skip_object_info = 1;
662+
data->mark_query = 0;
663+
for (i = 0; i < object_info_oids.nr; i++) {
664+
if (remote_object_info[i].sizep)
665+
data->size = *remote_object_info[i].sizep;
666+
if (remote_object_info[i].typep)
667+
data->type = *remote_object_info[i].typep;
668+
669+
data->oid = object_info_oids.oid[i];
670+
if (p_cmd)
671+
p_cmd->fn(opt, argv[i+1], output, data);
672+
else
673+
q_cmd->fn(opt, argv[i+1], output, data);
674+
}
675+
opt->use_remote_info = 0;
676+
data->skip_object_info = 0;
677+
data->mark_query = 1;
678+
679+
cleanup:
680+
for (i = 0; i < object_info_oids.nr; i++)
681+
free_object_info_contents(&remote_object_info[i]);
682+
free(remote_object_info);
683+
}
684+
559685
static void dispatch_calls(struct batch_options *opt,
560686
struct strbuf *output,
561687
struct expand_data *data,
@@ -567,8 +693,12 @@ static void dispatch_calls(struct batch_options *opt,
567693
if (!opt->buffer_output)
568694
die(_("flush is only for --buffer mode"));
569695

570-
for (i = 0; i < nr; i++)
571-
cmd[i].fn(opt, cmd[i].line, output, data);
696+
for (i = 0; i < nr; i++) {
697+
if (!strcmp(cmd[i].name, "remote-object-info"))
698+
parse_remote_info(opt, cmd[i].line, output, data, NULL, &cmd[i]);
699+
else
700+
cmd[i].fn(opt, cmd[i].line, output, data);
701+
}
572702

573703
fflush(stdout);
574704
}
@@ -583,17 +713,6 @@ static void free_cmds(struct queued_cmd *cmd, size_t *nr)
583713
*nr = 0;
584714
}
585715

586-
587-
static const struct parse_cmd {
588-
const char *name;
589-
parse_cmd_fn_t fn;
590-
unsigned takes_args;
591-
} commands[] = {
592-
{ "contents", parse_cmd_contents, 1},
593-
{ "info", parse_cmd_info, 1},
594-
{ "flush", NULL, 0},
595-
};
596-
597716
static void batch_objects_command(struct batch_options *opt,
598717
struct strbuf *output,
599718
struct expand_data *data)
@@ -639,11 +758,17 @@ static void batch_objects_command(struct batch_options *opt,
639758
dispatch_calls(opt, output, data, queued_cmd, nr);
640759
free_cmds(queued_cmd, &nr);
641760
} else if (!opt->buffer_output) {
642-
cmd->fn(opt, p, output, data);
761+
if (!strcmp(cmd->name, "remote-object-info")) {
762+
char *line = xstrdup_or_null(p);
763+
parse_remote_info(opt, line, output, data, cmd, NULL);
764+
} else {
765+
cmd->fn(opt, p, output, data);
766+
}
643767
} else {
644768
ALLOC_GROW(queued_cmd, nr + 1, alloc);
645769
call.fn = cmd->fn;
646770
call.line = xstrdup_or_null(p);
771+
call.name = cmd->name;
647772
queued_cmd[nr++] = call;
648773
}
649774
}
@@ -659,8 +784,6 @@ static void batch_objects_command(struct batch_options *opt,
659784
strbuf_release(&input);
660785
}
661786

662-
#define DEFAULT_FORMAT "%(objectname) %(objecttype) %(objectsize)"
663-
664787
static int batch_objects(struct batch_options *opt)
665788
{
666789
struct strbuf input = STRBUF_INIT;

0 commit comments

Comments
 (0)