Merge branch 'nd/archive-attribute'
* nd/archive-attribute: archive test: attributes archive: do not read .gitattributes in working directory unpack-trees: do not muck with attributes when we are not checking out attr: add GIT_ATTR_INDEX "direction" archive tests: do not use .gitattributes in working directory
This commit is contained in:
commit
5758b25da4
@ -10,7 +10,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
|
||||
[--output=<file>]
|
||||
[--output=<file>] [--worktree-attributes]
|
||||
[--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
|
||||
[path...]
|
||||
|
||||
@ -51,6 +51,9 @@ OPTIONS
|
||||
--output=<file>::
|
||||
Write the archive to <file> instead of stdout.
|
||||
|
||||
--worktree-attributes::
|
||||
Look for attributes in .gitattributes in working directory too.
|
||||
|
||||
<extra>::
|
||||
This can be any options that the archiver backend understands.
|
||||
See next section.
|
||||
|
23
archive.c
23
archive.c
@ -4,6 +4,7 @@
|
||||
#include "attr.h"
|
||||
#include "archive.h"
|
||||
#include "parse-options.h"
|
||||
#include "unpack-trees.h"
|
||||
|
||||
static char const * const archive_usage[] = {
|
||||
"git archive [options] <tree-ish> [path...]",
|
||||
@ -150,6 +151,8 @@ int write_archive_entries(struct archiver_args *args,
|
||||
write_archive_entry_fn_t write_entry)
|
||||
{
|
||||
struct archiver_context context;
|
||||
struct unpack_trees_options opts;
|
||||
struct tree_desc t;
|
||||
int err;
|
||||
|
||||
if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
|
||||
@ -168,6 +171,22 @@ int write_archive_entries(struct archiver_args *args,
|
||||
context.args = args;
|
||||
context.write_entry = write_entry;
|
||||
|
||||
/*
|
||||
* Setup index and instruct attr to read index only
|
||||
*/
|
||||
if (!args->worktree_attributes) {
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.index_only = 1;
|
||||
opts.head_idx = -1;
|
||||
opts.src_index = &the_index;
|
||||
opts.dst_index = &the_index;
|
||||
opts.fn = oneway_merge;
|
||||
init_tree_desc(&t, args->tree->buffer, args->tree->size);
|
||||
if (unpack_trees(1, &t, &opts))
|
||||
return -1;
|
||||
git_attr_set_direction(GIT_ATTR_INDEX, &the_index);
|
||||
}
|
||||
|
||||
err = read_tree_recursive(args->tree, args->base, args->baselen, 0,
|
||||
args->pathspec, write_archive_entry, &context);
|
||||
if (err == READ_TREE_RECURSIVE)
|
||||
@ -258,6 +277,7 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
int verbose = 0;
|
||||
int i;
|
||||
int list = 0;
|
||||
int worktree_attributes = 0;
|
||||
struct option opts[] = {
|
||||
OPT_GROUP(""),
|
||||
OPT_STRING(0, "format", &format, "fmt", "archive format"),
|
||||
@ -265,6 +285,8 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
"prepend prefix to each pathname in the archive"),
|
||||
OPT_STRING(0, "output", &output, "file",
|
||||
"write the archive to this file"),
|
||||
OPT_BOOLEAN(0, "worktree-attributes", &worktree_attributes,
|
||||
"read .gitattributes in working directory"),
|
||||
OPT__VERBOSE(&verbose),
|
||||
OPT__COMPR('0', &compression_level, "store only", 0),
|
||||
OPT__COMPR('1', &compression_level, "compress faster", 1),
|
||||
@ -324,6 +346,7 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
args->verbose = verbose;
|
||||
args->base = base;
|
||||
args->baselen = strlen(base);
|
||||
args->worktree_attributes = worktree_attributes;
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ struct archiver_args {
|
||||
time_t time;
|
||||
const char **pathspec;
|
||||
unsigned int verbose : 1;
|
||||
unsigned int worktree_attributes : 1;
|
||||
int compression_level;
|
||||
};
|
||||
|
||||
|
12
attr.c
12
attr.c
@ -405,7 +405,7 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
if (!res)
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
}
|
||||
else {
|
||||
else if (direction == GIT_ATTR_CHECKIN) {
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
if (!res)
|
||||
/*
|
||||
@ -415,6 +415,8 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
*/
|
||||
res = read_attr_from_index(path, macro_ok);
|
||||
}
|
||||
else
|
||||
res = read_attr_from_index(path, macro_ok);
|
||||
if (!res)
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
return res;
|
||||
@ -466,7 +468,7 @@ static void bootstrap_attr_stack(void)
|
||||
elem->prev = attr_stack;
|
||||
attr_stack = elem;
|
||||
|
||||
if (!is_bare_repository()) {
|
||||
if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
|
||||
elem = read_attr(GITATTRIBUTES_FILE, 1);
|
||||
elem->origin = strdup("");
|
||||
elem->prev = attr_stack;
|
||||
@ -533,7 +535,7 @@ static void prepare_attr_stack(const char *path, int dirlen)
|
||||
/*
|
||||
* Read from parent directories and push them down
|
||||
*/
|
||||
if (!is_bare_repository()) {
|
||||
if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
|
||||
while (1) {
|
||||
char *cp;
|
||||
|
||||
@ -674,6 +676,10 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
|
||||
void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
|
||||
{
|
||||
enum git_attr_direction old = direction;
|
||||
|
||||
if (is_bare_repository() && new != GIT_ATTR_INDEX)
|
||||
die("BUG: non-INDEX attr direction in a bare repo");
|
||||
|
||||
direction = new;
|
||||
if (new != old)
|
||||
drop_attr_stack();
|
||||
|
3
attr.h
3
attr.h
@ -33,7 +33,8 @@ int git_checkattr(const char *path, int, struct git_attr_check *);
|
||||
|
||||
enum git_attr_direction {
|
||||
GIT_ATTR_CHECKIN,
|
||||
GIT_ATTR_CHECKOUT
|
||||
GIT_ATTR_CHECKOUT,
|
||||
GIT_ATTR_INDEX,
|
||||
};
|
||||
void git_attr_set_direction(enum git_attr_direction, struct index_state *);
|
||||
|
||||
|
@ -24,7 +24,7 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)
|
||||
* git archive --format-tar --prefix=basedir tree-ish
|
||||
*/
|
||||
int i;
|
||||
const char **nargv = xcalloc(sizeof(*nargv), argc + 2);
|
||||
const char **nargv = xcalloc(sizeof(*nargv), argc + 3);
|
||||
char *basedir_arg;
|
||||
int nargc = 0;
|
||||
|
||||
@ -36,6 +36,13 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Because it's just a compatibility wrapper, tar-tree supports only
|
||||
* the old behaviour of reading attributes from the work tree.
|
||||
*/
|
||||
nargv[nargc++] = "--worktree-attributes";
|
||||
|
||||
switch (argc) {
|
||||
default:
|
||||
usage(tar_tree_usage);
|
||||
|
@ -50,7 +50,7 @@ test_expect_success \
|
||||
test_expect_success \
|
||||
'add ignored file' \
|
||||
'echo ignore me >a/ignored &&
|
||||
echo ignored export-ignore >.gitattributes'
|
||||
echo ignored export-ignore >.git/info/attributes'
|
||||
|
||||
test_expect_success \
|
||||
'add files to repository' \
|
||||
@ -64,7 +64,7 @@ test_expect_success \
|
||||
test_expect_success \
|
||||
'create bare clone' \
|
||||
'git clone --bare . bare.git &&
|
||||
cp .gitattributes bare.git/info/attributes'
|
||||
cp .git/info/attributes bare.git/info/attributes'
|
||||
|
||||
test_expect_success \
|
||||
'remove ignored file' \
|
||||
@ -139,10 +139,11 @@ test_expect_success \
|
||||
|
||||
test_expect_success \
|
||||
'create archives with substfiles' \
|
||||
'echo "substfile?" export-subst >a/.gitattributes &&
|
||||
'cp .git/info/attributes .git/info/attributes.before &&
|
||||
echo "substfile?" export-subst >>.git/info/attributes &&
|
||||
git archive HEAD >f.tar &&
|
||||
git archive --prefix=prefix/ HEAD >g.tar &&
|
||||
rm a/.gitattributes'
|
||||
mv .git/info/attributes.before .git/info/attributes'
|
||||
|
||||
test_expect_success \
|
||||
'extract substfiles' \
|
||||
|
91
t/t5001-archive-attr.sh
Executable file
91
t/t5001-archive-attr.sh
Executable file
@ -0,0 +1,91 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='git archive attribute tests'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
SUBSTFORMAT=%H%n
|
||||
|
||||
test_expect_exists() {
|
||||
test_expect_success " $1 exists" "test -e $1"
|
||||
}
|
||||
|
||||
test_expect_missing() {
|
||||
test_expect_success " $1 does not exist" "test ! -e $1"
|
||||
}
|
||||
|
||||
test_expect_success 'setup' '
|
||||
echo ignored >ignored &&
|
||||
echo ignored export-ignore >>.git/info/attributes &&
|
||||
git add ignored &&
|
||||
|
||||
echo ignored by tree >ignored-by-tree &&
|
||||
echo ignored-by-tree export-ignore >.gitattributes &&
|
||||
git add ignored-by-tree .gitattributes &&
|
||||
|
||||
echo ignored by worktree >ignored-by-worktree &&
|
||||
echo ignored-by-worktree export-ignore >.gitattributes &&
|
||||
git add ignored-by-worktree &&
|
||||
|
||||
printf "A\$Format:%s\$O" "$SUBSTFORMAT" >nosubstfile &&
|
||||
printf "A\$Format:%s\$O" "$SUBSTFORMAT" >substfile1 &&
|
||||
printf "A not substituted O" >substfile2 &&
|
||||
echo "substfile?" export-subst >>.git/info/attributes &&
|
||||
git add nosubstfile substfile1 substfile2 &&
|
||||
|
||||
git commit -m. &&
|
||||
|
||||
git clone --bare . bare &&
|
||||
cp .git/info/attributes bare/info/attributes
|
||||
'
|
||||
|
||||
test_expect_success 'git archive' '
|
||||
git archive HEAD >archive.tar &&
|
||||
(mkdir archive && cd archive && "$TAR" xf -) <archive.tar
|
||||
'
|
||||
|
||||
test_expect_missing archive/ignored
|
||||
test_expect_missing archive/ignored-by-tree
|
||||
test_expect_exists archive/ignored-by-worktree
|
||||
|
||||
test_expect_success 'git archive with worktree attributes' '
|
||||
git archive --worktree-attributes HEAD >worktree.tar &&
|
||||
(mkdir worktree && cd worktree && "$TAR" xf -) <worktree.tar
|
||||
'
|
||||
|
||||
test_expect_missing worktree/ignored
|
||||
test_expect_exists worktree/ignored-by-tree
|
||||
test_expect_missing worktree/ignored-by-worktree
|
||||
|
||||
test_expect_success 'git archive vs. bare' '
|
||||
(cd bare && git archive HEAD) >bare-archive.tar &&
|
||||
test_cmp archive.tar bare-archive.tar
|
||||
'
|
||||
|
||||
test_expect_success 'git archive with worktree attributes, bare' '
|
||||
(cd bare && git archive --worktree-attributes HEAD) >bare-worktree.tar &&
|
||||
(mkdir bare-worktree && cd bare-worktree && "$TAR" xf -) <bare-worktree.tar
|
||||
'
|
||||
|
||||
test_expect_missing bare-worktree/ignored
|
||||
test_expect_exists bare-worktree/ignored-by-tree
|
||||
test_expect_exists bare-worktree/ignored-by-worktree
|
||||
|
||||
test_expect_success 'export-subst' '
|
||||
git log "--pretty=format:A${SUBSTFORMAT}O" HEAD >substfile1.expected &&
|
||||
test_cmp nosubstfile archive/nosubstfile &&
|
||||
test_cmp substfile1.expected archive/substfile1 &&
|
||||
test_cmp substfile2 archive/substfile2
|
||||
'
|
||||
|
||||
test_expect_success 'git tar-tree vs. git archive with worktree attributes' '
|
||||
git tar-tree HEAD >tar-tree.tar &&
|
||||
test_cmp worktree.tar tar-tree.tar
|
||||
'
|
||||
|
||||
test_expect_success 'git tar-tree vs. git archive with worktree attrs, bare' '
|
||||
(cd bare && git tar-tree HEAD) >bare-tar-tree.tar &&
|
||||
test_cmp bare-worktree.tar bare-tar-tree.tar
|
||||
'
|
||||
|
||||
test_done
|
@ -87,7 +87,8 @@ static int check_updates(struct unpack_trees_options *o)
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
|
||||
if (o->update)
|
||||
git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
|
||||
for (i = 0; i < index->cache_nr; i++) {
|
||||
struct cache_entry *ce = index->cache[i];
|
||||
|
||||
@ -112,7 +113,8 @@ static int check_updates(struct unpack_trees_options *o)
|
||||
}
|
||||
}
|
||||
stop_progress(&progress);
|
||||
git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
|
||||
if (o->update)
|
||||
git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
|
||||
return errs != 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user