diff options
166 files changed, 1775 insertions, 828 deletions
diff --git a/Documentation/RelNotes/2.8.0.txt b/Documentation/RelNotes/2.8.0.txt new file mode 100644 index 000000000..ac3f8789d --- /dev/null +++ b/Documentation/RelNotes/2.8.0.txt @@ -0,0 +1,121 @@ +Git 2.8 Release Notes +===================== + +Updates since v2.7 +------------------ + +UI, Workflows & Features + + * "branch --delete" has "branch -d" but "push --delete" does not. + (merge 38a2559 ps/push-delete-option later to maint). + + * "git blame" learned to produce the progress eye-candy when it takes + too much time before emitting the first line of the result. + + * "git grep" can now be configured (or told from the command line) + how many threads to use when searching in the working tree files. + + * Some "git notes" operations, e.g. "git log --notes=<note>", should + be able to read notes from any tree-ish that is shaped like a notes + tree, but the notes infrastructure required that the argument must + be a ref under refs/notes/. Loosen it to require a valid ref only + when the operation would update the notes (in which case we must + have a place to store the updated notes tree, iow, a ref). + + * "git grep" by default does not fall back to its "--no-index" + behaviour outside a directory under Git's control (otherwise the + user may by mistake end up running a huge recursive search); with a + new configuration (set in $HOME/.gitconfig--by definition this + cannot be set in the config file per project), this safety can be + disabled. + + +Performance, Internal Implementation, Development Support etc. + + * Add a framework to spawn a group of processes in parallel, and use + it to run "git fetch --recurse-submodules" in parallel. + + * A slight update to the Makefile to mark "phoney" targets + as such correctly. + + * In-core storage of the reverse index for .pack files (which lets + you go from a pack offset to an object name) has been streamlined. + + * d95138e6 (setup: set env $GIT_WORK_TREE when work tree is set, like + $GIT_DIR, 2015-06-26) attempted to work around a glitch in alias + handling by overwriting GIT_WORK_TREE environment variable to + affect subprocesses when set_git_work_tree() gets called, which + resulted in a rather unpleasant regression to "clone" and "init". + Try to address the same issue by always restoring the environment + and respawning the real underlying command when handling alias. + + +Also contains various documentation updates and code clean-ups. + + +Fixes since v2.7 +---------------- + +Unless otherwise noted, all the fixes since v2.7 in the maintenance +track are contained in this release (see the maintenance releases' +notes for details). + + * An earlier change in 2.5.x-era broke users' hooks and aliases by + exporting GIT_WORK_TREE to point at the root of the working tree, + interfering when they tried to use a different working tree without + setting GIT_WORK_TREE environment themselves. + (merge df1e6ea nd/stop-setenv-work-tree later to maint). + + * The "exclude_list" structure has the usual "alloc, nr" pair of + fields to be used by ALLOC_GROW(), but clear_exclude_list() forgot + to reset 'alloc' to 0 when it cleared 'nr' to discard the managed + array. + (merge 2653a8c nd/dir-exclude-cleanup later to maint). + + * Paths that have been told the index about with "add -N" are not + quite yet in the index, but a few commands behaved as if they + already are in a harmful way. + (merge 4d55200 nd/ita-cleanup later to maint). + + * "git send-email" was confused by escaped quotes stored in the alias + files saved by "mutt", which has been corrected. + (merge 2c510f2 ew/send-email-mutt-alias-fix later to maint). + + * A few unportable C construct have been spotted by clang compiler + and have been fixed. + (merge a0df2e5 jk/clang-pedantic later to maint). + + * The documentation has been updated to hint the connection between + the '--signoff' option and DCO. + (merge b2c150d dw/signoff-doc later to maint). + + * "git reflog" incorrectly assumed that all objects that used to be + at the tip of a ref must be commits, which caused it to segfault. + (merge aecad37 dk/reflog-walk-with-non-commit later to maint). + + * The ignore mechanism saw a few regressions around untracked file + listing and sparse checkout selection areas in 2.7.0; the change + that is responsible for the regression has been reverted. + (merge 8c72236 nd/exclusion-regression-fix later to maint). + + * Some codepaths used fopen(3) when opening a fixed path in $GIT_DIR + (e.g. COMMIT_EDITMSG) that is meant to be left after the command is + done. This however did not work well if the repository is set to + be shared with core.sharedRepository and the umask of the previous + user is tighter. They have been made to work better by calling + unlink(2) and retrying after fopen(3) fails with EPERM. + (merge ea56518 js/fopen-harder later to maint). + + * Asking gitweb for a nonexistent commit left a warning in the server + log. + + Somebody may want to follow this up with an additional test, perhaps? + IIRC, we do test that no Perl warnings are given to the server log, + so this should have been caught if our test coverage were good. + (merge a9eb90a ho/gitweb-squelch-undef-warning later to maint). + + * Other minor clean-ups and documentation updates + (merge 99487cf ss/user-manual later to maint). + (merge e914ef0 ew/for-each-ref-doc later to maint). + (merge 36fc7d8 sg/t6050-failing-editor-test-fix later to maint). + (merge 60253a6 ss/clone-depth-single-doc later to maint). diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt index 760eab742..02cb6845c 100644 --- a/Documentation/blame-options.txt +++ b/Documentation/blame-options.txt @@ -69,6 +69,13 @@ include::line-range-format.txt[] iso format is used. For supported values, see the discussion of the --date option at linkgit:git-log[1]. +--[no-]progress:: + Progress status is reported on the standard error stream + by default when it is attached to a terminal. This flag + enables progress reporting even if not attached to a + terminal. Can't use `--progress` together with `--porcelain` + or `--incremental`. + -M|<num>|:: Detect moved or copied lines within a file. When a commit moves or copies a block of lines (e.g. the original file diff --git a/Documentation/config.txt b/Documentation/config.txt index f61788668..0f710ca3c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -870,6 +870,8 @@ When preserve, also pass `--preserve-merges` along to 'git rebase' so that locally committed merge commits will not be flattened by running 'git pull'. + +When the value is `interactive`, the rebase is run in interactive mode. ++ *NOTE*: this is a possibly dangerous operation; do *not* use it unless you understand the implications (see linkgit:git-rebase[1] for details). @@ -1450,6 +1452,14 @@ grep.extendedRegexp:: option is ignored when the 'grep.patternType' option is set to a value other than 'default'. +grep.threads:: + Number of grep worker threads to use. + See `grep.threads` in linkgit:git-grep[1] for more information. + +grep.fallbackToNoIndex:: + If set to true, fall back to git grep --no-index if git grep + is executed outside of a git repository. Defaults to false. + gpg.program:: Use this custom program instead of "gpg" found on $PATH when making or verifying a PGP signature. The program must support the @@ -2149,6 +2159,8 @@ When preserve, also pass `--preserve-merges` along to 'git rebase' so that locally committed merge commits will not be flattened by running 'git pull'. + +When the value is `interactive`, the rebase is run in interactive mode. ++ *NOTE*: this is a possibly dangerous operation; do *not* use it unless you understand the implications (see linkgit:git-rebase[1] for details). diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index 45583d845..952dfdfef 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -8,10 +8,11 @@ option old data in `.git/FETCH_HEAD` will be overwritten. --depth=<depth>:: - Deepen or shorten the history of a 'shallow' repository created by - `git clone` with `--depth=<depth>` option (see linkgit:git-clone[1]) - to the specified number of commits from the tip of each remote - branch history. Tags for the deepened commits are not fetched. + Limit fetching to the specified number of commits from the tip of + each remote branch history. If fetching to a 'shallow' repository + created by `git clone` with `--depth=<depth>` option (see + linkgit:git-clone[1]), deepen or shorten the history to the specified + number of commits. Tags for the deepened commits are not fetched. --unshallow:: If the source repository is complete, convert a shallow @@ -100,6 +101,13 @@ ifndef::git-pull[] reference to a commit that isn't already in the local submodule clone. +-j:: +--jobs=<n>:: + Number of parallel children to be used for fetching submodules. + Each will fetch from different submodules, such that fetching many + submodules will be faster. By default submodules will be fetched + one at a time. + --no-recurse-submodules:: Disable recursive fetching of submodules (this has the same effect as using the '--recurse-submodules=no' option). diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index 452c1feb2..13cdd7f3b 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -35,6 +35,7 @@ OPTIONS --signoff:: Add a `Signed-off-by:` line to the commit message, using the committer identity of yourself. + See the signoff option in linkgit:git-commit[1] for more information. -k:: --keep:: diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt index e6e947c80..ba5417567 100644 --- a/Documentation/git-blame.txt +++ b/Documentation/git-blame.txt @@ -10,7 +10,8 @@ SYNOPSIS [verse] 'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental] [-L <range>] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>] - [--abbrev=<n>] [<rev> | --contents <file> | --reverse <rev>] [--] <file> + [--progress] [--abbrev=<n>] [<rev> | --contents <file> | --reverse <rev>] + [--] <file> DESCRIPTION ----------- diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 77da29a47..6154e5723 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -100,6 +100,7 @@ effect to your index in a row. -s:: --signoff:: Add Signed-off-by line at the end of the commit message. + See the signoff option in linkgit:git-commit[1] for more information. -S[<keyid>]:: --gpg-sign[=<keyid>]:: diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 6bf000dac..789b668f7 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -190,15 +190,14 @@ objects from the source repository into a pack in the cloned repository. --depth <depth>:: Create a 'shallow' clone with a history truncated to the - specified number of revisions. + specified number of commits. Implies `--single-branch` unless + `--no-single-branch` is given to fetch the histories near the + tips of all branches. --[no-]single-branch:: Clone only the history leading to the tip of a single branch, either specified by the `--branch` option or the primary - branch remote's `HEAD` points at. When creating a shallow - clone with the `--depth` option, this is the default, unless - `--no-single-branch` is given to fetch the histories near the - tips of all branches. + branch remote's `HEAD` points at. Further fetches into the resulting repository will only update the remote-tracking branch for the branch this option was used for the initial cloning. If the HEAD at the remote did not point at any diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 7f34a5b33..9ec6b3cc1 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -154,7 +154,11 @@ OPTIONS -s:: --signoff:: Add Signed-off-by line by the committer at the end of the commit - log message. + log message. The meaning of a signoff depends on the project, + but it typically certifies that committer has + the rights to submit this work under the same license and + agrees to a Developer Certificate of Origin + (see http://developercertificate.org/ for more information). -n:: --no-verify:: diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index c6f073cea..06208c499 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -142,6 +142,11 @@ In addition to the above, for commit and tag objects, the header field names (`tree`, `parent`, `object`, `type`, and `tag`) can be used to specify the value in the header field. +For commit and tag objects, the special `creatordate` and `creator` +fields will correspond to the appropriate date or name-email-date tuple +from the `committer` or `tagger` fields depending on the object type. +These are intended for working on a mix of annotated and lightweight tags. + Fields that have name-email-date tuple as its value (`author`, `committer`, and `tagger`) can be suffixed with `name`, `email`, and `date` to extract the named component. @@ -153,8 +158,8 @@ line is 'contents:body', where body is all of the lines after the first blank line. The optional GPG signature is `contents:signature`. The first `N` lines of the message is obtained using `contents:lines=N`. -For sorting purposes, fields with numeric values sort in numeric -order (`objectsize`, `authordate`, `committerdate`, `taggerdate`). +For sorting purposes, fields with numeric values sort in numeric order +(`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`). All other fields are used to sort in their byte-value order. There is also an option to sort by versions, this can be done by using diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index e3cdaeb95..b149e0906 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -109,6 +109,7 @@ include::diff-options.txt[] --signoff:: Add `Signed-off-by:` line to the commit message, using the committer identity of yourself. + See the signoff option in linkgit:git-commit[1] for more information. --stdout:: Print all commits to the standard output in mbox format, diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 4a44d6da1..cb0f6cf67 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -23,6 +23,7 @@ SYNOPSIS [--break] [--heading] [-p | --show-function] [-A <post-context>] [-B <pre-context>] [-C <context>] [-W | --function-context] + [--threads <num>] [-f <file>] [-e] <pattern> [--and|--or|--not|(|)|-e <pattern>...] [ [--[no-]exclude-standard] [--cached | --no-index | --untracked] | <tree>...] @@ -53,9 +54,17 @@ grep.extendedRegexp:: option is ignored when the 'grep.patternType' option is set to a value other than 'default'. +grep.threads:: + Number of grep worker threads to use. If unset (or set to 0), + 8 threads are used by default (for now). + grep.fullName:: If set to true, enable '--full-name' option by default. +grep.fallbackToNoIndex:: + If set to true, fall back to git grep --no-index if git grep + is executed outside of a git repository. Defaults to false. + OPTIONS ------- @@ -227,6 +236,10 @@ OPTIONS effectively showing the whole function in which the match was found. +--threads <num>:: + Number of grep worker threads to use. + See `grep.threads` in 'CONFIGURATION' for more information. + -f <file>:: Read patterns from <file>, one per line. diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt index 93c72a29c..a62a2a615 100644 --- a/Documentation/git-pull.txt +++ b/Documentation/git-pull.txt @@ -101,7 +101,7 @@ Options related to merging include::merge-options.txt[] -r:: ---rebase[=false|true|preserve]:: +--rebase[=false|true|preserve|interactive]:: When true, rebase the current branch on top of the upstream branch after fetching. If there is a remote-tracking branch corresponding to the upstream branch and the upstream branch @@ -113,6 +113,8 @@ to `git rebase` so that locally created merge commits will not be flattened. + When false, merge the current branch into the upstream branch. + +When `interactive`, enable the interactive mode of rebase. ++ See `pull.rebase`, `branch.<name>.rebase` and `branch.autoSetupRebase` in linkgit:git-config[1] if you want to make `git pull` always use `--rebase` instead of merging. diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index 4c775bcec..32482cec4 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [verse] 'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>] - [--repo=<repository>] [-f | --force] [--prune] [-v | --verbose] + [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose] [-u | --set-upstream] [--[no-]signed|--sign=(true|false|if-asked)] [--force-with-lease[=<refname>[:<expect>]]] diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index b15139ffd..573616a04 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -89,6 +89,7 @@ effect to your index in a row. -s:: --signoff:: Add Signed-off-by line at the end of the commit message. + See the signoff option in linkgit:git-commit[1] for more information. --strategy=<strategy>:: Use the given merge strategy. Should only be used once. diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt index 79a1948a0..473623d63 100644 --- a/Documentation/gitignore.txt +++ b/Documentation/gitignore.txt @@ -82,12 +82,12 @@ PATTERN FORMAT - An optional prefix "`!`" which negates the pattern; any matching file excluded by a previous pattern will become - included again. + included again. It is not possible to re-include a file if a parent + directory of that file is excluded. Git doesn't list excluded + directories for performance reasons, so any patterns on contained + files have no effect, no matter where they are defined. Put a backslash ("`\`") in front of the first "`!`" for patterns that begin with a literal "`!`", for example, "`\!important!.txt`". - It is possible to re-include a file if a parent directory of that - file is excluded if certain conditions are met. See section NOTES - for detail. - If the pattern ends with a slash, it is removed for the purpose of the following description, but it would only find @@ -141,21 +141,6 @@ not tracked by Git remain untracked. To stop tracking a file that is currently tracked, use 'git rm --cached'. -To re-include files or directories when their parent directory is -excluded, the following conditions must be met: - - - The rules to exclude a directory and re-include a subset back must - be in the same .gitignore file. - - - The directory part in the re-include rules must be literal (i.e. no - wildcards) - - - The rules to exclude the parent directory must not end with a - trailing slash. - - - The rules to exclude the parent directory must have at least one - slash. - EXAMPLES -------- diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index e22597425..cafc28435 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -531,6 +531,11 @@ The most notable example is `HEAD`. "Secure Hash Algorithm 1"; a cryptographic hash function. In the context of Git used as a synonym for <<def_object_name,object name>>. +[[def_shallow_clone]]shallow clone:: + Mostly a synonym to <<def_shallow_repository,shallow repository>> + but the phrase makes it more explicit that it was created by + running `git clone --depth=...` command. + [[def_shallow_repository]]shallow repository:: A shallow <<def_repository,repository>> has an incomplete history some of whose <<def_commit,commits>> have <<def_parent,parents>> cauterized away (in other diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt index 4b659ac1a..54b88b6dc 100644 --- a/Documentation/pretty-options.txt +++ b/Documentation/pretty-options.txt @@ -43,7 +43,7 @@ people using 80-column terminals. commit may be copied to the output. ifndef::git-rev-list[] ---notes[=<ref>]:: +--notes[=<treeish>]:: Show the notes (see linkgit:git-notes[1]) that annotate the commit, when showing the commit log message. This is the default for `git log`, `git show` and `git whatchanged` commands when @@ -54,8 +54,8 @@ By default, the notes shown are from the notes refs listed in the 'core.notesRef' and 'notes.displayRef' variables (or corresponding environment overrides). See linkgit:git-config[1] for more details. + -With an optional '<ref>' argument, show this notes ref instead of the -default notes ref(s). The ref specifies the full refname when it begins +With an optional '<treeish>' argument, use the treeish to find the notes +to display. The treeish can specify the full refname when it begins with `refs/notes/`; when it begins with `notes/`, `refs/` and otherwise `refs/notes/` is prefixed to form a full name of the ref. + @@ -71,7 +71,7 @@ being displayed. Examples: "--notes=foo" will show only notes from "--notes --notes=foo --no-notes --notes=bar" will only show notes from "refs/notes/bar". ---show-notes[=<ref>]:: +--show-notes[=<treeish>]:: --[no-]standard-notes:: These options are deprecated. Use the above --notes/--no-notes options instead. diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 1c790ac74..ec6bacfcd 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -2125,8 +2125,37 @@ Allowing web browsing of a repository ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The gitweb cgi script provides users an easy way to browse your -project's files and history without having to install Git; see the file -gitweb/INSTALL in the Git source tree for instructions on setting it up. +project's revisions, file contents and logs without having to install +Git. Features like RSS/Atom feeds and blame/annotation details may +optionally be enabled. + +The linkgit:git-instaweb[1] command provides a simple way to start +browsing the repository using gitweb. The default server when using +instaweb is lighttpd. + +See the file gitweb/INSTALL in the Git source tree and +linkgit:gitweb[1] for instructions on details setting up a permament +installation with a CGI or Perl capable server. + +[[how-to-get-a-git-repository-with-minimal-history]] +How to get a Git repository with minimal history +------------------------------------------------ + +A <<def_shallow_clone,shallow clone>>, with its truncated +history, is useful when one is interested only in recent history +of a project and getting full history from the upstream is +expensive. + +A <<def_shallow_clone,shallow clone>> is created by specifying +the linkgit:git-clone[1] `--depth` switch. The depth can later be +changed with the linkgit:git-fetch[1] `--depth` switch, or full +history restored with `--unshallow`. + +Merging inside a <<def_shallow_clone,shallow clone>> will work as long +as a merge base is in the recent history. +Otherwise, it will be like merging unrelated histories and may +have to result in huge conflicts. This limitation may make such +a repository unsuitable to be used in merge based workflows. [[sharing-development-examples]] Examples @@ -4636,23 +4665,15 @@ Scan email archives for other stuff left out Scan man pages to see if any assume more background than this manual provides. -Simplify beginning by suggesting disconnected head instead of -temporary branch creation? - Add more good examples. Entire sections of just cookbook examples might be a good idea; maybe make an "advanced examples" section a standard end-of-chapter section? Include cross-references to the glossary, where appropriate. -Document shallow clones? See draft 1.5.0 release notes for some -documentation. - Add a section on working with other version control systems, including CVS, Subversion, and just imports of series of release tarballs. -More details on gitweb? - Write a chapter on using plumbing and writing scripts. Alternates, clone -reference, etc. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 51aa9e680..5873f163e 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.7.0 +DEF_VER=v2.7.0.GIT LF=' ' @@ -2025,6 +2025,7 @@ $(VCSSVN_LIB): $(VCSSVN_OBJS) export DEFAULT_EDITOR DEFAULT_PAGER +.PHONY: doc man html info pdf doc: $(MAKE) -C Documentation all @@ -2068,6 +2069,7 @@ po/git.pot: $(GENERATED_H) FORCE $(LOCALIZED_PERL) mv $@+ $@ +.PHONY: pot pot: po/git.pot POFILES := $(wildcard po/*.po) @@ -2277,6 +2279,7 @@ mergetools_instdir_SQ = $(subst ','\'',$(mergetools_instdir)) install_bindir_programs := $(patsubst %,%$X,$(BINDIR_PROGRAMS_NEED_X)) $(BINDIR_PROGRAMS_NO_X) +.PHONY: profile-install profile-fast-install profile-install: profile $(MAKE) install @@ -2343,6 +2346,8 @@ endif done && \ ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X" +.PHONY: install-gitweb install-doc install-man install-html install-info install-pdf +.PHONY: quick-install-doc quick-install-man quick-install-html install-gitweb: $(MAKE) -C gitweb install @@ -2402,6 +2407,7 @@ rpm: dist htmldocs = git-htmldocs-$(GIT_VERSION) manpages = git-manpages-$(GIT_VERSION) +.PHONY: dist-doc distclean dist-doc: $(RM) -r .doc-tmp-dir mkdir .doc-tmp-dir @@ -2470,6 +2476,8 @@ ALL_COMMANDS += git ALL_COMMANDS += gitk ALL_COMMANDS += gitweb ALL_COMMANDS += git-gui git-citool + +.PHONY: check-docs check-docs:: @(for v in $(ALL_COMMANDS); \ do \ @@ -2514,6 +2522,7 @@ check-builtins:: ### Test suite coverage testing # .PHONY: coverage coverage-clean coverage-compile coverage-test coverage-report +.PHONY: coverage-untested-functions cover_db cover_db_html .PHONY: coverage-clean-results coverage: @@ -1 +1 @@ -Documentation/RelNotes/2.7.0.txt
\ No newline at end of file +Documentation/RelNotes/2.8.0.txt
\ No newline at end of file diff --git a/builtin/am.c b/builtin/am.c index 9fb42fdd7..de235cf11 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -1939,6 +1939,7 @@ next: */ if (!state->rebasing) { am_destroy(state); + close_all_packs(); run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); } } diff --git a/builtin/blame.c b/builtin/blame.c index 1df13cf7f..55bf5fae9 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -28,6 +28,7 @@ #include "line-range.h" #include "line-log.h" #include "dir.h" +#include "progress.h" static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"); @@ -50,6 +51,7 @@ static int incremental; static int xdl_opts; static int abbrev = -1; static int no_whole_file_rename; +static int show_progress; static struct date_mode blame_date_mode = { DATE_ISO8601 }; static size_t blame_date_width; @@ -127,6 +129,11 @@ struct origin { char path[FLEX_ARRAY]; }; +struct progress_info { + struct progress *progress; + int blamed_lines; +}; + static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen, xdl_emit_hunk_consume_func_t hunk_func, void *cb_data) { @@ -1746,7 +1753,8 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat) * The blame_entry is found to be guilty for the range. * Show it in incremental output. */ -static void found_guilty_entry(struct blame_entry *ent) +static void found_guilty_entry(struct blame_entry *ent, + struct progress_info *pi) { if (incremental) { struct origin *suspect = ent->suspect; @@ -1758,6 +1766,8 @@ static void found_guilty_entry(struct blame_entry *ent) write_filename_info(suspect->path); maybe_flush_or_die(stdout, "stdout"); } + pi->blamed_lines += ent->num_lines; + display_progress(pi->progress, pi->blamed_lines); } /* @@ -1768,6 +1778,11 @@ static void assign_blame(struct scoreboard *sb, int opt) { struct rev_info *revs = sb->revs; struct commit *commit = prio_queue_get(&sb->commits); + struct progress_info pi = { NULL, 0 }; + + if (show_progress) + pi.progress = start_progress_delay(_("Blaming lines"), + sb->num_lines, 50, 1); while (commit) { struct blame_entry *ent; @@ -1809,7 +1824,7 @@ static void assign_blame(struct scoreboard *sb, int opt) suspect->guilty = 1; for (;;) { struct blame_entry *next = ent->next; - found_guilty_entry(ent); + found_guilty_entry(ent, &pi); if (next) { ent = next; continue; @@ -1825,6 +1840,8 @@ static void assign_blame(struct scoreboard *sb, int opt) if (DEBUG) /* sanity */ sanity_check_refcnt(sb); } + + stop_progress(&pi.progress); } static const char *format_time(unsigned long time, const char *tz_str, @@ -2392,11 +2409,6 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, ce->ce_mode = create_ce_mode(mode); add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); - /* - * We are not going to write this out, so this does not matter - * right now, but someday we might optimize diff-index --cached - * with cache-tree information. - */ cache_tree_invalidate_path(&the_index, path); return commit; @@ -2520,6 +2532,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")), OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")), OPT_BOOL(0, "show-stats", &show_stats, N_("Show work cost statistics")), + OPT_BOOL(0, "progress", &show_progress, N_("Force progress reporting")), OPT_BIT(0, "score-debug", &output_option, N_("Show output score for blame entries"), OUTPUT_SHOW_SCORE), OPT_BIT('f', "show-name", &output_option, N_("Show original filename (Default: auto)"), OUTPUT_SHOW_NAME), OPT_BIT('n', "show-number", &output_option, N_("Show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER), @@ -2555,6 +2568,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) save_commit_buffer = 0; dashdash_pos = 0; + show_progress = -1; parse_options_start(&ctx, argc, argv, prefix, options, PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0); @@ -2579,6 +2593,13 @@ parse_done: DIFF_OPT_CLR(&revs.diffopt, FOLLOW_RENAMES); argc = parse_options_end(&ctx); + if (incremental || (output_option & OUTPUT_PORCELAIN)) { + if (show_progress > 0) + die("--progress can't be used with --incremental or porcelain formats"); + show_progress = 0; + } else if (show_progress < 0) + show_progress = isatty(2); + if (0 < abbrev) /* one more abbrev length is needed for the boundary commit */ abbrev++; @@ -2828,11 +2849,11 @@ parse_done: read_mailmap(&mailmap, NULL); + assign_blame(&sb, opt); + if (!incremental) setup_pager(); - assign_blame(&sb, opt); - free(final_commit_name); if (incremental) diff --git a/builtin/commit.c b/builtin/commit.c index d054f8496..89bf6ad38 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -761,7 +761,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, hook_arg2 = ""; } - s->fp = fopen(git_path(commit_editmsg), "w"); + s->fp = fopen_for_writing(git_path(commit_editmsg)); if (s->fp == NULL) die_errno(_("could not open '%s'"), git_path(commit_editmsg)); diff --git a/builtin/fast-export.c b/builtin/fast-export.c index d9ac5d841..2471297f7 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -880,7 +880,7 @@ static void export_marks(char *file) FILE *f; int e = 0; - f = fopen(file, "w"); + f = fopen_for_writing(file); if (!f) die_errno("Unable to open marks file %s for writing.", file); diff --git a/builtin/fetch.c b/builtin/fetch.c index c85f3471d..8e742135f 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -37,6 +37,7 @@ static int prune = -1; /* unspecified */ static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity; static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; static int tags = TAGS_DEFAULT, unshallow, update_shallow; +static int max_children = 1; static const char *depth; static const char *upload_pack; static struct strbuf default_rla = STRBUF_INIT; @@ -99,6 +100,8 @@ static struct option builtin_fetch_options[] = { N_("fetch all tags and associated objects"), TAGS_SET), OPT_SET_INT('n', NULL, &tags, N_("do not fetch all tags (--no-tags)"), TAGS_UNSET), + OPT_INTEGER('j', "jobs", &max_children, + N_("number of submodules fetched in parallel")), OPT_BOOL('p', "prune", &prune, N_("prune remote-tracking branches no longer on remote")), { OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"), @@ -837,7 +840,7 @@ static void check_not_current_branch(struct ref *ref_map) static int truncate_fetch_head(void) { const char *filename = git_path_fetch_head(); - FILE *fp = fopen(filename, "w"); + FILE *fp = fopen_for_writing(filename); if (!fp) return error(_("cannot open %s: %s\n"), filename, strerror(errno)); @@ -1213,7 +1216,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) result = fetch_populated_submodules(&options, submodule_prefix, recurse_submodules, - verbosity < 0); + verbosity < 0, + max_children); argv_array_clear(&options); } @@ -1221,6 +1225,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) list.strdup_strings = 1; string_list_clear(&list, 0); + close_all_packs(); + argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL); if (verbosity < 0) argv_array_push(&argv_gc_auto, "--quiet"); diff --git a/builtin/grep.c b/builtin/grep.c index 4229cae39..5526fd705 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -24,11 +24,11 @@ static char const * const grep_usage[] = { NULL }; -static int use_threads = 1; +#define GREP_NUM_THREADS_DEFAULT 8 +static int num_threads; #ifndef NO_PTHREADS -#define THREADS 8 -static pthread_t threads[THREADS]; +static pthread_t *threads; /* We use one producer thread and THREADS consumer * threads. The producer adds struct work_items to 'todo' and the @@ -63,13 +63,13 @@ static pthread_mutex_t grep_mutex; static inline void grep_lock(void) { - if (use_threads) + if (num_threads) pthread_mutex_lock(&grep_mutex); } static inline void grep_unlock(void) { - if (use_threads) + if (num_threads) pthread_mutex_unlock(&grep_mutex); } @@ -206,7 +206,8 @@ static void start_threads(struct grep_opt *opt) strbuf_init(&todo[i].out, 0); } - for (i = 0; i < ARRAY_SIZE(threads); i++) { + threads = xcalloc(num_threads, sizeof(*threads)); + for (i = 0; i < num_threads; i++) { int err; struct grep_opt *o = grep_opt_dup(opt); o->output = strbuf_out; @@ -238,12 +239,14 @@ static int wait_all(void) pthread_cond_broadcast(&cond_add); grep_unlock(); - for (i = 0; i < ARRAY_SIZE(threads); i++) { + for (i = 0; i < num_threads; i++) { void *h; pthread_join(threads[i], &h); hit |= (int) (intptr_t) h; } + free(threads); + pthread_mutex_destroy(&grep_mutex); pthread_mutex_destroy(&grep_read_mutex); pthread_mutex_destroy(&grep_attr_mutex); @@ -267,6 +270,14 @@ static int grep_cmd_config(const char *var, const char *value, void *cb) int st = grep_config(var, value, cb); if (git_color_default_config(var, value, cb) < 0) st = -1; + + if (!strcmp(var, "grep.threads")) { + num_threads = git_config_int(var, value); + if (num_threads < 0) + die(_("invalid number of threads specified (%d) for %s"), + num_threads, var); + } + return st; } @@ -294,7 +305,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, } #ifndef NO_PTHREADS - if (use_threads) { + if (num_threads) { add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1); strbuf_release(&pathbuf); return 0; @@ -323,7 +334,7 @@ static int grep_file(struct grep_opt *opt, const char *filename) strbuf_addstr(&buf, filename); #ifndef NO_PTHREADS - if (use_threads) { + if (num_threads) { add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename); strbuf_release(&buf); return 0; @@ -375,7 +386,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int for (nr = 0; nr < active_nr; nr++) { const struct cache_entry *ce = active_cache[nr]; - if (!S_ISREG(ce->ce_mode)) + if (!S_ISREG(ce->ce_mode) || ce_intent_to_add(ce)) continue; if (!ce_path_match(ce, pathspec, NULL)) continue; @@ -697,6 +708,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) N_("show <n> context lines before matches")), OPT_INTEGER('A', "after-context", &opt.post_context, N_("show <n> context lines after matches")), + OPT_INTEGER(0, "threads", &num_threads, + N_("use <n> worker threads")), OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"), context_callback), OPT_BOOL('p', "show-function", &opt.funcname, @@ -755,9 +768,15 @@ int cmd_grep(int argc, const char **argv, const char *prefix) PARSE_OPT_STOP_AT_NON_OPTION); grep_commit_pattern_type(pattern_type_arg, &opt); - if (use_index && !startup_info->have_repository) - /* die the same way as if we did it at the beginning */ - setup_git_directory(); + if (use_index && !startup_info->have_repository) { + int fallback = 0; + git_config_get_bool("grep.fallbacktonoindex", &fallback); + if (fallback) + use_index = 0; + else + /* die the same way as if we did it at the beginning */ + setup_git_directory(); + } /* * skip a -- separator; we know it cannot be @@ -786,7 +805,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) opt.output_priv = &path_list; opt.output = append_path; string_list_append(&path_list, show_in_pager); - use_threads = 0; } if (!opt.pattern_list) @@ -817,14 +835,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix) } #ifndef NO_PTHREADS - if (list.nr || cached || online_cpus() == 1) - use_threads = 0; + if (list.nr || cached || show_in_pager) + num_threads = 0; + else if (num_threads == 0) + num_threads = GREP_NUM_THREADS_DEFAULT; + else if (num_threads < 0) + die(_("invalid number of threads specified (%d)"), num_threads); #else - use_threads = 0; + num_threads = 0; #endif #ifndef NO_PTHREADS - if (use_threads) { + if (num_threads) { if (!(opt.name_only || opt.unmatch_name_only || opt.count) && (opt.pre_context || opt.post_context || opt.file_break || opt.funcbody)) @@ -894,7 +916,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) hit = grep_objects(&opt, &pathspec, &list); } - if (use_threads) + if (num_threads) hit |= wait_all(); if (hit && show_in_pager) run_pager(&opt, prefix); diff --git a/builtin/merge.c b/builtin/merge.c index 15bf95b3a..b98a3489b 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -404,6 +404,7 @@ static void finish(struct commit *head_commit, * We ignore errors in 'gc --auto', since the * user should see them. */ + close_all_packs(); run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); } } diff --git a/builtin/notes.c b/builtin/notes.c index 52aa9af74..e1556896f 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -286,7 +286,7 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd) if (!c) return 0; } else { - init_notes(NULL, NULL, NULL, 0); + init_notes(NULL, NULL, NULL, NOTES_INIT_WRITABLE); t = &default_notes_tree; } @@ -329,15 +329,18 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd) return ret; } -static struct notes_tree *init_notes_check(const char *subcommand) +static struct notes_tree *init_notes_check(const char *subcommand, + int flags) { struct notes_tree *t; - init_notes(NULL, NULL, NULL, 0); + const char *ref; + init_notes(NULL, NULL, NULL, flags); t = &default_notes_tree; - if (!starts_with(t->ref, "refs/notes/")) + ref = (flags & NOTES_INIT_WRITABLE) ? t->update_ref : t->ref; + if (!starts_with(ref, "refs/notes/")) die("Refusing to %s notes in %s (outside of refs/notes/)", - subcommand, t->ref); + subcommand, ref); return t; } @@ -360,7 +363,7 @@ static int list(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_list_usage, options); } - t = init_notes_check("list"); + t = init_notes_check("list", 0); if (argc) { if (get_sha1(argv[0], object)) die(_("Failed to resolve '%s' as a valid ref."), argv[0]); @@ -420,7 +423,7 @@ static int add(int argc, const char **argv, const char *prefix) if (get_sha1(object_ref, object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); - t = init_notes_check("add"); + t = init_notes_check("add", NOTES_INIT_WRITABLE); note = get_note(t, object); if (note) { @@ -511,7 +514,7 @@ static int copy(int argc, const char **argv, const char *prefix) if (get_sha1(object_ref, object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); - t = init_notes_check("copy"); + t = init_notes_check("copy", NOTES_INIT_WRITABLE); note = get_note(t, object); if (note) { @@ -589,7 +592,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) if (get_sha1(object_ref, object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); - t = init_notes_check(argv[0]); + t = init_notes_check(argv[0], NOTES_INIT_WRITABLE); note = get_note(t, object); prepare_note_data(object, &d, edit ? note : NULL); @@ -652,7 +655,7 @@ static int show(int argc, const char **argv, const char *prefix) if (get_sha1(object_ref, object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); - t = init_notes_check("show"); + t = init_notes_check("show", 0); note = get_note(t, object); if (!note) @@ -809,7 +812,7 @@ static int merge(int argc, const char **argv, const char *prefix) expand_notes_ref(&remote_ref); o.remote_ref = remote_ref.buf; - t = init_notes_check("merge"); + t = init_notes_check("merge", NOTES_INIT_WRITABLE); if (strategy) { if (parse_notes_merge_strategy(strategy, &o.strategy)) { @@ -901,7 +904,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, git_notes_remove_usage, 0); - t = init_notes_check("remove"); + t = init_notes_check("remove", NOTES_INIT_WRITABLE); if (!argc && !from_stdin) { retval = remove_one_note(t, "HEAD", flag); @@ -943,7 +946,7 @@ static int prune(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_prune_usage, options); } - t = init_notes_check("prune"); + t = init_notes_check("prune", NOTES_INIT_WRITABLE); prune_notes(t, (verbose ? NOTES_PRUNE_VERBOSE : 0) | (show_only ? NOTES_PRUNE_VERBOSE|NOTES_PRUNE_DRYRUN : 0) ); diff --git a/builtin/pull.c b/builtin/pull.c index 5145fc60a..c713fe065 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -22,7 +22,8 @@ enum rebase_type { REBASE_INVALID = -1, REBASE_FALSE = 0, REBASE_TRUE, - REBASE_PRESERVE + REBASE_PRESERVE, + REBASE_INTERACTIVE }; /** @@ -42,6 +43,8 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value, return REBASE_TRUE; else if (!strcmp(value, "preserve")) return REBASE_PRESERVE; + else if (!strcmp(value, "interactive")) + return REBASE_INTERACTIVE; if (fatal) die(_("Invalid value for %s: %s"), key, value); @@ -95,6 +98,7 @@ static int opt_force; static char *opt_tags; static char *opt_prune; static char *opt_recurse_submodules; +static char *max_children; static int opt_dry_run; static char *opt_keep; static char *opt_depth; @@ -112,7 +116,7 @@ static struct option pull_options[] = { /* Options passed to git-merge or git-rebase */ OPT_GROUP(N_("Options related to merging")), { OPTION_CALLBACK, 'r', "rebase", &opt_rebase, - "false|true|preserve", + "false|true|preserve|interactive", N_("incorporate changes by rebasing rather than merging"), PARSE_OPT_OPTARG, parse_opt_rebase }, OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL, @@ -178,6 +182,9 @@ static struct option pull_options[] = { N_("on-demand"), N_("control recursive fetching of submodules"), PARSE_OPT_OPTARG), + OPT_PASSTHRU('j', "jobs", &max_children, N_("n"), + N_("number of submodules pulled in parallel"), + PARSE_OPT_OPTARG), OPT_BOOL(0, "dry-run", &opt_dry_run, N_("dry run")), OPT_PASSTHRU('k', "keep", &opt_keep, NULL, @@ -525,6 +532,8 @@ static int run_fetch(const char *repo, const char **refspecs) argv_array_push(&args, opt_prune); if (opt_recurse_submodules) argv_array_push(&args, opt_recurse_submodules); + if (max_children) + argv_array_push(&args, max_children); if (opt_dry_run) argv_array_push(&args, "--dry-run"); if (opt_keep) @@ -772,6 +781,8 @@ static int run_rebase(const unsigned char *curr_head, /* Options passed to git-rebase */ if (opt_rebase == REBASE_PRESERVE) argv_array_push(&args, "--preserve-merges"); + else if (opt_rebase == REBASE_INTERACTIVE) + argv_array_push(&args, "--interactive"); if (opt_diffstat) argv_array_push(&args, opt_diffstat); argv_array_pushv(&args, opt_strategies.argv); diff --git a/builtin/push.c b/builtin/push.c index 8963dbdf3..960ffc31e 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -538,7 +538,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL), OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"), (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), - OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")), + OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")), OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")), OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN), OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN), diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index ca3813187..f2d6761af 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1618,7 +1618,7 @@ static void prepare_shallow_update(struct command *commands, continue; si->need_reachability_test[i]++; for (k = 0; k < 32; k++) - if (si->used_shallow[i][j] & (1 << k)) + if (si->used_shallow[i][j] & (1U << k)) si->shallow_ref[j * 32 + k]++; } @@ -1796,6 +1796,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) "gc", "--auto", "--quiet", NULL, }; int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR; + close_all_packs(); run_command_v_opt(argv_gc_auto, opt); } if (auto_update_server_info) diff --git a/builtin/remote.c b/builtin/remote.c index 6694cf20e..2b2ff9b7d 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -251,7 +251,7 @@ static int add(int argc, const char **argv) struct branch_info { char *remote_name; struct string_list merge; - int rebase; + enum { NO_REBASE, NORMAL_REBASE, INTERACTIVE_REBASE } rebase; }; static struct string_list branch_list; @@ -311,7 +311,9 @@ static int config_read_branches(const char *key, const char *value, void *cb) if (v >= 0) info->rebase = v; else if (!strcmp(value, "preserve")) - info->rebase = 1; + info->rebase = NORMAL_REBASE; + else if (!strcmp(value, "interactive")) + info->rebase = INTERACTIVE_REBASE; } } return 0; @@ -980,7 +982,9 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data) printf(" %-*s ", show_info->width, item->string); if (branch_info->rebase) { - printf_ln(_("rebases onto remote %s"), merge->items[0].string); + printf_ln(_(branch_info->rebase == INTERACTIVE_REBASE ? + "rebases interactively onto remote %s" : + "rebases onto remote %s"), merge->items[0].string); return 0; } else if (show_info->any_rebase) { printf_ln(_(" merges with remote %s"), merge->items[0].string); diff --git a/builtin/rm.c b/builtin/rm.c index 80b972f92..8829b09d0 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -211,7 +211,7 @@ static int check_local_mod(unsigned char *head, int index_only) * "intent to add" entry. */ if (local_changes && staged_changes) { - if (!index_only || !(ce->ce_flags & CE_INTENT_TO_ADD)) + if (!index_only || !ce_intent_to_add(ce)) string_list_append(&files_staged, name); } else if (!index_only) { diff --git a/cache-tree.c b/cache-tree.c index a59e6f1e1..20ee7b52d 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -377,7 +377,7 @@ static int update_one(struct cache_tree *it, * they are not part of generated trees. Invalidate up * to root to force cache-tree users to read elsewhere. */ - if (ce->ce_flags & CE_INTENT_TO_ADD) { + if (ce_intent_to_add(ce)) { to_invalidate = 1; continue; } @@ -9,6 +9,7 @@ #include "convert.h" #include "trace.h" #include "string-list.h" +#include "pack-revindex.h" #include SHA1_HEADER #ifndef platform_SHA_CTX @@ -214,7 +215,7 @@ struct cache_entry { #define CE_INTENT_TO_ADD (1 << 29) #define CE_SKIP_WORKTREE (1 << 30) /* CE_EXTENDED2 is for future extension */ -#define CE_EXTENDED2 (1 << 31) +#define CE_EXTENDED2 (1U << 31) #define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD | CE_SKIP_WORKTREE) @@ -259,6 +260,7 @@ static inline unsigned create_ce_flags(unsigned stage) #define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE) #define ce_skip_worktree(ce) ((ce)->ce_flags & CE_SKIP_WORKTREE) #define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE) +#define ce_intent_to_add(ce) ((ce)->ce_flags & CE_INTENT_TO_ADD) #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644) static inline unsigned int create_ce_mode(unsigned int mode) @@ -1299,6 +1301,7 @@ extern struct packed_git { freshened:1, do_not_close:1; unsigned char sha1[20]; + struct revindex_entry *revindex; /* something like ".git/objects/pack/xxxxx.pack" */ char pack_name[FLEX_ARRAY]; /* more */ } *packed_git; diff --git a/compat/bswap.h b/compat/bswap.h index 7fed637ed..d47c00354 100644 --- a/compat/bswap.h +++ b/compat/bswap.h @@ -149,11 +149,12 @@ static inline uint64_t git_bswap64(uint64_t x) * and is faster on architectures with memory alignment issues. */ -#if defined(__i386__) || defined(__x86_64__) || \ +#if !defined(NO_UNALIGNED_LOADS) && ( \ + defined(__i386__) || defined(__x86_64__) || \ defined(_M_IX86) || defined(_M_X64) || \ defined(__ppc__) || defined(__ppc64__) || \ defined(__powerpc__) || defined(__powerpc64__) || \ - defined(__s390__) || defined(__s390x__) + defined(__s390__) || defined(__s390x__)) #define get_be16(p) ntohs(*(unsigned short *)(p)) #define get_be32(p) ntohl(*(unsigned int *)(p)) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 695680751..51f5223e2 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -1312,6 +1312,7 @@ _git_grep () --full-name --line-number --extended-regexp --basic-regexp --fixed-strings --perl-regexp + --threads --files-with-matches --name-only --files-without-match --max-depth @@ -1808,7 +1809,7 @@ _git_config () return ;; branch.*.rebase) - __gitcomp "false true" + __gitcomp "false true preserve interactive" return ;; remote.pushdefault) diff --git a/contrib/examples/git-commit.sh b/contrib/examples/git-commit.sh index 934505bab..86c9cfa0c 100755 --- a/contrib/examples/git-commit.sh +++ b/contrib/examples/git-commit.sh @@ -574,10 +574,10 @@ then if test "$templatefile" != "" then # Test whether this is just the unaltered template. - if cnt=`sed -e '/^#/d' < "$templatefile" | + if cnt=$(sed -e '/^#/d' < "$templatefile" | git stripspace | diff "$GIT_DIR"/COMMIT_BAREMSG - | - wc -l` && + wc -l) && test 0 -lt $cnt then have_commitmsg=t @@ -630,8 +630,8 @@ then fi if test -z "$quiet" then - commit=`git diff-tree --always --shortstat --pretty="format:%h: %s"\ - --abbrev --summary --root HEAD --` + commit=$(git diff-tree --always --shortstat --pretty="format:%h: %s"\ + --abbrev --summary --root HEAD --) echo "Created${initial_commit:+ initial} commit $commit" fi fi diff --git a/contrib/examples/git-fetch.sh b/contrib/examples/git-fetch.sh index 554070909..57d2e5616 100755 --- a/contrib/examples/git-fetch.sh +++ b/contrib/examples/git-fetch.sh @@ -146,13 +146,13 @@ esac reflist=$(get_remote_refs_for_fetch "$@") if test "$tags" then - taglist=`IFS=' ' && + taglist=$(IFS=' ' && echo "$ls_remote_result" | git show-ref --exclude-existing=refs/tags/ | while read sha1 name do echo ".${name}:${name}" - done` || exit + done) || exit if test "$#" -gt 1 then # remote URL plus explicit refspecs; we need to merge them. diff --git a/contrib/examples/git-merge.sh b/contrib/examples/git-merge.sh index 52f2aafb9..ee99f1a4e 100755 --- a/contrib/examples/git-merge.sh +++ b/contrib/examples/git-merge.sh @@ -523,10 +523,10 @@ do if test "$exit" -eq 1 then - cnt=`{ + cnt=$({ git diff-files --name-only git ls-files --unmerged - } | wc -l` + } | wc -l) if test $best_cnt -le 0 || test $cnt -le $best_cnt then best_strategy=$strategy diff --git a/contrib/examples/git-repack.sh b/contrib/examples/git-repack.sh index 96e3fed32..672af9344 100755 --- a/contrib/examples/git-repack.sh +++ b/contrib/examples/git-repack.sh @@ -67,8 +67,8 @@ case ",$all_into_one," in ,t,) args= existing= if [ -d "$PACKDIR" ]; then - for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \ - | sed -e 's/^\.\///' -e 's/\.pack$//'` + for e in $(cd "$PACKDIR" && find . -type f -name '*.pack' \ + | sed -e 's/^\.\///' -e 's/\.pack$//') do if [ -e "$PACKDIR/$e.keep" ]; then : keep diff --git a/contrib/examples/git-revert.sh b/contrib/examples/git-revert.sh index 7e2aad549..197838d10 100755 --- a/contrib/examples/git-revert.sh +++ b/contrib/examples/git-revert.sh @@ -138,8 +138,8 @@ cherry-pick) }' logmsg=$(git show -s --pretty=raw --encoding="$encoding" "$commit") - set_author_env=`echo "$logmsg" | - LANG=C LC_ALL=C sed -ne "$pick_author_script"` + set_author_env=$(echo "$logmsg" | + LANG=C LC_ALL=C sed -ne "$pick_author_script") eval "$set_author_env" export GIT_AUTHOR_NAME export GIT_AUTHOR_EMAIL @@ -160,9 +160,9 @@ cherry-pick) esac >.msg eval GITHEAD_$head=HEAD -eval GITHEAD_$next='`git show -s \ +eval GITHEAD_$next='$(git show -s \ --pretty=oneline --encoding="$encoding" "$commit" | - sed -e "s/^[^ ]* //"`' + sed -e "s/^[^ ]* //")' export GITHEAD_$head GITHEAD_$next # This three way merge is an interesting one. We are at diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh index edf36f8c3..efbdb720e 100755 --- a/contrib/subtree/git-subtree.sh +++ b/contrib/subtree/git-subtree.sh @@ -245,7 +245,10 @@ find_latest_squash() case "$a" in START) sq="$b" ;; git-subtree-mainline:) main="$b" ;; - git-subtree-split:) sub="$b" ;; + git-subtree-split:) + sub="$(git rev-parse "$b^0")" || + die "could not rev-parse split hash $b from commit $sq" + ;; END) if [ -n "$sub" ]; then if [ -n "$main" ]; then @@ -278,7 +281,10 @@ find_existing_splits() case "$a" in START) sq="$b" ;; git-subtree-mainline:) main="$b" ;; - git-subtree-split:) sub="$b" ;; + git-subtree-split:) + sub="$(git rev-parse "$b^0")" || + die "could not rev-parse split hash $b from commit $sq" + ;; END) debug " Main is: '$main'" if [ -z "$main" -a -n "$sub" ]; then diff --git a/contrib/thunderbird-patch-inline/appp.sh b/contrib/thunderbird-patch-inline/appp.sh index 8dc73ece1..1053872ee 100755 --- a/contrib/thunderbird-patch-inline/appp.sh +++ b/contrib/thunderbird-patch-inline/appp.sh @@ -31,8 +31,8 @@ BODY=$(sed -e "1,/${SEP}/d" $1) CMT_MSG=$(sed -e '1,/^$/d' -e '/^---$/,$d' "${PATCH}") DIFF=$(sed -e '1,/^---$/d' "${PATCH}") -CCS=`echo -e "$CMT_MSG\n$HEADERS" | sed -n -e 's/^Cc: \(.*\)$/\1,/gp' \ - -e 's/^Signed-off-by: \(.*\)/\1,/gp'` +CCS=$(echo -e "$CMT_MSG\n$HEADERS" | sed -n -e 's/^Cc: \(.*\)$/\1,/gp' \ + -e 's/^Signed-off-by: \(.*\)/\1,/gp') echo "$SUBJECT" > $1 echo "Cc: $CCS" >> $1 @@ -91,7 +91,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data) #define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28) #define DIFF_OPT_FUNCCONTEXT (1 << 29) #define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30) -#define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1 << 31) +#define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1U << 31) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_TOUCHED(opts, flag) ((opts)->touched_flags & DIFF_OPT_##flag) @@ -564,9 +564,7 @@ void clear_exclude_list(struct exclude_list *el) free(el->excludes); free(el->filebuf); - el->nr = 0; - el->excludes = NULL; - el->filebuf = NULL; + memset(el, 0, sizeof(*el)); } static void trim_trailing_spaces(char *buf) @@ -882,25 +880,6 @@ int match_pathname(const char *pathname, int pathlen, */ if (!patternlen && !namelen) return 1; - /* - * This can happen when we ignore some exclude rules - * on directories in other to see if negative rules - * may match. E.g. - * - * /abc - * !/abc/def/ghi - * - * The pattern of interest is "/abc". On the first - * try, we should match path "abc" with this pattern - * in the "if" statement right above, but the caller - * ignores it. - * - * On the second try with paths within "abc", - * e.g. "abc/xyz", we come here and try to match it - * with "/abc". - */ - if (!patternlen && namelen && *name == '/') - return 1; } return fnmatch_icase_mem(pattern, patternlen, @@ -909,48 +888,6 @@ int match_pathname(const char *pathname, int pathlen, } /* - * Return non-zero if pathname is a directory and an ancestor of the - * literal path in a (negative) pattern. This is used to keep - * descending in "foo" and "foo/bar" when the pattern is - * "!foo/bar/.gitignore". "foo/notbar" will not be descended however. - */ -static int match_neg_path(const char *pathname, int pathlen, int *dtype, - const char *base, int baselen, - const char *pattern, int prefix, int patternlen, - int flags) -{ - assert((flags & EXC_FLAG_NEGATIVE) && !(flags & EXC_FLAG_NODIR)); - - if (*dtype == DT_UNKNOWN) - *dtype = get_dtype(NULL, pathname, pathlen); - if (*dtype != DT_DIR) - return 0; - - if (*pattern == '/') { - pattern++; - patternlen--; - prefix--; - } - - if (baselen) { - if (((pathlen < baselen && base[pathlen] == '/') || - pathlen == baselen) && - !strncmp_icase(pathname, base, pathlen)) - return 1; - pathname += baselen + 1; - pathlen -= baselen + 1; - } - - - if (prefix && - ((pathlen < prefix && pattern[pathlen] == '/') && - !strncmp_icase(pathname, pattern, pathlen))) - return 1; - - return 0; -} - -/* * Scan the given exclude list in reverse to see whether pathname * should be ignored. The first match (i.e. the last on the list), if * any, determines the fate. Returns the exclude_list element which @@ -963,7 +900,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname, struct exclude_list *el) { struct exclude *exc = NULL; /* undecided */ - int i, matched_negative_path = 0; + int i; if (!el->nr) return NULL; /* undefined */ @@ -998,18 +935,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname, exc = x; break; } - - if ((x->flags & EXC_FLAG_NEGATIVE) && !matched_negative_path && - match_neg_path(pathname, pathlen, dtype, x->base, - x->baselen ? x->baselen - 1 : 0, - exclude, prefix, x->patternlen, x->flags)) - matched_negative_path = 1; - } - if (exc && - !(exc->flags & EXC_FLAG_NEGATIVE) && - !(exc->flags & EXC_FLAG_NODIR) && - matched_negative_path) - exc = NULL; + } return exc; } diff --git a/environment.c b/environment.c index 2da7fe2e0..1cc4aab4e 100644 --- a/environment.c +++ b/environment.c @@ -235,8 +235,6 @@ void set_git_work_tree(const char *new_work_tree) } git_work_tree_initialized = 1; work_tree = xstrdup(real_path(new_work_tree)); - if (setenv(GIT_WORK_TREE_ENVIRONMENT, work_tree, 1)) - die("could not set GIT_WORK_TREE to '%s'", work_tree); } const char *get_git_work_tree(void) diff --git a/git-compat-util.h b/git-compat-util.h index 2da0a75a3..e8f286722 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -733,6 +733,7 @@ extern int xmkstemp_mode(char *template, int mode); extern int odb_mkstemp(char *template, size_t limit, const char *pattern); extern int odb_pack_keep(char *name, size_t namesz, const unsigned char *sha1); extern char *xgetcwd(void); +extern FILE *fopen_for_writing(const char *path); #define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), (alloc) * sizeof(*(x))) diff --git a/git-gui/po/glossary/txt-to-pot.sh b/git-gui/po/glossary/txt-to-pot.sh index 49bf7c536..8249915d3 100755 --- a/git-gui/po/glossary/txt-to-pot.sh +++ b/git-gui/po/glossary/txt-to-pot.sh @@ -11,7 +11,7 @@ if [ $# -eq 0 ] then cat <<! -Usage: `basename $0` git-gui-glossary.txt > git-gui-glossary.pot +Usage: $(basename $0) git-gui-glossary.txt > git-gui-glossary.pot ! exit 1; fi @@ -33,7 +33,7 @@ cat <<! msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: `date +'%Y-%m-%d %H:%M%z'`\n" +"POT-Creation-Date: $(date +'%Y-%m-%d %H:%M%z')\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/git-rebase.sh b/git-rebase.sh index af7ba5fd9..cf60c4390 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -176,7 +176,7 @@ You can run "git stash pop" or "git stash drop" at any time. finish_rebase () { apply_autostash && - git gc --auto && + { git gc --auto || true; } && rm -rf "$state_dir" } diff --git a/git-send-email.perl b/git-send-email.perl index 6caa5b563..d35690134 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -524,8 +524,13 @@ my %parse_alias = ( if (/^\s*alias\s+(?:-group\s+\S+\s+)*(\S+)\s+(.*)$/) { my ($alias, $addr) = ($1, $2); $addr =~ s/#.*$//; # mutt allows # comments - # commas delimit multiple addresses - $aliases{$alias} = [ split_addrs($addr) ]; + # commas delimit multiple addresses + my @addr = split_addrs($addr); + + # quotes may be escaped in the file, + # unescape them so we do not double-escape them later. + s/\\"/"/g foreach @addr; + $aliases{$alias} = \@addr }}}, mailrc => sub { my $fh = shift; while (<$fh>) { if (/^alias\s+(\S+)\s+(.*)$/) { @@ -25,14 +25,14 @@ static const char *env_names[] = { GIT_PREFIX_ENVIRONMENT }; static char *orig_env[4]; -static int saved_environment; +static int saved_env_before_alias; -static void save_env(void) +static void save_env_before_alias(void) { int i; - if (saved_environment) + if (saved_env_before_alias) return; - saved_environment = 1; + saved_env_before_alias = 1; orig_cwd = xgetcwd(); for (i = 0; i < ARRAY_SIZE(env_names); i++) { orig_env[i] = getenv(env_names[i]); @@ -41,13 +41,16 @@ static void save_env(void) } } -static void restore_env(void) +static void restore_env(int external_alias) { int i; - if (orig_cwd && chdir(orig_cwd)) + if (!external_alias && orig_cwd && chdir(orig_cwd)) die_errno("could not move to %s", orig_cwd); free(orig_cwd); for (i = 0; i < ARRAY_SIZE(env_names); i++) { + if (external_alias && + !strcmp(env_names[i], GIT_PREFIX_ENVIRONMENT)) + continue; if (orig_env[i]) setenv(env_names[i], orig_env[i], 1); else @@ -226,14 +229,14 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) static int handle_alias(int *argcp, const char ***argv) { int envchanged = 0, ret = 0, saved_errno = errno; - const char *subdir; int count, option_count; const char **new_argv; const char *alias_command; char *alias_string; int unused_nongit; - subdir = setup_git_directory_gently(&unused_nongit); + save_env_before_alias(); + setup_git_directory_gently(&unused_nongit); alias_command = (*argv)[0]; alias_string = alias_lookup(alias_command); @@ -243,6 +246,7 @@ static int handle_alias(int *argcp, const char ***argv) int argc = *argcp, i; commit_pager_choice(); + restore_env(1); /* build alias_argv */ alias_argv = xmalloc(sizeof(*alias_argv) * (argc + 1)); @@ -291,8 +295,7 @@ static int handle_alias(int *argcp, const char ***argv) ret = 1; } - if (subdir && chdir(subdir)) - die_errno("Cannot change to '%s'", subdir); + restore_env(0); errno = saved_errno; @@ -307,7 +310,6 @@ static int handle_alias(int *argcp, const char ***argv) * RUN_SETUP for reading from the configuration file. */ #define NEED_WORK_TREE (1<<3) -#define NO_SETUP (1<<4) struct cmd_struct { const char *cmd; @@ -389,7 +391,7 @@ static struct cmd_struct commands[] = { { "cherry", cmd_cherry, RUN_SETUP }, { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE }, { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE }, - { "clone", cmd_clone, NO_SETUP }, + { "clone", cmd_clone }, { "column", cmd_column, RUN_SETUP_GENTLY }, { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE }, { "commit-tree", cmd_commit_tree, RUN_SETUP }, @@ -415,8 +417,8 @@ static struct cmd_struct commands[] = { { "hash-object", cmd_hash_object }, { "help", cmd_help }, { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY }, - { "init", cmd_init_db, NO_SETUP }, - { "init-db", cmd_init_db, NO_SETUP }, + { "init", cmd_init_db }, + { "init-db", cmd_init_db }, { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP_GENTLY }, { "log", cmd_log, RUN_SETUP }, { "ls-files", cmd_ls_files, RUN_SETUP }, @@ -530,9 +532,13 @@ static void handle_builtin(int argc, const char **argv) builtin = get_builtin(cmd); if (builtin) { - if (saved_environment && (builtin->option & NO_SETUP)) - restore_env(); - else + /* + * XXX: if we can figure out cases where it is _safe_ + * to do, we can avoid spawning a new process when + * saved_env_before_alias is true + * (i.e. setup_git_dir* has been run once) + */ + if (!saved_env_before_alias) exit(run_builtin(builtin, argc, argv)); } } @@ -590,7 +596,6 @@ static int run_argv(int *argcp, const char ***argv) */ if (done_alias) break; - save_env(); if (!handle_alias(argcp, argv)) break; done_alias = 1; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 7a5b23acf..05d7910b7 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -7576,7 +7576,7 @@ sub git_object { git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null' or die_error(404, "Object does not exist"); $type = <$fd>; - chomp $type; + defined $type && chomp $type; close $fd or die_error(404, "Object does not exist"); diff --git a/notes-cache.c b/notes-cache.c index c4e9bb7f6..5dfc5cbd0 100644 --- a/notes-cache.c +++ b/notes-cache.c @@ -32,14 +32,14 @@ void notes_cache_init(struct notes_cache *c, const char *name, const char *validity) { struct strbuf ref = STRBUF_INIT; - int flags = 0; + int flags = NOTES_INIT_WRITABLE; memset(c, 0, sizeof(*c)); c->validity = xstrdup(validity); strbuf_addf(&ref, "refs/notes/%s", name); if (!notes_cache_match_validity(ref.buf, validity)) - flags = NOTES_INIT_EMPTY; + flags |= NOTES_INIT_EMPTY; init_notes(&c->tree, ref.buf, combine_notes_overwrite, flags); strbuf_release(&ref); } @@ -49,7 +49,8 @@ int notes_cache_write(struct notes_cache *c) unsigned char tree_sha1[20]; unsigned char commit_sha1[20]; - if (!c || !c->tree.initialized || !c->tree.ref || !*c->tree.ref) + if (!c || !c->tree.initialized || !c->tree.update_ref || + !*c->tree.update_ref) return -1; if (!c->tree.dirty) return 0; @@ -59,8 +60,8 @@ int notes_cache_write(struct notes_cache *c) if (commit_tree(c->validity, strlen(c->validity), tree_sha1, NULL, commit_sha1, NULL, NULL) < 0) return -1; - if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL, - 0, UPDATE_REFS_QUIET_ON_ERR) < 0) + if (update_ref("update notes cache", c->tree.update_ref, commit_sha1, + NULL, 0, UPDATE_REFS_QUIET_ON_ERR) < 0) return -1; return 0; diff --git a/notes-utils.c b/notes-utils.c index 299e34bcc..24a33616a 100644 --- a/notes-utils.c +++ b/notes-utils.c @@ -37,7 +37,7 @@ void commit_notes(struct notes_tree *t, const char *msg) if (!t) t = &default_notes_tree; - if (!t->initialized || !t->ref || !*t->ref) + if (!t->initialized || !t->update_ref || !*t->update_ref) die(_("Cannot commit uninitialized/unreferenced notes tree")); if (!t->dirty) return; /* don't have to commit an unchanged tree */ @@ -48,7 +48,7 @@ void commit_notes(struct notes_tree *t, const char *msg) create_notes_commit(t, NULL, buf.buf, buf.len, commit_sha1); strbuf_insert(&buf, 0, "notes: ", 7); /* commit message starts at index 7 */ - update_ref(buf.buf, t->ref, commit_sha1, NULL, 0, + update_ref(buf.buf, t->update_ref, commit_sha1, NULL, 0, UPDATE_REFS_DIE_ON_ERR); strbuf_release(&buf); @@ -148,7 +148,7 @@ struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd) free(c); return NULL; } - c->trees = load_notes_trees(c->refs); + c->trees = load_notes_trees(c->refs, NOTES_INIT_WRITABLE); string_list_clear(c->refs, 0); free(c->refs); return c; @@ -1011,13 +1011,16 @@ void init_notes(struct notes_tree *t, const char *notes_ref, t->first_non_note = NULL; t->prev_non_note = NULL; t->ref = xstrdup_or_null(notes_ref); + t->update_ref = (flags & NOTES_INIT_WRITABLE) ? t->ref : NULL; t->combine_notes = combine_notes; t->initialized = 1; t->dirty = 0; if (flags & NOTES_INIT_EMPTY || !notes_ref || - read_ref(notes_ref, object_sha1)) + get_sha1_treeish(notes_ref, object_sha1)) return; + if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, object_sha1)) + die("Cannot use notes ref %s", notes_ref); if (get_tree_entry(object_sha1, "", sha1, &mode)) die("Failed to read notes tree referenced by %s (%s)", notes_ref, sha1_to_hex(object_sha1)); @@ -1027,7 +1030,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref, load_subtree(t, &root_tree, t->root, 0); } -struct notes_tree **load_notes_trees(struct string_list *refs) +struct notes_tree **load_notes_trees(struct string_list *refs, int flags) { struct string_list_item *item; int counter = 0; @@ -1035,7 +1038,7 @@ struct notes_tree **load_notes_trees(struct string_list *refs) trees = xmalloc((refs->nr+1) * sizeof(struct notes_tree *)); for_each_string_list_item(item, refs) { struct notes_tree *t = xcalloc(1, sizeof(struct notes_tree)); - init_notes(t, item->string, combine_notes_ignore, 0); + init_notes(t, item->string, combine_notes_ignore, flags); trees[counter++] = t; } trees[counter] = NULL; @@ -1071,7 +1074,7 @@ void init_display_notes(struct display_notes_opt *opt) item->string); } - display_notes_trees = load_notes_trees(&display_notes_refs); + display_notes_trees = load_notes_trees(&display_notes_refs, 0); string_list_clear(&display_notes_refs, 0); } @@ -44,6 +44,7 @@ extern struct notes_tree { struct int_node *root; struct non_note *first_non_note, *prev_non_note; char *ref; + char *update_ref; combine_notes_fn combine_notes; int initialized; int dirty; @@ -72,6 +73,13 @@ const char *default_notes_ref(void); #define NOTES_INIT_EMPTY 1 /* + * By default, the notes tree is only readable, and the notes ref can be + * any treeish. The notes tree can however be made writable with this flag, + * in which case only strict ref names can be used. + */ +#define NOTES_INIT_WRITABLE 2 + +/* * Initialize the given notes_tree with the notes tree structure at the given * ref. If given ref is NULL, the value of the $GIT_NOTES_REF environment * variable is used, and if that is missing, the default notes ref is used @@ -276,7 +284,7 @@ void format_display_notes(const unsigned char *object_sha1, * Load the notes tree from each ref listed in 'refs'. The output is * an array of notes_tree*, terminated by a NULL. */ -struct notes_tree **load_notes_trees(struct string_list *refs); +struct notes_tree **load_notes_trees(struct string_list *refs, int flags); /* * Add all refs that match 'glob' to the 'list'. diff --git a/pack-bitmap.c b/pack-bitmap.c index cb9c62280..dd8dc16e6 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -33,9 +33,6 @@ static struct bitmap_index { /* Packfile to which this bitmap index belongs to */ struct packed_git *pack; - /* reverse index for the packfile */ - struct pack_revindex *reverse_index; - /* * Mark the first `reuse_objects` in the packfile as reused: * they will be sent as-is without using them for repacking @@ -308,7 +305,7 @@ static int load_pack_bitmap(void) bitmap_git.bitmaps = kh_init_sha1(); bitmap_git.ext_index.positions = kh_init_sha1_pos(); - bitmap_git.reverse_index = revindex_for_pack(bitmap_git.pack); + load_pack_revindex(bitmap_git.pack); if (!(bitmap_git.commits = read_bitmap_1(&bitmap_git)) || !(bitmap_git.trees = read_bitmap_1(&bitmap_git)) || @@ -380,7 +377,7 @@ static inline int bitmap_position_packfile(const unsigned char *sha1) if (!offset) return -1; - return find_revindex_position(bitmap_git.reverse_index, offset); + return find_revindex_position(bitmap_git.pack, offset); } static int bitmap_position(const unsigned char *sha1) @@ -630,7 +627,7 @@ static void show_objects_for_type( if (pos + offset < bitmap_git.reuse_objects) continue; - entry = &bitmap_git.reverse_index->revindex[pos + offset]; + entry = &bitmap_git.pack->revindex[pos + offset]; sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr); if (bitmap_git.hashes) @@ -804,7 +801,7 @@ int reuse_partial_packfile_from_bitmap(struct packed_git **packfile, return -1; bitmap_git.reuse_objects = *entries = reuse_objects; - *up_to = bitmap_git.reverse_index->revindex[reuse_objects].offset; + *up_to = bitmap_git.pack->revindex[reuse_objects].offset; *packfile = bitmap_git.pack; return 0; @@ -1038,7 +1035,7 @@ int rebuild_existing_bitmaps(struct packing_data *mapping, struct revindex_entry *entry; struct object_entry *oe; - entry = &bitmap_git.reverse_index->revindex[i]; + entry = &bitmap_git.pack->revindex[i]; sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr); oe = packlist_find(mapping, sha1, NULL); diff --git a/pack-revindex.c b/pack-revindex.c index e542ea770..155a8a3d6 100644 --- a/pack-revindex.c +++ b/pack-revindex.c @@ -8,52 +8,13 @@ * size is easily available by examining the pack entry header). It is * also rather expensive to find the sha1 for an object given its offset. * - * We build a hashtable of existing packs (pack_revindex), and keep reverse - * index here -- pack index file is sorted by object name mapping to offset; - * this pack_revindex[].revindex array is a list of offset/index_nr pairs + * The pack index file is sorted by object name mapping to offset; + * this revindex array is a list of offset/index_nr pairs * ordered by offset, so if you know the offset of an object, next offset * is where its packed representation ends and the index_nr can be used to * get the object sha1 from the main index. */ -static struct pack_revindex *pack_revindex; -static int pack_revindex_hashsz; - -static int pack_revindex_ix(struct packed_git *p) -{ - unsigned long ui = (unsigned long)(intptr_t)p; - int i; - - ui = ui ^ (ui >> 16); /* defeat structure alignment */ - i = (int)(ui % pack_revindex_hashsz); - while (pack_revindex[i].p) { - if (pack_revindex[i].p == p) - return i; - if (++i == pack_revindex_hashsz) - i = 0; - } - return -1 - i; -} - -static void init_pack_revindex(void) -{ - int num; - struct packed_git *p; - - for (num = 0, p = packed_git; p; p = p->next) - num++; - if (!num) - return; - pack_revindex_hashsz = num * 11; - pack_revindex = xcalloc(pack_revindex_hashsz, sizeof(*pack_revindex)); - for (p = packed_git; p; p = p->next) { - num = pack_revindex_ix(p); - num = - 1 - num; - pack_revindex[num].p = p; - } - /* revindex elements are lazily initialized */ -} - /* * This is a least-significant-digit radix sort. * @@ -154,14 +115,13 @@ static void sort_revindex(struct revindex_entry *entries, unsigned n, off_t max) /* * Ordered list of offsets of objects in the pack. */ -static void create_pack_revindex(struct pack_revindex *rix) +static void create_pack_revindex(struct packed_git *p) { - struct packed_git *p = rix->p; unsigned num_ent = p->num_objects; unsigned i; const char *index = p->index_data; - rix->revindex = xmalloc(sizeof(*rix->revindex) * (num_ent + 1)); + p->revindex = xmalloc(sizeof(*p->revindex) * (num_ent + 1)); index += 4 * 256; if (p->index_version > 1) { @@ -171,55 +131,42 @@ static void create_pack_revindex(struct pack_revindex *rix) for (i = 0; i < num_ent; i++) { uint32_t off = ntohl(*off_32++); if (!(off & 0x80000000)) { - rix->revindex[i].offset = off; + p->revindex[i].offset = off; } else { - rix->revindex[i].offset = + p->revindex[i].offset = ((uint64_t)ntohl(*off_64++)) << 32; - rix->revindex[i].offset |= + p->revindex[i].offset |= ntohl(*off_64++); } - rix->revindex[i].nr = i; + p->revindex[i].nr = i; } } else { for (i = 0; i < num_ent; i++) { uint32_t hl = *((uint32_t *)(index + 24 * i)); - rix->revindex[i].offset = ntohl(hl); - rix->revindex[i].nr = i; + p->revindex[i].offset = ntohl(hl); + p->revindex[i].nr = i; } } /* This knows the pack format -- the 20-byte trailer * follows immediately after the last object data. */ - rix->revindex[num_ent].offset = p->pack_size - 20; - rix->revindex[num_ent].nr = -1; - sort_revindex(rix->revindex, num_ent, p->pack_size); + p->revindex[num_ent].offset = p->pack_size - 20; + p->revindex[num_ent].nr = -1; + sort_revindex(p->revindex, num_ent, p->pack_size); } -struct pack_revindex *revindex_for_pack(struct packed_git *p) +void load_pack_revindex(struct packed_git *p) { - int num; - struct pack_revindex *rix; - - if (!pack_revindex_hashsz) - init_pack_revindex(); - - num = pack_revindex_ix(p); - if (num < 0) - die("internal error: pack revindex fubar"); - - rix = &pack_revindex[num]; - if (!rix->revindex) - create_pack_revindex(rix); - - return rix; + if (!p->revindex) + create_pack_revindex(p); } -int find_revindex_position(struct pack_revindex *pridx, off_t ofs) +int find_revindex_position(struct packed_git *p, off_t ofs) { int lo = 0; - int hi = pridx->p->num_objects + 1; - struct revindex_entry *revindex = pridx->revindex; + int hi = p->num_objects + 1; + struct revindex_entry *revindex = p->revindex; do { unsigned mi = lo + (hi - lo) / 2; @@ -237,11 +184,13 @@ int find_revindex_position(struct pack_revindex *pridx, off_t ofs) struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs) { - struct pack_revindex *pridx = revindex_for_pack(p); - int pos = find_revindex_position(pridx, ofs); + int pos; + + load_pack_revindex(p); + pos = find_revindex_position(p, ofs); if (pos < 0) return NULL; - return pridx->revindex + pos; + return p->revindex + pos; } diff --git a/pack-revindex.h b/pack-revindex.h index d737f9896..e262f3efe 100644 --- a/pack-revindex.h +++ b/pack-revindex.h @@ -1,18 +1,15 @@ #ifndef PACK_REVINDEX_H #define PACK_REVINDEX_H +struct packed_git; + struct revindex_entry { off_t offset; unsigned int nr; }; -struct pack_revindex { - struct packed_git *p; - struct revindex_entry *revindex; -}; - -struct pack_revindex *revindex_for_pack(struct packed_git *p); -int find_revindex_position(struct pack_revindex *pridx, off_t ofs); +void load_pack_revindex(struct packed_git *p); +int find_revindex_position(struct packed_git *p, off_t ofs); struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs); diff --git a/read-cache.c b/read-cache.c index 84616c8e2..5be7cd1db 100644 --- a/read-cache.c +++ b/read-cache.c @@ -327,7 +327,7 @@ int ie_match_stat(const struct index_state *istate, * by definition never matches what is in the work tree until it * actually gets added. */ - if (ce->ce_flags & CE_INTENT_TO_ADD) + if (ce_intent_to_add(ce)) return DATA_CHANGED | TYPE_CHANGED | MODE_CHANGED; changed = ce_match_stat_basic(ce, st); @@ -1237,7 +1237,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, if (cache_errno == ENOENT) fmt = deleted_fmt; - else if (ce->ce_flags & CE_INTENT_TO_ADD) + else if (ce_intent_to_add(ce)) fmt = added_fmt; /* must be before other checks */ else if (changed & TYPE_CHANGED) fmt = typechange_fmt; diff --git a/reflog-walk.c b/reflog-walk.c index 85b8a5424..0ebd1da5c 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -221,6 +221,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) struct commit_info *commit_info = get_commit_info(commit, &info->reflogs, 0); struct commit_reflog *commit_reflog; + struct object *logobj; struct reflog_info *reflog; info->last_commit_reflog = NULL; @@ -232,15 +233,20 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) commit->parents = NULL; return; } - - reflog = &commit_reflog->reflogs->items[commit_reflog->recno]; info->last_commit_reflog = commit_reflog; - commit_reflog->recno--; - commit_info->commit = (struct commit *)parse_object(reflog->osha1); - if (!commit_info->commit) { + + do { + reflog = &commit_reflog->reflogs->items[commit_reflog->recno]; + commit_reflog->recno--; + logobj = parse_object(reflog->osha1); + } while (commit_reflog->recno && (logobj && logobj->type != OBJ_COMMIT)); + + if (!logobj || logobj->type != OBJ_COMMIT) { + commit_info->commit = NULL; commit->parents = NULL; return; } + commit_info->commit = (struct commit *)logobj; commit->parents = xcalloc(1, sizeof(struct commit_list)); commit->parents->item = commit_info->commit; diff --git a/run-command.c b/run-command.c index 13fa452e8..cdf018457 100644 --- a/run-command.c +++ b/run-command.c @@ -3,6 +3,8 @@ #include "exec_cmd.h" #include "sigchain.h" #include "argv-array.h" +#include "thread-utils.h" +#include "strbuf.h" void child_process_init(struct child_process *child) { @@ -245,7 +247,7 @@ static int wait_or_whine(pid_t pid, const char *argv0, int in_signal) error("waitpid is confused (%s)", argv0); } else if (WIFSIGNALED(status)) { code = WTERMSIG(status); - if (code != SIGINT && code != SIGQUIT) + if (code != SIGINT && code != SIGQUIT && code != SIGPIPE) error("%s died of signal %d", argv0, code); /* * This return value is chosen so that code & 0xff @@ -865,3 +867,336 @@ int capture_command(struct child_process *cmd, struct strbuf *buf, size_t hint) close(cmd->out); return finish_command(cmd); } + +enum child_state { + GIT_CP_FREE, + GIT_CP_WORKING, + GIT_CP_WAIT_CLEANUP, +}; + +struct parallel_processes { + void *data; + + int max_processes; + int nr_processes; + + get_next_task_fn get_next_task; + start_failure_fn start_failure; + task_finished_fn task_finished; + + struct { + enum child_state state; + struct child_process process; + struct strbuf err; + void *data; + } *children; + /* + * The struct pollfd is logically part of *children, + * but the system call expects it as its own array. + */ + struct pollfd *pfd; + + unsigned shutdown : 1; + + int output_owner; + struct strbuf buffered_output; /* of finished children */ +}; + +static int default_start_failure(struct child_process *cp, + struct strbuf *err, + void *pp_cb, + void *pp_task_cb) +{ + int i; + + strbuf_addstr(err, "Starting a child failed:"); + for (i = 0; cp->argv[i]; i++) + strbuf_addf(err, " %s", cp->argv[i]); + + return 0; +} + +static int default_task_finished(int result, + struct child_process *cp, + struct strbuf *err, + void *pp_cb, + void *pp_task_cb) +{ + int i; + + if (!result) + return 0; + + strbuf_addf(err, "A child failed with return code %d:", result); + for (i = 0; cp->argv[i]; i++) + strbuf_addf(err, " %s", cp->argv[i]); + + return 0; +} + +static void kill_children(struct parallel_processes *pp, int signo) +{ + int i, n = pp->max_processes; + + for (i = 0; i < n; i++) + if (pp->children[i].state == GIT_CP_WORKING) + kill(pp->children[i].process.pid, signo); +} + +static struct parallel_processes *pp_for_signal; + +static void handle_children_on_signal(int signo) +{ + kill_children(pp_for_signal, signo); + sigchain_pop(signo); + raise(signo); +} + +static void pp_init(struct parallel_processes *pp, + int n, + get_next_task_fn get_next_task, + start_failure_fn start_failure, + task_finished_fn task_finished, + void *data) +{ + int i; + + if (n < 1) + n = online_cpus(); + + pp->max_processes = n; + + trace_printf("run_processes_parallel: preparing to run up to %d tasks", n); + + pp->data = data; + if (!get_next_task) + die("BUG: you need to specify a get_next_task function"); + pp->get_next_task = get_next_task; + + pp->start_failure = start_failure ? start_failure : default_start_failure; + pp->task_finished = task_finished ? task_finished : default_task_finished; + + pp->nr_processes = 0; + pp->output_owner = 0; + pp->shutdown = 0; + pp->children = xcalloc(n, sizeof(*pp->children)); + pp->pfd = xcalloc(n, sizeof(*pp->pfd)); + strbuf_init(&pp->buffered_output, 0); + + for (i = 0; i < n; i++) { + strbuf_init(&pp->children[i].err, 0); + child_process_init(&pp->children[i].process); + pp->pfd[i].events = POLLIN | POLLHUP; + pp->pfd[i].fd = -1; + } + + pp_for_signal = pp; + sigchain_push_common(handle_children_on_signal); +} + +static void pp_cleanup(struct parallel_processes *pp) +{ + int i; + + trace_printf("run_processes_parallel: done"); + for (i = 0; i < pp->max_processes; i++) { + strbuf_release(&pp->children[i].err); + child_process_clear(&pp->children[i].process); + } + + free(pp->children); + free(pp->pfd); + + /* + * When get_next_task added messages to the buffer in its last + * iteration, the buffered output is non empty. + */ + fputs(pp->buffered_output.buf, stderr); + strbuf_release(&pp->buffered_output); + + sigchain_pop_common(); +} + +/* returns + * 0 if a new task was started. + * 1 if no new jobs was started (get_next_task ran out of work, non critical + * problem with starting a new command) + * <0 no new job was started, user wishes to shutdown early. Use negative code + * to signal the children. + */ +static int pp_start_one(struct parallel_processes *pp) +{ + int i, code; + + for (i = 0; i < pp->max_processes; i++) + if (pp->children[i].state == GIT_CP_FREE) + break; + if (i == pp->max_processes) + die("BUG: bookkeeping is hard"); + + code = pp->get_next_task(&pp->children[i].process, + &pp->children[i].err, + pp->data, + &pp->children[i].data); + if (!code) { + strbuf_addbuf(&pp->buffered_output, &pp->children[i].err); + strbuf_reset(&pp->children[i].err); + return 1; + } + pp->children[i].process.err = -1; + pp->children[i].process.stdout_to_stderr = 1; + pp->children[i].process.no_stdin = 1; + + if (start_command(&pp->children[i].process)) { + code = pp->start_failure(&pp->children[i].process, + &pp->children[i].err, + pp->data, + &pp->children[i].data); + strbuf_addbuf(&pp->buffered_output, &pp->children[i].err); + strbuf_reset(&pp->children[i].err); + if (code) + pp->shutdown = 1; + return code; + } + + pp->nr_processes++; + pp->children[i].state = GIT_CP_WORKING; + pp->pfd[i].fd = pp->children[i].process.err; + return 0; +} + +static void pp_buffer_stderr(struct parallel_processes *pp, int output_timeout) +{ + int i; + + while ((i = poll(pp->pfd, pp->max_processes, output_timeout)) < 0) { + if (errno == EINTR) + continue; + pp_cleanup(pp); + die_errno("poll"); + } + + /* Buffer output from all pipes. */ + for (i = 0; i < pp->max_processes; i++) { + if (pp->children[i].state == GIT_CP_WORKING && + pp->pfd[i].revents & (POLLIN | POLLHUP)) { + int n = strbuf_read_once(&pp->children[i].err, + pp->children[i].process.err, 0); + if (n == 0) { + close(pp->children[i].process.err); + pp->children[i].state = GIT_CP_WAIT_CLEANUP; + } else if (n < 0) + if (errno != EAGAIN) + die_errno("read"); + } + } +} + +static void pp_output(struct parallel_processes *pp) +{ + int i = pp->output_owner; + if (pp->children[i].state == GIT_CP_WORKING && + pp->children[i].err.len) { + fputs(pp->children[i].err.buf, stderr); + strbuf_reset(&pp->children[i].err); + } +} + +static int pp_collect_finished(struct parallel_processes *pp) +{ + int i, code; + int n = pp->max_processes; + int result = 0; + + while (pp->nr_processes > 0) { + for (i = 0; i < pp->max_processes; i++) + if (pp->children[i].state == GIT_CP_WAIT_CLEANUP) + break; + if (i == pp->max_processes) + break; + + code = finish_command(&pp->children[i].process); + + code = pp->task_finished(code, &pp->children[i].process, + &pp->children[i].err, pp->data, + &pp->children[i].data); + + if (code) + result = code; + if (code < 0) + break; + + pp->nr_processes--; + pp->children[i].state = GIT_CP_FREE; + pp->pfd[i].fd = -1; + child_process_init(&pp->children[i].process); + + if (i != pp->output_owner) { + strbuf_addbuf(&pp->buffered_output, &pp->children[i].err); + strbuf_reset(&pp->children[i].err); + } else { + fputs(pp->children[i].err.buf, stderr); + strbuf_reset(&pp->children[i].err); + + /* Output all other finished child processes */ + fputs(pp->buffered_output.buf, stderr); + strbuf_reset(&pp->buffered_output); + + /* + * Pick next process to output live. + * NEEDSWORK: + * For now we pick it randomly by doing a round + * robin. Later we may want to pick the one with + * the most output or the longest or shortest + * running process time. + */ + for (i = 0; i < n; i++) + if (pp->children[(pp->output_owner + i) % n].state == GIT_CP_WORKING) + break; + pp->output_owner = (pp->output_owner + i) % n; + } + } + return result; +} + +int run_processes_parallel(int n, + get_next_task_fn get_next_task, + start_failure_fn start_failure, + task_finished_fn task_finished, + void *pp_cb) +{ + int i, code; + int output_timeout = 100; + int spawn_cap = 4; + struct parallel_processes pp; + + pp_init(&pp, n, get_next_task, start_failure, task_finished, pp_cb); + while (1) { + for (i = 0; + i < spawn_cap && !pp.shutdown && + pp.nr_processes < pp.max_processes; + i++) { + code = pp_start_one(&pp); + if (!code) + continue; + if (code < 0) { + pp.shutdown = 1; + kill_children(&pp, -code); + } + break; + } + if (!pp.nr_processes) + break; + pp_buffer_stderr(&pp, output_timeout); + pp_output(&pp); + code = pp_collect_finished(&pp); + if (code) { + pp.shutdown = 1; + if (code < 0) + kill_children(&pp, -code); + } + } + + pp_cleanup(&pp); + return 0; +} diff --git a/run-command.h b/run-command.h index 12bb26c2a..d5a57f922 100644 --- a/run-command.h +++ b/run-command.h @@ -122,4 +122,84 @@ int start_async(struct async *async); int finish_async(struct async *async); int in_async(void); +/** + * This callback should initialize the child process and preload the + * error channel if desired. The preloading of is useful if you want to + * have a message printed directly before the output of the child process. + * pp_cb is the callback cookie as passed to run_processes_parallel. + * You can store a child process specific callback cookie in pp_task_cb. + * + * Even after returning 0 to indicate that there are no more processes, + * this function will be called again until there are no more running + * child processes. + * + * Return 1 if the next child is ready to run. + * Return 0 if there are currently no more tasks to be processed. + * To send a signal to other child processes for abortion, + * return the negative signal number. + */ +typedef int (*get_next_task_fn)(struct child_process *cp, + struct strbuf *err, + void *pp_cb, + void **pp_task_cb); + +/** + * This callback is called whenever there are problems starting + * a new process. + * + * You must not write to stdout or stderr in this function. Add your + * message to the strbuf err instead, which will be printed without + * messing up the output of the other parallel processes. + * + * pp_cb is the callback cookie as passed into run_processes_parallel, + * pp_task_cb is the callback cookie as passed into get_next_task_fn. + * + * Return 0 to continue the parallel processing. To abort return non zero. + * To send a signal to other child processes for abortion, return + * the negative signal number. + */ +typedef int (*start_failure_fn)(struct child_process *cp, + struct strbuf *err, + void *pp_cb, + void *pp_task_cb); + +/** + * This callback is called on every child process that finished processing. + * + * You must not write to stdout or stderr in this function. Add your + * message to the strbuf err instead, which will be printed without + * messing up the output of the other parallel processes. + * + * pp_cb is the callback cookie as passed into run_processes_parallel, + * pp_task_cb is the callback cookie as passed into get_next_task_fn. + * + * Return 0 to continue the parallel processing. To abort return non zero. + * To send a signal to other child processes for abortion, return + * the negative signal number. + */ +typedef int (*task_finished_fn)(int result, + struct child_process *cp, + struct strbuf *err, + void *pp_cb, + void *pp_task_cb); + +/** + * Runs up to n processes at the same time. Whenever a process can be + * started, the callback get_next_task_fn is called to obtain the data + * required to start another child process. + * + * The children started via this function run in parallel. Their output + * (both stdout and stderr) is routed to stderr in a manner that output + * from different tasks does not interleave. + * + * If start_failure_fn or task_finished_fn are NULL, default handlers + * will be used. The default handlers will print an error message on + * error without issuing an emergency stop. + */ +int run_processes_parallel(int n, + get_next_task_fn, + start_failure_fn, + task_finished_fn, + void *pp_cb); + #endif diff --git a/sigchain.c b/sigchain.c index faa375d5d..2ac43bbd2 100644 --- a/sigchain.c +++ b/sigchain.c @@ -50,3 +50,12 @@ void sigchain_push_common(sigchain_fun f) sigchain_push(SIGQUIT, f); sigchain_push(SIGPIPE, f); } + +void sigchain_pop_common(void) +{ + sigchain_pop(SIGPIPE); + sigchain_pop(SIGQUIT); + sigchain_pop(SIGTERM); + sigchain_pop(SIGHUP); + sigchain_pop(SIGINT); +} diff --git a/sigchain.h b/sigchain.h index 618083bce..138b20f54 100644 --- a/sigchain.h +++ b/sigchain.h @@ -7,5 +7,6 @@ int sigchain_push(int sig, sigchain_fun f); int sigchain_pop(int sig); void sigchain_push_common(sigchain_fun f); +void sigchain_pop_common(void); #endif /* SIGCHAIN_H */ @@ -384,6 +384,17 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) return sb->len - oldlen; } +ssize_t strbuf_read_once(struct strbuf *sb, int fd, size_t hint) +{ + ssize_t cnt; + + strbuf_grow(sb, hint ? hint : 8192); + cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1); + if (cnt > 0) + strbuf_setlen(sb, sb->len + cnt); + return cnt; +} + #define STRBUF_MAXLINK (2*PATH_MAX) int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint) @@ -367,6 +367,14 @@ extern size_t strbuf_fread(struct strbuf *, size_t, FILE *); extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint); /** + * Read the contents of a given file descriptor partially by using only one + * attempt of xread. The third argument can be used to give a hint about the + * file size, to avoid reallocs. Returns the number of new bytes appended to + * the sb. + */ +extern ssize_t strbuf_read_once(struct strbuf *, int fd, size_t hint); + +/** * Read the contents of a file, specified by its path. The third argument * can be used to give a hint about the file size, to avoid reallocs. */ diff --git a/submodule.c b/submodule.c index 14e76247b..b83939c29 100644 --- a/submodule.c +++ b/submodule.c @@ -12,6 +12,7 @@ #include "sha1-array.h" #include "argv-array.h" #include "blob.h" +#include "thread-utils.h" static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND; static struct string_list changed_submodule_paths; @@ -610,37 +611,28 @@ static void calculate_changed_submodule_paths(void) initialized_fetch_ref_tips = 0; } -int fetch_populated_submodules(const struct argv_array *options, - const char *prefix, int command_line_option, - int quiet) +struct submodule_parallel_fetch { + int count; + struct argv_array args; + const char *work_tree; + const char *prefix; + int command_line_option; + int quiet; + int result; +}; +#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0} + +static int get_next_submodule(struct child_process *cp, + struct strbuf *err, void *data, void **task_cb) { - int i, result = 0; - struct child_process cp = CHILD_PROCESS_INIT; - struct argv_array argv = ARGV_ARRAY_INIT; - const char *work_tree = get_git_work_tree(); - if (!work_tree) - goto out; - - if (read_cache() < 0) - die("index file corrupt"); - - argv_array_push(&argv, "fetch"); - for (i = 0; i < options->argc; i++) - argv_array_push(&argv, options->argv[i]); - argv_array_push(&argv, "--recurse-submodules-default"); - /* default value, "--submodule-prefix" and its value are added later */ - - cp.env = local_repo_env; - cp.git_cmd = 1; - cp.no_stdin = 1; - - calculate_changed_submodule_paths(); + int ret = 0; + struct submodule_parallel_fetch *spf = data; - for (i = 0; i < active_nr; i++) { + for (; spf->count < active_nr; spf->count++) { struct strbuf submodule_path = STRBUF_INIT; struct strbuf submodule_git_dir = STRBUF_INIT; struct strbuf submodule_prefix = STRBUF_INIT; - const struct cache_entry *ce = active_cache[i]; + const struct cache_entry *ce = active_cache[spf->count]; const char *git_dir, *default_argv; const struct submodule *submodule; @@ -652,7 +644,7 @@ int fetch_populated_submodules(const struct argv_array *options, submodule = submodule_from_name(null_sha1, ce->name); default_argv = "yes"; - if (command_line_option == RECURSE_SUBMODULES_DEFAULT) { + if (spf->command_line_option == RECURSE_SUBMODULES_DEFAULT) { if (submodule && submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) { @@ -675,40 +667,101 @@ int fetch_populated_submodules(const struct argv_array *options, default_argv = "on-demand"; } } - } else if (command_line_option == RECURSE_SUBMODULES_ON_DEMAND) { + } else if (spf->command_line_option == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } - strbuf_addf(&submodule_path, "%s/%s", work_tree, ce->name); + strbuf_addf(&submodule_path, "%s/%s", spf->work_tree, ce->name); strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf); - strbuf_addf(&submodule_prefix, "%s%s/", prefix, ce->name); + strbuf_addf(&submodule_prefix, "%s%s/", spf->prefix, ce->name); git_dir = read_gitfile(submodule_git_dir.buf); if (!git_dir) git_dir = submodule_git_dir.buf; if (is_directory(git_dir)) { - if (!quiet) - printf("Fetching submodule %s%s\n", prefix, ce->name); - cp.dir = submodule_path.buf; - argv_array_push(&argv, default_argv); - argv_array_push(&argv, "--submodule-prefix"); - argv_array_push(&argv, submodule_prefix.buf); - cp.argv = argv.argv; - if (run_command(&cp)) - result = 1; - argv_array_pop(&argv); - argv_array_pop(&argv); - argv_array_pop(&argv); + child_process_init(cp); + cp->dir = strbuf_detach(&submodule_path, NULL); + cp->env = local_repo_env; + cp->git_cmd = 1; + if (!spf->quiet) + strbuf_addf(err, "Fetching submodule %s%s\n", + spf->prefix, ce->name); + argv_array_init(&cp->args); + argv_array_pushv(&cp->args, spf->args.argv); + argv_array_push(&cp->args, default_argv); + argv_array_push(&cp->args, "--submodule-prefix"); + argv_array_push(&cp->args, submodule_prefix.buf); + ret = 1; } strbuf_release(&submodule_path); strbuf_release(&submodule_git_dir); strbuf_release(&submodule_prefix); + if (ret) { + spf->count++; + return 1; + } } - argv_array_clear(&argv); + return 0; +} + +static int fetch_start_failure(struct child_process *cp, + struct strbuf *err, + void *cb, void *task_cb) +{ + struct submodule_parallel_fetch *spf = cb; + + spf->result = 1; + + return 0; +} + +static int fetch_finish(int retvalue, struct child_process *cp, + struct strbuf *err, void *cb, void *task_cb) +{ + struct submodule_parallel_fetch *spf = cb; + + if (retvalue) + spf->result = 1; + + return 0; +} + +int fetch_populated_submodules(const struct argv_array *options, + const char *prefix, int command_line_option, + int quiet, int max_parallel_jobs) +{ + int i; + struct submodule_parallel_fetch spf = SPF_INIT; + + spf.work_tree = get_git_work_tree(); + spf.command_line_option = command_line_option; + spf.quiet = quiet; + spf.prefix = prefix; + + if (!spf.work_tree) + goto out; + + if (read_cache() < 0) + die("index file corrupt"); + + argv_array_push(&spf.args, "fetch"); + for (i = 0; i < options->argc; i++) + argv_array_push(&spf.args, options->argv[i]); + argv_array_push(&spf.args, "--recurse-submodules-default"); + /* default value, "--submodule-prefix" and its value are added later */ + + calculate_changed_submodule_paths(); + run_processes_parallel(max_parallel_jobs, + get_next_submodule, + fetch_start_failure, + fetch_finish, + &spf); + + argv_array_clear(&spf.args); out: string_list_clear(&changed_submodule_paths, 1); - return result; + return spf.result; } unsigned is_submodule_modified(const char *path, int ignore_untracked) diff --git a/submodule.h b/submodule.h index ddff51210..e06eaa5eb 100644 --- a/submodule.h +++ b/submodule.h @@ -32,7 +32,7 @@ void set_config_fetch_recurse_submodules(int value); void check_for_new_submodule_commits(unsigned char new_sha1[20]); int fetch_populated_submodules(const struct argv_array *options, const char *prefix, int command_line_option, - int quiet); + int quiet, int max_parallel_jobs); unsigned is_submodule_modified(const char *path, int ignore_untracked); int submodule_uses_gitfile(const char *path); int ok_to_remove_submodule(const char *path); diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index e9714467d..f9f3e5fd8 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -98,8 +98,8 @@ then test_skip_or_die $GIT_TEST_HTTPD "no web server found at '$LIB_HTTPD_PATH'" fi -HTTPD_VERSION=`$LIB_HTTPD_PATH -v | \ - sed -n 's/^Server version: Apache\/\([0-9]*\)\..*$/\1/p; q'` +HTTPD_VERSION=$($LIB_HTTPD_PATH -v | \ + sed -n 's/^Server version: Apache\/\([0-9]*\)\..*$/\1/p; q') if test -n "$HTTPD_VERSION" then diff --git a/t/t0001-init.sh b/t/t0001-init.sh index f91bbcfc8..295aa5949 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -87,6 +87,23 @@ test_expect_success 'plain nested in bare through aliased command' ' check_config bare-ancestor-aliased.git/plain-nested/.git false unset ' +test_expect_success 'No extra GIT_* on alias scripts' ' + ( + env | sed -ne "/^GIT_/s/=.*//p" && + echo GIT_PREFIX && # setup.c + echo GIT_TEXTDOMAINDIR # wrapper-for-bin.sh + ) | sort | uniq >expected && + cat <<-\EOF >script && + #!/bin/sh + env | sed -ne "/^GIT_/s/=.*//p" | sort >actual + exit 0 + EOF + chmod 755 script && + git config alias.script \!./script && + ( mkdir sub && cd sub && git script ) && + test_cmp expected actual +' + test_expect_success 'plain with GIT_WORK_TREE' ' mkdir plain-wt && test_must_fail env GIT_WORK_TREE="$(pwd)/plain-wt" git init plain-wt diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh index 9acf62872..12228b4aa 100755 --- a/t/t0061-run-command.sh +++ b/t/t0061-run-command.sh @@ -47,4 +47,57 @@ test_expect_success POSIXPERM,SANITY 'unreadable directory in PATH' ' test_cmp expect actual ' +cat >expect <<-EOF +preloaded output of a child +Hello +World +preloaded output of a child +Hello +World +preloaded output of a child +Hello +World +preloaded output of a child +Hello +World +EOF + +test_expect_success 'run_command runs in parallel with more jobs available than tasks' ' + test-run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual && + test_cmp expect actual +' + +test_expect_success 'run_command runs in parallel with as many jobs as tasks' ' + test-run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual && + test_cmp expect actual +' + +test_expect_success 'run_command runs in parallel with more tasks than jobs available' ' + test-run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual && + test_cmp expect actual +' + +cat >expect <<-EOF +preloaded output of a child +asking for a quick stop +preloaded output of a child +asking for a quick stop +preloaded output of a child +asking for a quick stop +EOF + +test_expect_success 'run_command is asked to abort gracefully' ' + test-run-command run-command-abort 3 false 2>actual && + test_cmp expect actual +' + +cat >expect <<-EOF +no further jobs available +EOF + +test_expect_success 'run_command outputs ' ' + test-run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual && + test_cmp expect actual +' + test_done diff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh index f8457f9d1..b7e9b4fc5 100755 --- a/t/t1100-commit-tree-options.sh +++ b/t/t1100-commit-tree-options.sh @@ -35,11 +35,11 @@ test_expect_success \ GIT_COMMITTER_NAME="Committer Name" \ GIT_COMMITTER_EMAIL="committer@email" \ GIT_COMMITTER_DATE="2005-05-26 23:30" \ - TZ=GMT git commit-tree `cat treeid` >commitid 2>/dev/null' + TZ=GMT git commit-tree $(cat treeid) >commitid 2>/dev/null' test_expect_success \ 'read commit' \ - 'git cat-file commit `cat commitid` >commit' + 'git cat-file commit $(cat commitid) >commit' test_expect_success \ 'compare commit' \ diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh index 1f0dff3a0..ce8b4f4d0 100755 --- a/t/t1401-symbolic-ref.sh +++ b/t/t1401-symbolic-ref.sh @@ -29,7 +29,7 @@ reset_to_sane test_expect_success 'symbolic-ref refuses bare sha1' ' echo content >file && git add file && git commit -m one && - test_must_fail git symbolic-ref HEAD `git rev-parse HEAD` + test_must_fail git symbolic-ref HEAD $(git rev-parse HEAD) ' reset_to_sane diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index b79049f6f..c623824b4 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -62,18 +62,18 @@ test_expect_success setup ' git add . && test_tick && git commit -m rabbit && - H=`git rev-parse --verify HEAD` && - A=`git rev-parse --verify HEAD:A` && - B=`git rev-parse --verify HEAD:A/B` && - C=`git rev-parse --verify HEAD:C` && - D=`git rev-parse --verify HEAD:A/D` && - E=`git rev-parse --verify HEAD:A/B/E` && + H=$(git rev-parse --verify HEAD) && + A=$(git rev-parse --verify HEAD:A) && + B=$(git rev-parse --verify HEAD:A/B) && + C=$(git rev-parse --verify HEAD:C) && + D=$(git rev-parse --verify HEAD:A/D) && + E=$(git rev-parse --verify HEAD:A/B/E) && check_fsck && test_chmod +x C && git add C && test_tick && git commit -m dragon && - L=`git rev-parse --verify HEAD` && + L=$(git rev-parse --verify HEAD) && check_fsck && rm -f C A/B/E && @@ -81,15 +81,15 @@ test_expect_success setup ' echo horse >A/G && git add F A/G && test_tick && git commit -a -m sheep && - F=`git rev-parse --verify HEAD:F` && - G=`git rev-parse --verify HEAD:A/G` && - I=`git rev-parse --verify HEAD:A` && - J=`git rev-parse --verify HEAD` && + F=$(git rev-parse --verify HEAD:F) && + G=$(git rev-parse --verify HEAD:A/G) && + I=$(git rev-parse --verify HEAD:A) && + J=$(git rev-parse --verify HEAD) && check_fsck && rm -f A/G && test_tick && git commit -a -m monkey && - K=`git rev-parse --verify HEAD` && + K=$(git rev-parse --verify HEAD) && check_fsck && check_have A B C D E F G H I J K L && @@ -325,4 +325,17 @@ test_expect_success 'parsing reverse reflogs at BUFSIZ boundaries' ' test_cmp expect actual ' +test_expect_success 'no segfaults for reflog containing non-commit sha1s' ' + git update-ref --create-reflog -m "Creating ref" \ + refs/tests/tree-in-reflog HEAD && + git update-ref -m "Forcing tree" refs/tests/tree-in-reflog HEAD^{tree} && + git update-ref -m "Restoring to commit" refs/tests/tree-in-reflog HEAD && + git reflog refs/tests/tree-in-reflog +' + +test_expect_failure 'reflog with non-commit entries displays all entries' ' + git reflog refs/tests/tree-in-reflog >actual && + test_line_count = 3 actual +' + test_done diff --git a/t/t1511-rev-parse-caret.sh b/t/t1511-rev-parse-caret.sh index 15973f209..7043ba794 100755 --- a/t/t1511-rev-parse-caret.sh +++ b/t/t1511-rev-parse-caret.sh @@ -6,11 +6,11 @@ test_description='tests for ref^{stuff}' test_expect_success 'setup' ' echo blob >a-blob && - git tag -a -m blob blob-tag `git hash-object -w a-blob` && + git tag -a -m blob blob-tag $(git hash-object -w a-blob) && mkdir a-tree && echo moreblobs >a-tree/another-blob && git add . && - TREE_SHA1=`git write-tree` && + TREE_SHA1=$(git write-tree) && git tag -a -m tree tree-tag "$TREE_SHA1" && git commit -m Initial && git tag -a -m commit commit-tag && diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 4a155c8d0..e221167cf 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -275,19 +275,19 @@ test_expect_success 'rev-parse --disambiguate' ' test_expect_success 'ambiguous 40-hex ref' ' TREE=$(git mktree </dev/null) && - REF=`git rev-parse HEAD` && + REF=$(git rev-parse HEAD) && VAL=$(git commit-tree $TREE </dev/null) && git update-ref refs/heads/$REF $VAL && - test `git rev-parse $REF 2>err` = $REF && + test $(git rev-parse $REF 2>err) = $REF && grep "refname.*${REF}.*ambiguous" err ' test_expect_success 'ambiguous short sha1 ref' ' TREE=$(git mktree </dev/null) && - REF=`git rev-parse --short HEAD` && + REF=$(git rev-parse --short HEAD) && VAL=$(git commit-tree $TREE </dev/null) && git update-ref refs/heads/$REF $VAL && - test `git rev-parse $REF 2>err` = $VAL && + test $(git rev-parse $REF 2>err) = $VAL && grep "refname.*${REF}.*ambiguous" err ' diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh index 193d55c3f..8aef49f23 100755 --- a/t/t1700-split-index.sh +++ b/t/t1700-split-index.sh @@ -55,7 +55,7 @@ test_expect_success 'disable split index' ' EOF test_cmp ls-files.expect ls-files.actual && - BASE=`test-dump-split-index .git/index | grep "^own" | sed "s/own/base/"` && + BASE=$(test-dump-split-index .git/index | grep "^own" | sed "s/own/base/") && test-dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<EOF && not a split index diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh index 369417498..0a804dab6 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -123,10 +123,10 @@ test_expect_success 'checkout from a bare repo without "add"' ' test_expect_success 'checkout with grafts' ' test_when_finished rm .git/info/grafts && test_commit abc && - SHA1=`git rev-parse HEAD` && + SHA1=$(git rev-parse HEAD) && test_commit def && test_commit xyz && - echo "`git rev-parse HEAD` $SHA1" >.git/info/grafts && + echo "$(git rev-parse HEAD) $SHA1" >.git/info/grafts && cat >expected <<-\EOF && xyz abc diff --git a/t/t2102-update-index-symlinks.sh b/t/t2102-update-index-symlinks.sh index 4d0d0a351..22f2c730a 100755 --- a/t/t2102-update-index-symlinks.sh +++ b/t/t2102-update-index-symlinks.sh @@ -23,7 +23,7 @@ git update-index symlink' test_expect_success \ 'the index entry must still be a symbolic link' ' -case "`git ls-files --stage --cached symlink`" in +case "$(git ls-files --stage --cached symlink)" in 120000" "*symlink) echo pass;; *) echo fail; git ls-files --stage --cached symlink; (exit 1);; esac' diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh index da257c020..3fc484e8c 100755 --- a/t/t3001-ls-files-others-exclude.sh +++ b/t/t3001-ls-files-others-exclude.sh @@ -305,29 +305,4 @@ test_expect_success 'ls-files with "**" patterns and no slashes' ' test_cmp expect actual ' -test_expect_success 'negative patterns' ' - git init reinclude && - ( - cd reinclude && - cat >.gitignore <<-\EOF && - /fooo - /foo - !foo/bar/bar - EOF - mkdir fooo && - cat >fooo/.gitignore <<-\EOF && - !/* - EOF - mkdir -p foo/bar && - touch abc foo/def foo/bar/ghi foo/bar/bar && - git ls-files -o --exclude-standard >../actual && - cat >../expected <<-\EOF && - .gitignore - abc - foo/bar/bar - EOF - test_cmp ../expected ../actual - ) -' - test_done diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 622418763..f7b0e599f 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -263,7 +263,7 @@ test_expect_success 'setup 8' ' test_ln_s_add e a && test_tick && git commit -m "rename a->e, symlink a->e" && - oln=`printf e | git hash-object --stdin` + oln=$(printf e | git hash-object --stdin) ' test_expect_success 'setup 9' ' diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh index eb73c06a4..325114f8f 100755 --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -28,7 +28,7 @@ test_expect_success \ echo Mi >path2/baz/b && find path? \( -type f -o -type l \) -print | xargs git update-index --add && - tree=`git write-tree` && + tree=$(git write-tree) && echo $tree' test_output () { diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh index 026f9f89d..425d85893 100755 --- a/t/t3101-ls-tree-dirname.sh +++ b/t/t3101-ls-tree-dirname.sh @@ -35,7 +35,7 @@ test_expect_success 'setup' ' echo 222 >path3/2.txt && find *.txt path* \( -type f -o -type l \) -print | xargs git update-index --add && - tree=`git write-tree` && + tree=$(git write-tree) && echo $tree ' diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh index db244d2f8..9b182a0c3 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -27,7 +27,7 @@ SHA1= test_expect_success \ 'see if git show-ref works as expected' \ 'git branch a && - SHA1=`cat .git/refs/heads/a` && + SHA1=$(cat .git/refs/heads/a) && echo "$SHA1 refs/heads/a" >expect && git show-ref a >result && test_cmp expect result' diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index cd70274ea..2d200fdf3 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -83,6 +83,16 @@ test_expect_success 'edit existing notes' ' test_must_fail git notes show HEAD^ ' +test_expect_success 'show notes from treeish' ' + test "b3" = "$(git notes --ref commits^{tree} show)" && + test "b4" = "$(git notes --ref commits@{1} show)" +' + +test_expect_success 'cannot edit notes from non-ref' ' + test_must_fail git notes --ref commits^{tree} edit && + test_must_fail git notes --ref commits@{1} edit +' + test_expect_success 'cannot "git notes add -m" where notes already exists' ' test_must_fail git notes add -m "b2" && test_path_is_missing .git/NOTES_EDITMSG && diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index 3968020e6..1f5122b63 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -67,7 +67,7 @@ test_expect_success 'rebase --skip with --merge' ' ' test_expect_success 'merge and reference trees equal' ' - test -z "`git diff-tree skip-merge skip-reference`" + test -z "$(git diff-tree skip-merge skip-reference)" ' test_expect_success 'moved back to branch correctly' ' diff --git a/t/t3511-cherry-pick-x.sh b/t/t3511-cherry-pick-x.sh index b7dff09d0..9cce5ae88 100755 --- a/t/t3511-cherry-pick-x.sh +++ b/t/t3511-cherry-pick-x.sh @@ -77,7 +77,7 @@ test_expect_success setup ' test_expect_success 'cherry-pick -x inserts blank line after one line subject' ' pristine_detach initial && - sha1=`git rev-parse mesg-one-line^0` && + sha1=$(git rev-parse mesg-one-line^0) && git cherry-pick -x mesg-one-line && cat <<-EOF >expect && $mesg_one_line @@ -114,7 +114,7 @@ test_expect_success 'cherry-pick -s inserts blank line after non-conforming foot test_expect_success 'cherry-pick -x inserts blank line when conforming footer not found' ' pristine_detach initial && - sha1=`git rev-parse mesg-no-footer^0` && + sha1=$(git rev-parse mesg-no-footer^0) && git cherry-pick -x mesg-no-footer && cat <<-EOF >expect && $mesg_no_footer @@ -139,7 +139,7 @@ test_expect_success 'cherry-pick -s inserts blank line when conforming footer no test_expect_success 'cherry-pick -x -s inserts blank line when conforming footer not found' ' pristine_detach initial && - sha1=`git rev-parse mesg-no-footer^0` && + sha1=$(git rev-parse mesg-no-footer^0) && git cherry-pick -x -s mesg-no-footer && cat <<-EOF >expect && $mesg_no_footer @@ -164,7 +164,7 @@ test_expect_success 'cherry-pick -s adds sob when last sob doesnt match committe test_expect_success 'cherry-pick -x -s adds sob when last sob doesnt match committer' ' pristine_detach initial && - sha1=`git rev-parse mesg-with-footer^0` && + sha1=$(git rev-parse mesg-with-footer^0) && git cherry-pick -x -s mesg-with-footer && cat <<-EOF >expect && $mesg_with_footer @@ -187,7 +187,7 @@ test_expect_success 'cherry-pick -s refrains from adding duplicate trailing sob' test_expect_success 'cherry-pick -x -s adds sob even when trailing sob exists for committer' ' pristine_detach initial && - sha1=`git rev-parse mesg-with-footer-sob^0` && + sha1=$(git rev-parse mesg-with-footer-sob^0) && git cherry-pick -x -s mesg-with-footer-sob && cat <<-EOF >expect && $mesg_with_footer_sob @@ -200,7 +200,7 @@ test_expect_success 'cherry-pick -x -s adds sob even when trailing sob exists fo test_expect_success 'cherry-pick -x treats "(cherry picked from..." line as part of footer' ' pristine_detach initial && - sha1=`git rev-parse mesg-with-cherry-footer^0` && + sha1=$(git rev-parse mesg-with-cherry-footer^0) && git cherry-pick -x mesg-with-cherry-footer && cat <<-EOF >expect && $mesg_with_cherry_footer @@ -223,7 +223,7 @@ test_expect_success 'cherry-pick -s treats "(cherry picked from..." line as part test_expect_success 'cherry-pick -x -s treats "(cherry picked from..." line as part of footer' ' pristine_detach initial && - sha1=`git rev-parse mesg-with-cherry-footer^0` && + sha1=$(git rev-parse mesg-with-cherry-footer^0) && git cherry-pick -x -s mesg-with-cherry-footer && cat <<-EOF >expect && $mesg_with_cherry_footer diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 9d90d2c93..2e47a2bfd 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -115,7 +115,7 @@ test_expect_success '"rm" command printed' ' git add test-file && git commit -m "add file for rm test" && git rm test-file > rm-output && - test `grep "^rm " rm-output | wc -l` = 1 && + test $(grep "^rm " rm-output | wc -l) = 1 && rm -f test-file rm-output && git commit -m "remove file from rm test" ' @@ -125,7 +125,7 @@ test_expect_success '"rm" command suppressed with --quiet' ' git add test-file && git commit -m "add file for rm --quiet test" && git rm --quiet test-file > rm-output && - test `wc -l < rm-output` = 0 && + test $(wc -l < rm-output) = 0 && rm -f test-file rm-output && git commit -m "remove file from rm --quiet test" ' diff --git a/t/t3700-add.sh b/t/t3700-add.sh index f7ff1f555..f14a66535 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -25,7 +25,7 @@ test_expect_success \ echo foo >xfoo1 && chmod 755 xfoo1 && git add xfoo1 && - case "`git ls-files --stage xfoo1`" in + case "$(git ls-files --stage xfoo1)" in 100644" "*xfoo1) echo pass;; *) echo fail; git ls-files --stage xfoo1; (exit 1);; esac' @@ -33,7 +33,7 @@ test_expect_success \ test_expect_success 'git add: filemode=0 should not get confused by symlink' ' rm -f xfoo1 && test_ln_s_add foo xfoo1 && - case "`git ls-files --stage xfoo1`" in + case "$(git ls-files --stage xfoo1)" in 120000" "*xfoo1) echo pass;; *) echo fail; git ls-files --stage xfoo1; (exit 1);; esac @@ -45,7 +45,7 @@ test_expect_success \ echo foo >xfoo2 && chmod 755 xfoo2 && git update-index --add xfoo2 && - case "`git ls-files --stage xfoo2`" in + case "$(git ls-files --stage xfoo2)" in 100644" "*xfoo2) echo pass;; *) echo fail; git ls-files --stage xfoo2; (exit 1);; esac' @@ -53,7 +53,7 @@ test_expect_success \ test_expect_success 'git add: filemode=0 should not get confused by symlink' ' rm -f xfoo2 && test_ln_s_add foo xfoo2 && - case "`git ls-files --stage xfoo2`" in + case "$(git ls-files --stage xfoo2)" in 120000" "*xfoo2) echo pass;; *) echo fail; git ls-files --stage xfoo2; (exit 1);; esac @@ -63,7 +63,7 @@ test_expect_success \ 'git update-index --add: Test that executable bit is not used...' \ 'git config core.filemode 0 && test_ln_s_add xfoo2 xfoo3 && # runs git update-index --add - case "`git ls-files --stage xfoo3`" in + case "$(git ls-files --stage xfoo3)" in 120000" "*xfoo3) echo pass;; *) echo fail; git ls-files --stage xfoo3; (exit 1);; esac' @@ -173,14 +173,14 @@ test_expect_success 'git add with filemode=0, symlinks=0 prefers stage 2 over st test_expect_success 'git add --refresh' ' >foo && git add foo && git commit -a -m "commit all" && - test -z "`git diff-index HEAD -- foo`" && + test -z "$(git diff-index HEAD -- foo)" && git read-tree HEAD && - case "`git diff-index HEAD -- foo`" in + case "$(git diff-index HEAD -- foo)" in :100644" "*"M foo") echo pass;; *) echo fail; (exit 1);; esac && git add --refresh -- foo && - test -z "`git diff-index HEAD -- foo`" + test -z "$(git diff-index HEAD -- foo)" ' test_expect_success 'git add --refresh with pathspec' ' diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh index e97cfb2ab..85b3df5e3 100755 --- a/t/t5100-mailinfo.sh +++ b/t/t5100-mailinfo.sh @@ -9,9 +9,9 @@ test_description='git mailinfo and git mailsplit test' test_expect_success 'split sample box' \ 'git mailsplit -o. "$TEST_DIRECTORY"/t5100/sample.mbox >last && - last=`cat last` && + last=$(cat last) && echo total is $last && - test `cat last` = 17' + test $(cat last) = 17' check_mailinfo () { mail=$1 opt=$2 @@ -23,7 +23,7 @@ check_mailinfo () { } -for mail in `echo 00*` +for mail in 00* do test_expect_success "mailinfo $mail" ' check_mailinfo $mail "" && @@ -47,11 +47,11 @@ test_expect_success 'split box with rfc2047 samples' \ 'mkdir rfc2047 && git mailsplit -orfc2047 "$TEST_DIRECTORY"/t5100/rfc2047-samples.mbox \ >rfc2047/last && - last=`cat rfc2047/last` && + last=$(cat rfc2047/last) && echo total is $last && - test `cat rfc2047/last` = 11' + test $(cat rfc2047/last) = 11' -for mail in `echo rfc2047/00*` +for mail in rfc2047/00* do test_expect_success "mailinfo $mail" ' git mailinfo -u $mail-msg $mail-patch <$mail >$mail-info && diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 20c196151..fc2be63e0 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -8,7 +8,7 @@ test_description='git pack-object ' . ./test-lib.sh -TRASH=`pwd` +TRASH=$(pwd) test_expect_success \ 'setup' \ @@ -20,8 +20,8 @@ test_expect_success \ test-genrandom "seed b" 2097152 > b_big && git update-index --add a a_big b b_big c && cat c >d && echo foo >>d && git update-index --add d && - tree=`git write-tree` && - commit=`git commit-tree $tree </dev/null` && { + tree=$(git write-tree) && + commit=$(git commit-tree $tree </dev/null) && { echo $tree && echo $commit && git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/" @@ -29,7 +29,7 @@ test_expect_success \ git diff-tree --root -p $commit && while read object do - t=`git cat-file -t $object` && + t=$(git cat-file -t $object) && git cat-file $t $object || return 1 done <obj-list } >expect' @@ -147,7 +147,7 @@ test_expect_success \ git diff-tree --root -p $commit && while read object do - t=`git cat-file -t $object` && + t=$(git cat-file -t $object) && git cat-file $t $object || return 1 done <obj-list } >current && @@ -162,7 +162,7 @@ test_expect_success \ git diff-tree --root -p $commit && while read object do - t=`git cat-file -t $object` && + t=$(git cat-file -t $object) && git cat-file $t $object || return 1 done <obj-list } >current && @@ -177,7 +177,7 @@ test_expect_success \ git diff-tree --root -p $commit && while read object do - t=`git cat-file -t $object` && + t=$(git cat-file -t $object) && git cat-file $t $object || return 1 done <obj-list } >current && @@ -252,8 +252,8 @@ test_expect_success \ test_expect_success \ 'verify-pack catches a corrupted sum of the index file itself' \ - 'l=`wc -c <test-3.idx` && - l=`expr $l - 20` && + 'l=$(wc -c <test-3.idx) && + l=$(expr $l - 20) && cat test-1-${packname_1}.pack >test-3.pack && printf "%20s" "" | dd of=test-3.idx count=20 bs=1 conv=notrunc seek=$l && if git verify-pack test-3.pack diff --git a/t/t5301-sliding-window.sh b/t/t5301-sliding-window.sh index 2fc5af600..cae8c2e88 100755 --- a/t/t5301-sliding-window.sh +++ b/t/t5301-sliding-window.sh @@ -16,12 +16,12 @@ test_expect_success \ git update-index --add $i || return 1 done && echo d >d && cat c >>d && git update-index --add d && - tree=`git write-tree` && - commit1=`git commit-tree $tree </dev/null` && + tree=$(git write-tree) && + commit1=$(git commit-tree $tree </dev/null) && git update-ref HEAD $commit1 && git repack -a -d && - test "`git count-objects`" = "0 objects, 0 kilobytes" && - pack1=`ls .git/objects/pack/*.pack` && + test "$(git count-objects)" = "0 objects, 0 kilobytes" && + pack1=$(ls .git/objects/pack/*.pack) && test -f "$pack1"' test_expect_success \ @@ -43,11 +43,11 @@ test_expect_success \ 'repack -a -d, packedGit{WindowSize,Limit} == 1 page' \ 'git config core.packedGitWindowSize 512 && git config core.packedGitLimit 512 && - commit2=`git commit-tree $tree -p $commit1 </dev/null` && + commit2=$(git commit-tree $tree -p $commit1 </dev/null) && git update-ref HEAD $commit2 && git repack -a -d && - test "`git count-objects`" = "0 objects, 0 kilobytes" && - pack2=`ls .git/objects/pack/*.pack` && + test "$(git count-objects)" = "0 objects, 0 kilobytes" && + pack2=$(ls .git/objects/pack/*.pack) && test -f "$pack2" && test "$pack1" \!= "$pack2"' diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index 3dc5ec4dd..c2fc584da 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -14,21 +14,21 @@ test_expect_success \ i=1 && while test $i -le 100 do - iii=`printf '%03i' $i` + iii=$(printf '%03i' $i) test-genrandom "bar" 200 > wide_delta_$iii && test-genrandom "baz $iii" 50 >> wide_delta_$iii && test-genrandom "foo"$i 100 > deep_delta_$iii && - test-genrandom "foo"`expr $i + 1` 100 >> deep_delta_$iii && - test-genrandom "foo"`expr $i + 2` 100 >> deep_delta_$iii && + test-genrandom "foo"$(expr $i + 1) 100 >> deep_delta_$iii && + test-genrandom "foo"$(expr $i + 2) 100 >> deep_delta_$iii && echo $iii >file_$iii && test-genrandom "$iii" 8192 >>file_$iii && git update-index --add file_$iii deep_delta_$iii wide_delta_$iii && - i=`expr $i + 1` || return 1 + i=$(expr $i + 1) || return 1 done && { echo 101 && test-genrandom 100 8192; } >file_101 && git update-index --add file_101 && - tree=`git write-tree` && - commit=`git commit-tree $tree </dev/null` && { + tree=$(git write-tree) && + commit=$(git commit-tree $tree </dev/null) && { echo $tree && git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/" } >obj-list && @@ -152,10 +152,10 @@ test_expect_success \ '[index v1] 2) create a stealth corruption in a delta base reference' \ '# This test assumes file_101 is a delta smaller than 16 bytes. # It should be against file_100 but we substitute its base for file_099 - sha1_101=`git hash-object file_101` && - sha1_099=`git hash-object file_099` && - offs_101=`index_obj_offset 1.idx $sha1_101` && - nr_099=`index_obj_nr 1.idx $sha1_099` && + sha1_101=$(git hash-object file_101) && + sha1_099=$(git hash-object file_099) && + offs_101=$(index_obj_offset 1.idx $sha1_101) && + nr_099=$(index_obj_nr 1.idx $sha1_099) && chmod +w ".git/objects/pack/pack-${pack1}.pack" && dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \ if=".git/objects/pack/pack-${pack1}.idx" \ @@ -193,10 +193,10 @@ test_expect_success \ '[index v2] 2) create a stealth corruption in a delta base reference' \ '# This test assumes file_101 is a delta smaller than 16 bytes. # It should be against file_100 but we substitute its base for file_099 - sha1_101=`git hash-object file_101` && - sha1_099=`git hash-object file_099` && - offs_101=`index_obj_offset 1.idx $sha1_101` && - nr_099=`index_obj_nr 1.idx $sha1_099` && + sha1_101=$(git hash-object file_101) && + sha1_099=$(git hash-object file_099) && + offs_101=$(index_obj_offset 1.idx $sha1_101) && + nr_099=$(index_obj_nr 1.idx $sha1_099) && chmod +w ".git/objects/pack/pack-${pack1}.pack" && dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \ if=".git/objects/pack/pack-${pack1}.idx" \ @@ -222,11 +222,11 @@ test_expect_success \ 'rm -f .git/objects/pack/* && git index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" && git verify-pack ".git/objects/pack/pack-${pack1}.pack" && - obj=`git hash-object file_001` && - nr=`index_obj_nr ".git/objects/pack/pack-${pack1}.idx" $obj` && + obj=$(git hash-object file_001) && + nr=$(index_obj_nr ".git/objects/pack/pack-${pack1}.idx" $obj) && chmod +w ".git/objects/pack/pack-${pack1}.idx" && printf xxxx | dd of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \ - bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + $nr * 4)) && + bs=1 count=4 seek=$((8 + 256 * 4 + $(wc -l <obj-list) * 20 + $nr * 4)) && ( while read obj do git cat-file -p $obj >/dev/null || exit 1 done <obj-list ) && diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh index 663b02bbb..5940ce208 100755 --- a/t/t5303-pack-corruption-resilience.sh +++ b/t/t5303-pack-corruption-resilience.sh @@ -32,23 +32,23 @@ create_test_files() { create_new_pack() { rm -rf .git && git init && - blob_1=`git hash-object -t blob -w file_1` && - blob_2=`git hash-object -t blob -w file_2` && - blob_3=`git hash-object -t blob -w file_3` && - pack=`printf "$blob_1\n$blob_2\n$blob_3\n" | - git pack-objects $@ .git/objects/pack/pack` && + blob_1=$(git hash-object -t blob -w file_1) && + blob_2=$(git hash-object -t blob -w file_2) && + blob_3=$(git hash-object -t blob -w file_3) && + pack=$(printf "$blob_1\n$blob_2\n$blob_3\n" | + git pack-objects $@ .git/objects/pack/pack) && pack=".git/objects/pack/pack-${pack}" && git verify-pack -v ${pack}.pack } do_repack() { - pack=`printf "$blob_1\n$blob_2\n$blob_3\n" | - git pack-objects $@ .git/objects/pack/pack` && + pack=$(printf "$blob_1\n$blob_2\n$blob_3\n" | + git pack-objects $@ .git/objects/pack/pack) && pack=".git/objects/pack/pack-${pack}" } do_corrupt_object() { - ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` && + ofs=$(git show-index < ${pack}.idx | grep $1 | cut -f1 -d" ") && ofs=$(($ofs + $2)) && chmod +w ${pack}.pack && dd of=${pack}.pack bs=1 conv=notrunc seek=$ofs && diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh index def203c72..133b5842b 100755 --- a/t/t5304-prune.sh +++ b/t/t5304-prune.sh @@ -266,7 +266,7 @@ EOF ' test_expect_success 'prune .git/shallow' ' - SHA1=`echo hi|git commit-tree HEAD^{tree}` && + SHA1=$(echo hi|git commit-tree HEAD^{tree}) && echo $SHA1 >.git/shallow && git prune --dry-run >out && grep $SHA1 .git/shallow && diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh index 21517c70c..f314ad507 100755 --- a/t/t5305-include-tag.sh +++ b/t/t5305-include-tag.sh @@ -3,20 +3,20 @@ test_description='git pack-object --include-tag' . ./test-lib.sh -TRASH=`pwd` +TRASH=$(pwd) test_expect_success setup ' echo c >d && git update-index --add d && - tree=`git write-tree` && - commit=`git commit-tree $tree </dev/null` && + tree=$(git write-tree) && + commit=$(git commit-tree $tree </dev/null) && echo "object $commit" >sig && echo "type commit" >>sig && echo "tag mytag" >>sig && echo "tagger $(git var GIT_COMMITTER_IDENT)" >>sig && echo >>sig && echo "our test tag" >>sig && - tag=`git mktag <sig` && + tag=$(git mktag <sig) && rm d sig && git update-ref refs/tags/mytag $tag && { echo $tree && diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 3a9b77576..e5f83bf5e 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -14,7 +14,7 @@ test_description='Testing multi_ack pack fetching' add () { name=$1 && text="$@" && - branch=`echo $name | sed -e 's/^\(.\).*$/\1/'` && + branch=$(echo $name | sed -e 's/^\(.\).*$/\1/') && parents="" && shift && @@ -50,18 +50,18 @@ pull_to_client () { case "$heads" in *B*) echo $BTIP > .git/refs/heads/B;; esac && - git symbolic-ref HEAD refs/heads/`echo $heads \ - | sed -e "s/^\(.\).*$/\1/"` && + git symbolic-ref HEAD refs/heads/$(echo $heads \ + | sed -e "s/^\(.\).*$/\1/") && git fsck --full && mv .git/objects/pack/pack-* . && - p=`ls -1 pack-*.pack` && + p=$(ls -1 pack-*.pack) && git unpack-objects <$p && git fsck --full && - idx=`echo pack-*.idx` && - pack_count=`git show-index <$idx | wc -l` && + idx=$(echo pack-*.idx) && + pack_count=$(git show-index <$idx | wc -l) && test $pack_count = $count && rm -f pack-* ) @@ -132,13 +132,13 @@ test_expect_success 'single given branch clone' ' test_expect_success 'clone shallow depth 1' ' git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0 && - test "`git --git-dir=shallow0/.git rev-list --count HEAD`" = 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 && + test "$(git --git-dir=shallow0fsck/.git rev-list --count HEAD)" = 1 && git config --global --unset fetch.fsckobjects ' @@ -147,7 +147,7 @@ test_expect_success 'clone shallow' ' ' test_expect_success 'clone shallow depth count' ' - test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 2 + test "$(git --git-dir=shallow/.git rev-list --count HEAD)" = 2 ' test_expect_success 'clone shallow object count' ' @@ -273,7 +273,7 @@ test_expect_success 'additional simple shallow deepenings' ' ' test_expect_success 'clone shallow depth count' ' - test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 11 + test "$(git --git-dir=shallow/.git rev-list --count HEAD)" = 11 ' test_expect_success 'clone shallow object count' ' diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index dfaf9d9f6..1a8e3b81c 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -85,7 +85,7 @@ test_expect_success C_LOCALE_OUTPUT 'check remote-tracking' ' test_expect_success 'remote forces tracking branches' ' ( cd test && - case `git config remote.second.fetch` in + case $(git config remote.second.fetch) in +*) true ;; *) false ;; esac diff --git a/t/t5506-remote-groups.sh b/t/t5506-remote-groups.sh index 530b01678..83d5558c0 100755 --- a/t/t5506-remote-groups.sh +++ b/t/t5506-remote-groups.sh @@ -20,7 +20,7 @@ update_repos() { } repo_fetched() { - if test "`git log -1 --pretty=format:%s $1 --`" = "`cat mark`"; then + if test "$(git log -1 --pretty=format:%s $1 --)" = "$(cat mark)"; then echo >&2 "repo was fetched: $1" return 0 fi diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 0ba9db088..9203a6507 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -7,7 +7,7 @@ test_description='Per branch config variables affects "git fetch". . ./test-lib.sh -D=`pwd` +D=$(pwd) test_bundle_object_count () { git verify-pack -v "$1" >verify.out && @@ -64,8 +64,8 @@ test_expect_success "fetch test" ' cd two && git fetch && test -f .git/refs/heads/one && - mine=`git rev-parse refs/heads/one` && - his=`cd ../one && git rev-parse refs/heads/master` && + mine=$(git rev-parse refs/heads/one) && + his=$(cd ../one && git rev-parse refs/heads/master) && test "z$mine" = "z$his" ' @@ -75,8 +75,8 @@ test_expect_success "fetch test for-merge" ' git fetch && test -f .git/refs/heads/two && test -f .git/refs/heads/one && - master_in_two=`cd ../two && git rev-parse master` && - one_in_two=`cd ../two && git rev-parse one` && + master_in_two=$(cd ../two && git rev-parse master) && + one_in_two=$(cd ../two && git rev-parse one) && { echo "$one_in_two " echo "$master_in_two not-for-merge" @@ -708,4 +708,17 @@ test_expect_success 'fetching a one-level ref works' ' ) ' +test_expect_success 'fetching with auto-gc does not lock up' ' + write_script askyesno <<-\EOF && + echo "$*" && + false + EOF + git clone "file://$D" auto-gc && + test_commit test2 && + cd auto-gc && + git config gc.autoPackLimit 1 && + GIT_ASK_YESNO="$D/askyesno" git fetch >fetch.out 2>&1 && + ! grep "Should I try again" fetch.out +' + test_done diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index dbb927dec..36b0dbc01 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -128,8 +128,8 @@ do case "$cmd" in '' | '#'*) continue ;; esac - test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'` - pfx=`printf "%04d" $test_count` + test=$(echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g') + pfx=$(printf "%04d" $test_count) expect_f="$TEST_DIRECTORY/t5515/fetch.$test" actual_f="$pfx-fetch.$test" expect_r="$TEST_DIRECTORY/t5515/refs.$test" diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 0a87e195e..26b2cafc4 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -16,7 +16,7 @@ This test checks the following functionality: . ./test-lib.sh -D=`pwd` +D=$(pwd) mk_empty () { repo_name="$1" @@ -422,7 +422,7 @@ test_expect_success 'push tag with non-existent, incomplete dest' ' test_expect_success 'push sha1 with non-existent, incomplete dest' ' mk_test testrepo && - test_must_fail git push testrepo `git rev-parse master`:foo + test_must_fail git push testrepo $(git rev-parse master):foo ' diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh index 12a5dfb17..02f160aae 100755 --- a/t/t5517-push-mirror.sh +++ b/t/t5517-push-mirror.sh @@ -4,7 +4,7 @@ test_description='pushing to a mirror repository' . ./test-lib.sh -D=`pwd` +D=$(pwd) invert () { if "$@"; then diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index a0013ee32..c952d5ef5 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -326,6 +326,16 @@ test_expect_success 'pull.rebase=preserve rebases and merges keep-merge' ' test "$(git rev-parse HEAD^2)" = "$(git rev-parse keep-merge)" ' +test_expect_success 'pull.rebase=interactive' ' + write_script "$TRASH_DIRECTORY/fake-editor" <<-\EOF && + echo I was here >fake.out && + false + EOF + test_set_editor "$TRASH_DIRECTORY/fake-editor" && + test_must_fail git pull --rebase=interactive . copy && + test "I was here" = "$(cat fake.out)" +' + test_expect_success 'pull.rebase=invalid fails' ' git reset --hard before-preserve-rebase && test_config pull.rebase invalid && diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh index 8e9b204e0..bcff460d0 100755 --- a/t/t5522-pull-symlink.sh +++ b/t/t5522-pull-symlink.sh @@ -54,7 +54,7 @@ test_expect_success SYMLINKS 'pulling from real subdir' ' # git rev-parse --show-cdup printed a path relative to # clone-repo/subdir/, not subdir-link/. Git rev-parse --show-cdup # used the correct .git, but when the git pull shell script did -# "cd `git rev-parse --show-cdup`", it ended up in the wrong +# "cd $(git rev-parse --show-cdup)", it ended up in the wrong # directory. A POSIX shell's "cd" works a little differently # than chdir() in C; "cd -P" is much closer to chdir(). # diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh index a4532b00d..124114622 100755 --- a/t/t5526-fetch-submodules.sh +++ b/t/t5526-fetch-submodules.sh @@ -16,7 +16,8 @@ add_upstream_commit() { git add subfile && git commit -m new subfile && head2=$(git rev-parse --short HEAD) && - echo "From $pwd/submodule" > ../expect.err && + echo "Fetching submodule submodule" > ../expect.err && + echo "From $pwd/submodule" >> ../expect.err && echo " $head1..$head2 master -> origin/master" >> ../expect.err ) && ( @@ -27,6 +28,7 @@ add_upstream_commit() { git add deepsubfile && git commit -m new deepsubfile && head2=$(git rev-parse --short HEAD) && + echo "Fetching submodule submodule/subdir/deepsubmodule" >> ../expect.err echo "From $pwd/deepsubmodule" >> ../expect.err && echo " $head1..$head2 master -> origin/master" >> ../expect.err ) @@ -56,9 +58,7 @@ test_expect_success setup ' ( cd downstream && git submodule update --init --recursive - ) && - echo "Fetching submodule submodule" > expect.out && - echo "Fetching submodule submodule/subdir/deepsubmodule" >> expect.out + ) ' test_expect_success "fetch --recurse-submodules recurses into submodules" ' @@ -67,10 +67,21 @@ test_expect_success "fetch --recurse-submodules recurses into submodules" ' cd downstream && git fetch --recurse-submodules >../actual.out 2>../actual.err ) && - test_i18ncmp expect.out actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err actual.err ' +test_expect_success "fetch --recurse-submodules -j2 has the same output behaviour" ' + add_upstream_commit && + ( + cd downstream && + GIT_TRACE=$(pwd)/../trace.out git fetch --recurse-submodules -j2 2>../actual.err + ) && + test_must_be_empty actual.out && + test_i18ncmp expect.err actual.err && + grep "2 tasks" trace.out +' + test_expect_success "fetch alone only fetches superproject" ' add_upstream_commit && ( @@ -96,7 +107,7 @@ test_expect_success "using fetchRecurseSubmodules=true in .gitmodules recurses i git config -f .gitmodules submodule.submodule.fetchRecurseSubmodules true && git fetch >../actual.out 2>../actual.err ) && - test_i18ncmp expect.out actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err actual.err ' @@ -127,7 +138,7 @@ test_expect_success "--recurse-submodules overrides fetchRecurseSubmodules setti git config --unset -f .gitmodules submodule.submodule.fetchRecurseSubmodules && git config --unset submodule.submodule.fetchRecurseSubmodules ) && - test_i18ncmp expect.out actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err actual.err ' @@ -140,13 +151,22 @@ test_expect_success "--quiet propagates to submodules" ' ! test -s actual.err ' +test_expect_success "--quiet propagates to parallel submodules" ' + ( + cd downstream && + git fetch --recurse-submodules -j 2 --quiet >../actual.out 2>../actual.err + ) && + ! test -s actual.out && + ! test -s actual.err +' + test_expect_success "--dry-run propagates to submodules" ' add_upstream_commit && ( cd downstream && git fetch --recurse-submodules --dry-run >../actual.out 2>../actual.err ) && - test_i18ncmp expect.out actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err actual.err ' @@ -155,7 +175,7 @@ test_expect_success "Without --dry-run propagates to submodules" ' cd downstream && git fetch --recurse-submodules >../actual.out 2>../actual.err ) && - test_i18ncmp expect.out actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err actual.err ' @@ -166,7 +186,7 @@ test_expect_success "recurseSubmodules=true propagates into submodules" ' git config fetch.recurseSubmodules true git fetch >../actual.out 2>../actual.err ) && - test_i18ncmp expect.out actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err actual.err ' @@ -180,7 +200,7 @@ test_expect_success "--recurse-submodules overrides config in submodule" ' ) && git fetch --recurse-submodules >../actual.out 2>../actual.err ) && - test_i18ncmp expect.out actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err actual.err ' @@ -214,16 +234,15 @@ test_expect_success "Recursion stops when no new submodule commits are fetched" git add submodule && git commit -m "new submodule" && head2=$(git rev-parse --short HEAD) && - echo "Fetching submodule submodule" > expect.out.sub && echo "From $pwd/." > expect.err.sub && echo " $head1..$head2 master -> origin/master" >>expect.err.sub && - head -2 expect.err >> expect.err.sub && + head -3 expect.err >> expect.err.sub && ( cd downstream && git fetch >../actual.out 2>../actual.err ) && test_i18ncmp expect.err.sub actual.err && - test_i18ncmp expect.out.sub actual.out + test_must_be_empty actual.out ' test_expect_success "Recursion doesn't happen when new superproject commits don't change any submodules" ' @@ -269,7 +288,7 @@ test_expect_success "Recursion picks up config in submodule" ' ) ) && test_i18ncmp expect.err.sub actual.err && - test_i18ncmp expect.out actual.out + test_must_be_empty actual.out ' test_expect_success "Recursion picks up all submodules when necessary" ' @@ -285,7 +304,8 @@ test_expect_success "Recursion picks up all submodules when necessary" ' git add subdir/deepsubmodule && git commit -m "new deepsubmodule" head2=$(git rev-parse --short HEAD) && - echo "From $pwd/submodule" > ../expect.err.sub && + echo "Fetching submodule submodule" > ../expect.err.sub && + echo "From $pwd/submodule" >> ../expect.err.sub && echo " $head1..$head2 master -> origin/master" >> ../expect.err.sub ) && head1=$(git rev-parse --short HEAD) && @@ -295,13 +315,13 @@ test_expect_success "Recursion picks up all submodules when necessary" ' echo "From $pwd/." > expect.err.2 && echo " $head1..$head2 master -> origin/master" >> expect.err.2 && cat expect.err.sub >> expect.err.2 && - tail -2 expect.err >> expect.err.2 && + tail -3 expect.err >> expect.err.2 && ( cd downstream && git fetch >../actual.out 2>../actual.err ) && test_i18ncmp expect.err.2 actual.err && - test_i18ncmp expect.out actual.out + test_must_be_empty actual.out ' test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no new commits are fetched in the superproject (and ignores config)" ' @@ -317,7 +337,8 @@ test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no ne git add subdir/deepsubmodule && git commit -m "new deepsubmodule" && head2=$(git rev-parse --short HEAD) && - echo "From $pwd/submodule" > ../expect.err.sub && + echo Fetching submodule submodule > ../expect.err.sub && + echo "From $pwd/submodule" >> ../expect.err.sub && echo " $head1..$head2 master -> origin/master" >> ../expect.err.sub ) && ( @@ -335,7 +356,7 @@ test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necess git add submodule && git commit -m "new submodule" && head2=$(git rev-parse --short HEAD) && - tail -2 expect.err > expect.err.deepsub && + tail -3 expect.err > expect.err.deepsub && echo "From $pwd/." > expect.err && echo " $head1..$head2 master -> origin/master" >>expect.err && cat expect.err.sub >> expect.err && @@ -354,7 +375,7 @@ test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necess git config --unset -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive ) ) && - test_i18ncmp expect.out actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err actual.err ' @@ -388,7 +409,7 @@ test_expect_success "'fetch.recurseSubmodules=on-demand' overrides global config head2=$(git rev-parse --short HEAD) && echo "From $pwd/." > expect.err.2 && echo " $head1..$head2 master -> origin/master" >>expect.err.2 && - head -2 expect.err >> expect.err.2 && + head -3 expect.err >> expect.err.2 && ( cd downstream && git config fetch.recurseSubmodules on-demand && @@ -399,7 +420,7 @@ test_expect_success "'fetch.recurseSubmodules=on-demand' overrides global config cd downstream && git config --unset fetch.recurseSubmodules ) && - test_i18ncmp expect.out.sub actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err.2 actual.err ' @@ -416,7 +437,7 @@ test_expect_success "'submodule.<sub>.fetchRecurseSubmodules=on-demand' override head2=$(git rev-parse --short HEAD) && echo "From $pwd/." > expect.err.2 && echo " $head1..$head2 master -> origin/master" >>expect.err.2 && - head -2 expect.err >> expect.err.2 && + head -3 expect.err >> expect.err.2 && ( cd downstream && git config submodule.submodule.fetchRecurseSubmodules on-demand && @@ -427,7 +448,7 @@ test_expect_success "'submodule.<sub>.fetchRecurseSubmodules=on-demand' override cd downstream && git config --unset submodule.submodule.fetchRecurseSubmodules ) && - test_i18ncmp expect.out.sub actual.out && + test_must_be_empty actual.out && test_i18ncmp expect.err.2 actual.err ' diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh index 3932e797f..4f6e32b04 100755 --- a/t/t5530-upload-pack-error.sh +++ b/t/t5530-upload-pack-error.sh @@ -4,7 +4,7 @@ test_description='errors in upload-pack' . ./test-lib.sh -D=`pwd` +D=$(pwd) corrupt_repo () { object_sha1=$(git rev-parse "$1") && diff --git a/t/t5532-fetch-proxy.sh b/t/t5532-fetch-proxy.sh index 5531bd1af..d75ef0ea2 100755 --- a/t/t5532-fetch-proxy.sh +++ b/t/t5532-fetch-proxy.sh @@ -15,7 +15,7 @@ test_expect_success 'setup remote repo' ' cat >proxy <<'EOF' #!/bin/sh echo >&2 "proxying for $*" -cmd=`"$PERL_PATH" -e ' +cmd=$("$PERL_PATH" -e ' read(STDIN, $buf, 4); my $n = hex($buf) - 4; read(STDIN, $buf, $n); @@ -23,7 +23,7 @@ cmd=`"$PERL_PATH" -e ' # drop absolute-path on repo name $cmd =~ s{ /}{ }; print $cmd; -'` +') echo >&2 "Running '$cmd'" exec $cmd EOF diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh index a98057468..df8d2f095 100755 --- a/t/t5537-fetch-shallow.sh +++ b/t/t5537-fetch-shallow.sh @@ -98,7 +98,7 @@ EOF test_expect_success 'fetch something upstream has but hidden by clients shallow boundaries' ' # the blob "1" is available in .git but hidden by the # shallow2/.git/shallow and it should be resent - ! git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` >/dev/null && + ! git --git-dir=shallow2/.git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null && echo 1 >1.t && git add 1.t && git commit -m add-1-back && @@ -114,7 +114,7 @@ add-1-back EOF test_cmp expect actual ) && - git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` >/dev/null + git --git-dir=shallow2/.git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null ' diff --git a/t/t5538-push-shallow.sh b/t/t5538-push-shallow.sh index ceee95b8a..ecbf84d21 100755 --- a/t/t5538-push-shallow.sh +++ b/t/t5538-push-shallow.sh @@ -104,7 +104,7 @@ EOF ' test_expect_success 'push from full to shallow' ' - ! git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` && + ! git --git-dir=shallow2/.git cat-file blob $(echo 1|git hash-object --stdin) && commit 1 && git push shallow2/.git +master:refs/remotes/top/master && ( @@ -117,7 +117,7 @@ test_expect_success 'push from full to shallow' ' 3 EOF test_cmp expect actual && - git cat-file blob `echo 1|git hash-object --stdin` >/dev/null + git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null ) ' test_done diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 87a7aa04a..64146352a 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -132,7 +132,7 @@ test_expect_success 'fetch packed objects' ' test_expect_success 'fetch notices corrupt pack' ' cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git && (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git && - p=`ls objects/pack/pack-*.pack` && + p=$(ls objects/pack/pack-*.pack) && chmod u+w $p && printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc ) && @@ -140,14 +140,14 @@ test_expect_success 'fetch notices corrupt pack' ' (cd repo_bad1.git && git --bare init && test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad1.git && - test 0 = `ls objects/pack/pack-*.pack | wc -l` + test 0 = $(ls objects/pack/pack-*.pack | wc -l) ) ' test_expect_success 'fetch notices corrupt idx' ' cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git && (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git && - p=`ls objects/pack/pack-*.idx` && + p=$(ls objects/pack/pack-*.idx) && chmod u+w $p && printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc ) && @@ -155,7 +155,7 @@ test_expect_success 'fetch notices corrupt idx' ' (cd repo_bad2.git && git --bare init && test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad2.git && - test 0 = `ls objects/pack | wc -l` + test 0 = $(ls objects/pack | wc -l) ) ' diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh index b7e283252..d76269a8f 100755 --- a/t/t5570-git-daemon.sh +++ b/t/t5570-git-daemon.sh @@ -57,7 +57,7 @@ test_expect_success 'prepare pack objects' ' test_expect_success 'fetch notices corrupt pack' ' cp -R "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_pack.git "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad1.git && (cd "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad1.git && - p=`ls objects/pack/pack-*.pack` && + p=$(ls objects/pack/pack-*.pack) && chmod u+w $p && printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc ) && @@ -65,14 +65,14 @@ test_expect_success 'fetch notices corrupt pack' ' (cd repo_bad1.git && git --bare init && test_must_fail git --bare fetch "$GIT_DAEMON_URL/repo_bad1.git" && - test 0 = `ls objects/pack/pack-*.pack | wc -l` + test 0 = $(ls objects/pack/pack-*.pack | wc -l) ) ' test_expect_success 'fetch notices corrupt idx' ' cp -R "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_pack.git "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad2.git && (cd "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad2.git && - p=`ls objects/pack/pack-*.idx` && + p=$(ls objects/pack/pack-*.idx) && chmod u+w $p && printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc ) && @@ -80,7 +80,7 @@ test_expect_success 'fetch notices corrupt idx' ' (cd repo_bad2.git && git --bare init && test_must_fail git --bare fetch "$GIT_DAEMON_URL/repo_bad2.git" && - test 0 = `ls objects/pack | wc -l` + test 0 = $(ls objects/pack | wc -l) ) ' diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index 9b34f3c61..669ec9ba8 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -65,6 +65,29 @@ test_expect_success 'clone respects GIT_WORK_TREE' ' ' +test_expect_success 'clone from hooks' ' + + test_create_repo r0 && + cd r0 && + test_commit initial && + cd .. && + git init r1 && + cd r1 && + cat >.git/hooks/pre-commit <<-\EOF && + #!/bin/sh + git clone ../r0 ../r2 + exit 1 + EOF + chmod u+x .git/hooks/pre-commit && + : >file && + git add file && + test_must_fail git commit -m invoke-hook && + cd .. && + test_cmp r0/.git/HEAD r2/.git/HEAD && + test_cmp r0/initial.t r2/initial.t + +' + test_expect_success 'clone creates intermediate directories' ' git clone src long/path/to/dst && @@ -221,7 +244,7 @@ test_expect_success 'clone separate gitdir' ' ' test_expect_success 'clone separate gitdir: output' ' - echo "gitdir: `pwd`/realgitdir" >expected && + echo "gitdir: $(pwd)/realgitdir" >expected && test_cmp expected dst/.git ' diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh index dfa1bf79c..4320082b1 100755 --- a/t/t5700-clone-reference.sh +++ b/t/t5700-clone-reference.sh @@ -6,7 +6,7 @@ test_description='test clone --reference' . ./test-lib.sh -base_dir=`pwd` +base_dir=$(pwd) U=$base_dir/UPLOAD_LOG diff --git a/t/t5710-info-alternate.sh b/t/t5710-info-alternate.sh index 5a6e49d18..9cd2626db 100755 --- a/t/t5710-info-alternate.sh +++ b/t/t5710-info-alternate.sh @@ -21,7 +21,7 @@ test_valid_repo() { test_line_count = 0 fsck.log } -base_dir=`pwd` +base_dir=$(pwd) test_expect_success 'preparing first repository' \ 'test_create_repo A && cd A && diff --git a/t/t5900-repo-selection.sh b/t/t5900-repo-selection.sh index 3d5b418bb..14e59c5b3 100755 --- a/t/t5900-repo-selection.sh +++ b/t/t5900-repo-selection.sh @@ -15,7 +15,7 @@ make_tree() { make_bare() { git init --bare "$1" && (cd "$1" && - tree=`git hash-object -w -t tree /dev/null` && + tree=$(git hash-object -w -t tree /dev/null) && commit=$(echo "$1" | git commit-tree $tree) && git update-ref HEAD $commit ) diff --git a/t/t6001-rev-list-graft.sh b/t/t6001-rev-list-graft.sh index 8efcd1307..05ddc69cf 100755 --- a/t/t6001-rev-list-graft.sh +++ b/t/t6001-rev-list-graft.sh @@ -10,15 +10,15 @@ test_expect_success setup ' echo >subdir/fileB fileB && git add fileA subdir/fileB && git commit -a -m "Initial in one history." && - A0=`git rev-parse --verify HEAD` && + A0=$(git rev-parse --verify HEAD) && echo >fileA fileA modified && git commit -a -m "Second in one history." && - A1=`git rev-parse --verify HEAD` && + A1=$(git rev-parse --verify HEAD) && echo >subdir/fileB fileB modified && git commit -a -m "Third in one history." && - A2=`git rev-parse --verify HEAD` && + A2=$(git rev-parse --verify HEAD) && rm -f .git/refs/heads/master .git/index && @@ -26,15 +26,15 @@ test_expect_success setup ' echo >subdir/fileB fileB again && git add fileA subdir/fileB && git commit -a -m "Initial in alternate history." && - B0=`git rev-parse --verify HEAD` && + B0=$(git rev-parse --verify HEAD) && echo >fileA fileA modified in alternate history && git commit -a -m "Second in alternate history." && - B1=`git rev-parse --verify HEAD` && + B1=$(git rev-parse --verify HEAD) && echo >subdir/fileB fileB modified in alternate history && git commit -a -m "Third in alternate history." && - B2=`git rev-parse --verify HEAD` && + B2=$(git rev-parse --verify HEAD) && : done ' diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh index 43ad77248..3bf2759ea 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -27,9 +27,9 @@ test_bisection_diff() # Test if bisection size is close to half of list size within # tolerance. # - _bisect_err=`expr $_list_size - $_bisection_size \* 2` - test "$_bisect_err" -lt 0 && _bisect_err=`expr 0 - $_bisect_err` - _bisect_err=`expr $_bisect_err / 2` ; # floor + _bisect_err=$(expr $_list_size - $_bisection_size \* 2) + test "$_bisect_err" -lt 0 && _bisect_err=$(expr 0 - $_bisect_err) + _bisect_err=$(expr $_bisect_err / 2) ; # floor test_expect_success \ "bisection diff $_bisect_option $_head $* <= $_max_diff" \ diff --git a/t/t6015-rev-list-show-all-parents.sh b/t/t6015-rev-list-show-all-parents.sh index 8b146fb43..3c73c93ba 100755 --- a/t/t6015-rev-list-show-all-parents.sh +++ b/t/t6015-rev-list-show-all-parents.sh @@ -6,11 +6,11 @@ test_description='--show-all --parents does not rewrite TREESAME commits' test_expect_success 'set up --show-all --parents test' ' test_commit one foo.txt && - commit1=`git rev-list -1 HEAD` && + commit1=$(git rev-list -1 HEAD) && test_commit two bar.txt && - commit2=`git rev-list -1 HEAD` && + commit2=$(git rev-list -1 HEAD) && test_commit three foo.txt && - commit3=`git rev-list -1 HEAD` + commit3=$(git rev-list -1 HEAD) ' test_expect_success '--parents rewrites TREESAME parents correctly' ' diff --git a/t/t6032-merge-large-rename.sh b/t/t6032-merge-large-rename.sh index 0f7926891..80777386d 100755 --- a/t/t6032-merge-large-rename.sh +++ b/t/t6032-merge-large-rename.sh @@ -20,7 +20,7 @@ test_expect_success 'setup (initial)' ' make_text() { echo $1: $2 - for i in `count 20`; do + for i in $(count 20); do echo $1: $i done echo $1: $3 diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index 4d5a25eed..c630aba65 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -351,11 +351,15 @@ test_expect_success 'test --format long' ' test_cmp expected actual ' -test_expect_success 'setup a fake editor' ' - write_script fakeeditor <<-\EOF +test_expect_success 'setup fake editors' ' + write_script fakeeditor <<-\EOF && sed -e "s/A U Thor/A fake Thor/" "$1" >"$1.new" mv "$1.new" "$1" EOF + write_script failingfakeeditor <<-\EOF + ./fakeeditor "$@" + false + EOF ' test_expect_success '--edit with and without already replaced object' ' @@ -372,7 +376,7 @@ test_expect_success '--edit with and without already replaced object' ' test_expect_success '--edit and change nothing or command failed' ' git replace -d "$PARA3" && test_must_fail env GIT_EDITOR=true git replace --edit "$PARA3" && - test_must_fail env GIT_EDITOR="./fakeeditor;false" git replace --edit "$PARA3" && + test_must_fail env GIT_EDITOR="./failingfakeeditor" git replace --edit "$PARA3" && GIT_EDITOR=./fakeeditor git replace --edit "$PARA3" && git replace -l | grep "$PARA3" && git cat-file commit "$PARA3" | grep "A fake Thor" diff --git a/t/t6132-pathspec-exclude.sh b/t/t6132-pathspec-exclude.sh index e1e1b1fa3..d51595cf6 100755 --- a/t/t6132-pathspec-exclude.sh +++ b/t/t6132-pathspec-exclude.sh @@ -7,7 +7,7 @@ test_description='test case exclude pathspec' test_expect_success 'setup' ' for p in file sub/file sub/sub/file sub/file2 sub/sub/sub/file sub2/file; do if echo $p | grep /; then - mkdir -p `dirname $p` + mkdir -p $(dirname $p) fi && : >$p && git add $p && diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index 7b5608113..51dd2b4e0 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -156,11 +156,11 @@ test_expect_success "Michael Cassar's test case" ' echo b > partA/outline.txt && echo c > papers/unsorted/_another && git add papers partA && - T1=`git write-tree` && + T1=$(git write-tree) && git mv papers/unsorted/Thesis.pdf papers/all-papers/moo-blah.pdf && - T=`git write-tree` && + T=$(git write-tree) && git ls-tree -r $T | verbose grep partA/outline.txt ' diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 869e0bf07..8868e6e09 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -387,7 +387,7 @@ test_expect_success 'setup submodule' ' git branch original HEAD ' -orig_head=`git show-ref --hash --head HEAD` +orig_head=$(git show-ref --hash --head HEAD) test_expect_success 'rewrite submodule with another content' ' git filter-branch --tree-filter "test -d submod && { @@ -396,7 +396,7 @@ test_expect_success 'rewrite submodule with another content' ' mkdir submod && : > submod/file } || :" HEAD && - test $orig_head != `git show-ref --hash --head HEAD` + test $orig_head != $(git show-ref --hash --head HEAD) ' test_expect_success 'replace submodule revision' ' @@ -405,7 +405,7 @@ test_expect_success 'replace submodule revision' ' "if git ls-files --error-unmatch -- submod > /dev/null 2>&1 then git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 submod fi" HEAD && - test $orig_head != `git show-ref --hash --head HEAD` + test $orig_head != $(git show-ref --hash --head HEAD) ' test_expect_success 'filter commit message without trailing newline' ' diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 3dd2f51e4..2797f2253 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -23,8 +23,8 @@ test_expect_success 'listing all tags in an empty tree should succeed' ' ' test_expect_success 'listing all tags in an empty tree should output nothing' ' - test `git tag -l | wc -l` -eq 0 && - test `git tag | wc -l` -eq 0 + test $(git tag -l | wc -l) -eq 0 && + test $(git tag | wc -l) -eq 0 ' test_expect_success 'looking for a tag in an empty tree should fail' \ @@ -72,8 +72,8 @@ test_expect_success 'listing all tags if one exists should succeed' ' ' test_expect_success 'listing all tags if one exists should output that tag' ' - test `git tag -l` = mytag && - test `git tag` = mytag + test $(git tag -l) = mytag && + test $(git tag) = mytag ' # pattern matching: @@ -83,7 +83,7 @@ test_expect_success 'listing a tag using a matching pattern should succeed' \ test_expect_success \ 'listing a tag using a matching pattern should output that tag' \ - 'test `git tag -l mytag` = mytag' + 'test $(git tag -l mytag) = mytag' # todo: git tag -l now returns always zero, when fixed, change this test test_expect_success \ @@ -92,7 +92,7 @@ test_expect_success \ test_expect_success \ 'listing tags using a non-matching pattern should output nothing' \ - 'test `git tag -l xxx | wc -l` -eq 0' + 'test $(git tag -l xxx | wc -l) -eq 0' # special cases for creating tags: @@ -102,13 +102,13 @@ test_expect_success \ test_expect_success \ 'trying to create a tag with a non-valid name should fail' ' - test `git tag -l | wc -l` -eq 1 && + test $(git tag -l | wc -l) -eq 1 && test_must_fail git tag "" && test_must_fail git tag .othertag && test_must_fail git tag "other tag" && test_must_fail git tag "othertag^" && test_must_fail git tag "other~tag" && - test `git tag -l | wc -l` -eq 1 + test $(git tag -l | wc -l) -eq 1 ' test_expect_success 'creating a tag using HEAD directly should succeed' ' diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index 6ea7ac4c4..e4fc5c826 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -424,7 +424,7 @@ test_expect_success TTY 'command-specific pager works for external commands' ' echo "foo:initial" >expect && >actual && test_config pager.external "sed s/^/foo:/ >actual" && - test_terminal git --exec-path="`pwd`" external log --format=%s -1 && + test_terminal git --exec-path="$(pwd)" external log --format=%s -1 && test_cmp expect actual ' diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh index 1eef93c2b..afe36a533 100755 --- a/t/t7103-reset-bare.sh +++ b/t/t7103-reset-bare.sh @@ -63,7 +63,7 @@ test_expect_success '"mixed" reset is not allowed in bare' ' test_expect_success '"soft" reset is allowed in bare' ' git reset --soft HEAD^ && - test "`git show --pretty=format:%s | head -n 1`" = "one" + test "$(git show --pretty=format:%s | head -n 1)" = "one" ' test_done diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index dda3929d9..68ea31d69 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -14,8 +14,8 @@ submodule and "git submodule update --rebase/--merge" does not detach the HEAD. compare_head() { - sha_master=`git rev-list --max-count=1 master` - sha_head=`git rev-list --max-count=1 HEAD` + sha_master=$(git rev-list --max-count=1 master) + sha_head=$(git rev-list --max-count=1 HEAD) test "$sha_master" = "$sha_head" } diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh index b770b2f04..eaea19b8f 100755 --- a/t/t7408-submodule-reference.sh +++ b/t/t7408-submodule-reference.sh @@ -6,7 +6,7 @@ test_description='test clone --reference' . ./test-lib.sh -base_dir=`pwd` +base_dir=$(pwd) U=$base_dir/UPLOAD_LOG diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh index 1f53ea809..8728db61d 100755 --- a/t/t7504-commit-msg-hook.sh +++ b/t/t7504-commit-msg-hook.sh @@ -179,7 +179,7 @@ EOF chmod +x "$HOOK" commit_msg_is () { - test "`git log --pretty=format:%s%b -1`" = "$1" + test "$(git log --pretty=format:%s%b -1)" = "$1" } test_expect_success 'hook edits commit message' ' diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh index 03dce09cf..b13f72975 100755 --- a/t/t7505-prepare-commit-msg-hook.sh +++ b/t/t7505-prepare-commit-msg-hook.sh @@ -53,7 +53,7 @@ test_expect_success 'with hook (-m)' ' echo "more" >> file && git add file && git commit -m "more" && - test "`git log -1 --pretty=format:%s`" = "message (no editor)" + test "$(git log -1 --pretty=format:%s)" = "message (no editor)" ' @@ -62,7 +62,7 @@ test_expect_success 'with hook (-m editor)' ' echo "more" >> file && git add file && GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -e -m "more more" && - test "`git log -1 --pretty=format:%s`" = message + test "$(git log -1 --pretty=format:%s)" = message ' @@ -71,7 +71,7 @@ test_expect_success 'with hook (-t)' ' echo "more" >> file && git add file && git commit -t "$(git rev-parse --git-dir)/template" && - test "`git log -1 --pretty=format:%s`" = template + test "$(git log -1 --pretty=format:%s)" = template ' @@ -80,7 +80,7 @@ test_expect_success 'with hook (-F)' ' echo "more" >> file && git add file && (echo more | git commit -F -) && - test "`git log -1 --pretty=format:%s`" = "message (no editor)" + test "$(git log -1 --pretty=format:%s)" = "message (no editor)" ' @@ -89,17 +89,17 @@ test_expect_success 'with hook (-F editor)' ' echo "more" >> file && git add file && (echo more more | GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -e -F -) && - test "`git log -1 --pretty=format:%s`" = message + test "$(git log -1 --pretty=format:%s)" = message ' test_expect_success 'with hook (-C)' ' - head=`git rev-parse HEAD` && + head=$(git rev-parse HEAD) && echo "more" >> file && git add file && git commit -C $head && - test "`git log -1 --pretty=format:%s`" = "$head (no editor)" + test "$(git log -1 --pretty=format:%s)" = "$head (no editor)" ' @@ -108,27 +108,27 @@ test_expect_success 'with hook (editor)' ' echo "more more" >> file && git add file && GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit && - test "`git log -1 --pretty=format:%s`" = default + test "$(git log -1 --pretty=format:%s)" = default ' test_expect_success 'with hook (--amend)' ' - head=`git rev-parse HEAD` && + head=$(git rev-parse HEAD) && echo "more" >> file && git add file && GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --amend && - test "`git log -1 --pretty=format:%s`" = "$head" + test "$(git log -1 --pretty=format:%s)" = "$head" ' test_expect_success 'with hook (-c)' ' - head=`git rev-parse HEAD` && + head=$(git rev-parse HEAD) && echo "more" >> file && git add file && GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head && - test "`git log -1 --pretty=format:%s`" = "$head" + test "$(git log -1 --pretty=format:%s)" = "$head" ' @@ -141,7 +141,7 @@ test_expect_success 'with hook (merge)' ' git commit -m other && git checkout - && git merge --no-ff other && - test "`git log -1 --pretty=format:%s`" = "merge (no editor)" + test "$(git log -1 --pretty=format:%s)" = "merge (no editor)" ' test_expect_success 'with hook and editor (merge)' ' @@ -153,7 +153,7 @@ test_expect_success 'with hook and editor (merge)' ' git commit -m other && git checkout - && env GIT_EDITOR="\"\$FAKE_EDITOR\"" git merge --no-ff -e other && - test "`git log -1 --pretty=format:%s`" = "merge" + test "$(git log -1 --pretty=format:%s)" = "merge" ' cat > "$HOOK" <<'EOF' @@ -164,7 +164,7 @@ EOF test_expect_success 'with failing hook' ' test_when_finished "git checkout -f master" && - head=`git rev-parse HEAD` && + head=$(git rev-parse HEAD) && echo "more" >> file && git add file && test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head @@ -174,7 +174,7 @@ test_expect_success 'with failing hook' ' test_expect_success 'with failing hook (--no-verify)' ' test_when_finished "git checkout -f master" && - head=`git rev-parse HEAD` && + head=$(git rev-parse HEAD) && echo "more" >> file && git add file && test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh index 955f09f8e..6abe441ae 100755 --- a/t/t7602-merge-octopus-many.sh +++ b/t/t7602-merge-octopus-many.sh @@ -19,7 +19,7 @@ test_expect_success 'setup' ' git add c$i.c && git commit -m c$i && git tag c$i && - i=`expr $i + 1` || return 1 + i=$(expr $i + 1) || return 1 done ' @@ -30,7 +30,7 @@ test_expect_success 'merge c1 with c2, c3, c4, ... c29' ' while test $i -le 30 do refs="$refs c$i" - i=`expr $i + 1` + i=$(expr $i + 1) done && git merge $refs && test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" && @@ -38,14 +38,14 @@ test_expect_success 'merge c1 with c2, c3, c4, ... c29' ' while test $i -le 30 do test "$(git rev-parse c$i)" = "$(git rev-parse HEAD^$i)" && - i=`expr $i + 1` || return 1 + i=$(expr $i + 1) || return 1 done && git diff --exit-code && i=1 && while test $i -le 30 do test -f c$i.c && - i=`expr $i + 1` || return 1 + i=$(expr $i + 1) || return 1 done ' diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 021c5479b..6061a0414 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -69,7 +69,7 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' ' test_expect_success 'loose objects in alternate ODB are not repacked' ' mkdir alt_objects && - echo `pwd`/alt_objects > .git/objects/info/alternates && + echo $(pwd)/alt_objects > .git/objects/info/alternates && echo content3 > file3 && objsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) && git add file3 && @@ -168,7 +168,7 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' ' ' test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' ' - echo `pwd`/alt_objects > .git/objects/info/alternates && + echo $(pwd)/alt_objects > .git/objects/info/alternates && echo "$csha1" | git pack-objects --non-empty --all --reflog pack && rm -f .git/objects/pack/* && mv pack-* .git/objects/pack/ && diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 028ffe4a0..b54094440 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -791,12 +791,12 @@ test_expect_success 'outside of git repository' ' } >non/expect.full && echo file2:world >non/expect.sub && ( - GIT_CEILING_DIRECTORIES="$(pwd)/non/git" && + GIT_CEILING_DIRECTORIES="$(pwd)/non" && export GIT_CEILING_DIRECTORIES && cd non/git && test_must_fail git grep o && git grep --no-index o >../actual.full && - test_cmp ../expect.full ../actual.full + test_cmp ../expect.full ../actual.full && cd sub && test_must_fail git grep o && git grep --no-index o >../../actual.sub && @@ -805,7 +805,7 @@ test_expect_success 'outside of git repository' ' echo ".*o*" >non/git/.gitignore && ( - GIT_CEILING_DIRECTORIES="$(pwd)/non/git" && + GIT_CEILING_DIRECTORIES="$(pwd)/non" && export GIT_CEILING_DIRECTORIES && cd non/git && test_must_fail git grep o && @@ -813,7 +813,7 @@ test_expect_success 'outside of git repository' ' test_cmp ../expect.full ../actual.full && { - echo ".gitignore:.*o*" + echo ".gitignore:.*o*" && cat ../expect.full } >../expect.with.ignored && git grep --no-index --no-exclude o >../actual.full && @@ -821,6 +821,47 @@ test_expect_success 'outside of git repository' ' ) ' +test_expect_success 'outside of git repository with fallbackToNoIndex' ' + rm -fr non && + mkdir -p non/git/sub && + echo hello >non/git/file1 && + echo world >non/git/sub/file2 && + cat <<-\EOF >non/expect.full && + file1:hello + sub/file2:world + EOF + echo file2:world >non/expect.sub && + ( + GIT_CEILING_DIRECTORIES="$(pwd)/non" && + export GIT_CEILING_DIRECTORIES && + cd non/git && + test_must_fail git -c grep.fallbackToNoIndex=false grep o && + git -c grep.fallbackToNoIndex=true grep o >../actual.full && + test_cmp ../expect.full ../actual.full && + cd sub && + test_must_fail git -c grep.fallbackToNoIndex=false grep o && + git -c grep.fallbackToNoIndex=true grep o >../../actual.sub && + test_cmp ../../expect.sub ../../actual.sub + ) && + + echo ".*o*" >non/git/.gitignore && + ( + GIT_CEILING_DIRECTORIES="$(pwd)/non" && + export GIT_CEILING_DIRECTORIES && + cd non/git && + test_must_fail git -c grep.fallbackToNoIndex=false grep o && + git -c grep.fallbackToNoIndex=true grep --exclude-standard o >../actual.full && + test_cmp ../expect.full ../actual.full && + + { + echo ".gitignore:.*o*" && + cat ../expect.full + } >../expect.with.ignored && + git -c grep.fallbackToNoIndex grep --no-exclude o >../actual.full && + test_cmp ../expect.with.ignored ../actual.full + ) +' + test_expect_success 'inside git repository but with --no-index' ' rm -fr is && mkdir -p is/git/sub && diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh index 16f1442c1..656842975 100755 --- a/t/t8003-blame-corner-cases.sh +++ b/t/t8003-blame-corner-cases.sh @@ -153,7 +153,7 @@ test_expect_success 'blame path that used to be a directory' ' ' test_expect_success 'blame to a commit with no author name' ' - TREE=`git rev-parse HEAD:` && + TREE=$(git rev-parse HEAD:) && cat >badcommit <<EOF && tree $TREE author <noname> 1234567890 +0000 @@ -161,7 +161,7 @@ committer David Reiss <dreiss@facebook.com> 1234567890 +0000 some message EOF - COMMIT=`git hash-object -t commit -w badcommit` && + COMMIT=$(git hash-object -t commit -w badcommit) && git --no-pager blame $COMMIT -- uno >/dev/null ' diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 3c49536e0..b3355d2c7 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -36,7 +36,7 @@ clean_fake_sendmail () { } test_expect_success $PREREQ 'Extract patches' ' - patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1` + patches=$(git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1) ' # Test no confirm early to ensure remaining tests will not hang @@ -1151,7 +1151,7 @@ test_expect_success $PREREQ '--no-bcc overrides sendemail.bcc' ' ' test_expect_success $PREREQ 'patches To headers are used by default' ' - patch=`git format-patch -1 --to="bodies@example.com"` && + patch=$(git format-patch -1 --to="bodies@example.com") && test_when_finished "rm $patch" && git send-email \ --dry-run \ @@ -1162,7 +1162,7 @@ test_expect_success $PREREQ 'patches To headers are used by default' ' ' test_expect_success $PREREQ 'patches To headers are appended to' ' - patch=`git format-patch -1 --to="bodies@example.com"` && + patch=$(git format-patch -1 --to="bodies@example.com") && test_when_finished "rm $patch" && git send-email \ --dry-run \ @@ -1175,8 +1175,8 @@ test_expect_success $PREREQ 'patches To headers are appended to' ' ' test_expect_success $PREREQ 'To headers from files reset each patch' ' - patch1=`git format-patch -1 --to="bodies@example.com"` && - patch2=`git format-patch -1 --to="other@example.com" HEAD~` && + patch1=$(git format-patch -1 --to="bodies@example.com") && + patch2=$(git format-patch -1 --to="other@example.com" HEAD~) && test_when_finished "rm $patch1 && rm $patch2" && git send-email \ --dry-run \ @@ -1488,7 +1488,7 @@ test_cover_addresses () { clean_fake_sendmail && rm -fr outdir && git format-patch --cover-letter -2 -o outdir && - cover=`echo outdir/0000-*.patch` && + cover=$(echo outdir/0000-*.patch) && mv $cover cover-to-edit.patch && perl -pe "s/^From:/$header: extra\@address.com\nFrom:/" cover-to-edit.patch >"$cover" && git send-email \ @@ -1527,6 +1527,21 @@ test_expect_success $PREREQ 'cccover adds Cc to all mail' ' test_cover_addresses "Cc" ' +test_expect_success $PREREQ 'escaped quotes in sendemail.aliasfiletype=mutt' ' + clean_fake_sendmail && + echo "alias sbd \\\"Dot U. Sir\\\" <somebody@example.org>" >.mutt && + git config --replace-all sendemail.aliasesfile "$(pwd)/.mutt" && + git config sendemail.aliasfiletype mutt && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=sbd \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/0001-*.patch \ + 2>errors >out && + grep "^!somebody@example\.org!$" commandline1 && + grep -F "To: \"Dot U. Sir\" <somebody@example.org>" out +' + test_expect_success $PREREQ 'sendemail.aliasfiletype=mailrc' ' clean_fake_sendmail && echo "alias sbd somebody@example.org" >.mailrc && diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index 4fea8d901..258d9b8ce 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -265,18 +265,18 @@ test_expect_success 'able to dcommit to a subdirectory' " git update-index --add d && git commit -m '/bar/d should be in the log' && git svn dcommit -i bar && - test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" && + test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" && mkdir newdir && echo new > newdir/dir && git update-index --add newdir/dir && git commit -m 'add a new directory' && git svn dcommit -i bar && - test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" && + test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" && echo foo >> newdir/dir && git update-index newdir/dir && git commit -m 'modify a file in new directory' && git svn dcommit -i bar && - test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" + test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" " test_expect_success 'dcommit should not fail with a touched file' ' @@ -295,7 +295,7 @@ test_expect_success 'able to set-tree to a subdirectory' " git update-index d && git commit -m 'update /bar/d' && git svn set-tree -i bar HEAD && - test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" + test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" " test_expect_success 'git-svn works in a bare repository' ' diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh index 8869f5018..e8173d5fe 100755 --- a/t/t9101-git-svn-props.sh +++ b/t/t9101-git-svn-props.sh @@ -26,27 +26,27 @@ cd import EOF printf "Hello\r\nWorld\r\n" > crlf - a_crlf=`git hash-object -w crlf` + a_crlf=$(git hash-object -w crlf) printf "Hello\rWorld\r" > cr - a_cr=`git hash-object -w cr` + a_cr=$(git hash-object -w cr) printf "Hello\nWorld\n" > lf - a_lf=`git hash-object -w lf` + a_lf=$(git hash-object -w lf) printf "Hello\r\nWorld" > ne_crlf - a_ne_crlf=`git hash-object -w ne_crlf` + a_ne_crlf=$(git hash-object -w ne_crlf) printf "Hello\nWorld" > ne_lf - a_ne_lf=`git hash-object -w ne_lf` + a_ne_lf=$(git hash-object -w ne_lf) printf "Hello\rWorld" > ne_cr - a_ne_cr=`git hash-object -w ne_cr` + a_ne_cr=$(git hash-object -w ne_cr) touch empty - a_empty=`git hash-object -w empty` + a_empty=$(git hash-object -w empty) printf "\n" > empty_lf - a_empty_lf=`git hash-object -w empty_lf` + a_empty_lf=$(git hash-object -w empty_lf) printf "\r" > empty_cr - a_empty_cr=`git hash-object -w empty_cr` + a_empty_cr=$(git hash-object -w empty_cr) printf "\r\n" > empty_crlf - a_empty_crlf=`git hash-object -w empty_crlf` + a_empty_crlf=$(git hash-object -w empty_crlf) svn_cmd import --no-auto-props -m 'import for git svn' . "$svnrepo" >/dev/null cd .. @@ -80,7 +80,7 @@ test_expect_success "$name" \ git pull . ${remotes_git_svn}' expect='/* $Id$ */' -got="`sed -ne 2p kw.c`" +got="$(sed -ne 2p kw.c)" test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'" test_expect_success "propset CR on crlf files" ' @@ -107,8 +107,8 @@ done cd test_wc printf '$Id$\rHello\rWorld\r' > cr printf '$Id$\rHello\rWorld' > ne_cr - a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git hash-object --stdin` - a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git hash-object --stdin` + a_cr=$(printf '$Id$\r\nHello\r\nWorld\r\n' | git hash-object --stdin) + a_ne_cr=$(printf '$Id$\r\nHello\r\nWorld' | git hash-object --stdin) test_expect_success 'Set CRLF on cr files' \ 'svn_cmd propset svn:eol-style CRLF cr && svn_cmd propset svn:eol-style CRLF ne_cr && @@ -119,8 +119,8 @@ cd .. test_expect_success 'fetch and pull latest from svn' \ 'git svn fetch && git pull . ${remotes_git_svn}' -b_cr="`git hash-object cr`" -b_ne_cr="`git hash-object ne_cr`" +b_cr="$(git hash-object cr)" +b_ne_cr="$(git hash-object ne_cr)" test_expect_success 'CRLF + $Id$' "test '$a_cr' = '$b_cr'" test_expect_success 'CRLF + $Id$ (no newline)' "test '$a_ne_cr' = '$b_ne_cr'" diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh index 83f17e13e..cd480edf1 100755 --- a/t/t9104-git-svn-follow-parent.sh +++ b/t/t9104-git-svn-follow-parent.sh @@ -31,12 +31,12 @@ test_expect_success 'initialize repo' ' test_expect_success 'init and fetch a moved directory' ' git svn init --minimize-url -i thunk "$svnrepo"/thunk && git svn fetch -i thunk && - test "`git rev-parse --verify refs/remotes/thunk@2`" \ - = "`git rev-parse --verify refs/remotes/thunk~1`" && - test "`git cat-file blob refs/remotes/thunk:readme |\ - sed -n -e "3p"`" = goodbye && - test -z "`git config --get svn-remote.svn.fetch \ - "^trunk:refs/remotes/thunk@2$"`" + test "$(git rev-parse --verify refs/remotes/thunk@2)" \ + = "$(git rev-parse --verify refs/remotes/thunk~1)" && + test "$(git cat-file blob refs/remotes/thunk:readme |\ + sed -n -e "3p")" = goodbye && + test -z "$(git config --get svn-remote.svn.fetch \ + "^trunk:refs/remotes/thunk@2$")" ' test_expect_success 'init and fetch from one svn-remote' ' @@ -46,10 +46,10 @@ test_expect_success 'init and fetch from one svn-remote' ' git config --add svn-remote.svn.fetch \ thunk:refs/remotes/svn/thunk && git svn fetch -i svn/thunk && - test "`git rev-parse --verify refs/remotes/svn/trunk`" \ - = "`git rev-parse --verify refs/remotes/svn/thunk~1`" && - test "`git cat-file blob refs/remotes/svn/thunk:readme |\ - sed -n -e "3p"`" = goodbye + test "$(git rev-parse --verify refs/remotes/svn/trunk)" \ + = "$(git rev-parse --verify refs/remotes/svn/thunk~1)" && + test "$(git cat-file blob refs/remotes/svn/thunk:readme |\ + sed -n -e "3p")" = goodbye ' test_expect_success 'follow deleted parent' ' @@ -61,9 +61,9 @@ test_expect_success 'follow deleted parent' ' junk:refs/remotes/svn/junk && git svn fetch -i svn/thunk && git svn fetch -i svn/junk && - test -z "`git diff svn/junk svn/trunk`" && - test "`git merge-base svn/junk svn/trunk`" \ - = "`git rev-parse svn/trunk`" + test -z "$(git diff svn/junk svn/trunk)" && + test "$(git merge-base svn/junk svn/trunk)" \ + = "$(git rev-parse svn/trunk)" ' test_expect_success 'follow larger parent' ' @@ -80,10 +80,10 @@ test_expect_success 'follow larger parent' ' git rev-parse --verify refs/remotes/larger && git rev-parse --verify \ refs/remotes/larger-parent && - test "`git merge-base \ + test "$(git merge-base \ refs/remotes/larger-parent \ - refs/remotes/larger`" = \ - "`git rev-parse refs/remotes/larger`" + refs/remotes/larger)" = \ + "$(git rev-parse refs/remotes/larger)" ' test_expect_success 'follow higher-level parent' ' @@ -106,8 +106,8 @@ test_expect_success 'follow deleted directory' ' svn_cmd rm -m "remove glob" "$svnrepo"/glob && git svn init --minimize-url -i glob "$svnrepo"/glob && git svn fetch -i glob && - test "`git cat-file blob refs/remotes/glob:blob/bye`" = hi && - test "`git ls-tree refs/remotes/glob | wc -l `" -eq 1 + test "$(git cat-file blob refs/remotes/glob:blob/bye)" = hi && + test "$(git ls-tree refs/remotes/glob | wc -l )" -eq 1 ' # ref: r9270 of the Subversion repository: (http://svn.collab.net/repos/svn) @@ -142,9 +142,9 @@ test_expect_success 'follow-parent avoids deleting relevant info' ' git svn init --minimize-url -i r9270-t \ "$svnrepo"/r9270/trunk/subversion/bindings/swig/perl/native/t && git svn fetch -i r9270-t && - test `git rev-list r9270-t | wc -l` -eq 2 && - test "`git ls-tree --name-only r9270-t~1`" = \ - "`git ls-tree --name-only r9270-t`" + test $(git rev-list r9270-t | wc -l) -eq 2 && + test "$(git ls-tree --name-only r9270-t~1)" = \ + "$(git ls-tree --name-only r9270-t)" ' test_expect_success "track initial change if it was only made to parent" ' @@ -152,11 +152,11 @@ test_expect_success "track initial change if it was only made to parent" ' git svn init --minimize-url -i r9270-d \ "$svnrepo"/r9270/drunk/subversion/bindings/swig/perl/native/t && git svn fetch -i r9270-d && - test `git rev-list r9270-d | wc -l` -eq 3 && - test "`git ls-tree --name-only r9270-t`" = \ - "`git ls-tree --name-only r9270-d`" && - test "`git rev-parse r9270-t`" = \ - "`git rev-parse r9270-d~1`" + test $(git rev-list r9270-d | wc -l) -eq 3 && + test "$(git ls-tree --name-only r9270-t)" = \ + "$(git ls-tree --name-only r9270-d)" && + test "$(git rev-parse r9270-t)" = \ + "$(git rev-parse r9270-d~1)" ' test_expect_success "follow-parent is atomic" ' @@ -193,19 +193,19 @@ test_expect_success "follow-parent is atomic" ' git svn fetch -i stunk && git svn init --minimize-url -i flunked "$svnrepo"/flunked && git svn fetch -i flunked && - test "`git rev-parse --verify refs/remotes/flunk@18`" \ - = "`git rev-parse --verify refs/remotes/stunk`" && - test "`git rev-parse --verify refs/remotes/flunk~1`" \ - = "`git rev-parse --verify refs/remotes/stunk`" && - test "`git rev-parse --verify refs/remotes/flunked~1`" \ - = "`git rev-parse --verify refs/remotes/stunk~1`" + test "$(git rev-parse --verify refs/remotes/flunk@18)" \ + = "$(git rev-parse --verify refs/remotes/stunk)" && + test "$(git rev-parse --verify refs/remotes/flunk~1)" \ + = "$(git rev-parse --verify refs/remotes/stunk)" && + test "$(git rev-parse --verify refs/remotes/flunked~1)" \ + = "$(git rev-parse --verify refs/remotes/stunk~1)" ' test_expect_success "track multi-parent paths" ' svn_cmd cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob && git svn multi-fetch && - test `git cat-file commit refs/remotes/glob | \ - grep "^parent " | wc -l` -eq 2 + test $(git cat-file commit refs/remotes/glob | \ + grep "^parent " | wc -l) -eq 2 ' test_expect_success "multi-fetch continues to work" " diff --git a/t/t9105-git-svn-commit-diff.sh b/t/t9105-git-svn-commit-diff.sh index 5d0afeae6..6ed5f74e2 100755 --- a/t/t9105-git-svn-commit-diff.sh +++ b/t/t9105-git-svn-commit-diff.sh @@ -18,8 +18,8 @@ test_expect_success 'initialize repo' ' git commit -a -m "another" ' -head=`git rev-parse --verify HEAD^0` -prev=`git rev-parse --verify HEAD^1` +head=$(git rev-parse --verify HEAD^0) +prev=$(git rev-parse --verify HEAD^1) # the internals of the commit-diff command are the same as the regular # commit, so only a basic test of functionality is needed since we've diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh index 6e69fc4c6..906019803 100755 --- a/t/t9107-git-svn-migrate.sh +++ b/t/t9107-git-svn-migrate.sh @@ -24,10 +24,10 @@ test_expect_success 'setup old-looking metadata' ' git update-ref -d refs/${remotes_git_svn} refs/${remotes_git_svn} ' -head=`git rev-parse --verify refs/heads/git-svn-HEAD^0` +head=$(git rev-parse --verify refs/heads/git-svn-HEAD^0) test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'" -svnrepo_escaped=`echo $svnrepo | sed 's/ /%20/'` +svnrepo_escaped=$(echo $svnrepo | sed 's/ /%20/') test_expect_success 'initialize old-style (v0) git svn layout' ' mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info && @@ -38,7 +38,7 @@ test_expect_success 'initialize old-style (v0) git svn layout' ' git rev-parse --verify refs/${remotes_git_svn}^0 && git rev-parse --verify refs/remotes/svn^0 && test "$(git config --get svn-remote.svn.url)" = "$svnrepo_escaped" && - test `git config --get svn-remote.svn.fetch` = \ + test $(git config --get svn-remote.svn.fetch) = \ ":refs/${remotes_git_svn}" ' @@ -46,10 +46,10 @@ test_expect_success 'initialize a multi-repository repo' ' git svn init "$svnrepo" -T trunk -t tags -b branches && git config --get-all svn-remote.svn.fetch > fetch.out && grep "^trunk:refs/remotes/origin/trunk$" fetch.out && - test -n "`git config --get svn-remote.svn.branches \ - "^branches/\*:refs/remotes/origin/\*$"`" && - test -n "`git config --get svn-remote.svn.tags \ - "^tags/\*:refs/remotes/origin/tags/\*$"`" && + test -n "$(git config --get svn-remote.svn.branches \ + "^branches/\*:refs/remotes/origin/\*$")" && + test -n "$(git config --get svn-remote.svn.tags \ + "^tags/\*:refs/remotes/origin/tags/\*$")" && git config --unset svn-remote.svn.branches \ "^branches/\*:refs/remotes/origin/\*$" && git config --unset svn-remote.svn.tags \ @@ -75,28 +75,28 @@ test_expect_success 'multi-fetch works on partial urls + paths' " for i in trunk a b tags/0.1 tags/0.2 tags/0.3; do git rev-parse --verify refs/remotes/origin/\$i^0 >> refs.out || exit 1; done && - test -z \"\`sort < refs.out | uniq -d\`\" && + test -z \"\$(sort < refs.out | uniq -d)\" && for i in trunk a b tags/0.1 tags/0.2 tags/0.3; do for j in trunk a b tags/0.1 tags/0.2 tags/0.3; do if test \$j != \$i; then continue; fi - test -z \"\`git diff refs/remotes/origin/\$i \ - refs/remotes/origin/\$j\`\" ||exit 1; done; done + test -z \"\$(git diff refs/remotes/origin/\$i \ + refs/remotes/origin/\$j)\" ||exit 1; done; done " test_expect_success 'migrate --minimize on old inited layout' ' git config --unset-all svn-remote.svn.fetch && git config --unset-all svn-remote.svn.url && rm -rf "$GIT_DIR"/svn && - for i in `cat fetch.out`; do - path=`expr $i : "\([^:]*\):.*$"` - ref=`expr $i : "[^:]*:\(refs/remotes/.*\)$"` + for i in $(cat fetch.out); do + path=$(expr $i : "\([^:]*\):.*$") + ref=$(expr $i : "[^:]*:\(refs/remotes/.*\)$") if test -z "$ref"; then continue; fi if test -n "$path"; then path="/$path"; fi ( mkdir -p "$GIT_DIR"/svn/$ref/info/ && echo "$svnrepo"$path > "$GIT_DIR"/svn/$ref/info/url ) || exit 1; done && git svn migrate --minimize && - test -z "`git config -l | grep "^svn-remote\.git-svn\."`" && + test -z "$(git config -l | grep "^svn-remote\.git-svn\.")" && git config --get-all svn-remote.svn.fetch > fetch.out && grep "^trunk:refs/remotes/origin/trunk$" fetch.out && grep "^branches/a:refs/remotes/origin/a$" fetch.out && diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh index d732d3130..a526d6037 100755 --- a/t/t9108-git-svn-glob.sh +++ b/t/t9108-git-svn-glob.sh @@ -50,10 +50,10 @@ test_expect_success 'test refspec globbing' ' git log --pretty=oneline refs/remotes/tags/end | \ sed -e "s/^.\{41\}//" > output.end && test_cmp expect.end output.end && - test "`git rev-parse refs/remotes/tags/end~1`" = \ - "`git rev-parse refs/remotes/branches/start`" && - test "`git rev-parse refs/remotes/branches/start~2`" = \ - "`git rev-parse refs/remotes/trunk`" && + test "$(git rev-parse refs/remotes/tags/end~1)" = \ + "$(git rev-parse refs/remotes/branches/start)" && + test "$(git rev-parse refs/remotes/branches/start~2)" = \ + "$(git rev-parse refs/remotes/trunk)" && test_must_fail git rev-parse refs/remotes/tags/end@3 ' @@ -75,12 +75,12 @@ test_expect_success 'test left-hand-side only globbing' ' svn_cmd commit -m "try to try" ) && git svn fetch two && - test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 && - test `git rev-list refs/remotes/two/branches/start | wc -l` -eq 3 && - test `git rev-parse refs/remotes/two/branches/start~2` = \ - `git rev-parse refs/remotes/two/trunk` && - test `git rev-parse refs/remotes/two/tags/end~3` = \ - `git rev-parse refs/remotes/two/branches/start` && + test $(git rev-list refs/remotes/two/tags/end | wc -l) -eq 6 && + test $(git rev-list refs/remotes/two/branches/start | wc -l) -eq 3 && + test $(git rev-parse refs/remotes/two/branches/start~2) = \ + $(git rev-parse refs/remotes/two/trunk) && + test $(git rev-parse refs/remotes/two/tags/end~3) = \ + $(git rev-parse refs/remotes/two/branches/start) && git log --pretty=oneline refs/remotes/two/tags/end | \ sed -e "s/^.\{41\}//" > output.two && test_cmp expect.two output.two diff --git a/t/t9109-git-svn-multi-glob.sh b/t/t9109-git-svn-multi-glob.sh index c318f9f94..f36b74924 100755 --- a/t/t9109-git-svn-multi-glob.sh +++ b/t/t9109-git-svn-multi-glob.sh @@ -50,10 +50,10 @@ test_expect_success 'test refspec globbing' ' git log --pretty=oneline refs/remotes/tags/end | \ sed -e "s/^.\{41\}//" > output.end && test_cmp expect.end output.end && - test "`git rev-parse refs/remotes/tags/end~1`" = \ - "`git rev-parse refs/remotes/branches/v1/start`" && - test "`git rev-parse refs/remotes/branches/v1/start~2`" = \ - "`git rev-parse refs/remotes/trunk`" && + test "$(git rev-parse refs/remotes/tags/end~1)" = \ + "$(git rev-parse refs/remotes/branches/v1/start)" && + test "$(git rev-parse refs/remotes/branches/v1/start~2)" = \ + "$(git rev-parse refs/remotes/trunk)" && test_must_fail git rev-parse refs/remotes/tags/end@3 ' @@ -75,12 +75,12 @@ test_expect_success 'test left-hand-side only globbing' ' svn_cmd commit -m "try to try" ) && git svn fetch two && - test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 && - test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 && - test `git rev-parse refs/remotes/two/branches/v1/start~2` = \ - `git rev-parse refs/remotes/two/trunk` && - test `git rev-parse refs/remotes/two/tags/end~3` = \ - `git rev-parse refs/remotes/two/branches/v1/start` && + test $(git rev-list refs/remotes/two/tags/end | wc -l) -eq 6 && + test $(git rev-list refs/remotes/two/branches/v1/start | wc -l) -eq 3 && + test $(git rev-parse refs/remotes/two/branches/v1/start~2) = \ + $(git rev-parse refs/remotes/two/trunk) && + test $(git rev-parse refs/remotes/two/tags/end~3) = \ + $(git rev-parse refs/remotes/two/branches/v1/start) && git log --pretty=oneline refs/remotes/two/tags/end | \ sed -e "s/^.\{41\}//" > output.two && test_cmp expect.two output.two @@ -124,12 +124,12 @@ test_expect_success 'test another branch' ' git config --add svn-remote.four.tags \ "tags/*:refs/remotes/four/tags/*" && git svn fetch four && - test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 && - test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 && - test `git rev-parse refs/remotes/four/branches/v2/start~2` = \ - `git rev-parse refs/remotes/four/trunk` && - test `git rev-parse refs/remotes/four/tags/next~2` = \ - `git rev-parse refs/remotes/four/branches/v2/start` && + test $(git rev-list refs/remotes/four/tags/next | wc -l) -eq 5 && + test $(git rev-list refs/remotes/four/branches/v2/start | wc -l) -eq 3 && + test $(git rev-parse refs/remotes/four/branches/v2/start~2) = \ + $(git rev-parse refs/remotes/four/trunk) && + test $(git rev-parse refs/remotes/four/tags/next~2) = \ + $(git rev-parse refs/remotes/four/branches/v2/start) && git log --pretty=oneline refs/remotes/four/tags/next | \ sed -e "s/^.\{41\}//" > output.four && test_cmp expect.four output.four diff --git a/t/t9110-git-svn-use-svm-props.sh b/t/t9110-git-svn-use-svm-props.sh index a06e4c5b8..29fbdfdd3 100755 --- a/t/t9110-git-svn-use-svm-props.sh +++ b/t/t9110-git-svn-use-svm-props.sh @@ -51,7 +51,7 @@ test_expect_success 'verify metadata for /dir' " test_expect_success 'find commit based on SVN revision number' " git svn find-rev r12 | - grep `git rev-parse HEAD` + grep $(git rev-parse HEAD) " test_expect_success 'empty rebase' " diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh index fb4187667..a3d388228 100755 --- a/t/t9114-git-svn-dcommit-merge.sh +++ b/t/t9114-git-svn-dcommit-merge.sh @@ -68,8 +68,8 @@ test_expect_success 'setup git mirror and merge' ' test_debug 'gitk --all & sleep 1' test_expect_success 'verify pre-merge ancestry' " - test x\`git rev-parse --verify refs/heads/svn^2\` = \ - x\`git rev-parse --verify refs/heads/merge\` && + test x\$(git rev-parse --verify refs/heads/svn^2) = \ + x\$(git rev-parse --verify refs/heads/merge) && git cat-file commit refs/heads/svn^ | grep '^friend$' " @@ -80,10 +80,10 @@ test_expect_success 'git svn dcommit merges' " test_debug 'gitk --all & sleep 1' test_expect_success 'verify post-merge ancestry' " - test x\`git rev-parse --verify refs/heads/svn\` = \ - x\`git rev-parse --verify refs/remotes/origin/trunk \` && - test x\`git rev-parse --verify refs/heads/svn^2\` = \ - x\`git rev-parse --verify refs/heads/merge\` && + test x\$(git rev-parse --verify refs/heads/svn) = \ + x\$(git rev-parse --verify refs/remotes/origin/trunk) && + test x\$(git rev-parse --verify refs/heads/svn^2) = \ + x\$(git rev-parse --verify refs/heads/merge) && git cat-file commit refs/heads/svn^ | grep '^friend$' " diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh index ed4d1369c..a2219154b 100755 --- a/t/t9118-git-svn-funky-branch-names.sh +++ b/t/t9118-git-svn-funky-branch-names.sh @@ -35,7 +35,7 @@ test_expect_success 'setup svnrepo' ' # SVN 1.7 will truncate "not-a%40{0]" to just "not-a". # Look at what SVN wound up naming the branch and use that. # Be sure to escape the @ if it shows up. -non_reflog=`svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/'` +non_reflog=$(svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/') test_expect_success 'test clone with funky branch names' ' git svn clone -s "$svnrepo/pr ject" project && diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh index f16f3234a..88241baee 100755 --- a/t/t9119-git-svn-info.sh +++ b/t/t9119-git-svn-info.sh @@ -8,7 +8,7 @@ test_description='git svn info' # Tested with: svn, version 1.4.4 (r25188) # Tested with: svn, version 1.6.[12345689] -v=`svn_cmd --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p'` +v=$(svn_cmd --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p') case $v in 1.[456].*) ;; diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh index 8cfdfe790..39b6bcb39 100755 --- a/t/t9129-git-svn-i18n-commitencoding.sh +++ b/t/t9129-git-svn-i18n-commitencoding.sh @@ -7,7 +7,7 @@ test_description='git svn honors i18n.commitEncoding in config' . ./lib-git-svn.sh compare_git_head_with () { - nr=`wc -l < "$1"` + nr=$(wc -l < "$1") a=7 b=$(($a + $nr - 1)) git cat-file commit HEAD | sed -ne "$a,${b}p" >current && @@ -29,7 +29,7 @@ fi compare_svn_head_with () { # extract just the log message and strip out committer info. # don't use --limit here since svn 1.1.x doesn't have it, - LC_ALL="$a_utf8_locale" svn log `git svn info --url` | perl -w -e ' + LC_ALL="$a_utf8_locale" svn log $(git svn info --url) | perl -w -e ' use bytes; $/ = ("-"x72) . "\n"; my @x = <STDIN>; diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh index c44de267a..d306b77c3 100755 --- a/t/t9130-git-svn-authors-file.sh +++ b/t/t9130-git-svn-authors-file.sh @@ -26,7 +26,7 @@ test_expect_success 'start import with incomplete authors file' ' test_expect_success 'imported 2 revisions successfully' ' ( cd x - test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 2 && + test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 2 && git rev-list -1 --pretty=raw refs/remotes/git-svn | \ grep "^author BBBBBBB BBBBBBB <bb@example\.com> " && git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \ @@ -43,7 +43,7 @@ test_expect_success 'continues to import once authors have been added' ' ( cd x git svn fetch --authors-file=../svn-authors && - test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 4 && + test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 4 && git rev-list -1 --pretty=raw refs/remotes/git-svn | \ grep "^author DDDDDDD DDDDDDD <dd@example\.com> " && git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \ @@ -73,8 +73,8 @@ tmp_config_get () { test_expect_success 'failure happened without negative side effects' ' ( cd aa-work && - test 6 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" && - test 6 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`" + test 6 -eq "$(tmp_config_get svn-remote.svn.branches-maxRev)" && + test 6 -eq "$(tmp_config_get svn-remote.svn.tags-maxRev)" ) ' @@ -86,8 +86,8 @@ test_expect_success 'fetch continues after authors-file is fixed' ' ( cd aa-work && git svn fetch --authors-file=../svn-authors && - test 8 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" && - test 8 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`" + test 8 -eq "$(tmp_config_get svn-remote.svn.branches-maxRev)" && + test 8 -eq "$(tmp_config_get svn-remote.svn.tags-maxRev)" ) ' diff --git a/t/t9132-git-svn-broken-symlink.sh b/t/t9132-git-svn-broken-symlink.sh index 6c4c90b03..aeceffaf7 100755 --- a/t/t9132-git-svn-broken-symlink.sh +++ b/t/t9132-git-svn-broken-symlink.sh @@ -87,7 +87,7 @@ test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" x' test_expect_success SYMLINKS '"bar" is a symlink that points to "asdf"' ' test -L x/bar && - (cd x && test xasdf = x"`git cat-file blob HEAD:bar`") + (cd x && test xasdf = x"$(git cat-file blob HEAD:bar)") ' test_expect_success 'get "bar" => symlink fix from svn' ' @@ -96,7 +96,7 @@ test_expect_success 'get "bar" => symlink fix from svn' ' test_expect_success SYMLINKS '"bar" remains a proper symlink' ' test -L x/bar && - (cd x && test xdoink = x"`git cat-file blob HEAD:bar`") + (cd x && test xdoink = x"$(git cat-file blob HEAD:bar)") ' test_done diff --git a/t/t9137-git-svn-dcommit-clobber-series.sh b/t/t9137-git-svn-dcommit-clobber-series.sh index d60da63f7..5fa07a369 100755 --- a/t/t9137-git-svn-dcommit-clobber-series.sh +++ b/t/t9137-git-svn-dcommit-clobber-series.sh @@ -16,15 +16,15 @@ test_expect_success 'initialize repo' ' ' test_expect_success '(supposedly) non-conflicting change from SVN' ' - test x"`sed -n -e 58p < file`" = x58 && - test x"`sed -n -e 61p < file`" = x61 && + test x"$(sed -n -e 58p < file)" = x58 && + test x"$(sed -n -e 61p < file)" = x61 && svn_cmd co "$svnrepo" tmp && (cd tmp && perl -i.bak -p -e "s/^58$/5588/" file && perl -i.bak -p -e "s/^61$/6611/" file && poke file && - test x"`sed -n -e 58p < file`" = x5588 && - test x"`sed -n -e 61p < file`" = x6611 && + test x"$(sed -n -e 58p < file)" = x5588 && + test x"$(sed -n -e 61p < file)" = x6611 && svn_cmd commit -m "58 => 5588, 61 => 6611" ) ' @@ -38,20 +38,20 @@ test_expect_success 'some unrelated changes to git' " " test_expect_success 'change file but in unrelated area' " - test x\"\`sed -n -e 4p < file\`\" = x4 && - test x\"\`sed -n -e 7p < file\`\" = x7 && + test x\"\$(sed -n -e 4p < file)\" = x4 && + test x\"\$(sed -n -e 7p < file)\" = x7 && perl -i.bak -p -e 's/^4\$/4444/' file && perl -i.bak -p -e 's/^7\$/7777/' file && - test x\"\`sed -n -e 4p < file\`\" = x4444 && - test x\"\`sed -n -e 7p < file\`\" = x7777 && + test x\"\$(sed -n -e 4p < file)\" = x4444 && + test x\"\$(sed -n -e 7p < file)\" = x7777 && git commit -m '4 => 4444, 7 => 7777' file && git svn dcommit && svn_cmd up tmp && cd tmp && - test x\"\`sed -n -e 4p < file\`\" = x4444 && - test x\"\`sed -n -e 7p < file\`\" = x7777 && - test x\"\`sed -n -e 58p < file\`\" = x5588 && - test x\"\`sed -n -e 61p < file\`\" = x6611 + test x\"\$(sed -n -e 4p < file)\" = x4444 && + test x\"\$(sed -n -e 7p < file)\" = x7777 && + test x\"\$(sed -n -e 58p < file)\" = x5588 && + test x\"\$(sed -n -e 61p < file)\" = x6611 " test_expect_success 'attempt to dcommit with a dirty index' ' diff --git a/t/t9138-git-svn-authors-prog.sh b/t/t9138-git-svn-authors-prog.sh index 2937f4c26..7d7e9d46b 100755 --- a/t/t9138-git-svn-authors-prog.sh +++ b/t/t9138-git-svn-authors-prog.sh @@ -37,7 +37,7 @@ test_expect_success 'import authors with prog and file' ' test_expect_success 'imported 6 revisions successfully' ' ( cd x - test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 6 + test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 6 ) ' diff --git a/t/t9145-git-svn-master-branch.sh b/t/t9145-git-svn-master-branch.sh index 655913749..3bbf341f6 100755 --- a/t/t9145-git-svn-master-branch.sh +++ b/t/t9145-git-svn-master-branch.sh @@ -17,8 +17,8 @@ test_expect_success 'git svn clone --stdlayout sets up trunk as master' ' git svn clone -s "$svnrepo" g && ( cd g && - test x`git rev-parse --verify refs/remotes/origin/trunk^0` = \ - x`git rev-parse --verify refs/heads/master^0` + test x$(git rev-parse --verify refs/remotes/origin/trunk^0) = \ + x$(git rev-parse --verify refs/heads/master^0) ) ' diff --git a/t/t9150-svk-mergetickets.sh b/t/t9150-svk-mergetickets.sh index 24c2421bf..1bb676bed 100755 --- a/t/t9150-svk-mergetickets.sh +++ b/t/t9150-svk-mergetickets.sh @@ -19,7 +19,7 @@ test_expect_success 'load svk depot' " uuid=b48289b2-9c08-4d72-af37-0358a40b9c15 test_expect_success 'svk merges were represented coming in' " - [ `git cat-file commit HEAD | grep parent | wc -l` -eq 2 ] + [ $(git cat-file commit HEAD | grep parent | wc -l) -eq 2 ] " test_done diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 14a938402..4c5f3c9d4 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -171,10 +171,10 @@ test_expect_success 'A: verify tag/series-A-blob' ' test_expect_success 'A: verify marks output' ' cat >expect <<-EOF && - :2 `git rev-parse --verify master:file2` - :3 `git rev-parse --verify master:file3` - :4 `git rev-parse --verify master:file4` - :5 `git rev-parse --verify master^0` + :2 $(git rev-parse --verify master:file2) + :3 $(git rev-parse --verify master:file3) + :4 $(git rev-parse --verify master:file4) + :5 $(git rev-parse --verify master^0) EOF test_cmp expect marks.out ' @@ -264,8 +264,8 @@ test_expect_success 'A: verify diff' ' EOF git diff-tree -M -r master verify--import-marks >actual && compare_diff_raw expect actual && - test `git rev-parse --verify master:file2` \ - = `git rev-parse --verify verify--import-marks:copy-of-file2` + test $(git rev-parse --verify master:file2) \ + = $(git rev-parse --verify verify--import-marks:copy-of-file2) ' test_expect_success 'A: export marks with large values' ' @@ -364,7 +364,7 @@ test_expect_success 'B: accept branch name "TEMP_TAG"' ' git prune" && git fast-import <input && test -f .git/TEMP_TAG && - test `git rev-parse master` = `git rev-parse TEMP_TAG^` + test $(git rev-parse master) = $(git rev-parse TEMP_TAG^) ' test_expect_success 'B: accept empty committer' ' @@ -473,8 +473,8 @@ test_expect_success 'B: fail on invalid committer (5)' ' ### test_expect_success 'C: incremental import create pack from stdin' ' - newf=`echo hi newf | git hash-object -w --stdin` && - oldf=`git rev-parse --verify master:file2` && + newf=$(echo hi newf | git hash-object -w --stdin) && + oldf=$(git rev-parse --verify master:file2) && test_tick && cat >input <<-INPUT_END && commit refs/heads/branch @@ -499,13 +499,13 @@ test_expect_success 'C: verify pack' ' ' test_expect_success 'C: validate reuse existing blob' ' - test $newf = `git rev-parse --verify branch:file2/newf` && - test $oldf = `git rev-parse --verify branch:file2/oldf` + test $newf = $(git rev-parse --verify branch:file2/newf) && + test $oldf = $(git rev-parse --verify branch:file2/oldf) ' test_expect_success 'C: verify commit' ' cat >expect <<-EOF && - parent `git rev-parse --verify master^0` + parent $(git rev-parse --verify master^0) author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE @@ -624,7 +624,7 @@ test_expect_success 'E: verify commit' ' ### test_expect_success 'F: non-fast-forward update skips' ' - old_branch=`git rev-parse --verify branch^0` && + old_branch=$(git rev-parse --verify branch^0) && test_tick && cat >input <<-INPUT_END && commit refs/heads/branch @@ -642,7 +642,7 @@ test_expect_success 'F: non-fast-forward update skips' ' test_must_fail git fast-import <input && # branch must remain unaffected - test $old_branch = `git rev-parse --verify branch^0` + test $old_branch = $(git rev-parse --verify branch^0) ' test_expect_success 'F: verify pack' ' @@ -651,8 +651,8 @@ test_expect_success 'F: verify pack' ' test_expect_success 'F: verify other commit' ' cat >expect <<-EOF && - tree `git rev-parse branch~1^{tree}` - parent `git rev-parse branch~1` + tree $(git rev-parse branch~1^{tree}) + parent $(git rev-parse branch~1) author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE @@ -667,7 +667,7 @@ test_expect_success 'F: verify other commit' ' ### test_expect_success 'G: non-fast-forward update forced' ' - old_branch=`git rev-parse --verify branch^0` && + old_branch=$(git rev-parse --verify branch^0) && test_tick && cat >input <<-INPUT_END && commit refs/heads/branch @@ -687,8 +687,8 @@ test_expect_success 'G: verify pack' ' ' test_expect_success 'G: branch changed, but logged' ' - test $old_branch != `git rev-parse --verify branch^0` && - test $old_branch = `git rev-parse --verify branch@{1}` + test $old_branch != $(git rev-parse --verify branch^0) && + test $old_branch = $(git rev-parse --verify branch@{1}) ' ### @@ -763,7 +763,7 @@ test_expect_success 'I: export-pack-edges' ' test_expect_success 'I: verify edge list' ' cat >expect <<-EOF && - .git/objects/pack/pack-.pack: `git rev-parse --verify export-boundary` + .git/objects/pack/pack-.pack: $(git rev-parse --verify export-boundary) EOF sed -e s/pack-.*pack/pack-.pack/ edges.list >actual && test_cmp expect actual @@ -795,8 +795,8 @@ test_expect_success 'J: reset existing branch creates empty commit' ' git fast-import <input ' test_expect_success 'J: branch has 1 commit, empty tree' ' - test 1 = `git rev-list J | wc -l` && - test 0 = `git ls-tree J | wc -l` + test 1 = $(git rev-list J | wc -l) && + test 0 = $(git ls-tree J | wc -l) ' test_expect_success 'J: tag must fail on empty branch' ' @@ -838,8 +838,8 @@ test_expect_success 'K: reinit branch with from' ' git fast-import <input ' test_expect_success 'K: verify K^1 = branch^1' ' - test `git rev-parse --verify branch^1` \ - = `git rev-parse --verify K^1` + test $(git rev-parse --verify branch^1) \ + = $(git rev-parse --verify K^1) ' ### @@ -929,7 +929,7 @@ test_expect_success 'L: nested tree copy does not corrupt deltas' ' git ls-tree L2 g/b/ >tmp && cat tmp | cut -f 2 >actual && test_cmp expect actual && - git fsck `git rev-parse L2` + git fsck $(git rev-parse L2) ' ### @@ -1106,7 +1106,7 @@ test_expect_success 'N: copy dirty subdirectory' ' INPUT_END git fast-import <input && - test `git rev-parse N2^{tree}` = `git rev-parse N3^{tree}` + test $(git rev-parse N2^{tree}) = $(git rev-parse N3^{tree}) ' test_expect_success 'N: copy directory by id' ' @@ -1503,7 +1503,7 @@ test_expect_success 'O: comments are all skipped' ' INPUT_END git fast-import <input && - test `git rev-parse N3` = `git rev-parse O1` + test $(git rev-parse N3) = $(git rev-parse O1) ' test_expect_success 'O: blank lines not necessary after data commands' ' @@ -1524,7 +1524,7 @@ test_expect_success 'O: blank lines not necessary after data commands' ' INPUT_END git fast-import <input && - test `git rev-parse N3` = `git rev-parse O2` + test $(git rev-parse N3) = $(git rev-parse O2) ' test_expect_success 'O: repack before next test' ' @@ -1570,8 +1570,8 @@ test_expect_success 'O: blank lines not necessary after other commands' ' INPUT_END git fast-import <input && - test 8 = `find .git/objects/pack -type f | wc -l` && - test `git rev-parse refs/tags/O3-2nd` = `git rev-parse O3^` && + test 8 = $(find .git/objects/pack -type f | wc -l) && + test $(git rev-parse refs/tags/O3-2nd) = $(git rev-parse O3^) && git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual && test_cmp expect actual ' @@ -1631,7 +1631,7 @@ test_expect_success 'P: superproject & submodule mix' ' data <<DATAEND [submodule "sub"] path = sub - url = "`pwd`/sub" + url = "$(pwd)/sub" DATAEND commit refs/heads/subuse1 @@ -1691,7 +1691,7 @@ test_expect_success 'P: verbatim SHA gitlinks' ' data <<DATAEND [submodule "sub"] path = sub - url = "`pwd`/sub" + url = "$(pwd)/sub" DATAEND commit refs/heads/subuse2 @@ -1978,7 +1978,7 @@ test_expect_success 'Q: verify first note for third commit' ' test_expect_success 'Q: verify second notes commit' ' cat >expect <<-EOF && - parent `git rev-parse --verify refs/notes/foobar~2` + parent $(git rev-parse --verify refs/notes/foobar~2) author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE @@ -2045,7 +2045,7 @@ test_expect_success 'Q: verify third note for first commit' ' test_expect_success 'Q: verify fourth notes commit' ' cat >expect <<-EOF && - parent `git rev-parse --verify refs/notes/foobar^` + parent $(git rev-parse --verify refs/notes/foobar^) author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 66c8b0a37..b5149fde6 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -163,7 +163,7 @@ test_expect_success 'setup submodule' ' git add file && git commit -m sub_initial ) && - git submodule add "`pwd`/sub" sub && + git submodule add "$(pwd)/sub" sub && git commit -m initial && test_tick && ( @@ -377,7 +377,7 @@ test_expect_success 'full-tree re-shows unmodified files' ' test_expect_success 'set-up a few more tags for tag export tests' ' git checkout -f master && - HEAD_TREE=`git show -s --pretty=raw HEAD | grep tree | sed "s/tree //"` && + HEAD_TREE=$(git show -s --pretty=raw HEAD | grep tree | sed "s/tree //") && git tag tree_tag -m "tagging a tree" $HEAD_TREE && git tag -a tree_tag-obj -m "tagging a tree" $HEAD_TREE && git tag tag-obj_tag -m "tagging a tag" tree_tag-obj && @@ -422,7 +422,7 @@ test_expect_success 'directory becomes symlink' ' test_expect_success 'fast-export quotes pathnames' ' git init crazy-paths && (cd crazy-paths && - blob=`echo foo | git hash-object -w --stdin` && + blob=$(echo foo | git hash-object -w --stdin) && git update-index --add \ --cacheinfo 100644 $blob "$(printf "path with\\nnewline")" \ --cacheinfo 100644 $blob "path with \"quote\"" \ diff --git a/t/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh index d3a5bac75..2a0ffed87 100755 --- a/t/t9501-gitweb-standalone-http-status.sh +++ b/t/t9501-gitweb-standalone-http-status.sh @@ -100,14 +100,14 @@ test_expect_success 'snapshots: bad tree-ish id (tagged object)' ' echo object > tag-object && git add tag-object && test_tick && git commit -m "Object to be tagged" && - git tag tagged-object `git hash-object tag-object` && + git tag tagged-object $(git hash-object tag-object) && gitweb_run "p=.git;a=snapshot;h=tagged-object;sf=tgz" && grep "400 - Object is not a tree-ish" gitweb.output ' test_debug 'cat gitweb.output' test_expect_success 'snapshots: good object id' ' - ID=`git rev-parse --verify HEAD` && + ID=$(git rev-parse --verify HEAD) && gitweb_run "p=.git;a=snapshot;h=$ID;sf=tgz" && grep "Status: 200 OK" gitweb.output ' @@ -173,7 +173,7 @@ test_expect_success DATE_PARSER 'modification: snapshot if-modified-since (unmod test_debug 'cat gitweb.headers' test_expect_success DATE_PARSER 'modification: tree snapshot' ' - ID=`git rev-parse --verify HEAD^{tree}` && + ID=$(git rev-parse --verify HEAD^{tree}) && HTTP_IF_MODIFIED_SINCE="Wed, 6 Apr 2005 22:14:13 +0000" && export HTTP_IF_MODIFIED_SINCE && test_when_finished "unset HTTP_IF_MODIFIED_SINCE" && diff --git a/t/t9901-git-web--browse.sh b/t/t9901-git-web--browse.sh index b0a6bad8d..de7152f82 100755 --- a/t/t9901-git-web--browse.sh +++ b/t/t9901-git-web--browse.sh @@ -43,7 +43,7 @@ test_expect_success \ echo fake: "$@" EOF chmod +x "fake browser" && - git config browser.w3m.path "`pwd`/fake browser" && + git config browser.w3m.path "$(pwd)/fake browser" && test_web_browse w3m http://example.com/foo ' diff --git a/test-run-command.c b/test-run-command.c index 89c7de2c6..fbe0a27ef 100644 --- a/test-run-command.c +++ b/test-run-command.c @@ -10,16 +10,54 @@ #include "git-compat-util.h" #include "run-command.h" +#include "argv-array.h" +#include "strbuf.h" #include <string.h> #include <errno.h> +static int number_callbacks; +static int parallel_next(struct child_process *cp, + struct strbuf *err, + void *cb, + void **task_cb) +{ + struct child_process *d = cb; + if (number_callbacks >= 4) + return 0; + + argv_array_pushv(&cp->args, d->argv); + strbuf_addf(err, "preloaded output of a child\n"); + number_callbacks++; + return 1; +} + +static int no_job(struct child_process *cp, + struct strbuf *err, + void *cb, + void **task_cb) +{ + strbuf_addf(err, "no further jobs available\n"); + return 0; +} + +static int task_finished(int result, + struct child_process *cp, + struct strbuf *err, + void *pp_cb, + void *pp_task_cb) +{ + strbuf_addf(err, "asking for a quick stop\n"); + return 1; +} + int main(int argc, char **argv) { struct child_process proc = CHILD_PROCESS_INIT; + int jobs; if (argc < 3) return 1; - proc.argv = (const char **)argv+2; + proc.argv = (const char **)argv + 2; if (!strcmp(argv[1], "start-command-ENOENT")) { if (start_command(&proc) < 0 && errno == ENOENT) @@ -30,6 +68,21 @@ int main(int argc, char **argv) if (!strcmp(argv[1], "run-command")) exit(run_command(&proc)); + jobs = atoi(argv[2]); + proc.argv = (const char **)argv + 3; + + if (!strcmp(argv[1], "run-command-parallel")) + exit(run_processes_parallel(jobs, parallel_next, + NULL, NULL, &proc)); + + if (!strcmp(argv[1], "run-command-abort")) + exit(run_processes_parallel(jobs, parallel_next, + NULL, task_finished, &proc)); + + if (!strcmp(argv[1], "run-command-no-jobs")) + exit(run_processes_parallel(jobs, no_job, + NULL, task_finished, &proc)); + fprintf(stderr, "check usage\n"); return 1; } diff --git a/test-sha1.sh b/test-sha1.sh index 0f0bc5d02..cef4bcc86 100755 --- a/test-sha1.sh +++ b/test-sha1.sh @@ -6,13 +6,13 @@ dd if=/dev/zero bs=1048576 count=100 2>/dev/null | while read expect cnt pfx do case "$expect" in '#'*) continue ;; esac - actual=` + actual=$( { test -z "$pfx" || echo "$pfx" dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null | perl -pe 'y/\000/g/' } | ./test-sha1 $cnt - ` + ) if test "$expect" = "$actual" then echo "OK: $expect $cnt $pfx" @@ -51,14 +51,14 @@ exit while read cnt pfx do - actual=` + actual=$( { test -z "$pfx" || echo "$pfx" dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null | perl -pe 'y/\000/g/' } | sha1sum | sed -e 's/ .*//' - ` + ) echo "$actual $cnt $pfx" done <<EOF 0 diff --git a/unimplemented.sh b/unimplemented.sh index 5252de4b2..fee21d24e 100644 --- a/unimplemented.sh +++ b/unimplemented.sh @@ -1,4 +1,4 @@ #!/bin/sh -echo >&2 "fatal: git was built without support for `basename $0` (@@REASON@@)." +echo >&2 "fatal: git was built without support for $(basename $0) (@@REASON@@)." exit 128 @@ -236,8 +236,24 @@ ssize_t xread(int fd, void *buf, size_t len) len = MAX_IO_SIZE; while (1) { nr = read(fd, buf, len); - if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) - continue; + if (nr < 0) { + if (errno == EINTR) + continue; + if (errno == EAGAIN || errno == EWOULDBLOCK) { + struct pollfd pfd; + pfd.events = POLLIN; + pfd.fd = fd; + /* + * it is OK if this poll() failed; we + * want to leave this infinite loop + * only when read() returns with + * success, or an expected failure, + * which would be checked by the next + * call to read(2). + */ + poll(&pfd, 1, -1); + } + } return nr; } } @@ -375,6 +391,19 @@ FILE *xfdopen(int fd, const char *mode) return stream; } +FILE *fopen_for_writing(const char *path) +{ + FILE *ret = fopen(path, "w"); + + if (!ret && errno == EPERM) { + if (!unlink(path)) + ret = fopen(path, "w"); + else + errno = EPERM; + } + return ret; +} + int xmkstemp(char *template) { int fd; |