Skip to content

Commit 8c878f3

Browse files
committed
Merge branch 'js/scalar-diagnose' into next
Implementation of "scalar diagnose" subcommand. * js/scalar-diagnose: scalar: teach `diagnose` to gather loose objects information scalar: teach `diagnose` to gather packfile info scalar diagnose: include disk space information scalar: implement `scalar diagnose` scalar: validate the optional enlistment argument archive --add-virtual-file: allow paths containing colons archive: optionally add "virtual" files
2 parents 8edd204 + 15d8adc commit 8c878f3

File tree

6 files changed

+435
-22
lines changed

6 files changed

+435
-22
lines changed

Documentation/git-archive.txt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ OPTIONS
5151
--prefix=<prefix>/::
5252
Prepend <prefix>/ to paths in the archive. Can be repeated; its
5353
rightmost value is used for all tracked files. See below which
54-
value gets used by `--add-file`.
54+
value gets used by `--add-file` and `--add-virtual-file`.
5555

5656
-o <file>::
5757
--output=<file>::
@@ -63,6 +63,23 @@ OPTIONS
6363
concatenating the value of the last `--prefix` option (if any)
6464
before this `--add-file` and the basename of <file>.
6565

66+
--add-virtual-file=<path>:<content>::
67+
Add the specified contents to the archive. Can be repeated to add
68+
multiple files. The path of the file in the archive is built
69+
by concatenating the value of the last `--prefix` option (if any)
70+
before this `--add-virtual-file` and `<path>`.
71+
+
72+
The `<path>` argument can start and end with a literal double-quote
73+
character; the contained file name is interpreted as a C-style string,
74+
i.e. the backslash is interpreted as escape character. The path must
75+
be quoted if it contains a colon, to avoid the colon from being
76+
misinterpreted as the separator between the path and the contents, or
77+
if the path begins or ends with a double-quote character.
78+
+
79+
The file mode is limited to a regular file, and the option may be
80+
subject to platform-dependent command-line limits. For non-trivial
81+
cases, write an untracked file and use `--add-file` instead.
82+
6683
--worktree-attributes::
6784
Look for attributes in .gitattributes files in the working tree
6885
as well (see <<ATTRIBUTES>>).

archive.c

Lines changed: 68 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "parse-options.h"
1010
#include "unpack-trees.h"
1111
#include "dir.h"
12+
#include "quote.h"
1213

1314
static char const * const archive_usage[] = {
1415
N_("git archive [<options>] <tree-ish> [<path>...]"),
@@ -263,6 +264,7 @@ static int queue_or_write_archive_entry(const struct object_id *oid,
263264
struct extra_file_info {
264265
char *base;
265266
struct stat stat;
267+
void *content;
266268
};
267269

268270
int write_archive_entries(struct archiver_args *args,
@@ -331,19 +333,27 @@ int write_archive_entries(struct archiver_args *args,
331333

332334
put_be64(fake_oid.hash, i + 1);
333335

334-
strbuf_reset(&path_in_archive);
335-
if (info->base)
336-
strbuf_addstr(&path_in_archive, info->base);
337-
strbuf_addstr(&path_in_archive, basename(path));
338-
339-
strbuf_reset(&content);
340-
if (strbuf_read_file(&content, path, info->stat.st_size) < 0)
341-
err = error_errno(_("cannot read '%s'"), path);
342-
else
343-
err = write_entry(args, &fake_oid, path_in_archive.buf,
344-
path_in_archive.len,
336+
if (!info->content) {
337+
strbuf_reset(&path_in_archive);
338+
if (info->base)
339+
strbuf_addstr(&path_in_archive, info->base);
340+
strbuf_addstr(&path_in_archive, basename(path));
341+
342+
strbuf_reset(&content);
343+
if (strbuf_read_file(&content, path, info->stat.st_size) < 0)
344+
err = error_errno(_("cannot read '%s'"), path);
345+
else
346+
err = write_entry(args, &fake_oid, path_in_archive.buf,
347+
path_in_archive.len,
348+
canon_mode(info->stat.st_mode),
349+
content.buf, content.len);
350+
} else {
351+
err = write_entry(args, &fake_oid,
352+
path, strlen(path),
345353
canon_mode(info->stat.st_mode),
346-
content.buf, content.len);
354+
info->content, info->stat.st_size);
355+
}
356+
347357
if (err)
348358
break;
349359
}
@@ -493,6 +503,7 @@ static void extra_file_info_clear(void *util, const char *str)
493503
{
494504
struct extra_file_info *info = util;
495505
free(info->base);
506+
free(info->content);
496507
free(info);
497508
}
498509

@@ -514,14 +525,49 @@ static int add_file_cb(const struct option *opt, const char *arg, int unset)
514525
if (!arg)
515526
return -1;
516527

517-
path = prefix_filename(args->prefix, arg);
518-
item = string_list_append_nodup(&args->extra_files, path);
519-
item->util = info = xmalloc(sizeof(*info));
528+
info = xmalloc(sizeof(*info));
520529
info->base = xstrdup_or_null(base);
521-
if (stat(path, &info->stat))
522-
die(_("File not found: %s"), path);
523-
if (!S_ISREG(info->stat.st_mode))
524-
die(_("Not a regular file: %s"), path);
530+
531+
if (!strcmp(opt->long_name, "add-file")) {
532+
path = prefix_filename(args->prefix, arg);
533+
if (stat(path, &info->stat))
534+
die(_("File not found: %s"), path);
535+
if (!S_ISREG(info->stat.st_mode))
536+
die(_("Not a regular file: %s"), path);
537+
info->content = NULL; /* read the file later */
538+
} else if (!strcmp(opt->long_name, "add-virtual-file")) {
539+
struct strbuf buf = STRBUF_INIT;
540+
const char *p = arg;
541+
542+
if (*p != '"')
543+
p = strchr(p, ':');
544+
else if (unquote_c_style(&buf, p, &p) < 0)
545+
die(_("unclosed quote: '%s'"), arg);
546+
547+
if (!p || *p != ':')
548+
die(_("missing colon: '%s'"), arg);
549+
550+
if (p == arg)
551+
die(_("empty file name: '%s'"), arg);
552+
553+
path = buf.len ?
554+
strbuf_detach(&buf, NULL) : xstrndup(arg, p - arg);
555+
556+
if (args->prefix) {
557+
char *save = path;
558+
path = prefix_filename(args->prefix, path);
559+
free(save);
560+
}
561+
memset(&info->stat, 0, sizeof(info->stat));
562+
info->stat.st_mode = S_IFREG | 0644;
563+
info->content = xstrdup(p + 1);
564+
info->stat.st_size = strlen(info->content);
565+
} else {
566+
BUG("add_file_cb() called for %s", opt->long_name);
567+
}
568+
item = string_list_append_nodup(&args->extra_files, path);
569+
item->util = info;
570+
525571
return 0;
526572
}
527573

@@ -554,6 +600,9 @@ static int parse_archive_args(int argc, const char **argv,
554600
{ OPTION_CALLBACK, 0, "add-file", args, N_("file"),
555601
N_("add untracked file to archive"), 0, add_file_cb,
556602
(intptr_t)&base },
603+
{ OPTION_CALLBACK, 0, "add-virtual-file", args,
604+
N_("path:content"), N_("add untracked file to archive"), 0,
605+
add_file_cb, (intptr_t)&base },
557606
OPT_STRING('o', "output", &output, N_("file"),
558607
N_("write the archive to this file")),
559608
OPT_BOOL(0, "worktree-attributes", &worktree_attributes,

0 commit comments

Comments
 (0)