diff options
82 files changed, 1322 insertions, 582 deletions
diff --git a/Documentation/RelNotes-1.7.0.7.txt b/Documentation/RelNotes-1.7.0.7.txt new file mode 100644 index 0000000000..d0cb7ca7e2 --- /dev/null +++ b/Documentation/RelNotes-1.7.0.7.txt @@ -0,0 +1,16 @@ +Git v1.7.0.7 Release Notes +========================== + +Fixes since v1.7.0.6 +-------------------- + + * "make NO_CURL=NoThanks install" was broken. + + * An overlong line after ".gitdir: " in a git file caused out of bounds + access to an array on the stack. + + * "git config --path conf.var" to attempt to expand a variable conf.var + that uses "~/" short-hand segfaulted when $HOME environment variable + was not set. + +And other minor fixes and documentation updates. diff --git a/Documentation/RelNotes-1.7.1.2.txt b/Documentation/RelNotes-1.7.1.2.txt index 46b6a960c7..61ba14e262 100644 --- a/Documentation/RelNotes-1.7.1.2.txt +++ b/Documentation/RelNotes-1.7.1.2.txt @@ -17,3 +17,12 @@ Fixes since v1.7.1.1 * "git rev-parse --parseopt --stop-at-non-option" did not stop at non option when --keep-dashdash was in effect. + + * An overlong line after ".gitdir: " in a git file caused out of bounds + access to an array on the stack. + + * "git config --path conf.var" to attempt to expand a variable conf.var + that uses "~/" short-hand segfaulted when $HOME environment variable + was not set. + +And other minor fixes and documentation updates. diff --git a/Documentation/RelNotes-1.7.2.1.txt b/Documentation/RelNotes-1.7.2.1.txt new file mode 100644 index 0000000000..1103c47a4f --- /dev/null +++ b/Documentation/RelNotes-1.7.2.1.txt @@ -0,0 +1,25 @@ +Git v1.7.2.1 Release Notes +========================== + +Fixes since v1.7.2 +------------------ + + * "git instaweb" wasn't useful when your Apache was installed under a + name other than apache2 (e.g. "httpd"). + + * Similarly, "git web--browse" (invoked by "git help -w") learned that + chrome browser is sometimes called google-chrome. + + * An overlong line after ".gitdir: " in a git file caused out of bounds + access to an array on the stack. + + * "git config --path conf.var" to attempt to expand a variable conf.var + that uses "~/" short-hand segfaulted when $HOME environment variable + was not set. + + * Documentation on Cygwin failed to build. + + * The error message from "git pull blarg" when 'blarg' is an unknown + remote name has been improved. + +And other minor fixes and documentation updates. diff --git a/Documentation/RelNotes-1.7.2.2.txt b/Documentation/RelNotes-1.7.2.2.txt new file mode 100644 index 0000000000..71eb6a8b0a --- /dev/null +++ b/Documentation/RelNotes-1.7.2.2.txt @@ -0,0 +1,22 @@ +Git v1.7.2.2 Release Notes +========================== + +Fixes since v1.7.2.1 +-------------------- + + * Object transfer over smart http transport deadlocked the client when + the remote HTTP server returned a failure, instead of erroring it out. + + * git-gui honors custom textconv filters when showing diff and blame; + + * git diff --relative=subdir (without the necessary trailing /) did not + work well; + + * "git diff-files -p --submodule" was recently broken; + + * "git checkout -b n ':/token'" did not work; + + * "git index-pack" (hence "git fetch/clone/pull/push") enabled the object + replacement machinery by mistake (it never should have); + +And other minor fixes and documentation updates. diff --git a/Documentation/RelNotes-1.7.2.txt b/Documentation/RelNotes-1.7.2.txt index f24b3876af..15cf01178c 100644 --- a/Documentation/RelNotes-1.7.2.txt +++ b/Documentation/RelNotes-1.7.2.txt @@ -1,5 +1,5 @@ -Git v1.7.2 Release Notes (draft) -================================ +Git v1.7.2 Release Notes +======================== Updates since v1.7.1 -------------------- @@ -123,6 +123,8 @@ Updates since v1.7.1 * The test harness has been updated to produce TAP-friendly output. + * Many documentation improvement patches are also included. + Fixes since v1.7.1 ------------------ @@ -147,9 +149,3 @@ release, unless otherwise noted. * "git read-tree -m A B" used to switch to branch B while retaining local changes added an incorrect cache-tree information (b1f47514). - --- -exec >/var/tmp/1 -O=v1.7.2-rc2-17-gc9a9766 -echo O=$(git describe HEAD) -git shortlog --no-merges HEAD ^maint ^$O diff --git a/Documentation/config.txt b/Documentation/config.txt index e15c6123f4..7fffee7e3d 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1560,6 +1560,10 @@ receive.denyDeletes:: If set to true, git-receive-pack will deny a ref update that deletes the ref. Use this to prevent such a ref deletion via a push. +receive.denyDeleteCurrent:: + If set to true, git-receive-pack will deny a ref update that + deletes the currently checked out branch of a non-bare repository. + receive.denyCurrentBranch:: If set to true or "refuse", git-receive-pack will deny a ref update to the currently checked out branch of a non-bare repository. diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 2371262b10..eecedaab6e 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -206,10 +206,29 @@ endif::git-format-patch[] the diff-patch output format. Non default number of digits can be specified with `--abbrev=<n>`. --B:: - Break complete rewrite changes into pairs of delete and create. - --M:: +-B[<n>][/<m>]:: + Break complete rewrite changes into pairs of delete and + create. This serves two purposes: ++ +It affects the way a change that amounts to a total rewrite of a file +not as a series of deletion and insertion mixed together with a very +few lines that happen to match textually as the context, but as a +single deletion of everything old followed by a single insertion of +everything new, and the number `m` controls this aspect of the -B +option (defaults to 60%). `-B/70%` specifies that less than 30% of the +original should remain in the result for git to consider it a total +rewrite (i.e. otherwise the resulting patch will be a series of +deletion and insertion mixed together with context lines). ++ +When used with -M, a totally-rewritten file is also considered as the +source of a rename (usually -M only considers a file that disappeared +as the source of a rename), and the number `n` controls this aspect of +the -B option (defaults to 50%). `-B20%` specifies that a change with +addition and deletion compared to 20% or more of the file's size are +eligible for being picked up as a possible source of a rename to +another file. + +-M[<n>]:: ifndef::git-log[] Detect renames. endif::git-log[] @@ -218,9 +237,15 @@ ifdef::git-log[] For following files across renames while traversing history, see `--follow`. endif::git-log[] + If `n` is specified, it is a is a threshold on the similarity + index (i.e. amount of addition/deletions compared to the + file's size). For example, `-M90%` means git should consider a + delete/add pair to be a rename if more than 90% of the file + hasn't changed. --C:: +-C[<n>]:: Detect copies as well as renames. See also `--find-copies-harder`. + If `n` is specified, it has the same meaning as for `-M<n>`. ifndef::git-format-patch[] --diff-filter=[ACDMRTUXB*]:: diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index 8463439ac5..4a74b23d40 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -26,6 +26,10 @@ with the `--cache` option the patch is only applied to the index. Without these options, the command applies the patch only to files, and does not require them to be in a git repository. +This command applies the patch but does not create a commit. Use +linkgit:git-am[1] to create commits from patches generated by +linkgit:git-format-patch[1] and/or received by email. + OPTIONS ------- <patch>...:: @@ -242,6 +246,12 @@ If `--index` is not specified, then the submodule commits in the patch are ignored and only the absence or presence of the corresponding subdirectory is checked and (if possible) updated. + +SEE ALSO +-------- +linkgit:git-am[1]. + + Author ------ Written by Linus Torvalds <torvalds@osdl.org> diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index e970664fe1..c213bdbdc5 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -55,6 +55,9 @@ OPTIONS paths. With this, the full diff is shown for commits that touch the specified paths; this means that "<path>..." limits only commits, and doesn't limit diff for those commits. ++ +Note that this affects all diff-based output types, e.g. those +produced by --stat etc. --log-size:: Before the log message print out its size in bytes. Intended diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt index 3521637b58..bd919f2dfd 100644 --- a/Documentation/git-ls-files.txt +++ b/Documentation/git-ls-files.txt @@ -106,8 +106,16 @@ OPTIONS with `-s` or `-u` options does not make any sense. -t:: - Identify the file status with the following tags (followed by - a space) at the start of each line: + This feature is semi-deprecated. For scripting purpose, + linkgit:git-status[1] `--porcelain` and + linkgit:git-diff-files[1] `--name-status` are almost always + superior alternatives, and users should look at + linkgit:git-status[1] `--short` or linkgit:git-diff[1] + `--name-status` for more user-friendly alternatives. ++ +This option identifies the file status with the following tags (followed by +a space) at the start of each line: + H:: cached S:: skip-worktree M:: unmerged diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt index 5540af5d16..2981d8c5ef 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.txt @@ -129,10 +129,12 @@ OPTIONS is taken to be in `refs/notes/` if it is not qualified. -n:: +--dry-run:: Do not remove anything; just report the object names whose notes would be removed. -v:: +--verbose:: Report all object names whose notes are removed. diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt index 15cfb7a8dc..4d673a5686 100644 --- a/Documentation/git-prune.txt +++ b/Documentation/git-prune.txt @@ -31,10 +31,12 @@ OPTIONS ------- -n:: +--dry-run:: Do not remove anything; just report what it would remove. -v:: +--verbose:: Report all removed objects. \--:: diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt index ab4de10358..c50f7dcb89 100644 --- a/Documentation/git-pull.txt +++ b/Documentation/git-pull.txt @@ -8,29 +8,72 @@ git-pull - Fetch from and merge with another repository or a local branch SYNOPSIS -------- -'git pull' <options> <repository> <refspec>... +'git pull' [options] [<repository> [<refspec>...]] DESCRIPTION ----------- -Runs 'git fetch' with the given parameters, and calls 'git merge' -to merge the retrieved head(s) into the current branch. -With `--rebase`, calls 'git rebase' instead of 'git merge'. -Note that you can use `.` (current directory) as the -<repository> to pull from the local repository -- this is useful -when merging local branches into the current branch. +Incorporates changes from a remote repository into the current +branch. In its default mode, `git pull` is shorthand for +`git fetch` followed by `git merge FETCH_HEAD`. -Also note that options meant for 'git pull' itself and underlying -'git merge' must be given before the options meant for 'git fetch'. +More precisely, 'git pull' runs 'git fetch' with the given +parameters and calls 'git merge' to merge the retrieved branch +heads into the current branch. +With `--rebase`, it runs 'git rebase' instead of 'git merge'. -*Warning*: Running 'git pull' (actually, the underlying 'git merge') +<repository> should be the name of a remote repository as +passed to linkgit:git-fetch[1]. <refspec> can name an +arbitrary remote ref (for example, the name of a tag) or even +a collection of refs with corresponding remote tracking branches +(e.g., refs/heads/*:refs/remotes/origin/*), but usually it is +the name of a branch in the remote repository. + +Default values for <repository> and <branch> are read from the +"remote" and "merge" configuration for the current branch +as set by linkgit:git-branch[1] `--track`. + +Assume the following history exists and the current branch is +"`master`": + +------------ + A---B---C master on origin + / + D---E---F---G master +------------ + +Then "`git pull`" will fetch and replay the changes from the remote +`master` branch since it diverged from the local `master` (i.e., `E`) +until its current commit (`C`) on top of `master` and record the +result in a new commit along with the names of the two parent commits +and a log message from the user describing the changes. + +------------ + A---B---C remotes/origin/master + / \ + D---E---F---G---H master +------------ + +See linkgit:git-merge[1] for details, including how conflicts +are presented and handled. + +In git 1.7.0 or later, to cancel a conflicting merge, use +`git reset --merge`. *Warning*: In older versions of git, running 'git pull' with uncommitted changes is discouraged: while possible, it leaves you -in a state that is hard to back out of in the case of a conflict. +in a state that may be hard to back out of in the case of a conflict. + +If any of the remote changes overlap with local uncommitted changes, +the merge will be automatically cancelled and the work tree untouched. +It is generally best to get any local changes in working order before +pulling or stash them away with linkgit:git-stash[1]. OPTIONS ------- +Options meant for 'git pull' itself and the underlying 'git merge' +must be given before the options meant for 'git fetch'. + -q:: --quiet:: This is passed to both underlying git-fetch to squelch reporting of diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index b68abff28a..658ff2ff67 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -200,16 +200,29 @@ summary:: For a successfully pushed ref, the summary shows the old and new values of the ref in a form suitable for using as an argument to `git log` (this is `<old>..<new>` in most cases, and - `<old>...<new>` for forced non-fast-forward updates). For a - failed update, more details are given for the failure. - The string `rejected` indicates that git did not try to send the - ref at all (typically because it is not a fast-forward). The - string `remote rejected` indicates that the remote end refused - the update; this rejection is typically caused by a hook on the - remote side. The string `remote failure` indicates that the - remote end did not report the successful update of the ref - (perhaps because of a temporary error on the remote side, a - break in the network connection, or other transient error). + `<old>...<new>` for forced non-fast-forward updates). ++ +For a failed update, more details are given: ++ +-- +rejected:: + Git did not try to send the ref at all, typically because it + is not a fast-forward and you did not force the update. + +remote rejected:: + The remote end refused the update. Usually caused by a hook + on the remote side, or because the remote repository has one + of the following safety options in effect: + `receive.denyCurrentBranch` (for pushes to the checked out + branch), `receive.denyNonFastForwards` (for forced + non-fast-forward updates), `receive.denyDeletes` or + `receive.denyDeleteCurrent`. See linkgit:git-config[1]. + +remote failure:: + The remote end did not report the successful update of the ref, + perhaps because of a temporary error on the remote side, a + break in the network connection, or other transient error. +-- from:: The name of the local ref being pushed, minus its diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index f6037c4f6a..2e78da448f 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -412,6 +412,13 @@ turn `core.sparseCheckout` on in order to have sparse checkout support. +BUGS +---- +In order to match a directory with $GIT_DIR/info/sparse-checkout, +trailing slash must be used. The form without trailing slash, while +works with .gitignore, does not work with sparse checkout. + + SEE ALSO -------- linkgit:git-write-tree[1]; linkgit:git-ls-files[1]; diff --git a/Documentation/git-request-pull.txt b/Documentation/git-request-pull.txt index 19335fddae..400f61f6e2 100644 --- a/Documentation/git-request-pull.txt +++ b/Documentation/git-request-pull.txt @@ -7,7 +7,7 @@ git-request-pull - Generates a summary of pending changes SYNOPSIS -------- -'git request-pull' <start> <url> [<end>] +'git request-pull' [-p] <start> <url> [<end>] DESCRIPTION ----------- @@ -17,6 +17,9 @@ the given URL in the generated summary. OPTIONS ------- +-p:: + Show patch text + <start>:: Commit to start at. diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index a9d287f629..9cf31485fe 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -8,40 +8,50 @@ git-reset - Reset current HEAD to the specified state SYNOPSIS -------- [verse] -'git reset' [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>] 'git reset' [-q] [<commit>] [--] <paths>... 'git reset' --patch [<commit>] [--] [<paths>...] +'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>] DESCRIPTION ----------- -Sets the current head to the specified commit and optionally resets the -index and working tree to match. - -This command is useful if you notice some small error in a recent -commit (or set of commits) and want to redo that part without showing -the undo in the history. - -If you want to undo a commit other than the latest on a branch, -linkgit:git-revert[1] is your friend. - -The second and third forms with 'paths' and/or --patch are used to -revert selected paths in the index from a given commit, without moving -HEAD. - +In the first and second form, copy entries from <commit> to the index. +In the third form, set the current branch to <commit>, optionally +modifying index and worktree to match. The <commit> defaults to HEAD +in all forms. + +'git reset' [-q] [<commit>] [--] <paths>...:: + This form resets the index entries for all <paths> to their + state at the <commit>. (It does not affect the worktree, nor + the current branch.) ++ +This means that `git reset <paths>` is the opposite of `git add +<paths>`. -OPTIONS -------- ---mixed:: - Resets the index but not the working tree (i.e., the changed files - are preserved but not marked for commit) and reports what has not - been updated. This is the default action. +'git reset' --patch|-p [<commit>] [--] [<paths>...]:: + Interactively select hunks in the difference between the index + and <commit> (defaults to HEAD). The chosen hunks are applied + in reverse to the index. ++ +This means that `git reset -p` is the opposite of `git add -p` (see +linkgit:git-add[1]). +'git reset' [--<mode>] [<commit>]:: + This form points the current branch to <commit> and then + updates index and working tree according to <mode>, which must + be one of the following: ++ +-- --soft:: Does not touch the index file nor the working tree at all, but requires them to be in a good order. This leaves all your changed files "Changes to be committed", as 'git status' would put it. +--mixed:: + Resets the index but not the working tree (i.e., the changed files + are preserved but not marked for commit) and reports what has not + been updated. This is the default action. + --hard:: Matches the working tree and index to that of the tree being switched to. Any changes to tracked files in the working tree @@ -59,132 +69,46 @@ OPTIONS the given commit. If a file that is different between the current commit and the given commit has local changes, reset is aborted. +-- --p:: ---patch:: - Interactively select hunks in the difference between the index - and <commit> (defaults to HEAD). The chosen hunks are applied - in reverse to the index. -+ -This means that `git reset -p` is the opposite of `git add -p` (see -linkgit:git-add[1]). +If you want to undo a commit other than the latest on a branch, +linkgit:git-revert[1] is your friend. + + +OPTIONS +------- -q:: --quiet:: Be quiet, only report errors. -<commit>:: - Commit to make the current HEAD. If not given defaults to HEAD. - -DISCUSSION ----------- -The tables below show what happens when running: - ----------- -git reset --option target ----------- - -to reset the HEAD to another commit (`target`) with the different -reset options depending on the state of the files. - -In these tables, A, B, C and D are some different states of a -file. For example, the first line of the first table means that if a -file is in state A in the working tree, in state B in the index, in -state C in HEAD and in state D in the target, then "git reset --soft -target" will put the file in state A in the working tree, in state B -in the index and in state D in HEAD. - - working index HEAD target working index HEAD - ---------------------------------------------------- - A B C D --soft A B D - --mixed A D D - --hard D D D - --merge (disallowed) - --keep (disallowed) - - working index HEAD target working index HEAD - ---------------------------------------------------- - A B C C --soft A B C - --mixed A C C - --hard C C C - --merge (disallowed) - --keep A C C - - working index HEAD target working index HEAD - ---------------------------------------------------- - B B C D --soft B B D - --mixed B D D - --hard D D D - --merge D D D - --keep (disallowed) - - working index HEAD target working index HEAD - ---------------------------------------------------- - B B C C --soft B B C - --mixed B C C - --hard C C C - --merge C C C - --keep B C C - - working index HEAD target working index HEAD - ---------------------------------------------------- - B C C D --soft B C D - --mixed B D D - --hard D D D - --merge (disallowed) - --keep (disallowed) - - working index HEAD target working index HEAD - ---------------------------------------------------- - B C C C --soft B C C - --mixed B C C - --hard C C C - --merge B C C - --keep B C C - -"reset --merge" is meant to be used when resetting out of a conflicted -merge. Any mergy operation guarantees that the work tree file that is -involved in the merge does not have local change wrt the index before -it starts, and that it writes the result out to the work tree. So if -we see some difference between the index and the target and also -between the index and the work tree, then it means that we are not -resetting out from a state that a mergy operation left after failing -with a conflict. That is why we disallow --merge option in this case. - -"reset --keep" is meant to be used when removing some of the last -commits in the current branch while keeping changes in the working -tree. If there could be conflicts between the changes in the commit we -want to remove and the changes in the working tree we want to keep, -the reset is disallowed. That's why it is disallowed if there are both -changes between the working tree and HEAD, and between HEAD and the -target. To be safe, it is also disallowed when there are unmerged -entries. - -The following tables show what happens when there are unmerged -entries: - - working index HEAD target working index HEAD - ---------------------------------------------------- - X U A B --soft (disallowed) - --mixed X B B - --hard B B B - --merge B B B - --keep (disallowed) - - working index HEAD target working index HEAD - ---------------------------------------------------- - X U A A --soft (disallowed) - --mixed X A A - --hard A A A - --merge A A A - --keep (disallowed) - -X means any state and U means an unmerged index. - -Examples +EXAMPLES -------- +Undo add:: ++ +------------ +$ edit <1> +$ git add frotz.c filfre.c +$ mailx <2> +$ git reset <3> +$ git pull git://info.example.com/ nitfol <4> +------------ ++ +<1> You are happily working on something, and find the changes +in these files are in good order. You do not want to see them +when you run "git diff", because you plan to work on other files +and changes with these files are distracting. +<2> Somebody asks you to pull, and the changes sounds worthy of merging. +<3> However, you already dirtied the index (i.e. your index does +not match the HEAD commit). But you know the pull you are going +to make does not affect frotz.c nor filfre.c, so you revert the +index changes for these two files. Your changes in working tree +remain there. +<4> Then you can pull and merge, leaving frotz.c and filfre.c +changes still in the working tree. + Undo a commit and redo:: + ------------ @@ -204,19 +128,6 @@ edit the message further, you can give -C option instead. + See also the --amend option to linkgit:git-commit[1]. -Undo commits permanently:: -+ ------------- -$ git commit ... -$ git reset --hard HEAD~3 <1> ------------- -+ -<1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad -and you do not want to ever see them again. Do *not* do this if -you have already given these commits to somebody else. (See the -"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for -the implications of doing so.) - Undo a commit, making it a topic branch:: + ------------ @@ -232,28 +143,18 @@ current HEAD. <2> Rewind the master branch to get rid of those three commits. <3> Switch to "topic/wip" branch and keep working. -Undo add:: +Undo commits permanently:: + ------------ -$ edit <1> -$ git add frotz.c filfre.c -$ mailx <2> -$ git reset <3> -$ git pull git://info.example.com/ nitfol <4> +$ git commit ... +$ git reset --hard HEAD~3 <1> ------------ + -<1> You are happily working on something, and find the changes -in these files are in good order. You do not want to see them -when you run "git diff", because you plan to work on other files -and changes with these files are distracting. -<2> Somebody asks you to pull, and the changes sounds worthy of merging. -<3> However, you already dirtied the index (i.e. your index does -not match the HEAD commit). But you know the pull you are going -to make does not affect frotz.c nor filfre.c, so you revert the -index changes for these two files. Your changes in working tree -remain there. -<4> Then you can pull and merge, leaving frotz.c and filfre.c -changes still in the working tree. +<1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad +and you do not want to ever see them again. Do *not* do this if +you have already given these commits to somebody else. (See the +"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for +the implications of doing so.) Undo a merge or pull:: + @@ -376,6 +277,114 @@ $ git reset --keep start <3> <3> But you can use "reset --keep" to remove the unwanted commit after you switched to "branch2". + +DISCUSSION +---------- + +The tables below show what happens when running: + +---------- +git reset --option target +---------- + +to reset the HEAD to another commit (`target`) with the different +reset options depending on the state of the files. + +In these tables, A, B, C and D are some different states of a +file. For example, the first line of the first table means that if a +file is in state A in the working tree, in state B in the index, in +state C in HEAD and in state D in the target, then "git reset --soft +target" will put the file in state A in the working tree, in state B +in the index and in state D in HEAD. + + working index HEAD target working index HEAD + ---------------------------------------------------- + A B C D --soft A B D + --mixed A D D + --hard D D D + --merge (disallowed) + --keep (disallowed) + + working index HEAD target working index HEAD + ---------------------------------------------------- + A B C C --soft A B C + --mixed A C C + --hard C C C + --merge (disallowed) + --keep A C C + + working index HEAD target working index HEAD + ---------------------------------------------------- + B B C D --soft B B D + --mixed B D D + --hard D D D + --merge D D D + --keep (disallowed) + + working index HEAD target working index HEAD + ---------------------------------------------------- + B B C C --soft B B C + --mixed B C C + --hard C C C + --merge C C C + --keep B C C + + working index HEAD target working index HEAD + ---------------------------------------------------- + B C C D --soft B C D + --mixed B D D + --hard D D D + --merge (disallowed) + --keep (disallowed) + + working index HEAD target working index HEAD + ---------------------------------------------------- + B C C C --soft B C C + --mixed B C C + --hard C C C + --merge B C C + --keep B C C + +"reset --merge" is meant to be used when resetting out of a conflicted +merge. Any mergy operation guarantees that the work tree file that is +involved in the merge does not have local change wrt the index before +it starts, and that it writes the result out to the work tree. So if +we see some difference between the index and the target and also +between the index and the work tree, then it means that we are not +resetting out from a state that a mergy operation left after failing +with a conflict. That is why we disallow --merge option in this case. + +"reset --keep" is meant to be used when removing some of the last +commits in the current branch while keeping changes in the working +tree. If there could be conflicts between the changes in the commit we +want to remove and the changes in the working tree we want to keep, +the reset is disallowed. That's why it is disallowed if there are both +changes between the working tree and HEAD, and between HEAD and the +target. To be safe, it is also disallowed when there are unmerged +entries. + +The following tables show what happens when there are unmerged +entries: + + working index HEAD target working index HEAD + ---------------------------------------------------- + X U A B --soft (disallowed) + --mixed X B B + --hard B B B + --merge B B B + --keep (disallowed) + + working index HEAD target working index HEAD + ---------------------------------------------------- + X U A A --soft (disallowed) + --mixed X A A + --hard A A A + --merge A A A + --keep (disallowed) + +X means any state and U means an unmerged index. + + Author ------ Written by Junio C Hamano <gitster@pobox.com> and Linus Torvalds <torvalds@osdl.org> diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 0727f431c6..be4c053360 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -184,10 +184,13 @@ scripts the same facilities C builtins have. It works as an option normalizer (e.g. splits single switches aggregate values), a bit like `getopt(1)` does. It takes on the standard input the specification of the options to parse and -understand, and echoes on the standard output a line suitable for `sh(1)` `eval` +understand, and echoes on the standard output a string suitable for `sh(1)` `eval` to replace the arguments with normalized ones. In case of error, it outputs usage on the standard error stream, and exits with code 129. +Note: Make sure you quote the result when passing it to `eval`. See +below for an example. + Input Format ~~~~~~~~~~~~ @@ -244,7 +247,7 @@ bar= some cool option --bar with an argument An option group Header C? option C with an optional argument" -eval `echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?` +eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)" ------------ SQ-QUOTE diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.txt index 3f9d9c6db3..75780d7d63 100644 --- a/Documentation/git-show-ref.txt +++ b/Documentation/git-show-ref.txt @@ -163,9 +163,15 @@ flag, so you can do to get a listing of all tags together with what they dereference. +FILES +----- +`.git/refs/*`, `.git/packed-refs` + SEE ALSO -------- -linkgit:git-ls-remote[1] +linkgit:git-ls-remote[1], +linkgit:git-update-ref[1], +linkgit:gitrepository-layout[5] AUTHORS ------- diff --git a/Documentation/git.txt b/Documentation/git.txt index 12066ab3fc..531789321c 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -44,15 +44,24 @@ unreleased) version of git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.7.1.1/git.html[documentation for release 1.7.1.1] +* link:v1.7.2.2/git.html[documentation for release 1.7.2.2] * release notes for + link:RelNotes-1.7.2.2.txt[1.7.2.2], + link:RelNotes-1.7.2.1.txt[1.7.2.1], + link:RelNotes-1.7.2.txt[1.7.2]. + +* link:v1.7.1.2/git.html[documentation for release 1.7.1.2] + +* release notes for + link:RelNotes-1.7.1.2.txt[1.7.1.2], link:RelNotes-1.7.1.1.txt[1.7.1.1], link:RelNotes-1.7.1.txt[1.7.1]. -* link:v1.7.0.6/git.html[documentation for release 1.7.0.6] +* link:v1.7.0.7/git.html[documentation for release 1.7.0.7] * release notes for + link:RelNotes-1.7.0.7.txt[1.7.0.7], link:RelNotes-1.7.0.6.txt[1.7.0.6], link:RelNotes-1.7.0.5.txt[1.7.0.5], link:RelNotes-1.7.0.4.txt[1.7.0.4], @@ -719,6 +728,13 @@ The documentation for git suite was started by David Greaves <david@dgreaves.com>, and later enhanced greatly by the contributors on the git-list <git@vger.kernel.org>. +Reporting Bugs +-------------- + +Report bugs to the Git mailing list <git@vger.kernel.org> where the +development and maintenance is primarily done. You do not have to be +subscribed to the list to send a message there. + SEE ALSO -------- linkgit:gittutorial[7], linkgit:gittutorial-2[7], diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt index d78e121c76..9b6f3899ec 100644 --- a/Documentation/pretty-options.txt +++ b/Documentation/pretty-options.txt @@ -1,5 +1,5 @@ --pretty[='<format>']:: ---format[='<format>']:: +--format='<format>':: Pretty-print the contents of the commit logs in a given format, where '<format>' can be one of 'oneline', 'short', 'medium', diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index e45513dee9..2c4f44bfb6 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.7.1.GIT +DEF_VER=v1.7.2.2 LF=' ' @@ -157,3 +157,36 @@ Issues of note: It has been reported that docbook-xsl version 1.72 and 1.73 are buggy; 1.72 misformats manual pages for callouts, and 1.73 needs the patch in contrib/patches/docbook-xsl-manpages-charmap.patch + + Users attempting to build the documentation on Cygwin may need to ensure + that the /etc/xml/catalog file looks something like this: + + <?xml version="1.0"?> + <!DOCTYPE catalog PUBLIC + "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" + "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd" + > + <catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"> + <rewriteURI + uriStartString = "http://docbook.sourceforge.net/release/xsl/current" + rewritePrefix = "/usr/share/sgml/docbook/xsl-stylesheets" + /> + <rewriteURI + uriStartString="http://www.oasis-open.org/docbook/xml/4.5" + rewritePrefix="/usr/share/sgml/docbook/xml-dtd-4.5" + /> + </catalog> + + This can be achieved with the following two xmlcatalog commands: + + xmlcatalog --noout \ + --add rewriteURI \ + http://docbook.sourceforge.net/release/xsl/current \ + /usr/share/sgml/docbook/xsl-stylesheets \ + /etc/xml/catalog + + xmlcatalog --noout \ + --add rewriteURI \ + http://www.oasis-open.org/docbook/xml/4.5/xsl/current \ + /usr/share/sgml/docbook/xml-dtd-4.5 \ + /etc/xml/catalog @@ -1854,8 +1854,9 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h builtin/commit.o builtin/revert.o wt-status.o: wt-status.h builtin/tar-tree.o archive-tar.o: tar.h builtin/pack-objects.o: thread-utils.h +connect.o transport.o http-backend.o: url.h http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h -http.o http-walker.o http-push.o remote-curl.o: http.h +http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h xdiff-interface.o $(XDIFF_OBJS): \ xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \ @@ -2075,10 +2076,19 @@ endif bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \ execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \ { test "$$bindir/" = "$$execdir/" || \ - { $(RM) "$$execdir/git$X" && \ + for p in git$X $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \ + $(RM) "$$execdir/$$p" && \ test -z "$(NO_CROSS_DIRECTORY_HARDLINKS)" && \ - ln "$$bindir/git$X" "$$execdir/git$X" 2>/dev/null || \ - cp "$$bindir/git$X" "$$execdir/git$X"; } ; } && \ + ln "$$bindir/$$p" "$$execdir/$$p" 2>/dev/null || \ + cp "$$bindir/$$p" "$$execdir/$$p" || exit; \ + done; \ + } && \ + for p in $(filter $(install_bindir_programs),$(BUILT_INS)); do \ + $(RM) "$$bindir/$$p" && \ + ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \ + ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \ + cp "$$bindir/git$X" "$$bindir/$$p" || exit; \ + done && \ for p in $(BUILT_INS); do \ $(RM) "$$execdir/$$p" && \ ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \ @@ -2254,6 +2264,7 @@ check-docs:: documented,gitglossary | \ documented,githooks | \ documented,gitrepository-layout | \ + documented,gitrevisions | \ documented,gittutorial | \ documented,gittutorial-2 | \ documented,git-bisect-lk2009 | \ @@ -1 +1 @@ -Documentation/RelNotes-1.7.2.txt
\ No newline at end of file +Documentation/RelNotes-1.7.2.2.txt
\ No newline at end of file @@ -7,9 +7,9 @@ #define say1(a,b) fprintf(stderr, a, b) #define say2(a,b,c) fprintf(stderr, a, b, c) #else -#define say(a) do {} while(0) -#define say1(a,b) do {} while(0) -#define say2(a,b,c) do {} while(0) +#define say(a) do { /* nothing */ } while (0) +#define say1(a,b) do { /* nothing */ } while (0) +#define say2(a,b,c) do { /* nothing */ } while (0) #endif static const char en85[] = { diff --git a/builtin/apply.c b/builtin/apply.c index 12ef9ea8af..f38c1f7b88 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -2979,8 +2979,7 @@ static void build_fake_ancestor(struct patch *list, const char *filename) else if (get_sha1(patch->old_sha1_prefix, sha1)) /* git diff has no index line for mode/type changes */ if (!patch->lines_added && !patch->lines_deleted) { - if (get_current_sha1(patch->new_name, sha1) || - get_current_sha1(patch->old_name, sha1)) + if (get_current_sha1(patch->old_name, sha1)) die("mode change for %s, which is not " "in current HEAD", name); sha1_ptr = sha1; diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c index b106c65d80..ae3f28115a 100644 --- a/builtin/check-ref-format.c +++ b/builtin/check-ref-format.c @@ -33,28 +33,38 @@ static void collapse_slashes(char *dst, const char *src) *dst = '\0'; } +static int check_ref_format_branch(const char *arg) +{ + struct strbuf sb = STRBUF_INIT; + int nongit; + + setup_git_directory_gently(&nongit); + if (strbuf_check_branch_ref(&sb, arg)) + die("'%s' is not a valid branch name", arg); + printf("%s\n", sb.buf + 11); + return 0; +} + +static int check_ref_format_print(const char *arg) +{ + char *refname = xmalloc(strlen(arg) + 1); + + if (check_ref_format(arg)) + return 1; + collapse_slashes(refname, arg); + printf("%s\n", refname); + return 0; +} + int cmd_check_ref_format(int argc, const char **argv, const char *prefix) { if (argc == 2 && !strcmp(argv[1], "-h")) usage(builtin_check_ref_format_usage); - if (argc == 3 && !strcmp(argv[1], "--branch")) { - struct strbuf sb = STRBUF_INIT; - - if (strbuf_check_branch_ref(&sb, argv[2])) - die("'%s' is not a valid branch name", argv[2]); - printf("%s\n", sb.buf + 11); - exit(0); - } - if (argc == 3 && !strcmp(argv[1], "--print")) { - char *refname = xmalloc(strlen(argv[2]) + 1); - - if (check_ref_format(argv[2])) - exit(1); - collapse_slashes(refname, argv[2]); - printf("%s\n", refname); - exit(0); - } + if (argc == 3 && !strcmp(argv[1], "--branch")) + return check_ref_format_branch(argv[2]); + if (argc == 3 && !strcmp(argv[1], "--print")) + return check_ref_format_print(argv[2]); if (argc != 2) usage(builtin_check_ref_format_usage); return !!check_ref_format(argv[1]); diff --git a/builtin/commit.c b/builtin/commit.c index a78dbd83bf..2bb30c0e80 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -147,7 +147,7 @@ static struct option builtin_commit_options[] = { "terminate entries with NUL"), OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"), OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"), - { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, + { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, /* end commit contents options */ { OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL, diff --git a/builtin/fetch.c b/builtin/fetch.c index 6eb1dfea09..1b67f5fda5 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -845,7 +845,8 @@ static int fetch_one(struct remote *remote, int argc, const char **argv) int exit_code; if (!remote) - die("Where do you want to fetch from today?"); + die("No remote repository specified. Please, specify either a URL or a\n" + "remote name from which new revisions should be fetched."); transport = transport_get(remote, NULL); transport_set_verbosity(transport, verbosity, progress); diff --git a/builtin/help.c b/builtin/help.c index a9836b00ae..61ff79839b 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -120,7 +120,7 @@ static void exec_woman_emacs(const char *path, const char *page) if (!path) path = "emacsclient"; strbuf_addf(&man_page, "(woman \"%s\")", page); - execlp(path, "emacsclient", "-e", man_page.buf, NULL); + execlp(path, "emacsclient", "-e", man_page.buf, (char *)NULL); warning("failed to exec '%s': %s", path, strerror(errno)); } } @@ -148,7 +148,7 @@ static void exec_man_konqueror(const char *path, const char *page) } else path = "kfmclient"; strbuf_addf(&man_page, "man:%s(1)", page); - execlp(path, filename, "newTab", man_page.buf, NULL); + execlp(path, filename, "newTab", man_page.buf, (char *)NULL); warning("failed to exec '%s': %s", path, strerror(errno)); } } @@ -157,7 +157,7 @@ static void exec_man_man(const char *path, const char *page) { if (!path) path = "man"; - execlp(path, "man", page, NULL); + execlp(path, "man", page, (char *)NULL); warning("failed to exec '%s': %s", path, strerror(errno)); } @@ -165,7 +165,7 @@ static void exec_man_cmd(const char *cmd, const char *page) { struct strbuf shell_cmd = STRBUF_INIT; strbuf_addf(&shell_cmd, "%s %s", cmd, page); - execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL); + execl("/bin/sh", "sh", "-c", shell_cmd.buf, (char *)NULL); warning("failed to exec '%s': %s", cmd, strerror(errno)); } @@ -372,7 +372,7 @@ static void show_info_page(const char *git_cmd) { const char *page = cmd_to_page(git_cmd); setenv("INFOPATH", system_path(GIT_INFO_PATH), 1); - execlp("info", "info", "gitman", page, NULL); + execlp("info", "info", "gitman", page, (char *)NULL); die("no info viewer handled the request"); } @@ -398,7 +398,7 @@ static void get_html_page_path(struct strbuf *page_path, const char *page) #ifndef open_html static void open_html(const char *path) { - execl_git_cmd("web--browse", "-c", "help.browser", path, NULL); + execl_git_cmd("web--browse", "-c", "help.browser", path, (char *)NULL); } #endif diff --git a/builtin/index-pack.c b/builtin/index-pack.c index a89ae831dd..fad76bf7a8 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -884,6 +884,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (argc == 2 && !strcmp(argv[1], "-h")) usage(index_pack_usage); + read_replace_refs = 0; + /* * We wish to read the repository's config file if any, and * for that it is necessary to call setup_git_directory_gently(). diff --git a/builtin/notes.c b/builtin/notes.c index 190005f3cd..fbc347c9f0 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -798,8 +798,9 @@ static int prune(int argc, const char **argv, const char *prefix) struct notes_tree *t; int show_only = 0, verbose = 0; struct option options[] = { - OPT_BOOLEAN('n', NULL, &show_only, "do not remove, show only"), - OPT_BOOLEAN('v', NULL, &verbose, "report pruned notes"), + OPT_BOOLEAN('n', "dry-run", &show_only, + "do not remove, show only"), + OPT_BOOLEAN('v', "verbose", &verbose, "report pruned notes"), OPT_END() }; diff --git a/builtin/prune.c b/builtin/prune.c index 81f915ec31..99218ba49e 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -125,10 +125,9 @@ int cmd_prune(int argc, const char **argv, const char *prefix) { struct rev_info revs; const struct option options[] = { - OPT_BOOLEAN('n', NULL, &show_only, + OPT_BOOLEAN('n', "dry-run", &show_only, "do not remove, show only"), - OPT_BOOLEAN('v', NULL, &verbose, - "report pruned objects"), + OPT_BOOLEAN('v', "verbose", &verbose, "report pruned objects"), OPT_DATE(0, "expire", &expire, "expire objects older than <time>"), OPT_END() diff --git a/builtin/push.c b/builtin/push.c index f4358b9d23..69bc2f27ac 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -130,8 +130,8 @@ static int push_with_options(struct transport *transport, int flags) if (nonfastforward && advice_push_nonfastforward) { fprintf(stderr, "To prevent you from losing history, non-fast-forward updates were rejected\n" - "Merge the remote changes before pushing again. See the 'Note about\n" - "fast-forwards' section of 'git push --help' for details.\n"); + "Merge the remote changes (e.g. 'git pull') before pushing again. See the\n" + "'Note about fast-forwards' section of 'git push --help' for details.\n"); } return 1; @@ -449,7 +449,7 @@ extern int init_db(const char *template_dir, unsigned int flags); alloc = alloc_nr(alloc); \ x = xrealloc((x), alloc * sizeof(*(x))); \ } \ - } while(0) + } while (0) /* Initialize and use the cache information */ extern int read_index(struct index_state *); diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email index 30ae63d74d..09c524105c 100755 --- a/contrib/hooks/post-receive-email +++ b/contrib/hooks/post-receive-email @@ -203,7 +203,7 @@ generate_email_header() # Generate header cat <<-EOF To: $recipients - Subject: ${emailprefix}$projectdesc $refname_type, $short_refname, ${change_type}d. $describe + Subject: ${emailprefix}$projectdesc $refname_type $short_refname ${change_type}d. $describe X-Git-Refname: $refname X-Git-Reftype: $refname_type X-Git-Oldrev: $oldrev diff --git a/contrib/svn-fe/.gitignore b/contrib/svn-fe/.gitignore index 27a33b669e..02a7791585 100644 --- a/contrib/svn-fe/.gitignore +++ b/contrib/svn-fe/.gitignore @@ -1,3 +1,4 @@ /*.xml /*.1 /*.html +/svn-fe diff --git a/contrib/svn-fe/Makefile b/contrib/svn-fe/Makefile index 4cc8d15827..360d8da417 100644 --- a/contrib/svn-fe/Makefile +++ b/contrib/svn-fe/Makefile @@ -38,7 +38,7 @@ svn-fe$X: svn-fe.o $(VCSSVN_LIB) $(GIT_LIB) $(ALL_LDFLAGS) $(LIBS) svn-fe.o: svn-fe.c ../../vcs-svn/svndump.h - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $< + $(QUIET_CC)$(CC) -I../../vcs-svn -o $*.o -c $(ALL_CFLAGS) $< svn-fe.html: svn-fe.txt $(QUIET_SUBDIR0)../../Documentation $(QUIET_SUBDIR1) \ diff --git a/contrib/svn-fe/svn-fe.c b/contrib/svn-fe/svn-fe.c index 43c4320cac..e9b9ba4da4 100644 --- a/contrib/svn-fe/svn-fe.c +++ b/contrib/svn-fe/svn-fe.c @@ -4,7 +4,7 @@ */ #include <stdlib.h> -#include "vcs-svn/svndump.h" +#include "svndump.h" int main(int argc, char **argv) { @@ -2704,10 +2704,16 @@ static void diff_fill_sha1_info(struct diff_filespec *one) static void strip_prefix(int prefix_length, const char **namep, const char **otherp) { /* Strip the prefix but do not molest /dev/null and absolute paths */ - if (*namep && **namep != '/') + if (*namep && **namep != '/') { *namep += prefix_length; - if (*otherp && **otherp != '/') + if (**namep == '/') + ++*namep; + } + if (*otherp && **otherp != '/') { *otherp += prefix_length; + if (**otherp == '/') + ++*otherp; + } } static void run_diff(struct diff_filepair *p, struct diff_options *o) @@ -2814,7 +2820,6 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o) void diff_setup(struct diff_options *options) { memset(options, 0, sizeof(*options)); - memset(&diff_queued_diff, 0, sizeof(diff_queued_diff)); options->file = stdout; diff --git a/diffcore.h b/diffcore.h index 491bea0b44..05ebc115a1 100644 --- a/diffcore.h +++ b/diffcore.h @@ -18,7 +18,7 @@ #define MAX_SCORE 60000.0 #define DEFAULT_RENAME_SCORE 30000 /* rename/copy similarity minimum (50%) */ #define DEFAULT_BREAK_SCORE 30000 /* minimum for break to happen (50%) */ -#define DEFAULT_MERGE_SCORE 36000 /* maximum for break-merge to happen 60%) */ +#define DEFAULT_MERGE_SCORE 36000 /* maximum for break-merge to happen (60%) */ #define MINIMUM_BREAK_SIZE 400 /* do not break a file smaller than this */ @@ -98,7 +98,7 @@ struct diff_queue_struct { (q)->queue = NULL; \ (q)->nr = (q)->alloc = 0; \ (q)->run = 0; \ - } while(0); + } while (0) extern struct diff_queue_struct diff_queued_diff; extern struct diff_filepair *diff_queue(struct diff_queue_struct *, @@ -118,9 +118,9 @@ void diff_debug_filespec(struct diff_filespec *, int, const char *); void diff_debug_filepair(const struct diff_filepair *, int); void diff_debug_queue(const char *, struct diff_queue_struct *); #else -#define diff_debug_filespec(a,b,c) do {} while(0) -#define diff_debug_filepair(a,b) do {} while(0) -#define diff_debug_queue(a,b) do {} while(0) +#define diff_debug_filespec(a,b,c) do { /* nothing */ } while (0) +#define diff_debug_filepair(a,b) do { /* nothing */ } while (0) +#define diff_debug_queue(a,b) do { /* nothing */ } while (0) #endif extern int diffcore_count_changes(struct diff_filespec *src, diff --git a/fast-import.c b/fast-import.c index 1e5d66ed0a..ddad289dae 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1666,7 +1666,7 @@ static void dump_marks_helper(FILE *f, if (m->shift) { for (k = 0; k < 1024; k++) { if (m->data.sets[k]) - dump_marks_helper(f, (base + k) << m->shift, + dump_marks_helper(f, base + (k << m->shift), m->data.sets[k]); } } else { diff --git a/git-compat-util.h b/git-compat-util.h index 02a73eeb66..fe845ae639 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -388,6 +388,8 @@ extern int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1); static inline size_t xsize_t(off_t len) { + if (len > (size_t) len) + die("Cannot handle files this big"); return (size_t)len; } diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh index 7d5451198c..bb104895a9 100755 --- a/git-gui/git-gui.sh +++ b/git-gui/git-gui.sh @@ -38,7 +38,7 @@ if {[catch {package require Tcl 8.4} err] tk_messageBox \ -icon error \ -type ok \ - -title [mc "git-gui: fatal error"] \ + -title "git-gui: fatal error" \ -message $err exit 1 } @@ -269,6 +269,17 @@ proc is_config_true {name} { } } +proc is_config_false {name} { + global repo_config + if {[catch {set v $repo_config($name)}]} { + return 0 + } elseif {$v eq {false} || $v eq {0} || $v eq {no}} { + return 1 + } else { + return 0 + } +} + proc get_config {name} { global repo_config if {[catch {set v $repo_config($name)}]} { @@ -323,6 +334,8 @@ proc _trace_exec {cmd} { puts stderr $d } +#'" fix poor old emacs font-lock mode + proc _git_cmd {name} { global _git_cmd_path @@ -416,6 +429,9 @@ proc _lappend_nice {cmd_var} { if {![info exists _nice]} { set _nice [_which nice] + if {[catch {exec $_nice git version}]} { + set _nice {} + } } if {$_nice ne {}} { lappend cmd $_nice @@ -634,6 +650,7 @@ proc rmsel_tag {text} { return $text } +wm withdraw . set root_exists 0 bind . <Visibility> { bind . <Visibility> {} @@ -782,6 +799,7 @@ set default_config(user.email) {} set default_config(gui.encoding) [encoding system] set default_config(gui.matchtrackingbranch) false +set default_config(gui.textconv) true set default_config(gui.pruneduringfetch) false set default_config(gui.trustmtime) false set default_config(gui.fastcopyblame) false @@ -1155,6 +1173,9 @@ apply_config # try to set work tree from environment, falling back to core.worktree if {[catch { set _gitworktree $env(GIT_WORK_TREE) }]} { set _gitworktree [get_config core.worktree] + if {$_gitworktree eq ""} { + set _gitworktree [file dirname [file normalize $_gitdir]] + } } if {$_prefix ne {}} { if {$_gitworktree eq {}} { @@ -2098,7 +2119,7 @@ proc do_explore {} { # freedesktop.org-conforming system is our best shot set explorer "xdg-open" } - eval exec $explorer $_gitworktree & + eval exec $explorer [list [file nativename $_gitworktree]] & } set is_quitting 0 @@ -2901,6 +2922,7 @@ blame { set current_branch $head } + wm deiconify . switch -- $subcommand { browser { if {$jump_spec ne {}} usage @@ -3405,6 +3427,19 @@ lappend diff_actions [list $ctxmsm entryconf [$ctxmsm index last] -state] $ctxmsm add separator create_common_diff_popup $ctxmsm +proc has_textconv {path} { + if {[is_config_false gui.textconv]} { + return 0 + } + set filter [gitattr $path diff set] + set textconv [get_config [join [list diff $filter textconv] .]] + if {$filter ne {set} && $textconv ne {}} { + return 1 + } else { + return 0 + } +} + proc popup_diff_menu {ctxm ctxmmg ctxmsm x y X Y} { global current_diff_path file_states set ::cursorX $x @@ -3440,7 +3475,8 @@ proc popup_diff_menu {ctxm ctxmmg ctxmsm x y X Y} { || {__} eq $state || {_O} eq $state || {_T} eq $state - || {T_} eq $state} { + || {T_} eq $state + || [has_textconv $current_diff_path]} { set s disabled } else { set s normal @@ -3460,29 +3496,44 @@ $main_status show [mc "Initializing..."] # -- Load geometry # -catch { -set gm $repo_config(gui.geometry) -wm geometry . [lindex $gm 0] -if {$use_ttk} { - .vpane sashpos 0 [lindex $gm 1] - .vpane.files sashpos 0 [lindex $gm 2] -} else { - .vpane sash place 0 \ - [lindex $gm 1] \ - [lindex [.vpane sash coord 0] 1] - .vpane.files sash place 0 \ - [lindex [.vpane.files sash coord 0] 0] \ - [lindex $gm 2] +proc on_ttk_pane_mapped {w pane pos} { + bind $w <Map> {} + after 0 [list after idle [list $w sashpos $pane $pos]] +} +proc on_tk_pane_mapped {w pane x y} { + bind $w <Map> {} + after 0 [list after idle [list $w sash place $pane $x $y]] +} +proc on_application_mapped {} { + global repo_config use_ttk + bind . <Map> {} + set gm $repo_config(gui.geometry) + if {$use_ttk} { + bind .vpane <Map> \ + [list on_ttk_pane_mapped %W 0 [lindex $gm 1]] + bind .vpane.files <Map> \ + [list on_ttk_pane_mapped %W 0 [lindex $gm 2]] + } else { + bind .vpane <Map> \ + [list on_tk_pane_mapped %W 0 \ + [lindex $gm 1] \ + [lindex [.vpane sash coord 0] 1]] + bind .vpane.files <Map> \ + [list on_tk_pane_mapped %W 0 \ + [lindex [.vpane.files sash coord 0] 0] \ + [lindex $gm 2]] + } + wm geometry . [lindex $gm 0] } -unset gm +if {[info exists repo_config(gui.geometry)]} { + bind . <Map> [list on_application_mapped] + wm geometry . [lindex $repo_config(gui.geometry) 0] } # -- Load window state # -catch { -set gws $repo_config(gui.wmstate) -wm state . $gws -unset gws +if {[info exists repo_config(gui.wmstate)]} { + catch {wm state . $repo_config(gui.wmstate)} } # -- Key Bindings diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl index 786b50b8c2..2137ec9684 100644 --- a/git-gui/lib/blame.tcl +++ b/git-gui/lib/blame.tcl @@ -449,11 +449,28 @@ method _load {jump} { $status show [mc "Reading %s..." "$commit:[escape_path $path]"] $w_path conf -text [escape_path $path] + + set do_textconv 0 + if {![is_config_false gui.textconv] && [git-version >= 1.7.2]} { + set filter [gitattr $path diff set] + set textconv [get_config [join [list diff $filter textconv] .]] + if {$filter ne {set} && $textconv ne {}} { + set do_textconv 1 + } + } if {$commit eq {}} { - set fd [open $path r] + if {$do_textconv ne 0} { + set fd [open |[list $textconv $path] r] + } else { + set fd [open $path r] + } fconfigure $fd -eofchar {} } else { - set fd [git_read cat-file blob "$commit:$path"] + if {$do_textconv ne 0} { + set fd [git_read cat-file --textconv "$commit:$path"] + } else { + set fd [git_read cat-file blob "$commit:$path"] + } } fconfigure $fd \ -blocking 0 \ diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl index 64f06748b6..fae119286d 100644 --- a/git-gui/lib/choose_repository.tcl +++ b/git-gui/lib/choose_repository.tcl @@ -100,12 +100,17 @@ constructor pick {} { $opts insert end [mc "Clone Existing Repository"] link_clone $opts insert end "\n" if {$m_repo ne {}} { + if {[tk windowingsystem] eq "win32"} { + set key L + } else { + set key C + } $m_repo add command \ -command [cb _next clone] \ - -accelerator $M1T-C \ + -accelerator $M1T-$key \ -label [mc "Clone..."] - bind $top <$M1B-c> [cb _next clone] - bind $top <$M1B-C> [cb _next clone] + bind $top <$M1B-[string tolower $key]> [cb _next clone] + bind $top <$M1B-[string toupper $key]> [cb _next clone] } $opts tag conf link_open -foreground blue -underline 1 diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl index ec8c11eeb7..c628750276 100644 --- a/git-gui/lib/diff.tcl +++ b/git-gui/lib/diff.tcl @@ -55,7 +55,7 @@ proc handle_empty_diff {} { set path $current_diff_path set s $file_states($path) - if {[lindex $s 0] ne {_M}} return + if {[lindex $s 0] ne {_M} || [has_textconv $path]} return # Prevent infinite rescan loops incr diff_empty_count @@ -280,6 +280,9 @@ proc start_show_diff {cont_info {add_opts {}}} { lappend cmd diff-files } } + if {![is_config_false gui.textconv] && [git-version >= 1.6.1]} { + lappend cmd --textconv + } if {[string match {160000 *} [lindex $s 2]] || [string match {160000 *} [lindex $s 3]]} { diff --git a/git-gui/lib/option.tcl b/git-gui/lib/option.tcl index d4c5e45c8a..3807c8d283 100644 --- a/git-gui/lib/option.tcl +++ b/git-gui/lib/option.tcl @@ -148,6 +148,7 @@ proc do_options {} { {b gui.trustmtime {mc "Trust File Modification Timestamps"}} {b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}} {b gui.matchtrackingbranch {mc "Match Tracking Branches"}} + {b gui.textconv {mc "Use Textconv For Diffs and Blames"}} {b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}} {i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}} {i-0..300 gui.blamehistoryctx {mc "Blame History Context Radius (days)"}} diff --git a/git-gui/lib/shortcut.tcl b/git-gui/lib/shortcut.tcl index 79c1888e11..78878ef89d 100644 --- a/git-gui/lib/shortcut.tcl +++ b/git-gui/lib/shortcut.tcl @@ -16,7 +16,7 @@ proc do_windows_shortcut {} { [info nameofexecutable] \ [file normalize $::argv0] \ ] \ - [file normalize [$_gitworktree]] + [file normalize $_gitworktree] } err]} { error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"] } @@ -57,7 +57,7 @@ proc do_cygwin_shortcut {} { $sh -c \ "CHERE_INVOKING=1 source /etc/profile;[sq $me] &" \ ] \ - [file normalize [$_gitworktree]] + [file normalize $_gitworktree] } err]} { error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"] } diff --git a/git-gui/lib/status_bar.tcl b/git-gui/lib/status_bar.tcl index 5fe3aad382..95cb44991f 100644 --- a/git-gui/lib/status_bar.tcl +++ b/git-gui/lib/status_bar.tcl @@ -39,6 +39,7 @@ method _oneline_pack {} { } constructor two_line {path} { + global NS set w $path set w_l $w.l set w_c $w.c diff --git a/git-gui/lib/win32.tcl b/git-gui/lib/win32.tcl index d7f93d045d..db91ab84a5 100644 --- a/git-gui/lib/win32.tcl +++ b/git-gui/lib/win32.tcl @@ -18,9 +18,9 @@ proc win32_create_lnk {lnk_path lnk_exec lnk_dir} { eval [list exec wscript.exe \ /E:jscript \ /nologo \ - [file join $oguilib win32_shortcut.js] \ + [file nativename [file join $oguilib win32_shortcut.js]] \ $lnk_path \ - [file join $oguilib git-gui.ico] \ + [file nativename [file join $oguilib git-gui.ico]] \ $lnk_dir \ $lnk_exec] $lnk_args } diff --git a/git-gui/windows/git-gui.sh b/git-gui/windows/git-gui.sh index 66bbb2f8fa..b1845c5055 100644 --- a/git-gui/windows/git-gui.sh +++ b/git-gui/windows/git-gui.sh @@ -13,10 +13,11 @@ if { $argc >=2 && [lindex $argv 0] == "--working-dir" } { incr argc -2 } -set bindir [file dirname \ +set basedir [file dirname \ [file dirname \ [file dirname [info script]]]] -set bindir [file join $bindir bin] +set bindir [file join $basedir bin] +set bindir "$bindir;[file join $basedir mingw bin]" regsub -all ";" $bindir "\\;" bindir set env(PATH) "$bindir;$env(PATH)" unset bindir diff --git a/git-instaweb.sh b/git-instaweb.sh index 6635fbefdf..b7342e22c8 100755 --- a/git-instaweb.sh +++ b/git-instaweb.sh @@ -43,7 +43,8 @@ test -z "$port" && port=1234 resolve_full_httpd () { case "$httpd" in - *apache2*|*lighttpd*) + *apache2*|*lighttpd*|*httpd*) + # yes, *httpd* covers *lighttpd* above, but it is there for clarity # ensure that the apache2/lighttpd command ends with "-f" if ! echo "$httpd" | sane_grep -- '-f *$' >/dev/null 2>&1 then @@ -300,7 +301,13 @@ EOF } apache2_conf () { - test -z "$module_path" && module_path=/usr/lib/apache2/modules + if test -z "$module_path" + then + test -d "/usr/lib/httpd/modules" && + module_path="/usr/lib/httpd/modules" + test -d "/usr/lib/apache2/modules" && + module_path="/usr/lib/apache2/modules" + fi bind= test x"$local" = xtrue && bind='127.0.0.1:' echo 'text/css css' > "$fqgitdir/mime.types" @@ -314,8 +321,10 @@ PidFile "$fqgitdir/pid" Listen $bind$port EOF - for mod in mime dir; do - if test -e $module_path/mod_${mod}.so; then + for mod in mime dir env log_config + do + if test -e $module_path/mod_${mod}.so + then echo "LoadModule ${mod}_module " \ "$module_path/mod_${mod}.so" >> "$conf" fi @@ -334,7 +343,7 @@ EOF cat >> "$conf" <<EOF LoadModule perl_module $module_path/mod_perl.so PerlPassEnv GIT_DIR -PerlPassEnv GIT_EXEC_DIR +PerlPassEnv GIT_EXEC_PATH PerlPassEnv GITWEB_CONFIG <Location /gitweb.cgi> SetHandler perl-script @@ -364,6 +373,9 @@ EOF echo "ScriptSock logs/gitweb.sock" >> "$conf" fi cat >> "$conf" <<EOF +PassEnv GIT_DIR +PassEnv GIT_EXEC_PATH +PassEnv GITWEB_CONFIG AddHandler cgi-script .cgi <Location /gitweb.cgi> Options +ExecCGI @@ -560,7 +572,7 @@ case "$httpd" in *lighttpd*) lighttpd_conf ;; -*apache2*) +*apache2*|*httpd*) apache2_conf ;; webrick) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 31e68603f4..b94c2a0386 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -119,7 +119,7 @@ run 'git rebase --continue'" export GIT_CHERRY_PICK_HELP warn () { - echo "$*" >&2 + printf '%s\n' "$*" >&2 } output () { @@ -606,7 +606,7 @@ skip_unnecessary_picks () { fd=1 ;; esac - echo "$command${sha1:+ }$sha1${rest:+ }$rest" >&$fd + printf '%s\n' "$command${sha1:+ }$sha1${rest:+ }$rest" >&$fd done <"$TODO" >"$TODO.new" 3>>"$DONE" && mv -f "$TODO".new "$TODO" && case "$(peek_next_command)" in @@ -649,12 +649,12 @@ rearrange_squash () { case " $used" in *" $sha1 "*) continue ;; esac - echo "$pick $sha1 $message" + printf '%s\n' "$pick $sha1 $message" while read -r squash action msg do case "$message" in "$msg"*) - echo "$action $squash $action! $msg" + printf '%s\n' "$action $squash $action! $msg" used="$used$squash " ;; esac @@ -895,7 +895,7 @@ first and then run 'git rebase --continue' again." do if test t != "$PRESERVE_MERGES" then - echo "pick $shortsha1 $rest" >> "$TODO" + printf '%s\n' "pick $shortsha1 $rest" >> "$TODO" else sha1=$(git rev-parse $shortsha1) if test -z "$REBASE_ROOT" @@ -914,7 +914,7 @@ first and then run 'git rebase --continue' again." if test f = "$preserve" then touch "$REWRITTEN"/$sha1 - echo "pick $shortsha1 $rest" >> "$TODO" + printf '%s\n' "pick $shortsha1 $rest" >> "$TODO" fi fi done diff --git a/git-rebase.sh b/git-rebase.sh index ab4afa7dee..1b9ea48cd7 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -208,6 +208,7 @@ do test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply || die "No rebase in progress?" + git update-index --ignore-submodules --refresh && git diff-files --quiet --ignore-submodules || { echo "You must edit all merge conflicts and then" echo "mark them as resolved using git add" @@ -345,7 +346,7 @@ do --root) rebase_root=t ;; - -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase|--no-ff) + -f|--f|--fo|--for|--forc|--force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase|--no-ff) force_rebase=t ;; --rerere-autoupdate|--no-rerere-autoupdate) @@ -543,7 +544,7 @@ fi if test -z "$do_merge" then git format-patch -k --stdout --full-index --ignore-if-in-upstream \ - $root_flag "$revisions" | + --no-renames $root_flag "$revisions" | git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" && move_to_original_branch ret=$? diff --git a/git-web--browse.sh b/git-web--browse.sh index dbded76aaf..3fc4166b25 100755 --- a/git-web--browse.sh +++ b/git-web--browse.sh @@ -31,7 +31,7 @@ valid_custom_tool() valid_tool() { case "$1" in - firefox | iceweasel | chrome | chromium | konqueror | w3m | links | lynx | dillo | open | start) + firefox | iceweasel | chrome | google-chrome | chromium | konqueror | w3m | links | lynx | dillo | open | start) ;; # happy *) valid_custom_tool "$1" || return 1 @@ -103,7 +103,7 @@ fi if test -z "$browser" ; then if test -n "$DISPLAY"; then - browser_candidates="firefox iceweasel chrome chromium konqueror w3m links lynx dillo" + browser_candidates="firefox iceweasel google-chrome chrome chromium konqueror w3m links lynx dillo" if test "$KDE_FULL_SESSION" = "true"; then browser_candidates="konqueror $browser_candidates" fi @@ -146,7 +146,7 @@ case "$browser" in test "$vers" -lt 2 && NEWTAB='' "$browser_path" $NEWTAB "$@" & ;; - chrome|chromium) + google-chrome|chrome|chromium) # Actual command for chromium is chromium-browser. # No need to specify newTab. It's default in chromium eval "$browser_path" "$@" & @@ -8,8 +8,8 @@ const char git_usage_string[] = "git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n" " [-p|--paginate|--no-pager] [--no-replace-objects]\n" " [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n" - " [-c name=value\n" - " [--help] COMMAND [ARGS]"; + " [-c name=value] [--help]\n" + " COMMAND [ARGS]"; const char git_more_info_string[] = "See 'git help COMMAND' for more information on a specific command."; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index cedc357313..6deec87e5d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6522,12 +6522,13 @@ sub git_search { $paging_nav .= " ⋅ next"; } - if ($#commitlist >= 100) { - } - git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav); git_print_header_div('commit', esc_html($co{'title'}), $hash); - git_search_grep_body(\@commitlist, 0, 99, $next_link); + if ($page == 0 && !@commitlist) { + print "<p>No match.</p>\n"; + } else { + git_search_grep_body(\@commitlist, 0, 99, $next_link); + } } if ($searchtype eq 'pickaxe') { @@ -23,10 +23,10 @@ #endif #if LIBCURL_VERSION_NUM < 0x070704 -#define curl_global_cleanup() do { /* nothing */ } while(0) +#define curl_global_cleanup() do { /* nothing */ } while (0) #endif #if LIBCURL_VERSION_NUM < 0x070800 -#define curl_global_init(a) do { /* nothing */ } while(0) +#define curl_global_init(a) do { /* nothing */ } while (0) #endif #if (LIBCURL_VERSION_NUM < 0x070c04) || (LIBCURL_VERSION_NUM == 0x071000) diff --git a/imap-send.c b/imap-send.c index 1a577a0a09..71506a8dd3 100644 --- a/imap-send.c +++ b/imap-send.c @@ -543,9 +543,13 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx, while (imap->literal_pending) get_cmd_result(ctx, NULL); - bufl = nfsnprintf(buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ? - "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n", - cmd->tag, cmd->cmd, cmd->cb.dlen); + if (!cmd->cb.data) + bufl = nfsnprintf(buf, sizeof(buf), "%d %s\r\n", cmd->tag, cmd->cmd); + else + bufl = nfsnprintf(buf, sizeof(buf), "%d %s{%d%s}\r\n", + cmd->tag, cmd->cmd, cmd->cb.dlen, + CAP(LITERALPLUS) ? "+" : ""); + if (Verbose) { if (imap->num_in_progress) printf("(%d in progress) ", imap->num_in_progress); @@ -1086,7 +1090,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc) int gai; char portstr[6]; - snprintf(portstr, sizeof(portstr), "%hu", srvc->port); + snprintf(portstr, sizeof(portstr), "%d", srvc->port); memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; @@ -316,6 +316,8 @@ char *expand_user_path(const char *path) size_t username_len = first_slash - username; if (username_len == 0) { const char *home = getenv("HOME"); + if (!home) + goto return_null; strbuf_add(&user_path, home, strlen(home)); } else { struct passwd *pw = getpw_str(username, username_len); diff --git a/remote-curl.c b/remote-curl.c index 24fbb9a9b9..04d4813e41 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -528,11 +528,12 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads) rpc->len = n; err |= post_rpc(rpc); } - strbuf_read(&rpc->result, client.out, 0); close(client.in); - close(client.out); client.in = -1; + strbuf_read(&rpc->result, client.out, 0); + + close(client.out); client.out = -1; err |= finish_command(&client); diff --git a/sha1_name.c b/sha1_name.c index 4f2af8da93..4af94fa598 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -659,6 +659,16 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1) return get_short_sha1(name, len, sha1, 0); } +/* + * This interprets names like ':/Initial revision of "git"' by searching + * through history and returning the first commit whose message starts + * the given regular expression. + * + * For future extension, ':/!' is reserved. If you want to match a message + * beginning with a '!', you have to repeat the exclamation mark. + */ +#define ONELINE_SEEN (1u<<20) + static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) { @@ -674,19 +684,10 @@ static int handle_one_ref(const char *path, if (object->type != OBJ_COMMIT) return 0; insert_by_date((struct commit *)object, list); + object->flags |= ONELINE_SEEN; return 0; } -/* - * This interprets names like ':/Initial revision of "git"' by searching - * through history and returning the first commit whose message matches - * the given regular expression. - * - * For future extension, ':/!' is reserved. If you want to match a message - * beginning with a '!', you have to repeat the exclamation mark. - */ - -#define ONELINE_SEEN (1u<<20) static int get_sha1_oneline(const char *prefix, unsigned char *sha1) { struct commit_list *list = NULL, *backup = NULL, *l; @@ -259,11 +259,11 @@ Do: test ... That way all of the commands in your tests will succeed or fail. If - you must ignore the return value of something (e.g. the return - value of export is unportable) it's best to indicate so explicitly - with a semicolon: + you must ignore the return value of something (e.g., the return + after unsetting a variable that was already unset is unportable) it's + best to indicate so explicitly with a semicolon: - export HLAGH; + unset HLAGH; git merge hla && git push gh && test ... diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index c3f6676ca2..92d6d31942 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -16,7 +16,6 @@ fi GIT_DIR=$PWD/.git GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn SVN_TREE=$GIT_SVN_DIR/svn-tree -PERL=${PERL:-perl} svn >/dev/null 2>&1 if test $? -ne 1 @@ -30,7 +29,7 @@ export svnrepo svnconf=$PWD/svnconf export svnconf -$PERL -w -e " +"$PERL_PATH" -w -e " use SVN::Core; use SVN::Repos; \$SVN::Core::VERSION gt '1.1.0' or exit(42); @@ -130,7 +129,7 @@ stop_httpd () { } convert_to_rev_db () { - $PERL -w -- - "$@" <<\EOF + "$PERL_PATH" -w -- - "$@" <<\EOF use strict; @ARGV == 2 or die "Usage: convert_to_rev_db <input> <output>"; open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]"; diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 64f05080b6..074f2f2e3e 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -707,19 +707,41 @@ test_expect_success 'set --path' ' git config --path path.trailingtilde "foo~" && test_cmp expect .git/config' +if test "${HOME+set}" +then + test_set_prereq HOMEVAR +fi + cat >expect <<EOF $HOME/ /dev/null foo~ EOF -test_expect_success 'get --path' ' +test_expect_success HOMEVAR 'get --path' ' git config --get --path path.home > result && git config --get --path path.normal >> result && git config --get --path path.trailingtilde >> result && test_cmp expect result ' +cat >expect <<\EOF +/dev/null +foo~ +EOF + +test_expect_success 'get --path copes with unset $HOME' ' + ( + unset HOME; + test_must_fail git config --get --path path.home \ + >result 2>msg && + git config --get --path path.normal >>result && + git config --get --path path.trailingtilde >>result + ) && + grep "[Ff]ailed to expand.*~/" msg && + test_cmp expect result +' + rm .git/config git config quote.leading " test" diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index eb45afb018..782e75d000 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -41,6 +41,23 @@ test_expect_success "check-ref-format --branch @{-1}" ' refname2=$(git check-ref-format --branch @{-2}) && test "$refname2" = master' +test_expect_success 'check-ref-format --branch from subdir' ' + mkdir subdir && + + T=$(git write-tree) && + sha1=$(echo A | git commit-tree $T) && + git update-ref refs/heads/master $sha1 && + git update-ref refs/remotes/origin/master $sha1 + git checkout master && + git checkout origin/master && + git checkout master && + refname=$( + cd subdir && + git check-ref-format --branch @{-1} + ) && + test "$refname" = "$sha1" +' + valid_ref_normalized() { test_expect_success "ref name '$1' simplifies to '$2'" " refname=\$(git check-ref-format --print '$1') && diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh index be88d4b5ee..2d2f63f22e 100755 --- a/t/t2017-checkout-orphan.sh +++ b/t/t2017-checkout-orphan.sh @@ -68,41 +68,34 @@ test_expect_success '--orphan makes reflog by default' ' git checkout master && git config --unset core.logAllRefUpdates && git checkout --orphan delta && - ! test -f .git/logs/refs/heads/delta && - test_must_fail PAGER= git reflog show delta && + test_must_fail git rev-parse --verify delta@{0} && git commit -m Delta && - test -f .git/logs/refs/heads/delta && - PAGER= git reflog show delta + git rev-parse --verify delta@{0} ' test_expect_success '--orphan does not make reflog when core.logAllRefUpdates = false' ' git checkout master && git config core.logAllRefUpdates false && git checkout --orphan epsilon && - ! test -f .git/logs/refs/heads/epsilon && - test_must_fail PAGER= git reflog show epsilon && + test_must_fail git rev-parse --verify epsilon@{0} && git commit -m Epsilon && - ! test -f .git/logs/refs/heads/epsilon && - test_must_fail PAGER= git reflog show epsilon + test_must_fail git rev-parse --verify epsilon@{0} ' test_expect_success '--orphan with -l makes reflog when core.logAllRefUpdates = false' ' git checkout master && git checkout -l --orphan zeta && - test -f .git/logs/refs/heads/zeta && - test_must_fail PAGER= git reflog show zeta && + test_must_fail git rev-parse --verify zeta@{0} && git commit -m Zeta && - PAGER= git reflog show zeta + git rev-parse --verify zeta@{0} ' test_expect_success 'giving up --orphan not committed when -l and core.logAllRefUpdates = false deletes reflog' ' git checkout master && git checkout -l --orphan eta && - test -f .git/logs/refs/heads/eta && - test_must_fail PAGER= git reflog show eta && + test_must_fail git rev-parse --verify eta@{0} && git checkout master && - ! test -f .git/logs/refs/heads/eta && - test_must_fail PAGER= git reflog show eta + test_must_fail git rev-parse --verify eta@{0} ' test_expect_success '--orphan is rejected with an existing name' ' diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 859b99abf1..f54a533456 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -228,24 +228,21 @@ test_expect_success 'checkout -b makes reflog by default' ' git checkout master && git config --unset core.logAllRefUpdates && git checkout -b alpha && - test -f .git/logs/refs/heads/alpha && - PAGER= git reflog show alpha + git rev-parse --verify alpha@{0} ' test_expect_success 'checkout -b does not make reflog when core.logAllRefUpdates = false' ' git checkout master && git config core.logAllRefUpdates false && git checkout -b beta && - ! test -f .git/logs/refs/heads/beta && - test_must_fail PAGER= git reflog show beta + test_must_fail git rev-parse --verify beta@{0} ' test_expect_success 'checkout -b with -l makes reflog when core.logAllRefUpdates = false' ' git checkout master && git checkout -lb gamma && git config --unset core.logAllRefUpdates && - test -f .git/logs/refs/heads/gamma && - PAGER= git reflog show gamma + git rev-parse --verify gamma@{0} ' test_expect_success 'avoid ambiguous track' ' diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 2d67a40fc1..1d82f79ee0 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -693,7 +693,11 @@ test_expect_success 'create note from non-existing note with "git notes add -c" git add a10 && test_tick && git commit -m 10th && - test_must_fail MSG="yet another note" git notes add -c deadbeef && + ( + MSG="yet another note" && + export MSG && + test_must_fail git notes add -c deadbeef + ) && test_must_fail git notes list HEAD ' diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index d98c7b5571..a19aeb6441 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -14,140 +14,164 @@ GIT_AUTHOR_NAME=author@name GIT_AUTHOR_EMAIL=bogus@email@address export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL -test_expect_success \ - 'prepare repository with topic branches' \ - 'git config core.logAllRefUpdates true && - echo First > A && - git update-index --add A && - git commit -m "Add A." && - git checkout -b my-topic-branch && - echo Second > B && - git update-index --add B && - git commit -m "Add B." && - git checkout -f master && - echo Third >> A && - git update-index A && - git commit -m "Modify A." && - git checkout -b side my-topic-branch && - echo Side >> C && - git add C && - git commit -m "Add C" && - git checkout -b nonlinear my-topic-branch && - echo Edit >> B && - git add B && - git commit -m "Modify B" && - git merge side && - git checkout -b upstream-merged-nonlinear && - git merge master && - git checkout -f my-topic-branch && - git tag topic +test_expect_success 'prepare repository with topic branches' ' + git config core.logAllRefUpdates true && + echo First >A && + git update-index --add A && + git commit -m "Add A." && + git checkout -b force-3way && + echo Dummy >Y && + git update-index --add Y && + git commit -m "Add Y." && + git checkout -b filemove && + git reset --soft master && + mkdir D && + git mv A D/A && + git commit -m "Move A." && + git checkout -b my-topic-branch master && + echo Second >B && + git update-index --add B && + git commit -m "Add B." && + git checkout -f master && + echo Third >>A && + git update-index A && + git commit -m "Modify A." && + git checkout -b side my-topic-branch && + echo Side >>C && + git add C && + git commit -m "Add C" && + git checkout -b nonlinear my-topic-branch && + echo Edit >>B && + git add B && + git commit -m "Modify B" && + git merge side && + git checkout -b upstream-merged-nonlinear && + git merge master && + git checkout -f my-topic-branch && + git tag topic ' test_expect_success 'rebase on dirty worktree' ' - echo dirty >> A && - test_must_fail git rebase master' + echo dirty >>A && + test_must_fail git rebase master +' test_expect_success 'rebase on dirty cache' ' - git add A && - test_must_fail git rebase master' + git add A && + test_must_fail git rebase master +' test_expect_success 'rebase against master' ' - git reset --hard HEAD && - git rebase master' + git reset --hard HEAD && + git rebase master +' test_expect_success 'rebase against master twice' ' - git rebase master >out && - grep "Current branch my-topic-branch is up to date" out + git rebase master >out && + grep "Current branch my-topic-branch is up to date" out ' test_expect_success 'rebase against master twice with --force' ' - git rebase --force-rebase master >out && - grep "Current branch my-topic-branch is up to date, rebase forced" out + git rebase --force-rebase master >out && + grep "Current branch my-topic-branch is up to date, rebase forced" out ' test_expect_success 'rebase against master twice from another branch' ' - git checkout my-topic-branch^ && - git rebase master my-topic-branch >out && - grep "Current branch my-topic-branch is up to date" out + git checkout my-topic-branch^ && + git rebase master my-topic-branch >out && + grep "Current branch my-topic-branch is up to date" out ' test_expect_success 'rebase fast-forward to master' ' - git checkout my-topic-branch^ && - git rebase my-topic-branch >out && - grep "Fast-forwarded HEAD to my-topic-branch" out + git checkout my-topic-branch^ && + git rebase my-topic-branch >out && + grep "Fast-forwarded HEAD to my-topic-branch" out ' -test_expect_success \ - 'the rebase operation should not have destroyed author information' \ - '! (git log | grep "Author:" | grep "<>")' +test_expect_success 'the rebase operation should not have destroyed author information' ' + ! (git log | grep "Author:" | grep "<>") +' -test_expect_success \ - 'the rebase operation should not have destroyed author information (2)' \ - "git log -1 | grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>'" +test_expect_success 'the rebase operation should not have destroyed author information (2)' " + git log -1 | + grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>' +" test_expect_success 'HEAD was detached during rebase' ' - test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1}) + test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1}) ' test_expect_success 'rebase after merge master' ' - git reset --hard topic && - git merge master && - git rebase master && - ! (git show | grep "^Merge:") + git reset --hard topic && + git merge master && + git rebase master && + ! (git show | grep "^Merge:") ' test_expect_success 'rebase of history with merges is linearized' ' - git checkout nonlinear && - test 4 = $(git rev-list master.. | wc -l) && - git rebase master && - test 3 = $(git rev-list master.. | wc -l) + git checkout nonlinear && + test 4 = $(git rev-list master.. | wc -l) && + git rebase master && + test 3 = $(git rev-list master.. | wc -l) ' -test_expect_success \ - 'rebase of history with merges after upstream merge is linearized' ' - git checkout upstream-merged-nonlinear && - test 5 = $(git rev-list master.. | wc -l) && - git rebase master && - test 3 = $(git rev-list master.. | wc -l) +test_expect_success 'rebase of history with merges after upstream merge is linearized' ' + git checkout upstream-merged-nonlinear && + test 5 = $(git rev-list master.. | wc -l) && + git rebase master && + test 3 = $(git rev-list master.. | wc -l) ' test_expect_success 'rebase a single mode change' ' - git checkout master && - echo 1 > X && - git add X && - test_tick && - git commit -m prepare && - git checkout -b modechange HEAD^ && - echo 1 > X && - git add X && - test_chmod +x A && - test_tick && - git commit -m modechange && - GIT_TRACE=1 git rebase master + git checkout master && + echo 1 >X && + git add X && + test_tick && + git commit -m prepare && + git checkout -b modechange HEAD^ && + echo 1 >X && + git add X && + test_chmod +x A && + test_tick && + git commit -m modechange && + GIT_TRACE=1 git rebase master +' + +test_expect_success 'rebase is not broken by diff.renames' ' + git config diff.renames copies && + test_when_finished "git config --unset diff.renames" && + git checkout filemove && + GIT_TRACE=1 git rebase force-3way +' + +test_expect_success 'setup: recover' ' + test_might_fail git rebase --abort && + git reset --hard && + git checkout modechange ' test_expect_success 'Show verbose error when HEAD could not be detached' ' - : > B && - test_must_fail git rebase topic 2> output.err > output.out && - grep "Untracked working tree file .B. would be overwritten" output.err + >B && + test_must_fail git rebase topic 2>output.err >output.out && + grep "Untracked working tree file .B. would be overwritten" output.err ' rm -f B test_expect_success 'dump usage when upstream arg is missing' ' - git checkout -b usage topic && - test_must_fail git rebase 2>error1 && - grep "[Uu]sage" error1 && - test_must_fail git rebase --abort 2>error2 && - grep "No rebase in progress" error2 && - test_must_fail git rebase --onto master 2>error3 && - grep "[Uu]sage" error3 && - ! grep "can.t shift" error3 + git checkout -b usage topic && + test_must_fail git rebase 2>error1 && + grep "[Uu]sage" error1 && + test_must_fail git rebase --abort 2>error2 && + grep "No rebase in progress" error2 && + test_must_fail git rebase --onto master 2>error3 && + grep "[Uu]sage" error3 && + ! grep "can.t shift" error3 ' test_expect_success 'rebase -q is quiet' ' - git checkout -b quiet topic && - git rebase -q master > output.out 2>&1 && - test ! -s output.out + git checkout -b quiet topic && + git rebase -q master >output.out 2>&1 && + test ! -s output.out ' test_expect_success 'Rebase a commit that sprinkles CRs in' ' diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 47ca88fc52..9f03ce699e 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -637,13 +637,19 @@ test_expect_success 'set up commits with funny messages' ' git commit -a -m "end with slash\\" && echo >>file1 && test_tick && + git commit -a -m "something (\000) that looks like octal" && + echo >>file1 && + test_tick && + git commit -a -m "something (\n) that looks like a newline" && + echo >>file1 && + test_tick && git commit -a -m "another commit" ' test_expect_success 'rebase-i history with funny messages' ' git rev-list A..funny >expect && test_tick && - FAKE_LINES="1 2" git rebase -i A && + FAKE_LINES="1 2 3 4" git rebase -i A && git rev-list A.. >actual && test_cmp expect actual ' diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh new file mode 100755 index 0000000000..3b0d27350e --- /dev/null +++ b/t/t3418-rebase-continue.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +test_description='git rebase --continue tests' + +. ./test-lib.sh + +. "$TEST_DIRECTORY"/lib-rebase.sh + +set_fake_editor + +test_expect_success 'setup' ' + test_commit "commit-new-file-F1" F1 1 && + test_commit "commit-new-file-F2" F2 2 && + + git checkout -b topic HEAD^ && + test_commit "commit-new-file-F2-on-topic-branch" F2 22 && + + git checkout master +' + +test_expect_success 'interactive rebase --continue works with touched file' ' + rm -fr .git/rebase-* && + git reset --hard && + git checkout master && + + FAKE_LINES="edit 1" git rebase -i HEAD^ && + test-chmtime =-60 F1 && + git rebase --continue +' + +test_expect_success 'non-interactive rebase --continue works with touched file' ' + rm -fr .git/rebase-* && + git reset --hard && + git checkout master && + + test_must_fail git rebase --onto master master topic && + echo "Resolved" >F2 && + git add F2 && + test-chmtime =-60 F1 && + git rebase --continue +' + +test_done diff --git a/t/t3700-add.sh b/t/t3700-add.sh index d03495dc7a..7d7140db38 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -272,17 +272,20 @@ test_expect_success 'git add --dry-run of non-existing file' " echo \"fatal: pathspec 'ignored-file' did not match any files\" | test_cmp - actual " -cat >expect <<EOF +cat >expect.err <<\EOF The following paths are ignored by one of your .gitignore files: ignored-file Use -f if you really want to add them. fatal: no files added +EOF +cat >expect.out <<\EOF add 'track-this' EOF test_expect_success 'git add --dry-run --ignore-missing of non-existing file' ' - test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual 2>&1 && - test_cmp expect actual + test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual.out 2>actual.err && + test_cmp expect.out actual.out && + test_cmp expect.err actual.err ' test_done diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh new file mode 100755 index 0000000000..8a3c63b9e2 --- /dev/null +++ b/t/t4045-diff-relative.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +test_description='diff --relative tests' +. ./test-lib.sh + +test_expect_success 'setup' ' + git commit --allow-empty -m empty && + echo content >file1 && + mkdir subdir && + echo other content >subdir/file2 && + git add . && + git commit -m one +' + +check_diff() { +expect=$1; shift +cat >expected <<EOF +diff --git a/$expect b/$expect +new file mode 100644 +index 0000000..25c05ef +--- /dev/null ++++ b/$expect +@@ -0,0 +1 @@ ++other content +EOF +test_expect_success "-p $*" " + git diff -p $* HEAD^ >actual && + test_cmp expected actual +" +} + +check_stat() { +expect=$1; shift +cat >expected <<EOF + $expect | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) +EOF +test_expect_success "--stat $*" " + git diff --stat $* HEAD^ >actual && + test_cmp expected actual +" +} + +check_raw() { +expect=$1; shift +cat >expected <<EOF +:000000 100644 0000000000000000000000000000000000000000 25c05ef3639d2d270e7fe765a67668f098092bc5 A $expect +EOF +test_expect_success "--raw $*" " + git diff --no-abbrev --raw $* HEAD^ >actual && + test_cmp expected actual +" +} + +for type in diff stat raw; do + check_$type file2 --relative=subdir/ + check_$type file2 --relative=subdir + check_$type dir/file2 --relative=sub +done + +test_done diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 810b04b817..1c3d8ed548 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -4,66 +4,71 @@ test_description='git am running' . ./test-lib.sh -cat >msg <<EOF -second - -Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy -eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam -voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita -kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem -ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod -tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At -vero eos et accusam et justo duo dolores et ea rebum. - - Duis autem vel eum iriure dolor in hendrerit in vulputate velit - esse molestie consequat, vel illum dolore eu feugiat nulla facilisis - at vero eros et accumsan et iusto odio dignissim qui blandit - praesent luptatum zzril delenit augue duis dolore te feugait nulla - facilisi. - - -Lorem ipsum dolor sit amet, -consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut -laoreet dolore magna aliquam erat volutpat. - - git - --- - +++ - -Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit -lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure -dolor in hendrerit in vulputate velit esse molestie consequat, vel illum -dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio -dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te -feugait nulla facilisi. -EOF - -cat >failmail <<EOF -From foo@example.com Fri May 23 10:43:49 2008 -From: foo@example.com -To: bar@example.com -Subject: Re: [RFC/PATCH] git-foo.sh -Date: Fri, 23 May 2008 05:23:42 +0200 - -Sometimes we have to find out that there's nothing left. - -EOF - -cat >pine <<EOF -From MAILER-DAEMON Fri May 23 10:43:49 2008 -Date: 23 May 2008 05:23:42 +0200 -From: Mail System Internal Data <MAILER-DAEMON@example.com> -Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA -Message-ID: <foo-0001@example.com> - -This text is part of the internal format of your mail folder, and is not -a real message. It is created automatically by the mail system software. -If deleted, important folder data will be lost, and it will be re-created -with the data reset to initial values. - -EOF - -echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected +test_expect_success 'setup: messages' ' + cat >msg <<-\EOF && + second + + Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy + eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam + voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita + kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem + ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod + tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At + vero eos et accusam et justo duo dolores et ea rebum. + + EOF + q_to_tab <<-\EOF >>msg && + QDuis autem vel eum iriure dolor in hendrerit in vulputate velit + Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis + Qat vero eros et accumsan et iusto odio dignissim qui blandit + Qpraesent luptatum zzril delenit augue duis dolore te feugait nulla + Qfacilisi. + EOF + cat >>msg <<-\EOF && + + Lorem ipsum dolor sit amet, + consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut + laoreet dolore magna aliquam erat volutpat. + + git + --- + +++ + + Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit + lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure + dolor in hendrerit in vulputate velit esse molestie consequat, vel illum + dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio + dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te + feugait nulla facilisi. + EOF + + cat >failmail <<-\EOF && + From foo@example.com Fri May 23 10:43:49 2008 + From: foo@example.com + To: bar@example.com + Subject: Re: [RFC/PATCH] git-foo.sh + Date: Fri, 23 May 2008 05:23:42 +0200 + + Sometimes we have to find out that there'\''s nothing left. + + EOF + + cat >pine <<-\EOF && + From MAILER-DAEMON Fri May 23 10:43:49 2008 + Date: 23 May 2008 05:23:42 +0200 + From: Mail System Internal Data <MAILER-DAEMON@example.com> + Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA + Message-ID: <foo-0001@example.com> + + This text is part of the internal format of your mail folder, and is not + a real message. It is created automatically by the mail system software. + If deleted, important folder data will be lost, and it will be re-created + with the data reset to initial values. + + EOF + + signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" +' test_expect_success setup ' echo hello >file && @@ -71,11 +76,13 @@ test_expect_success setup ' test_tick && git commit -m first && git tag first && + echo world >>file && git add file && test_tick && git commit -s -F msg && git tag second && + git format-patch --stdout first >patch1 && { echo "X-Fake-Field: Line One" && @@ -89,74 +96,101 @@ test_expect_success setup ' echo "X-Fake-Field: Line Three" && git format-patch --stdout first | sed -e "1d" } | append_cr >patch1-crlf.eml && + sed -n -e "3,\$p" msg >file && git add file && test_tick && git commit -m third && + git format-patch --stdout first >patch2 && + git checkout -b lorem && sed -n -e "11,\$p" msg >file && head -n 9 msg >>file && test_tick && git commit -a -m "moved stuff" && + echo goodbye >another && git add another && test_tick && git commit -m "added another file" && - git format-patch --stdout master >lorem-move.patch -' -# reset time -unset test_tick -test_tick + git format-patch --stdout master >lorem-move.patch && + + git checkout -b rename && + git mv file renamed && + git commit -m "renamed a file" && + + git format-patch -M --stdout lorem >rename.patch && + + git reset --soft lorem^ && + git commit -m "renamed a file and added another" && + + git format-patch -M --stdout lorem^ >rename-add.patch && + + # reset time + unset test_tick && + test_tick +' test_expect_success 'am applies patch correctly' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am <patch1 && ! test -d .git/rebase-apply && - test -z "$(git diff second)" && + git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' test_expect_success 'am applies patch e-mail not in a mbox' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && git am patch1.eml && ! test -d .git/rebase-apply && - test -z "$(git diff second)" && + git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' test_expect_success 'am applies patch e-mail not in a mbox with CRLF' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && git am patch1-crlf.eml && ! test -d .git/rebase-apply && - test -z "$(git diff second)" && + git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' -GIT_AUTHOR_NAME="Another Thor" -GIT_AUTHOR_EMAIL="a.thor@example.com" -GIT_COMMITTER_NAME="Co M Miter" -GIT_COMMITTER_EMAIL="c.miter@example.com" -export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL +test_expect_success 'setup: new author and committer' ' + GIT_AUTHOR_NAME="Another Thor" && + GIT_AUTHOR_EMAIL="a.thor@example.com" && + GIT_COMMITTER_NAME="Co M Miter" && + GIT_COMMITTER_EMAIL="c.miter@example.com" && + export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL +' compare () { - test "$(git cat-file commit "$2" | grep "^$1 ")" = \ - "$(git cat-file commit "$3" | grep "^$1 ")" + a=$(git cat-file commit "$2" | grep "^$1 ") && + b=$(git cat-file commit "$3" | grep "^$1 ") && + test "$a" = "$b" } test_expect_success 'am changes committer and keeps author' ' test_tick && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && git am patch2 && ! test -d .git/rebase-apply && test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" && - test -z "$(git diff master..HEAD)" && - test -z "$(git diff master^..HEAD^)" && + git diff --exit-code master..HEAD && + git diff --exit-code master^..HEAD^ && compare author master HEAD && compare author master^ HEAD^ && test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \ @@ -164,41 +198,55 @@ test_expect_success 'am changes committer and keeps author' ' ' test_expect_success 'am --signoff adds Signed-off-by: line' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout -b master2 first && git am --signoff <patch2 && + printf "%s\n" "$signoff" >expected && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected && git cat-file commit HEAD^ | grep "Signed-off-by:" >actual && - test_cmp actual expected && + test_cmp expected actual && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected && git cat-file commit HEAD | grep "Signed-off-by:" >actual && - test_cmp actual expected + test_cmp expected actual ' test_expect_success 'am stays in branch' ' - test "refs/heads/master2" = "$(git symbolic-ref HEAD)" + echo refs/heads/master2 >expected && + git symbolic-ref HEAD >actual && + test_cmp expected actual ' test_expect_success 'am --signoff does not add Signed-off-by: line if already there' ' git format-patch --stdout HEAD^ >patch3 && sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2," patch3 >patch4 + rm -fr .git/rebase-apply && + git reset --hard && git checkout HEAD^ && git am --signoff patch4 && - test "$(git cat-file commit HEAD | grep -c "^Signed-off-by:")" -eq 1 + git cat-file commit HEAD >actual && + test $(grep -c "^Signed-off-by:" actual) -eq 1 ' test_expect_success 'am without --keep removes Re: and [PATCH] stuff' ' - test "$(git rev-parse HEAD)" = "$(git rev-parse master2)" + git rev-parse HEAD >expected && + git rev-parse master2 >actual && + test_cmp expected actual ' test_expect_success 'am --keep really keeps the subject' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout HEAD^ && git am --keep patch4 && ! test -d .git/rebase-apply && - git cat-file commit HEAD | - fgrep "Re: Re: Re: [PATCH 1/5 v2] third" + git cat-file commit HEAD >actual && + grep "Re: Re: Re: \[PATCH 1/5 v2\] third" actual ' test_expect_success 'am -3 falls back to 3-way merge' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout -b lorem2 master2 && sed -n -e "3,\$p" msg >file && head -n 9 msg >>file && @@ -207,34 +255,75 @@ test_expect_success 'am -3 falls back to 3-way merge' ' git commit -m "copied stuff" && git am -3 lorem-move.patch && ! test -d .git/rebase-apply && - test -z "$(git diff lorem)" + git diff --exit-code lorem +' + +test_expect_success 'am can rename a file' ' + grep "^rename from" rename.patch && + rm -fr .git/rebase-apply && + git reset --hard && + git checkout lorem^0 && + git am rename.patch && + ! test -d .git/rebase-apply && + git update-index --refresh && + git diff --exit-code rename +' + +test_expect_success 'am -3 can rename a file' ' + grep "^rename from" rename.patch && + rm -fr .git/rebase-apply && + git reset --hard && + git checkout lorem^0 && + git am -3 rename.patch && + ! test -d .git/rebase-apply && + git update-index --refresh && + git diff --exit-code rename +' + +test_expect_success 'am -3 can rename a file after falling back to 3-way merge' ' + grep "^rename from" rename-add.patch && + rm -fr .git/rebase-apply && + git reset --hard && + git checkout lorem^0 && + git am -3 rename-add.patch && + ! test -d .git/rebase-apply && + git update-index --refresh && + git diff --exit-code rename ' test_expect_success 'am -3 -q is quiet' ' + rm -fr .git/rebase-apply && + git checkout -f lorem2 && git reset master2 --hard && sed -n -e "3,\$p" msg >file && head -n 9 msg >>file && git add file && test_tick && git commit -m "copied stuff" && - git am -3 -q lorem-move.patch > output.out 2>&1 && + git am -3 -q lorem-move.patch >output.out 2>&1 && ! test -s output.out ' test_expect_success 'am pauses on conflict' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test -d .git/rebase-apply ' test_expect_success 'am --skip works' ' + echo goodbye >expected && git am --skip && ! test -d .git/rebase-apply && - test -z "$(git diff lorem2^^ -- file)" && - test goodbye = "$(cat another)" + git diff --exit-code lorem2^^ -- file && + test_cmp expected another ' test_expect_success 'am --resolved works' ' + echo goodbye >expected && + rm -fr .git/rebase-apply && + git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test -d .git/rebase-apply && @@ -242,22 +331,29 @@ test_expect_success 'am --resolved works' ' git add file && git am --resolved && ! test -d .git/rebase-apply && - test goodbye = "$(cat another)" + test_cmp expected another ' test_expect_success 'am takes patches from a Pine mailbox' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && cat pine patch1 | git am && ! test -d .git/rebase-apply && - test -z "$(git diff master^..HEAD)" + git diff --exit-code master^..HEAD ' test_expect_success 'am fails on mail without patch' ' + rm -fr .git/rebase-apply && + git reset --hard && test_must_fail git am <failmail && - rm -r .git/rebase-apply/ + git am --abort && + ! test -d .git/rebase-apply ' test_expect_success 'am fails on empty patch' ' + rm -fr .git/rebase-apply && + git reset --hard && echo "---" >>failmail && test_must_fail git am <failmail && git am --skip && @@ -266,28 +362,34 @@ test_expect_success 'am fails on empty patch' ' test_expect_success 'am works from stdin in subdirectory' ' rm -fr subdir && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && ( mkdir -p subdir && cd subdir && git am <../patch1 ) && - test -z "$(git diff second)" + git diff --exit-code second ' test_expect_success 'am works from file (relative path given) in subdirectory' ' rm -fr subdir && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && ( mkdir -p subdir && cd subdir && git am ../patch1 ) && - test -z "$(git diff second)" + git diff --exit-code second ' test_expect_success 'am works from file (absolute path given) in subdirectory' ' rm -fr subdir && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && P=$(pwd) && ( @@ -295,27 +397,31 @@ test_expect_success 'am works from file (absolute path given) in subdirectory' ' cd subdir && git am "$P/patch1" ) && - test -z "$(git diff second)" + git diff --exit-code second ' test_expect_success 'am --committer-date-is-author-date' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am --committer-date-is-author-date patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && - at=$(sed -ne "/^author /s/.*> //p" head1) && - ct=$(sed -ne "/^committer /s/.*> //p" head1) && - test "$at" = "$ct" + sed -ne "/^author /s/.*> //p" head1 >at && + sed -ne "/^committer /s/.*> //p" head1 >ct && + test_cmp at ct ' test_expect_success 'am without --committer-date-is-author-date' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && - at=$(sed -ne "/^author /s/.*> //p" head1) && - ct=$(sed -ne "/^committer /s/.*> //p" head1) && - test "$at" != "$ct" + sed -ne "/^author /s/.*> //p" head1 >at && + sed -ne "/^committer /s/.*> //p" head1 >ct && + ! test_cmp at ct ' # This checks for +0000 because TZ is set to UTC and that should @@ -323,41 +429,51 @@ test_expect_success 'am without --committer-date-is-author-date' ' # by test_tick that uses -0700 timezone; if this feature does not # work, we will see that instead of +0000. test_expect_success 'am --ignore-date' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am --ignore-date patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && - at=$(sed -ne "/^author /s/.*> //p" head1) && - echo "$at" | grep "+0000" + sed -ne "/^author /s/.*> //p" head1 >at && + grep "+0000" at ' test_expect_success 'am into an unborn branch' ' + git rev-parse first^{tree} >expected && + rm -fr .git/rebase-apply && + git reset --hard && rm -fr subdir && - mkdir -p subdir && + mkdir subdir && git format-patch --numbered-files -o subdir -1 first && ( cd subdir && git init && git am 1 ) && - result=$( - cd subdir && git rev-parse HEAD^{tree} + ( + cd subdir && + git rev-parse HEAD^{tree} >../actual ) && - test "z$result" = "z$(git rev-parse first^{tree})" + test_cmp expected actual ' test_expect_success 'am newline in subject' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && - sed -e "s/second/second \\\n foo/" patch1 > patchnl && - git am < patchnl > output.out 2>&1 && + sed -e "s/second/second \\\n foo/" patch1 >patchnl && + git am <patchnl >output.out 2>&1 && grep "^Applying: second \\\n foo$" output.out ' test_expect_success 'am -q is quiet' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && - git am -q < patch1 > output.out 2>&1 && + git am -q <patch1 >output.out 2>&1 && ! test -s output.out ' diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index 203ffdb17a..4185b7ca1d 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -219,6 +219,12 @@ test_expect_success 'bisect and replacements' ' git bisect reset ' +test_expect_success 'index-pack and replacements' ' + git --no-replace-objects rev-list --objects HEAD | + git --no-replace-objects pack-objects test- && + git index-pack test-*.pack +' + # # test_done diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 0da13a8d6b..2c55801ee8 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -143,11 +143,12 @@ test_expect_success 'more setup' ' test_expect_success 'use index-filter to move into a subdirectory' ' git branch directorymoved && git filter-branch -f --index-filter \ - "git ls-files -s | sed \"s-\\t-&newsubdir/-\" | + "git ls-files -s | sed \"s- -&newsubdir/-\" | GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \ git update-index --index-info && mv \"\$GIT_INDEX_FILE.new\" \"\$GIT_INDEX_FILE\"" directorymoved && - test -z "$(git diff HEAD directorymoved:newsubdir)"' + git diff --exit-code HEAD directorymoved:newsubdir +' test_expect_success 'stops when msg filter fails' ' old=$(git rev-parse HEAD) && diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 131f032988..2aeed7bd06 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -166,6 +166,63 @@ test_expect_success \ test `git rev-parse --verify master:file2` \ = `git rev-parse --verify verify--import-marks:copy-of-file2`' +test_tick +mt=$(git hash-object --stdin < /dev/null) +: >input.blob +: >marks.exp +: >tree.exp + +cat >input.commit <<EOF +commit refs/heads/verify--dump-marks +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +test the sparse array dumping routines with exponentially growing marks +COMMIT +EOF + +i=0 +l=4 +m=6 +n=7 +while test "$i" -lt 27; do + cat >>input.blob <<EOF +blob +mark :$l +data 0 +blob +mark :$m +data 0 +blob +mark :$n +data 0 +EOF + echo "M 100644 :$l l$i" >>input.commit + echo "M 100644 :$m m$i" >>input.commit + echo "M 100644 :$n n$i" >>input.commit + + echo ":$l $mt" >>marks.exp + echo ":$m $mt" >>marks.exp + echo ":$n $mt" >>marks.exp + + printf "100644 blob $mt\tl$i\n" >>tree.exp + printf "100644 blob $mt\tm$i\n" >>tree.exp + printf "100644 blob $mt\tn$i\n" >>tree.exp + + l=$(($l + $l)) + m=$(($m + $m)) + n=$(($l + $n)) + + i=$((1 + $i)) +done + +sort tree.exp > tree.exp_s + +test_expect_success 'A: export marks with large values' ' + cat input.blob input.commit | git fast-import --export-marks=marks.large && + git ls-tree refs/heads/verify--dump-marks >tree.out && + test_cmp tree.exp_s tree.out && + test_cmp marks.exp marks.large' + ### ### series B ### diff --git a/t/test-lib.sh b/t/test-lib.sh index e5523dd690..29fd7209cf 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -127,14 +127,13 @@ do -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) verbose=t; shift ;; -q|--q|--qu|--qui|--quie|--quiet) - quiet=t; shift ;; + # Ignore --quiet under a TAP::Harness. Saying how many tests + # passed without the ok/not ok details is always an error. + test -z "$HARNESS_ACTIVE" && quiet=t; shift ;; --with-dashes) with_dashes=t; shift ;; --no-color) color=; shift ;; - --no-python) - # noop now... - shift ;; --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind) valgrind=t; verbose=t; shift ;; --tee) @@ -257,6 +256,10 @@ q_to_cr () { tr Q '\015' } +q_to_tab () { + tr Q '\011' +} + append_cr () { sed -e 's/$/Q/' | tr Q '\015' } @@ -40,7 +40,8 @@ void *xmalloc(size_t size) if (!ret && !size) ret = malloc(1); if (!ret) - die("Out of memory, malloc failed"); + die("Out of memory, malloc failed (tried to allocate %lu bytes)", + (unsigned long)size); } #ifdef XMALLOC_POISON memset(ret, 0xA5, size); |