diff options
121 files changed, 1688 insertions, 661 deletions
diff --git a/.gitignore b/.gitignore index 6669bf0c6c..0a1f93b25a 100644 --- a/.gitignore +++ b/.gitignore @@ -190,6 +190,7 @@ /test-mktemp /test-parse-options /test-path-utils +/test-read-cache /test-regex /test-revision-walking /test-run-command diff --git a/Documentation/RelNotes/1.8.3.2.txt b/Documentation/RelNotes/1.8.3.2.txt new file mode 100644 index 0000000000..26ae142c3d --- /dev/null +++ b/Documentation/RelNotes/1.8.3.2.txt @@ -0,0 +1,59 @@ +Git v1.8.3.2 Release Notes +========================== + +Fixes since v1.8.3.1 +-------------------- + + * Cloning with "git clone --depth N" while fetch.fsckobjects (or + transfer.fsckobjects) is set to true did not tell the cut-off + points of the shallow history to the process that validates the + objects and the history received, causing the validation to fail. + + * "git checkout foo" DWIMs the intended "upstream" and turns it into + "git checkout -t -b foo remotes/origin/foo". This codepath has been + updated to correctly take existing remote definitions into account. + + * "git fetch" into a shallow repository from a repository that does + not know about the shallow boundary commits (e.g. a different fork + from the repository the current shallow repository was cloned from) + did not work correctly. + + * "git subtree" (in contrib/) had one codepath with loose error + checks to lose data at the remote side. + + * "git log --ancestry-path A...B" did not work as expected, as it did + not pay attention to the fact that the merge base between A and B + was the bottom of the range being specified. + + * "git diff -c -p" was not showing a deleted line from a hunk when + another hunk immediately begins where the earlier one ends. + + * "git merge @{-1}~22" was rewritten to "git merge frotz@{1}~22" + incorrectly when your previous branch was "frotz" (it should be + rewritten to "git merge frotz~22" instead). + + * "git commit --allow-empty-message -m ''" should not start an + editor. + + * "git push --[no-]verify" was not documented. + + * An entry for "file://" scheme in the enumeration of URL types Git + can take in the HTML documentation was made into a clickable link + by mistake. + + * zsh prompt script that borrowed from bash prompt script did not + work due to slight differences in array variable notation between + these two shells. + + * The bash prompt code (in contrib/) displayed the name of the branch + being rebased when "rebase -i/-m/-p" modes are in use, but not the + plain vanilla "rebase". + + * "git push $there HEAD:branch" did not resolve HEAD early enough, so + it was easy to flip it around while push is still going on and push + out a branch that the user did not originally intended when the + command was started. + + * "difftool --dir-diff" did not copy back changes made by the + end-user in the diff tool backend to the working tree in some + cases. diff --git a/Documentation/RelNotes/1.8.3.3.txt b/Documentation/RelNotes/1.8.3.3.txt new file mode 100644 index 0000000000..9ba4f4da0f --- /dev/null +++ b/Documentation/RelNotes/1.8.3.3.txt @@ -0,0 +1,47 @@ +Git v1.8.3.3 Release Notes +========================== + +Fixes since v1.8.3.2 +-------------------- + + * "git apply" parsed patches that add new files, generated by programs + other than Git, incorrectly. This is an old breakage in v1.7.11. + + * Older cURL wanted piece of memory we call it with to be stable, but + we updated the auth material after handing it to a call. + + * "git pull" into nothing trashed "local changes" that were in the + index. + + * Many "git submodule" operations did not work on a submodule at a + path whose name is not in ASCII. + + * "cherry-pick" had a small leak in its error codepath. + + * Logic used by git-send-email to suppress cc mishandled names like + "A U. Thor" <author@example.xz>, where the human readable part + needs to be quoted (the user input may not have the double quotes + around the name, and comparison was done between quoted and + unquoted strings). It also mishandled names that need RFC2047 + quoting. + + * "gitweb" forgot to clear a global variable $search_regexp upon each + request, mistakenly carrying over the previous search to a new one + when used as a persistent CGI. + + * The wildmatch engine did not honor WM_CASEFOLD option correctly. + + * "git log -c --follow $path" segfaulted upon hitting the commit that + renamed the $path being followed. + + * When a reflog notation is used for implicit "current branch", + e.g. "git log @{u}", we did not say which branch and worse said + "branch ''" in the error messages. + + * Mac OS X does not like to write(2) more than INT_MAX number of + bytes; work it around by chopping write(2) into smaller pieces. + + * Newer MacOS X encourages the programs to compile and link with + their CommonCrypto, not with OpenSSL. + +Also contains various minor documentation updates. diff --git a/Documentation/config.txt b/Documentation/config.txt index 6e53fc5074..0a7bd06a29 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -930,6 +930,9 @@ column.ui:: This variable consists of a list of tokens separated by spaces or commas: + +These options control when the feature should be enabled +(defaults to 'never'): ++ -- `always`;; always show in columns @@ -937,19 +940,30 @@ column.ui:: never show in columns `auto`;; show in columns if the output is to the terminal +-- ++ +These options control layout (defaults to 'column'). Setting any +of these implies 'always' if none of 'always', 'never', or 'auto' are +specified. ++ +-- `column`;; - fill columns before rows (default) + fill columns before rows `row`;; fill rows before columns `plain`;; show in one column +-- ++ +Finally, these options can be combined with a layout option (defaults +to 'nodense'): ++ +-- `dense`;; make unequal size columns to utilize more space `nodense`;; make equal size columns -- -+ -This option defaults to 'never'. column.branch:: Specify whether to output branch listing in `git branch` in columns. diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index b8a9b86375..a85288f23e 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -383,14 +383,36 @@ ifndef::git-format-patch[] that matches other criteria, nothing is selected. -S<string>:: - Look for differences that introduce or remove an instance of - <string>. Note that this is different than the string simply - appearing in diff output; see the 'pickaxe' entry in - linkgit:gitdiffcore[7] for more details. + Look for differences that change the number of occurrences of + the specified string (i.e. addition/deletion) in a file. + Intended for the scripter's use. ++ +It is useful when you're looking for an exact block of code (like a +struct), and want to know the history of that block since it first +came into being: use the feature iteratively to feed the interesting +block in the preimage back into `-S`, and keep going until you get the +very first version of the block. -G<regex>:: - Look for differences whose added or removed line matches - the given <regex>. + Look for differences whose patch text contains added/removed + lines that match <regex>. ++ +To illustrate the difference between `-S<regex> --pickaxe-regex` and +`-G<regex>`, consider a commit with the following diff in the same +file: ++ +---- ++ return !regexec(regexp, two->ptr, 1, ®match, 0); +... +- hit = !regexec(regexp, mf2.ptr, 1, ®match, 0); +---- ++ +While `git log -G"regexec\(regexp"` will show this commit, `git log +-S"regexec\(regexp" --pickaxe-regex` will not (because the number of +occurrences of that string did not change). ++ +See the 'pickaxe' entry in linkgit:gitdiffcore[7] for more +information. --pickaxe-all:: When `-S` or `-G` finds a change, show all the changes in that @@ -398,8 +420,8 @@ ifndef::git-format-patch[] in <string>. --pickaxe-regex:: - Make the <string> not a plain string but an extended POSIX - regex to match. + Treat the <string> given to `-S` as an extended POSIX regular + expression to match. endif::git-format-patch[] -O<orderfile>:: diff --git a/Documentation/git-check-ignore.txt b/Documentation/git-check-ignore.txt index 854e4d0c42..7f5601bda5 100644 --- a/Documentation/git-check-ignore.txt +++ b/Documentation/git-check-ignore.txt @@ -82,7 +82,7 @@ SEE ALSO -------- linkgit:gitignore[5] linkgit:gitconfig[5] -linkgit:git-ls-files[5] +linkgit:git-ls-files[1] GIT --- diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 23a9413525..ca118ac6bf 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -131,9 +131,9 @@ entries; instead, unmerged entries are ignored. "--track" in linkgit:git-branch[1] for details. + If no '-b' option is given, the name of the new branch will be -derived from the remote-tracking branch. If "remotes/" or "refs/remotes/" -is prefixed it is stripped away, and then the part up to the -next slash (which would be the nickname of the remote) is removed. +derived from the remote-tracking branch, by looking at the local part of +the refspec configured for the corresponding remote, and then stripping +the initial part up to the "*". This would tell us to use "hack" as the local branch when branching off of "origin/hack" (or "remotes/origin/hack", or even "refs/remotes/origin/hack"). If the given name has no slash, or the above diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index d88a6fcb29..606f00c3b8 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -82,7 +82,7 @@ OPTIONS --get:: Get the value for a given key (optionally filtered by a regex matching the value). Returns error code 1 if the key was not - found and error code 2 if multiple key values were found. + found and the last value if multiple key values were found. --get-all:: Like get, but does not fail if the number of values for the key diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt index c0b7c581ad..a86cf62e68 100644 --- a/Documentation/git-diff-index.txt +++ b/Documentation/git-diff-index.txt @@ -3,7 +3,7 @@ git-diff-index(1) NAME ---- -git-diff-index - Compares content and mode of blobs between the index and repository +git-diff-index - Compare a tree to the working tree or index SYNOPSIS @@ -13,11 +13,11 @@ SYNOPSIS DESCRIPTION ----------- -Compares the content and mode of the blobs found via a tree -object with the content of the current index and, optionally -ignoring the stat state of the file on disk. When paths are -specified, compares only those named paths. Otherwise all -entries in the index are compared. +Compares the content and mode of the blobs found in a tree object +with the corresponding tracked files in the working tree, or with the +corresponding paths in the index. When <path> arguments are present, +compares only paths matching those patterns. Otherwise all tracked +files are compared. OPTIONS ------- diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index d51481394c..df5be268ba 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -11,7 +11,7 @@ SYNOPSIS [verse] 'git push' [--all | --mirror | --tags] [--follow-tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [--prune] [-v | --verbose] [-u | --set-upstream] - [<repository> [<refspec>...]] + [--no-verify] [<repository> [<refspec>...]] DESCRIPTION ----------- @@ -195,6 +195,11 @@ useful if you write an alias or script around 'git push'. be pushed. If on-demand was not able to push all necessary revisions it will also be aborted and exit with non-zero status. +--[no-]verify:: + Toggle the pre-push hook (see linkgit:githooks[5]). The + default is \--verify, giving the hook a chance to prevent the + push. With \--no-verify, the hook is bypassed completely. + include::urls-remotes.txt[] diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index a404b47b7b..f445cb38fa 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'git reset' [-q] [<tree-ish>] [--] <paths>... -'git reset' (--patch | -p) [<tree-sh>] [--] [<paths>...] +'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...] 'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>] DESCRIPTION diff --git a/Documentation/git.txt b/Documentation/git.txt index 443d88ff12..1f783028bc 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,11 @@ unreleased) version of Git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.8.3.1/git.html[documentation for release 1.8.3.1] +* link:v1.8.3.3/git.html[documentation for release 1.8.3.3] * release notes for + link:RelNotes/1.8.3.3.txt[1.8.3.3], + link:RelNotes/1.8.3.2.txt[1.8.3.2], link:RelNotes/1.8.3.1.txt[1.8.3.1], link:RelNotes/1.8.3.txt[1.8.3]. @@ -683,9 +685,7 @@ Git so take care if using Cogito etc. The '--git-dir' command-line option also sets this value. 'GIT_WORK_TREE':: - Set the path to the working tree. The value will not be - used in combination with repositories found automatically in - a .git directory (i.e. $GIT_DIR is not set). + Set the path to the root of the working tree. This can also be controlled by the '--work-tree' command line option and the core.worktree configuration variable. diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.txt index 568d75783a..c8b3e51c84 100644 --- a/Documentation/gitdiffcore.txt +++ b/Documentation/gitdiffcore.txt @@ -222,26 +222,35 @@ version prefixed with '+'. diffcore-pickaxe: For Detecting Addition/Deletion of Specified String --------------------------------------------------------------------- -This transformation is used to find filepairs that represent -changes that touch a specified string, and is controlled by the --S option and the `--pickaxe-all` option to the 'git diff-*' -commands. - -When diffcore-pickaxe is in use, it checks if there are -filepairs whose "result" side and whose "origin" side have -different number of specified string. Such a filepair represents -"the string appeared in this changeset". It also checks for the -opposite case that loses the specified string. - -When `--pickaxe-all` is not in effect, diffcore-pickaxe leaves -only such filepairs that touch the specified string in its -output. When `--pickaxe-all` is used, diffcore-pickaxe leaves all -filepairs intact if there is such a filepair, or makes the -output empty otherwise. The latter behaviour is designed to -make reviewing of the changes in the context of the whole +This transformation limits the set of filepairs to those that change +specified strings between the preimage and the postimage in a certain +way. -S<block of text> and -G<regular expression> options are used to +specify different ways these strings are sought. + +"-S<block of text>" detects filepairs whose preimage and postimage +have different number of occurrences of the specified block of text. +By definition, it will not detect in-file moves. Also, when a +changeset moves a file wholesale without affecting the interesting +string, diffcore-rename kicks in as usual, and `-S` omits the filepair +(since the number of occurrences of that string didn't change in that +rename-detected filepair). When used with `--pickaxe-regex`, treat +the <block of text> as an extended POSIX regular expression to match, +instead of a literal string. + +"-G<regular expression>" (mnemonic: grep) detects filepairs whose +textual diff has an added or a deleted line that matches the given +regular expression. This means that it will detect in-file (or what +rename-detection considers the same file) moves, which is noise. The +implementation runs diff twice and greps, and this can be quite +expensive. + +When `-S` or `-G` are used without `--pickaxe-all`, only filepairs +that match their respective criterion are kept in the output. When +`--pickaxe-all` is used, if even one filepair matches their respective +criterion in a changeset, the entire changeset is kept. This behavior +is designed to make reviewing changes in the context of the whole changeset easier. - diffcore-order: For Sorting the Output Based on Filenames --------------------------------------------------------- diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index 68a18e1497..db2a74df93 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -400,12 +400,13 @@ should not be combined with other pathspec. <<def_ref,ref>> and local ref. [[def_remote_tracking_branch]]remote-tracking branch:: - A regular Git <<def_branch,branch>> that is used to follow changes from - another <<def_repository,repository>>. A remote-tracking - branch should not contain direct modifications or have local commits - made to it. A remote-tracking branch can usually be - identified as the right-hand-side <<def_ref,ref>> in a Pull: - <<def_refspec,refspec>>. + A <<def_ref,ref>> that is used to follow changes from another + <<def_repository,repository>>. It typically looks like + 'refs/remotes/foo/bar' (indicating that it tracks a branch named + 'bar' in a remote named 'foo'), and matches the right-hand-side of + a configured fetch <<def_refspec,refspec>>. A remote-tracking + branch should not contain direct modifications or have local + commits made to it. [[def_repository]]repository:: A collection of <<def_ref,refs>> together with an diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index 2adccf8fec..afba8d4f3b 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -8,12 +8,13 @@ failed and do not autocommit, to give the user a chance to inspect and further tweak the merge result before committing. --edit:: +-e:: --no-edit:: Invoke an editor before committing successful mechanical merge to further edit the auto-generated merge message, so that the user can explain and justify the merge. The `--no-edit` option can be used to accept the auto-generated message (this is generally - discouraged). The `--edit` option is still useful if you are + discouraged). The `--edit` (or `-e`) option is still useful if you are giving a draft message with the `-m` option from the command line and want to edit it in the editor. + diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt index f1a51edf47..b898e97988 100644 --- a/Documentation/technical/pack-protocol.txt +++ b/Documentation/technical/pack-protocol.txt @@ -228,8 +228,7 @@ obtained through ref discovery. The client MUST write all obj-ids which it only has shallow copies of (meaning that it does not have the parents of a commit) as 'shallow' lines so that the server is aware of the limitations of -the client's history. Clients MUST NOT mention an obj-id which -it does not know exists on the server. +the client's history. The client now sends the maximum commit history depth it wants for this transaction, which is the number of commits it wants from the diff --git a/Documentation/urls.txt b/Documentation/urls.txt index 3ca122faed..60ba300117 100644 --- a/Documentation/urls.txt +++ b/Documentation/urls.txt @@ -33,7 +33,7 @@ For local repositories, also supported by Git natively, the following syntaxes may be used: - /path/to/repo.git/ -- file:///path/to/repo.git/ +- \file:///path/to/repo.git/ ifndef::git-clone[] These two syntaxes are mostly equivalent, except when cloning, when diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index eeecb5d9fc..8ddaa16ac1 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.8.3.1 +DEF_VER=v1.8.3.3 LF=' ' @@ -69,6 +69,9 @@ all:: # Define NO_MSGFMT_EXTENDED_OPTIONS if your implementation of msgfmt # doesn't support GNU extensions like --check and --statistics # +# Define NEEDS_CLIPPED_WRITE if your write(2) cannot write more than +# INT_MAX bytes at once (e.g. MacOS X). +# # Define HAVE_PATHS_H if you have paths.h and want to use the default PATH # it specifies. # @@ -137,6 +140,10 @@ all:: # specify your own (or DarwinPort's) include directories and # library directories by defining CFLAGS and LDFLAGS appropriately. # +# Define NO_APPLE_COMMON_CRYPTO if you are building on Darwin/Mac OS X +# and do not want to use Apple's CommonCrypto library. This allows you +# to provide your own OpenSSL library, for example from MacPorts. +# # Define BLK_SHA1 environment variable to make use of the bundled # optimized C SHA1 routine. # @@ -558,6 +565,7 @@ TEST_PROGRAMS_NEED_X += test-mergesort TEST_PROGRAMS_NEED_X += test-mktemp TEST_PROGRAMS_NEED_X += test-parse-options TEST_PROGRAMS_NEED_X += test-path-utils +TEST_PROGRAMS_NEED_X += test-read-cache TEST_PROGRAMS_NEED_X += test-regex TEST_PROGRAMS_NEED_X += test-revision-walking TEST_PROGRAMS_NEED_X += test-run-command @@ -1054,6 +1062,11 @@ ifeq ($(uname_S),Darwin) BASIC_LDFLAGS += -L/opt/local/lib endif endif + ifndef NO_APPLE_COMMON_CRYPTO + APPLE_COMMON_CRYPTO = YesPlease + COMPAT_CFLAGS += -DAPPLE_COMMON_CRYPTO + endif + NO_REGEX = YesPlease PTHREAD_LIBS = endif @@ -1388,10 +1401,16 @@ ifdef PPC_SHA1 LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o LIB_H += ppc/sha1.h else +ifdef APPLE_COMMON_CRYPTO + COMPAT_CFLAGS += -DCOMMON_DIGEST_FOR_OPENSSL + SHA1_HEADER = <CommonCrypto/CommonDigest.h> +else SHA1_HEADER = <openssl/sha.h> EXTLIBS += $(LIB_4_CRYPTO) endif endif +endif + ifdef NO_PERL_MAKEMAKER export NO_PERL_MAKEMAKER endif @@ -1466,6 +1485,11 @@ ifndef NO_MSGFMT_EXTENDED_OPTIONS MSGFMT += --check --statistics endif +ifdef NEEDS_CLIPPED_WRITE + BASIC_CFLAGS += -DNEEDS_CLIPPED_WRITE + COMPAT_OBJS += compat/clipped-write.o +endif + ifneq (,$(XDL_FAST_HASH)) BASIC_CFLAGS += -DXDL_FAST_HASH endif @@ -2262,9 +2286,6 @@ check: common-cmds.h exit 1; \ fi -remove-dashes: - ./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS) - ### Installation rules ifneq ($(filter /%,$(firstword $(template_dir))),) @@ -2443,7 +2464,7 @@ profile-clean: $(RM) $(addsuffix *.gcda,$(addprefix $(PROFILE_DIR)/, $(object_dirs))) $(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs))) -clean: profile-clean +clean: profile-clean coverage-clean $(RM) *.o block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o vcs-svn/*.o \ builtin/*.o $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB) $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X @@ -2524,29 +2545,34 @@ check-builtins:: ### Test suite coverage testing # -.PHONY: coverage coverage-clean coverage-build coverage-report +.PHONY: coverage coverage-clean coverage-compile coverage-test coverage-report +.PHONY: coverage-clean-results coverage: - $(MAKE) coverage-build - $(MAKE) coverage-report + $(MAKE) coverage-test + $(MAKE) coverage-untested-functions object_dirs := $(sort $(dir $(OBJECTS))) -coverage-clean: +coverage-clean-results: $(RM) $(addsuffix *.gcov,$(object_dirs)) $(RM) $(addsuffix *.gcda,$(object_dirs)) - $(RM) $(addsuffix *.gcno,$(object_dirs)) $(RM) coverage-untested-functions $(RM) -r cover_db/ $(RM) -r cover_db_html/ +coverage-clean: coverage-clean-results + $(RM) $(addsuffix *.gcno,$(object_dirs)) + COVERAGE_CFLAGS = $(CFLAGS) -O0 -ftest-coverage -fprofile-arcs COVERAGE_LDFLAGS = $(CFLAGS) -O0 -lgcov GCOVFLAGS = --preserve-paths --branch-probabilities --all-blocks -coverage-build: coverage-clean +coverage-compile: $(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" all + +coverage-test: coverage-clean-results coverage-compile $(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" \ - -j1 test + DEFAULT_TEST_TARGET=test -j1 test coverage-report: $(QUIET_GCOV)for dir in $(object_dirs); do \ @@ -1 +1 @@ -Documentation/RelNotes/1.8.3.1.txt
\ No newline at end of file +Documentation/RelNotes/1.8.3.3.txt
\ No newline at end of file diff --git a/archive-zip.c b/archive-zip.c index b2c4fe0e9f..4bde019bce 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -232,7 +232,6 @@ static int write_zip_entry(struct archiver_args *args, size = 0; compressed_size = 0; buffer = NULL; - size = 0; } else if (S_ISREG(mode) || S_ISLNK(mode)) { enum object_type type = sha1_object_info(sha1, &size); @@ -197,6 +197,21 @@ int validate_new_branchname(const char *name, struct strbuf *ref, return 1; } +static int check_tracking_branch(struct remote *remote, void *cb_data) +{ + char *tracking_branch = cb_data; + struct refspec query; + memset(&query, 0, sizeof(struct refspec)); + query.dst = tracking_branch; + return !(remote_find_tracking(remote, &query) || + prefixcmp(query.src, "refs/heads/")); +} + +static int validate_remote_tracking_branch(char *ref) +{ + return !for_each_remote(check_tracking_branch, ref); +} + static const char upstream_not_branch[] = N_("Cannot setup tracking information; starting point '%s' is not a branch."); static const char upstream_missing[] = @@ -259,7 +274,7 @@ void create_branch(const char *head, case 1: /* Unique completion -- good, only if it is a real branch */ if (prefixcmp(real_ref, "refs/heads/") && - prefixcmp(real_ref, "refs/remotes/")) { + validate_remote_tracking_branch(real_ref)) { if (explicit_tracking) die(_(upstream_not_branch), start_name); else diff --git a/builtin/apply.c b/builtin/apply.c index faf8e30883..0e9b631db6 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -906,7 +906,7 @@ static void parse_traditional_patch(const char *first, const char *second, struc patch->old_name = name; } else { patch->old_name = name; - patch->new_name = xstrdup(name); + patch->new_name = null_strdup(name); } } if (!name) diff --git a/builtin/checkout.c b/builtin/checkout.c index 81b4419da5..f5b50e520f 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -825,38 +825,40 @@ static int git_checkout_config(const char *var, const char *value, void *cb) } struct tracking_name_data { - const char *name; - char *remote; + /* const */ char *src_ref; + char *dst_ref; + unsigned char *dst_sha1; int unique; }; -static int check_tracking_name(const char *refname, const unsigned char *sha1, - int flags, void *cb_data) +static int check_tracking_name(struct remote *remote, void *cb_data) { struct tracking_name_data *cb = cb_data; - const char *slash; - - if (prefixcmp(refname, "refs/remotes/")) - return 0; - slash = strchr(refname + 13, '/'); - if (!slash || strcmp(slash + 1, cb->name)) + struct refspec query; + memset(&query, 0, sizeof(struct refspec)); + query.src = cb->src_ref; + if (remote_find_tracking(remote, &query) || + get_sha1(query.dst, cb->dst_sha1)) return 0; - if (cb->remote) { + if (cb->dst_ref) { cb->unique = 0; return 0; } - cb->remote = xstrdup(refname); + cb->dst_ref = xstrdup(query.dst); return 0; } -static const char *unique_tracking_name(const char *name) +static const char *unique_tracking_name(const char *name, unsigned char *sha1) { - struct tracking_name_data cb_data = { NULL, NULL, 1 }; - cb_data.name = name; - for_each_ref(check_tracking_name, &cb_data); + struct tracking_name_data cb_data = { NULL, NULL, NULL, 1 }; + char src_ref[PATH_MAX]; + snprintf(src_ref, PATH_MAX, "refs/heads/%s", name); + cb_data.src_ref = src_ref; + cb_data.dst_sha1 = sha1; + for_each_remote(check_tracking_name, &cb_data); if (cb_data.unique) - return cb_data.remote; - free(cb_data.remote); + return cb_data.dst_ref; + free(cb_data.dst_ref); return NULL; } @@ -919,8 +921,8 @@ static int parse_branchname_arg(int argc, const char **argv, if (dwim_new_local_branch_ok && !check_filename(NULL, arg) && argc == 1) { - const char *remote = unique_tracking_name(arg); - if (!remote || get_sha1(remote, rev)) + const char *remote = unique_tracking_name(arg, rev); + if (!remote) return argcount; *new_branch = arg; arg = remote; diff --git a/builtin/clone.c b/builtin/clone.c index 035ab64950..dad4265989 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -546,8 +546,12 @@ static void update_remote_refs(const struct ref *refs, { const struct ref *rm = mapped_refs; + if (0 <= option_verbosity) + printf(_("Checking connectivity... ")); if (check_everything_connected(iterate_ref_map, 0, &rm)) die(_("remote did not send all necessary objects")); + if (0 <= option_verbosity) + printf(_("done\n")); if (refs) { write_remote_refs(mapped_refs); diff --git a/builtin/commit.c b/builtin/commit.c index d2f30d960a..1621dfcd40 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -107,7 +107,7 @@ static const char *cleanup_arg; static enum commit_whence whence; static int use_editor = 1, include_status = 1; -static int show_ignored_in_status; +static int show_ignored_in_status, have_option_m; static const char *only_include_assumed; static struct strbuf message = STRBUF_INIT; @@ -121,9 +121,11 @@ static enum { static int opt_parse_m(const struct option *opt, const char *arg, int unset) { struct strbuf *buf = opt->value; - if (unset) + if (unset) { + have_option_m = 0; strbuf_setlen(buf, 0); - else { + } else { + have_option_m = 1; if (buf->len) strbuf_addch(buf, '\n'); strbuf_addstr(buf, arg); @@ -975,7 +977,7 @@ static int parse_and_validate_options(int argc, const char *argv[], if (force_author && renew_authorship) die(_("Using both --reset-author and --author does not make sense")); - if (logfile || message.len || use_message || fixup_message) + if (logfile || have_option_m || use_message || fixup_message) use_editor = 0; if (0 <= edit_flag) use_editor = edit_flag; diff --git a/builtin/merge.c b/builtin/merge.c index 3e2daa37c3..2ebe732896 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -1054,7 +1054,8 @@ static struct commit_list *collect_parents(struct commit *head_commit, for (i = 0; i < argc; i++) { struct commit *commit = get_merge_parent(argv[i]); if (!commit) - die(_("%s - not something we can merge"), argv[i]); + help_unknown_ref(argv[i], "merge", + "not something we can merge"); remotes = &commit_list_insert(commit, remotes)->next; } *remotes = NULL; diff --git a/builtin/push.c b/builtin/push.c index 909c34dfda..2d84d10720 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -113,17 +113,19 @@ static NORETURN int die_push_simple(struct branch *branch, struct remote *remote remote->name, branch->name, advice_maybe); } +static const char message_detached_head_die[] = + N_("You are not currently on a branch.\n" + "To push the history leading to the current (detached HEAD)\n" + "state now, use\n" + "\n" + " git push %s HEAD:<name-of-remote-branch>\n"); + static void setup_push_upstream(struct remote *remote, int simple) { struct strbuf refspec = STRBUF_INIT; struct branch *branch = branch_get(NULL); if (!branch) - die(_("You are not currently on a branch.\n" - "To push the history leading to the current (detached HEAD)\n" - "state now, use\n" - "\n" - " git push %s HEAD:<name-of-remote-branch>\n"), - remote->name); + die(_(message_detached_head_die), remote->name); if (!branch->merge_nr || !branch->merge || !branch->remote_name) die(_("The current branch %s has no upstream branch.\n" "To push the current branch and set the remote as upstream, use\n" @@ -173,6 +175,8 @@ static void warn_unspecified_push_default_configuration(void) static void setup_default_push_refspecs(struct remote *remote) { + struct branch *branch; + switch (push_default) { default: case PUSH_DEFAULT_UNSPECIFIED: @@ -192,7 +196,10 @@ static void setup_default_push_refspecs(struct remote *remote) break; case PUSH_DEFAULT_CURRENT: - add_refspec("HEAD"); + branch = branch_get(NULL); + if (!branch) + die(_(message_detached_head_die), remote->name); + add_refspec(branch->name); break; case PUSH_DEFAULT_NOTHING: diff --git a/combine-diff.c b/combine-diff.c index 77d7872aaf..6dc06093d3 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -518,8 +518,11 @@ static int give_context(struct sline *sline, unsigned long cnt, int num_parent) unsigned long k; /* Paint a few lines before the first interesting line. */ - while (j < i) - sline[j++].flag |= mark | no_pre_delete; + while (j < i) { + if (!(sline[j].flag & mark)) + sline[j].flag |= no_pre_delete; + sline[j++].flag |= mark; + } again: /* we know up to i is to be included. where does the @@ -1302,6 +1305,7 @@ void diff_tree_combined(const unsigned char *sha1, int i, num_paths, needsep, show_log_first, num_parent = parents->nr; diffopts = *opt; + diff_tree_setup_paths(diffopts.pathspec.raw, &diffopts); diffopts.output_format = DIFF_FORMAT_NO_OUTPUT; DIFF_OPT_SET(&diffopts, RECURSIVE); DIFF_OPT_CLR(&diffopts, ALLOW_EXTERNAL); @@ -1372,6 +1376,8 @@ void diff_tree_combined(const unsigned char *sha1, paths = paths->next; free(tmp); } + + diff_tree_release_paths(&diffopts); } void diff_tree_combined_merge(const struct commit *commit, int dense, @@ -176,6 +176,8 @@ extern int for_each_commit_graft(each_commit_graft_fn, void *); extern int is_repository_shallow(void); extern struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag); +extern void check_shallow_file_for_update(void); +extern void set_alternate_shallow_file(const char *path); int is_descendant_of(struct commit *, struct commit_list *); int in_merge_bases(struct commit *, struct commit *); diff --git a/compat/clipped-write.c b/compat/clipped-write.c new file mode 100644 index 0000000000..b8f98ff77f --- /dev/null +++ b/compat/clipped-write.c @@ -0,0 +1,13 @@ +#include "../git-compat-util.h" +#undef write + +/* + * Version of write that will write at most INT_MAX bytes. + * Workaround a xnu bug on Mac OS X + */ +ssize_t clipped_write(int fildes, const void *buf, size_t nbyte) +{ + if (nbyte > INT_MAX) + nbyte = INT_MAX; + return write(fildes, buf, nbyte); +} @@ -566,7 +566,20 @@ static int git_default_core_config(const char *var, const char *value) trust_ctime = git_config_bool(var, value); return 0; } - if (!strcmp(var, "core.statinfo")) { + if (!strcmp(var, "core.statinfo") || + !strcmp(var, "core.checkstat")) { + /* + * NEEDSWORK: statinfo was a typo in v1.8.2 that has + * never been advertised. we will remove it at Git + * 2.0 boundary. + */ + if (!strcmp(var, "core.statinfo")) { + static int warned; + if (!warned++) { + warning("'core.statinfo' will be removed in Git 2.0; " + "use 'core.checkstat' instead."); + } + } if (!strcasecmp(value, "default")) check_stat = 1; else if (!strcasecmp(value, "minimal")) diff --git a/config.mak.uname b/config.mak.uname index d78fd3df5b..174703b67c 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -95,6 +95,7 @@ ifeq ($(uname_S),Darwin) NO_MEMMEM = YesPlease USE_ST_TIMESPEC = YesPlease HAVE_DEV_TTY = YesPlease + NEEDS_CLIPPED_WRITE = YesPlease COMPAT_OBJS += compat/precompose_utf8.o BASIC_CFLAGS += -DPRECOMPOSE_UNICODE endif diff --git a/configure.ac b/configure.ac index f3462d9c81..2f433939dc 100644 --- a/configure.ac +++ b/configure.ac @@ -193,7 +193,7 @@ AC_ARG_ENABLE([pthreads], [FLAGS is the value to pass to the compiler to enable POSIX Threads.] [The default if FLAGS is not specified is to try first -pthread] [and then -lpthread.] - [--without-pthreads will disable threading.])], + [--disable-pthreads will disable threading.])], [ if test "x$enableval" = "xyes"; then AC_MSG_NOTICE([Will try -pthread then -lpthread to enable POSIX Threads]) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 1c35eef56a..ecf58e0328 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -1246,7 +1246,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary --no-prefix --src-prefix= --dst-prefix= --inter-hunk-context= --patience --histogram --minimal - --raw + --raw --word-diff --dirstat --dirstat= --dirstat-by-file --dirstat-by-file= --cumulative --diff-algorithm= diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index eaf5c369aa..54e48299ae 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -124,7 +124,7 @@ __git_ps1_show_upstream () fi ;; svn-remote.*.url) - svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value" + svn_remote[$((${#svn_remote[@]} + 1))]="$value" svn_url_pattern+="\\|$value" upstream=svn+git # default upstream is SVN if available, else git ;; @@ -146,10 +146,11 @@ __git_ps1_show_upstream () svn*) # get the upstream from the "git-svn-id: ..." in a commit message # (git-svn uses essentially the same procedure internally) - local svn_upstream=($(git log --first-parent -1 \ + local -a svn_upstream + svn_upstream=($(git log --first-parent -1 \ --grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null)) if [[ 0 -ne ${#svn_upstream[@]} ]]; then - svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]} + svn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]} svn_upstream=${svn_upstream%@*} local n_stop="${#svn_remote[@]}" for ((n=1; n <= n_stop; n++)); do @@ -279,6 +280,7 @@ __git_ps1 () step=$(cat "$g/rebase-apply/next") total=$(cat "$g/rebase-apply/last") if [ -f "$g/rebase-apply/rebasing" ]; then + b="$(cat "$g/rebase-apply/head-name")" r="|REBASE" elif [ -f "$g/rebase-apply/applying" ]; then r="|AM" @@ -295,6 +297,7 @@ __git_ps1 () r="|BISECTING" fi + test -n "$b" || b="$(git symbolic-ref HEAD 2>/dev/null)" || { detached=yes b="$( diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh index 8a23f58ba0..51ae932e5e 100755 --- a/contrib/subtree/git-subtree.sh +++ b/contrib/subtree/git-subtree.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # # git-subtree.sh: split/join git repositories in subdirectories of this one # @@ -715,7 +715,8 @@ cmd_push() repository=$1 refspec=$2 echo "git push using: " $repository $refspec - git push $repository $(git subtree split --prefix=$prefix):refs/heads/$refspec + localrev=$(git subtree split --prefix="$prefix") || die + git push $repository $localrev:refs/heads/$refspec else die "'$dir' must already exist. Try 'git subtree add'." fi diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c index 63722f86dc..c97ac9b463 100644 --- a/diffcore-pickaxe.c +++ b/diffcore-pickaxe.c @@ -122,7 +122,7 @@ static void diffcore_pickaxe_grep(struct diff_options *o) char errbuf[1024]; regerror(err, ®ex, errbuf, 1024); regfree(®ex); - die("invalid log-grep regex: %s", errbuf); + die("invalid regex: %s", errbuf); } pickaxe(&diff_queued_diff, o, ®ex, NULL, diff_grep); @@ -246,7 +246,7 @@ static void diffcore_pickaxe_count(struct diff_options *o) char errbuf[1024]; regerror(err, ®ex, errbuf, 1024); regfree(®ex); - die("invalid pickaxe regex: %s", errbuf); + die("invalid regex: %s", errbuf); } regexp = ®ex; } else { diff --git a/fetch-pack.c b/fetch-pack.c index f156dd4fac..6b5467c6de 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -20,6 +20,8 @@ static int no_done; static int fetch_fsck_objects = -1; static int transfer_fsck_objects = -1; static int agent_supported; +static struct lock_file shallow_lock; +static const char *alternate_shallow_file; #define COMPLETE (1U << 0) #define COMMON (1U << 1) @@ -683,7 +685,7 @@ static int get_pack(struct fetch_pack_args *args, int xd[2], char **pack_lockfile) { struct async demux; - const char *argv[20]; + const char *argv[22]; char keep_arg[256]; char hdr_arg[256]; const char **av; @@ -724,6 +726,11 @@ static int get_pack(struct fetch_pack_args *args, do_keep = 1; } + if (alternate_shallow_file) { + *av++ = "--shallow-file"; + *av++ = alternate_shallow_file; + } + if (do_keep) { if (pack_lockfile) cmd.out = -1; @@ -779,6 +786,27 @@ static int cmp_ref_by_name(const void *a_, const void *b_) return strcmp(a->name, b->name); } +static void setup_alternate_shallow(void) +{ + struct strbuf sb = STRBUF_INIT; + int fd; + + check_shallow_file_for_update(); + fd = hold_lock_file_for_update(&shallow_lock, git_path("shallow"), + LOCK_DIE_ON_ERROR); + if (write_shallow_commits(&sb, 0)) { + if (write_in_full(fd, sb.buf, sb.len) != sb.len) + die_errno("failed to write to %s", shallow_lock.filename); + alternate_shallow_file = shallow_lock.filename; + } else + /* + * is_repository_shallow() sees empty string as "no + * shallow file". + */ + alternate_shallow_file = ""; + strbuf_release(&sb); +} + static struct ref *do_fetch_pack(struct fetch_pack_args *args, int fd[2], const struct ref *orig_ref, @@ -858,6 +886,8 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, if (args->stateless_rpc) packet_flush(fd[1]); + if (args->depth > 0) + setup_alternate_shallow(); if (get_pack(args, fd, pack_lockfile)) die("git fetch-pack: fetch failed."); @@ -936,15 +966,9 @@ struct ref *fetch_pack(struct fetch_pack_args *args, struct ref **sought, int nr_sought, char **pack_lockfile) { - struct stat st; struct ref *ref_cpy; fetch_pack_setup(); - if (args->depth > 0) { - if (stat(git_path("shallow"), &st)) - st.st_mtime = 0; - } - if (nr_sought) nr_sought = remove_duplicates_in_refs(sought, nr_sought); @@ -954,35 +978,12 @@ struct ref *fetch_pack(struct fetch_pack_args *args, } ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, pack_lockfile); - if (args->depth > 0) { - static struct lock_file lock; - struct cache_time mtime; - struct strbuf sb = STRBUF_INIT; - char *shallow = git_path("shallow"); - int fd; - - mtime.sec = st.st_mtime; - mtime.nsec = ST_MTIME_NSEC(st); - if (stat(shallow, &st)) { - if (mtime.sec) - die("shallow file was removed during fetch"); - } else if (st.st_mtime != mtime.sec -#ifdef USE_NSEC - || ST_MTIME_NSEC(st) != mtime.nsec -#endif - ) - die("shallow file was changed during fetch"); - - fd = hold_lock_file_for_update(&lock, shallow, - LOCK_DIE_ON_ERROR); - if (!write_shallow_commits(&sb, 0) - || write_in_full(fd, sb.buf, sb.len) != sb.len) { - unlink_or_warn(shallow); - rollback_lock_file(&lock); - } else { - commit_lock_file(&lock); - } - strbuf_release(&sb); + if (alternate_shallow_file) { + if (*alternate_shallow_file == '\0') { /* --unshallow */ + unlink_or_warn(git_path("shallow")); + rollback_lock_file(&shallow_lock); + } else + commit_lock_file(&shallow_lock); } reprepare_packed_git(); diff --git a/fixup-builtins b/fixup-builtins deleted file mode 100755 index 63dfa4c475..0000000000 --- a/fixup-builtins +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -while [ "$1" ] -do - if [ "$1" != "git-sh-setup" -a "$1" != "git-parse-remote" -a "$1" != "git-svn" ]; then - old="$1" - new=$(echo "$1" | sed 's/git-/git /') - echo "Converting '$old' to '$new'" - sed -i "s/\\<$old\\>/$new/g" $(git ls-files '*.sh') - fi - shift -done - -sed -i 's/git merge-one-file/git-merge-one-file/g -s/git rebase-todo/git-rebase-todo/g' $(git ls-files '*.sh') -git update-index --refresh >& /dev/null -exit 0 diff --git a/git-bisect.sh b/git-bisect.sh index d7518e9c3b..9f064b6f4f 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -320,8 +320,8 @@ bisect_next() { elif test $res -eq 2 then echo "# only skipped commits left to test" >>"$GIT_DIR/BISECT_LOG" - good_revs=$(git for-each-ref --format="--not %(objectname)" "refs/bisect/good-*") - for skipped in $(git rev-list refs/bisect/bad $good_revs) + good_revs=$(git for-each-ref --format="%(objectname)" "refs/bisect/good-*") + for skipped in $(git rev-list refs/bisect/bad --not $good_revs) do skipped_commit=$(git show-branch $skipped) echo "# possible first bad commit: $skipped_commit" >>"$GIT_DIR/BISECT_LOG" diff --git a/git-compat-util.h b/git-compat-util.h index c1f8a477fb..660b7f012a 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -185,6 +185,11 @@ int get_st_mode_bits(const char *path, int *mode); #define probe_utf8_pathname_composition(a,b) #endif +#ifdef NEEDS_CLIPPED_WRITE +ssize_t clipped_write(int fildes, const void *buf, size_t nbyte); +#define write(x,y,z) clipped_write((x),(y),(z)) +#endif + #ifdef MKDIR_WO_TRAILING_SLASH #define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b)) extern int compat_mkdir_wo_trailing_slash(const char*, mode_t); diff --git a/git-difftool.perl b/git-difftool.perl index 8a75205537..e57d3d1295 100755 --- a/git-difftool.perl +++ b/git-difftool.perl @@ -85,13 +85,9 @@ sub exit_cleanup sub use_wt_file { - my ($repo, $workdir, $file, $sha1, $symlinks) = @_; + my ($repo, $workdir, $file, $sha1) = @_; my $null_sha1 = '0' x 40; - if ($sha1 ne $null_sha1 and not $symlinks) { - return 0; - } - if (! -e "$workdir/$file") { # If the file doesn't exist in the working tree, we cannot # use it. @@ -213,8 +209,7 @@ EOF if ($rmode ne $null_mode) { my ($use, $wt_sha1) = use_wt_file($repo, $workdir, - $dst_path, $rsha1, - $symlinks); + $dst_path, $rsha1); if ($use) { push @working_tree, $dst_path; $wtindex .= "$rmode $wt_sha1\t$dst_path\0"; diff --git a/git-pull.sh b/git-pull.sh index 638aabb7b3..6828e2c715 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -266,10 +266,17 @@ case "$merge_head" in ;; esac +# Pulling into unborn branch: a shorthand for branching off +# FETCH_HEAD, for lazy typers. if test -z "$orig_head" then - git update-ref -m "initial pull" HEAD $merge_head "$curr_head" && - git read-tree -m -u HEAD || exit 1 + # Two-way merge: we claim the index is based on an empty tree, + # and try to fast-forward to HEAD. This ensures we will not + # lose index/worktree changes that the user already made on + # the unborn branch. + empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 + git read-tree -m -u $empty_tree $merge_head && + git update-ref -m "initial pull" HEAD $merge_head "$curr_head" exit fi diff --git a/git-send-email.perl b/git-send-email.perl index bd13cc812d..cd93490c87 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -760,6 +760,11 @@ if (!defined $sender) { $sender = $repoauthor || $repocommitter || ''; } +# $sender could be an already sanitized address +# (e.g. sendemail.from could be manually sanitized by user). +# But it's a no-op to run sanitize_address on an already sanitized address. +$sender = sanitize_address($sender); + my $prompting = 0; if (!@initial_to && !defined $to_cmd) { my $to = ask("Who should the emails be sent to (if any)? ", @@ -1113,10 +1118,9 @@ sub send_message { if ($cc ne '') { $ccline = "\nCc: $cc"; } - my $sanitized_sender = sanitize_address($sender); make_message_id() unless defined($message_id); - my $header = "From: $sanitized_sender + my $header = "From: $sender To: $to${ccline} Subject: $subject Date: $date @@ -1133,7 +1137,7 @@ X-Mailer: git-send-email $gitversion } my @sendmail_parameters = ('-i', @recipients); - my $raw_from = $sanitized_sender; + my $raw_from = $sender; if (defined $envelope_sender && $envelope_sender ne "auto") { $raw_from = $envelope_sender; } @@ -1270,6 +1274,7 @@ foreach my $t (@files) { open my $fh, "<", $t or die "can't open file $t"; my $author = undef; + my $sauthor = undef; my $author_encoding; my $has_content_type; my $body_encoding; @@ -1308,8 +1313,9 @@ foreach my $t (@files) { } elsif (/^From:\s+(.*)$/i) { ($author, $author_encoding) = unquote_rfc2047($1); + $sauthor = sanitize_address($author); next if $suppress_cc{'author'}; - next if $suppress_cc{'self'} and $author eq $sender; + next if $suppress_cc{'self'} and $sauthor eq $sender; printf("(mbox) Adding cc: %s from line '%s'\n", $1, $_) unless $quiet; push @cc, $1; @@ -1323,7 +1329,9 @@ foreach my $t (@files) { } elsif (/^Cc:\s+(.*)$/i) { foreach my $addr (parse_address_line($1)) { - if (unquote_rfc2047($addr) eq $sender) { + my $qaddr = unquote_rfc2047($addr); + my $saddr = sanitize_address($qaddr); + if ($saddr eq $sender) { next if ($suppress_cc{'self'}); } else { next if ($suppress_cc{'cc'}); @@ -1370,7 +1378,8 @@ foreach my $t (@files) { chomp; my ($what, $c) = ($1, $2); chomp $c; - if ($c eq $sender) { + my $sc = sanitize_address($c); + if ($sc eq $sender) { next if ($suppress_cc{'self'}); } else { next if $suppress_cc{'sob'} and $what =~ /Signed-off-by/i; @@ -1400,7 +1409,7 @@ foreach my $t (@files) { $subject = quote_subject($subject, $auto_8bit_encoding); } - if (defined $author and $author ne $sender) { + if (defined $sauthor and $sauthor ne $sender) { $message = "From: $author\n\n$message"; if (defined $author_encoding) { if ($has_content_type) { @@ -1454,7 +1463,6 @@ foreach my $t (@files) { sub recipients_cmd { my ($prefix, $what, $cmd, $file) = @_; - my $sanitized_sender = sanitize_address($sender); my @addresses = (); open my $fh, "-|", "$cmd \Q$file\E" or die "($prefix) Could not execute '$cmd'"; @@ -1462,7 +1470,7 @@ sub recipients_cmd { $address =~ s/^\s*//g; $address =~ s/\s*$//g; $address = sanitize_address($address); - next if ($address eq $sanitized_sender and $suppress_from); + next if ($address eq $sender and $suppress_cc{'self'}); push @addresses, $address; printf("($prefix) Adding %s: %s from: '%s'\n", $what, $address, $cmd) unless $quiet; diff --git a/git-submodule.sh b/git-submodule.sh index 79bfaac9d4..48bdf84324 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -113,7 +113,7 @@ resolve_relative_url () module_list() { ( - git ls-files --error-unmatch --stage -- "$@" || + git ls-files -z --error-unmatch --stage -- "$@" || echo "unmatched pathspec exists" ) | perl -e ' @@ -121,6 +121,7 @@ module_list() my ($null_sha1) = ("0" x 40); my @out = (); my $unmatched = 0; + $/ = "\0"; while (<STDIN>) { if (/^unmatched pathspec/) { $unmatched = 1; @@ -4,6 +4,7 @@ #include "help.h" #include "quote.h" #include "run-command.h" +#include "commit.h" const char git_usage_string[] = "git [--version] [--help] [-c name=value]\n" @@ -146,6 +147,12 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "0", 1); if (envchanged) *envchanged = 1; + } else if (!strcmp(cmd, "--shallow-file")) { + (*argv)++; + (*argc)--; + set_alternate_shallow_file((*argv)[0]); + if (envchanged) + *envchanged = 1; } else { fprintf(stderr, "Unknown option: %s\n", cmd); usage(git_usage_string); diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 80950c018d..8d69ada042 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1086,7 +1086,7 @@ sub evaluate_and_validate_params { our $search_use_regexp = $input_params{'search_use_regexp'}; our $searchtext = $input_params{'searchtext'}; - our $search_regexp; + our $search_regexp = undef; if (defined $searchtext) { if (length($searchtext) < 2) { die_error(403, "At least two characters are required for search parameter"); @@ -7,6 +7,7 @@ #include "string-list.h" #include "column.h" #include "version.h" +#include "refs.h" void add_cmdname(struct cmdnames *cmds, const char *name, int len) { @@ -404,3 +405,52 @@ int cmd_version(int argc, const char **argv, const char *prefix) printf("git version %s\n", git_version_string); return 0; } + +struct similar_ref_cb { + const char *base_ref; + struct string_list *similar_refs; +}; + +static int append_similar_ref(const char *refname, const unsigned char *sha1, + int flags, void *cb_data) +{ + struct similar_ref_cb *cb = (struct similar_ref_cb *)(cb_data); + char *branch = strrchr(refname, '/') + 1; + /* A remote branch of the same name is deemed similar */ + if (!prefixcmp(refname, "refs/remotes/") && + !strcmp(branch, cb->base_ref)) + string_list_append(cb->similar_refs, + refname + strlen("refs/remotes/")); + return 0; +} + +static struct string_list guess_refs(const char *ref) +{ + struct similar_ref_cb ref_cb; + struct string_list similar_refs = STRING_LIST_INIT_NODUP; + + ref_cb.base_ref = ref; + ref_cb.similar_refs = &similar_refs; + for_each_ref(append_similar_ref, &ref_cb); + return similar_refs; +} + +void help_unknown_ref(const char *ref, const char *cmd, const char *error) +{ + int i; + struct string_list suggested_refs = guess_refs(ref); + + fprintf_ln(stderr, _("%s: %s - %s"), cmd, ref, error); + + if (suggested_refs.nr > 0) { + fprintf_ln(stderr, + Q_("\nDid you mean this?", + "\nDid you mean one of these?", + suggested_refs.nr)); + for (i = 0; i < suggested_refs.nr; i++) + fprintf(stderr, "\t%s\n", suggested_refs.items[i].string); + } + + string_list_clear(&suggested_refs, 0); + exit(1); +} @@ -27,4 +27,9 @@ extern void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); extern int is_in_cmdlist(struct cmdnames *cmds, const char *name); extern void list_commands(unsigned int colopts, struct cmdnames *main_cmds, struct cmdnames *other_cmds); +/* + * call this to die(), when it is suspected that the user mistyped a + * ref to the command, to give suggested "correct" refs. + */ +extern void help_unknown_ref(const char *ref, const char *cmd, const char *error); #endif /* HELP_H */ @@ -228,9 +228,15 @@ static void init_curl_http_auth(CURL *result) #else { static struct strbuf up = STRBUF_INIT; - strbuf_reset(&up); - strbuf_addf(&up, "%s:%s", - http_auth.username, http_auth.password); + /* + * Note that we assume we only ever have a single set of + * credentials in a given program run, so we do not have + * to worry about updating this buffer, only setting its + * initial value. + */ + if (!up.len) + strbuf_addf(&up, "%s:%s", + http_auth.username, http_auth.password); curl_easy_setopt(result, CURLOPT_USERPWD, up.buf); } #endif diff --git a/imap-send.c b/imap-send.c index d9bcfb44dc..d6b65e204c 100644 --- a/imap-send.c +++ b/imap-send.c @@ -29,8 +29,18 @@ #ifdef NO_OPENSSL typedef void *SSL; #else +#ifdef APPLE_COMMON_CRYPTO +#include <CommonCrypto/CommonHMAC.h> +#define HMAC_CTX CCHmacContext +#define HMAC_Init(hmac, key, len, algo) CCHmacInit(hmac, algo, key, len) +#define HMAC_Update CCHmacUpdate +#define HMAC_Final(hmac, hash, ptr) CCHmacFinal(hmac, hash) +#define HMAC_CTX_cleanup(ignore) +#define EVP_md5() kCCHmacAlgMD5 +#else #include <openssl/evp.h> #include <openssl/hmac.h> +#endif #include <openssl/x509v3.h> #endif diff --git a/read-cache.c b/read-cache.c index 04ed561bfe..d97e3bf7cd 100644 --- a/read-cache.c +++ b/read-cache.c @@ -626,7 +626,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, if (*ptr == '/') { struct cache_entry *foundce; ++ptr; - foundce = index_name_exists(&the_index, ce->name, ptr - ce->name, ignore_case); + foundce = index_name_exists(istate, ce->name, ptr - ce->name, ignore_case); if (foundce) { memcpy((void *)startPtr, foundce->name + (startPtr - ce->name), ptr - startPtr); startPtr = ptr; @@ -979,7 +979,7 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti if (istate->cache_nr == istate->cache_alloc) { istate->cache_alloc = alloc_nr(istate->cache_alloc); istate->cache = xrealloc(istate->cache, - istate->cache_alloc * sizeof(struct cache_entry *)); + istate->cache_alloc * sizeof(*istate->cache)); } /* Add it in.. */ @@ -1449,7 +1449,7 @@ int read_index_from(struct index_state *istate, const char *path) istate->version = ntohl(hdr->hdr_version); istate->cache_nr = ntohl(hdr->hdr_entries); istate->cache_alloc = alloc_nr(istate->cache_nr); - istate->cache = xcalloc(istate->cache_alloc, sizeof(struct cache_entry *)); + istate->cache = xcalloc(istate->cache_alloc, sizeof(*istate->cache)); istate->initialized = 1; if (istate->version == 4) @@ -1518,8 +1518,9 @@ int discard_index(struct index_state *istate) free_name_hash(istate); cache_tree_free(&(istate->cache_tree)); istate->initialized = 0; - - /* no need to throw away allocated active_cache */ + free(istate->cache); + istate->cache = NULL; + istate->cache_alloc = 0; return 0; } diff --git a/revision.c b/revision.c index a67b615bfc..7f7a8ab7cb 100644 --- a/revision.c +++ b/revision.c @@ -915,6 +915,19 @@ static void add_rev_cmdline(struct rev_info *revs, info->nr++; } +static void add_rev_cmdline_list(struct rev_info *revs, + struct commit_list *commit_list, + int whence, + unsigned flags) +{ + while (commit_list) { + struct object *object = &commit_list->item->object; + add_rev_cmdline(revs, object, sha1_to_hex(object->sha1), + whence, flags); + commit_list = commit_list->next; + } +} + struct all_refs_cb { int all_flags; int warned_bad_reflog; @@ -1092,6 +1105,7 @@ static void prepare_show_merge(struct rev_info *revs) add_pending_object(revs, &head->object, "HEAD"); add_pending_object(revs, &other->object, "MERGE_HEAD"); bases = get_merge_bases(head, other, 1); + add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING); add_pending_commit_list(revs, bases, UNINTERESTING); free_commit_list(bases); head->object.flags |= SYMMETRIC_LEFT; @@ -1179,6 +1193,9 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi if (symmetric) { exclude = get_merge_bases(a, b, 1); + add_rev_cmdline_list(revs, exclude, + REV_CMD_MERGE_BASE, + flags_exclude); add_pending_commit_list(revs, exclude, flags_exclude); free_commit_list(exclude); diff --git a/revision.h b/revision.h index 01bd2b7c07..878a5556fd 100644 --- a/revision.h +++ b/revision.h @@ -35,6 +35,7 @@ struct rev_cmdline_info { REV_CMD_PARENTS_ONLY, REV_CMD_LEFT, REV_CMD_RIGHT, + REV_CMD_MERGE_BASE, REV_CMD_REV } whence; unsigned flags; diff --git a/sequencer.c b/sequencer.c index ab6f8a722d..f7be7d8be6 100644 --- a/sequencer.c +++ b/sequencer.c @@ -474,7 +474,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts) struct commit_message msg = { NULL, NULL, NULL, NULL, NULL }; char *defmsg = NULL; struct strbuf msgbuf = STRBUF_INIT; - int res, unborn = 0; + int res, unborn = 0, allow; if (opts->no_commit) { /* @@ -624,14 +624,18 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts) msg.subject); print_advice(res == 1, opts); rerere(opts->allow_rerere_auto); - } else { - int allow = allow_empty(opts, commit); - if (allow < 0) - return allow; - if (!opts->no_commit) - res = run_git_commit(defmsg, opts, allow); + goto leave; + } + + allow = allow_empty(opts, commit); + if (allow < 0) { + res = allow; + goto leave; } + if (!opts->no_commit) + res = run_git_commit(defmsg, opts, allow); +leave: free_message(&msg); free(defmsg); diff --git a/sha1_name.c b/sha1_name.c index 3820f28ae7..b3a90e6f05 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -517,12 +517,21 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) } if (read_ref_at(real_ref, at_time, nth, sha1, NULL, &co_time, &co_tz, &co_cnt)) { + if (!len) { + if (!prefixcmp(real_ref, "refs/heads/")) { + str = real_ref + 11; + len = strlen(real_ref + 11); + } else { + /* detached HEAD */ + str = "HEAD"; + len = 4; + } + } if (at_time) warning("Log for '%.*s' only goes " "back to %s.", len, str, show_date(co_time, co_tz, DATE_RFC2822)); else { - free(real_ref); die("Log for '%.*s' only has %d entries.", len, str, co_cnt); } @@ -1033,14 +1042,15 @@ int interpret_branch_name(const char *name, struct strbuf *buf) * points to something different than a branch. */ if (!upstream) - return error(_("HEAD does not point to a branch")); + die(_("HEAD does not point to a branch")); if (!upstream->merge || !upstream->merge[0]->dst) { if (!ref_exists(upstream->refname)) - return error(_("No such branch: '%s'"), cp); - if (!upstream->merge) - return error(_("No upstream configured for branch '%s'"), - upstream->name); - return error( + die(_("No such branch: '%s'"), cp); + if (!upstream->merge) { + die(_("No upstream configured for branch '%s'"), + upstream->name); + } + die( _("Upstream branch '%s' not stored as a remote-tracking branch"), upstream->merge[0]->src); } @@ -1055,9 +1065,13 @@ int interpret_branch_name(const char *name, struct strbuf *buf) int strbuf_branchname(struct strbuf *sb, const char *name) { int len = strlen(name); - if (interpret_branch_name(name, sb) == len) + int used = interpret_branch_name(name, sb); + + if (used == len) return 0; - strbuf_add(sb, name, len); + if (used < 0) + used = 0; + strbuf_add(sb, name + used, len - used); return len; } @@ -3,6 +3,16 @@ #include "tag.h" static int is_shallow = -1; +static struct stat shallow_stat; +static char *alternate_shallow_file; + +void set_alternate_shallow_file(const char *path) +{ + if (is_shallow != -1) + die("BUG: is_repository_shallow must not be called before set_alternate_shallow_file"); + free(alternate_shallow_file); + alternate_shallow_file = path ? xstrdup(path) : NULL; +} int register_shallow(const unsigned char *sha1) { @@ -21,12 +31,21 @@ int is_repository_shallow(void) { FILE *fp; char buf[1024]; + const char *path = alternate_shallow_file; if (is_shallow >= 0) return is_shallow; - fp = fopen(git_path("shallow"), "r"); - if (!fp) { + if (!path) + path = git_path("shallow"); + /* + * fetch-pack sets '--shallow-file ""' as an indicator that no + * shallow file should be used. We could just open it and it + * will likely fail. But let's do an explicit check instead. + */ + if (!*path || + stat(path, &shallow_stat) || + (fp = fopen(path, "r")) == NULL) { is_shallow = 0; return is_shallow; } @@ -108,3 +127,22 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth, return result; } + +void check_shallow_file_for_update(void) +{ + struct stat st; + + if (!is_shallow) + return; + else if (is_shallow == -1) + die("BUG: shallow must be initialized by now"); + + if (stat(git_path("shallow"), &st)) + die("shallow file was removed during fetch"); + else if (st.st_mtime != shallow_stat.st_mtime +#ifdef USE_NSEC + || ST_MTIME_NSEC(st) != ST_MTIME_NSEC(shallow_stat) +#endif + ) + die("shallow file was changed during fetch"); +} @@ -595,6 +595,20 @@ library for your script to use. test_cmp expected actual ' + - test_ln_s_add <path1> <path2> + + This function helps systems whose filesystem does not support symbolic + links. Use it to add a symbolic link entry to the index when it is not + important that the file system entry is a symbolic link, i.e., instead + of the sequence + + ln -s foo bar && + git add bar + + Sometimes it is possible to split a test in a part that does not need + the symbolic link in the file system and a part that does; then only + the latter part need be protected by a SYMLINKS prerequisite (see below). + Prerequisites ------------- diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index b5bce459b6..dd17e3a09d 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -1,5 +1,4 @@ ServerName dummy -LockFile accept.lock PidFile httpd.pid DocumentRoot www LogFormat "%h %l %u %t \"%r\" %>s %b" common @@ -24,6 +23,10 @@ ErrorLog error.log LoadModule version_module modules/mod_version.so </IfModule> +<IfVersion < 2.4> +LockFile accept.lock +</IfVersion> + <IfVersion < 2.1> <IfModule !mod_auth.c> LoadModule auth_module modules/mod_auth.so @@ -45,6 +48,21 @@ ErrorLog error.log </IfModule> </IfVersion> +<IfVersion >= 2.4> +<IfModule !mod_authn_core.c> + LoadModule authn_core_module modules/mod_authn_core.so +</IfModule> +<IfModule !mod_authz_core.c> + LoadModule authz_core_module modules/mod_authz_core.so +</IfModule> +<IfModule !mod_access_compat.c> + LoadModule access_compat_module modules/mod_access_compat.so +</IfModule> +<IfModule !mod_mpm_prefork.c> + LoadModule mpm_prefork_module modules/mod_mpm_prefork.so +</IfModule> +</IfVersion> + PassEnv GIT_VALGRIND PassEnv GIT_VALGRIND_OPTIONS diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 6ccf797091..8098a88c82 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -17,6 +17,8 @@ # ("squash", "fixup", "edit", or "reword") and the SHA1 taken # from the specified line. # +# "exec_cmd_with_args" -- add an "exec cmd with args" line. +# # "#" -- Add a comment line. # # ">" -- Add a blank line. diff --git a/t/perf/p0002-read-cache.sh b/t/perf/p0002-read-cache.sh new file mode 100755 index 0000000000..9180ae9343 --- /dev/null +++ b/t/perf/p0002-read-cache.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +test_description="Tests performance of reading the index" + +. ./perf-lib.sh + +test_perf_default_repo + +count=1000 +test_perf "read_cache/discard_cache $count times" " + test-read-cache $count +" + +test_done diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index cefe33d6d1..0f1318056c 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -367,22 +367,6 @@ test_expect_success 'validate object ID of a known tree' ' # Various types of objects -# Some filesystems do not support symblic links; on such systems -# some expected values are different -if test_have_prereq SYMLINKS -then - expectfilter=cat - expectedtree=087704a96baf1c2d1c869a8b084481e121c88b5b - expectedptree1=21ae8269cacbe57ae09138dcc3a2887f904d02b3 - expectedptree2=3c5e5399f3a333eddecce7a9b9465b63f65f51e2 -else - expectfilter='grep -v sym' - expectedtree=8e18edf7d7edcf4371a3ac6ae5f07c2641db7c46 - expectedptree1=cfb8591b2f65de8b8cc1020cd7d9e67e7793b325 - expectedptree2=ce580448f0148b985a513b693fdf7d802cacb44f -fi - - test_expect_success 'adding various types of objects with git update-index --add' ' mkdir path2 path3 path3/subp3 && paths="path0 path2/file2 path3/file3 path3/subp3/file3" && @@ -390,10 +374,7 @@ test_expect_success 'adding various types of objects with git update-index --add for p in $paths do echo "hello $p" >$p || exit 1 - if test_have_prereq SYMLINKS - then - ln -s "hello $p" ${p}sym || exit 1 - fi + test_ln_s_add "hello $p" ${p}sym || exit 1 done ) && find path* ! -type d -print | xargs git update-index --add @@ -405,7 +386,7 @@ test_expect_success 'showing stage with git ls-files --stage' ' ' test_expect_success 'validate git ls-files output for a known tree' ' - $expectfilter >expected <<-\EOF && + cat >expected <<-\EOF && 100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2 @@ -423,14 +404,14 @@ test_expect_success 'writing tree out with git write-tree' ' ' test_expect_success 'validate object ID for a known tree' ' - test "$tree" = "$expectedtree" + test "$tree" = 087704a96baf1c2d1c869a8b084481e121c88b5b ' test_expect_success 'showing tree with git ls-tree' ' git ls-tree $tree >current ' -test_expect_success SYMLINKS 'git ls-tree output for a known tree' ' +test_expect_success 'git ls-tree output for a known tree' ' cat >expected <<-\EOF && 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym @@ -447,7 +428,7 @@ test_expect_success 'showing tree with git ls-tree -r' ' ' test_expect_success 'git ls-tree -r output for a known tree' ' - $expectfilter >expected <<-\EOF && + cat >expected <<-\EOF && 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym 100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 @@ -465,7 +446,7 @@ test_expect_success 'showing tree with git ls-tree -r -t' ' git ls-tree -r -t $tree >current ' -test_expect_success SYMLINKS 'git ls-tree -r output for a known tree' ' +test_expect_success 'git ls-tree -r output for a known tree' ' cat >expected <<-\EOF && 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym @@ -487,7 +468,7 @@ test_expect_success 'writing partial tree out with git write-tree --prefix' ' ' test_expect_success 'validate object ID for a known tree' ' - test "$ptree" = "$expectedptree1" + test "$ptree" = 21ae8269cacbe57ae09138dcc3a2887f904d02b3 ' test_expect_success 'writing partial tree out with git write-tree --prefix' ' @@ -495,7 +476,7 @@ test_expect_success 'writing partial tree out with git write-tree --prefix' ' ' test_expect_success 'validate object ID for a known tree' ' - test "$ptree" = "$expectedptree2" + test "$ptree" = 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 ' test_expect_success 'put invalid objects into the index' ' @@ -529,7 +510,7 @@ test_expect_success 'git read-tree followed by write-tree should be idempotent' ' test_expect_success 'validate git diff-files output for a know cache/work tree state' ' - $expectfilter >expected <<\EOF && + cat >expected <<\EOF && :100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M path0 :120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M path0sym :100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M path2/file2 @@ -553,7 +534,7 @@ test_expect_success 'no diff after checkout and git update-index --refresh' ' ' ################################################################ -P=$expectedtree +P=087704a96baf1c2d1c869a8b084481e121c88b5b test_expect_success 'git commit-tree records the correct tree in a commit' ' commit0=$(echo NO | git commit-tree $P) && diff --git a/t/t0100-previous.sh b/t/t0100-previous.sh index 315b9b3f10..e0a6940232 100755 --- a/t/t0100-previous.sh +++ b/t/t0100-previous.sh @@ -27,6 +27,7 @@ test_expect_success 'merge @{-1}' ' test_commit B && git checkout A && test_commit C && + test_commit D && git branch -f master B && git branch -f other && git checkout other && @@ -35,14 +36,24 @@ test_expect_success 'merge @{-1}' ' git cat-file commit HEAD | grep "Merge branch '\''other'\''" ' -test_expect_success 'merge @{-1} when there is not enough switches yet' ' +test_expect_success 'merge @{-1}~1' ' + git checkout master && + git reset --hard B && + git checkout other && + git checkout master && + git merge @{-1}~1 && + git cat-file commit HEAD >actual && + grep "Merge branch '\''other'\''" actual +' + +test_expect_success 'merge @{-100} before checking out that many branches yet' ' git reflog expire --expire=now && git checkout -f master && git reset --hard B && git branch -f other C && git checkout other && git checkout master && - test_must_fail git merge @{-12} + test_must_fail git merge @{-100} ' test_done diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh index b3ae7d52c6..3e72aff470 100755 --- a/t/t1004-read-tree-m-u-wf.sh +++ b/t/t1004-read-tree-m-u-wf.sh @@ -158,7 +158,7 @@ test_expect_success '3-way not overwriting local changes (their side)' ' ' -test_expect_success SYMLINKS 'funny symlink in work tree' ' +test_expect_success 'funny symlink in work tree' ' git reset --hard && git checkout -b sym-b side-b && @@ -170,15 +170,14 @@ test_expect_success SYMLINKS 'funny symlink in work tree' ' rm -fr a && git checkout -b sym-a side-a && mkdir -p a && - ln -s ../b a/b && - git add a/b && + test_ln_s_add ../b a/b && git commit -m "we add a/b" && read_tree_u_must_succeed -m -u sym-a sym-a sym-b ' -test_expect_success SYMLINKS,SANITY 'funny symlink in work tree, un-unlink-able' ' +test_expect_success SANITY 'funny symlink in work tree, un-unlink-able' ' rm -fr a b && git reset --hard && diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh index b27a7209f7..2a19e797eb 100755 --- a/t/t1507-rev-parse-upstream.sh +++ b/t/t1507-rev-parse-upstream.sh @@ -129,8 +129,7 @@ test_expect_success 'branch@{u} works when tracking a local branch' ' test_expect_success 'branch@{u} error message when no upstream' ' cat >expect <<-EOF && - error: No upstream configured for branch ${sq}non-tracking${sq} - fatal: Needed a single revision + fatal: No upstream configured for branch ${sq}non-tracking${sq} EOF error_message non-tracking@{u} 2>actual && test_i18ncmp expect actual @@ -138,8 +137,7 @@ test_expect_success 'branch@{u} error message when no upstream' ' test_expect_success '@{u} error message when no upstream' ' cat >expect <<-EOF && - error: No upstream configured for branch ${sq}master${sq} - fatal: Needed a single revision + fatal: No upstream configured for branch ${sq}master${sq} EOF test_must_fail git rev-parse --verify @{u} 2>actual && test_i18ncmp expect actual @@ -147,8 +145,7 @@ test_expect_success '@{u} error message when no upstream' ' test_expect_success 'branch@{u} error message with misspelt branch' ' cat >expect <<-EOF && - error: No such branch: ${sq}no-such-branch${sq} - fatal: Needed a single revision + fatal: No such branch: ${sq}no-such-branch${sq} EOF error_message no-such-branch@{u} 2>actual && test_i18ncmp expect actual @@ -156,8 +153,7 @@ test_expect_success 'branch@{u} error message with misspelt branch' ' test_expect_success '@{u} error message when not on a branch' ' cat >expect <<-EOF && - error: HEAD does not point to a branch - fatal: Needed a single revision + fatal: HEAD does not point to a branch EOF git checkout HEAD^0 && test_must_fail git rev-parse --verify @{u} 2>actual && @@ -166,8 +162,7 @@ test_expect_success '@{u} error message when not on a branch' ' test_expect_success 'branch@{u} error message if upstream branch not fetched' ' cat >expect <<-EOF && - error: Upstream branch ${sq}refs/heads/side${sq} not stored as a remote-tracking branch - fatal: Needed a single revision + fatal: Upstream branch ${sq}refs/heads/side${sq} not stored as a remote-tracking branch EOF error_message bad-upstream@{u} 2>actual && test_i18ncmp expect actual diff --git a/t/t2001-checkout-cache-clash.sh b/t/t2001-checkout-cache-clash.sh index 98aa73e823..1fc8e634b7 100755 --- a/t/t2001-checkout-cache-clash.sh +++ b/t/t2001-checkout-cache-clash.sh @@ -59,10 +59,9 @@ test_expect_success \ 'git read-tree -m $tree1 && git checkout-index -f -a' test_debug 'show_files $tree1' -test_expect_success SYMLINKS \ - 'git update-index --add a symlink.' \ - 'ln -s path0 path1 && - git update-index --add path1' +test_expect_success \ + 'add a symlink' \ + 'test_ln_s_add path0 path1' test_expect_success \ 'writing tree out with git write-tree' \ 'tree3=$(git write-tree)' diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh index 0f4b2896af..f171a5578b 100755 --- a/t/t2004-checkout-cache-temp.sh +++ b/t/t2004-checkout-cache-temp.sh @@ -194,11 +194,10 @@ test_expect_success \ test $(cat ../$s1) = tree1asubdir/path5) )' -test_expect_success SYMLINKS \ +test_expect_success \ 'checkout --temp symlink' ' rm -f path* .merge_* out .git/index && -ln -s b a && -git update-index --add a && +test_ln_s_add b a && t4=$(git write-tree) && rm -f .git/index && git read-tree $t4 && diff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh index e6f59f1914..fc9aad530e 100755 --- a/t/t2007-checkout-symlink.sh +++ b/t/t2007-checkout-symlink.sh @@ -6,7 +6,7 @@ test_description='git checkout to switch between branches with symlink<->dir' . ./test-lib.sh -test_expect_success SYMLINKS setup ' +test_expect_success setup ' mkdir frotz && echo hello >frotz/filfre && @@ -25,25 +25,25 @@ test_expect_success SYMLINKS setup ' git rm --cached frotz/filfre && mv frotz xyzzy && - ln -s xyzzy frotz && - git add xyzzy/filfre frotz && + test_ln_s_add xyzzy frotz && + git add xyzzy/filfre && test_tick && git commit -m "side moves frotz/ to xyzzy/ and adds frotz->xyzzy/" ' -test_expect_success SYMLINKS 'switch from symlink to dir' ' +test_expect_success 'switch from symlink to dir' ' git checkout master ' -test_expect_success SYMLINKS 'Remove temporary directories & switch to master' ' +test_expect_success 'Remove temporary directories & switch to master' ' rm -fr frotz xyzzy nitfol && git checkout -f master ' -test_expect_success SYMLINKS 'switch from dir to symlink' ' +test_expect_success 'switch from dir to symlink' ' git checkout side diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh index 5da63e9fa2..c2ada7de37 100755 --- a/t/t2021-checkout-overwrite.sh +++ b/t/t2021-checkout-overwrite.sh @@ -29,21 +29,25 @@ test_expect_success 'checkout commit with dir must not remove untracked a/b' ' test -f a/b ' -test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' ' +test_expect_success 'create a commit where dir a/b changed to symlink' ' rm -rf a/b && # cleanup if previous test failed git checkout -f -b symlink start && rm -rf a/b && - ln -s foo a/b && git add -A && + test_ln_s_add foo a/b && git commit -m "dir to symlink" ' -test_expect_success SYMLINKS 'checkout commit with dir must not remove untracked a/b' ' +test_expect_success 'checkout commit with dir must not remove untracked a/b' ' git rm --cached a/b && git commit -m "un-track the symlink" && - test_must_fail git checkout start && + test_must_fail git checkout start +' + +test_expect_success SYMLINKS 'the symlink remained' ' + test -h a/b ' diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh new file mode 100755 index 0000000000..dee55e428f --- /dev/null +++ b/t/t2024-checkout-dwim.sh @@ -0,0 +1,167 @@ +#!/bin/sh + +test_description='checkout <branch> + +Ensures that checkout on an unborn branch does what the user expects' + +. ./test-lib.sh + +# Is the current branch "refs/heads/$1"? +test_branch () { + printf "%s\n" "refs/heads/$1" >expect.HEAD && + git symbolic-ref HEAD >actual.HEAD && + test_cmp expect.HEAD actual.HEAD +} + +# Is branch "refs/heads/$1" set to pull from "$2/$3"? +test_branch_upstream () { + printf "%s\n" "$2" "refs/heads/$3" >expect.upstream && + { + git config "branch.$1.remote" && + git config "branch.$1.merge" + } >actual.upstream && + test_cmp expect.upstream actual.upstream +} + +test_expect_success 'setup' ' + test_commit my_master && + git init repo_a && + ( + cd repo_a && + test_commit a_master && + git checkout -b foo && + test_commit a_foo && + git checkout -b bar && + test_commit a_bar + ) && + git init repo_b && + ( + cd repo_b && + test_commit b_master && + git checkout -b foo && + test_commit b_foo && + git checkout -b baz && + test_commit b_baz + ) && + git remote add repo_a repo_a && + git remote add repo_b repo_b && + git config remote.repo_b.fetch \ + "+refs/heads/*:refs/remotes/other_b/*" && + git fetch --all +' + +test_expect_success 'checkout of non-existing branch fails' ' + git checkout -B master && + test_might_fail git branch -D xyzzy && + + test_must_fail git checkout xyzzy && + test_must_fail git rev-parse --verify refs/heads/xyzzy && + test_branch master +' + +test_expect_success 'checkout of branch from multiple remotes fails #1' ' + git checkout -B master && + test_might_fail git branch -D foo && + + test_must_fail git checkout foo && + test_must_fail git rev-parse --verify refs/heads/foo && + test_branch master +' + +test_expect_success 'checkout of branch from a single remote succeeds #1' ' + git checkout -B master && + test_might_fail git branch -D bar && + + git checkout bar && + test_branch bar && + test_cmp_rev remotes/repo_a/bar HEAD && + test_branch_upstream bar repo_a bar +' + +test_expect_success 'checkout of branch from a single remote succeeds #2' ' + git checkout -B master && + test_might_fail git branch -D baz && + + git checkout baz && + test_branch baz && + test_cmp_rev remotes/other_b/baz HEAD && + test_branch_upstream baz repo_b baz +' + +test_expect_success '--no-guess suppresses branch auto-vivification' ' + git checkout -B master && + test_might_fail git branch -D bar && + + test_must_fail git checkout --no-guess bar && + test_must_fail git rev-parse --verify refs/heads/bar && + test_branch master +' + +test_expect_success 'setup more remotes with unconventional refspecs' ' + git checkout -B master && + git init repo_c && + ( + cd repo_c && + test_commit c_master && + git checkout -b bar && + test_commit c_bar + git checkout -b spam && + test_commit c_spam + ) && + git init repo_d && + ( + cd repo_d && + test_commit d_master && + git checkout -b baz && + test_commit f_baz + git checkout -b eggs && + test_commit c_eggs + ) && + git remote add repo_c repo_c && + git config remote.repo_c.fetch \ + "+refs/heads/*:refs/remotes/extra_dir/repo_c/extra_dir/*" && + git remote add repo_d repo_d && + git config remote.repo_d.fetch \ + "+refs/heads/*:refs/repo_d/*" && + git fetch --all +' + +test_expect_success 'checkout of branch from multiple remotes fails #2' ' + git checkout -B master && + test_might_fail git branch -D bar && + + test_must_fail git checkout bar && + test_must_fail git rev-parse --verify refs/heads/bar && + test_branch master +' + +test_expect_success 'checkout of branch from multiple remotes fails #3' ' + git checkout -B master && + test_might_fail git branch -D baz && + + test_must_fail git checkout baz && + test_must_fail git rev-parse --verify refs/heads/baz && + test_branch master +' + +test_expect_success 'checkout of branch from a single remote succeeds #3' ' + git checkout -B master && + test_might_fail git branch -D spam && + + git checkout spam && + test_branch spam && + test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD && + test_branch_upstream spam repo_c spam +' + +test_expect_success 'checkout of branch from a single remote succeeds #4' ' + git checkout -B master && + test_might_fail git branch -D eggs && + + git checkout eggs && + test_branch eggs && + test_cmp_rev refs/repo_d/eggs HEAD && + test_branch_upstream eggs repo_d eggs +' + +test_done diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index b2bd41918e..9bf2bdffd2 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -96,11 +96,10 @@ test_expect_success 'non-limited update in subdir leaves root alone' ' test_cmp expect actual ' -test_expect_success SYMLINKS 'replace a file with a symlink' ' +test_expect_success 'replace a file with a symlink' ' rm foo && - ln -s top foo && - git add -u -- foo + test_ln_s_add top foo ' diff --git a/t/t3010-ls-files-killed-modified.sh b/t/t3010-ls-files-killed-modified.sh index 95671c2053..262e617445 100755 --- a/t/t3010-ls-files-killed-modified.sh +++ b/t/t3010-ls-files-killed-modified.sh @@ -37,71 +37,65 @@ modified without reporting path9 and path10. ' . ./test-lib.sh -date >path0 -if test_have_prereq SYMLINKS -then - ln -s xyzzy path1 -else - date > path1 -fi -mkdir path2 path3 -date >path2/file2 -date >path3/file3 -: >path7 -date >path8 -: >path9 -date >path10 -test_expect_success \ - 'git update-index --add to add various paths.' \ - "git update-index --add -- path0 path1 path?/file? path7 path8 path9 path10" - -rm -fr path? ;# leave path10 alone -date >path2 -if test_have_prereq SYMLINKS -then - ln -s frotz path3 - ln -s nitfol path5 -else - date > path3 - date > path5 -fi -mkdir path0 path1 path6 -date >path0/file0 -date >path1/file1 -date >path6/file6 -date >path7 -: >path8 -: >path9 -touch path10 +test_expect_success 'git update-index --add to add various paths.' ' + date >path0 && + test_ln_s_add xyzzy path1 && + mkdir path2 path3 && + date >path2/file2 && + date >path3/file3 && + : >path7 && + date >path8 && + : >path9 && + date >path10 && + git update-index --add -- path0 path?/file? path7 path8 path9 path10 && + rm -fr path? # leave path10 alone +' -test_expect_success \ - 'git ls-files -k to show killed files.' \ - 'git ls-files -k >.output' -cat >.expected <<EOF -path0/file0 -path1/file1 -path2 -path3 -EOF +test_expect_success 'git ls-files -k to show killed files.' ' + date >path2 && + if test_have_prereq SYMLINKS + then + ln -s frotz path3 && + ln -s nitfol path5 + else + date >path3 && + date >path5 + fi && + mkdir path0 path1 path6 && + date >path0/file0 && + date >path1/file1 && + date >path6/file6 && + date >path7 && + : >path8 && + : >path9 && + touch path10 && + git ls-files -k >.output +' -test_expect_success \ - 'validate git ls-files -k output.' \ - 'test_cmp .expected .output' +test_expect_success 'validate git ls-files -k output.' ' + cat >.expected <<-\EOF && + path0/file0 + path1/file1 + path2 + path3 + EOF + test_cmp .expected .output +' -test_expect_success \ - 'git ls-files -m to show modified files.' \ - 'git ls-files -m >.output' -cat >.expected <<EOF -path0 -path1 -path2/file2 -path3/file3 -path7 -path8 -EOF +test_expect_success 'git ls-files -m to show modified files.' ' + git ls-files -m >.output +' -test_expect_success \ - 'validate git ls-files -m output.' \ - 'test_cmp .expected .output' +test_expect_success 'validate git ls-files -m output.' ' + cat >.expected <<-\EOF && + path0 + path1 + path2/file2 + path3/file3 + path7 + path8 + EOF + test_cmp .expected .output +' test_done diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index a5e3da7e41..2f96100a5f 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -25,10 +25,7 @@ test_expect_success 'setup 1' ' git branch submod && git branch copy && git branch rename && - if test_have_prereq SYMLINKS - then - git branch rename-ln - fi && + git branch rename-ln && echo hello >>a && cp a d/e && @@ -260,16 +257,12 @@ test_expect_success 'setup 8' ' git add e && test_tick && git commit -m "rename a->e" && - if test_have_prereq SYMLINKS - then - git checkout rename-ln && - git mv a e && - ln -s e a && - git add a e && - test_tick && - git commit -m "rename a->e, symlink a->e" && - oln=`printf e | git hash-object --stdin` - fi + git checkout rename-ln && + git mv a e && + test_ln_s_add e a && + test_tick && + git commit -m "rename a->e, symlink a->e" && + oln=`printf e | git hash-object --stdin` ' test_expect_success 'setup 9' ' @@ -569,28 +562,25 @@ test_expect_success 'merge-recursive copy vs. rename' ' test_cmp expected actual ' -if test_have_prereq SYMLINKS -then - test_expect_failure 'merge-recursive rename vs. rename/symlink' ' - - git checkout -f rename && - git merge rename-ln && - ( git ls-tree -r HEAD ; git ls-files -s ) >actual && - ( - echo "120000 blob $oln a" - echo "100644 blob $o0 b" - echo "100644 blob $o0 c" - echo "100644 blob $o0 d/e" - echo "100644 blob $o0 e" - echo "120000 $oln 0 a" - echo "100644 $o0 0 b" - echo "100644 $o0 0 c" - echo "100644 $o0 0 d/e" - echo "100644 $o0 0 e" - ) >expected && - test_cmp expected actual - ' -fi +test_expect_failure 'merge-recursive rename vs. rename/symlink' ' + + git checkout -f rename && + git merge rename-ln && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "120000 blob $oln a" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 blob $o0 e" + echo "120000 $oln 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + echo "100644 $o0 0 e" + ) >expected && + test_cmp expected actual +' test_done diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index 4c37057ddf..38446a0e87 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -6,20 +6,20 @@ test_description='wildmatch tests' match() { if [ $1 = 1 ]; then - test_expect_success "wildmatch: match '$3' '$4'" " + test_expect_success "wildmatch: match '$3' '$4'" " test-wildmatch wildmatch '$3' '$4' " else - test_expect_success "wildmatch: no match '$3' '$4'" " + test_expect_success "wildmatch: no match '$3' '$4'" " ! test-wildmatch wildmatch '$3' '$4' " fi if [ $2 = 1 ]; then - test_expect_success "fnmatch: match '$3' '$4'" " + test_expect_success "fnmatch: match '$3' '$4'" " test-wildmatch fnmatch '$3' '$4' " elif [ $2 = 0 ]; then - test_expect_success "fnmatch: no match '$3' '$4'" " + test_expect_success "fnmatch: no match '$3' '$4'" " ! test-wildmatch fnmatch '$3' '$4' " # else @@ -29,13 +29,25 @@ match() { fi } +imatch() { + if [ $1 = 1 ]; then + test_expect_success "iwildmatch: match '$2' '$3'" " + test-wildmatch iwildmatch '$2' '$3' + " + else + test_expect_success "iwildmatch: no match '$2' '$3'" " + ! test-wildmatch iwildmatch '$2' '$3' + " + fi +} + pathmatch() { if [ $1 = 1 ]; then - test_expect_success "pathmatch: match '$2' '$3'" " + test_expect_success "pathmatch: match '$2' '$3'" " test-wildmatch pathmatch '$2' '$3' " else - test_expect_success "pathmatch: no match '$2' '$3'" " + test_expect_success "pathmatch: no match '$2' '$3'" " ! test-wildmatch pathmatch '$2' '$3' " fi @@ -235,4 +247,35 @@ pathmatch 1 abcXdefXghi '*X*i' pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i' pathmatch 1 ab/cXd/efXg/hi '*Xg*i' +# Case-sensitivy features +match 0 x 'a' '[A-Z]' +match 1 x 'A' '[A-Z]' +match 0 x 'A' '[a-z]' +match 1 x 'a' '[a-z]' +match 0 x 'a' '[[:upper:]]' +match 1 x 'A' '[[:upper:]]' +match 0 x 'A' '[[:lower:]]' +match 1 x 'a' '[[:lower:]]' +match 0 x 'A' '[B-Za]' +match 1 x 'a' '[B-Za]' +match 0 x 'A' '[B-a]' +match 1 x 'a' '[B-a]' +match 0 x 'z' '[Z-y]' +match 1 x 'Z' '[Z-y]' + +imatch 1 'a' '[A-Z]' +imatch 1 'A' '[A-Z]' +imatch 1 'A' '[a-z]' +imatch 1 'a' '[a-z]' +imatch 1 'a' '[[:upper:]]' +imatch 1 'A' '[[:upper:]]' +imatch 1 'A' '[[:lower:]]' +imatch 1 'a' '[[:lower:]]' +imatch 1 'A' '[B-Za]' +imatch 1 'a' '[B-Za]' +imatch 1 'A' '[B-a]' +imatch 1 'a' '[B-a]' +imatch 1 'z' '[Z-y]' +imatch 1 'Z' '[Z-y]' + test_done diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh index 81d90b66c5..eb73c06a4e 100755 --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -22,20 +22,8 @@ test_expect_success \ 'setup' \ 'mkdir path2 path2/baz && echo Hi >path0 && - if test_have_prereq SYMLINKS - then - ln -s path0 path1 && - ln -s ../path1 path2/bazbo - make_expected () { - cat >expected - } - else - printf path0 > path1 && - printf ../path1 > path2/bazbo - make_expected () { - sed -e "s/120000 /100644 /" >expected - } - fi && + test_ln_s_add path0 path1 && + test_ln_s_add ../path1 path2/bazbo && echo Lo >path2/foo && echo Mi >path2/baz/b && find path? \( -type f -o -type l \) -print | @@ -51,7 +39,7 @@ test_output () { test_expect_success \ 'ls-tree plain' \ 'git ls-tree $tree >current && - make_expected <<\EOF && + cat >expected <<\EOF && 100644 blob X path0 120000 blob X path1 040000 tree X path2 @@ -61,7 +49,7 @@ EOF test_expect_success \ 'ls-tree recursive' \ 'git ls-tree -r $tree >current && - make_expected <<\EOF && + cat >expected <<\EOF && 100644 blob X path0 120000 blob X path1 100644 blob X path2/baz/b @@ -73,7 +61,7 @@ EOF test_expect_success \ 'ls-tree recursive with -t' \ 'git ls-tree -r -t $tree >current && - make_expected <<\EOF && + cat >expected <<\EOF && 100644 blob X path0 120000 blob X path1 040000 tree X path2 @@ -87,7 +75,7 @@ EOF test_expect_success \ 'ls-tree recursive with -d' \ 'git ls-tree -r -d $tree >current && - make_expected <<\EOF && + cat >expected <<\EOF && 040000 tree X path2 040000 tree X path2/baz EOF @@ -96,7 +84,7 @@ EOF test_expect_success \ 'ls-tree filtered with path' \ 'git ls-tree $tree path >current && - make_expected <<\EOF && + cat >expected <<\EOF && EOF test_output' @@ -106,7 +94,7 @@ EOF test_expect_success \ 'ls-tree filtered with path1 path0' \ 'git ls-tree $tree path1 path0 >current && - make_expected <<\EOF && + cat >expected <<\EOF && 100644 blob X path0 120000 blob X path1 EOF @@ -115,7 +103,7 @@ EOF test_expect_success \ 'ls-tree filtered with path0/' \ 'git ls-tree $tree path0/ >current && - make_expected <<\EOF && + cat >expected <<\EOF && EOF test_output' @@ -124,7 +112,7 @@ EOF test_expect_success \ 'ls-tree filtered with path2' \ 'git ls-tree $tree path2 >current && - make_expected <<\EOF && + cat >expected <<\EOF && 040000 tree X path2 EOF test_output' @@ -133,7 +121,7 @@ EOF test_expect_success \ 'ls-tree filtered with path2/' \ 'git ls-tree $tree path2/ >current && - make_expected <<\EOF && + cat >expected <<\EOF && 040000 tree X path2/baz 120000 blob X path2/bazbo 100644 blob X path2/foo @@ -145,7 +133,7 @@ EOF test_expect_success \ 'ls-tree filtered with path2/baz' \ 'git ls-tree $tree path2/baz >current && - make_expected <<\EOF && + cat >expected <<\EOF && 040000 tree X path2/baz EOF test_output' @@ -153,14 +141,14 @@ EOF test_expect_success \ 'ls-tree filtered with path2/bak' \ 'git ls-tree $tree path2/bak >current && - make_expected <<\EOF && + cat >expected <<\EOF && EOF test_output' test_expect_success \ 'ls-tree -t filtered with path2/bak' \ 'git ls-tree -t $tree path2/bak >current && - make_expected <<\EOF && + cat >expected <<\EOF && 040000 tree X path2 EOF test_output' @@ -168,7 +156,7 @@ EOF test_expect_success \ 'ls-tree with one path a prefix of the other' \ 'git ls-tree $tree path2/baz path2/bazbo >current && - make_expected <<\EOF && + cat >expected <<\EOF && 040000 tree X path2/baz 120000 blob X path2/bazbo EOF diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index d969f0ecd8..44ec6a45f4 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -317,13 +317,13 @@ test_expect_success 'test tracking setup (non-wildcard, matching)' ' test $(git config branch.my4.merge) = refs/heads/master ' -test_expect_success 'test tracking setup (non-wildcard, not matching)' ' +test_expect_success 'tracking setup fails on non-matching refspec' ' git config remote.local.url . && git config remote.local.fetch refs/heads/s:refs/remotes/local/s && (git show-ref -q refs/remotes/local/master || git fetch local) && - git branch --track my5 local/master && - ! test "$(git config branch.my5.remote)" = local && - ! test "$(git config branch.my5.merge)" = refs/heads/master + test_must_fail git branch --track my5 local/master && + test_must_fail git config branch.my5.remote && + test_must_fail git config branch.my5.merge ' test_expect_success 'test tracking setup via config' ' diff --git a/t/t3509-cherry-pick-merge-df.sh b/t/t3509-cherry-pick-merge-df.sh index df921d1f33..a5b6a5f331 100755 --- a/t/t3509-cherry-pick-merge-df.sh +++ b/t/t3509-cherry-pick-merge-df.sh @@ -10,17 +10,15 @@ test_expect_success 'Initialize repository' ' git commit -m a ' -test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts' ' +test_expect_success 'Setup rename across paths each below D/F conflicts' ' mkdir b && - ln -s ../a b/a && - git add b && + test_ln_s_add ../a b/a && git commit -m b && git checkout -b branch && rm b/a && - mv a b/a && - ln -s b/a a && - git add . && + git mv a b/a && + test_ln_s_add b/a a && git commit -m swap && >f1 && @@ -28,7 +26,7 @@ test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts git commit -m f1 ' -test_expect_success SYMLINKS 'Cherry-pick succeeds with rename across D/F conflicts' ' +test_expect_success 'Cherry-pick succeeds with rename across D/F conflicts' ' git reset --hard && git checkout master^0 && git cherry-pick branch diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 874b3a6444..aab86e838b 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -30,10 +30,9 @@ test_expect_success \ *) echo fail; git ls-files --stage xfoo1; (exit 1);; esac' -test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' ' +test_expect_success 'git add: filemode=0 should not get confused by symlink' ' rm -f xfoo1 && - ln -s foo xfoo1 && - git add xfoo1 && + test_ln_s_add foo xfoo1 && case "`git ls-files --stage xfoo1`" in 120000" "*xfoo1) echo pass;; *) echo fail; git ls-files --stage xfoo1; (exit 1);; @@ -51,21 +50,19 @@ test_expect_success \ *) echo fail; git ls-files --stage xfoo2; (exit 1);; esac' -test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' ' +test_expect_success 'git add: filemode=0 should not get confused by symlink' ' rm -f xfoo2 && - ln -s foo xfoo2 && - git update-index --add xfoo2 && + test_ln_s_add foo xfoo2 && case "`git ls-files --stage xfoo2`" in 120000" "*xfoo2) echo pass;; *) echo fail; git ls-files --stage xfoo2; (exit 1);; esac ' -test_expect_success SYMLINKS \ +test_expect_success \ 'git update-index --add: Test that executable bit is not used...' \ 'git config core.filemode 0 && - ln -s xfoo2 xfoo3 && - git update-index --add xfoo3 && + test_ln_s_add xfoo2 xfoo3 && # runs git update-index --add case "`git ls-files --stage xfoo3`" in 120000" "*xfoo3) echo pass;; *) echo fail; git ls-files --stage xfoo3; (exit 1);; diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 5dfbda7491..8ff039bdfa 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -336,41 +336,58 @@ test_expect_success SYMLINKS 'stash file to symlink (full stage)' ' # This test creates a commit with a symlink used for the following tests -test_expect_success SYMLINKS 'stash symlink to file' ' +test_expect_success 'stash symlink to file' ' git reset --hard && - ln -s file filelink && - git add filelink && + test_ln_s_add file filelink && git commit -m "Add symlink" && rm filelink && cp file filelink && - git stash save "symlink to file" && + git stash save "symlink to file" +' + +test_expect_success SYMLINKS 'this must have re-created the symlink' ' test -h filelink && - case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac && + case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac +' + +test_expect_success 'unstash must re-create the file' ' git stash apply && ! test -h filelink && test bar = "$(cat file)" ' -test_expect_success SYMLINKS 'stash symlink to file (stage rm)' ' +test_expect_success 'stash symlink to file (stage rm)' ' git reset --hard && git rm filelink && cp file filelink && - git stash save "symlink to file (stage rm)" && + git stash save "symlink to file (stage rm)" +' + +test_expect_success SYMLINKS 'this must have re-created the symlink' ' test -h filelink && - case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac && + case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac +' + +test_expect_success 'unstash must re-create the file' ' git stash apply && ! test -h filelink && test bar = "$(cat file)" ' -test_expect_success SYMLINKS 'stash symlink to file (full stage)' ' +test_expect_success 'stash symlink to file (full stage)' ' git reset --hard && rm filelink && cp file filelink && git add filelink && - git stash save "symlink to file (full stage)" && + git stash save "symlink to file (full stage)" +' + +test_expect_success SYMLINKS 'this must have re-created the symlink' ' test -h filelink && - case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac && + case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac +' + +test_expect_success 'unstash must re-create the file' ' git stash apply && ! test -h filelink && test bar = "$(cat file)" diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh index 73b4a24f5e..27e98a8f9d 100755 --- a/t/t4008-diff-break-rewrite.sh +++ b/t/t4008-diff-break-rewrite.sh @@ -99,11 +99,11 @@ test_expect_success \ 'validate result of -B -M (#4)' \ 'compare_diff_raw expected current' -test_expect_success SYMLINKS \ +test_expect_success \ 'make file0 into something completely different' \ 'rm -f file0 && - ln -s frotz file0 && - git update-index file0 file1' + test_ln_s_add frotz file0 && + git update-index file1' test_expect_success \ 'run diff with -B' \ @@ -114,7 +114,7 @@ cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100 file1 EOF -test_expect_success SYMLINKS \ +test_expect_success \ 'validate result of -B (#5)' \ 'compare_diff_raw expected current' @@ -129,7 +129,7 @@ cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 R file0 file1 EOF -test_expect_success SYMLINKS \ +test_expect_success \ 'validate result of -B -M (#6)' \ 'compare_diff_raw expected current' @@ -144,7 +144,7 @@ cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M file1 EOF -test_expect_success SYMLINKS \ +test_expect_success \ 'validate result of -M (#7)' \ 'compare_diff_raw expected current' diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index f0d5041c11..13e7f621ab 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -9,7 +9,7 @@ test_description='Test diff of symlinks. . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh -test_expect_success SYMLINKS 'diff new symlink and file' ' +test_expect_success 'diff new symlink and file' ' cat >expected <<-\EOF && diff --git a/frotz b/frotz new file mode 120000 @@ -27,22 +27,25 @@ test_expect_success SYMLINKS 'diff new symlink and file' ' @@ -0,0 +1 @@ +xyzzy EOF - ln -s xyzzy frotz && - echo xyzzy >nitfol && + + # the empty tree git update-index && tree=$(git write-tree) && - git update-index --add frotz nitfol && + + test_ln_s_add xyzzy frotz && + echo xyzzy >nitfol && + git update-index --add nitfol && GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current && compare_diff_patch expected current ' -test_expect_success SYMLINKS 'diff unchanged symlink and file' ' +test_expect_success 'diff unchanged symlink and file' ' tree=$(git write-tree) && git update-index frotz nitfol && test -z "$(git diff-index --name-only $tree)" ' -test_expect_success SYMLINKS 'diff removed symlink and file' ' +test_expect_success 'diff removed symlink and file' ' cat >expected <<-\EOF && diff --git a/frotz b/frotz deleted file mode 120000 @@ -66,12 +69,18 @@ test_expect_success SYMLINKS 'diff removed symlink and file' ' compare_diff_patch expected current ' -test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' ' +test_expect_success 'diff identical, but newly created symlink and file' ' >expected && rm -f frotz nitfol && echo xyzzy >nitfol && test-chmtime +10 nitfol && - ln -s xyzzy frotz && + if test_have_prereq SYMLINKS + then + ln -s xyzzy frotz + else + printf xyzzy >frotz + # the symlink property propagates from the index + fi && git diff-index -M -p $tree >current && compare_diff_patch expected current && @@ -80,7 +89,7 @@ test_expect_success SYMLINKS 'diff identical, but newly created symlink and file compare_diff_patch expected current ' -test_expect_success SYMLINKS 'diff different symlink and file' ' +test_expect_success 'diff different symlink and file' ' cat >expected <<-\EOF && diff --git a/frotz b/frotz index 7c465af..df1db54 120000 @@ -100,7 +109,13 @@ test_expect_success SYMLINKS 'diff different symlink and file' ' +yxyyz EOF rm -f frotz && - ln -s yxyyz frotz && + if test_have_prereq SYMLINKS + then + ln -s yxyyz frotz + else + printf yxyyz >frotz + # the symlink property propagates from the index + fi && echo yxyyz >nitfol && git diff-index -M -p $tree >current && compare_diff_patch expected current diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh index 5d20acf436..55d549fcf4 100755 --- a/t/t4023-diff-rename-typechange.sh +++ b/t/t4023-diff-rename-typechange.sh @@ -4,44 +4,44 @@ test_description='typechange rename detection' . ./test-lib.sh -test_expect_success SYMLINKS setup ' +test_expect_success setup ' rm -f foo bar && cat "$TEST_DIRECTORY"/../COPYING >foo && - ln -s linklink bar && - git add foo bar && + test_ln_s_add linklink bar && + git add foo && git commit -a -m Initial && git tag one && - rm -f foo bar && + git rm -f foo bar && cat "$TEST_DIRECTORY"/../COPYING >bar && - ln -s linklink foo && - git add foo bar && + test_ln_s_add linklink foo && + git add bar && git commit -a -m Second && git tag two && - rm -f foo bar && + git rm -f foo bar && cat "$TEST_DIRECTORY"/../COPYING >foo && git add foo && git commit -a -m Third && git tag three && mv foo bar && - ln -s linklink foo && - git add foo bar && + test_ln_s_add linklink foo && + git add bar && git commit -a -m Fourth && git tag four && # This is purely for sanity check - rm -f foo bar && + git rm -f foo bar && cat "$TEST_DIRECTORY"/../COPYING >foo && cat "$TEST_DIRECTORY"/../Makefile >bar && git add foo bar && git commit -a -m Fifth && git tag five && - rm -f foo bar && + git rm -f foo bar && cat "$TEST_DIRECTORY"/../Makefile >foo && cat "$TEST_DIRECTORY"/../COPYING >bar && git add foo bar && @@ -50,7 +50,7 @@ test_expect_success SYMLINKS setup ' ' -test_expect_success SYMLINKS 'cross renames to be detected for regular files' ' +test_expect_success 'cross renames to be detected for regular files' ' git diff-tree five six -r --name-status -B -M | sort >actual && { @@ -61,7 +61,7 @@ test_expect_success SYMLINKS 'cross renames to be detected for regular files' ' ' -test_expect_success SYMLINKS 'cross renames to be detected for typechange' ' +test_expect_success 'cross renames to be detected for typechange' ' git diff-tree one two -r --name-status -B -M | sort >actual && { @@ -72,7 +72,7 @@ test_expect_success SYMLINKS 'cross renames to be detected for typechange' ' ' -test_expect_success SYMLINKS 'moves and renames' ' +test_expect_success 'moves and renames' ' git diff-tree three four -r --name-status -B -M | sort >actual && { diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh index 53ec330ce8..f75f46f92d 100755 --- a/t/t4030-diff-textconv.sh +++ b/t/t4030-diff-textconv.sh @@ -139,12 +139,10 @@ index 0000000..67be421 +frotz \ No newline at end of file EOF -# make a symlink the hard way that works on symlink-challenged file systems + test_expect_success 'textconv does not act on symlinks' ' - printf frotz > file && - git add file && - git ls-files -s | sed -e s/100644/120000/ | - git update-index --index-info && + rm -f file && + test_ln_s_add frotz file && git commit -m typechange && git show >diff && find_diff <diff >actual && diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh index 1261dbbdf5..1019d7b35f 100755 --- a/t/t4038-diff-combined.sh +++ b/t/t4038-diff-combined.sh @@ -353,4 +353,52 @@ test_expect_failure 'combine diff coalesce three parents' ' compare_diff_patch expected actual ' +# Test for a bug reported at +# http://thread.gmane.org/gmane.comp.version-control.git/224410 +# where a delete lines were missing from combined diff output when they +# occurred exactly before the context lines of a later change. +test_expect_success 'combine diff missing delete bug' ' + git commit -m initial --allow-empty && + cat <<-\EOF >test && + 1 + 2 + 3 + 4 + EOF + git add test && + git commit -a -m side1 && + git checkout -B side1 && + git checkout HEAD^ && + cat <<-\EOF >test && + 0 + 1 + 2 + 3 + 4modified + EOF + git add test && + git commit -m side2 && + git branch -f side2 && + test_must_fail git merge --no-commit side1 && + cat <<-\EOF >test && + 1 + 2 + 3 + 4modified + EOF + git add test && + git commit -a -m merge && + git diff-tree -c -p HEAD >actual.tmp && + sed -e "1,/^@@@/d" < actual.tmp >actual && + tr -d Q <<-\EOF >expected && + - 0 + 1 + 2 + 3 + -4 + +4modified + EOF + compare_diff_patch expected actual +' + test_done diff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh index 7c398432ba..1618a6dbc7 100755 --- a/t/t4111-apply-subdir.sh +++ b/t/t4111-apply-subdir.sh @@ -86,6 +86,20 @@ test_expect_success 'apply --index from subdir of toplevel' ' test_cmp expected sub/dir/file ' +test_expect_success 'apply half-broken patch from subdir of toplevel' ' + ( + cd sub/dir && + test_must_fail git apply <<-EOF + --- sub/dir/file + +++ sub/dir/file + @@ -1,0 +1,0 @@ + --- file_in_root + +++ file_in_root + @@ -1,0 +1,0 @@ + EOF + ) +' + test_expect_success 'apply from .git dir' ' cp postimage expected && cp preimage .git/file && diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh index f12826fb09..ebadbc347f 100755 --- a/t/t4114-apply-typechange.sh +++ b/t/t4114-apply-typechange.sh @@ -9,20 +9,19 @@ test_description='git apply should not get confused with type changes. . ./test-lib.sh -test_expect_success SYMLINKS 'setup repository and commits' ' +test_expect_success 'setup repository and commits' ' echo "hello world" > foo && echo "hi planet" > bar && git update-index --add foo bar && git commit -m initial && git branch initial && rm -f foo && - ln -s bar foo && - git update-index foo && + test_ln_s_add bar foo && git commit -m "foo symlinked to bar" && git branch foo-symlinked-to-bar && - rm -f foo && + git rm -f foo && echo "how far is the sun?" > foo && - git update-index foo && + git update-index --add foo && git commit -m "foo back to file" && git branch foo-back-to-file && printf "\0" > foo && @@ -42,7 +41,7 @@ test_expect_success SYMLINKS 'setup repository and commits' ' git branch foo-baz-renamed-from-foo ' -test_expect_success SYMLINKS 'file renamed from foo to foo/baz' ' +test_expect_success 'file renamed from foo to foo/baz' ' git checkout -f initial && git diff-tree -M -p HEAD foo-baz-renamed-from-foo > patch && git apply --index < patch @@ -50,7 +49,7 @@ test_expect_success SYMLINKS 'file renamed from foo to foo/baz' ' test_debug 'cat patch' -test_expect_success SYMLINKS 'file renamed from foo/baz to foo' ' +test_expect_success 'file renamed from foo/baz to foo' ' git checkout -f foo-baz-renamed-from-foo && git diff-tree -M -p HEAD initial > patch && git apply --index < patch @@ -58,7 +57,7 @@ test_expect_success SYMLINKS 'file renamed from foo/baz to foo' ' test_debug 'cat patch' -test_expect_success SYMLINKS 'directory becomes file' ' +test_expect_success 'directory becomes file' ' git checkout -f foo-becomes-a-directory && git diff-tree -p HEAD initial > patch && git apply --index < patch @@ -66,7 +65,7 @@ test_expect_success SYMLINKS 'directory becomes file' ' test_debug 'cat patch' -test_expect_success SYMLINKS 'file becomes directory' ' +test_expect_success 'file becomes directory' ' git checkout -f initial && git diff-tree -p HEAD foo-becomes-a-directory > patch && git apply --index < patch @@ -74,7 +73,7 @@ test_expect_success SYMLINKS 'file becomes directory' ' test_debug 'cat patch' -test_expect_success SYMLINKS 'file becomes symlink' ' +test_expect_success 'file becomes symlink' ' git checkout -f initial && git diff-tree -p HEAD foo-symlinked-to-bar > patch && git apply --index < patch @@ -82,21 +81,21 @@ test_expect_success SYMLINKS 'file becomes symlink' ' test_debug 'cat patch' -test_expect_success SYMLINKS 'symlink becomes file' ' +test_expect_success 'symlink becomes file' ' git checkout -f foo-symlinked-to-bar && git diff-tree -p HEAD foo-back-to-file > patch && git apply --index < patch ' test_debug 'cat patch' -test_expect_success SYMLINKS 'binary file becomes symlink' ' +test_expect_success 'binary file becomes symlink' ' git checkout -f foo-becomes-binary && git diff-tree -p --binary HEAD foo-symlinked-to-bar > patch && git apply --index < patch ' test_debug 'cat patch' -test_expect_success SYMLINKS 'symlink becomes binary file' ' +test_expect_success 'symlink becomes binary file' ' git checkout -f foo-symlinked-to-bar && git diff-tree -p --binary HEAD foo-becomes-binary > patch && git apply --index < patch @@ -104,7 +103,7 @@ test_expect_success SYMLINKS 'symlink becomes binary file' ' test_debug 'cat patch' -test_expect_success SYMLINKS 'symlink becomes directory' ' +test_expect_success 'symlink becomes directory' ' git checkout -f foo-symlinked-to-bar && git diff-tree -p HEAD foo-becomes-a-directory > patch && git apply --index < patch @@ -112,7 +111,7 @@ test_expect_success SYMLINKS 'symlink becomes directory' ' test_debug 'cat patch' -test_expect_success SYMLINKS 'directory becomes symlink' ' +test_expect_success 'directory becomes symlink' ' git checkout -f foo-becomes-a-directory && git diff-tree -p HEAD foo-symlinked-to-bar > patch && git apply --index < patch diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh index 7674dd2ec9..872fcda6cb 100755 --- a/t/t4115-apply-symlink.sh +++ b/t/t4115-apply-symlink.sh @@ -9,18 +9,16 @@ test_description='git apply symlinks and partial files . ./test-lib.sh -test_expect_success SYMLINKS setup ' +test_expect_success setup ' - ln -s path1/path2/path3/path4/path5 link1 && - git add link? && + test_ln_s_add path1/path2/path3/path4/path5 link1 && git commit -m initial && git branch side && rm -f link? && - ln -s htap6 link1 && - git update-index link? && + test_ln_s_add htap6 link1 && git commit -m second && git diff-tree -p HEAD^ HEAD >patch && @@ -37,7 +35,7 @@ test_expect_success SYMLINKS 'apply symlink patch' ' ' -test_expect_success SYMLINKS 'apply --index symlink patch' ' +test_expect_success 'apply --index symlink patch' ' git checkout -f side && git apply --index patch && diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh index 39407376ba..70b3a06e1d 100755 --- a/t/t4122-apply-symlink-inside.sh +++ b/t/t4122-apply-symlink-inside.sh @@ -10,11 +10,11 @@ lecho () { done } -test_expect_success SYMLINKS setup ' +test_expect_success setup ' mkdir -p arch/i386/boot arch/x86_64 && lecho 1 2 3 4 5 >arch/i386/boot/Makefile && - ln -s ../i386/boot arch/x86_64/boot && + test_ln_s_add ../i386/boot arch/x86_64/boot && git add . && test_tick && git commit -m initial && @@ -31,7 +31,7 @@ test_expect_success SYMLINKS setup ' ' -test_expect_success SYMLINKS apply ' +test_expect_success apply ' git checkout test && git diff --exit-code test && @@ -40,7 +40,7 @@ test_expect_success SYMLINKS apply ' ' -test_expect_success SYMLINKS 'check result' ' +test_expect_success 'check result' ' git diff --exit-code master && git diff --exit-code --cached master && diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 9243a97993..cb03d28769 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -530,6 +530,20 @@ test_expect_success 'show added path under "--follow -M"' ' ) ' +test_expect_success 'git log -c --follow' ' + test_create_repo follow-c && + ( + cd follow-c && + test_commit initial file original && + git rm file && + test_commit rename file2 original && + git reset --hard initial && + test_commit modify file foo && + git merge -m merge rename && + git log -c --follow file2 + ) +' + cat >expect <<\EOF * commit COMMIT_OBJECT_NAME |\ Merge: MERGE_PARENTS diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 3fbd366ec3..c2023b1a3d 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -30,10 +30,76 @@ GUNZIP=${GUNZIP:-gzip -d} SUBSTFORMAT=%H%n +test_lazy_prereq TAR_NEEDS_PAX_FALLBACK ' + ( + mkdir pax && + cd pax && + "$TAR" xf "$TEST_DIRECTORY"/t5000/pax.tar && + test -f PaxHeaders.1791/file + ) +' + +get_pax_header() { + file=$1 + header=$2= + + while read len rest + do + if test "$len" = $(echo "$len $rest" | wc -c) + then + case "$rest" in + $header*) + echo "${rest#$header}" + ;; + esac + fi + done <"$file" +} + +check_tar() { + tarfile=$1.tar + listfile=$1.lst + dir=$1 + dir_with_prefix=$dir/$2 + + test_expect_success ' extract tar archive' ' + (mkdir $dir && cd $dir && "$TAR" xf -) <$tarfile + ' + + test_expect_success TAR_NEEDS_PAX_FALLBACK ' interpret pax headers' ' + ( + cd $dir && + for header in *.paxheader + do + data=${header%.paxheader}.data && + if test -h $data -o -e $data + then + path=$(get_pax_header $header path) && + if test -n "$path" + then + mv "$data" "$path" + fi + fi + done + ) + ' + + test_expect_success ' validate filenames' ' + (cd ${dir_with_prefix}a && find .) | sort >$listfile && + test_cmp a.lst $listfile + ' + + test_expect_success ' validate file contents' ' + diff -r a ${dir_with_prefix}a + ' +} + test_expect_success \ 'populate workdir' \ - 'mkdir a b c && + 'mkdir a && echo simple textfile >a/a && + ten=0123456789 && hundred=$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten && + echo long filename >a/four$hundred && mkdir a/bin && cp /bin/sh a/bin && printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 && @@ -62,6 +128,12 @@ test_expect_success \ git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \ git commit-tree $treeid </dev/null)' +test_expect_success 'setup export-subst' ' + echo "substfile?" export-subst >>.git/info/attributes && + git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \ + >a/substfile1 +' + test_expect_success \ 'create bare clone' \ 'git clone --bare . bare.git && @@ -75,13 +147,19 @@ test_expect_success \ 'git archive' \ 'git archive HEAD >b.tar' -test_expect_success \ - 'git tar-tree' \ - 'git tar-tree HEAD >b2.tar' +check_tar b -test_expect_success \ - 'git archive vs. git tar-tree' \ - 'test_cmp b.tar b2.tar' +test_expect_success 'git archive --prefix=prefix/' ' + git archive --prefix=prefix/ HEAD >with_prefix.tar +' + +check_tar with_prefix prefix/ + +test_expect_success 'git-archive --prefix=olde-' ' + git archive --prefix=olde- HEAD >with_olde-prefix.tar +' + +check_tar with_olde-prefix olde- test_expect_success 'git archive on large files' ' test_config core.bigfilethreshold 1 && @@ -118,66 +196,14 @@ test_expect_success \ 'git get-tar-commit-id <b.tar >b.commitid && test_cmp .git/$(git symbolic-ref HEAD) b.commitid' -test_expect_success \ - 'extract tar archive' \ - '(cd b && "$TAR" xf -) <b.tar' - -test_expect_success \ - 'validate filenames' \ - '(cd b/a && find .) | sort >b.lst && - test_cmp a.lst b.lst' - -test_expect_success \ - 'validate file contents' \ - 'diff -r a b/a' - -test_expect_success \ - 'git tar-tree with prefix' \ - 'git tar-tree HEAD prefix >c.tar' - -test_expect_success \ - 'extract tar archive with prefix' \ - '(cd c && "$TAR" xf -) <c.tar' - -test_expect_success \ - 'validate filenames with prefix' \ - '(cd c/prefix/a && find .) | sort >c.lst && - test_cmp a.lst c.lst' - -test_expect_success \ - 'validate file contents with prefix' \ - 'diff -r a c/prefix/a' - -test_expect_success \ - 'create archives with substfiles' \ - 'cp .git/info/attributes .git/info/attributes.before && - echo "substfile?" export-subst >>.git/info/attributes && - git archive HEAD >f.tar && - git archive --prefix=prefix/ HEAD >g.tar && - mv .git/info/attributes.before .git/info/attributes' - -test_expect_success \ - 'extract substfiles' \ - '(mkdir f && cd f && "$TAR" xf -) <f.tar' - -test_expect_success \ - 'validate substfile contents' \ - 'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \ - >f/a/substfile1.expected && - test_cmp f/a/substfile1.expected f/a/substfile1 && - test_cmp a/substfile2 f/a/substfile2 +test_expect_success 'git tar-tree' ' + git tar-tree HEAD >tar-tree.tar && + test_cmp b.tar tar-tree.tar ' -test_expect_success \ - 'extract substfiles from archive with prefix' \ - '(mkdir g && cd g && "$TAR" xf -) <g.tar' - -test_expect_success \ - 'validate substfile contents from archive with prefix' \ - 'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \ - >g/prefix/a/substfile1.expected && - test_cmp g/prefix/a/substfile1.expected g/prefix/a/substfile1 && - test_cmp a/substfile2 g/prefix/a/substfile2 +test_expect_success 'git tar-tree with prefix' ' + git tar-tree HEAD prefix >tar-tree_with_prefix.tar && + test_cmp with_prefix.tar tar-tree_with_prefix.tar ' test_expect_success 'git archive with --output, override inferred format' ' @@ -197,18 +223,6 @@ test_expect_success 'clients cannot access unreachable commits' ' test_must_fail git archive --remote=. $sha1 >remote.tar ' -test_expect_success 'git-archive --prefix=olde-' ' - git archive --prefix=olde- >h.tar HEAD && - ( - mkdir h && - cd h && - "$TAR" xf - <../h.tar - ) && - test -d h/olde-a && - test -d h/olde-a/bin && - test -f h/olde-a/bin/sh -' - test_expect_success 'setup tar filters' ' git config tar.tar.foo.command "tr ab ba" && git config tar.bar.command "tr ab ba" && diff --git a/t/t5000/pax.tar b/t/t5000/pax.tar Binary files differnew file mode 100644 index 0000000000..d911737149 --- /dev/null +++ b/t/t5000/pax.tar diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh index 4e7b05dd23..c72f71eb18 100755 --- a/t/t5003-archive-zip.sh +++ b/t/t5003-archive-zip.sh @@ -37,7 +37,7 @@ check_zip() { test_expect_success \ 'populate workdir' \ - 'mkdir a b c && + 'mkdir a && echo simple textfile >a/a && mkdir a/bin && cp /bin/sh a/bin && diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh index 8d1bbd356a..67f3b54bed 100755 --- a/t/t5004-archive-corner-cases.sh +++ b/t/t5004-archive-corner-cases.sh @@ -27,6 +27,21 @@ check_dir() { test_cmp expect actual } + +# bsdtar/libarchive versions before 3.1.3 consider a tar file with a +# global pax header that is not followed by a file record as corrupt. +if "$TAR" tf "$TEST_DIRECTORY"/t5004/empty-with-pax-header.tar >/dev/null 2>&1 +then + test_set_prereq HEADER_ONLY_TAR_OK +fi + +test_expect_success HEADER_ONLY_TAR_OK 'tar archive of commit with empty tree' ' + git archive --format=tar HEAD >empty-with-pax-header.tar && + make_dir extract && + "$TAR" xf empty-with-pax-header.tar -C extract && + check_dir extract +' + test_expect_success 'tar archive of empty tree is empty' ' git archive --format=tar HEAD: >empty.tar && perl -e "print \"\\0\" x 10240" >10knuls.tar && diff --git a/t/t5004/empty-with-pax-header.tar b/t/t5004/empty-with-pax-header.tar Binary files differnew file mode 100644 index 0000000000..da9e39e6cf --- /dev/null +++ b/t/t5004/empty-with-pax-header.tar diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index d574085696..fd2598e601 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -135,6 +135,13 @@ test_expect_success 'clone shallow depth 1' ' test "`git --git-dir=shallow0/.git rev-list --count HEAD`" = 1 ' +test_expect_success 'clone shallow depth 1 with fsck' ' + git config --global fetch.fsckobjects true && + git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0fsck && + test "`git --git-dir=shallow0fsck/.git rev-list --count HEAD`" = 1 && + git config --global --unset fetch.fsckobjects +' + test_expect_success 'clone shallow' ' git clone --no-single-branch --depth 2 "file://$(pwd)/." shallow ' @@ -373,6 +380,20 @@ test_expect_success 'clone shallow with packed refs' ' test_cmp count8.expected count8.actual ' +test_expect_success 'fetch in shallow repo unreachable shallow objects' ' + ( + git clone --bare --branch B --single-branch "file://$(pwd)/." no-reflog && + git clone --depth 1 "file://$(pwd)/no-reflog" shallow9 && + cd no-reflog && + git tag -d TAGB1 TAGB2 && + git update-ref refs/heads/B B~~ && + git gc --prune=now && + cd ../shallow9 && + git fetch origin && + git fsck --no-dangling + ) +' + test_expect_success 'setup tests for the --stdin parameter' ' for head in C D E F do diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 6af6c63350..ed4d9c8318 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -57,6 +57,35 @@ test_expect_success 'pulling into void does not overwrite untracked files' ' ) ' +test_expect_success 'pulling into void does not overwrite staged files' ' + git init cloned-staged-colliding && + ( + cd cloned-staged-colliding && + echo "alternate content" >file && + git add file && + test_must_fail git pull .. master && + echo "alternate content" >expect && + test_cmp expect file && + git cat-file blob :file >file.index && + test_cmp expect file.index + ) +' + + +test_expect_success 'pulling into void does not remove new staged files' ' + git init cloned-staged-new && + ( + cd cloned-staged-new && + echo "new tracked file" >newfile && + git add newfile && + git pull .. master && + echo "new tracked file" >expect && + test_cmp expect newfile && + git cat-file blob :newfile >newfile.index && + test_cmp expect newfile.index + ) +' + test_expect_success 'test . as a remote' ' git branch copy master && diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh index b23efbbfd9..55a866af80 100755 --- a/t/t5551-http-fetch.sh +++ b/t/t5551-http-fetch.sh @@ -209,13 +209,17 @@ test_expect_success EXPENSIVE 'create 50,000 tags in the repo' ' # now assign tags to all the dangling commits we created above tag=$("$PERL_PATH" -e "print \"bla\" x 30") && - sed -e "s/^:\(.\+\) \(.\+\)$/\2 refs\/tags\/$tag-\1/" <marks >>packed-refs + sed -e "s|^:\([^ ]*\) \(.*\)$|\2 refs/tags/$tag-\1|" <marks >>packed-refs ) ' test_expect_success EXPENSIVE 'clone the 50,000 tag repo to check OS command line overflow' ' git clone $HTTPD_URL/smart/repo.git too-many-refs 2>err && - test_line_count = 0 err + test_line_count = 0 err && + ( + cd too-many-refs && + test $(git for-each-ref refs/tags | wc -l) = 50000 + ) ' stop_httpd diff --git a/t/t6019-rev-list-ancestry-path.sh b/t/t6019-rev-list-ancestry-path.sh index 39b4cb0ecd..dd5b0e55d2 100755 --- a/t/t6019-rev-list-ancestry-path.sh +++ b/t/t6019-rev-list-ancestry-path.sh @@ -13,6 +13,9 @@ test_description='--ancestry-path' # # D..M -- M.t == M # --ancestry-path D..M -- M.t == M +# +# F...I == F G H I +# --ancestry-path F...I == F H I . ./test-lib.sh @@ -63,13 +66,29 @@ test_expect_success 'rev-list D..M -- M.t' ' test_cmp expect actual ' -test_expect_success 'rev-list --ancestry-patch D..M -- M.t' ' +test_expect_success 'rev-list --ancestry-path D..M -- M.t' ' echo M >expect && git rev-list --ancestry-path --format=%s D..M -- M.t | sed -e "/^commit /d" >actual && test_cmp expect actual ' +test_expect_success 'rev-list F...I' ' + for c in F G H I; do echo $c; done >expect && + git rev-list --format=%s F...I | + sed -e "/^commit /d" | + sort >actual && + test_cmp expect actual +' + +test_expect_success 'rev-list --ancestry-path F...I' ' + for c in F H I; do echo $c; done >expect && + git rev-list --ancestry-path --format=%s F...I | + sed -e "/^commit /d" | + sort >actual && + test_cmp expect actual +' + # b---bc # / \ / # a X diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh index 2599ae50eb..9324ea4416 100755 --- a/t/t6035-merge-dir-to-symlink.sh +++ b/t/t6035-merge-dir-to-symlink.sh @@ -3,7 +3,7 @@ test_description='merging when a directory was replaced with a symlink' . ./test-lib.sh -test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' ' +test_expect_success 'create a commit where dir a/b changed to symlink' ' mkdir -p a/b/c a/b-2/c && > a/b/c/d && > a/b-2/c/d && @@ -12,12 +12,12 @@ test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' git commit -m base && git tag start && rm -rf a/b && - ln -s b-2 a/b && git add -A && + test_ln_s_add b-2 a/b && git commit -m "dir to symlink" ' -test_expect_success SYMLINKS 'checkout does not clobber untracked symlink' ' +test_expect_success 'checkout does not clobber untracked symlink' ' git checkout HEAD^0 && git reset --hard master && git rm --cached a/b && @@ -25,7 +25,7 @@ test_expect_success SYMLINKS 'checkout does not clobber untracked symlink' ' test_must_fail git checkout start^0 ' -test_expect_success SYMLINKS 'a/b-2/c/d is kept when clobbering symlink b' ' +test_expect_success 'a/b-2/c/d is kept when clobbering symlink b' ' git checkout HEAD^0 && git reset --hard master && git rm --cached a/b && @@ -34,14 +34,14 @@ test_expect_success SYMLINKS 'a/b-2/c/d is kept when clobbering symlink b' ' test -f a/b-2/c/d ' -test_expect_success SYMLINKS 'checkout should not have deleted a/b-2/c/d' ' +test_expect_success 'checkout should not have deleted a/b-2/c/d' ' git checkout HEAD^0 && git reset --hard master && git checkout start^0 && test -f a/b-2/c/d ' -test_expect_success SYMLINKS 'setup for merge test' ' +test_expect_success 'setup for merge test' ' git reset --hard && test -f a/b-2/c/d && echo x > a/x && @@ -50,39 +50,51 @@ test_expect_success SYMLINKS 'setup for merge test' ' git tag baseline ' -test_expect_success SYMLINKS 'Handle D/F conflict, do not lose a/b-2/c/d in merge (resolve)' ' +test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (resolve)' ' git reset --hard && git checkout baseline^0 && git merge -s resolve master && - test -h a/b && test -f a/b-2/c/d ' -test_expect_success SYMLINKS 'Handle D/F conflict, do not lose a/b-2/c/d in merge (recursive)' ' +test_expect_success SYMLINKS 'a/b was resolved as symlink' ' + test -h a/b +' + +test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (recursive)' ' git reset --hard && git checkout baseline^0 && git merge -s recursive master && - test -h a/b && test -f a/b-2/c/d ' -test_expect_success SYMLINKS 'Handle F/D conflict, do not lose a/b-2/c/d in merge (resolve)' ' +test_expect_success SYMLINKS 'a/b was resolved as symlink' ' + test -h a/b +' + +test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (resolve)' ' git reset --hard && git checkout master^0 && git merge -s resolve baseline^0 && - test -h a/b && test -f a/b-2/c/d ' -test_expect_success SYMLINKS 'Handle F/D conflict, do not lose a/b-2/c/d in merge (recursive)' ' +test_expect_success SYMLINKS 'a/b was resolved as symlink' ' + test -h a/b +' + +test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (recursive)' ' git reset --hard && git checkout master^0 && git merge -s recursive baseline^0 && - test -h a/b && test -f a/b-2/c/d ' -test_expect_failure SYMLINKS 'do not lose untracked in merge (resolve)' ' +test_expect_success SYMLINKS 'a/b was resolved as symlink' ' + test -h a/b +' + +test_expect_failure 'do not lose untracked in merge (resolve)' ' git reset --hard && git checkout baseline^0 && >a/b/c/e && @@ -91,7 +103,7 @@ test_expect_failure SYMLINKS 'do not lose untracked in merge (resolve)' ' test -f a/b-2/c/d ' -test_expect_success SYMLINKS 'do not lose untracked in merge (recursive)' ' +test_expect_success 'do not lose untracked in merge (recursive)' ' git reset --hard && git checkout baseline^0 && >a/b/c/e && @@ -100,52 +112,61 @@ test_expect_success SYMLINKS 'do not lose untracked in merge (recursive)' ' test -f a/b-2/c/d ' -test_expect_success SYMLINKS 'do not lose modifications in merge (resolve)' ' +test_expect_success 'do not lose modifications in merge (resolve)' ' git reset --hard && git checkout baseline^0 && echo more content >>a/b/c/d && test_must_fail git merge -s resolve master ' -test_expect_success SYMLINKS 'do not lose modifications in merge (recursive)' ' +test_expect_success 'do not lose modifications in merge (recursive)' ' git reset --hard && git checkout baseline^0 && echo more content >>a/b/c/d && test_must_fail git merge -s recursive master ' -test_expect_success SYMLINKS 'setup a merge where dir a/b-2 changed to symlink' ' +test_expect_success 'setup a merge where dir a/b-2 changed to symlink' ' git reset --hard && git checkout start^0 && rm -rf a/b-2 && - ln -s b a/b-2 && git add -A && + test_ln_s_add b a/b-2 && git commit -m "dir a/b-2 to symlink" && git tag test2 ' -test_expect_success SYMLINKS 'merge should not have D/F conflicts (resolve)' ' +test_expect_success 'merge should not have D/F conflicts (resolve)' ' git reset --hard && git checkout baseline^0 && git merge -s resolve test2 && - test -h a/b-2 && test -f a/b/c/d ' -test_expect_success SYMLINKS 'merge should not have D/F conflicts (recursive)' ' +test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' ' + test -h a/b-2 +' + +test_expect_success 'merge should not have D/F conflicts (recursive)' ' git reset --hard && git checkout baseline^0 && git merge -s recursive test2 && - test -h a/b-2 && test -f a/b/c/d ' -test_expect_success SYMLINKS 'merge should not have F/D conflicts (recursive)' ' +test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' ' + test -h a/b-2 +' + +test_expect_success 'merge should not have F/D conflicts (recursive)' ' git reset --hard && git checkout -b foo test2 && git merge -s recursive baseline^0 && - test -h a/b-2 && test -f a/b/c/d ' +test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' ' + test -h a/b-2 +' + test_done diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index a845b154e4..101816e718 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -218,13 +218,13 @@ test_expect_success 'git mv should not change sha1 of moved cache entry' ' rm -f dirty dirty2 -test_expect_success SYMLINKS 'git mv should overwrite symlink to a file' ' +test_expect_success 'git mv should overwrite symlink to a file' ' rm -fr .git && git init && echo 1 >moved && - ln -s moved symlink && - git add moved symlink && + test_ln_s_add moved symlink && + git add moved && test_must_fail git mv moved symlink && git mv -f moved symlink && ! test -e moved && @@ -237,22 +237,26 @@ test_expect_success SYMLINKS 'git mv should overwrite symlink to a file' ' rm -f moved symlink -test_expect_success SYMLINKS 'git mv should overwrite file with a symlink' ' +test_expect_success 'git mv should overwrite file with a symlink' ' rm -fr .git && git init && echo 1 >moved && - ln -s moved symlink && - git add moved symlink && + test_ln_s_add moved symlink && + git add moved && test_must_fail git mv symlink moved && git mv -f symlink moved && ! test -e symlink && - test -h moved && git update-index --refresh && git diff-files --quiet ' +test_expect_success SYMLINKS 'check moved symlink' ' + + test -h moved +' + rm -f moved symlink test_done diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh index 8f3b54d826..88d60c1ce2 100755 --- a/t/t7011-skip-worktree-reading.sh +++ b/t/t7011-skip-worktree-reading.sh @@ -91,12 +91,12 @@ test_expect_success 'update-index --remove' ' test_cmp expected 1 ' -test_expect_success 'ls-files --delete' ' +test_expect_success 'ls-files --deleted' ' setup_absent && test -z "$(git ls-files -d)" ' -test_expect_success 'ls-files --delete' ' +test_expect_success 'ls-files --deleted' ' setup_dirty && test -z "$(git ls-files -d)" ' diff --git a/t/t7201-co.sh b/t/t7201-co.sh index be9672e5a0..0c9ec0ad44 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -431,6 +431,7 @@ test_expect_success 'detach a symbolic link HEAD' ' test_expect_success \ 'checkout with --track fakes a sensible -b <name>' ' + git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" && git update-ref refs/remotes/origin/koala/bear renamer && git checkout --track origin/koala/bear && diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index ff265353a3..7e23421309 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -868,4 +868,19 @@ test_expect_success 'submodule deinit fails when submodule has a .git directory test -n "$(git config --get-regexp "submodule\.example\.")" ' +test_expect_success 'submodule with UTF-8 name' ' + svname=$(printf "\303\245 \303\244\303\266") && + mkdir "$svname" && + ( + cd "$svname" && + git init && + >sub && + git add sub && + git commit -m "init sub" + ) && + test_config core.precomposeunicode true && + git submodule add ./"$svname" && + git submodule >&2 && + test -n "$(git submodule | grep "$svname")" +' test_done diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh index 436b7b606e..bdc1f29503 100755 --- a/t/t7500-commit.sh +++ b/t/t7500-commit.sh @@ -13,9 +13,9 @@ commit_msg_is () { expect=commit_msg_is.expect actual=commit_msg_is.actual - printf "%s" "$(git log --pretty=format:%s%b -1)" >$expect && - printf "%s" "$1" >$actual && - test_i18ncmp $expect $actual + printf "%s" "$(git log --pretty=format:%s%b -1)" >"$actual" && + printf "%s" "$1" >"$expect" && + test_i18ncmp "$expect" "$actual" } # A sanity check to see if commit is working at all. diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index 195e7477d8..99ce36f5ef 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -524,4 +524,17 @@ test_expect_success 'commit a file whose name is a dash' ' test_i18ngrep " changed, 5 insertions" output ' +test_expect_success '--only works on to-be-born branch' ' + # This test relies on having something in the index, as it + # would not otherwise actually prove much. So check this. + test -n "$(git ls-files)" && + git checkout --orphan orphan && + echo foo >newfile && + git add newfile && + git commit --only newfile -m"--only on unborn branch" && + echo newfile >expected && + git ls-tree -r --name-only HEAD >actual && + test_cmp expected actual +' + test_done diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh index a4938b1e45..6313da2cdd 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -361,6 +361,23 @@ test_expect_success !AUTOIDENT 'do not fire editor when committer is bogus' ' test_cmp expect .git/result ' +test_expect_success 'do not fire editor if -m <msg> was given' ' + echo tick >file && + git add file && + echo "editor not started" >.git/result && + (GIT_EDITOR="\"$(pwd)/.git/FAKE_EDITOR\"" git commit -m tick) && + test "$(cat .git/result)" = "editor not started" +' + +test_expect_success 'do not fire editor if -m "" was given' ' + echo tock >file && + git add file && + echo "editor not started" >.git/result && + (GIT_EDITOR="\"$(pwd)/.git/FAKE_EDITOR\"" \ + git commit -m "" --allow-empty-message) && + test "$(cat .git/result)" = "editor not started" +' + test_expect_success 'do not fire editor in the presence of conflicts' ' git clean -f && diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh index 6547eb8f54..758a623cdb 100755 --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@ -141,11 +141,10 @@ test_expect_success SYMLINKS 'will not overwrite untracked symlink in leading pa test_path_is_missing .git/MERGE_HEAD ' -test_expect_success SYMLINKS 'will not be confused by symlink in leading path' ' +test_expect_success 'will not be confused by symlink in leading path' ' git reset --hard c0 && rm -rf sub && - ln -s sub2 sub && - git add sub && + test_ln_s_add sub2 sub && git commit -m ln && git checkout sub ' diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index d46f0411bd..2418528487 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -385,6 +385,25 @@ test_expect_success PERL,SYMLINKS 'difftool --dir-diff --symlink without unstage test_cmp actual expect ' +write_script modify-right-file <<\EOF +echo "new content" >"$2/file" +EOF + +run_dir_diff_test 'difftool --dir-diff syncs worktree with unstaged change' ' + test_when_finished git reset --hard && + echo "orig content" >file && + git difftool -d $symlinks --extcmd "$(pwd)/modify-right-file" branch && + echo "new content" >expect && + test_cmp expect file +' + +run_dir_diff_test 'difftool --dir-diff syncs worktree without unstaged change' ' + test_when_finished git reset --hard && + git difftool -d $symlinks --extcmd "$(pwd)/modify-right-file" branch && + echo "new content" >expect && + test_cmp expect file +' + write_script modify-file <<\EOF echo "new content" >file EOF diff --git a/t/t8006-blame-textconv.sh b/t/t8006-blame-textconv.sh index bf6caa4dc3..7683515155 100755 --- a/t/t8006-blame-textconv.sh +++ b/t/t8006-blame-textconv.sh @@ -18,17 +18,13 @@ test_expect_success 'setup ' ' echo "bin: test number 0" >zero.bin && echo "bin: test 1" >one.bin && echo "bin: test number 2" >two.bin && - if test_have_prereq SYMLINKS; then - ln -s one.bin symlink.bin - fi && + test_ln_s_add one.bin symlink.bin && git add . && GIT_AUTHOR_NAME=Number1 git commit -a -m First --date="2010-01-01 18:00:00" && echo "bin: test 1 version 2" >one.bin && echo "bin: test number 2 version 2" >>two.bin && - if test_have_prereq SYMLINKS; then - rm symlink.bin && - ln -s two.bin symlink.bin - fi && + rm -f symlink.bin && + test_ln_s_add two.bin symlink.bin && GIT_AUTHOR_NAME=Number2 git commit -a -m Second --date="2010-01-01 20:00:00" ' @@ -135,7 +131,7 @@ test_expect_success SYMLINKS 'blame --textconv (on symlink)' ' # cp two.bin three.bin and make small tweak # (this will direct blame -C -C three.bin to consider two.bin and symlink.bin) -test_expect_success SYMLINKS 'make another new commit' ' +test_expect_success 'make another new commit' ' cat >three.bin <<\EOF && bin: test number 2 bin: test number 2 version 2 @@ -146,7 +142,7 @@ EOF GIT_AUTHOR_NAME=Number4 git commit -a -m Fourth --date="2010-01-01 23:00:00" ' -test_expect_success SYMLINKS 'blame on last commit (-C -C, symlink)' ' +test_expect_success 'blame on last commit (-C -C, symlink)' ' git blame -C -C three.bin >blame && find_blame <blame >result && cat >expected <<\EOF && diff --git a/t/t8007-cat-file-textconv.sh b/t/t8007-cat-file-textconv.sh index 78a0085e64..b95e102891 100755 --- a/t/t8007-cat-file-textconv.sh +++ b/t/t8007-cat-file-textconv.sh @@ -12,9 +12,7 @@ chmod +x helper test_expect_success 'setup ' ' echo "bin: test" >one.bin && - if test_have_prereq SYMLINKS; then - ln -s one.bin symlink.bin - fi && + test_ln_s_add one.bin symlink.bin && git add . && GIT_AUTHOR_NAME=Number1 git commit -a -m First --date="2010-01-01 18:00:00" && echo "bin: test version 2" >one.bin && @@ -72,14 +70,14 @@ test_expect_success 'cat-file --textconv on previous commit' ' test_cmp expected result ' -test_expect_success SYMLINKS 'cat-file without --textconv (symlink)' ' +test_expect_success 'cat-file without --textconv (symlink)' ' git cat-file blob :symlink.bin >result && printf "%s" "one.bin" >expected test_cmp expected result ' -test_expect_success SYMLINKS 'cat-file --textconv on index (symlink)' ' +test_expect_success 'cat-file --textconv on index (symlink)' ' ! git cat-file --textconv :symlink.bin 2>result && cat >expected <<\EOF && fatal: git cat-file --textconv: unable to run textconv on :symlink.bin @@ -87,7 +85,7 @@ EOF test_cmp expected result ' -test_expect_success SYMLINKS 'cat-file --textconv on HEAD (symlink)' ' +test_expect_success 'cat-file --textconv on HEAD (symlink)' ' ! git cat-file --textconv HEAD:symlink.bin 2>result && cat >expected <<EOF && fatal: git cat-file --textconv: unable to run textconv on HEAD:symlink.bin diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index ebd5c5db45..d6f0271866 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -171,6 +171,81 @@ Result: OK EOF " +test_suppress_self () { + test_commit $3 && + test_when_finished "git reset --hard HEAD^" && + + write_script cccmd-sed <<-EOF && + sed -n -e s/^cccmd--//p "\$1" + EOF + + git commit --amend --author="$1 <$2>" -F - && + clean_fake_sendmail && + git format-patch --stdout -1 >"suppress-self-$3.patch" && + + git send-email --from="$1 <$2>" \ + --to=nobody@example.com \ + --cc-cmd=./cccmd-sed \ + --suppress-cc=self \ + --smtp-server="$(pwd)/fake.sendmail" \ + suppress-self-$3.patch && + + mv msgtxt1 msgtxt1-$3 && + sed -e '/^$/q' msgtxt1-$3 >"msghdr1-$3" && + >"expected-no-cc-$3" && + + (grep '^Cc:' msghdr1-$3 >"actual-no-cc-$3"; + test_cmp expected-no-cc-$3 actual-no-cc-$3) +} + +test_suppress_self_unquoted () { + test_suppress_self "$1" "$2" "unquoted-$3" <<-EOF + test suppress-cc.self unquoted-$3 with name $1 email $2 + + unquoted-$3 + + cccmd--$1 <$2> + + Cc: $1 <$2> + Signed-off-by: $1 <$2> + EOF +} + +test_suppress_self_quoted () { + test_suppress_self "$1" "$2" "quoted-$3" <<-EOF + test suppress-cc.self quoted-$3 with name $1 email $2 + + quoted-$3 + + cccmd--"$1" <$2> + + Cc: $1 <$2> + Cc: "$1" <$2> + Signed-off-by: $1 <$2> + Signed-off-by: "$1" <$2> + EOF +} + +test_expect_success $PREREQ 'self name is suppressed' " + test_suppress_self_unquoted 'A U Thor' 'author@example.com' \ + 'self_name_suppressed' +" + +test_expect_success $PREREQ 'self name with dot is suppressed' " + test_suppress_self_quoted 'A U. Thor' 'author@example.com' \ + 'self_name_dot_suppressed' +" + +test_expect_success $PREREQ 'non-ascii self name is suppressed' " + test_suppress_self_quoted 'Füñný Nâmé' 'odd_?=mail@example.com' \ + 'non_ascii_self_suppressed' +" + +test_expect_success $PREREQ 'sanitized self name is suppressed' " + test_suppress_self_unquoted '\"A U. Thor\"' 'author@example.com' \ + 'self_name_sanitized_suppressed' +" + test_expect_success $PREREQ 'Show all headers' ' git send-email \ --dry-run \ @@ -881,6 +956,20 @@ test_expect_success $PREREQ 'utf8 author is correctly passed on' ' grep "^From: Füñný Nâmé <odd_?=mail@example.com>" msgtxt1 ' +test_expect_success $PREREQ 'utf8 sender is not duplicated' ' + clean_fake_sendmail && + test_commit weird_sender && + test_when_finished "git reset --hard HEAD^" && + git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" && + git format-patch --stdout -1 >funny_name.patch && + git send-email --from="Füñný Nâmé <odd_?=mail@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + funny_name.patch && + grep "^From: " msgtxt1 >msgfrom && + test_line_count = 1 msgfrom +' + test_expect_success $PREREQ 'sendemail.composeencoding works' ' clean_fake_sendmail && git config sendemail.composeencoding iso-8859-1 && diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh index 3077851015..f524d2f383 100755 --- a/t/t9114-git-svn-dcommit-merge.sh +++ b/t/t9114-git-svn-dcommit-merge.sh @@ -48,7 +48,7 @@ test_expect_success 'setup svn repository' ' test_expect_success 'setup git mirror and merge' ' git svn init "$svnrepo" -t tags -T trunk -b branches && git svn fetch && - git checkout --track -b svn remotes/trunk && + git checkout -b svn remotes/trunk && git checkout -b merge && echo new file > new_file && git add new_file && diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 2471bc6777..34c2d8f49a 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -396,7 +396,7 @@ test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj' test_expect_success 'tag-obj_tag' 'git fast-export tag-obj_tag' test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj' -test_expect_success SYMLINKS 'directory becomes symlink' ' +test_expect_success 'directory becomes symlink' ' git init dirtosymlink && git init result && ( @@ -408,8 +408,7 @@ test_expect_success SYMLINKS 'directory becomes symlink' ' git add foo/world bar/world && git commit -q -mone && git rm -r foo && - ln -s bar foo && - git add foo && + test_ln_s_add bar foo && git commit -q -mtwo ) && ( diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 6783c14c1a..6fca19353d 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -156,10 +156,10 @@ test_expect_success \ git commit -a -m "File renamed." && gitweb_run "p=.git;a=commitdiff"' -test_expect_success SYMLINKS \ +test_expect_success \ 'commitdiff(0): file to symlink' \ 'rm renamed_file && - ln -s file renamed_file && + test_ln_s_add file renamed_file && git commit -a -m "File to symlink." && gitweb_run "p=.git;a=commitdiff"' @@ -212,15 +212,14 @@ test_expect_success \ # ---------------------------------------------------------------------- # commitdiff testing (taken from t4114-apply-typechange.sh) -test_expect_success SYMLINKS 'setup typechange commits' ' +test_expect_success 'setup typechange commits' ' echo "hello world" > foo && echo "hi planet" > bar && git update-index --add foo bar && git commit -m initial && git branch initial && rm -f foo && - ln -s bar foo && - git update-index foo && + test_ln_s_add bar foo && git commit -m "foo symlinked to bar" && git branch foo-symlinked-to-bar && rm -f foo && @@ -361,11 +360,7 @@ test_expect_success \ echo "Changed" >> 04-rename-to && test_chmod +x 05-mode-change && rm -f 06-file-or-symlink && - if test_have_prereq SYMLINKS; then - ln -s 01-change 06-file-or-symlink - else - printf %s 01-change > 06-file-or-symlink - fi && + test_ln_s_add 01-change 06-file-or-symlink && echo "Changed and have mode changed" > 07-change-mode-change && test_chmod +x 07-change-mode-change && git commit -a -m "Large commit" && diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index 083b319ed1..15521cc4f9 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -276,7 +276,7 @@ test_expect_success 'prompt - rebase merge' ' ' test_expect_success 'prompt - rebase' ' - printf " ((t2)|REBASE 1/3)" > expected && + printf " (b2|REBASE 1/3)" > expected && git checkout b2 && test_when_finished "git checkout master" && test_must_fail git rebase b1 b2 && diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 52510094ad..fac9234d3c 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -679,3 +679,20 @@ test_create_repo () { mv .git/hooks .git/hooks-disabled ) || exit } + +# This function helps on symlink challenged file systems when it is not +# important that the file system entry is a symbolic link. +# Use test_ln_s_add instead of "ln -s x y && git add y" to add a +# symbolic link entry y to the index. + +test_ln_s_add () { + if test_have_prereq SYMLINKS + then + ln -s "$1" "$2" && + git update-index --add "$2" + else + printf '%s' "$1" >"$2" && + ln_s_obj=$(git hash-object -w "$2") && + git update-index --add --cacheinfo 120000 $ln_s_obj "$2" + fi +} diff --git a/test-chmtime.c b/test-chmtime.c index 02b42badd5..2e601a8038 100644 --- a/test-chmtime.c +++ b/test-chmtime.c @@ -84,7 +84,7 @@ int main(int argc, const char *argv[]) if (stat(argv[i], &sb) < 0) { fprintf(stderr, "Failed to stat %s: %s\n", argv[i], strerror(errno)); - return -1; + return 1; } #ifdef WIN32 @@ -92,7 +92,7 @@ int main(int argc, const char *argv[]) chmod(argv[i], sb.st_mode | S_IWUSR)) { fprintf(stderr, "Could not make user-writable %s: %s", argv[i], strerror(errno)); - return -1; + return 1; } #endif @@ -107,7 +107,7 @@ int main(int argc, const char *argv[]) if (utb.modtime != sb.st_mtime && utime(argv[i], &utb) < 0) { fprintf(stderr, "Failed to modify time on %s: %s\n", argv[i], strerror(errno)); - return -1; + return 1; } } @@ -115,5 +115,5 @@ int main(int argc, const char *argv[]) usage: fprintf(stderr, "usage: %s %s\n", argv[0], usage_str); - return -1; + return 1; } diff --git a/test-read-cache.c b/test-read-cache.c new file mode 100644 index 0000000000..b25bcf139b --- /dev/null +++ b/test-read-cache.c @@ -0,0 +1,13 @@ +#include "cache.h" + +int main (int argc, char **argv) +{ + int i, cnt = 1; + if (argc == 2) + cnt = strtol(argv[1], NULL, 0); + for (i = 0; i < cnt; i++) { + read_cache(); + discard_cache(); + } + return 0; +} diff --git a/upload-pack.c b/upload-pack.c index bfa6279cc4..127e59a603 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -592,7 +592,7 @@ static void receive_needs(void) die("invalid shallow line: %s", line); object = parse_object(sha1); if (!object) - die("did not find object for %s", line); + continue; if (object->type != OBJ_COMMIT) die("invalid shallow object %s", sha1_to_hex(sha1)); if (!(object->flags & CLIENT_SHALLOW)) { diff --git a/wildmatch.c b/wildmatch.c index 7192bdc1b8..f91ba99f32 100644 --- a/wildmatch.c +++ b/wildmatch.c @@ -196,6 +196,11 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) } if (t_ch <= p_ch && t_ch >= prev_ch) matched = 1; + else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch)) { + uchar t_ch_upper = toupper(t_ch); + if (t_ch_upper <= p_ch && t_ch_upper >= prev_ch) + matched = 1; + } p_ch = 0; /* This makes "prev_ch" get set to 0. */ } else if (p_ch == '[' && p[1] == ':') { const uchar *s; @@ -245,6 +250,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) } else if (CC_EQ(s,i, "upper")) { if (ISUPPER(t_ch)) matched = 1; + else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch)) + matched = 1; } else if (CC_EQ(s,i, "xdigit")) { if (ISXDIGIT(t_ch)) matched = 1; |