Merge branch 'svn-travis' of git://bogomips.org/git-svn
* 'svn-travis' of git://bogomips.org/git-svn:
travis-ci: enable Git SVN tests t91xx on Linux
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 3e39e28..f6e288b 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -204,6 +204,7 @@
QUIET_DBLATEX = @echo ' ' DBLATEX $@;
QUIET_XSLTPROC = @echo ' ' XSLTPROC $@;
QUIET_GEN = @echo ' ' GEN $@;
+ QUIET_LINT = @echo ' ' LINT $@;
QUIET_STDERR = 2> /dev/null
QUIET_SUBDIR0 = +@subdir=
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
@@ -427,4 +428,7 @@
print-man1:
@for i in $(MAN1_TXT); do echo $$i; done
+lint-docs::
+ $(QUIET_LINT)$(PERL_PATH) lint-gitlink.perl
+
.PHONY: FORCE
diff --git a/Documentation/config.txt b/Documentation/config.txt
index e4cd291..53f00db 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -353,9 +353,9 @@
core.eol::
Sets the line ending type to use in the working directory for
- files that have the `text` property set. Alternatives are
- 'lf', 'crlf' and 'native', which uses the platform's native
- line ending. The default value is `native`. See
+ files that have the `text` property set when core.autocrlf is false.
+ Alternatives are 'lf', 'crlf' and 'native', which uses the platform's
+ native line ending. The default value is `native`. See
linkgit:gitattributes[5] for more information on end-of-line
conversion.
@@ -1141,6 +1141,10 @@
Specify the pathname of a file to use as the template for
new commit messages.
+commit.verbose::
+ A boolean or int to specify the level of verbose with `git commit`.
+ See linkgit:git-commit[1].
+
credential.helper::
Specify an external helper to be called when a username or
password credential is needed; the helper may consult external
@@ -1290,6 +1294,10 @@
Set a custom directory to store the resulting files instead of the
current working directory.
+format.useAutoBase::
+ A boolean value which lets you enable the `--base=auto` option of
+ format-patch by default.
+
filter.<driver>.clean::
The command which is used to convert the content of a worktree
file to a blob upon checkin. See linkgit:gitattributes[5] for
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 9ec6b3c..d474226 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -290,7 +290,8 @@
what changes the commit has.
Note that this diff output doesn't have its
lines prefixed with '#'. This diff will not be a part
- of the commit message.
+ of the commit message. See the `commit.verbose` configuration
+ variable in linkgit:git-config[1].
+
If specified twice, show in addition the unified diff between
what would be committed and the worktree files, i.e. the unstaged
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 6821441..bdeecd5 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -265,6 +265,11 @@
Output an all-zero hash in each patch's From header instead
of the hash of the commit.
+--base=<commit>::
+ Record the base tree information to identify the state the
+ patch series applies to. See the BASE TREE INFORMATION section
+ below for details.
+
--root::
Treat the revision argument as a <revision range>, even if it
is just a single commit (that would normally be treated as a
@@ -520,6 +525,61 @@
5. Back in the compose window: add whatever other text you wish to the
message, complete the addressing and subject fields, and press send.
+BASE TREE INFORMATION
+---------------------
+
+The base tree information block is used for maintainers or third party
+testers to know the exact state the patch series applies to. It consists
+of the 'base commit', which is a well-known commit that is part of the
+stable part of the project history everybody else works off of, and zero
+or more 'prerequisite patches', which are well-known patches in flight
+that is not yet part of the 'base commit' that need to be applied on top
+of 'base commit' in topological order before the patches can be applied.
+
+The 'base commit' is shown as "base-commit: " followed by the 40-hex of
+the commit object name. A 'prerequisite patch' is shown as
+"prerequisite-patch-id: " followed by the 40-hex 'patch id', which can
+be obtained by passing the patch through the `git patch-id --stable`
+command.
+
+Imagine that on top of the public commit P, you applied well-known
+patches X, Y and Z from somebody else, and then built your three-patch
+series A, B, C, the history would be like:
+
+................................................
+---P---X---Y---Z---A---B---C
+................................................
+
+With `git format-patch --base=P -3 C` (or variants thereof, e.g. with
+`--cover-letter` of using `Z..C` instead of `-3 C` to specify the
+range), the base tree information block is shown at the end of the
+first message the command outputs (either the first patch, or the
+cover letter), like this:
+
+------------
+base-commit: P
+prerequisite-patch-id: X
+prerequisite-patch-id: Y
+prerequisite-patch-id: Z
+------------
+
+For non-linear topology, such as
+
+................................................
+---P---X---A---M---C
+ \ /
+ Y---Z---B
+................................................
+
+You can also use `git format-patch --base=P -3 C` to generate patches
+for A, B and C, and the identifiers for P, X, Y, Z are appended at the
+end of the first message.
+
+If set `--base=auto` in cmdline, it will track base commit automatically,
+the base commit will be the merge base of tip commit of the remote-tracking
+branch and revision-range specified in cmdline.
+For a local branch, you need to track a remote branch by `git branch
+--set-upstream-to` before using this option.
EXAMPLES
--------
diff --git a/Documentation/lint-gitlink.perl b/Documentation/lint-gitlink.perl
new file mode 100755
index 0000000..476cc30
--- /dev/null
+++ b/Documentation/lint-gitlink.perl
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+use File::Find;
+use Getopt::Long;
+
+my $basedir = ".";
+GetOptions("basedir=s" => \$basedir)
+ or die("Cannot parse command line arguments\n");
+
+my $found_errors = 0;
+
+sub report {
+ my ($where, $what, $error) = @_;
+ print "$where: $error: $what\n";
+ $found_errors = 1;
+}
+
+sub grab_section {
+ my ($page) = @_;
+ open my $fh, "<", "$basedir/$page.txt";
+ my $firstline = <$fh>;
+ chomp $firstline;
+ close $fh;
+ my ($section) = ($firstline =~ /.*\((\d)\)$/);
+ return $section;
+}
+
+sub lint {
+ my ($file) = @_;
+ open my $fh, "<", $file
+ or return;
+ while (<$fh>) {
+ my $where = "$file:$.";
+ while (s/linkgit:((.*?)\[(\d)\])//) {
+ my ($target, $page, $section) = ($1, $2, $3);
+
+ # De-AsciiDoc
+ $page =~ s/{litdd}/--/g;
+
+ if ($page !~ /^git/) {
+ report($where, $target, "nongit link");
+ next;
+ }
+ if (! -f "$basedir/$page.txt") {
+ report($where, $target, "no such source");
+ next;
+ }
+ $real_section = grab_section($page);
+ if ($real_section != $section) {
+ report($where, $target,
+ "wrong section (should be $real_section)");
+ next;
+ }
+ }
+ }
+ close $fh;
+}
+
+sub lint_it {
+ lint($File::Find::name) if -f && /\.txt$/;
+}
+
+if (!@ARGV) {
+ find({ wanted => \&lint_it, no_chdir => 1 }, $basedir);
+} else {
+ for (@ARGV) {
+ lint($_);
+ }
+}
+
+exit $found_errors;
diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
index 695bd4b..27bd701 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -144,8 +144,12 @@
`OPT_COUNTUP(short, long, &int_var, description)`::
Introduce a count-up option.
- `int_var` is incremented on each use of `--option`, and
- reset to zero with `--no-option`.
+ Each use of `--option` increments `int_var`, starting from zero
+ (even if initially negative), and `--no-option` resets it to
+ zero. To determine if `--option` or `--no-option` was encountered at
+ all, initialize `int_var` to a negative value, and if it is still
+ negative after parse_options(), then neither `--option` nor
+ `--no-option` was seen.
`OPT_BIT(short, long, &int_var, description, mask)`::
Introduce a boolean option.
diff --git a/Makefile b/Makefile
index bc3d41e..0d59718 100644
--- a/Makefile
+++ b/Makefile
@@ -2483,6 +2483,7 @@
.PHONY: check-docs
check-docs::
+ $(MAKE) -C Documentation lint-docs
@(for v in $(ALL_COMMANDS); \
do \
case "$$v" in \
diff --git a/branch.c b/branch.c
index 4162443..a5a8dcb 100644
--- a/branch.c
+++ b/branch.c
@@ -334,15 +334,16 @@
unlink(git_path_squash_msg());
}
-void die_if_checked_out(const char *branch)
+void die_if_checked_out(const char *branch, int ignore_current_worktree)
{
- char *existing;
+ const struct worktree *wt;
- existing = find_shared_symref("HEAD", branch);
- if (existing) {
- skip_prefix(branch, "refs/heads/", &branch);
- die(_("'%s' is already checked out at '%s'"), branch, existing);
- }
+ wt = find_shared_symref("HEAD", branch);
+ if (!wt || (ignore_current_worktree && wt->is_current))
+ return;
+ skip_prefix(branch, "refs/heads/", &branch);
+ die(_("'%s' is already checked out at '%s'"),
+ branch, wt->path);
}
int replace_each_worktree_head_symref(const char *oldref, const char *newref)
@@ -357,7 +358,8 @@
if (strcmp(oldref, worktrees[i]->head_ref))
continue;
- if (set_worktree_head_symref(worktrees[i]->git_dir, newref)) {
+ if (set_worktree_head_symref(get_worktree_git_dir(worktrees[i]),
+ newref)) {
ret = -1;
error(_("HEAD of working tree %s is not updated"),
worktrees[i]->path);
diff --git a/branch.h b/branch.h
index d69163d..b2f9649 100644
--- a/branch.h
+++ b/branch.h
@@ -58,7 +58,7 @@
* worktree and die (with a message describing its checkout location) if
* it is.
*/
-extern void die_if_checked_out(const char *branch);
+extern void die_if_checked_out(const char *branch, int ignore_current_worktree);
/*
* Update all per-worktree HEADs pointing at the old ref to point the new ref.
diff --git a/builtin/branch.c b/builtin/branch.c
index eacec57..2ecde53 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -220,12 +220,12 @@
name = mkpathdup(fmt, bname.buf);
if (kinds == FILTER_REFS_BRANCHES) {
- char *worktree = find_shared_symref("HEAD", name);
- if (worktree) {
+ const struct worktree *wt =
+ find_shared_symref("HEAD", name);
+ if (wt) {
error(_("Cannot delete branch '%s' "
"checked out at '%s'"),
- bname.buf, worktree);
- free(worktree);
+ bname.buf, wt->path);
ret = 1;
continue;
}
@@ -526,6 +526,29 @@
ref_array_clear(&array);
}
+static void reject_rebase_or_bisect_branch(const char *target)
+{
+ struct worktree **worktrees = get_worktrees();
+ int i;
+
+ for (i = 0; worktrees[i]; i++) {
+ struct worktree *wt = worktrees[i];
+
+ if (!wt->is_detached)
+ continue;
+
+ if (is_worktree_being_rebased(wt, target))
+ die(_("Branch %s is being rebased at %s"),
+ target, wt->path);
+
+ if (is_worktree_being_bisected(wt, target))
+ die(_("Branch %s is being bisected at %s"),
+ target, wt->path);
+ }
+
+ free_worktrees(worktrees);
+}
+
static void rename_branch(const char *oldname, const char *newname, int force)
{
struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
@@ -555,6 +578,8 @@
validate_new_branchname(newname, &newref, force, clobber_head_ok);
+ reject_rebase_or_bisect_branch(oldref.buf);
+
strbuf_addf(&logmsg, "Branch: renamed %s to %s",
oldref.buf, newref.buf);
diff --git a/builtin/checkout.c b/builtin/checkout.c
index ea2fe1c..3398c61 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1110,7 +1110,7 @@
char *head_ref = resolve_refdup("HEAD", 0, sha1, &flag);
if (head_ref &&
(!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path)))
- die_if_checked_out(new->path);
+ die_if_checked_out(new->path, 1);
free(head_ref);
}
diff --git a/builtin/commit.c b/builtin/commit.c
index 391126e..443ff91 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -114,6 +114,7 @@
static int all, also, interactive, patch_interactive, only, amend, signoff;
static int edit_flag = -1; /* unspecified */
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
+static int config_commit_verbose = -1; /* unspecified */
static int no_post_rewrite, allow_empty_message;
static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
static char *sign_commit;
@@ -1515,6 +1516,11 @@
sign_commit = git_config_bool(k, v) ? "" : NULL;
return 0;
}
+ if (!strcmp(k, "commit.verbose")) {
+ int is_bool;
+ config_commit_verbose = git_config_bool_or_int(k, v, &is_bool);
+ return 0;
+ }
status = git_gpg_config(k, v, NULL);
if (status)
@@ -1661,9 +1667,13 @@
if (parse_commit(current_head))
die(_("could not parse HEAD commit"));
}
+ verbose = -1; /* unspecified */
argc = parse_and_validate_options(argc, argv, builtin_commit_options,
builtin_commit_usage,
prefix, current_head, &s);
+ if (verbose == -1)
+ verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
+
if (dry_run)
return dry_run_commit(argc, argv, prefix, current_head, &s);
index_file = prepare_index(argc, argv, prefix, current_head, 0);
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index 8ed2eb8..15c61fd 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -24,6 +24,7 @@
gitmodules_config();
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
rev.abbrev = 0;
+ precompose_argv(argc, argv);
argc = setup_revisions(argc, argv, &rev, NULL);
while (1 < argc && argv[1][0] == '-') {
diff --git a/builtin/diff-index.c b/builtin/diff-index.c
index d979824..1af373d 100644
--- a/builtin/diff-index.c
+++ b/builtin/diff-index.c
@@ -21,6 +21,7 @@
gitmodules_config();
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
rev.abbrev = 0;
+ precompose_argv(argc, argv);
argc = setup_revisions(argc, argv, &rev, NULL);
for (i = 1; i < argc; i++) {
diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index 2a12b81..806dd7a 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -114,6 +114,8 @@
opt->disable_stdin = 1;
memset(&s_r_opt, 0, sizeof(s_r_opt));
s_r_opt.tweak = diff_tree_tweak_rev;
+
+ precompose_argv(argc, argv);
argc = setup_revisions(argc, argv, opt, &s_r_opt);
while (--argc > 0) {
diff --git a/builtin/diff.c b/builtin/diff.c
index 343c6b8..b7a9405 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -320,6 +320,7 @@
gitmodules_config();
init_diff_ui_defaults();
git_config(git_diff_ui_config, NULL);
+ precompose_argv(argc, argv);
init_revisions(&rev, prefix);
diff --git a/builtin/log.c b/builtin/log.c
index dff3fbb..099f4f7 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -702,6 +702,7 @@
#define THREAD_DEEP 2
static int thread;
static int do_signoff;
+static int base_auto;
static const char *signature = git_version_string;
static const char *signature_file;
static int config_cover_letter;
@@ -786,6 +787,10 @@
}
if (!strcmp(var, "format.outputdirectory"))
return git_config_string(&config_output_directory, var, value);
+ if (!strcmp(var, "format.useautobase")) {
+ base_auto = git_config_bool(var, value);
+ return 0;
+ }
return git_log_config(var, value, cb);
}
@@ -1191,6 +1196,155 @@
return 0;
}
+struct base_tree_info {
+ struct object_id base_commit;
+ int nr_patch_id, alloc_patch_id;
+ struct object_id *patch_id;
+};
+
+static struct commit *get_base_commit(const char *base_commit,
+ struct commit **list,
+ int total)
+{
+ struct commit *base = NULL;
+ struct commit **rev;
+ int i = 0, rev_nr = 0;
+
+ if (base_commit && strcmp(base_commit, "auto")) {
+ base = lookup_commit_reference_by_name(base_commit);
+ if (!base)
+ die(_("Unknown commit %s"), base_commit);
+ } else if ((base_commit && !strcmp(base_commit, "auto")) || base_auto) {
+ struct branch *curr_branch = branch_get(NULL);
+ const char *upstream = branch_get_upstream(curr_branch, NULL);
+ if (upstream) {
+ struct commit_list *base_list;
+ struct commit *commit;
+ unsigned char sha1[20];
+
+ if (get_sha1(upstream, sha1))
+ die(_("Failed to resolve '%s' as a valid ref."), upstream);
+ commit = lookup_commit_or_die(sha1, "upstream base");
+ base_list = get_merge_bases_many(commit, total, list);
+ /* There should be one and only one merge base. */
+ if (!base_list || base_list->next)
+ die(_("Could not find exact merge base."));
+ base = base_list->item;
+ free_commit_list(base_list);
+ } else {
+ die(_("Failed to get upstream, if you want to record base commit automatically,\n"
+ "please use git branch --set-upstream-to to track a remote branch.\n"
+ "Or you could specify base commit by --base=<base-commit-id> manually."));
+ }
+ }
+
+ ALLOC_ARRAY(rev, total);
+ for (i = 0; i < total; i++)
+ rev[i] = list[i];
+
+ rev_nr = total;
+ /*
+ * Get merge base through pair-wise computations
+ * and store it in rev[0].
+ */
+ while (rev_nr > 1) {
+ for (i = 0; i < rev_nr / 2; i++) {
+ struct commit_list *merge_base;
+ merge_base = get_merge_bases(rev[2 * i], rev[2 * i + 1]);
+ if (!merge_base || merge_base->next)
+ die(_("Failed to find exact merge base"));
+
+ rev[i] = merge_base->item;
+ }
+
+ if (rev_nr % 2)
+ rev[i] = rev[2 * i];
+ rev_nr = (rev_nr + 1) / 2;
+ }
+
+ if (!in_merge_bases(base, rev[0]))
+ die(_("base commit should be the ancestor of revision list"));
+
+ for (i = 0; i < total; i++) {
+ if (base == list[i])
+ die(_("base commit shouldn't be in revision list"));
+ }
+
+ free(rev);
+ return base;
+}
+
+static void prepare_bases(struct base_tree_info *bases,
+ struct commit *base,
+ struct commit **list,
+ int total)
+{
+ struct commit *commit;
+ struct rev_info revs;
+ struct diff_options diffopt;
+ int i;
+
+ if (!base)
+ return;
+
+ diff_setup(&diffopt);
+ DIFF_OPT_SET(&diffopt, RECURSIVE);
+ diff_setup_done(&diffopt);
+
+ oidcpy(&bases->base_commit, &base->object.oid);
+
+ init_revisions(&revs, NULL);
+ revs.max_parents = 1;
+ revs.topo_order = 1;
+ for (i = 0; i < total; i++) {
+ list[i]->object.flags &= ~UNINTERESTING;
+ add_pending_object(&revs, &list[i]->object, "rev_list");
+ list[i]->util = (void *)1;
+ }
+ base->object.flags |= UNINTERESTING;
+ add_pending_object(&revs, &base->object, "base");
+
+ if (prepare_revision_walk(&revs))
+ die(_("revision walk setup failed"));
+ /*
+ * Traverse the commits list, get prerequisite patch ids
+ * and stuff them in bases structure.
+ */
+ while ((commit = get_revision(&revs)) != NULL) {
+ unsigned char sha1[20];
+ struct object_id *patch_id;
+ if (commit->util)
+ continue;
+ if (commit_patch_id(commit, &diffopt, sha1))
+ die(_("cannot get patch id"));
+ ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id);
+ patch_id = bases->patch_id + bases->nr_patch_id;
+ hashcpy(patch_id->hash, sha1);
+ bases->nr_patch_id++;
+ }
+}
+
+static void print_bases(struct base_tree_info *bases)
+{
+ int i;
+
+ /* Only do this once, either for the cover or for the first one */
+ if (is_null_oid(&bases->base_commit))
+ return;
+
+ /* Show the base commit */
+ printf("base-commit: %s\n", oid_to_hex(&bases->base_commit));
+
+ /* Show the prerequisite patches */
+ for (i = bases->nr_patch_id - 1; i >= 0; i--)
+ printf("prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
+
+ free(bases->patch_id);
+ bases->nr_patch_id = 0;
+ bases->alloc_patch_id = 0;
+ oidclr(&bases->base_commit);
+}
+
int cmd_format_patch(int argc, const char **argv, const char *prefix)
{
struct commit *commit;
@@ -1215,6 +1369,9 @@
int reroll_count = -1;
char *branch_name = NULL;
char *from = NULL;
+ char *base_commit = NULL;
+ struct base_tree_info bases;
+
const struct option builtin_format_patch_options[] = {
{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
N_("use [PATCH n/m] even with a single patch"),
@@ -1277,6 +1434,8 @@
PARSE_OPT_OPTARG, thread_callback },
OPT_STRING(0, "signature", &signature, N_("signature"),
N_("add a signature")),
+ OPT_STRING(0, "base", &base_commit, N_("base-commit"),
+ N_("add prerequisite tree info to the patch series")),
OPT_FILENAME(0, "signature-file", &signature_file,
N_("add a signature from a file")),
OPT__QUIET(&quiet, N_("don't print the patch filenames")),
@@ -1514,6 +1673,13 @@
signature = strbuf_detach(&buf, NULL);
}
+ memset(&bases, 0, sizeof(bases));
+ if (base_commit || base_auto) {
+ struct commit *base = get_base_commit(base_commit, list, nr);
+ reset_revision_walk();
+ prepare_bases(&bases, base, list, nr);
+ }
+
if (in_reply_to || thread || cover_letter)
rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
if (in_reply_to) {
@@ -1527,6 +1693,7 @@
gen_message_id(&rev, "cover");
make_cover_letter(&rev, use_stdout,
origin, nr, list, branch_name, quiet);
+ print_bases(&bases);
total++;
start_number--;
}
@@ -1592,6 +1759,7 @@
rev.mime_boundary);
else
print_signature();
+ print_bases(&bases);
}
if (!use_stdout)
fclose(stdout);
diff --git a/builtin/notes.c b/builtin/notes.c
index 6fd058d..c65b59a 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -847,15 +847,15 @@
update_ref(msg.buf, default_notes_ref(), result_sha1, NULL,
0, UPDATE_REFS_DIE_ON_ERR);
else { /* Merge has unresolved conflicts */
- char *existing;
+ const struct worktree *wt;
/* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL,
0, UPDATE_REFS_DIE_ON_ERR);
/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
- existing = find_shared_symref("NOTES_MERGE_REF", default_notes_ref());
- if (existing)
+ wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref());
+ if (wt)
die(_("A notes merge into %s is already in-progress at %s"),
- default_notes_ref(), existing);
+ default_notes_ref(), wt->path);
if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL))
die("Failed to store link to current notes ref (%s)",
default_notes_ref());
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 331ecf6..96a2834 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -205,7 +205,7 @@
if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
ref_exists(symref.buf)) { /* it's a branch */
if (!opts->force)
- die_if_checked_out(symref.buf);
+ die_if_checked_out(symref.buf, 0);
} else { /* must be a commit */
commit = lookup_commit_reference_by_name(refname);
if (!commit)
@@ -349,7 +349,7 @@
if (!opts.force &&
!strbuf_check_branch_ref(&symref, opts.new_branch) &&
ref_exists(symref.buf))
- die_if_checked_out(symref.buf);
+ die_if_checked_out(symref.buf, 0);
strbuf_release(&symref);
}
diff --git a/cache.h b/cache.h
index 6b80a17..6049f86 100644
--- a/cache.h
+++ b/cache.h
@@ -808,11 +808,14 @@
*/
extern const char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
extern const char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+extern const char *git_common_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
__attribute__((format (printf, 3, 4)));
extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
__attribute__((format (printf, 2, 3)));
+extern void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...)
+ __attribute__((format (printf, 2, 3)));
extern char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
__attribute__((format (printf, 2, 3)));
extern void strbuf_git_path_submodule(struct strbuf *sb, const char *path,
diff --git a/config.c b/config.c
index 096fe03..f51c56b 100644
--- a/config.c
+++ b/config.c
@@ -806,8 +806,6 @@
if (!strcmp(var, "core.autocrlf")) {
if (value && !strcasecmp(value, "input")) {
- if (core_eol == EOL_CRLF)
- return error("core.autocrlf=input conflicts with core.eol=crlf");
auto_crlf = AUTO_CRLF_INPUT;
return 0;
}
@@ -833,8 +831,6 @@
core_eol = EOL_NATIVE;
else
core_eol = EOL_UNSET;
- if (core_eol == EOL_CRLF && auto_crlf == AUTO_CRLF_INPUT)
- return error("core.autocrlf=input conflicts with core.eol=crlf");
return 0;
}
diff --git a/convert.c b/convert.c
index f524b8d..b1614bf 100644
--- a/convert.c
+++ b/convert.c
@@ -1380,27 +1380,22 @@
struct stream_filter *get_stream_filter(const char *path, const unsigned char *sha1)
{
struct conv_attrs ca;
- enum crlf_action crlf_action;
struct stream_filter *filter = NULL;
convert_attrs(&ca, path);
-
if (ca.drv && (ca.drv->smudge || ca.drv->clean))
- return filter;
+ return NULL;
+
+ if (ca.crlf_action == CRLF_AUTO || ca.crlf_action == CRLF_AUTO_CRLF)
+ return NULL;
if (ca.ident)
filter = ident_filter(sha1);
- crlf_action = ca.crlf_action;
-
- if ((crlf_action == CRLF_BINARY) ||
- crlf_action == CRLF_AUTO_INPUT ||
- (crlf_action == CRLF_TEXT_INPUT))
- filter = cascade_filter(filter, &null_filter_singleton);
-
- else if (output_eol(crlf_action) == EOL_CRLF &&
- !(crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_CRLF))
+ if (output_eol(ca.crlf_action) == EOL_CRLF)
filter = cascade_filter(filter, lf_to_crlf_filter());
+ else
+ filter = cascade_filter(filter, &null_filter_singleton);
return filter;
}
diff --git a/dir.c b/dir.c
index 656f272..6172b34 100644
--- a/dir.c
+++ b/dir.c
@@ -53,13 +53,12 @@
int check_only, const struct path_simplify *simplify);
static int get_dtype(struct dirent *de, const char *path, int len);
-/* helper string functions with support for the ignore_case flag */
-int strcmp_icase(const char *a, const char *b)
+int fspathcmp(const char *a, const char *b)
{
return ignore_case ? strcasecmp(a, b) : strcmp(a, b);
}
-int strncmp_icase(const char *a, const char *b, size_t count)
+int fspathncmp(const char *a, const char *b, size_t count)
{
return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
}
@@ -795,12 +794,12 @@
{
if (prefix == patternlen) {
if (patternlen == basenamelen &&
- !strncmp_icase(pattern, basename, basenamelen))
+ !fspathncmp(pattern, basename, basenamelen))
return 1;
} else if (flags & EXC_FLAG_ENDSWITH) {
/* "*literal" matching against "fooliteral" */
if (patternlen - 1 <= basenamelen &&
- !strncmp_icase(pattern + 1,
+ !fspathncmp(pattern + 1,
basename + basenamelen - (patternlen - 1),
patternlen - 1))
return 1;
@@ -837,7 +836,7 @@
*/
if (pathlen < baselen + 1 ||
(baselen && pathname[baselen] != '/') ||
- strncmp_icase(pathname, base, baselen))
+ fspathncmp(pathname, base, baselen))
return 0;
namelen = baselen ? pathlen - baselen - 1 : pathlen;
@@ -851,7 +850,7 @@
if (prefix > namelen)
return 0;
- if (strncmp_icase(pattern, name, prefix))
+ if (fspathncmp(pattern, name, prefix))
return 0;
pattern += prefix;
patternlen -= prefix;
diff --git a/dir.h b/dir.h
index d56d2fb..bfde698 100644
--- a/dir.h
+++ b/dir.h
@@ -270,8 +270,8 @@
/* tries to remove the path with empty directories along it, ignores ENOENT */
extern int remove_path(const char *path);
-extern int strcmp_icase(const char *a, const char *b);
-extern int strncmp_icase(const char *a, const char *b, size_t count);
+extern int fspathcmp(const char *a, const char *b);
+extern int fspathncmp(const char *a, const char *b, size_t count);
/*
* The prefix part of pattern must not contains wildcards.
diff --git a/fast-import.c b/fast-import.c
index 21881d1..83558dc 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1512,7 +1512,7 @@
t = root->tree;
for (i = 0; i < t->entry_count; i++) {
e = t->entries[i];
- if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
+ if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
if (!*slash1) {
if (!S_ISDIR(mode)
&& e->versions[1].mode == mode
@@ -1602,7 +1602,7 @@
t = root->tree;
for (i = 0; i < t->entry_count; i++) {
e = t->entries[i];
- if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
+ if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
if (*slash1 && !S_ISDIR(e->versions[1].mode))
/*
* If p names a file in some subdirectory, and a
@@ -1669,7 +1669,7 @@
t = root->tree;
for (i = 0; i < t->entry_count; i++) {
e = t->entries[i];
- if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
+ if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
if (!*slash1)
goto found_entry;
if (!S_ISDIR(e->versions[1].mode))
diff --git a/git-difftool.perl b/git-difftool.perl
index 488d14b..ebd13ba 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -138,6 +138,7 @@
my %submodule;
my %symlink;
my @working_tree = ();
+ my %working_tree_dups = ();
my @rawdiff = split('\0', $diffrtn);
my $i = 0;
@@ -188,6 +189,10 @@
}
if ($rmode ne $null_mode) {
+ # Avoid duplicate working_tree entries
+ if ($working_tree_dups{$dst_path}++) {
+ next;
+ }
my ($use, $wt_sha1) = use_wt_file($repo, $workdir,
$dst_path, $rsha1);
if ($use) {
@@ -273,7 +278,7 @@
# temporary file to both the left and right directories to show the
# change in the recorded SHA1 for the submodule.
for my $path (keys %submodule) {
- my $ok;
+ my $ok = 0;
if (defined($submodule{$path}{left})) {
$ok = write_to_file("$ldir/$path",
"Subproject commit $submodule{$path}{left}");
@@ -289,7 +294,7 @@
# shows only the link itself, not the contents of the link target.
# This loop replicates that behavior.
for my $path (keys %symlink) {
- my $ok;
+ my $ok = 0;
if (defined($symlink{$path}{left})) {
$ok = write_to_file("$ldir/$path",
$symlink{$path}{left});
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 1c6dfb6..9d2bfb7 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -867,12 +867,12 @@
# $3: the input filename
check_commit_sha () {
badsha=0
- if test -z $1
+ if test -z "$1"
then
badsha=1
else
sha1_verif="$(git rev-parse --verify --quiet $1^{commit})"
- if test -z $sha1_verif
+ if test -z "$sha1_verif"
then
badsha=1
fi
diff --git a/git-stash.sh b/git-stash.sh
index c7c65e2..c7509e8 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -185,7 +185,7 @@
git update-ref --create-reflog -m "$stash_msg" $ref_stash $w_commit
ret=$?
- test $ret != 0 && test -z $quiet &&
+ test $ret != 0 && test -z "$quiet" &&
die "$(eval_gettext "Cannot update \$ref_stash with \$w_commit")"
return $ret
}
@@ -277,7 +277,7 @@
git clean --force --quiet -d $CLEAN_X_OPTION
fi
- if test "$keep_index" = "t" && test -n $i_tree
+ if test "$keep_index" = "t" && test -n "$i_tree"
then
git read-tree --reset -u $i_tree
fi
diff --git a/parse-options.c b/parse-options.c
index 47a9192..312a85d 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -110,6 +110,8 @@
return 0;
case OPTION_COUNTUP:
+ if (*(int *)opt->value < 0)
+ *(int *)opt->value = 0;
*(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
return 0;
diff --git a/patch-ids.c b/patch-ids.c
index b7b3e5a..a4d0016 100644
--- a/patch-ids.c
+++ b/patch-ids.c
@@ -4,7 +4,7 @@
#include "sha1-lookup.h"
#include "patch-ids.h"
-static int commit_patch_id(struct commit *commit, struct diff_options *options,
+int commit_patch_id(struct commit *commit, struct diff_options *options,
unsigned char *sha1)
{
if (commit->parents)
diff --git a/patch-ids.h b/patch-ids.h
index c8c7ca1..eeb56b3 100644
--- a/patch-ids.h
+++ b/patch-ids.h
@@ -13,6 +13,8 @@
struct patch_id_bucket *patches;
};
+int commit_patch_id(struct commit *commit, struct diff_options *options,
+ unsigned char *sha1);
int init_patch_ids(struct patch_ids *);
int free_patch_ids(struct patch_ids *);
struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *);
diff --git a/path.c b/path.c
index 5037667..259aeed 100644
--- a/path.c
+++ b/path.c
@@ -5,6 +5,7 @@
#include "strbuf.h"
#include "string-list.h"
#include "dir.h"
+#include "worktree.h"
static int get_st_mode_bits(const char *path, int *mode)
{
@@ -383,10 +384,11 @@
update_common_dir(buf, git_dir_len, NULL);
}
-static void do_git_path(struct strbuf *buf, const char *fmt, va_list args)
+static void do_git_path(const struct worktree *wt, struct strbuf *buf,
+ const char *fmt, va_list args)
{
int gitdir_len;
- strbuf_addstr(buf, get_git_dir());
+ strbuf_addstr(buf, get_worktree_git_dir(wt));
if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
strbuf_addch(buf, '/');
gitdir_len = buf->len;
@@ -400,7 +402,7 @@
va_list args;
strbuf_reset(buf);
va_start(args, fmt);
- do_git_path(buf, fmt, args);
+ do_git_path(NULL, buf, fmt, args);
va_end(args);
return buf->buf;
}
@@ -409,7 +411,7 @@
{
va_list args;
va_start(args, fmt);
- do_git_path(sb, fmt, args);
+ do_git_path(NULL, sb, fmt, args);
va_end(args);
}
@@ -418,7 +420,7 @@
struct strbuf *pathname = get_pathname();
va_list args;
va_start(args, fmt);
- do_git_path(pathname, fmt, args);
+ do_git_path(NULL, pathname, fmt, args);
va_end(args);
return pathname->buf;
}
@@ -428,7 +430,7 @@
struct strbuf path = STRBUF_INIT;
va_list args;
va_start(args, fmt);
- do_git_path(&path, fmt, args);
+ do_git_path(NULL, &path, fmt, args);
va_end(args);
return strbuf_detach(&path, NULL);
}
@@ -454,6 +456,16 @@
return cleanup_path(pathname->buf);
}
+const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
+{
+ struct strbuf *pathname = get_pathname();
+ va_list args;
+ va_start(args, fmt);
+ do_git_path(wt, pathname, fmt, args);
+ va_end(args);
+ return pathname->buf;
+}
+
static void do_submodule_path(struct strbuf *buf, const char *path,
const char *fmt, va_list args)
{
@@ -503,6 +515,35 @@
va_end(args);
}
+static void do_git_common_path(struct strbuf *buf,
+ const char *fmt,
+ va_list args)
+{
+ strbuf_addstr(buf, get_git_common_dir());
+ if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
+ strbuf_addch(buf, '/');
+ strbuf_vaddf(buf, fmt, args);
+ strbuf_cleanup_path(buf);
+}
+
+const char *git_common_path(const char *fmt, ...)
+{
+ struct strbuf *pathname = get_pathname();
+ va_list args;
+ va_start(args, fmt);
+ do_git_common_path(pathname, fmt, args);
+ va_end(args);
+ return pathname->buf;
+}
+
+void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ do_git_common_path(sb, fmt, args);
+ va_end(args);
+}
+
int validate_headref(const char *path)
{
struct stat st;
diff --git a/rerere.c b/rerere.c
index 1810c04..aaadec1 100644
--- a/rerere.c
+++ b/rerere.c
@@ -1050,8 +1050,8 @@
handle_cache(path, sha1, rerere_path(id, "thisimage"));
if (read_mmfile(&cur, rerere_path(id, "thisimage"))) {
free(cur.ptr);
- return error("Failed to update conflicted state in '%s'",
- path);
+ error("Failed to update conflicted state in '%s'", path);
+ goto fail_exit;
}
cleanly_resolved = !try_merge(id, path, &cur, &result);
free(result.ptr);
@@ -1060,14 +1060,19 @@
break;
}
- if (id->collection->status_nr <= id->variant)
- return error("no remembered resolution for '%s'", path);
+ if (id->collection->status_nr <= id->variant) {
+ error("no remembered resolution for '%s'", path);
+ goto fail_exit;
+ }
filename = rerere_path(id, "postimage");
- if (unlink(filename))
- return (errno == ENOENT
- ? error("no remembered resolution for %s", path)
- : error_errno("cannot unlink %s", filename));
+ if (unlink(filename)) {
+ if (errno == ENOENT)
+ error("no remembered resolution for %s", path);
+ else
+ error_errno("cannot unlink %s", filename);
+ goto fail_exit;
+ }
/*
* Update the preimage so that the user can resolve the
@@ -1086,6 +1091,10 @@
item->util = id;
fprintf(stderr, "Forgot resolution for %s\n", path);
return 0;
+
+fail_exit:
+ free(id);
+ return -1;
}
int rerere_forget(struct pathspec *pathspec)
diff --git a/sha1_file.c b/sha1_file.c
index a7f45b3..d5e1121 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -301,7 +301,7 @@
return -1;
}
}
- if (!strcmp_icase(ent->base, normalized_objdir)) {
+ if (!fspathcmp(ent->base, normalized_objdir)) {
free(ent);
return -1;
}
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index 2c8c8f1..8a1235d 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -7,16 +7,25 @@
static unsigned long magnitude = 0;
static unsigned long timestamp;
static int abbrev = 7;
-static int verbose = 0, dry_run = 0, quiet = 0;
+static int verbose = -1; /* unspecified */
+static int dry_run = 0, quiet = 0;
static char *string = NULL;
static char *file = NULL;
static int ambiguous;
static struct string_list list;
+static struct {
+ int called;
+ const char *arg;
+ int unset;
+} length_cb;
+
static int length_callback(const struct option *opt, const char *arg, int unset)
{
- printf("Callback: \"%s\", %d\n",
- (arg ? arg : "not set"), unset);
+ length_cb.called = 1;
+ length_cb.arg = arg;
+ length_cb.unset = unset;
+
if (unset)
return 1; /* do not support unset */
@@ -30,6 +39,61 @@
return 0;
}
+static int collect_expect(const struct option *opt, const char *arg, int unset)
+{
+ struct string_list *expect;
+ struct string_list_item *item;
+ struct strbuf label = STRBUF_INIT;
+ const char *colon;
+
+ if (!arg || unset)
+ die("malformed --expect option");
+
+ expect = (struct string_list *)opt->value;
+ colon = strchr(arg, ':');
+ if (!colon)
+ die("malformed --expect option, lacking a colon");
+ strbuf_add(&label, arg, colon - arg);
+ item = string_list_insert(expect, strbuf_detach(&label, NULL));
+ if (item->util)
+ die("malformed --expect option, duplicate %s", label.buf);
+ item->util = (void *)arg;
+ return 0;
+}
+
+__attribute__((format (printf,3,4)))
+static void show(struct string_list *expect, int *status, const char *fmt, ...)
+{
+ struct string_list_item *item;
+ struct strbuf buf = STRBUF_INIT;
+ va_list args;
+
+ va_start(args, fmt);
+ strbuf_vaddf(&buf, fmt, args);
+ va_end(args);
+
+ if (!expect->nr)
+ printf("%s\n", buf.buf);
+ else {
+ char *colon = strchr(buf.buf, ':');
+ if (!colon)
+ die("malformed output format, output lacking colon: %s", fmt);
+ *colon = '\0';
+ item = string_list_lookup(expect, buf.buf);
+ *colon = ':';
+ if (!item)
+ ; /* not among entries being checked */
+ else {
+ if (strcmp((const char *)item->util, buf.buf)) {
+ printf("-%s\n", (char *)item->util);
+ printf("+%s\n", buf.buf);
+ *status = 1;
+ }
+ }
+ }
+ strbuf_release(&buf);
+}
+
int main(int argc, char **argv)
{
const char *prefix = "prefix/";
@@ -37,6 +101,7 @@
"test-parse-options <options>",
NULL
};
+ struct string_list expect = STRING_LIST_INIT_NODUP;
struct option options[] = {
OPT_BOOL(0, "yes", &boolean, "get a boolean"),
OPT_BOOL('D', "no-doubt", &boolean, "begins with 'no-'"),
@@ -77,28 +142,38 @@
OPT__VERBOSE(&verbose, "be verbose"),
OPT__DRY_RUN(&dry_run, "dry run"),
OPT__QUIET(&quiet, "be quiet"),
+ OPT_CALLBACK(0, "expect", &expect, "string",
+ "expected output in the variable dump",
+ collect_expect),
OPT_END(),
};
int i;
+ int ret = 0;
argc = parse_options(argc, (const char **)argv, prefix, options, usage, 0);
- printf("boolean: %d\n", boolean);
- printf("integer: %d\n", integer);
- printf("magnitude: %lu\n", magnitude);
- printf("timestamp: %lu\n", timestamp);
- printf("string: %s\n", string ? string : "(not set)");
- printf("abbrev: %d\n", abbrev);
- printf("verbose: %d\n", verbose);
- printf("quiet: %s\n", quiet ? "yes" : "no");
- printf("dry run: %s\n", dry_run ? "yes" : "no");
- printf("file: %s\n", file ? file : "(not set)");
+ if (length_cb.called) {
+ const char *arg = length_cb.arg;
+ int unset = length_cb.unset;
+ show(&expect, &ret, "Callback: \"%s\", %d",
+ (arg ? arg : "not set"), unset);
+ }
+ show(&expect, &ret, "boolean: %d", boolean);
+ show(&expect, &ret, "integer: %d", integer);
+ show(&expect, &ret, "magnitude: %lu", magnitude);
+ show(&expect, &ret, "timestamp: %lu", timestamp);
+ show(&expect, &ret, "string: %s", string ? string : "(not set)");
+ show(&expect, &ret, "abbrev: %d", abbrev);
+ show(&expect, &ret, "verbose: %d", verbose);
+ show(&expect, &ret, "quiet: %d", quiet);
+ show(&expect, &ret, "dry run: %s", dry_run ? "yes" : "no");
+ show(&expect, &ret, "file: %s", file ? file : "(not set)");
for (i = 0; i < list.nr; i++)
- printf("list: %s\n", list.items[i].string);
+ show(&expect, &ret, "list: %s", list.items[i].string);
for (i = 0; i < argc; i++)
- printf("arg %02d: %s\n", i, argv[i]);
+ show(&expect, &ret, "arg %02d: %s", i, argv[i]);
- return 0;
+ return ret;
}
diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh
index 6a50b87..fb88232 100644
--- a/t/lib-git-svn.sh
+++ b/t/lib-git-svn.sh
@@ -1,8 +1,5 @@
. ./test-lib.sh
-remotes_git_svn=remotes/git""-svn
-git_svn_id=git""-svn-id
-
if test -n "$NO_SVN_TESTS"
then
skip_all='skipping git svn tests, NO_SVN_TESTS defined'
diff --git a/t/perf/p3404-rebase-interactive.sh b/t/perf/p3404-rebase-interactive.sh
new file mode 100755
index 0000000..88f47de
--- /dev/null
+++ b/t/perf/p3404-rebase-interactive.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+test_description='Tests rebase -i performance'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+# This commit merges a sufficiently long topic branch for reasonable
+# performance testing
+branch_merge=ba5312da19c6fdb6c6747d479f58932aae6e900c^{commit}
+export branch_merge
+
+git rev-parse --verify $branch_merge >/dev/null 2>&1 || {
+ skip_all='skipping because $branch_merge was not found'
+ test_done
+}
+
+write_script swap-first-two.sh <<\EOF
+case "$1" in
+*/COMMIT_EDITMSG)
+ mv "$1" "$1".bak &&
+ sed -e '1{h;d}' -e 2G <"$1".bak >"$1"
+ ;;
+esac
+EOF
+
+test_expect_success 'setup' '
+ git config core.editor "\"$PWD"/swap-first-two.sh\" &&
+ git checkout -f $branch_merge^2
+'
+
+test_perf 'rebase -i' '
+ git rebase -i $branch_merge^
+'
+
+test_done
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index 5cf74ed..5ef1744 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -80,23 +80,26 @@
error "bug in the test script: not 2 parameters to test-create-repo"
repo="$1"
source="$2"
- source_git=$source/$(cd "$source" && git rev-parse --git-dir)
+ source_git="$(git -C "$source" rev-parse --git-dir)"
+ objects_dir="$(git -C "$source" rev-parse --git-path objects)"
mkdir -p "$repo/.git"
(
- cd "$repo/.git" &&
- { cp -Rl "$source_git/objects" . 2>/dev/null ||
- cp -R "$source_git/objects" .; } &&
+ { cp -Rl "$objects_dir" "$repo/.git/" 2>/dev/null ||
+ cp -R "$objects_dir" "$repo/.git/"; } &&
for stuff in "$source_git"/*; do
case "$stuff" in
- */objects|*/hooks|*/config)
+ */objects|*/hooks|*/config|*/commondir)
;;
*)
- cp -R "$stuff" . || exit 1
+ cp -R "$stuff" "$repo/.git/" || exit 1
;;
esac
done &&
- cd .. &&
- git init -q &&
+ cd "$repo" &&
+ git init -q && {
+ test_have_prereq SYMLINKS ||
+ git config core.symlinks false
+ } &&
mv .git/hooks .git/hooks-disabled 2>/dev/null
) || error "failed to copy repository '$source' to '$repo'"
}
diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh
index f33962b..9372589 100755
--- a/t/t0027-auto-crlf.sh
+++ b/t/t0027-auto-crlf.sh
@@ -12,7 +12,7 @@
compare_files () {
tr '\015\000' QN <"$1" >"$1".expect &&
- tr '\015\000' QN <"$2" >"$2".actual &&
+ tr '\015\000' QN <"$2" | tr -d 'Z' >"$2".actual &&
test_cmp "$1".expect "$2".actual &&
rm "$1".expect "$2".actual
}
@@ -52,14 +52,17 @@
create_NNO_files () {
for crlf in false true input
do
- for attr in "" auto text -text lf crlf
+ for attr in "" auto text -text
do
- pfx=NNO_${crlf}_attr_${attr} &&
- cp CRLF_mix_LF ${pfx}_LF.txt &&
- cp CRLF_mix_LF ${pfx}_CRLF.txt &&
- cp CRLF_mix_LF ${pfx}_CRLF_mix_LF.txt &&
- cp CRLF_mix_LF ${pfx}_LF_mix_CR.txt &&
- cp CRLF_mix_LF ${pfx}_CRLF_nul.txt
+ for aeol in "" lf crlf
+ do
+ pfx=NNO_attr_${attr}_aeol_${aeol}_${crlf}
+ cp CRLF_mix_LF ${pfx}_LF.txt &&
+ cp CRLF_mix_LF ${pfx}_CRLF.txt &&
+ cp CRLF_mix_LF ${pfx}_CRLF_mix_LF.txt &&
+ cp CRLF_mix_LF ${pfx}_LF_mix_CR.txt &&
+ cp CRLF_mix_LF ${pfx}_CRLF_nul.txt
+ done
done
done
}
@@ -100,20 +103,22 @@
}
commit_chk_wrnNNO () {
- crlf=$1
- attr=$2
- lfwarn=$3
- crlfwarn=$4
- lfmixcrlf=$5
- lfmixcr=$6
- crlfnul=$7
- pfx=NNO_${crlf}_attr_${attr}
+ attr=$1 ; shift
+ aeol=$1 ; shift
+ crlf=$1 ; shift
+ lfwarn=$1 ; shift
+ crlfwarn=$1 ; shift
+ lfmixcrlf=$1 ; shift
+ lfmixcr=$1 ; shift
+ crlfnul=$1 ; shift
+ pfx=NNO_attr_${attr}_aeol_${aeol}_${crlf}
#Commit files on top of existing file
- create_gitattributes "$attr" &&
+ create_gitattributes "$attr" $aeol &&
for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
do
fname=${pfx}_$f.txt &&
cp $f $fname &&
+ printf Z >>"$fname" &&
git -c core.autocrlf=$crlf add $fname 2>/dev/null &&
git -c core.autocrlf=$crlf commit -m "commit_$fname" $fname >"${pfx}_$f.err" 2>&1
done
@@ -121,19 +126,19 @@
test_expect_success "commit NNO files crlf=$crlf attr=$attr LF" '
check_warning "$lfwarn" ${pfx}_LF.err
'
- test_expect_success "commit NNO files crlf=$crlf attr=$attr CRLF" '
+ test_expect_success "commit NNO files attr=$attr aeol=$aeol crlf=$crlf CRLF" '
check_warning "$crlfwarn" ${pfx}_CRLF.err
'
- test_expect_success "commit NNO files crlf=$crlf attr=$attr CRLF_mix_LF" '
+ test_expect_success "commit NNO files attr=$attr aeol=$aeol crlf=$crlf CRLF_mix_LF" '
check_warning "$lfmixcrlf" ${pfx}_CRLF_mix_LF.err
'
- test_expect_success "commit NNO files crlf=$crlf attr=$attr LF_mix_cr" '
+ test_expect_success "commit NNO files attr=$attr aeol=$aeol crlf=$crlf LF_mix_cr" '
check_warning "$lfmixcr" ${pfx}_LF_mix_CR.err
'
- test_expect_success "commit NNO files crlf=$crlf attr=$attr CRLF_nul" '
+ test_expect_success "commit NNO files attr=$attr aeol=$aeol crlf=$crlf CRLF_nul" '
check_warning "$crlfnul" ${pfx}_CRLF_nul.err
'
}
@@ -162,6 +167,7 @@
# contruct the attr/ returned by git ls-files --eol
# Take none (=empty), one or two args
+# convert.c: eol=XX overrides text=auto
attr_ascii () {
case $1,$2 in
-text,*) echo "-text" ;;
@@ -169,8 +175,8 @@
text,lf) echo "text eol=lf" ;;
text,crlf) echo "text eol=crlf" ;;
auto,) echo "text=auto" ;;
- auto,lf) echo "text=auto eol=lf" ;;
- auto,crlf) echo "text=auto eol=crlf" ;;
+ auto,lf) echo "text eol=lf" ;;
+ auto,crlf) echo "text eol=crlf" ;;
lf,) echo "text eol=lf" ;;
crlf,) echo "text eol=crlf" ;;
,) echo "" ;;
@@ -195,28 +201,29 @@
}
check_in_repo_NNO () {
- crlf=$1
- attr=$2
- lfname=$3
- crlfname=$4
- lfmixcrlf=$5
- lfmixcr=$6
- crlfnul=$7
- pfx=NNO_${crlf}_attr_${attr}_
- test_expect_success "compare_files $lfname ${pfx}LF.txt" '
- compare_files $lfname ${pfx}LF.txt
+ attr=$1 ; shift
+ aeol=$1 ; shift
+ crlf=$1 ; shift
+ lfname=$1 ; shift
+ crlfname=$1 ; shift
+ lfmixcrlf=$1 ; shift
+ lfmixcr=$1 ; shift
+ crlfnul=$1 ; shift
+ pfx=NNO_attr_${attr}_aeol_${aeol}_${crlf}
+ test_expect_success "compare_files $lfname ${pfx}_LF.txt" '
+ compare_files $lfname ${pfx}_LF.txt
'
- test_expect_success "compare_files $crlfname ${pfx}CRLF.txt" '
- compare_files $crlfname ${pfx}CRLF.txt
+ test_expect_success "compare_files $crlfname ${pfx}_CRLF.txt" '
+ compare_files $crlfname ${pfx}_CRLF.txt
'
- test_expect_success "compare_files $lfmixcrlf ${pfx}CRLF_mix_LF.txt" '
- compare_files $lfmixcrlf ${pfx}CRLF_mix_LF.txt
+ test_expect_success "compare_files $lfmixcrlf ${pfx}_CRLF_mix_LF.txt" '
+ compare_files $lfmixcrlf ${pfx}_CRLF_mix_LF.txt
'
- test_expect_success "compare_files $lfmixcr ${pfx}LF_mix_CR.txt" '
- compare_files $lfmixcr ${pfx}LF_mix_CR.txt
+ test_expect_success "compare_files $lfmixcr ${pfx}_LF_mix_CR.txt" '
+ compare_files $lfmixcr ${pfx}_LF_mix_CR.txt
'
- test_expect_success "compare_files $crlfnul ${pfx}CRLF_nul.txt" '
- compare_files $crlfnul ${pfx}CRLF_nul.txt
+ test_expect_success "compare_files $crlfnul ${pfx}_CRLF_nul.txt" '
+ compare_files $crlfnul ${pfx}_CRLF_nul.txt
'
}
@@ -231,7 +238,7 @@
lfmixcrlf=$1 ; shift
lfmixcr=$1 ; shift
crlfnul=$1 ; shift
- create_gitattributes "$attr" "$ident" &&
+ create_gitattributes "$attr" $ident $aeol &&
git config core.autocrlf $crlf &&
pfx=eol_${ceol}_crlf_${crlf}_attr_${attr}_ &&
for f in LF CRLF LF_mix_CR CRLF_mix_LF LF_nul
@@ -244,7 +251,7 @@
fi
done
- test_expect_success "ls-files --eol attr=$attr $ident $aeol core.autocrlf=$crlf core.eol=$ceol" '
+ test_expect_success "ls-files --eol attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol" '
test_when_finished "rm expect actual" &&
sort <<-EOF >expect &&
i/crlf w/$(stats_ascii $crlfname) attr/$(attr_ascii $attr $aeol) crlf_false_attr__CRLF.txt
@@ -259,19 +266,19 @@
sort >actual &&
test_cmp expect actual
'
- test_expect_success "checkout $ident $attr $aeol core.autocrlf=$crlf core.eol=$ceol file=LF" "
+ test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=LF" "
compare_ws_file $pfx $lfname crlf_false_attr__LF.txt
"
- test_expect_success "checkout $ident $attr $aeol core.autocrlf=$crlf core.eol=$ceol file=CRLF" "
+ test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=CRLF" "
compare_ws_file $pfx $crlfname crlf_false_attr__CRLF.txt
"
- test_expect_success "checkout $ident $attr $aeol core.autocrlf=$crlf core.eol=$ceol file=CRLF_mix_LF" "
+ test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=CRLF_mix_LF" "
compare_ws_file $pfx $lfmixcrlf crlf_false_attr__CRLF_mix_LF.txt
"
- test_expect_success "checkout $ident $attr $aeol core.autocrlf=$crlf core.eol=$ceol file=LF_mix_CR" "
+ test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=LF_mix_CR" "
compare_ws_file $pfx $lfmixcr crlf_false_attr__LF_mix_CR.txt
"
- test_expect_success "checkout $ident $attr $aeol core.autocrlf=$crlf core.eol=$ceol file=LF_nul" "
+ test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=LF_nul" "
compare_ws_file $pfx $crlfnul crlf_false_attr__LF_nul.txt
"
}
@@ -385,31 +392,31 @@
commit_check_warn input "crlf" "LF_CRLF" "" "LF_CRLF" "LF_CRLF" ""
'
-# attr LF CRLF CRLFmixLF LF_mix_CR CRLFNUL
-commit_chk_wrnNNO false "" "" "" "" "" ""
-commit_chk_wrnNNO true "" "LF_CRLF" "" "" "" ""
-commit_chk_wrnNNO input "" "" "" "" "" ""
+# attr LF CRLF CRLFmixLF LF_mix_CR CRLFNUL
+commit_chk_wrnNNO "" "" false "" "" "" "" ""
+commit_chk_wrnNNO "" "" true LF_CRLF "" "" "" ""
+commit_chk_wrnNNO "" "" input "" "" "" "" ""
+commit_chk_wrnNNO "auto" "" false "$WILC" "$WICL" "$WAMIX" "" ""
+commit_chk_wrnNNO "auto" "" true LF_CRLF "" LF_CRLF "" ""
+commit_chk_wrnNNO "auto" "" input "" CRLF_LF CRLF_LF "" ""
-commit_chk_wrnNNO false "auto" "$WILC" "$WICL" "$WAMIX" "" ""
-commit_chk_wrnNNO true "auto" "LF_CRLF" "" "LF_CRLF" "" ""
-commit_chk_wrnNNO input "auto" "" "CRLF_LF" "CRLF_LF" "" ""
+for crlf in true false input
+do
+ commit_chk_wrnNNO -text "" $crlf "" "" "" "" ""
+ commit_chk_wrnNNO -text lf $crlf "" "" "" "" ""
+ commit_chk_wrnNNO -text crlf $crlf "" "" "" "" ""
+ commit_chk_wrnNNO "" lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF
+ commit_chk_wrnNNO "" crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF ""
+ commit_chk_wrnNNO auto lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF
+ commit_chk_wrnNNO auto crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF ""
+ commit_chk_wrnNNO text lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF
+ commit_chk_wrnNNO text crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF ""
+done
-commit_chk_wrnNNO false "text" "$WILC" "$WICL" "$WAMIX" "$WILC" "$WICL"
-commit_chk_wrnNNO true "text" "LF_CRLF" "" "LF_CRLF" "LF_CRLF" ""
-commit_chk_wrnNNO input "text" "" "CRLF_LF" "CRLF_LF" "" "CRLF_LF"
-
-commit_chk_wrnNNO false "-text" "" "" "" "" ""
-commit_chk_wrnNNO true "-text" "" "" "" "" ""
-commit_chk_wrnNNO input "-text" "" "" "" "" ""
-
-commit_chk_wrnNNO false "lf" "" "CRLF_LF" "CRLF_LF" "" "CRLF_LF"
-commit_chk_wrnNNO true "lf" "" "CRLF_LF" "CRLF_LF" "" "CRLF_LF"
-commit_chk_wrnNNO input "lf" "" "CRLF_LF" "CRLF_LF" "" "CRLF_LF"
-
-commit_chk_wrnNNO false "crlf" "LF_CRLF" "" "LF_CRLF" "LF_CRLF" ""
-commit_chk_wrnNNO true "crlf" "LF_CRLF" "" "LF_CRLF" "LF_CRLF" ""
-commit_chk_wrnNNO input "crlf" "LF_CRLF" "" "LF_CRLF" "LF_CRLF" ""
+commit_chk_wrnNNO "text" "" false "$WILC" "$WICL" "$WAMIX" "$WILC" "$WICL"
+commit_chk_wrnNNO "text" "" true LF_CRLF "" LF_CRLF LF_CRLF ""
+commit_chk_wrnNNO "text" "" input "" CRLF_LF CRLF_LF "" CRLF_LF
test_expect_success 'create files cleanup' '
rm -f *.txt &&
@@ -440,24 +447,20 @@
check_files_in_repo input "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
'
-# attr LF CRLF CRLF_mix_LF LF_mix_CR CRLFNUL
-check_in_repo_NNO false "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
-check_in_repo_NNO true "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
-check_in_repo_NNO input "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
-
-check_in_repo_NNO false "auto" LF LF LF LF_mix_CR CRLF_nul
-check_in_repo_NNO true "auto" LF LF LF LF_mix_CR CRLF_nul
-check_in_repo_NNO input "auto" LF LF LF LF_mix_CR CRLF_nul
-
-check_in_repo_NNO false "text" LF LF LF LF_mix_CR LF_nul
-check_in_repo_NNO true "text" LF LF LF LF_mix_CR LF_nul
-check_in_repo_NNO input "text" LF LF LF LF_mix_CR LF_nul
-
-check_in_repo_NNO false "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
-check_in_repo_NNO true "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
-check_in_repo_NNO input "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
-
-
+for crlf in true false input
+do
+ # attr aeol LF CRLF CRLF_mix_LF LF_mix_CR CRLFNUL
+ check_in_repo_NNO "" "" $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+ check_in_repo_NNO -text "" $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+ check_in_repo_NNO -text lf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+ check_in_repo_NNO -text crlf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+ check_in_repo_NNO auto "" $crlf LF LF LF LF_mix_CR CRLF_nul
+ check_in_repo_NNO auto lf $crlf LF LF LF LF_mix_CR LF_nul
+ check_in_repo_NNO auto crlf $crlf LF LF LF LF_mix_CR LF_nul
+ check_in_repo_NNO text "" $crlf LF LF LF LF_mix_CR LF_nul
+ check_in_repo_NNO text lf $crlf LF LF LF LF_mix_CR LF_nul
+ check_in_repo_NNO text crlf $crlf LF LF LF LF_mix_CR LF_nul
+done
################################################################################
# Check how files in the repo are changed when they are checked out
# How to read the table below:
@@ -489,89 +492,47 @@
fi
export CRLF_MIX_LF_CR MIX NL
-checkout_files "" "" "" false "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" "" "" false crlf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" "" "" false lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" "" "" false native LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" "" "" input "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" "" "" input lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" "" "" true "" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" "" "" true crlf CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" "" "" true lf CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" "" "" true native CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" false "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" false crlf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" false lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" false native LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" input "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" input lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" true "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" true crlf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" true lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "" ident "" true native LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" "" "" false "" $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul
-checkout_files "auto" "" "" false crlf CRLF CRLF CRLF LF_mix_CR LF_nul
-checkout_files "auto" "" "" false lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" "" "" false native $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul
-checkout_files "auto" "" "" input "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" "" "" input lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" "" "" true "" CRLF CRLF CRLF LF_mix_CR LF_nul
-checkout_files "auto" "" "" true crlf CRLF CRLF CRLF LF_mix_CR LF_nul
-checkout_files "auto" "" "" true lf CRLF CRLF CRLF LF_mix_CR LF_nul
-checkout_files "auto" "" "" true native CRLF CRLF CRLF LF_mix_CR LF_nul
-checkout_files "auto" ident "" false "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" ident "" false crlf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" ident "" false lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" ident "" false native LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" ident "" input "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" ident "" input lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" ident "" true "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" ident "" true crlf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" ident "" true lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-checkout_files "auto" ident "" true native LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
-
-for id in "" ident;
+# Same handling with and without ident
+for id in "" ident
do
- checkout_files "crlf" "$id" "" false "" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "crlf" "$id" "" false crlf CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "crlf" "$id" "" false lf CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "crlf" "$id" "" false native CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "crlf" "$id" "" input "" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "crlf" "$id" "" input lf CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "crlf" "$id" "" true "" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "crlf" "$id" "" true crlf CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "crlf" "$id" "" true lf CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "crlf" "$id" "" true native CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "lf" "$id" "" false "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "lf" "$id" "" false crlf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "lf" "$id" "" false lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "lf" "$id" "" false native LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "lf" "$id" "" input "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "lf" "$id" "" input lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "lf" "$id" "" true "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "lf" "$id" "" true crlf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "lf" "$id" "" true lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "lf" "$id" "" true native LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "text" "$id" "" false "" $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL
- checkout_files "text" "$id" "" false crlf CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "text" "$id" "" false lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "text" "$id" "" false native $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL
- checkout_files "text" "$id" "" input "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "text" "$id" "" input lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "text" "$id" "" true "" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "text" "$id" "" true crlf CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "text" "$id" "" true lf CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "text" "$id" "" true native CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
- checkout_files "-text" "$id" "" false "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "-text" "$id" "" false crlf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "-text" "$id" "" false lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "-text" "$id" "" false native LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "-text" "$id" "" input "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "-text" "$id" "" input lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "-text" "$id" "" true "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "-text" "$id" "" true crlf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "-text" "$id" "" true lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
- checkout_files "-text" "$id" "" true native LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ for ceol in lf crlf native
+ do
+ for crlf in true false input
+ do
+ # -text overrides core.autocrlf and core.eol
+ # text and eol=crlf or eol=lf override core.autocrlf and core.eol
+ checkout_files -text "$id" "" "$crlf" "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ checkout_files -text "$id" "lf" "$crlf" "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ checkout_files -text "$id" "crlf" "$crlf" "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ # text
+ checkout_files text "$id" "lf" "$crlf" "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ checkout_files text "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+ # currently the same as text, eol=XXX
+ checkout_files auto "$id" "lf" "$crlf" "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ checkout_files auto "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+ done
+
+ # core.autocrlf false, different core.eol
+ checkout_files "" "$id" "" false "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ # core.autocrlf true
+ checkout_files "" "$id" "" true "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ # text: core.autocrlf = true overrides core.eol
+ checkout_files auto "$id" "" true "$ceol" CRLF CRLF CRLF LF_mix_CR LF_nul
+ checkout_files text "$id" "" true "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+ # text: core.autocrlf = input overrides core.eol
+ checkout_files text "$id" "" input "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ checkout_files auto "$id" "" input "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ # text=auto + eol=XXX
+ done
+ # text: core.autocrlf=false uses core.eol
+ checkout_files text "$id" "" false crlf CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+ checkout_files text "$id" "" false lf LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ # text: core.autocrlf=false and core.eol unset(or native) uses native eol
+ checkout_files text "$id" "" false "" $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL
+ checkout_files text "$id" "" false native $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL
+ # auto: core.autocrlf=false and core.eol unset(or native) uses native eol
+ checkout_files auto "$id" "" false "" $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul
+ checkout_files auto "$id" "" false native $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul
done
# Should be the last test case: remove some files from the worktree
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 9be6411..db5f60d 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -7,7 +7,7 @@
. ./test-lib.sh
-cat > expect << EOF
+cat >expect <<\EOF
usage: test-parse-options <options>
--yes get a boolean
@@ -45,63 +45,24 @@
-v, --verbose be verbose
-n, --dry-run dry run
-q, --quiet be quiet
+ --expect <string> expected output in the variable dump
EOF
test_expect_success 'test help' '
- test_must_fail test-parse-options -h > output 2> output.err &&
+ test_must_fail test-parse-options -h >output 2>output.err &&
test_must_be_empty output.err &&
test_i18ncmp expect output
'
mv expect expect.err
-cat >expect.template <<EOF
-boolean: 0
-integer: 0
-magnitude: 0
-timestamp: 0
-string: (not set)
-abbrev: 7
-verbose: 0
-quiet: no
-dry run: no
-file: (not set)
-EOF
-
-check() {
+check () {
what="$1" &&
shift &&
expect="$1" &&
shift &&
- sed "s/^$what .*/$what $expect/" <expect.template >expect &&
- test-parse-options $* >output 2>output.err &&
- test_must_be_empty output.err &&
- test_cmp expect output
-}
-
-check_i18n() {
- what="$1" &&
- shift &&
- expect="$1" &&
- shift &&
- sed "s/^$what .*/$what $expect/" <expect.template >expect &&
- test-parse-options $* >output 2>output.err &&
- test_must_be_empty output.err &&
- test_i18ncmp expect output
-}
-
-check_unknown() {
- case "$1" in
- --*)
- echo error: unknown option \`${1#--}\' >expect ;;
- -*)
- echo error: unknown switch \`${1#-}\' >expect ;;
- esac &&
- cat expect.err >>expect &&
- test_must_fail test-parse-options $* >output 2>output.err &&
- test_must_be_empty output &&
- test_cmp expect output.err
+ test-parse-options --expect="$what $expect" "$@"
}
check_unknown_i18n() {
@@ -156,7 +117,7 @@
check magnitude: 3221225472 -m 3g
'
-cat > expect << EOF
+cat >expect <<\EOF
boolean: 2
integer: 1729
magnitude: 16384
@@ -164,7 +125,7 @@
string: 123
abbrev: 7
verbose: 2
-quiet: no
+quiet: 0
dry run: yes
file: prefix/my.file
EOF
@@ -176,7 +137,7 @@
test_must_be_empty output.err
'
-cat > expect << EOF
+cat >expect <<\EOF
boolean: 2
integer: 1729
magnitude: 16384
@@ -184,7 +145,7 @@
string: 321
abbrev: 10
verbose: 2
-quiet: no
+quiet: 0
dry run: no
file: prefix/fi.le
EOF
@@ -204,15 +165,15 @@
test_expect_code 129 test-parse-options --file
'
-cat > expect << EOF
+cat >expect <<\EOF
boolean: 1
integer: 13
magnitude: 0
timestamp: 0
string: 123
abbrev: 7
-verbose: 0
-quiet: no
+verbose: -1
+quiet: 0
dry run: no
file: (not set)
arg 00: a1
@@ -222,32 +183,32 @@
test_expect_success 'intermingled arguments' '
test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
- > output 2> output.err &&
+ >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
-cat > expect << EOF
+cat >expect <<\EOF
boolean: 0
integer: 2
magnitude: 0
timestamp: 0
string: (not set)
abbrev: 7
-verbose: 0
-quiet: no
+verbose: -1
+quiet: 0
dry run: no
file: (not set)
EOF
test_expect_success 'unambiguously abbreviated option' '
- test-parse-options --int 2 --boolean --no-bo > output 2> output.err &&
+ test-parse-options --int 2 --boolean --no-bo >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
test_expect_success 'unambiguously abbreviated option with "="' '
- test-parse-options --int=2 > output 2> output.err &&
+ test-parse-options --int=2 >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
@@ -256,74 +217,74 @@
test_expect_code 129 test-parse-options --strin 123
'
-cat > expect << EOF
+cat >expect <<\EOF
boolean: 0
integer: 0
magnitude: 0
timestamp: 0
string: 123
abbrev: 7
-verbose: 0
-quiet: no
+verbose: -1
+quiet: 0
dry run: no
file: (not set)
EOF
test_expect_success 'non ambiguous option (after two options it abbreviates)' '
- test-parse-options --st 123 > output 2> output.err &&
+ test-parse-options --st 123 >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
-cat > typo.err << EOF
-error: did you mean \`--boolean\` (with two dashes ?)
+cat >typo.err <<\EOF
+error: did you mean `--boolean` (with two dashes ?)
EOF
test_expect_success 'detect possible typos' '
- test_must_fail test-parse-options -boolean > output 2> output.err &&
+ test_must_fail test-parse-options -boolean >output 2>output.err &&
test_must_be_empty output &&
test_cmp typo.err output.err
'
-cat > typo.err << EOF
-error: did you mean \`--ambiguous\` (with two dashes ?)
+cat >typo.err <<\EOF
+error: did you mean `--ambiguous` (with two dashes ?)
EOF
test_expect_success 'detect possible typos' '
- test_must_fail test-parse-options -ambiguous > output 2> output.err &&
+ test_must_fail test-parse-options -ambiguous >output 2>output.err &&
test_must_be_empty output &&
test_cmp typo.err output.err
'
-cat > expect <<EOF
+cat >expect <<\EOF
boolean: 0
integer: 0
magnitude: 0
timestamp: 0
string: (not set)
abbrev: 7
-verbose: 0
-quiet: no
+verbose: -1
+quiet: 0
dry run: no
file: (not set)
arg 00: --quux
EOF
test_expect_success 'keep some options as arguments' '
- test-parse-options --quux > output 2> output.err &&
+ test-parse-options --quux >output 2>output.err &&
test_must_be_empty output.err &&
- test_cmp expect output
+ test_cmp expect output
'
-cat > expect <<EOF
+cat >expect <<\EOF
boolean: 0
integer: 0
magnitude: 0
timestamp: 1
string: (not set)
abbrev: 7
-verbose: 0
-quiet: yes
+verbose: -1
+quiet: 1
dry run: no
file: (not set)
arg 00: foo
@@ -331,12 +292,12 @@
test_expect_success 'OPT_DATE() works' '
test-parse-options -t "1970-01-01 00:00:01 +0000" \
- foo -q > output 2> output.err &&
+ foo -q >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
-cat > expect <<EOF
+cat >expect <<\EOF
Callback: "four", 0
boolean: 5
integer: 4
@@ -344,112 +305,110 @@
timestamp: 0
string: (not set)
abbrev: 7
-verbose: 0
-quiet: no
+verbose: -1
+quiet: 0
dry run: no
file: (not set)
EOF
test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
- test-parse-options --length=four -b -4 > output 2> output.err &&
+ test-parse-options --length=four -b -4 >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
-cat > expect <<EOF
-Callback: "not set", 1
-EOF
+>expect
test_expect_success 'OPT_CALLBACK() and callback errors work' '
- test_must_fail test-parse-options --no-length > output 2> output.err &&
+ test_must_fail test-parse-options --no-length >output 2>output.err &&
test_i18ncmp expect output &&
test_i18ncmp expect.err output.err
'
-cat > expect <<EOF
+cat >expect <<\EOF
boolean: 1
integer: 23
magnitude: 0
timestamp: 0
string: (not set)
abbrev: 7
-verbose: 0
-quiet: no
+verbose: -1
+quiet: 0
dry run: no
file: (not set)
EOF
test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
- test-parse-options --set23 -bbbbb --no-or4 > output 2> output.err &&
+ test-parse-options --set23 -bbbbb --no-or4 >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
- test-parse-options --set23 -bbbbb --neg-or4 > output 2> output.err &&
+ test-parse-options --set23 -bbbbb --neg-or4 >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
-cat > expect <<EOF
+cat >expect <<\EOF
boolean: 6
integer: 0
magnitude: 0
timestamp: 0
string: (not set)
abbrev: 7
-verbose: 0
-quiet: no
+verbose: -1
+quiet: 0
dry run: no
file: (not set)
EOF
test_expect_success 'OPT_BIT() works' '
- test-parse-options -bb --or4 > output 2> output.err &&
+ test-parse-options -bb --or4 >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
test_expect_success 'OPT_NEGBIT() works' '
- test-parse-options -bb --no-neg-or4 > output 2> output.err &&
+ test-parse-options -bb --no-neg-or4 >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
- test-parse-options + + + + + + > output 2> output.err &&
+ test-parse-options + + + + + + >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
-cat > expect <<EOF
+cat >expect <<\EOF
boolean: 0
integer: 12345
magnitude: 0
timestamp: 0
string: (not set)
abbrev: 7
-verbose: 0
-quiet: no
+verbose: -1
+quiet: 0
dry run: no
file: (not set)
EOF
test_expect_success 'OPT_NUMBER_CALLBACK() works' '
- test-parse-options -12345 > output 2> output.err &&
+ test-parse-options -12345 >output 2>output.err &&
test_must_be_empty output.err &&
test_cmp expect output
'
-cat >expect <<EOF
+cat >expect <<\EOF
boolean: 0
integer: 0
magnitude: 0
timestamp: 0
string: (not set)
abbrev: 7
-verbose: 0
-quiet: no
+verbose: -1
+quiet: 0
dry run: no
file: (not set)
EOF
@@ -460,7 +419,7 @@
test_cmp expect output
'
-cat >>expect <<'EOF'
+cat >>expect <<\EOF
list: foo
list: bar
list: baz
@@ -476,4 +435,118 @@
test_cmp expect output
'
+cat >expect <<\EOF
+boolean: 0
+integer: 0
+magnitude: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: -1
+quiet: 3
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success 'multiple quiet levels' '
+ test-parse-options -q -q -q >output 2>output.err &&
+ test_must_be_empty output.err &&
+ test_cmp expect output
+'
+
+cat >expect <<\EOF
+boolean: 0
+integer: 0
+magnitude: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 3
+quiet: 0
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success 'multiple verbose levels' '
+ test-parse-options -v -v -v >output 2>output.err &&
+ test_must_be_empty output.err &&
+ test_cmp expect output
+'
+
+cat >expect <<\EOF
+boolean: 0
+integer: 0
+magnitude: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: -1
+quiet: 0
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success '--no-quiet sets --quiet to 0' '
+ test-parse-options --no-quiet >output 2>output.err &&
+ test_must_be_empty output.err &&
+ test_cmp expect output
+'
+
+cat >expect <<\EOF
+boolean: 0
+integer: 0
+magnitude: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: -1
+quiet: 0
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success '--no-quiet resets multiple -q to 0' '
+ test-parse-options -q -q -q --no-quiet >output 2>output.err &&
+ test_must_be_empty output.err &&
+ test_cmp expect output
+'
+
+cat >expect <<\EOF
+boolean: 0
+integer: 0
+magnitude: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: 0
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success '--no-verbose sets verbose to 0' '
+ test-parse-options --no-verbose >output 2>output.err &&
+ test_must_be_empty output.err &&
+ test_cmp expect output
+'
+
+cat >expect <<\EOF
+boolean: 0
+integer: 0
+magnitude: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: 0
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success '--no-verbose resets multiple verbose to 0' '
+ test-parse-options -v -v -v --no-verbose >output 2>output.err &&
+ test_must_be_empty output.err &&
+ test_cmp expect output
+'
+
test_done
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index 3acb992..3a22fc5 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -4,6 +4,8 @@
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
test_expect_success 'setup' '
test_commit init
'
@@ -225,4 +227,61 @@
test_cmp init.t swamp2/init.t
'
+test_expect_success 'put a worktree under rebase' '
+ git worktree add under-rebase &&
+ (
+ cd under-rebase &&
+ set_fake_editor &&
+ FAKE_LINES="edit 1" git rebase -i HEAD^ &&
+ git worktree list | grep "under-rebase.*detached HEAD"
+ )
+'
+
+test_expect_success 'add a worktree, checking out a rebased branch' '
+ test_must_fail git worktree add new-rebase under-rebase &&
+ ! test -d new-rebase
+'
+
+test_expect_success 'checking out a rebased branch from another worktree' '
+ git worktree add new-place &&
+ test_must_fail git -C new-place checkout under-rebase
+'
+
+test_expect_success 'not allow to delete a branch under rebase' '
+ (
+ cd under-rebase &&
+ test_must_fail git branch -D under-rebase
+ )
+'
+
+test_expect_success 'rename a branch under rebase not allowed' '
+ test_must_fail git branch -M under-rebase rebase-with-new-name
+'
+
+test_expect_success 'check out from current worktree branch ok' '
+ (
+ cd under-rebase &&
+ git checkout under-rebase &&
+ git checkout - &&
+ git rebase --abort
+ )
+'
+
+test_expect_success 'checkout a branch under bisect' '
+ git worktree add under-bisect &&
+ (
+ cd under-bisect &&
+ git bisect start &&
+ git bisect bad &&
+ git bisect good HEAD~2 &&
+ git worktree list | grep "under-bisect.*detached HEAD" &&
+ test_must_fail git worktree add new-bisect under-bisect &&
+ ! test -d new-bisect
+ )
+'
+
+test_expect_success 'rename a branch under bisect not allowed' '
+ test_must_fail git branch -M under-bisect bisect-with-new-name
+'
+
test_done
diff --git a/t/t3419-rebase-patch-id.sh b/t/t3419-rebase-patch-id.sh
index 217dd79..49f548c 100755
--- a/t/t3419-rebase-patch-id.sh
+++ b/t/t3419-rebase-patch-id.sh
@@ -73,17 +73,17 @@
run git format-patch --stdout --ignore-if-in-upstream master
"
- test_expect_success $pr 'detect upstream patch' "
+ test_expect_success $pr 'detect upstream patch' '
git checkout -q master &&
scramble file &&
git add file &&
- git commit -q -m 'change big file again' &&
+ git commit -q -m "change big file again" &&
git checkout -q other^{} &&
git rebase master &&
- test_must_fail test -n \"\$(git rev-list master...HEAD~)\"
- "
+ test_must_fail test -n "$(git rev-list master...HEAD~)"
+ '
- test_expect_success $pr 'do not drop patch' "
+ test_expect_success $pr 'do not drop patch' '
git branch -f squashed master &&
git checkout -q -f squashed &&
git reset -q --soft HEAD~2 &&
@@ -91,7 +91,7 @@
git checkout -q other^{} &&
test_must_fail git rebase squashed &&
rm -rf .git/rebase-apply
- "
+ '
}
do_tests 500
diff --git a/t/t3910-mac-os-precompose.sh b/t/t3910-mac-os-precompose.sh
index 8319356..26dd5b7 100755
--- a/t/t3910-mac-os-precompose.sh
+++ b/t/t3910-mac-os-precompose.sh
@@ -49,12 +49,54 @@
test_expect_success "setup case mac" '
git checkout -b mac_os
'
+# This will test nfd2nfc in git diff
+test_expect_success "git diff f.Adiar" '
+ touch f.$Adiarnfc &&
+ git add f.$Adiarnfc &&
+ echo f.Adiarnfc >f.$Adiarnfc &&
+ git diff f.$Adiarnfd >expect &&
+ git diff f.$Adiarnfc >actual &&
+ test_cmp expect actual &&
+ git reset HEAD f.Adiarnfc &&
+ rm f.$Adiarnfc expect actual
+'
+# This will test nfd2nfc in git diff-files
+test_expect_success "git diff-files f.Adiar" '
+ touch f.$Adiarnfc &&
+ git add f.$Adiarnfc &&
+ echo f.Adiarnfc >f.$Adiarnfc &&
+ git diff-files f.$Adiarnfd >expect &&
+ git diff-files f.$Adiarnfc >actual &&
+ test_cmp expect actual &&
+ git reset HEAD f.Adiarnfc &&
+ rm f.$Adiarnfc expect actual
+'
+# This will test nfd2nfc in git diff-index
+test_expect_success "git diff-index f.Adiar" '
+ touch f.$Adiarnfc &&
+ git add f.$Adiarnfc &&
+ echo f.Adiarnfc >f.$Adiarnfc &&
+ git diff-index HEAD f.$Adiarnfd >expect &&
+ git diff-index HEAD f.$Adiarnfc >actual &&
+ test_cmp expect actual &&
+ git reset HEAD f.Adiarnfc &&
+ rm f.$Adiarnfc expect actual
+'
# This will test nfd2nfc in readdir()
test_expect_success "add file Adiarnfc" '
echo f.Adiarnfc >f.$Adiarnfc &&
git add f.$Adiarnfc &&
git commit -m "add f.$Adiarnfc"
'
+# This will test nfd2nfc in git diff-tree
+test_expect_success "git diff-tree f.Adiar" '
+ echo f.Adiarnfc >>f.$Adiarnfc &&
+ git diff-tree HEAD f.$Adiarnfd >expect &&
+ git diff-tree HEAD f.$Adiarnfc >actual &&
+ test_cmp expect actual &&
+ git checkout f.$Adiarnfc &&
+ rm expect actual
+'
# This will test nfd2nfc in git stage()
test_expect_success "stage file d.Adiarnfd/f.Adiarnfd" '
mkdir d.$Adiarnfd &&
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index eed2981..8049cad 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -1460,4 +1460,109 @@
test_path_is_dir patchset
'
+test_expect_success 'format-patch --base' '
+ git checkout side &&
+ git format-patch --stdout --base=HEAD~3 -1 >patch &&
+ grep "^base-commit:" patch >actual &&
+ grep "^prerequisite-patch-id:" patch >>actual &&
+ echo "base-commit: $(git rev-parse HEAD~3)" >expected &&
+ echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
+ echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'format-patch --base errors out when base commit is in revision list' '
+ test_must_fail git format-patch --base=HEAD -2 &&
+ test_must_fail git format-patch --base=HEAD~1 -2 &&
+ git format-patch --stdout --base=HEAD~2 -2 >patch &&
+ grep "^base-commit:" patch >actual &&
+ echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
+ # For history as below:
+ #
+ # ---Q---P---Z---Y---*---X
+ # \ /
+ # ------------W
+ #
+ # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
+ git checkout -b topic1 master &&
+ git rev-parse HEAD >commit-id-base &&
+ test_commit P &&
+ git rev-parse HEAD >commit-id-P &&
+ test_commit Z &&
+ git rev-parse HEAD >commit-id-Z &&
+ test_commit Y &&
+ git checkout -b topic2 master &&
+ test_commit W &&
+ git merge topic1 &&
+ test_commit X &&
+ test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
+ test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
+ git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
+ grep "^base-commit:" patch >actual &&
+ echo "base-commit: $(cat commit-id-base)" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'format-patch --base=auto' '
+ git checkout -b upstream master &&
+ git checkout -b local upstream &&
+ git branch --set-upstream-to=upstream &&
+ test_commit N1 &&
+ test_commit N2 &&
+ git format-patch --stdout --base=auto -2 >patch &&
+ grep "^base-commit:" patch >actual &&
+ echo "base-commit: $(git rev-parse upstream)" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'format-patch errors out when history involves criss-cross' '
+ # setup criss-cross history
+ #
+ # B---M1---D
+ # / \ /
+ # A X
+ # \ / \
+ # C---M2---E
+ #
+ git checkout master &&
+ test_commit A &&
+ git checkout -b xb master &&
+ test_commit B &&
+ git checkout -b xc master &&
+ test_commit C &&
+ git checkout -b xbc xb -- &&
+ git merge xc &&
+ git checkout -b xcb xc -- &&
+ git branch --set-upstream-to=xbc &&
+ git merge xb &&
+ git checkout xbc &&
+ test_commit D &&
+ git checkout xcb &&
+ test_commit E &&
+ test_must_fail git format-patch --base=auto -1
+'
+
+test_expect_success 'format-patch format.useAutoBaseoption' '
+ test_when_finished "git config --unset format.useAutoBase" &&
+ git checkout local &&
+ git config format.useAutoBase true &&
+ git format-patch --stdout -1 >patch &&
+ grep "^base-commit:" patch >actual &&
+ echo "base-commit: $(git rev-parse upstream)" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'format-patch --base overrides format.useAutoBase' '
+ test_when_finished "git config --unset format.useAutoBase" &&
+ git config format.useAutoBase true &&
+ git format-patch --stdout --base=HEAD~1 -1 >patch &&
+ grep "^base-commit:" patch >actual &&
+ echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index 900f7de..d84897a 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -607,4 +607,24 @@
test_cmp expected actual
'
+test_expect_success '--dry-run with conflicts fixed from a merge' '
+ # setup two branches with conflicting information
+ # in the same file, resolve the conflict,
+ # call commit with --dry-run
+ echo "Initial contents, unimportant" >test-file &&
+ git add test-file &&
+ git commit -m "Initial commit" &&
+ echo "commit-1-state" >test-file &&
+ git commit -m "commit 1" -i test-file &&
+ git tag commit-1 &&
+ git checkout -b branch-2 HEAD^1 &&
+ echo "commit-2-state" >test-file &&
+ git commit -m "commit 2" -i test-file &&
+ ! $(git merge --no-commit commit-1) &&
+ echo "commit-2-state" >test-file &&
+ git add test-file &&
+ git commit --dry-run &&
+ git commit -m "conflicts fixed from merge."
+'
+
test_done
diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh
index 2ddf28c..ed2653d 100755
--- a/t/t7507-commit-verbose.sh
+++ b/t/t7507-commit-verbose.sh
@@ -3,11 +3,10 @@
test_description='verbose commit template'
. ./test-lib.sh
-cat >check-for-diff <<EOF
-#!$SHELL_PATH
-exec grep '^diff --git' "\$1"
+write_script "check-for-diff" <<\EOF &&
+grep '^diff --git' "$1" >out
+exit 0
EOF
-chmod +x check-for-diff
test_set_editor "$PWD/check-for-diff"
cat >message <<'EOF'
@@ -23,7 +22,8 @@
'
test_expect_success 'initial commit shows verbose diff' '
- git commit --amend -v
+ git commit --amend -v &&
+ test_line_count = 1 out
'
test_expect_success 'second commit' '
@@ -39,13 +39,15 @@
test_expect_success 'verbose diff is stripped out' '
git commit --amend -v &&
- check_message message
+ check_message message &&
+ test_line_count = 1 out
'
test_expect_success 'verbose diff is stripped out (mnemonicprefix)' '
git config diff.mnemonicprefix true &&
git commit --amend -v &&
- check_message message
+ check_message message &&
+ test_line_count = 1 out
'
cat >diff <<'EOF'
@@ -96,4 +98,60 @@
test_i18ngrep "Aborting commit due to empty commit message." err
'
+test_expect_success 'status does not verbose without --verbose' '
+ git status >actual &&
+ ! grep "^diff --git" actual
+'
+
+test_expect_success 'setup -v -v' '
+ echo dirty >file
+'
+
+for i in true 1
+do
+ test_expect_success "commit.verbose=$i and --verbose omitted" "
+ git -c commit.verbose=$i commit --amend &&
+ test_line_count = 1 out
+ "
+done
+
+for i in false -2 -1 0
+do
+ test_expect_success "commit.verbose=$i and --verbose omitted" "
+ git -c commit.verbose=$i commit --amend &&
+ test_line_count = 0 out
+ "
+done
+
+for i in 2 3
+do
+ test_expect_success "commit.verbose=$i and --verbose omitted" "
+ git -c commit.verbose=$i commit --amend &&
+ test_line_count = 2 out
+ "
+done
+
+for i in true false -2 -1 0 1 2 3
+do
+ test_expect_success "commit.verbose=$i and --verbose" "
+ git -c commit.verbose=$i commit --amend --verbose &&
+ test_line_count = 1 out
+ "
+
+ test_expect_success "commit.verbose=$i and --no-verbose" "
+ git -c commit.verbose=$i commit --amend --no-verbose &&
+ test_line_count = 0 out
+ "
+
+ test_expect_success "commit.verbose=$i and -v -v" "
+ git -c commit.verbose=$i commit --amend -v -v &&
+ test_line_count = 2 out
+ "
+done
+
+test_expect_success "status ignores commit.verbose=true" '
+ git -c commit.verbose=true status >actual &&
+ ! grep "^diff --git actual"
+'
+
test_done
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index ff7a9e9..7ce4cd7 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -419,6 +419,29 @@
grep file2 output
'
+run_dir_diff_test 'difftool --dir-diff with unmerged files' '
+ test_when_finished git reset --hard &&
+ test_config difftool.echo.cmd "echo ok" &&
+ git checkout -B conflict-a &&
+ git checkout -B conflict-b &&
+ git checkout conflict-a &&
+ echo a >>file &&
+ git add file &&
+ git commit -m conflict-a &&
+ git checkout conflict-b &&
+ echo b >>file &&
+ git add file &&
+ git commit -m conflict-b &&
+ git checkout master &&
+ git merge conflict-a &&
+ test_must_fail git merge conflict-b &&
+ cat >expect <<-EOF &&
+ ok
+ EOF
+ git difftool --dir-diff $symlinks -t echo >actual &&
+ test_cmp expect actual
+'
+
write_script .git/CHECK_SYMLINKS <<\EOF
for f in file file2 sub/sub
do
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index 22d8367..28082b1 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -45,13 +45,13 @@
name='try a deep --rmdir with a commit'
test_expect_success "$name" '
- git checkout -f -b mybranch ${remotes_git_svn} &&
+ git checkout -f -b mybranch remotes/git-svn &&
mv dir/a/b/c/d/e/file dir/file &&
cp dir/file file &&
git update-index --add --remove dir/a/b/c/d/e/file dir/file file &&
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch &&
+ remotes/git-svn..mybranch &&
svn_cmd up "$SVN_TREE" &&
test -d "$SVN_TREE"/dir && test ! -d "$SVN_TREE"/dir/a'
@@ -65,14 +65,14 @@
git update-index --add dir/file/file &&
git commit -m '$name' &&
test_must_fail git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch
+ remotes/git-svn..mybranch
"
name='detect node change from directory to file #1'
test_expect_success "$name" '
rm -rf dir "$GIT_DIR"/index &&
- git checkout -f -b mybranch2 ${remotes_git_svn} &&
+ git checkout -f -b mybranch2 remotes/git-svn &&
mv bar/zzz zzz &&
rm -rf bar &&
mv zzz bar &&
@@ -80,14 +80,14 @@
git update-index --add -- bar &&
git commit -m "$name" &&
test_must_fail git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch2
+ remotes/git-svn..mybranch2
'
name='detect node change from file to directory #2'
test_expect_success "$name" '
rm -f "$GIT_DIR"/index &&
- git checkout -f -b mybranch3 ${remotes_git_svn} &&
+ git checkout -f -b mybranch3 remotes/git-svn &&
rm bar/zzz &&
git update-index --remove bar/zzz &&
mkdir bar/zzz &&
@@ -95,7 +95,7 @@
git update-index --add bar/zzz/yyy &&
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch3 &&
+ remotes/git-svn..mybranch3 &&
svn_cmd up "$SVN_TREE" &&
test -d "$SVN_TREE"/bar/zzz &&
test -e "$SVN_TREE"/bar/zzz/yyy
@@ -104,7 +104,7 @@
name='detect node change from directory to file #2'
test_expect_success "$name" '
rm -f "$GIT_DIR"/index &&
- git checkout -f -b mybranch4 ${remotes_git_svn} &&
+ git checkout -f -b mybranch4 remotes/git-svn &&
rm -rf dir &&
git update-index --remove -- dir/file &&
touch dir &&
@@ -112,19 +112,19 @@
git update-index --add -- dir &&
git commit -m "$name" &&
test_must_fail git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch4
+ remotes/git-svn..mybranch4
'
name='remove executable bit from a file'
test_expect_success POSIXPERM "$name" '
rm -f "$GIT_DIR"/index &&
- git checkout -f -b mybranch5 ${remotes_git_svn} &&
+ git checkout -f -b mybranch5 remotes/git-svn &&
chmod -x exec.sh &&
git update-index exec.sh &&
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch5 &&
+ remotes/git-svn..mybranch5 &&
svn_cmd up "$SVN_TREE" &&
test ! -x "$SVN_TREE"/exec.sh'
@@ -135,7 +135,7 @@
git update-index exec.sh &&
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch5 &&
+ remotes/git-svn..mybranch5 &&
svn_cmd up "$SVN_TREE" &&
test -x "$SVN_TREE"/exec.sh'
@@ -147,7 +147,7 @@
git update-index exec.sh &&
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch5 &&
+ remotes/git-svn..mybranch5 &&
svn_cmd up "$SVN_TREE" &&
test -h "$SVN_TREE"/exec.sh'
@@ -159,7 +159,7 @@
git update-index --add file exec-2.sh &&
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch5 &&
+ remotes/git-svn..mybranch5 &&
svn_cmd up "$SVN_TREE" &&
test -x "$SVN_TREE"/file &&
test -h "$SVN_TREE"/exec-2.sh'
@@ -172,7 +172,7 @@
git update-index exec-2.sh &&
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
- ${remotes_git_svn}..mybranch5 &&
+ remotes/git-svn..mybranch5 &&
svn_cmd up "$SVN_TREE" &&
test -f "$SVN_TREE"/exec-2.sh &&
test ! -h "$SVN_TREE"/exec-2.sh &&
@@ -194,7 +194,7 @@
export GIT_SVN_ID
test_expect_success "$name" \
'git svn init "$svnrepo" && git svn fetch &&
- git rev-list --pretty=raw ${remotes_git_svn} | grep ^tree | uniq > a &&
+ git rev-list --pretty=raw remotes/git-svn | grep ^tree | uniq > a &&
git rev-list --pretty=raw remotes/alt | grep ^tree | uniq > b &&
test_cmp a b'
@@ -217,17 +217,17 @@
test_expect_success POSIXPERM,SYMLINKS "$name" "test_cmp a expected"
-test_expect_success 'exit if remote refs are ambigious' "
+test_expect_success 'exit if remote refs are ambigious' '
git config --add svn-remote.svn.fetch \
- bar:refs/${remotes_git_svn} &&
+ bar:refs/remotes/git-svn &&
test_must_fail git svn migrate
-"
+'
test_expect_success 'exit if init-ing a would clobber a URL' '
svnadmin create "${PWD}/svnrepo2" &&
svn mkdir -m "mkdir bar" "${svnrepo}2/bar" &&
git config --unset svn-remote.svn.fetch \
- "^bar:refs/${remotes_git_svn}$" &&
+ "^bar:refs/remotes/git-svn$" &&
test_must_fail git svn init "${svnrepo}2/bar"
'
@@ -237,7 +237,7 @@
git config --get svn-remote.svn.fetch \
"^bar:refs/remotes/bar$" &&
git config --get svn-remote.svn.fetch \
- "^:refs/${remotes_git_svn}$"
+ "^:refs/remotes/git-svn$"
'
test_expect_success 'dcommit $rev does not clobber current branch' '
@@ -259,26 +259,26 @@
git branch -D my-bar
'
-test_expect_success 'able to dcommit to a subdirectory' "
+test_expect_success 'able to dcommit to a subdirectory' '
git svn fetch -i bar &&
git checkout -b my-bar refs/remotes/bar &&
echo abc > d &&
git update-index --add d &&
- git commit -m '/bar/d should be in the log' &&
+ git commit -m "/bar/d should be in the log" &&
git svn dcommit -i bar &&
- test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" &&
+ test -z "$(git diff refs/heads/my-bar refs/remotes/bar)" &&
mkdir newdir &&
echo new > newdir/dir &&
git update-index --add newdir/dir &&
- git commit -m 'add a new directory' &&
+ git commit -m "add a new directory" &&
git svn dcommit -i bar &&
- test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" &&
+ test -z "$(git diff refs/heads/my-bar refs/remotes/bar)" &&
echo foo >> newdir/dir &&
git update-index newdir/dir &&
- git commit -m 'modify a file in new directory' &&
+ git commit -m "modify a file in new directory" &&
git svn dcommit -i bar &&
- test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\"
- "
+ test -z "$(git diff refs/heads/my-bar refs/remotes/bar)"
+'
test_expect_success 'dcommit should not fail with a touched file' '
test_commit "commit-new-file-foo2" foo2 &&
@@ -291,13 +291,13 @@
git svn rebase
'
-test_expect_success 'able to set-tree to a subdirectory' "
+test_expect_success 'able to set-tree to a subdirectory' '
echo cba > d &&
git update-index d &&
- git commit -m 'update /bar/d' &&
+ git commit -m "update /bar/d" &&
git svn set-tree -i bar HEAD &&
- test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\"
- "
+ test -z "$(git diff refs/heads/my-bar refs/remotes/bar)"
+'
test_expect_success 'git-svn works in a bare repository' '
mkdir bare-repo &&
diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh
index e8173d5..07bfb63 100755
--- a/t/t9101-git-svn-props.sh
+++ b/t/t9101-git-svn-props.sh
@@ -73,11 +73,11 @@
name='test svn:keywords ignoring'
test_expect_success "$name" \
- 'git checkout -b mybranch ${remotes_git_svn} &&
+ 'git checkout -b mybranch remotes/git-svn &&
echo Hi again >> kw.c &&
git commit -a -m "test keywords ignoring" &&
- git svn set-tree ${remotes_git_svn}..mybranch &&
- git pull . ${remotes_git_svn}'
+ git svn set-tree remotes/git-svn..mybranch &&
+ git pull . remotes/git-svn'
expect='/* $Id$ */'
got="$(sed -ne 2p kw.c)"
@@ -95,7 +95,7 @@
test_expect_success 'fetch and pull latest from svn and checkout a new wc' \
'git svn fetch &&
- git pull . ${remotes_git_svn} &&
+ git pull . remotes/git-svn &&
svn_cmd co "$svnrepo" new_wc'
for i in crlf ne_crlf lf ne_lf cr ne_cr empty_cr empty_lf empty empty_crlf
@@ -117,7 +117,7 @@
svn_cmd commit -m "propset CRLF on cr files"'
cd ..
test_expect_success 'fetch and pull latest from svn' \
- 'git svn fetch && git pull . ${remotes_git_svn}'
+ 'git svn fetch && git pull . remotes/git-svn'
b_cr="$(git hash-object cr)"
b_ne_cr="$(git hash-object ne_cr)"
@@ -168,7 +168,7 @@
EOF
test_expect_success 'test create-ignore' "
- git svn fetch && git pull . ${remotes_git_svn} &&
+ git svn fetch && git pull . remotes/git-svn &&
git svn create-ignore &&
cmp ./.gitignore create-ignore.expect &&
cmp ./deeply/.gitignore create-ignore.expect &&
diff --git a/t/t9102-git-svn-deep-rmdir.sh b/t/t9102-git-svn-deep-rmdir.sh
index eb70f48..66cd511 100755
--- a/t/t9102-git-svn-deep-rmdir.sh
+++ b/t/t9102-git-svn-deep-rmdir.sh
@@ -17,7 +17,7 @@
test_expect_success 'mirror via git svn' '
git svn init "$svnrepo" &&
git svn fetch &&
- git checkout -f -b test-rmdir ${remotes_git_svn}
+ git checkout -f -b test-rmdir remotes/git-svn
'
test_expect_success 'Try a commit on rmdir' '
diff --git a/t/t9103-git-svn-tracked-directory-removed.sh b/t/t9103-git-svn-tracked-directory-removed.sh
index 3413164..b282713 100755
--- a/t/t9103-git-svn-tracked-directory-removed.sh
+++ b/t/t9103-git-svn-tracked-directory-removed.sh
@@ -23,17 +23,19 @@
test_expect_success 'clone repo with git' '
git svn clone -s "$svnrepo" x &&
- test -f x/FOLLOWME &&
- test ! -f x/README
+ test_path_is_file x/FOLLOWME &&
+ test_path_is_missing x/README
'
-test_expect_success 'make sure r2 still has old file' "
- cd x &&
- test -n \"\$(git svn find-rev r1)\" &&
- git reset --hard \$(git svn find-rev r1) &&
- test -f README &&
- test ! -f FOLLOWME &&
- test x\$(git svn find-rev r2) = x
-"
+test_expect_success 'make sure r2 still has old file' '
+ (
+ cd x &&
+ test -n "$(git svn find-rev r1)" &&
+ git reset --hard "$(git svn find-rev r1)" &&
+ test_path_is_file README &&
+ test_path_is_missing FOLLOWME &&
+ test -z "$(git svn find-rev r2)"
+ )
+'
test_done
diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh
index f6d7ac7..dbe8dea 100755
--- a/t/t9106-git-svn-commit-diff-clobber.sh
+++ b/t/t9106-git-svn-commit-diff-clobber.sh
@@ -44,7 +44,7 @@
test_expect_success 'dcommit fails to commit because of conflict' '
git svn init "$svnrepo" &&
git svn fetch &&
- git reset --hard refs/${remotes_git_svn} &&
+ git reset --hard refs/remotes/git-svn &&
svn_cmd co "$svnrepo" t.svn &&
(
cd t.svn &&
@@ -59,7 +59,7 @@
'
test_expect_success 'dcommit does the svn equivalent of an index merge' "
- git reset --hard refs/${remotes_git_svn} &&
+ git reset --hard refs/remotes/git-svn &&
echo 'index merge' > file2 &&
git update-index --add file2 &&
git commit -a -m 'index merge' &&
@@ -81,7 +81,7 @@
'
test_expect_success 'multiple dcommit from git svn will not clobber svn' "
- git reset --hard refs/${remotes_git_svn} &&
+ git reset --hard refs/remotes/git-svn &&
echo new file >> new-file &&
git update-index --add new-file &&
git commit -a -m 'new file' &&
diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh
index 9060198..9f3ef8f 100755
--- a/t/t9107-git-svn-migrate.sh
+++ b/t/t9107-git-svn-migrate.sh
@@ -19,13 +19,14 @@
git svn init "$svnrepo" &&
git svn fetch &&
rm -rf "$GIT_DIR"/svn &&
- git update-ref refs/heads/git-svn-HEAD refs/${remotes_git_svn} &&
- git update-ref refs/heads/svn-HEAD refs/${remotes_git_svn} &&
- git update-ref -d refs/${remotes_git_svn} refs/${remotes_git_svn}
+ git update-ref refs/heads/git-svn-HEAD refs/remotes/git-svn &&
+ git update-ref refs/heads/svn-HEAD refs/remotes/git-svn &&
+ git update-ref -d refs/remotes/git-svn refs/remotes/git-svn
'
-head=$(git rev-parse --verify refs/heads/git-svn-HEAD^0)
-test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'"
+test_expect_success 'git-svn-HEAD is a real HEAD' '
+ git rev-parse --verify refs/heads/git-svn-HEAD^0
+'
svnrepo_escaped=$(echo $svnrepo | sed 's/ /%20/')
@@ -35,11 +36,11 @@
echo "$svnrepo" > "$GIT_DIR"/svn/info/url &&
git svn migrate &&
! test -d "$GIT_DIR"/git-svn &&
- git rev-parse --verify refs/${remotes_git_svn}^0 &&
+ git rev-parse --verify refs/remotes/git-svn^0 &&
git rev-parse --verify refs/remotes/svn^0 &&
test "$(git config --get svn-remote.svn.url)" = "$svnrepo_escaped" &&
test $(git config --get svn-remote.svn.fetch) = \
- ":refs/${remotes_git_svn}"
+ ":refs/remotes/git-svn"
'
test_expect_success 'initialize a multi-repository repo' '
@@ -56,9 +57,11 @@
"^tags/\*:refs/remotes/origin/tags/\*$" &&
git config --add svn-remote.svn.fetch "branches/a:refs/remotes/origin/a" &&
git config --add svn-remote.svn.fetch "branches/b:refs/remotes/origin/b" &&
- for i in tags/0.1 tags/0.2 tags/0.3; do
+ for i in tags/0.1 tags/0.2 tags/0.3
+ do
git config --add svn-remote.svn.fetch \
- $i:refs/remotes/origin/$i || exit 1; done &&
+ $i:refs/remotes/origin/$i || return 1
+ done &&
git config --get-all svn-remote.svn.fetch > fetch.out &&
grep "^trunk:refs/remotes/origin/trunk$" fetch.out &&
grep "^branches/a:refs/remotes/origin/a$" fetch.out &&
@@ -66,34 +69,42 @@
grep "^tags/0\.1:refs/remotes/origin/tags/0\.1$" fetch.out &&
grep "^tags/0\.2:refs/remotes/origin/tags/0\.2$" fetch.out &&
grep "^tags/0\.3:refs/remotes/origin/tags/0\.3$" fetch.out &&
- grep "^:refs/${remotes_git_svn}" fetch.out
+ grep "^:refs/remotes/git-svn" fetch.out
'
# refs should all be different, but the trees should all be the same:
-test_expect_success 'multi-fetch works on partial urls + paths' "
+test_expect_success 'multi-fetch works on partial urls + paths' '
+ refs="trunk a b tags/0.1 tags/0.2 tags/0.3" &&
git svn multi-fetch &&
- for i in trunk a b tags/0.1 tags/0.2 tags/0.3; do
- git rev-parse --verify refs/remotes/origin/\$i^0 >> refs.out || exit 1;
- done &&
- test -z \"\$(sort < refs.out | uniq -d)\" &&
- for i in trunk a b tags/0.1 tags/0.2 tags/0.3; do
- for j in trunk a b tags/0.1 tags/0.2 tags/0.3; do
- if test \$j != \$i; then continue; fi
- test -z \"\$(git diff refs/remotes/origin/\$i \
- refs/remotes/origin/\$j)\" ||exit 1; done; done
- "
+ for i in $refs
+ do
+ git rev-parse --verify refs/remotes/origin/$i^0 || return 1;
+ done >refs.out &&
+ test -z "$(sort <refs.out | uniq -d)" &&
+ for i in $refs
+ do
+ for j in $refs
+ do
+ git diff --exit-code refs/remotes/origin/$i \
+ refs/remotes/origin/$j ||
+ return 1
+ done
+ done
+'
test_expect_success 'migrate --minimize on old inited layout' '
git config --unset-all svn-remote.svn.fetch &&
git config --unset-all svn-remote.svn.url &&
rm -rf "$GIT_DIR"/svn &&
- for i in $(cat fetch.out); do
+ for i in $(cat fetch.out)
+ do
path=$(expr $i : "\([^:]*\):.*$")
ref=$(expr $i : "[^:]*:\(refs/remotes/.*\)$")
if test -z "$ref"; then continue; fi
if test -n "$path"; then path="/$path"; fi
- ( mkdir -p "$GIT_DIR"/svn/$ref/info/ &&
- echo "$svnrepo"$path > "$GIT_DIR"/svn/$ref/info/url ) || exit 1;
+ mkdir -p "$GIT_DIR"/svn/$ref/info/ &&
+ echo "$svnrepo"$path >"$GIT_DIR"/svn/$ref/info/url ||
+ return 1
done &&
git svn migrate --minimize &&
test -z "$(git config -l | grep "^svn-remote\.git-svn\.")" &&
@@ -104,7 +115,7 @@
grep "^tags/0\.1:refs/remotes/origin/tags/0\.1$" fetch.out &&
grep "^tags/0\.2:refs/remotes/origin/tags/0\.2$" fetch.out &&
grep "^tags/0\.3:refs/remotes/origin/tags/0\.3$" fetch.out &&
- grep "^:refs/${remotes_git_svn}" fetch.out
+ grep "^:refs/remotes/git-svn" fetch.out
'
test_expect_success ".rev_db auto-converted to .rev_map.UUID" '
diff --git a/t/t9110-git-svn-use-svm-props.sh b/t/t9110-git-svn-use-svm-props.sh
index 29fbdfd..dde0a3c 100755
--- a/t/t9110-git-svn-use-svm-props.sh
+++ b/t/t9110-git-svn-use-svm-props.sh
@@ -22,31 +22,31 @@
bar_url=http://mayonaise/svnrepo/bar
test_expect_success 'verify metadata for /bar' "
git cat-file commit refs/remotes/bar | \
- grep '^${git_svn_id}: $bar_url@12 $uuid$' &&
+ grep '^git-svn-id: $bar_url@12 $uuid$' &&
git cat-file commit refs/remotes/bar~1 | \
- grep '^${git_svn_id}: $bar_url@11 $uuid$' &&
+ grep '^git-svn-id: $bar_url@11 $uuid$' &&
git cat-file commit refs/remotes/bar~2 | \
- grep '^${git_svn_id}: $bar_url@10 $uuid$' &&
+ grep '^git-svn-id: $bar_url@10 $uuid$' &&
git cat-file commit refs/remotes/bar~3 | \
- grep '^${git_svn_id}: $bar_url@9 $uuid$' &&
+ grep '^git-svn-id: $bar_url@9 $uuid$' &&
git cat-file commit refs/remotes/bar~4 | \
- grep '^${git_svn_id}: $bar_url@6 $uuid$' &&
+ grep '^git-svn-id: $bar_url@6 $uuid$' &&
git cat-file commit refs/remotes/bar~5 | \
- grep '^${git_svn_id}: $bar_url@1 $uuid$'
+ grep '^git-svn-id: $bar_url@1 $uuid$'
"
e_url=http://mayonaise/svnrepo/dir/a/b/c/d/e
test_expect_success 'verify metadata for /dir/a/b/c/d/e' "
git cat-file commit refs/remotes/e | \
- grep '^${git_svn_id}: $e_url@1 $uuid$'
+ grep '^git-svn-id: $e_url@1 $uuid$'
"
dir_url=http://mayonaise/svnrepo/dir
test_expect_success 'verify metadata for /dir' "
git cat-file commit refs/remotes/dir | \
- grep '^${git_svn_id}: $dir_url@2 $uuid$' &&
+ grep '^git-svn-id: $dir_url@2 $uuid$' &&
git cat-file commit refs/remotes/dir~1 | \
- grep '^${git_svn_id}: $dir_url@1 $uuid$'
+ grep '^git-svn-id: $dir_url@1 $uuid$'
"
test_expect_success 'find commit based on SVN revision number' "
diff --git a/t/t9111-git-svn-use-svnsync-props.sh b/t/t9111-git-svn-use-svnsync-props.sh
index bd081c2..22b6e5e 100755
--- a/t/t9111-git-svn-use-svnsync-props.sh
+++ b/t/t9111-git-svn-use-svnsync-props.sh
@@ -21,31 +21,31 @@
bar_url=http://mayonaise/svnrepo/bar
test_expect_success 'verify metadata for /bar' "
git cat-file commit refs/remotes/bar | \
- grep '^${git_svn_id}: $bar_url@12 $uuid$' &&
+ grep '^git-svn-id: $bar_url@12 $uuid$' &&
git cat-file commit refs/remotes/bar~1 | \
- grep '^${git_svn_id}: $bar_url@11 $uuid$' &&
+ grep '^git-svn-id: $bar_url@11 $uuid$' &&
git cat-file commit refs/remotes/bar~2 | \
- grep '^${git_svn_id}: $bar_url@10 $uuid$' &&
+ grep '^git-svn-id: $bar_url@10 $uuid$' &&
git cat-file commit refs/remotes/bar~3 | \
- grep '^${git_svn_id}: $bar_url@9 $uuid$' &&
+ grep '^git-svn-id: $bar_url@9 $uuid$' &&
git cat-file commit refs/remotes/bar~4 | \
- grep '^${git_svn_id}: $bar_url@6 $uuid$' &&
+ grep '^git-svn-id: $bar_url@6 $uuid$' &&
git cat-file commit refs/remotes/bar~5 | \
- grep '^${git_svn_id}: $bar_url@1 $uuid$'
+ grep '^git-svn-id: $bar_url@1 $uuid$'
"
e_url=http://mayonaise/svnrepo/dir/a/b/c/d/e
test_expect_success 'verify metadata for /dir/a/b/c/d/e' "
git cat-file commit refs/remotes/e | \
- grep '^${git_svn_id}: $e_url@1 $uuid$'
+ grep '^git-svn-id: $e_url@1 $uuid$'
"
dir_url=http://mayonaise/svnrepo/dir
test_expect_success 'verify metadata for /dir' "
git cat-file commit refs/remotes/dir | \
- grep '^${git_svn_id}: $dir_url@2 $uuid$' &&
+ grep '^git-svn-id: $dir_url@2 $uuid$' &&
git cat-file commit refs/remotes/dir~1 | \
- grep '^${git_svn_id}: $dir_url@1 $uuid$'
+ grep '^git-svn-id: $dir_url@1 $uuid$'
"
test_done
diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh
index 1c84ce1..59465b1 100755
--- a/t/t9120-git-svn-clone-with-percent-escapes.sh
+++ b/t/t9120-git-svn-clone-with-percent-escapes.sh
@@ -22,7 +22,7 @@
git svn clone "$svnrepo/pr%20ject" clone &&
(
cd clone &&
- git rev-parse refs/${remotes_git_svn}
+ git rev-parse refs/remotes/git-svn
)
'
@@ -42,7 +42,7 @@
git svn clone --minimize-url "$svnrepo/pr%20ject/trunk" minimize &&
(
cd minimize &&
- git rev-parse refs/${remotes_git_svn}
+ git rev-parse refs/remotes/git-svn
)
'
@@ -50,7 +50,7 @@
git svn clone "$svnrepo/pr%20ject/trunk" trunk &&
(
cd trunk &&
- git rev-parse refs/${remotes_git_svn}
+ git rev-parse refs/remotes/git-svn
)
'
diff --git a/t/t9123-git-svn-rebuild-with-rewriteroot.sh b/t/t9123-git-svn-rebuild-with-rewriteroot.sh
index fd81847..ead4045 100755
--- a/t/t9123-git-svn-rebuild-with-rewriteroot.sh
+++ b/t/t9123-git-svn-rebuild-with-rewriteroot.sh
@@ -17,7 +17,7 @@
test_expect_success 'init, fetch and checkout repository' '
git svn init --rewrite-root=http://invalid.invalid/ "$svnrepo" &&
git svn fetch &&
- git checkout -b mybranch ${remotes_git_svn}
+ git checkout -b mybranch remotes/git-svn
'
test_expect_success 'remove rev_map' '
diff --git a/t/t9153-git-svn-rewrite-uuid.sh b/t/t9153-git-svn-rewrite-uuid.sh
index 88a2cfa..372ef15 100755
--- a/t/t9153-git-svn-rewrite-uuid.sh
+++ b/t/t9153-git-svn-rewrite-uuid.sh
@@ -17,9 +17,9 @@
test_expect_success 'verify uuid' "
git cat-file commit refs/remotes/git-svn~0 | \
- grep '^${git_svn_id}: .*@2 $uuid$' &&
+ grep '^git-svn-id: .*@2 $uuid$' &&
git cat-file commit refs/remotes/git-svn~1 | \
- grep '^${git_svn_id}: .*@1 $uuid$'
+ grep '^git-svn-id: .*@1 $uuid$'
"
test_done
diff --git a/worktree.c b/worktree.c
index 89ebe67..199b1ef 100644
--- a/worktree.c
+++ b/worktree.c
@@ -2,6 +2,8 @@
#include "refs.h"
#include "strbuf.h"
#include "worktree.h"
+#include "dir.h"
+#include "wt-status.h"
void free_worktrees(struct worktree **worktrees)
{
@@ -9,7 +11,7 @@
for (i = 0; worktrees[i]; i++) {
free(worktrees[i]->path);
- free(worktrees[i]->git_dir);
+ free(worktrees[i]->id);
free(worktrees[i]->head_ref);
free(worktrees[i]);
}
@@ -74,13 +76,11 @@
struct worktree *worktree = NULL;
struct strbuf path = STRBUF_INIT;
struct strbuf worktree_path = STRBUF_INIT;
- struct strbuf gitdir = STRBUF_INIT;
struct strbuf head_ref = STRBUF_INIT;
int is_bare = 0;
int is_detached = 0;
- strbuf_addf(&gitdir, "%s", absolute_path(get_git_common_dir()));
- strbuf_addbuf(&worktree_path, &gitdir);
+ strbuf_addstr(&worktree_path, absolute_path(get_git_common_dir()));
is_bare = !strbuf_strip_suffix(&worktree_path, "/.git");
if (is_bare)
strbuf_strip_suffix(&worktree_path, "/.");
@@ -92,15 +92,15 @@
worktree = xmalloc(sizeof(struct worktree));
worktree->path = strbuf_detach(&worktree_path, NULL);
- worktree->git_dir = strbuf_detach(&gitdir, NULL);
+ worktree->id = NULL;
worktree->is_bare = is_bare;
worktree->head_ref = NULL;
worktree->is_detached = is_detached;
+ worktree->is_current = 0;
add_head_info(&head_ref, worktree);
done:
strbuf_release(&path);
- strbuf_release(&gitdir);
strbuf_release(&worktree_path);
strbuf_release(&head_ref);
return worktree;
@@ -111,16 +111,13 @@
struct worktree *worktree = NULL;
struct strbuf path = STRBUF_INIT;
struct strbuf worktree_path = STRBUF_INIT;
- struct strbuf gitdir = STRBUF_INIT;
struct strbuf head_ref = STRBUF_INIT;
int is_detached = 0;
if (!id)
die("Missing linked worktree name");
- strbuf_addf(&gitdir, "%s/worktrees/%s",
- absolute_path(get_git_common_dir()), id);
- strbuf_addf(&path, "%s/gitdir", gitdir.buf);
+ strbuf_git_common_path(&path, "worktrees/%s/gitdir", id);
if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0)
/* invalid gitdir file */
goto done;
@@ -140,20 +137,39 @@
worktree = xmalloc(sizeof(struct worktree));
worktree->path = strbuf_detach(&worktree_path, NULL);
- worktree->git_dir = strbuf_detach(&gitdir, NULL);
+ worktree->id = xstrdup(id);
worktree->is_bare = 0;
worktree->head_ref = NULL;
worktree->is_detached = is_detached;
+ worktree->is_current = 0;
add_head_info(&head_ref, worktree);
done:
strbuf_release(&path);
- strbuf_release(&gitdir);
strbuf_release(&worktree_path);
strbuf_release(&head_ref);
return worktree;
}
+static void mark_current_worktree(struct worktree **worktrees)
+{
+ struct strbuf git_dir = STRBUF_INIT;
+ struct strbuf path = STRBUF_INIT;
+ int i;
+
+ strbuf_addstr(&git_dir, absolute_path(get_git_dir()));
+ for (i = 0; worktrees[i]; i++) {
+ struct worktree *wt = worktrees[i];
+ strbuf_addstr(&path, absolute_path(get_worktree_git_dir(wt)));
+ wt->is_current = !fspathcmp(git_dir.buf, path.buf);
+ strbuf_reset(&path);
+ if (wt->is_current)
+ break;
+ }
+ strbuf_release(&git_dir);
+ strbuf_release(&path);
+}
+
struct worktree **get_worktrees(void)
{
struct worktree **list = NULL;
@@ -185,35 +201,105 @@
}
ALLOC_GROW(list, counter + 1, alloc);
list[counter] = NULL;
+
+ mark_current_worktree(list);
return list;
}
-char *find_shared_symref(const char *symref, const char *target)
+const char *get_worktree_git_dir(const struct worktree *wt)
{
- char *existing = NULL;
+ if (!wt)
+ return get_git_dir();
+ else if (!wt->id)
+ return get_git_common_dir();
+ else
+ return git_common_path("worktrees/%s", wt->id);
+}
+
+int is_worktree_being_rebased(const struct worktree *wt,
+ const char *target)
+{
+ struct wt_status_state state;
+ int found_rebase;
+
+ memset(&state, 0, sizeof(state));
+ found_rebase = wt_status_check_rebase(wt, &state) &&
+ ((state.rebase_in_progress ||
+ state.rebase_interactive_in_progress) &&
+ state.branch &&
+ starts_with(target, "refs/heads/") &&
+ !strcmp(state.branch, target + strlen("refs/heads/")));
+ free(state.branch);
+ free(state.onto);
+ return found_rebase;
+}
+
+int is_worktree_being_bisected(const struct worktree *wt,
+ const char *target)
+{
+ struct wt_status_state state;
+ int found_rebase;
+
+ memset(&state, 0, sizeof(state));
+ found_rebase = wt_status_check_bisect(wt, &state) &&
+ state.branch &&
+ starts_with(target, "refs/heads/") &&
+ !strcmp(state.branch, target + strlen("refs/heads/"));
+ free(state.branch);
+ return found_rebase;
+}
+
+/*
+ * note: this function should be able to detect shared symref even if
+ * HEAD is temporarily detached (e.g. in the middle of rebase or
+ * bisect). New commands that do similar things should update this
+ * function as well.
+ */
+const struct worktree *find_shared_symref(const char *symref,
+ const char *target)
+{
+ const struct worktree *existing = NULL;
struct strbuf path = STRBUF_INIT;
struct strbuf sb = STRBUF_INIT;
- struct worktree **worktrees = get_worktrees();
+ static struct worktree **worktrees;
int i = 0;
+ if (worktrees)
+ free_worktrees(worktrees);
+ worktrees = get_worktrees();
+
for (i = 0; worktrees[i]; i++) {
+ struct worktree *wt = worktrees[i];
+
+ if (wt->is_detached && !strcmp(symref, "HEAD")) {
+ if (is_worktree_being_rebased(wt, target)) {
+ existing = wt;
+ break;
+ }
+ if (is_worktree_being_bisected(wt, target)) {
+ existing = wt;
+ break;
+ }
+ }
+
strbuf_reset(&path);
strbuf_reset(&sb);
- strbuf_addf(&path, "%s/%s", worktrees[i]->git_dir, symref);
+ strbuf_addf(&path, "%s/%s",
+ get_worktree_git_dir(wt),
+ symref);
if (parse_ref(path.buf, &sb, NULL)) {
continue;
}
if (!strcmp(sb.buf, target)) {
- existing = xstrdup(worktrees[i]->path);
+ existing = wt;
break;
}
}
strbuf_release(&path);
strbuf_release(&sb);
- free_worktrees(worktrees);
return existing;
}
diff --git a/worktree.h b/worktree.h
index b4b3dda..1394909 100644
--- a/worktree.h
+++ b/worktree.h
@@ -3,11 +3,12 @@
struct worktree {
char *path;
- char *git_dir;
+ char *id;
char *head_ref;
unsigned char head_sha1[20];
int is_detached;
int is_bare;
+ int is_current;
};
/* Functions for acting on the information about worktrees. */
@@ -23,16 +24,33 @@
extern struct worktree **get_worktrees(void);
/*
+ * Return git dir of the worktree. Note that the path may be relative.
+ * If wt is NULL, git dir of current worktree is returned.
+ */
+extern const char *get_worktree_git_dir(const struct worktree *wt);
+
+/*
* Free up the memory for worktree(s)
*/
extern void free_worktrees(struct worktree **);
/*
* Check if a per-worktree symref points to a ref in the main worktree
- * or any linked worktree, and return the path to the exising worktree
- * if it is. Returns NULL if there is no existing ref. The caller is
- * responsible for freeing the returned path.
+ * or any linked worktree, and return the worktree that holds the ref,
+ * or NULL otherwise. The result may be destroyed by the next call.
*/
-extern char *find_shared_symref(const char *symref, const char *target);
+extern const struct worktree *find_shared_symref(const char *symref,
+ const char *target);
+
+int is_worktree_being_rebased(const struct worktree *wt, const char *target);
+int is_worktree_being_bisected(const struct worktree *wt, const char *target);
+
+/*
+ * Similar to git_path() but can produce paths for a specified
+ * worktree instead of current one
+ */
+extern const char *worktree_git_path(const struct worktree *wt,
+ const char *fmt, ...)
+ __attribute__((format (printf, 2, 3)));
#endif
diff --git a/wt-status.c b/wt-status.c
index 1ea2ebe..4f27bd6 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -15,6 +15,7 @@
#include "column.h"
#include "strbuf.h"
#include "utf8.h"
+#include "worktree.h"
static const char cut_line[] =
"------------------------ >8 ------------------------\n";
@@ -950,6 +951,7 @@
status_printf_ln(s, color,
_(" (fix conflicts and run \"git commit\")"));
} else {
+ s-> commitable = 1;
status_printf_ln(s, color,
_("All conflicts fixed but you are still merging."));
if (s->hints)
@@ -1262,13 +1264,13 @@
/*
* Extract branch information from rebase/bisect
*/
-static char *read_and_strip_branch(const char *path)
+static char *get_branch(const struct worktree *wt, const char *path)
{
struct strbuf sb = STRBUF_INIT;
unsigned char sha1[20];
const char *branch_name;
- if (strbuf_read_file(&sb, git_path("%s", path), 0) <= 0)
+ if (strbuf_read_file(&sb, worktree_git_path(wt, "%s", path), 0) <= 0)
goto got_nothing;
while (sb.len && sb.buf[sb.len - 1] == '\n')
@@ -1360,6 +1362,46 @@
strbuf_release(&cb.buf);
}
+int wt_status_check_rebase(const struct worktree *wt,
+ struct wt_status_state *state)
+{
+ struct stat st;
+
+ if (!stat(worktree_git_path(wt, "rebase-apply"), &st)) {
+ if (!stat(worktree_git_path(wt, "rebase-apply/applying"), &st)) {
+ state->am_in_progress = 1;
+ if (!stat(worktree_git_path(wt, "rebase-apply/patch"), &st) && !st.st_size)
+ state->am_empty_patch = 1;
+ } else {
+ state->rebase_in_progress = 1;
+ state->branch = get_branch(wt, "rebase-apply/head-name");
+ state->onto = get_branch(wt, "rebase-apply/onto");
+ }
+ } else if (!stat(worktree_git_path(wt, "rebase-merge"), &st)) {
+ if (!stat(worktree_git_path(wt, "rebase-merge/interactive"), &st))
+ state->rebase_interactive_in_progress = 1;
+ else
+ state->rebase_in_progress = 1;
+ state->branch = get_branch(wt, "rebase-merge/head-name");
+ state->onto = get_branch(wt, "rebase-merge/onto");
+ } else
+ return 0;
+ return 1;
+}
+
+int wt_status_check_bisect(const struct worktree *wt,
+ struct wt_status_state *state)
+{
+ struct stat st;
+
+ if (!stat(worktree_git_path(wt, "BISECT_LOG"), &st)) {
+ state->bisect_in_progress = 1;
+ state->branch = get_branch(wt, "BISECT_START");
+ return 1;
+ }
+ return 0;
+}
+
void wt_status_get_state(struct wt_status_state *state,
int get_detached_from)
{
@@ -1368,32 +1410,14 @@
if (!stat(git_path_merge_head(), &st)) {
state->merge_in_progress = 1;
- } else if (!stat(git_path("rebase-apply"), &st)) {
- if (!stat(git_path("rebase-apply/applying"), &st)) {
- state->am_in_progress = 1;
- if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
- state->am_empty_patch = 1;
- } else {
- state->rebase_in_progress = 1;
- state->branch = read_and_strip_branch("rebase-apply/head-name");
- state->onto = read_and_strip_branch("rebase-apply/onto");
- }
- } else if (!stat(git_path("rebase-merge"), &st)) {
- if (!stat(git_path("rebase-merge/interactive"), &st))
- state->rebase_interactive_in_progress = 1;
- else
- state->rebase_in_progress = 1;
- state->branch = read_and_strip_branch("rebase-merge/head-name");
- state->onto = read_and_strip_branch("rebase-merge/onto");
+ } else if (wt_status_check_rebase(NULL, state)) {
+ ; /* all set */
} else if (!stat(git_path_cherry_pick_head(), &st) &&
!get_sha1("CHERRY_PICK_HEAD", sha1)) {
state->cherry_pick_in_progress = 1;
hashcpy(state->cherry_pick_head_sha1, sha1);
}
- if (!stat(git_path("BISECT_LOG"), &st)) {
- state->bisect_in_progress = 1;
- state->branch = read_and_strip_branch("BISECT_START");
- }
+ wt_status_check_bisect(NULL, state);
if (!stat(git_path_revert_head(), &st) &&
!get_sha1("REVERT_HEAD", sha1)) {
state->revert_in_progress = 1;
diff --git a/wt-status.h b/wt-status.h
index c9b3b74..2ca93f6 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -6,6 +6,8 @@
#include "color.h"
#include "pathspec.h"
+struct worktree;
+
enum color_wt_status {
WT_STATUS_HEADER = 0,
WT_STATUS_UPDATED,
@@ -100,6 +102,10 @@
void wt_status_print(struct wt_status *s);
void wt_status_collect(struct wt_status *s);
void wt_status_get_state(struct wt_status_state *state, int get_detached_from);
+int wt_status_check_rebase(const struct worktree *wt,
+ struct wt_status_state *state);
+int wt_status_check_bisect(const struct worktree *wt,
+ struct wt_status_state *state);
void wt_shortstatus_print(struct wt_status *s);
void wt_porcelain_print(struct wt_status *s);