Skip to content

Commit

Permalink
Merge branch 'js/scalar-diagnose'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gitster committed Jun 7, 2022
2 parents 006fd83 + 15d8adc commit 08baf19
Show file tree
Hide file tree
Showing 6 changed files with 435 additions and 22 deletions.
19 changes: 18 additions & 1 deletion Documentation/git-archive.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ OPTIONS
--prefix=<prefix>/::
Prepend <prefix>/ to paths in the archive. Can be repeated; its
rightmost value is used for all tracked files. See below which
value gets used by `--add-file`.
value gets used by `--add-file` and `--add-virtual-file`.

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

--add-virtual-file=<path>:<content>::
Add the specified contents to the archive. Can be repeated to add
multiple files. The path of the file in the archive is built
by concatenating the value of the last `--prefix` option (if any)
before this `--add-virtual-file` and `<path>`.
+
The `<path>` argument can start and end with a literal double-quote
character; the contained file name is interpreted as a C-style string,
i.e. the backslash is interpreted as escape character. The path must
be quoted if it contains a colon, to avoid the colon from being
misinterpreted as the separator between the path and the contents, or
if the path begins or ends with a double-quote character.
+
The file mode is limited to a regular file, and the option may be
subject to platform-dependent command-line limits. For non-trivial
cases, write an untracked file and use `--add-file` instead.

--worktree-attributes::
Look for attributes in .gitattributes files in the working tree
as well (see <<ATTRIBUTES>>).
Expand Down
87 changes: 68 additions & 19 deletions archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "parse-options.h"
#include "unpack-trees.h"
#include "dir.h"
#include "quote.h"

static char const * const archive_usage[] = {
N_("git archive [<options>] <tree-ish> [<path>...]"),
Expand Down Expand Up @@ -263,6 +264,7 @@ static int queue_or_write_archive_entry(const struct object_id *oid,
struct extra_file_info {
char *base;
struct stat stat;
void *content;
};

int write_archive_entries(struct archiver_args *args,
Expand Down Expand Up @@ -331,19 +333,27 @@ int write_archive_entries(struct archiver_args *args,

put_be64(fake_oid.hash, i + 1);

strbuf_reset(&path_in_archive);
if (info->base)
strbuf_addstr(&path_in_archive, info->base);
strbuf_addstr(&path_in_archive, basename(path));

strbuf_reset(&content);
if (strbuf_read_file(&content, path, info->stat.st_size) < 0)
err = error_errno(_("cannot read '%s'"), path);
else
err = write_entry(args, &fake_oid, path_in_archive.buf,
path_in_archive.len,
if (!info->content) {
strbuf_reset(&path_in_archive);
if (info->base)
strbuf_addstr(&path_in_archive, info->base);
strbuf_addstr(&path_in_archive, basename(path));

strbuf_reset(&content);
if (strbuf_read_file(&content, path, info->stat.st_size) < 0)
err = error_errno(_("cannot read '%s'"), path);
else
err = write_entry(args, &fake_oid, path_in_archive.buf,
path_in_archive.len,
canon_mode(info->stat.st_mode),
content.buf, content.len);
} else {
err = write_entry(args, &fake_oid,
path, strlen(path),
canon_mode(info->stat.st_mode),
content.buf, content.len);
info->content, info->stat.st_size);
}

if (err)
break;
}
Expand Down Expand Up @@ -493,6 +503,7 @@ static void extra_file_info_clear(void *util, const char *str)
{
struct extra_file_info *info = util;
free(info->base);
free(info->content);
free(info);
}

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

path = prefix_filename(args->prefix, arg);
item = string_list_append_nodup(&args->extra_files, path);
item->util = info = xmalloc(sizeof(*info));
info = xmalloc(sizeof(*info));
info->base = xstrdup_or_null(base);
if (stat(path, &info->stat))
die(_("File not found: %s"), path);
if (!S_ISREG(info->stat.st_mode))
die(_("Not a regular file: %s"), path);

if (!strcmp(opt->long_name, "add-file")) {
path = prefix_filename(args->prefix, arg);
if (stat(path, &info->stat))
die(_("File not found: %s"), path);
if (!S_ISREG(info->stat.st_mode))
die(_("Not a regular file: %s"), path);
info->content = NULL; /* read the file later */
} else if (!strcmp(opt->long_name, "add-virtual-file")) {
struct strbuf buf = STRBUF_INIT;
const char *p = arg;

if (*p != '"')
p = strchr(p, ':');
else if (unquote_c_style(&buf, p, &p) < 0)
die(_("unclosed quote: '%s'"), arg);

if (!p || *p != ':')
die(_("missing colon: '%s'"), arg);

if (p == arg)
die(_("empty file name: '%s'"), arg);

path = buf.len ?
strbuf_detach(&buf, NULL) : xstrndup(arg, p - arg);

if (args->prefix) {
char *save = path;
path = prefix_filename(args->prefix, path);
free(save);
}
memset(&info->stat, 0, sizeof(info->stat));
info->stat.st_mode = S_IFREG | 0644;
info->content = xstrdup(p + 1);
info->stat.st_size = strlen(info->content);
} else {
BUG("add_file_cb() called for %s", opt->long_name);
}
item = string_list_append_nodup(&args->extra_files, path);
item->util = info;

return 0;
}

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

0 comments on commit 08baf19

Please sign in to comment.