]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'jc/cat-file-batch-default-format-optim'
authorJunio C Hamano <gitster@pobox.com>
Wed, 23 Mar 2022 21:09:31 +0000 (14:09 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 23 Mar 2022 21:09:31 +0000 (14:09 -0700)
Optimize away strbuf_expand() call with a hardcoded formatting logic
specific for the default format in the --batch and --batch-check
options of "git cat-file".

* jc/cat-file-batch-default-format-optim:
  cat-file: skip expanding default format

1  2 
builtin/cat-file.c

index 0663661c0b051135bc6944f7aea903ac0c31a07b,650920eba136123e113640439666be104dec3dd7..50cf38999d10125428e4c558383582af4f191b95
@@@ -391,11 -389,17 +398,17 @@@ static void batch_object_write(const ch
        }
  
        strbuf_reset(scratch);
-       strbuf_expand(scratch, opt->format, expand_format, data);
-       strbuf_addch(scratch, '\n');
+       if (!opt->format) {
+               print_default_format(scratch, data);
+       } else {
+               strbuf_expand(scratch, opt->format, expand_format, data);
+               strbuf_addch(scratch, '\n');
+       }
        batch_write(opt, scratch->buf, scratch->len);
  
 -      if (opt->print_contents) {
 +      if (opt->batch_mode == BATCH_MODE_CONTENTS) {
                print_object_or_die(opt, data);
                batch_write(opt, "\n", 1);
        }
@@@ -517,135 -521,8 +530,137 @@@ static int batch_unordered_packed(cons
                                      data);
  }
  
 +typedef void (*parse_cmd_fn_t)(struct batch_options *, const char *,
 +                             struct strbuf *, struct expand_data *);
 +
 +struct queued_cmd {
 +      parse_cmd_fn_t fn;
 +      char *line;
 +};
 +
 +static void parse_cmd_contents(struct batch_options *opt,
 +                           const char *line,
 +                           struct strbuf *output,
 +                           struct expand_data *data)
 +{
 +      opt->batch_mode = BATCH_MODE_CONTENTS;
 +      batch_one_object(line, output, opt, data);
 +}
 +
 +static void parse_cmd_info(struct batch_options *opt,
 +                         const char *line,
 +                         struct strbuf *output,
 +                         struct expand_data *data)
 +{
 +      opt->batch_mode = BATCH_MODE_INFO;
 +      batch_one_object(line, output, opt, data);
 +}
 +
 +static void dispatch_calls(struct batch_options *opt,
 +              struct strbuf *output,
 +              struct expand_data *data,
 +              struct queued_cmd *cmd,
 +              int nr)
 +{
 +      int i;
 +
 +      if (!opt->buffer_output)
 +              die(_("flush is only for --buffer mode"));
 +
 +      for (i = 0; i < nr; i++)
 +              cmd[i].fn(opt, cmd[i].line, output, data);
 +
 +      fflush(stdout);
 +}
 +
 +static void free_cmds(struct queued_cmd *cmd, size_t *nr)
 +{
 +      size_t i;
 +
 +      for (i = 0; i < *nr; i++)
 +              FREE_AND_NULL(cmd[i].line);
 +
 +      *nr = 0;
 +}
 +
 +
 +static const struct parse_cmd {
 +      const char *name;
 +      parse_cmd_fn_t fn;
 +      unsigned takes_args;
 +} commands[] = {
 +      { "contents", parse_cmd_contents, 1},
 +      { "info", parse_cmd_info, 1},
 +      { "flush", NULL, 0},
 +};
 +
 +static void batch_objects_command(struct batch_options *opt,
 +                                  struct strbuf *output,
 +                                  struct expand_data *data)
 +{
 +      struct strbuf input = STRBUF_INIT;
 +      struct queued_cmd *queued_cmd = NULL;
 +      size_t alloc = 0, nr = 0;
 +
 +      while (!strbuf_getline(&input, stdin)) {
 +              int i;
 +              const struct parse_cmd *cmd = NULL;
 +              const char *p = NULL, *cmd_end;
 +              struct queued_cmd call = {0};
 +
 +              if (!input.len)
 +                      die(_("empty command in input"));
 +              if (isspace(*input.buf))
 +                      die(_("whitespace before command: '%s'"), input.buf);
 +
 +              for (i = 0; i < ARRAY_SIZE(commands); i++) {
 +                      if (!skip_prefix(input.buf, commands[i].name, &cmd_end))
 +                              continue;
 +
 +                      cmd = &commands[i];
 +                      if (cmd->takes_args) {
 +                              if (*cmd_end != ' ')
 +                                      die(_("%s requires arguments"),
 +                                          commands[i].name);
 +
 +                              p = cmd_end + 1;
 +                      } else if (*cmd_end) {
 +                              die(_("%s takes no arguments"),
 +                                  commands[i].name);
 +                      }
 +
 +                      break;
 +              }
 +
 +              if (!cmd)
 +                      die(_("unknown command: '%s'"), input.buf);
 +
 +              if (!strcmp(cmd->name, "flush")) {
 +                      dispatch_calls(opt, output, data, queued_cmd, nr);
 +                      free_cmds(queued_cmd, &nr);
 +              } else if (!opt->buffer_output) {
 +                      cmd->fn(opt, p, output, data);
 +              } else {
 +                      ALLOC_GROW(queued_cmd, nr + 1, alloc);
 +                      call.fn = cmd->fn;
 +                      call.line = xstrdup_or_null(p);
 +                      queued_cmd[nr++] = call;
 +              }
 +      }
 +
 +      if (opt->buffer_output &&
 +          nr &&
 +          !git_env_bool("GIT_TEST_CAT_FILE_NO_FLUSH_ON_EXIT", 0)) {
 +              dispatch_calls(opt, output, data, queued_cmd, nr);
 +              free_cmds(queued_cmd, &nr);
 +      }
 +
 +      free(queued_cmd);
 +      strbuf_release(&input);
 +}
 +
+ #define DEFAULT_FORMAT "%(objectname) %(objecttype) %(objectsize)"
  static int batch_objects(struct batch_options *opt)
  {
        struct strbuf input = STRBUF_INIT;
         */
        memset(&data, 0, sizeof(data));
        data.mark_query = 1;
-       strbuf_expand(&output, opt->format, expand_format, &data);
+       strbuf_expand(&output,
+                     opt->format ? opt->format : DEFAULT_FORMAT,
+                     expand_format,
+                     &data);
        data.mark_query = 0;
        strbuf_release(&output);
 -      if (opt->cmdmode)
 +      if (opt->transform_mode)
                data.split_on_whitespace = 1;
  
+       if (opt->format && !strcmp(opt->format, DEFAULT_FORMAT))
+               opt->format = NULL;
        /*
         * If we are printing out the object, then always fill in the type,
         * since we will want to decide whether or not to stream.