@@ -61,6 +61,17 @@ OPTIONS
by concatenating the value for `--prefix` (if any) and the
basename of <file>.
+--add-file-with-content=<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 for `--prefix` (if any) and the
+ basename of <file>.
++
+The `<path>` cannot contain any colon, 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>>).
@@ -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,
@@ -337,7 +338,13 @@ int write_archive_entries(struct archiver_args *args,
strbuf_addstr(&path_in_archive, basename(path));
strbuf_reset(&content);
- if (strbuf_read_file(&content, path, info->stat.st_size) < 0)
+ if (info->content)
+ err = write_entry(args, &fake_oid, path_in_archive.buf,
+ path_in_archive.len,
+ info->stat.st_mode,
+ info->content, info->stat.st_size);
+ else if (strbuf_read_file(&content, path,
+ info->stat.st_size) < 0)
err = error_errno(_("could not read '%s'"), path);
else
err = write_entry(args, &fake_oid, path_in_archive.buf,
@@ -493,6 +500,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 +522,38 @@ 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 {
+ 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);
+ }
+ item = string_list_append_nodup(&args->extra_files, path);
+ item->util = info;
+
return 0;
}
@@ -554,6 +586,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-file-with-content", 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,
@@ -206,6 +206,18 @@ test_expect_success 'git archive --format=zip --add-file' '
check_zip with_untracked
check_added with_untracked untracked untracked
+test_expect_success UNZIP 'git archive --format=zip --add-file-with-content' '
+ git archive --format=zip >with_file_with_content.zip \
+ --add-file-with-content=hello:world $EMPTY_TREE &&
+ test_when_finished "rm -rf tmp-unpack" &&
+ mkdir tmp-unpack && (
+ cd tmp-unpack &&
+ "$GIT_UNZIP" ../with_file_with_content.zip &&
+ test_path_is_file hello &&
+ test world = $(cat hello)
+ )
+'
+
test_expect_success 'git archive --format=zip --add-file twice' '
echo untracked >untracked &&
git archive --format=zip --prefix=one/ --add-file=untracked \