Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schindelin <johannes.schindelin@gmx.de>2022-05-29 02:11:12 +0300
committerJunio C Hamano <gitster@pobox.com>2022-05-31 09:07:22 +0300
commit237a1d138c4322a7e934f129dee02e2ea6a214cd (patch)
tree72146e883c5056136fdf0aabddd1160f9cf55747 /archive.c
parent23f2356fd902434a9b8e9e4cdae735f399c16ff0 (diff)
archive: optionally add "virtual" files
With the `--add-virtual-file=<path>:<content>` option, `git archive` now supports use cases where relatively trivial files need to be added that do not exist on disk. This will allow us to generate `.zip` files with generated content, without having to add said content to the object database and without having to write it out to disk. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> [jc: tweaked <path> handling] Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'archive.c')
-rw-r--r--archive.c77
1 files changed, 58 insertions, 19 deletions
diff --git a/archive.c b/archive.c
index e2121ebefb..29a90c7032 100644
--- a/archive.c
+++ b/archive.c
@@ -263,6 +263,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,
@@ -331,19 +332,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;
}
@@ -493,6 +502,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);
}
@@ -514,14 +524,40 @@ 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")) {
+ const char *colon = strchr(arg, ':');
+ char *p;
+
+ if (!colon)
+ die(_("missing colon: '%s'"), arg);
+
+ p = xstrndup(arg, colon - arg);
+ if (!args->prefix)
+ path = p;
+ else {
+ path = prefix_filename(args->prefix, p);
+ free(p);
+ }
+ memset(&info->stat, 0, sizeof(info->stat));
+ info->stat.st_mode = S_IFREG | 0644;
+ info->content = xstrdup(colon + 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;
}
@@ -554,6 +590,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,