diff options
227 files changed, 2385 insertions, 693 deletions
diff --git a/.gitignore b/.gitignore index acffdfaae6..8572c8c0b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /GIT-BUILD-OPTIONS /GIT-CFLAGS +/GIT-LDFLAGS /GIT-GUI-VARS /GIT-VERSION-FILE /bin-wrappers/ diff --git a/Documentation/.gitignore b/Documentation/.gitignore index 1c3a9fead5..d62aebd848 100644 --- a/Documentation/.gitignore +++ b/Documentation/.gitignore @@ -3,6 +3,7 @@ *.[1-8] *.made *.texi +*.pdf git.info gitman.info howto-index.txt diff --git a/Documentation/Makefile b/Documentation/Makefile index 36989b7f65..18c71d763f 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -232,6 +232,7 @@ cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) clean: $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7 $(RM) *.texi *.texi+ *.texi++ git.info gitman.info + $(RM) *.pdf $(RM) howto-index.txt howto/*.html doc.dep $(RM) technical/api-*.html technical/api-index.txt $(RM) $(cmds_txt) *.made diff --git a/Documentation/RelNotes/1.7.6.1.txt b/Documentation/RelNotes/1.7.6.1.txt new file mode 100644 index 0000000000..42e46ab17f --- /dev/null +++ b/Documentation/RelNotes/1.7.6.1.txt @@ -0,0 +1,63 @@ +Git v1.7.6.1 Release Notes +========================== + +Fixes since v1.7.6 +------------------ + + * Various codepaths that invoked zlib deflate/inflate assumed that these + functions can compress or uncompress more than 4GB data in one call on + platforms with 64-bit long, which has been corrected. + + * "git unexecutable" reported that "unexecutable" was not found, even + though the actual error was that "unexecutable" was found but did + not have a proper she-bang line to be executed. + + * Error exits from $PAGER were silently ignored. + + * "git checkout -b <branch>" was confused when attempting to create a + branch whose name ends with "-g" followed by hexadecimal digits, + and refused to work. + + * "git checkout -b <branch>" sometimes wrote a bogus reflog entry, + causing later "git checkout -" to fail. + + * "git diff --cc" learned to correctly ignore binary files. + + * "git diff -c/--cc" mishandled a deletion that resolves a conflict, and + looked in the working tree instead. + + * "git fast-export" forgot to quote pathnames with unsafe characters + in its output. + + * "git fetch" over smart-http transport used to abort when the + repository was updated between the initial connection and the + subsequent object transfer. + + * "git fetch" did not recurse into submodules in subdirectories. + + * "git ls-tree" did not error out when asked to show a corrupt tree. + + * "git pull" without any argument left an extra whitespace after the + command name in its reflog. + + * "git push --quiet" was not really quiet. + + * "git rebase -i -p" incorrectly dropped commits from side branches. + + * "git reset [<commit>] paths..." did not reset the index entry correctly + for unmerged paths. + + * "git submodule add" did not allow a relative repository path when + the superproject did not have any default remote url. + + * "git submodule foreach" failed to correctly give the standard input to + the user-supplied command it invoked. + + * submodules that the user has never showed interest in by running + "git submodule init" was incorrectly marked as interesting by "git + submodule sync". + + * "git submodule update --quiet" was not really quiet. + + * "git tag -l <glob>..." did not take multiple glob patterns from the + command line. diff --git a/Documentation/RelNotes/1.7.6.2.txt b/Documentation/RelNotes/1.7.6.2.txt new file mode 100644 index 0000000000..67ae414965 --- /dev/null +++ b/Documentation/RelNotes/1.7.6.2.txt @@ -0,0 +1,8 @@ +Git v1.7.6.2 Release Notes +========================== + +Fixes since v1.7.6.1 +-------------------- + + * v1.7.6.1 broke "git push --quiet"; it used to be a no-op against an old + version of Git running on the other end, but v1.7.6.1 made it abort. diff --git a/Documentation/RelNotes/1.7.6.3.txt b/Documentation/RelNotes/1.7.6.3.txt new file mode 100644 index 0000000000..95971831b9 --- /dev/null +++ b/Documentation/RelNotes/1.7.6.3.txt @@ -0,0 +1,24 @@ +Git v1.7.6.3 Release Notes +========================== + +Fixes since v1.7.6.2 +-------------------- + + * "git -c var=value subcmd" misparsed the custom configuration when + value contained an equal sign. + + * "git fetch" had a major performance regression, wasting many + needless cycles in a repository where there is no submodules + present. This was especially bad, when there were many refs. + + * "git reflog $refname" did not default to the "show" subcommand as + the documentation advertised the command to do. + + * "git reset" did not leave meaningful log message in the reflog. + + * "git status --ignored" did not show ignored items when there is no + untracked items. + + * "git tag --contains $commit" was unnecessarily inefficient. + +Also contains minor fixes and documentation updates. diff --git a/Documentation/RelNotes/1.7.6.4.txt b/Documentation/RelNotes/1.7.6.4.txt new file mode 100644 index 0000000000..e19acac2da --- /dev/null +++ b/Documentation/RelNotes/1.7.6.4.txt @@ -0,0 +1,32 @@ +Git v1.7.6.4 Release Notes +========================== + +Fixes since v1.7.6.3 +-------------------- + + * The error reporting logic of "git am" when the command is fed a file + whose mail-storage format is unknown was fixed. + + * "git branch --set-upstream @{-1} foo" did not expand @{-1} correctly. + + * "git check-ref-format --print" used to parrot a candidate string that + began with a slash (e.g. /refs/heads/master) without stripping it, to make + the result a suitably normalized string the caller can append to "$GIT_DIR/". + + * "git clone" failed to clone locally from a ".git" file that itself + is not a directory but is a pointer to one. + + * "git clone" from a local repository that borrows from another + object store using a relative path in its objects/info/alternates + file did not adjust the alternates in the resulting repository. + + * "git describe --dirty" did not refresh the index before checking the + state of the working tree files. + + * "git ls-files ../$path" that is run from a subdirectory reported errors + incorrectly when there is no such path that matches the given pathspec. + + * "git mergetool" could loop forever prompting when nothing can be read + from the standard input. + +Also contains minor fixes and documentation updates. diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 938eccf2a5..0dbf2c9843 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -134,8 +134,7 @@ Another thing: NULL pointers shall be written as NULL, not as 0. (2) Generate your patch using git tools out of your commits. -git based diff tools (git, Cogito, and StGIT included) generate -unidiff which is the preferred format. +git based diff tools generate unidiff which is the preferred format. You do not have to be afraid to use -M option to "git diff" or "git format-patch", if your patch involves file renames. The diff --git a/Documentation/config.txt b/Documentation/config.txt index 6b93777199..ae9913b034 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -344,7 +344,9 @@ core.logAllRefUpdates:: SHA1, the date/time and the reason of the update, but only when the file exists. If this configuration variable is set to true, missing "$GIT_DIR/logs/<ref>" - file is automatically created for branch heads. + file is automatically created for branch heads (i.e. under + refs/heads/), remote refs (i.e. under refs/remotes/), + note refs (i.e. under refs/notes/), and the symbolic ref HEAD. + This information can be used to determine what commit was the tip of a branch "2 days ago". @@ -676,7 +678,7 @@ branch.<name>.rebase:: browser.<tool>.cmd:: Specify the command to invoke the specified browser. The specified command is evaluated in shell with the URLs passed - as arguments. (See linkgit:git-web--browse[1].) + as arguments. (See linkgit:git-web{litdd}browse[1].) browser.<tool>.path:: Override the path for the given tool that may be used to diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 24f189f96b..659de6f123 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -416,6 +416,17 @@ endif::git-format-patch[] --no-ext-diff:: Disallow external diff drivers. +--textconv:: +--no-textconv:: + Allow (or disallow) external text conversion filters to be run + when comparing binary files. See linkgit:gitattributes[5] for + details. Because textconv filters are typically a one-way + conversion, the resulting diff is suitable for human + consumption, but cannot be applied. For this reason, textconv + filters are enabled by default only for linkgit:git-diff[1] and + linkgit:git-log[1], but not for linkgit:git-format-patch[1] or + diff plumbing commands. + --ignore-submodules[=<when>]:: Ignore changes to submodules in the diff generation. <when> can be either "none", "untracked", "dirty" or "all", which is the default diff --git a/Documentation/git-annotate.txt b/Documentation/git-annotate.txt index 9eb75c37da..05fd482b74 100644 --- a/Documentation/git-annotate.txt +++ b/Documentation/git-annotate.txt @@ -7,6 +7,7 @@ git-annotate - Annotate file lines with commit information SYNOPSIS -------- +[verse] 'git annotate' [options] file [revision] DESCRIPTION diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index 7b7bafba0c..ab60a18470 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -8,6 +8,7 @@ git-bisect - Find by binary search the change that introduced a bug SYNOPSIS -------- +[verse] 'git bisect' <subcommand> <options> DESCRIPTION diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt index 205d83dd0b..c9fdf84a08 100644 --- a/Documentation/git-check-ref-format.txt +++ b/Documentation/git-check-ref-format.txt @@ -18,9 +18,12 @@ Checks if a given 'refname' is acceptable, and exits with a non-zero status if it is not. A reference is used in git to specify branches and tags. A -branch head is stored under the `$GIT_DIR/refs/heads` directory, and -a tag is stored under the `$GIT_DIR/refs/tags` directory (or, if refs -are packed by `git gc`, as entries in the `$GIT_DIR/packed-refs` file). +branch head is stored in the `refs/heads` hierarchy, while +a tag is stored in the `refs/tags` hierarchy of the ref namespace +(typically in `$GIT_DIR/refs/heads` and `$GIT_DIR/refs/tags` +directories or, as entries in file `$GIT_DIR/packed-refs` +if refs are packed by `git gc`). + git imposes the following rules on how references are named: . They can include slash `/` for hierarchical (directory) diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 9d8fe0d261..6c9c2cb383 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -7,6 +7,7 @@ git-cherry-pick - Apply the changes introduced by some existing commits SYNOPSIS -------- +[verse] 'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>... DESCRIPTION diff --git a/Documentation/git-cherry.txt b/Documentation/git-cherry.txt index 79448c505b..f6c19c734d 100644 --- a/Documentation/git-cherry.txt +++ b/Documentation/git-cherry.txt @@ -7,6 +7,7 @@ git-cherry - Find commits not merged upstream SYNOPSIS -------- +[verse] 'git cherry' [-v] [<upstream> [<head> [<limit>]]] DESCRIPTION diff --git a/Documentation/git-citool.txt b/Documentation/git-citool.txt index 6e5c8126f5..c7a11c36c1 100644 --- a/Documentation/git-citool.txt +++ b/Documentation/git-citool.txt @@ -7,6 +7,7 @@ git-citool - Graphical alternative to git-commit SYNOPSIS -------- +[verse] 'git citool' DESCRIPTION diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt index f524d76019..0fdb82ee86 100644 --- a/Documentation/git-commit-tree.txt +++ b/Documentation/git-commit-tree.txt @@ -8,6 +8,7 @@ git-commit-tree - Create a new commit object SYNOPSIS -------- +[verse] 'git commit-tree' <tree> [(-p <parent commit>)...] < changelog DESCRIPTION diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 7951cb7b00..5cc84a1391 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -284,7 +284,7 @@ When recording your own work, the contents of modified files in your working tree are temporarily stored to a staging area called the "index" with 'git add'. A file can be reverted back, only in the index but not in the working tree, -to that of the last commit with `git reset HEAD -- <file>`, +to that of the last commit with `git reset HEAD \-- <file>`, which effectively reverts 'git add' and prevents the changes to this file from participating in the next commit. After building the state to be committed incrementally with these commands, diff --git a/Documentation/git-count-objects.txt b/Documentation/git-count-objects.txt index a73933a931..23c80cea64 100644 --- a/Documentation/git-count-objects.txt +++ b/Documentation/git-count-objects.txt @@ -7,6 +7,7 @@ git-count-objects - Count unpacked number of objects and their disk consumption SYNOPSIS -------- +[verse] 'git count-objects' [-v] DESCRIPTION diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt index ad93a3e84e..7f79cec3f8 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.txt @@ -8,6 +8,7 @@ git-cvsexportcommit - Export a single commit to a CVS checkout SYNOPSIS -------- +[verse] 'git cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-w cvsworkdir] [-W] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt index 8d481948bd..906774f0f7 100644 --- a/Documentation/git-diff-files.txt +++ b/Documentation/git-diff-files.txt @@ -8,6 +8,7 @@ git-diff-files - Compares files in the working tree and the index SYNOPSIS -------- +[verse] 'git diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...] DESCRIPTION diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt index 2ea22abca2..c0b7c581ad 100644 --- a/Documentation/git-diff-index.txt +++ b/Documentation/git-diff-index.txt @@ -8,6 +8,7 @@ git-diff-index - Compares content and mode of blobs between the index and reposi SYNOPSIS -------- +[verse] 'git diff-index' [-m] [--cached] [<common diff options>] <tree-ish> [<path>...] DESCRIPTION diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt index 590f410abf..a03515f1ec 100644 --- a/Documentation/git-difftool.txt +++ b/Documentation/git-difftool.txt @@ -7,6 +7,7 @@ git-difftool - Show changes using common diff tools SYNOPSIS -------- +[verse] 'git difftool' [<options>] [<commit> [<commit>]] [--] [<path>...] DESCRIPTION diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt index 781bd6edc3..a29ac021d9 100644 --- a/Documentation/git-fast-export.txt +++ b/Documentation/git-fast-export.txt @@ -8,6 +8,7 @@ git-fast-export - Git data exporter SYNOPSIS -------- +[verse] 'git fast-export [options]' | 'git fast-import' DESCRIPTION diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 249249aac7..95e480ef79 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -8,6 +8,7 @@ git-fast-import - Backend for fast Git data importers SYNOPSIS -------- +[verse] frontend | 'git fast-import' [options] DESCRIPTION @@ -648,9 +649,14 @@ paths for a commit are encouraged to do so. `notemodify` ^^^^^^^^^^^^ -Included in a `commit` command to add a new note (annotating a given -commit) or change the content of an existing note. This command has -two different means of specifying the content of the note. +Included in a `commit` `<notes_ref>` command to add a new note +annotating a `<committish>` or change this annotation contents. +Internally it is similar to filemodify 100644 on `<committish>` +path (maybe split into subdirectories). It's not advised to +use any other commands to write to the `<notes_ref>` tree except +`filedeleteall` to delete all existing notes in this tree. +This command has two different means of specifying the content +of the note. External data format:: The data content for the note was already supplied by a prior diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index 48d4bf6d68..ed1bdaacd1 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -8,6 +8,7 @@ git-fetch-pack - Receive missing objects from another repository SYNOPSIS -------- +[verse] 'git fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...] DESCRIPTION diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt index 60ac8d26eb..b41d7c1de1 100644 --- a/Documentation/git-fetch.txt +++ b/Documentation/git-fetch.txt @@ -8,12 +8,10 @@ git-fetch - Download objects and refs from another repository SYNOPSIS -------- +[verse] 'git fetch' [<options>] [<repository> [<refspec>...]] - 'git fetch' [<options>] <group> - 'git fetch' --multiple [<options>] [(<repository> | <group>)...] - 'git fetch' --all [<options>] diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index 9dc1f2a947..0f2f117383 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -32,8 +32,9 @@ changes, which would normally have no effect. Nevertheless, this may be useful in the future for compensating for some git bugs or such, therefore such a usage is permitted. -*NOTE*: This command honors `.git/info/grafts`. If you have any grafts -defined, running this command will make them permanent. +*NOTE*: This command honors `.git/info/grafts` and `.git/refs/replace/`. +If you have any grafts or replacement refs defined, running this command +will make them permanent. *WARNING*! The rewritten history will have different object names for all the objects and will not converge with the original branch. You will not diff --git a/Documentation/git-fsck-objects.txt b/Documentation/git-fsck-objects.txt index 90ebb8a594..eec4bdb600 100644 --- a/Documentation/git-fsck-objects.txt +++ b/Documentation/git-fsck-objects.txt @@ -8,6 +8,7 @@ git-fsck-objects - Verifies the connectivity and validity of the objects in the SYNOPSIS -------- +[verse] 'git fsck-objects' ... DESCRIPTION diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt index 4966cb5784..815afcb922 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.txt @@ -8,6 +8,7 @@ git-gc - Cleanup unnecessary files and optimize the local repository SYNOPSIS -------- +[verse] 'git gc' [--aggressive] [--auto] [--quiet] [--prune=<date> | --no-prune] DESCRIPTION diff --git a/Documentation/git-get-tar-commit-id.txt b/Documentation/git-get-tar-commit-id.txt index 8035736c96..1e2a20dd26 100644 --- a/Documentation/git-get-tar-commit-id.txt +++ b/Documentation/git-get-tar-commit-id.txt @@ -8,6 +8,7 @@ git-get-tar-commit-id - Extract commit ID from an archive created using git-arch SYNOPSIS -------- +[verse] 'git get-tar-commit-id' < <tarfile> diff --git a/Documentation/git-gui.txt b/Documentation/git-gui.txt index 32a833e0ae..18f713b67a 100644 --- a/Documentation/git-gui.txt +++ b/Documentation/git-gui.txt @@ -7,6 +7,7 @@ git-gui - A portable graphical interface to Git SYNOPSIS -------- +[verse] 'git gui' [<command>] [arguments] DESCRIPTION diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt index 42aa2b0c01..9e0b3f6811 100644 --- a/Documentation/git-help.txt +++ b/Documentation/git-help.txt @@ -7,6 +7,7 @@ git-help - display help information about git SYNOPSIS -------- +[verse] 'git help' [-a|--all|-i|--info|-m|--man|-w|--web] [COMMAND] DESCRIPTION diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.txt index fefa752198..4d42073867 100644 --- a/Documentation/git-http-fetch.txt +++ b/Documentation/git-http-fetch.txt @@ -8,6 +8,7 @@ git-http-fetch - Download from a remote git repository via HTTP SYNOPSIS -------- +[verse] 'git http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin] <commit> <url> DESCRIPTION diff --git a/Documentation/git-http-push.txt b/Documentation/git-http-push.txt index 82ae34b9b8..2e67362bd4 100644 --- a/Documentation/git-http-push.txt +++ b/Documentation/git-http-push.txt @@ -8,6 +8,7 @@ git-http-push - Push objects over HTTP/DAV to another repository SYNOPSIS -------- +[verse] 'git http-push' [--all] [--dry-run] [--force] [--verbose] <url> <ref> [<ref>...] DESCRIPTION diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt index 4e09708cc9..875d2831a5 100644 --- a/Documentation/git-imap-send.txt +++ b/Documentation/git-imap-send.txt @@ -8,6 +8,7 @@ git-imap-send - Send a collection of patches from stdin to an IMAP folder SYNOPSIS -------- +[verse] 'git imap-send' diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt index 9f97f5a915..a21e346789 100644 --- a/Documentation/git-init-db.txt +++ b/Documentation/git-init-db.txt @@ -8,6 +8,7 @@ git-init-db - Creates an empty git repository SYNOPSIS -------- +[verse] 'git init-db' [-q | --quiet] [--bare] [--template=<template_directory>] [--separate-git-dir <git dir>] [--shared[=<permissions>]] diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt index f2777a7786..9ac2bbaa56 100644 --- a/Documentation/git-init.txt +++ b/Documentation/git-init.txt @@ -8,6 +8,7 @@ git-init - Create an empty git repository or reinitialize an existing one SYNOPSIS -------- +[verse] 'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--separate-git-dir <git dir>] [--shared[=<permissions>]] [directory] diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index de5c0d37a5..771a3565bd 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -8,6 +8,7 @@ git-log - Show commit logs SYNOPSIS -------- +[verse] 'git log' [<options>] [<since>..<until>] [[\--] <path>...] DESCRIPTION @@ -68,10 +69,13 @@ produced by --stat etc. its size is not included. [\--] <path>...:: - Show only commits that affect any of the specified paths. To - prevent confusion with options and branch names, paths may need - to be prefixed with "\-- " to separate them from options or - refnames. + Show only commits that are enough to explain how the files + that match the specified paths came to be. See "History + Simplification" below for details and other simplification + modes. ++ +To prevent confusion with options and branch names, paths may need to +be prefixed with "\-- " to separate them from options or refnames. include::rev-list-options.txt[] diff --git a/Documentation/git-lost-found.txt b/Documentation/git-lost-found.txt index adf7e1c055..c406a11001 100644 --- a/Documentation/git-lost-found.txt +++ b/Documentation/git-lost-found.txt @@ -7,6 +7,7 @@ git-lost-found - Recover lost refs that luckily have not yet been pruned SYNOPSIS -------- +[verse] 'git lost-found' DESCRIPTION diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt index ed45662cc9..51dc325748 100644 --- a/Documentation/git-mailinfo.txt +++ b/Documentation/git-mailinfo.txt @@ -8,6 +8,7 @@ git-mailinfo - Extracts patch and authorship from a single e-mail message SYNOPSIS -------- +[verse] 'git mailinfo' [-k|-b] [-u | --encoding=<encoding> | -n] [--scissors] <msg> <patch> diff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt index 9b2049d674..4d1b871d96 100644 --- a/Documentation/git-mailsplit.txt +++ b/Documentation/git-mailsplit.txt @@ -7,6 +7,7 @@ git-mailsplit - Simple UNIX mbox splitter program SYNOPSIS -------- +[verse] 'git mailsplit' [-b] [-f<nn>] [-d<prec>] [--keep-cr] -o<directory> [--] [(<mbox>|<Maildir>)...] DESCRIPTION diff --git a/Documentation/git-merge-index.txt b/Documentation/git-merge-index.txt index 6ce54673b0..e0df1b3340 100644 --- a/Documentation/git-merge-index.txt +++ b/Documentation/git-merge-index.txt @@ -8,6 +8,7 @@ git-merge-index - Run a merge for files needing merging SYNOPSIS -------- +[verse] 'git merge-index' [-o] [-q] <merge-program> (-a | [--] <file>*) DESCRIPTION diff --git a/Documentation/git-merge-one-file.txt b/Documentation/git-merge-one-file.txt index ee059def79..04e803d5d3 100644 --- a/Documentation/git-merge-one-file.txt +++ b/Documentation/git-merge-one-file.txt @@ -8,6 +8,7 @@ git-merge-one-file - The standard helper program to use with git-merge-index SYNOPSIS -------- +[verse] 'git merge-one-file' DESCRIPTION diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 3bfa7b4220..c5f84b6495 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -8,6 +8,7 @@ git-merge-tree - Show three-way merge without touching index SYNOPSIS -------- +[verse] 'git merge-tree' <base-tree> <branch1> <branch2> DESCRIPTION diff --git a/Documentation/git-mergetool--lib.txt b/Documentation/git-mergetool--lib.txt index 63ededec1d..f98a41b87c 100644 --- a/Documentation/git-mergetool--lib.txt +++ b/Documentation/git-mergetool--lib.txt @@ -7,7 +7,8 @@ git-mergetool--lib - Common git merge tool shell scriptlets SYNOPSIS -------- -'TOOL_MODE=(diff|merge) . "$(git --exec-path)/git-mergetool--lib"' +[verse] +'TOOL_MODE=(diff|merge) . "$(git --exec-path)/git-mergetool{litdd}lib"' DESCRIPTION ----------- diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index 8c79ae8d2a..3470910109 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -7,6 +7,7 @@ git-mergetool - Run merge conflict resolution tools to resolve merge conflicts SYNOPSIS -------- +[verse] 'git mergetool' [--tool=<tool>] [-y|--no-prompt|--prompt] [<file>...] DESCRIPTION diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt index 037ab1045d..65e167a5c5 100644 --- a/Documentation/git-mktag.txt +++ b/Documentation/git-mktag.txt @@ -8,6 +8,7 @@ git-mktag - Creates a tag object SYNOPSIS -------- +[verse] 'git mktag' < signature_file DESCRIPTION diff --git a/Documentation/git-mktree.txt b/Documentation/git-mktree.txt index afe21be64d..5c6ebdfad9 100644 --- a/Documentation/git-mktree.txt +++ b/Documentation/git-mktree.txt @@ -8,6 +8,7 @@ git-mktree - Build a tree-object from ls-tree formatted text SYNOPSIS -------- +[verse] 'git mktree' [-z] [--missing] [--batch] DESCRIPTION diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt index db0e030d69..b8db373964 100644 --- a/Documentation/git-mv.txt +++ b/Documentation/git-mv.txt @@ -8,6 +8,7 @@ git-mv - Move or rename a file, a directory, or a symlink SYNOPSIS -------- +[verse] 'git mv' <options>... <args>... DESCRIPTION diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt index db9f0f7055..f2869da572 100644 --- a/Documentation/git-pack-redundant.txt +++ b/Documentation/git-pack-redundant.txt @@ -8,6 +8,7 @@ git-pack-redundant - Find redundant pack files SYNOPSIS -------- +[verse] 'git pack-redundant' [ --verbose ] [ --alt-odb ] < --all | .pack filename ... > DESCRIPTION diff --git a/Documentation/git-pack-refs.txt b/Documentation/git-pack-refs.txt index 54b92534ce..a3c6677bfa 100644 --- a/Documentation/git-pack-refs.txt +++ b/Documentation/git-pack-refs.txt @@ -7,6 +7,7 @@ git-pack-refs - Pack heads and tags for efficient repository access SYNOPSIS -------- +[verse] 'git pack-refs' [--all] [--no-prune] DESCRIPTION diff --git a/Documentation/git-parse-remote.txt b/Documentation/git-parse-remote.txt index 02217f6ba2..a45ea1ece8 100644 --- a/Documentation/git-parse-remote.txt +++ b/Documentation/git-parse-remote.txt @@ -8,6 +8,7 @@ git-parse-remote - Routines to help parsing remote repository access parameters SYNOPSIS -------- +[verse] '. "$(git --exec-path)/git-parse-remote"' DESCRIPTION diff --git a/Documentation/git-patch-id.txt b/Documentation/git-patch-id.txt index 50e26f43c1..90268f02e7 100644 --- a/Documentation/git-patch-id.txt +++ b/Documentation/git-patch-id.txt @@ -7,6 +7,7 @@ git-patch-id - Compute unique ID for a patch SYNOPSIS -------- +[verse] 'git patch-id' < <patch> DESCRIPTION diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt index a34d62f0da..87ea3fb054 100644 --- a/Documentation/git-peek-remote.txt +++ b/Documentation/git-peek-remote.txt @@ -8,6 +8,7 @@ git-peek-remote - List the references in a remote repository SYNOPSIS -------- +[verse] 'git peek-remote' [--upload-pack=<git-upload-pack>] [<host>:]<directory> DESCRIPTION diff --git a/Documentation/git-prune-packed.txt b/Documentation/git-prune-packed.txt index 9e6202cdff..80dc022ede 100644 --- a/Documentation/git-prune-packed.txt +++ b/Documentation/git-prune-packed.txt @@ -8,6 +8,7 @@ git-prune-packed - Remove extra objects that are already in pack files SYNOPSIS -------- +[verse] 'git prune-packed' [-n|--dry-run] [-q|--quiet] diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt index f616a739ef..80d01b0571 100644 --- a/Documentation/git-prune.txt +++ b/Documentation/git-prune.txt @@ -8,6 +8,7 @@ git-prune - Prune all unreachable objects from the object database SYNOPSIS -------- +[verse] 'git prune' [-n] [-v] [--expire <expire>] [--] [<head>...] DESCRIPTION diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt index 14609cbd4d..e1da468766 100644 --- a/Documentation/git-pull.txt +++ b/Documentation/git-pull.txt @@ -8,6 +8,7 @@ git-pull - Fetch from and merge with another repository or a local branch SYNOPSIS -------- +[verse] 'git pull' [options] [<repository> [<refspec>...]] diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index c7fc1ceb5e..1bd0317a42 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -8,6 +8,7 @@ git-read-tree - Reads tree information into the index SYNOPSIS -------- +[verse] 'git read-tree' [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]] [--index-output=<file>] [--no-sparse-checkout] diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 9a075bc4d2..504945c691 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -12,7 +12,6 @@ SYNOPSIS [<upstream>] [<branch>] 'git rebase' [-i | --interactive] [options] --onto <newbase> --root [<branch>] - 'git rebase' --continue | --skip | --abort DESCRIPTION @@ -46,7 +45,7 @@ with a different commit message or timestamp will be skipped). It is possible that a merge failure will prevent this process from being completely automatic. You will have to resolve any such merge failure and run `git rebase --continue`. Another option is to bypass the commit -that caused the merge failure with `git rebase --skip`. To restore the +that caused the merge failure with `git rebase --skip`. To check out the original <branch> and remove the .git/rebase-apply working files, use the command `git rebase --abort` instead. @@ -233,7 +232,11 @@ leave out at most one of A and B, in which case it defaults to HEAD. Restart the rebasing process after having resolved a merge conflict. --abort:: - Restore the original branch and abort the rebase operation. + Abort the rebase operation and reset HEAD to the original + branch. If <branch> was provided when the rebase operation was + started, then HEAD will be reset to <branch>. Otherwise HEAD + will be reset to where it was when the rebase operation was + started. --skip:: Restart the rebasing process by skipping the current patch. diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt index f34e0ae1bd..459c08598f 100644 --- a/Documentation/git-receive-pack.txt +++ b/Documentation/git-receive-pack.txt @@ -8,6 +8,7 @@ git-receive-pack - Receive what is pushed into the repository SYNOPSIS -------- +[verse] 'git-receive-pack' <directory> DESCRIPTION diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt index 09057bf90c..976dc14937 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.txt @@ -8,6 +8,7 @@ git-reflog - Manage reflog information SYNOPSIS -------- +[verse] 'git reflog' <subcommand> <options> DESCRIPTION diff --git a/Documentation/git-relink.txt b/Documentation/git-relink.txt index 9893376487..3b33c99510 100644 --- a/Documentation/git-relink.txt +++ b/Documentation/git-relink.txt @@ -7,6 +7,7 @@ git-relink - Hardlink common objects in local repositories SYNOPSIS -------- +[verse] 'git relink' [--safe] <dir>... <master_dir> DESCRIPTION diff --git a/Documentation/git-remote-ext.txt b/Documentation/git-remote-ext.txt index 68263a6a53..8a8e1d775d 100644 --- a/Documentation/git-remote-ext.txt +++ b/Documentation/git-remote-ext.txt @@ -7,6 +7,7 @@ git-remote-ext - Bridge smart transport to external command. SYNOPSIS -------- +[verse] git remote add <nick> "ext::<command>[ <arguments>...]" DESCRIPTION diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt index 58f6ad4994..930b4034ac 100644 --- a/Documentation/git-remote-helpers.txt +++ b/Documentation/git-remote-helpers.txt @@ -7,6 +7,7 @@ git-remote-helpers - Helper programs to interact with remote repositories SYNOPSIS -------- +[verse] 'git remote-<transport>' <repository> [<URL>] DESCRIPTION diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 528f34a131..5a8c5061f3 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -60,11 +60,11 @@ the remote repository. + With `-t <branch>` option, instead of the default glob refspec for the remote to track all branches under -`$GIT_DIR/remotes/<name>/`, a refspec to track only `<branch>` +the `refs/remotes/<name>/` namespace, a refspec to track only `<branch>` is created. You can give more than one `-t <branch>` to track multiple branches without grabbing all branches. + -With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set +With `-m <master>` option, a symbolic-ref `refs/remotes/<name>/HEAD` is set up to point at remote's `<master>` branch. See also the set-head command. + When a fetch mirror is created with `\--mirror=fetch`, the refs will not @@ -92,24 +92,25 @@ configuration settings for the remote are removed. 'set-head':: -Sets or deletes the default branch (`$GIT_DIR/remotes/<name>/HEAD`) for +Sets or deletes the default branch (i.e. the target of the +symbolic-ref `refs/remotes/<name>/HEAD`) for the named remote. Having a default branch for a remote is not required, but allows the name of the remote to be specified in lieu of a specific branch. For example, if the default branch for `origin` is set to `master`, then `origin` may be specified wherever you would normally specify `origin/master`. + -With `-d`, `$GIT_DIR/remotes/<name>/HEAD` is deleted. +With `-d`, the symbolic ref `refs/remotes/<name>/HEAD` is deleted. + -With `-a`, the remote is queried to determine its `HEAD`, then -`$GIT_DIR/remotes/<name>/HEAD` is set to the same branch. e.g., if the remote +With `-a`, the remote is queried to determine its `HEAD`, then the +symbolic-ref `refs/remotes/<name>/HEAD` is set to the same branch. e.g., if the remote `HEAD` is pointed at `next`, "`git remote set-head origin -a`" will set -`$GIT_DIR/refs/remotes/origin/HEAD` to `refs/remotes/origin/next`. This will +the symbolic-ref `refs/remotes/origin/HEAD` to `refs/remotes/origin/next`. This will only work if `refs/remotes/origin/next` already exists; if not it must be fetched first. + -Use `<branch>` to set `$GIT_DIR/remotes/<name>/HEAD` explicitly. e.g., "git -remote set-head origin master" will set `$GIT_DIR/refs/remotes/origin/HEAD` to +Use `<branch>` to set the symbolic-ref `refs/remotes/<name>/HEAD` explicitly. e.g., "git +remote set-head origin master" will set the symbolic-ref `refs/remotes/origin/HEAD` to `refs/remotes/origin/master`. This will only work if `refs/remotes/origin/master` already exists; if not it must be fetched first. + diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index 0decee240b..40af321153 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -8,6 +8,7 @@ git-repack - Pack unpacked objects in a repository SYNOPSIS -------- +[verse] 'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [--window=<n>] [--depth=<n>] DESCRIPTION diff --git a/Documentation/git-repo-config.txt b/Documentation/git-repo-config.txt index a0d1fa6594..9ec115b9e0 100644 --- a/Documentation/git-repo-config.txt +++ b/Documentation/git-repo-config.txt @@ -8,6 +8,7 @@ git-repo-config - Get and set repository or global options SYNOPSIS -------- +[verse] 'git repo-config' ... diff --git a/Documentation/git-request-pull.txt b/Documentation/git-request-pull.txt index 3521d8e3c8..b99681ce85 100644 --- a/Documentation/git-request-pull.txt +++ b/Documentation/git-request-pull.txt @@ -7,6 +7,7 @@ git-request-pull - Generates a summary of pending changes SYNOPSIS -------- +[verse] 'git request-pull' [-p] <start> <url> [<end>] DESCRIPTION diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt index 52db1d80cf..a6253ba617 100644 --- a/Documentation/git-rerere.txt +++ b/Documentation/git-rerere.txt @@ -7,6 +7,7 @@ git-rerere - Reuse recorded resolution of conflicted merges SYNOPSIS -------- +[verse] 'git rerere' ['clear'|'forget' <pathspec>|'diff'|'status'|'gc'] DESCRIPTION diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 02c44c999f..42c9676eaa 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -8,6 +8,7 @@ git-rev-parse - Pick out and massage parameters SYNOPSIS -------- +[verse] 'git rev-parse' [ --option ] <args>... DESCRIPTION diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index ac10cfbb14..3d0a7d1dac 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -7,6 +7,7 @@ git-revert - Revert some existing commits SYNOPSIS -------- +[verse] 'git revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>... DESCRIPTION @@ -23,7 +24,7 @@ throw away all uncommitted changes in your working directory, you should see linkgit:git-reset[1], particularly the '--hard' option. If you want to extract specific files as they were in another commit, you should see linkgit:git-checkout[1], specifically the `git checkout -<commit> -- <filename>` syntax. Take care with these alternatives as +<commit> \-- <filename>` syntax. Take care with these alternatives as both will discard uncommitted changes in your working directory. OPTIONS diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt index 8c0554f971..da0215d20c 100644 --- a/Documentation/git-rm.txt +++ b/Documentation/git-rm.txt @@ -7,6 +7,7 @@ git-rm - Remove files from the working tree and from the index SYNOPSIS -------- +[verse] 'git rm' [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>... DESCRIPTION diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 5a168cfab2..327233c85b 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -8,6 +8,7 @@ git-send-email - Send a collection of patches as emails SYNOPSIS -------- +[verse] 'git send-email' [options] <file|directory|rev-list options>... diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt index 17f8f55526..bd3eaa69bf 100644 --- a/Documentation/git-send-pack.txt +++ b/Documentation/git-send-pack.txt @@ -8,6 +8,7 @@ git-send-pack - Push objects over git protocol to another repository SYNOPSIS -------- +[verse] 'git send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...] DESCRIPTION diff --git a/Documentation/git-sh-i18n--envsubst.txt b/Documentation/git-sh-i18n--envsubst.txt index 61e4c08dac..5c3ec327bb 100644 --- a/Documentation/git-sh-i18n--envsubst.txt +++ b/Documentation/git-sh-i18n--envsubst.txt @@ -1,5 +1,5 @@ -git-sh-i18n--envsubst(1) -======================== +git-sh-i18n{litdd}envsubst(1) +============================= NAME ---- @@ -10,8 +10,8 @@ SYNOPSIS [verse] eval_gettext () { printf "%s" "$1" | ( - export PATH $('git sh-i18n--envsubst' --variables "$1"); - 'git sh-i18n--envsubst' "$1" + export PATH $('git sh-i18n{litdd}envsubst' --variables "$1"); + 'git sh-i18n{litdd}envsubst' "$1" ) } @@ -22,7 +22,7 @@ This is not a command the end user would want to run. Ever. This documentation is meant for people who are studying the plumbing scripts and/or are writing new ones. -git-sh-i18n--envsubst is Git's stripped-down copy of the GNU +'git sh-i18n{litdd}envsubst' is Git's stripped-down copy of the GNU `envsubst(1)` program that comes with the GNU gettext package. It's used internally by linkgit:git-sh-i18n[1] to interpolate the variables passed to the the `eval_gettext` function. diff --git a/Documentation/git-sh-i18n.txt b/Documentation/git-sh-i18n.txt index 3b1f7ac7b5..60cf49cb2a 100644 --- a/Documentation/git-sh-i18n.txt +++ b/Documentation/git-sh-i18n.txt @@ -7,6 +7,7 @@ git-sh-i18n - Git's i18n setup code for shell scripts SYNOPSIS -------- +[verse] '. "$(git --exec-path)/git-sh-i18n"' DESCRIPTION @@ -34,7 +35,7 @@ gettext:: eval_gettext:: Currently a dummy fall-through function implemented as a wrapper around `printf(1)` with variables expanded by the - linkgit:git-sh-i18n--envsubst[1] helper. Will be replaced by a + linkgit:git-sh-i18n{litdd}envsubst[1] helper. Will be replaced by a real gettext implementation in a later version. GIT diff --git a/Documentation/git-sh-setup.txt b/Documentation/git-sh-setup.txt index 27fd8ba854..a2f346ca71 100644 --- a/Documentation/git-sh-setup.txt +++ b/Documentation/git-sh-setup.txt @@ -7,6 +7,7 @@ git-sh-setup - Common git shell script setup code SYNOPSIS -------- +[verse] '. "$(git --exec-path)/git-sh-setup"' DESCRIPTION diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt index d7d4b92894..9b9250600f 100644 --- a/Documentation/git-shell.txt +++ b/Documentation/git-shell.txt @@ -8,6 +8,7 @@ git-shell - Restricted login shell for Git-only SSH access SYNOPSIS -------- +[verse] 'git shell' [-c <command> <argument>] DESCRIPTION diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt index ee4559b6f2..a8e77b5350 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.txt @@ -13,7 +13,6 @@ SYNOPSIS [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...] - 'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>] DESCRIPTION diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt index c4d99f1028..2dcbbb2454 100644 --- a/Documentation/git-show-index.txt +++ b/Documentation/git-show-index.txt @@ -8,6 +8,7 @@ git-show-index - Show packed archive index SYNOPSIS -------- +[verse] 'git show-index' < idx-file diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt index 7f075e84f5..1f0e30b912 100644 --- a/Documentation/git-show.txt +++ b/Documentation/git-show.txt @@ -8,6 +8,7 @@ git-show - Show various types of objects SYNOPSIS -------- +[verse] 'git show' [options] <object>... DESCRIPTION diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index 38cb741f18..3d51717bbe 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -8,6 +8,7 @@ git-status - Show the working tree status SYNOPSIS -------- +[verse] 'git status' [<options>...] [--] [<pathspec>...] DESCRIPTION @@ -69,6 +70,9 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submodulesummary` is set). +--ignored:: + Show ignored files as well. + -z:: Terminate entries with NUL, instead of LF. This implies the `--porcelain` output format if no other format is given. @@ -119,7 +123,8 @@ codes can be interpreted as follows: * 'C' = copied * 'U' = updated but unmerged -Ignored files are not listed. +Ignored files are not listed, unless `--ignored` option is in effect, +in which case `XY` are `!!`. X Y Meaning ------------------------------------------------- @@ -142,6 +147,7 @@ Ignored files are not listed. U U unmerged, both modified ------------------------------------------------- ? ? untracked + ! ! ignored ------------------------------------------------- If -b is used the short-format status is preceded by a line diff --git a/Documentation/git-stripspace.txt b/Documentation/git-stripspace.txt index 10509cc450..b78f031cd4 100644 --- a/Documentation/git-stripspace.txt +++ b/Documentation/git-stripspace.txt @@ -8,6 +8,7 @@ git-stripspace - Filter out empty lines SYNOPSIS -------- +[verse] 'git stripspace' [-s | --strip-comments] < <stream> DESCRIPTION diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index 5e7a4130ee..0ec85742dd 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -78,7 +78,9 @@ to exist in the superproject. If <path> is not given, the <repository> is the URL of the new submodule's origin repository. This may be either an absolute URL, or (if it begins with ./ or ../), the location relative to the superproject's origin -repository. +repository. If the superproject doesn't have an origin configured +the superproject is its own authoritative upstream and the current +working directory is used instead. + <path> is the relative location for the cloned submodule to exist in the superproject. If <path> does not exist, then the @@ -167,12 +169,14 @@ commit for each submodule. sync:: Synchronizes submodules' remote URL configuration setting - to the value specified in .gitmodules. This is useful when + to the value specified in .gitmodules. It will only affect those + submodules which already have an url entry in .git/config (that is the + case when they are initialized or freshly added). This is useful when submodule URLs change upstream and you need to update your local repositories accordingly. + "git submodule sync" synchronizes all submodules while -"git submodule sync -- A" synchronizes submodule "A" only. +"git submodule sync \-- A" synchronizes submodule "A" only. OPTIONS ------- diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 713e523034..ed5eca1fce 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -7,6 +7,7 @@ git-svn - Bidirectional operation between a Subversion repository and git SYNOPSIS -------- +[verse] 'git svn' <command> [options] [arguments] DESCRIPTION diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt index d7795ed657..75b1ae5061 100644 --- a/Documentation/git-symbolic-ref.txt +++ b/Documentation/git-symbolic-ref.txt @@ -7,6 +7,7 @@ git-symbolic-ref - Read and modify symbolic refs SYNOPSIS -------- +[verse] 'git symbolic-ref' [-q] [-m <reason>] <name> [<ref>] DESCRIPTION diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index d82f62120a..fb1c0ac694 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -12,7 +12,7 @@ SYNOPSIS 'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] <tagname> [<commit> | <object>] 'git tag' -d <tagname>... -'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>] +'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>...] 'git tag' -v <tagname>... DESCRIPTION @@ -69,8 +69,11 @@ OPTIONS If the tag is not annotated, the commit message is displayed instead. -l <pattern>:: - List tags with names that match the given pattern (or all if no pattern is given). - Typing "git tag" without arguments, also lists all tags. + List tags with names that match the given pattern (or all if no + pattern is given). Running "git tag" without arguments also + lists all tags. The pattern is a shell wildcard (i.e., matched + using fnmatch(3)). Multiple patterns may be given; if any of + them matches, the tag is shown. --contains <commit>:: Only list tags which contain the specified commit. diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt index 5f15754257..95b135d8ad 100644 --- a/Documentation/git-tar-tree.txt +++ b/Documentation/git-tar-tree.txt @@ -8,6 +8,7 @@ git-tar-tree - Create a tar archive of the files in the named tree object SYNOPSIS -------- +[verse] 'git tar-tree' [--remote=<repo>] <tree-ish> [ <base> ] DESCRIPTION diff --git a/Documentation/git-unpack-file.txt b/Documentation/git-unpack-file.txt index c49d727f74..e9f148a00d 100644 --- a/Documentation/git-unpack-file.txt +++ b/Documentation/git-unpack-file.txt @@ -9,6 +9,7 @@ git-unpack-file - Creates a temporary file with a blob's contents SYNOPSIS -------- +[verse] 'git unpack-file' <blob> DESCRIPTION diff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.txt index dd7799095b..ff23494e70 100644 --- a/Documentation/git-unpack-objects.txt +++ b/Documentation/git-unpack-objects.txt @@ -8,6 +8,7 @@ git-unpack-objects - Unpack objects from a packed archive SYNOPSIS -------- +[verse] 'git unpack-objects' [-n] [-q] [-r] [--strict] <pack-file diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index d3931294d1..a3081f4e23 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -264,7 +264,9 @@ tree files, you have to explicitly tell git about it by dropping "assume unchanged" bit, either before or after you modify them. In order to set "assume unchanged" bit, use `--assume-unchanged` -option. To unset, use `--no-assume-unchanged`. +option. To unset, use `--no-assume-unchanged`. To see which files +have the "assume unchanged" bit set, use `git ls-files -v` +(see linkgit:git-ls-files[1]). The command looks at `core.ignorestat` configuration variable. When this is true, paths updated with `git update-index paths...` and @@ -363,7 +365,8 @@ ctime for marking files processed) (see linkgit:git-config[1]). SEE ALSO -------- linkgit:git-config[1], -linkgit:git-add[1] +linkgit:git-add[1], +linkgit:git-ls-files[1] GIT --- diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt index e25a65a80f..d377a35243 100644 --- a/Documentation/git-update-ref.txt +++ b/Documentation/git-update-ref.txt @@ -7,6 +7,7 @@ git-update-ref - Update the object name stored in a ref safely SYNOPSIS -------- +[verse] 'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>]) DESCRIPTION @@ -60,8 +61,9 @@ still contains <oldvalue>. Logging Updates --------------- -If config parameter "core.logAllRefUpdates" is true or the file -"$GIT_DIR/logs/<ref>" exists then `git update-ref` will append +If config parameter "core.logAllRefUpdates" is true and the ref is one under +"refs/heads/", "refs/remotes/", "refs/notes/", or the symbolic ref HEAD; or +the file "$GIT_DIR/logs/<ref>" exists then `git update-ref` will append a line to the log file "$GIT_DIR/logs/<ref>" (dereferencing all symbolic refs before creating the log name) describing the change in ref value. Log lines are formatted as: diff --git a/Documentation/git-update-server-info.txt b/Documentation/git-update-server-info.txt index 775024da3e..bd0e36492f 100644 --- a/Documentation/git-update-server-info.txt +++ b/Documentation/git-update-server-info.txt @@ -8,6 +8,7 @@ git-update-server-info - Update auxiliary info file to help dumb servers SYNOPSIS -------- +[verse] 'git update-server-info' [--force] DESCRIPTION diff --git a/Documentation/git-upload-archive.txt b/Documentation/git-upload-archive.txt index acbf634f85..4d52d3833a 100644 --- a/Documentation/git-upload-archive.txt +++ b/Documentation/git-upload-archive.txt @@ -8,6 +8,7 @@ git-upload-archive - Send archive back to git-archive SYNOPSIS -------- +[verse] 'git upload-archive' <directory> DESCRIPTION diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt index 4c0ca9ded2..a58e90ca8d 100644 --- a/Documentation/git-upload-pack.txt +++ b/Documentation/git-upload-pack.txt @@ -8,6 +8,7 @@ git-upload-pack - Send objects packed back to git-fetch-pack SYNOPSIS -------- +[verse] 'git-upload-pack' [--strict] [--timeout=<n>] <directory> DESCRIPTION diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt index 6498f7cb69..5317cc2474 100644 --- a/Documentation/git-var.txt +++ b/Documentation/git-var.txt @@ -8,6 +8,7 @@ git-var - Show a git logical variable SYNOPSIS -------- +[verse] 'git var' ( -l | <variable> ) DESCRIPTION diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt index 7c2428d569..cd230769fd 100644 --- a/Documentation/git-verify-pack.txt +++ b/Documentation/git-verify-pack.txt @@ -8,6 +8,7 @@ git-verify-pack - Validate packed git archive files SYNOPSIS -------- +[verse] 'git verify-pack' [-v|--verbose] [-s|--stat-only] [--] <pack>.idx ... diff --git a/Documentation/git-verify-tag.txt b/Documentation/git-verify-tag.txt index 8c9a71865b..5ff76e892a 100644 --- a/Documentation/git-verify-tag.txt +++ b/Documentation/git-verify-tag.txt @@ -7,6 +7,7 @@ git-verify-tag - Check the GPG signature of tags SYNOPSIS -------- +[verse] 'git verify-tag' <tag>... DESCRIPTION diff --git a/Documentation/git-web--browse.txt b/Documentation/git-web--browse.txt index 69d92fa00e..c2bc87bc61 100644 --- a/Documentation/git-web--browse.txt +++ b/Documentation/git-web--browse.txt @@ -7,6 +7,7 @@ git-web--browse - git helper script to launch a web browser SYNOPSIS -------- +[verse] 'git web{litdd}browse' [OPTIONS] URL/FILE ... DESCRIPTION @@ -68,7 +69,7 @@ browser.<tool>.path You can explicitly provide a full path to your preferred browser by setting the configuration variable 'browser.<tool>.path'. For example, you can configure the absolute path to firefox by setting -'browser.firefox.path'. Otherwise, 'git web--browse' assumes the tool +'browser.firefox.path'. Otherwise, 'git web{litdd}browse' assumes the tool is available in PATH. browser.<tool>.cmd diff --git a/Documentation/git-whatchanged.txt b/Documentation/git-whatchanged.txt index 31f3663ae7..99388bd374 100644 --- a/Documentation/git-whatchanged.txt +++ b/Documentation/git-whatchanged.txt @@ -8,6 +8,7 @@ git-whatchanged - Show logs with difference each commit introduces SYNOPSIS -------- +[verse] 'git whatchanged' <option>... DESCRIPTION diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt index e8c94c1352..f22041a9dc 100644 --- a/Documentation/git-write-tree.txt +++ b/Documentation/git-write-tree.txt @@ -8,6 +8,7 @@ git-write-tree - Create a tree object from the current index SYNOPSIS -------- +[verse] 'git write-tree' [--missing-ok] [--prefix=<prefix>/] DESCRIPTION diff --git a/Documentation/git.txt b/Documentation/git.txt index 3c7a832343..d1481354a8 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -44,9 +44,13 @@ 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.6/git.html[documentation for release 1.7.6] +* link:v1.7.6.4/git.html[documentation for release 1.7.6.4] * release notes for + link:RelNotes/1.7.6.4.txt[1.7.6.4], + link:RelNotes/1.7.6.3.txt[1.7.6.3], + link:RelNotes/1.7.6.2.txt[1.7.6.2], + link:RelNotes/1.7.6.1.txt[1.7.6.1], link:RelNotes/1.7.6.txt[1.7.6]. * link:v1.7.5.4/git.html[documentation for release 1.7.5.4] @@ -523,16 +527,15 @@ Any git command accepting any <object> can also use the following symbolic notation: HEAD:: - indicates the head of the current branch (i.e. the - contents of `$GIT_DIR/HEAD`). + indicates the head of the current branch. <tag>:: a valid tag 'name' - (i.e. the contents of `$GIT_DIR/refs/tags/<tag>`). + (i.e. a `refs/tags/<tag>` reference). <head>:: a valid head 'name' - (i.e. the contents of `$GIT_DIR/refs/heads/<head>`). + (i.e. a `refs/heads/<head>` reference). For a more complete list of ways to spell object names, see "SPECIFYING REVISIONS" section in linkgit:gitrevisions[7]. diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 412c55b549..2bbe76b5d8 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -79,7 +79,7 @@ Attributes for all users on a system should be placed in the `$(prefix)/etc/gitattributes` file. Sometimes you would need to override an setting of an attribute -for a path to `unspecified` state. This can be done by listing +for a path to `Unspecified` state. This can be done by listing the name of the attribute prefixed with an exclamation point `!`. @@ -868,7 +868,7 @@ If this attribute is not set or has an invalid value, the value of the (See linkgit:git-config[1]). -USING ATTRIBUTE MACROS +USING MACRO ATTRIBUTES ---------------------- You do not want any end-of-line conversions applied to, nor textual diffs @@ -879,24 +879,27 @@ produced for, any binary file you track. You would need to specify e.g. ------------ but that may become cumbersome, when you have many attributes. Using -attribute macros, you can specify groups of attributes set or unset at -the same time. The system knows a built-in attribute macro, `binary`: +macro attributes, you can define an attribute that, when set, also +sets or unsets a number of other attributes at the same time. The +system knows a built-in macro attribute, `binary`: ------------ *.jpg binary ------------ -which is equivalent to the above. Note that the attribute macros can only -be "Set" (see the above example that sets "binary" macro as if it were an -ordinary attribute --- setting it in turn unsets "text" and "diff"). +Setting the "binary" attribute also unsets the "text" and "diff" +attributes as above. Note that macro attributes can only be "Set", +though setting one might have the effect of setting or unsetting other +attributes or even returning other attributes to the "Unspecified" +state. -DEFINING ATTRIBUTE MACROS +DEFINING MACRO ATTRIBUTES ------------------------- -Custom attribute macros can be defined only in the `.gitattributes` file -at the toplevel (i.e. not in any subdirectory). The built-in attribute -macro "binary" is equivalent to: +Custom macro attributes can be defined only in the `.gitattributes` +file at the toplevel (i.e. not in any subdirectory). The built-in +macro attribute "binary" is equivalent to: ------------ [attr]binary -diff -text diff --git a/Documentation/gitcvs-migration.txt b/Documentation/gitcvs-migration.txt index d861ec452f..aeb0cdc973 100644 --- a/Documentation/gitcvs-migration.txt +++ b/Documentation/gitcvs-migration.txt @@ -7,7 +7,8 @@ gitcvs-migration - git for CVS users SYNOPSIS -------- -git cvsimport * +[verse] +'git cvsimport' * DESCRIPTION ----------- diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.txt index 6af29a4603..370624c171 100644 --- a/Documentation/gitdiffcore.txt +++ b/Documentation/gitdiffcore.txt @@ -7,6 +7,7 @@ gitdiffcore - Tweaking diff output SYNOPSIS -------- +[verse] 'git diff' * DESCRIPTION diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt index e10ac58cae..a17a354936 100644 --- a/Documentation/gitk.txt +++ b/Documentation/gitk.txt @@ -7,6 +7,7 @@ gitk - The git repository browser SYNOPSIS -------- +[verse] 'gitk' [<option>...] [<revs>] [--] [<path>...] DESCRIPTION diff --git a/Documentation/gittutorial-2.txt b/Documentation/gittutorial-2.txt index 7fe5848d1f..f1e4422acc 100644 --- a/Documentation/gittutorial-2.txt +++ b/Documentation/gittutorial-2.txt @@ -7,6 +7,7 @@ gittutorial-2 - A tutorial introduction to git: part two SYNOPSIS -------- +[verse] git * DESCRIPTION diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt index 0982f74ef6..dee050567e 100644 --- a/Documentation/gittutorial.txt +++ b/Documentation/gittutorial.txt @@ -7,6 +7,7 @@ gittutorial - A tutorial introduction to git (for version 1.5.1 or newer) SYNOPSIS -------- +[verse] git * DESCRIPTION diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt index 1ef55fffcf..5e4f362ff8 100644 --- a/Documentation/gitworkflows.txt +++ b/Documentation/gitworkflows.txt @@ -7,6 +7,7 @@ gitworkflows - An overview of recommended workflows with git SYNOPSIS -------- +[verse] git * diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index 8f62d1abee..3595b586bc 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -161,8 +161,8 @@ to point at the new commit. [[def_head]]head:: A <<def_ref,named reference>> to the <<def_commit,commit>> at the tip of a - <<def_branch,branch>>. Heads are stored in - `$GIT_DIR/refs/heads/`, except when using packed refs. (See + <<def_branch,branch>>. Heads are stored in a file in + `$GIT_DIR/refs/heads/` directory, except when using packed refs. (See linkgit:git-pack-refs[1].) [[def_HEAD]]HEAD:: @@ -170,8 +170,8 @@ to point at the new commit. working tree>> is normally derived from the state of the tree referred to by HEAD. HEAD is a reference to one of the <<def_head,heads>> in your repository, except when using a - <<def_detached_HEAD,detached HEAD>>, in which case it may - reference an arbitrary commit. + <<def_detached_HEAD,detached HEAD>>, in which case it directly + references an arbitrary commit. [[def_head_ref]]head ref:: A synonym for <<def_head,head>>. @@ -382,8 +382,9 @@ should not be combined with other pathspec. [[def_ref]]ref:: A 40-byte hex representation of a <<def_SHA1,SHA1>> or a name that - denotes a particular <<def_object,object>>. These may be stored in - `$GIT_DIR/refs/`. + denotes a particular <<def_object,object>>. They may be stored in + a file under `$GIT_DIR/refs/` directory, or + in the `$GIT_DIR/packed-refs` file. [[def_reflog]]reflog:: A reflog shows the local "history" of a ref. In other words, @@ -459,14 +460,14 @@ should not be combined with other pathspec. command. [[def_tag]]tag:: - A <<def_ref,ref>> pointing to a <<def_tag_object,tag>> or - <<def_commit_object,commit object>>. In contrast to a <<def_head,head>>, - a tag is not changed by a <<def_commit,commit>>. Tags (not - <<def_tag_object,tag objects>>) are stored in `$GIT_DIR/refs/tags/`. A - git tag has nothing to do with a Lisp tag (which would be - called an <<def_object_type,object type>> in git's context). A - tag is most typically used to mark a particular point in the - commit ancestry <<def_chain,chain>>. + A <<def_ref,ref>> under `refs/tags/` namespace that points to an + object of an arbitrary type (typically a tag points to either a + <<def_tag_object,tag>> or a <<def_commit_object,commit object>>). + In contrast to a <<def_head,head>>, a tag is not updated by + the `commit` command. A git tag has nothing to do with a Lisp + tag (which would be called an <<def_object_type,object type>> + in git's context). A tag is most typically used to mark a particular + point in the commit ancestry <<def_chain,chain>>. [[def_tag_object]]tag object:: An <<def_object,object>> containing a <<def_ref,ref>> pointing to diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 7e7ba68781..39e6207269 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -272,7 +272,7 @@ Default mode:: --full-history:: - As the default mode but does not prune some history. + Same as the default mode, but does not prune some history. --dense:: @@ -313,7 +313,7 @@ that you are filtering for a file `foo` in this commit graph: \ / / / / `-------------' ----------------------------------------------------------------------- -The horizontal line of history A--P is taken to be the first parent of +The horizontal line of history A---P is taken to be the first parent of each merge. The commits are: * `I` is the initial commit, in which `foo` exists with contents diff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt index 5cb2b0590a..b0cafe87be 100644 --- a/Documentation/technical/api-builtin.txt +++ b/Documentation/technical/api-builtin.txt @@ -49,6 +49,8 @@ Additionally, if `foo` is a new command, there are 3 more things to do: . Add an entry for `git-foo` to `command-list.txt`. +. Add an entry for `/git-foo` to `.gitignore`. + How a built-in is called ------------------------ diff --git a/Documentation/technical/api-ref-iteration.txt b/Documentation/technical/api-ref-iteration.txt new file mode 100644 index 0000000000..dbbea95db7 --- /dev/null +++ b/Documentation/technical/api-ref-iteration.txt @@ -0,0 +1,81 @@ +ref iteration API +================= + + +Iteration of refs is done by using an iterate function which will call a +callback function for every ref. The callback function has this +signature: + + int handle_one_ref(const char *refname, const unsigned char *sha1, + int flags, void *cb_data); + +There are different kinds of iterate functions which all take a +callback of this type. The callback is then called for each found ref +until the callback returns nonzero. The returned value is then also +returned by the iterate function. + +Iteration functions +------------------- + +* `head_ref()` just iterates the head ref. + +* `for_each_ref()` iterates all refs. + +* `for_each_ref_in()` iterates all refs which have a defined prefix and + strips that prefix from the passed variable refname. + +* `for_each_tag_ref()`, `for_each_branch_ref()`, `for_each_remote_ref()`, + `for_each_replace_ref()` iterate refs from the respective area. + +* `for_each_glob_ref()` iterates all refs that match the specified glob + pattern. + +* `for_each_glob_ref_in()` the previous and `for_each_ref_in()` combined. + +* `head_ref_submodule()`, `for_each_ref_submodule()`, + `for_each_ref_in_submodule()`, `for_each_tag_ref_submodule()`, + `for_each_branch_ref_submodule()`, `for_each_remote_ref_submodule()` + do the same as the functions descibed above but for a specified + submodule. + +* `for_each_rawref()` can be used to learn about broken ref and symref. + +* `for_each_reflog()` iterates each reflog file. + +Submodules +---------- + +If you want to iterate the refs of a submodule you first need to add the +submodules object database. You can do this by a code-snippet like +this: + + const char *path = "path/to/submodule" + if (!add_submodule_odb(path)) + die("Error submodule '%s' not populated.", path); + +`add_submodule_odb()` will return an non-zero value on success. If you +do not do this you will get an error for each ref that it does not point +to a valid object. + +Note: As a side-effect of this you can not safely assume that all +objects you lookup are available in superproject. All submodule objects +will be available the same way as the superprojects objects. + +Example: +-------- + +---- +static int handle_remote_ref(const char *refname, + const unsigned char *sha1, int flags, void *cb_data) +{ + struct strbuf *output = cb_data; + strbuf_addf(output, "%s\n", refname); + return 0; +} + +... + + struct strbuf output = STRBUF_INIT; + for_each_remote_ref(handle_remote_ref, &output); + printf("%s", output.buf); +---- diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt index 7b233ca196..8930b3fabc 100644 --- a/Documentation/technical/index-format.txt +++ b/Documentation/technical/index-format.txt @@ -147,8 +147,9 @@ GIT index format - 160-bit object name for the object that would result from writing this span of index as a tree. - An entry can be in an invalidated state and is represented by having -1 - in the entry_count field. + An entry can be in an invalidated state and is represented by having + -1 in the entry_count field. In this case, there is no object name + and the next entry starts immediately after the newline. The entries are written out in the top-down, depth-first order. The first entry represents the root level of the repository, followed by the diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt index 369f91d3b9..a7004c63e7 100644 --- a/Documentation/technical/pack-protocol.txt +++ b/Documentation/technical/pack-protocol.txt @@ -179,34 +179,36 @@ and descriptions. Packfile Negotiation -------------------- -After reference and capabilities discovery, the client can decide -to terminate the connection by sending a flush-pkt, telling the -server it can now gracefully terminate (as happens with the ls-remote -command) or it can enter the negotiation phase, where the client and -server determine what the minimal packfile necessary for transport is. - -Once the client has the initial list of references that the server -has, as well as the list of capabilities, it will begin telling the -server what objects it wants and what objects it has, so the server -can make a packfile that only contains the objects that the client needs. -The client will also send a list of the capabilities it wants to be in -effect, out of what the server said it could do with the first 'want' line. +After reference and capabilities discovery, the client can decide to +terminate the connection by sending a flush-pkt, telling the server it can +now gracefully terminate, and disconnect, when it does not need any pack +data. This can happen with the ls-remote command, and also can happen when +the client already is up-to-date. + +Otherwise, it enters the negotiation phase, where the client and +server determine what the minimal packfile necessary for transport is, +by telling the server what objects it wants, its shallow objects +(if any), and the maximum commit depth it wants (if any). The client +will also send a list of the capabilities it wants to be in effect, +out of what the server said it could do with the first 'want' line. ---- upload-request = want-list - have-list - compute-end + *shallow-line + *1depth-request + flush-pkt want-list = first-want *additional-want - flush-pkt + + shallow-line = PKT_LINE("shallow" SP obj-id) + + depth-request = PKT_LINE("deepen" SP depth) first-want = PKT-LINE("want" SP obj-id SP capability-list LF) additional-want = PKT-LINE("want" SP obj-id LF) - have-list = *have-line - have-line = PKT-LINE("have" SP obj-id LF) - compute-end = flush-pkt / PKT-LINE("done") + depth = 1*DIGIT ---- Clients MUST send all the obj-ids it wants from the reference @@ -215,21 +217,64 @@ discovery phase as 'want' lines. Clients MUST send at least one obj-id in a 'want' command which did not appear in the response obtained through ref discovery. -If client is requesting a shallow clone, it will now send a 'deepen' -line with the depth it is requesting. +The client MUST write all obj-ids which it only has shallow copies +of (meaning that it does not have the parents of a commit) as +'shallow' lines so that the server is aware of the limitations of +the client's history. Clients MUST NOT mention an obj-id which +it does not know exists on the server. + +The client now sends the maximum commit history depth it wants for +this transaction, which is the number of commits it wants from the +tip of the history, if any, as a 'deepen' line. A depth of 0 is the +same as not making a depth request. The client does not want to receive +any commits beyond this depth, nor objects needed only to complete +those commits. Commits whose parents are not received as a result are +defined as shallow and marked as such in the server. This information +is sent back to the client in the next step. + +Once all the 'want's and 'shallow's (and optional 'deepen') are +transferred, clients MUST send a flush-pkt, to tell the server side +that it is done sending the list. + +Otherwise, if the client sent a positive depth request, the server +will determine which commits will and will not be shallow and +send this information to the client. If the client did not request +a positive depth, this step is skipped. -Once all the "want"s (and optional 'deepen') are transferred, -clients MUST send a flush-pkt. If the client has all the references -on the server, client flushes and disconnects. +---- + shallow-update = *shallow-line + *unshallow-line + flush-pkt -TODO: shallow/unshallow response and document the deepen command in the ABNF. + shallow-line = PKT-LINE("shallow" SP obj-id) + + unshallow-line = PKT-LINE("unshallow" SP obj-id) +---- + +If the client has requested a positive depth, the server will compute +the set of commits which are no deeper than the desired depth, starting +at the client's wants. The server writes 'shallow' lines for each +commit whose parents will not be sent as a result. The server writes +an 'unshallow' line for each commit which the client has indicated is +shallow, but is no longer shallow at the currently requested depth +(that is, its parents will now be sent). The server MUST NOT mark +as unshallow anything which the client has not indicated was shallow. Now the client will send a list of the obj-ids it has using 'have' -lines. In multi_ack mode, the canonical implementation will send up -to 32 of these at a time, then will send a flush-pkt. The canonical -implementation will skip ahead and send the next 32 immediately, -so that there is always a block of 32 "in-flight on the wire" at a -time. +lines, so the server can make a packfile that only contains the objects +that the client needs. In multi_ack mode, the canonical implementation +will send up to 32 of these at a time, then will send a flush-pkt. The +canonical implementation will skip ahead and send the next 32 immediately, +so that there is always a block of 32 "in-flight on the wire" at a time. + +---- + upload-haves = have-list + compute-end + + have-list = *have-line + have-line = PKT-LINE("have" SP obj-id LF) + compute-end = flush-pkt / PKT-LINE("done") +---- If the server reads 'have' lines, it then will respond by ACKing any of the obj-ids the client said it had that the server also has. The diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index f04e4b138d..b42c77c392 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.7.6 +DEF_VER=v1.7.6.4 LF=' ' @@ -1706,7 +1706,7 @@ git.sp git.s git.o: EXTRA_CPPFLAGS = -DGIT_VERSION='"$(GIT_VERSION)"' \ '-DGIT_MAN_PATH="$(mandir_SQ)"' \ '-DGIT_INFO_PATH="$(infodir_SQ)"' -git$X: git.o $(BUILTIN_OBJS) $(GITLIBS) +git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \ $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) @@ -2004,17 +2004,17 @@ compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \ -DNDEBUG -DOVERRIDE_STRDUP -DREPLACE_SYSTEM_ALLOCATOR endif -git-%$X: %.o $(GITLIBS) +git-%$X: %.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) -git-imap-send$X: imap-send.o $(GITLIBS) +git-imap-send$X: imap-send.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO) -git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS) +git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) -git-http-push$X: revision.o http.o http-push.o $(GITLIBS) +git-http-push$X: revision.o http.o http-push.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) @@ -2024,7 +2024,7 @@ $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_PRIMARY) ln -s $< $@ 2>/dev/null || \ cp $< $@ -$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBS) +$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) @@ -2094,6 +2094,15 @@ GIT-CFLAGS: FORCE echo "$$FLAGS" >GIT-CFLAGS; \ fi +TRACK_LDFLAGS = $(subst ','\'',$(ALL_LDFLAGS)) + +GIT-LDFLAGS: FORCE + @FLAGS='$(TRACK_LDFLAGS)'; \ + if test x"$$FLAGS" != x"`cat GIT-LDFLAGS 2>/dev/null`" ; then \ + echo 1>&2 " * new link flags"; \ + echo "$$FLAGS" >GIT-LDFLAGS; \ + fi + # We need to apply sq twice, once to protect from the shell # that runs GIT-BUILD-OPTIONS, and then again to protect it # and the first level quoting from the shell that runs "echo". @@ -2165,7 +2174,7 @@ test-svn-fe$X: vcs-svn/lib.a .PRECIOUS: $(TEST_OBJS) -test-%$X: test-%.o $(GITLIBS) +test-%$X: test-%.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS) check-sha1:: test-sha1$X @@ -2375,7 +2384,7 @@ ifndef NO_TCLTK $(MAKE) -C gitk-git clean $(MAKE) -C git-gui clean endif - $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS + $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS .PHONY: all install clean strip .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell @@ -1 +1 @@ -Documentation/RelNotes/1.7.6.txt
\ No newline at end of file +Documentation/RelNotes/1.7.6.4.txt
\ No newline at end of file @@ -102,7 +102,8 @@ static const char *get_pwd_cwd(void) pwd = getenv("PWD"); if (pwd && strcmp(pwd, cwd)) { stat(cwd, &cwd_stat); - if (!stat(pwd, &pwd_stat) && + if ((cwd_stat.st_dev || cwd_stat.st_ino) && + !stat(pwd, &pwd_stat) && pwd_stat.st_dev == cwd_stat.st_dev && pwd_stat.st_ino == cwd_stat.st_ino) { strlcpy(cwd, pwd, PATH_MAX); diff --git a/archive-zip.c b/archive-zip.c index cf285044e3..72d55a58ac 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -90,14 +90,14 @@ static void copy_le32(unsigned char *dest, unsigned int n) static void *zlib_deflate(void *data, unsigned long size, int compression_level, unsigned long *compressed_size) { - z_stream stream; + git_zstream stream; unsigned long maxsize; void *buffer; int result; memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, compression_level); - maxsize = deflateBound(&stream, size); + git_deflate_init(&stream, compression_level); + maxsize = git_deflate_bound(&stream, size); buffer = xmalloc(maxsize); stream.next_in = data; @@ -106,7 +106,7 @@ static void *zlib_deflate(void *data, unsigned long size, stream.avail_out = maxsize; do { - result = deflate(&stream, Z_FINISH); + result = git_deflate(&stream, Z_FINISH); } while (result == Z_OK); if (result != Z_STREAM_END) { @@ -114,7 +114,7 @@ static void *zlib_deflate(void *data, unsigned long size, return NULL; } - deflateEnd(&stream); + git_deflate_end(&stream); *compressed_size = stream.total_out; return buffer; @@ -210,7 +210,7 @@ void create_branch(const char *head, start_name); if (real_ref && track) - setup_tracking(name, real_ref, track); + setup_tracking(ref.buf+11, real_ref, track); if (!dont_change_ref) if (write_ref_sha1(lock, sha1, msg) < 0) diff --git a/builtin/apply.c b/builtin/apply.c index 530d4bb7e7..f2edc52818 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -1634,7 +1634,7 @@ static inline int metadata_changes(struct patch *patch) static char *inflate_it(const void *data, unsigned long size, unsigned long inflated_size) { - z_stream stream; + git_zstream stream; void *out; int st; diff --git a/builtin/branch.c b/builtin/branch.c index d6ab93bfbb..3142daa57a 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -19,7 +19,7 @@ static const char * const builtin_branch_usage[] = { "git branch [options] [-r | -a] [--merged | --no-merged]", "git branch [options] [-l] [-f] <branchname> [<start-point>]", - "git branch [options] [-r] (-d | -D) <branchname>", + "git branch [options] [-r] (-d | -D) <branchname>...", "git branch [options] (-m | -M) [<oldbranch>] <newbranch>", NULL }; diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c index ae3f28115a..0723cf245e 100644 --- a/builtin/check-ref-format.c +++ b/builtin/check-ref-format.c @@ -12,8 +12,8 @@ static const char builtin_check_ref_format_usage[] = " or: git check-ref-format --branch <branchname-shorthand>"; /* - * Replace each run of adjacent slashes in src with a single slash, - * and write the result to dst. + * Remove leading slashes and replace each run of adjacent slashes in + * src with a single slash, and write the result to dst. * * This function is similar to normalize_path_copy(), but stripped down * to meet check_ref_format's simpler needs. @@ -21,7 +21,7 @@ static const char builtin_check_ref_format_usage[] = static void collapse_slashes(char *dst, const char *src) { char ch; - char prev = '\0'; + char prev = '/'; while ((ch = *src++) != '\0') { if (prev == '/' && ch == prev) diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index f1fec24745..c16d82b7de 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -3,38 +3,6 @@ * * Copyright (C) 2005 Linus Torvalds * - * Careful: order of argument flags does matter. For example, - * - * git checkout-index -a -f file.c - * - * Will first check out all files listed in the cache (but not - * overwrite any old ones), and then force-checkout "file.c" a - * second time (ie that one _will_ overwrite any old contents - * with the same filename). - * - * Also, just doing "git checkout-index" does nothing. You probably - * meant "git checkout-index -a". And if you want to force it, you - * want "git checkout-index -f -a". - * - * Intuitiveness is not the goal here. Repeatability is. The - * reason for the "no arguments means no work" thing is that - * from scripts you are supposed to be able to do things like - * - * find . -name '*.h' -print0 | xargs -0 git checkout-index -f -- - * - * or: - * - * find . -name '*.h' -print0 | git checkout-index -f -z --stdin - * - * which will force all existing *.h files to be replaced with - * their cached copies. If an empty command line implied "all", - * then this would force-refresh everything in the cache, which - * was not the point. - * - * Oh, and the "--" is just a good idea when you know the rest - * will be filenames. Just so that you wouldn't have a filename - * of "-a" causing problems (not possible in the above example, - * but get used to it in scripting!). */ #include "builtin.h" #include "cache.h" diff --git a/builtin/checkout.c b/builtin/checkout.c index 28cdc51b85..4c20dae34d 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -201,7 +201,7 @@ static int checkout_merged(int pos, struct checkout *state) } static int checkout_paths(struct tree *source_tree, const char **pathspec, - struct checkout_opts *opts) + const char *prefix, struct checkout_opts *opts) { int pos; struct checkout state; @@ -231,7 +231,7 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec, match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, ps_matched); } - if (report_path_error(ps_matched, pathspec, 0)) + if (report_path_error(ps_matched, pathspec, prefix)) return 1; /* "checkout -m path" to recreate conflicted state */ @@ -715,10 +715,12 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new) unsigned char rev[20]; int flag; memset(&old, 0, sizeof(old)); - old.path = resolve_ref("HEAD", rev, 0, &flag); + old.path = xstrdup(resolve_ref("HEAD", rev, 0, &flag)); old.commit = lookup_commit_reference_gently(rev, 1); - if (!(flag & REF_ISSYMREF)) + if (!(flag & REF_ISSYMREF)) { + free((char *)old.path); old.path = NULL; + } if (old.path && !prefixcmp(old.path, "refs/heads/")) old.name = old.path + strlen("refs/heads/"); @@ -741,6 +743,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new) update_refs_for_switch(opts, &old, new); ret = post_checkout_hook(old.commit, new->commit, 1); + free((char *)old.path); return ret || opts->writeout_error; } @@ -1060,7 +1063,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) if (1 < !!opts.writeout_stage + !!opts.force + !!opts.merge) die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\nchecking out of the index.")); - return checkout_paths(source_tree, pathspec, &opts); + return checkout_paths(source_tree, pathspec, prefix, &opts); } if (patch_mode) @@ -1071,7 +1074,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) if (strbuf_check_branch_ref(&buf, opts.new_branch)) die(_("git checkout: we do not like '%s' as a branch name."), opts.new_branch); - if (!get_sha1(buf.buf, rev)) { + if (ref_exists(buf.buf)) { opts.branch_exists = 1; if (!opts.new_branch_force) die(_("git checkout: branch %s already exists"), diff --git a/builtin/clone.c b/builtin/clone.c index f579794d9a..5f20082d6d 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -39,13 +39,23 @@ static const char * const builtin_clone_usage[] = { static int option_no_checkout, option_bare, option_mirror; static int option_local, option_no_hardlinks, option_shared, option_recursive; -static char *option_template, *option_reference, *option_depth; +static char *option_template, *option_depth; static char *option_origin = NULL; static char *option_branch = NULL; static const char *real_git_dir; static char *option_upload_pack = "git-upload-pack"; static int option_verbosity; static int option_progress; +static struct string_list option_reference; + +static int opt_parse_reference(const struct option *opt, const char *arg, int unset) +{ + struct string_list *option_reference = opt->value; + if (!arg) + return -1; + string_list_append(option_reference, arg); + return 0; +} static struct option builtin_clone_options[] = { OPT__VERBOSITY(&option_verbosity), @@ -71,8 +81,8 @@ static struct option builtin_clone_options[] = { "initialize submodules in the clone"), OPT_STRING(0, "template", &option_template, "template-directory", "directory from which templates will be used"), - OPT_STRING(0, "reference", &option_reference, "repo", - "reference repository"), + OPT_CALLBACK(0 , "reference", &option_reference, "repo", + "reference repository", &opt_parse_reference), OPT_STRING('o', "origin", &option_origin, "branch", "use <branch> instead of 'origin' to track upstream"), OPT_STRING('b', "branch", &option_branch, "branch", @@ -101,9 +111,26 @@ static char *get_repo_path(const char *repo, int *is_bundle) for (i = 0; i < ARRAY_SIZE(suffix); i++) { const char *path; path = mkpath("%s%s", repo, suffix[i]); - if (is_directory(path)) { + if (stat(path, &st)) + continue; + if (S_ISDIR(st.st_mode)) { *is_bundle = 0; return xstrdup(absolute_path(path)); + } else if (S_ISREG(st.st_mode) && st.st_size > 8) { + /* Is it a "gitfile"? */ + char signature[8]; + int len, fd = open(path, O_RDONLY); + if (fd < 0) + continue; + len = read_in_full(fd, signature, 8); + close(fd); + if (len != 8 || strncmp(signature, "gitdir: ", 8)) + continue; + path = read_gitfile(path); + if (path) { + *is_bundle = 0; + return xstrdup(absolute_path(path)); + } } } @@ -197,39 +224,80 @@ static void strip_trailing_slashes(char *dir) *end = '\0'; } -static void setup_reference(const char *repo) +static int add_one_reference(struct string_list_item *item, void *cb_data) { - const char *ref_git; - char *ref_git_copy; - + char *ref_git; + struct strbuf alternate = STRBUF_INIT; struct remote *remote; struct transport *transport; const struct ref *extra; - ref_git = real_path(option_reference); - - if (is_directory(mkpath("%s/.git/objects", ref_git))) - ref_git = mkpath("%s/.git", ref_git); - else if (!is_directory(mkpath("%s/objects", ref_git))) + /* Beware: real_path() and mkpath() return static buffer */ + ref_git = xstrdup(real_path(item->string)); + if (is_directory(mkpath("%s/.git/objects", ref_git))) { + char *ref_git_git = xstrdup(mkpath("%s/.git", ref_git)); + free(ref_git); + ref_git = ref_git_git; + } else if (!is_directory(mkpath("%s/objects", ref_git))) die(_("reference repository '%s' is not a local directory."), - option_reference); + item->string); - ref_git_copy = xstrdup(ref_git); + strbuf_addf(&alternate, "%s/objects", ref_git); + add_to_alternates_file(alternate.buf); + strbuf_release(&alternate); - add_to_alternates_file(ref_git_copy); - - remote = remote_get(ref_git_copy); - transport = transport_get(remote, ref_git_copy); + remote = remote_get(ref_git); + transport = transport_get(remote, ref_git); for (extra = transport_get_remote_refs(transport); extra; extra = extra->next) add_extra_ref(extra->name, extra->old_sha1, 0); transport_disconnect(transport); + free(ref_git); + return 0; +} - free(ref_git_copy); +static void setup_reference(void) +{ + for_each_string_list(&option_reference, add_one_reference, NULL); } -static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest) +static void copy_alternates(struct strbuf *src, struct strbuf *dst, + const char *src_repo) +{ + /* + * Read from the source objects/info/alternates file + * and copy the entries to corresponding file in the + * destination repository with add_to_alternates_file(). + * Both src and dst have "$path/objects/info/alternates". + * + * Instead of copying bit-for-bit from the original, + * we need to append to existing one so that the already + * created entry via "clone -s" is not lost, and also + * to turn entries with paths relative to the original + * absolute, so that they can be used in the new repository. + */ + FILE *in = fopen(src->buf, "r"); + struct strbuf line = STRBUF_INIT; + + while (strbuf_getline(&line, in, '\n') != EOF) { + char *abs_path, abs_buf[PATH_MAX]; + if (!line.len || line.buf[0] == '#') + continue; + if (is_absolute_path(line.buf)) { + add_to_alternates_file(line.buf); + continue; + } + abs_path = mkpath("%s/objects/%s", src_repo, line.buf); + normalize_path_copy(abs_buf, abs_path); + add_to_alternates_file(abs_buf); + } + strbuf_release(&line); + fclose(in); +} + +static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, + const char *src_repo, int src_baselen) { struct dirent *de; struct stat buf; @@ -265,7 +333,14 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest) } if (S_ISDIR(buf.st_mode)) { if (de->d_name[0] != '.') - copy_or_link_directory(src, dest); + copy_or_link_directory(src, dest, + src_repo, src_baselen); + continue; + } + + /* Files that cannot be copied bit-for-bit... */ + if (!strcmp(src->buf + src_baselen, "/info/alternates")) { + copy_alternates(src, dest, src_repo); continue; } @@ -288,17 +363,20 @@ static const struct ref *clone_local(const char *src_repo, const char *dest_repo) { const struct ref *ret; - struct strbuf src = STRBUF_INIT; - struct strbuf dest = STRBUF_INIT; struct remote *remote; struct transport *transport; - if (option_shared) - add_to_alternates_file(src_repo); - else { + if (option_shared) { + struct strbuf alt = STRBUF_INIT; + strbuf_addf(&alt, "%s/objects", src_repo); + add_to_alternates_file(alt.buf); + strbuf_release(&alt); + } else { + struct strbuf src = STRBUF_INIT; + struct strbuf dest = STRBUF_INIT; strbuf_addf(&src, "%s/objects", src_repo); strbuf_addf(&dest, "%s/objects", dest_repo); - copy_or_link_directory(&src, &dest); + copy_or_link_directory(&src, &dest, src_repo, src.len); strbuf_release(&src); strbuf_release(&dest); } @@ -521,8 +599,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix) git_config_set(key.buf, repo); strbuf_reset(&key); - if (option_reference) - setup_reference(git_dir); + if (option_reference.nr) + setup_reference(); fetch_pattern = value.buf; refspec = parse_fetch_refspec(1, &fetch_pattern); diff --git a/builtin/commit.c b/builtin/commit.c index e1af9b19f0..9679a99f99 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -272,7 +272,7 @@ static int list_paths(struct string_list *list, const char *with_tree, item->util = item; /* better a valid pointer than a fake one */ } - return report_path_error(m, pattern, prefix ? strlen(prefix) : 0); + return report_path_error(m, pattern, prefix); } static void add_remove_files(struct string_list *list) diff --git a/builtin/describe.c b/builtin/describe.c index 66fc291c8a..9f63067f50 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -462,8 +462,21 @@ int cmd_describe(int argc, const char **argv, const char *prefix) die(_("No names found, cannot describe anything.")); if (argc == 0) { - if (dirty && !cmd_diff_index(ARRAY_SIZE(diff_index_args) - 1, diff_index_args, prefix)) - dirty = NULL; + if (dirty) { + static struct lock_file index_lock; + int fd; + + read_cache_preload(NULL); + refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, + NULL, NULL, NULL); + fd = hold_locked_index(&index_lock, 0); + if (0 <= fd) + update_index_if_able(&the_index, &index_lock); + + if (!cmd_diff_index(ARRAY_SIZE(diff_index_args) - 1, + diff_index_args, prefix)) + dirty = NULL; + } describe("HEAD", 1); } else if (dirty) { die(_("--dirty is incompatible with committishes")); diff --git a/builtin/fast-export.c b/builtin/fast-export.c index daf19451ba..48bd5e6a80 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -16,6 +16,7 @@ #include "string-list.h" #include "utf8.h" #include "parse-options.h" +#include "quote.h" static const char *fast_export_usage[] = { "git fast-export [rev-list-opts]", @@ -178,6 +179,15 @@ static int depth_first(const void *a_, const void *b_) return (a->status == 'R') - (b->status == 'R'); } +static void print_path(const char *path) +{ + int need_quote = quote_c_style(path, NULL, NULL, 0); + if (need_quote) + quote_c_style(path, NULL, stdout, 0); + else + printf("%s", path); +} + static void show_filemodify(struct diff_queue_struct *q, struct diff_options *options, void *data) { @@ -195,13 +205,18 @@ static void show_filemodify(struct diff_queue_struct *q, switch (q->queue[i]->status) { case DIFF_STATUS_DELETED: - printf("D %s\n", spec->path); + printf("D "); + print_path(spec->path); + putchar('\n'); break; case DIFF_STATUS_COPIED: case DIFF_STATUS_RENAMED: - printf("%c \"%s\" \"%s\"\n", q->queue[i]->status, - ospec->path, spec->path); + printf("%c ", q->queue[i]->status); + print_path(ospec->path); + putchar(' '); + print_path(spec->path); + putchar('\n'); if (!hashcmp(ospec->sha1, spec->sha1) && ospec->mode == spec->mode) @@ -216,13 +231,15 @@ static void show_filemodify(struct diff_queue_struct *q, * output the SHA-1 verbatim. */ if (no_data || S_ISGITLINK(spec->mode)) - printf("M %06o %s %s\n", spec->mode, - sha1_to_hex(spec->sha1), spec->path); + printf("M %06o %s ", spec->mode, + sha1_to_hex(spec->sha1)); else { struct object *object = lookup_object(spec->sha1); - printf("M %06o :%d %s\n", spec->mode, - get_object_mark(object), spec->path); + printf("M %06o :%d ", spec->mode, + get_object_mark(object)); } + print_path(spec->path); + putchar('\n'); break; default: diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 4367984102..3c871c2da8 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -395,6 +395,8 @@ static int find_common(int fd[2], unsigned char *result_sha1, case ACK_continue: { struct commit *commit = lookup_commit(result_sha1); + if (!commit) + die("invalid commit %s", sha1_to_hex(result_sha1)); if (args.stateless_rpc && ack == ACK_common && !(commit->object.flags & COMMON)) { diff --git a/builtin/fetch.c b/builtin/fetch.c index 93c99385a9..e422ced929 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -941,6 +941,15 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_fetch_options, builtin_fetch_usage, 0); + if (recurse_submodules != RECURSE_SUBMODULES_OFF) { + if (recurse_submodules_default) { + int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default); + set_config_fetch_recurse_submodules(arg); + } + gitmodules_config(); + git_config(submodule_config, NULL); + } + if (all) { if (argc == 1) die(_("fetch --all does not take a repository argument")); @@ -976,12 +985,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) { const char *options[10]; int num_options = 0; - if (recurse_submodules_default) { - int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default); - set_config_fetch_recurse_submodules(arg); - } - gitmodules_config(); - git_config(submodule_config, NULL); add_options_to_argv(&num_options, options); result = fetch_populated_submodules(num_options, options, submodule_prefix, diff --git a/builtin/index-pack.c b/builtin/index-pack.c index e40451ffb4..81cdc28b30 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -265,7 +265,7 @@ static void unlink_base_data(struct base_data *c) static void *unpack_entry_data(unsigned long offset, unsigned long size) { int status; - z_stream stream; + git_zstream stream; void *buf = xmalloc(size); memset(&stream, 0, sizeof(stream)); @@ -355,7 +355,7 @@ static void *get_data_from_pack(struct object_entry *obj) off_t from = obj[0].idx.offset + obj[0].hdr_size; unsigned long len = obj[1].idx.offset - from; unsigned char *data, *inbuf; - z_stream stream; + git_zstream stream; int status; data = xmalloc(obj->size); @@ -666,26 +666,26 @@ static void parse_pack_objects(unsigned char *sha1) static int write_compressed(struct sha1file *f, void *in, unsigned int size) { - z_stream stream; + git_zstream stream; int status; unsigned char outbuf[4096]; memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, zlib_compression_level); + git_deflate_init(&stream, zlib_compression_level); stream.next_in = in; stream.avail_in = size; do { stream.next_out = outbuf; stream.avail_out = sizeof(outbuf); - status = deflate(&stream, Z_FINISH); + status = git_deflate(&stream, Z_FINISH); sha1write(f, outbuf, sizeof(outbuf) - stream.avail_out); } while (status == Z_OK); if (status != Z_STREAM_END) die("unable to deflate appended object (%d)", status); size = stream.total_out; - deflateEnd(&stream); + git_deflate_end(&stream); return size; } diff --git a/builtin/init-db.c b/builtin/init-db.c index 025aa47c80..d07554c884 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -347,7 +347,7 @@ static void separate_git_dir(const char *git_dir) const char *src; if (S_ISREG(st.st_mode)) - src = read_gitfile_gently(git_link); + src = read_gitfile(git_link); else if (S_ISDIR(st.st_mode)) src = git_link; else diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 15701233e2..468bb13c81 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -388,11 +388,13 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix) } } -int report_path_error(const char *ps_matched, const char **pathspec, int prefix_len) +int report_path_error(const char *ps_matched, const char **pathspec, const char *prefix) { /* * Make sure all pathspec matched; otherwise it is an error. */ + struct strbuf sb = STRBUF_INIT; + const char *name; int num, errors = 0; for (num = 0; pathspec[num]; num++) { int other, found_dup; @@ -417,10 +419,12 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_ if (found_dup) continue; + name = quote_path_relative(pathspec[num], -1, &sb, prefix); error("pathspec '%s' did not match any file(s) known to git.", - pathspec[num] + prefix_len); + name); errors++; } + strbuf_release(&sb); return errors; } @@ -611,7 +615,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) if (ps_matched) { int bad; - bad = report_path_error(ps_matched, pathspec, prefix_len); + bad = report_path_error(ps_matched, pathspec, prefix); if (bad) fprintf(stderr, "Did you forget to 'git add'?\n"); diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index f08c5b0c94..6b666e1e87 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -173,7 +173,5 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) tree = parse_tree_indirect(sha1); if (!tree) die("not a tree object"); - read_tree_recursive(tree, "", 0, 0, &pathspec, show_tree, NULL); - - return 0; + return !!read_tree_recursive(tree, "", 0, 0, &pathspec, show_tree, NULL); } diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index f402a843bb..c6e2d8766b 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -126,13 +126,13 @@ static void *get_delta(struct object_entry *entry) static unsigned long do_compress(void **pptr, unsigned long size) { - z_stream stream; + git_zstream stream; void *in, *out; unsigned long maxsize; memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, pack_compression_level); - maxsize = deflateBound(&stream, size); + git_deflate_init(&stream, pack_compression_level); + maxsize = git_deflate_bound(&stream, size); in = *pptr; out = xmalloc(maxsize); @@ -142,9 +142,9 @@ static unsigned long do_compress(void **pptr, unsigned long size) stream.avail_in = size; stream.next_out = out; stream.avail_out = maxsize; - while (deflate(&stream, Z_FINISH) == Z_OK) + while (git_deflate(&stream, Z_FINISH) == Z_OK) ; /* nothing */ - deflateEnd(&stream); + git_deflate_end(&stream); free(in); return stream.total_out; @@ -160,7 +160,7 @@ static int check_pack_inflate(struct packed_git *p, off_t len, unsigned long expect) { - z_stream stream; + git_zstream stream; unsigned char fakebuf[4096], *in; int st; @@ -187,12 +187,12 @@ static void copy_pack_data(struct sha1file *f, off_t len) { unsigned char *in; - unsigned int avail; + unsigned long avail; while (len) { in = use_pack(p, w_curs, offset, &avail); if (avail > len) - avail = (unsigned int)len; + avail = (unsigned long)len; sha1write(f, in, avail); offset += avail; len -= avail; @@ -994,7 +994,7 @@ static void check_object(struct object_entry *entry) const unsigned char *base_ref = NULL; struct object_entry *base_entry; unsigned long used, used_0; - unsigned int avail; + unsigned long avail; off_t ofs; unsigned char *buf, c; diff --git a/builtin/reflog.c b/builtin/reflog.c index ebf610e64a..3a9c80f3db 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -777,6 +777,5 @@ int cmd_reflog(int argc, const char **argv, const char *prefix) if (!strcmp(argv[1], "delete")) return cmd_reflog_delete(argc - 1, argv + 1, prefix); - /* Not a recognized reflog command..*/ - usage(reflog_usage); + return cmd_log_reflog(argc, argv, prefix); } diff --git a/builtin/remote.c b/builtin/remote.c index 9ff1cac69b..1fb441c964 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -1113,7 +1113,7 @@ static int show(int argc, const char **argv) url = states.remote->url; url_nr = states.remote->url_nr; } - for (i=0; i < url_nr; i++) + for (i = 0; i < url_nr; i++) printf(" Push URL: %s\n", url[i]); if (!i) printf(" Push URL: %s\n", "(no URL)"); diff --git a/builtin/reset.c b/builtin/reset.c index 98bca044c1..811e8e252c 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -33,25 +33,6 @@ static const char *reset_type_names[] = { N_("mixed"), N_("soft"), N_("hard"), N_("merge"), N_("keep"), NULL }; -static char *args_to_str(const char **argv) -{ - char *buf = NULL; - unsigned long len, space = 0, nr = 0; - - for (; *argv; argv++) { - len = strlen(*argv); - ALLOC_GROW(buf, nr + 1 + len, space); - if (nr) - buf[nr++] = ' '; - memcpy(buf + nr, *argv, len); - nr += len; - } - ALLOC_GROW(buf, nr + 1, space); - buf[nr] = '\0'; - - return buf; -} - static inline int is_merge(void) { return !access(git_path("MERGE_HEAD"), F_OK); @@ -162,7 +143,7 @@ static void update_index_from_diff(struct diff_queue_struct *q, for (i = 0; i < q->nr; i++) { struct diff_filespec *one = q->queue[i]->one; - if (one->mode) { + if (one->mode && !is_null_sha1(one->sha1)) { struct cache_entry *ce; ce = make_cache_entry(one->mode, one->sha1, one->path, 0, 0); @@ -215,14 +196,18 @@ static int read_from_tree(const char *prefix, const char **argv, return update_index_refresh(index_fd, lock, refresh_flags); } -static void prepend_reflog_action(const char *action, char *buf, size_t size) +static void set_reflog_message(struct strbuf *sb, const char *action, + const char *rev) { - const char *sep = ": "; const char *rla = getenv("GIT_REFLOG_ACTION"); - if (!rla) - rla = sep = ""; - if (snprintf(buf, size, "%s%s%s", rla, sep, action) >= size) - warning(_("Reflog action message too long: %.*s..."), 50, buf); + + strbuf_reset(sb); + if (rla) + strbuf_addf(sb, "%s: %s", rla, action); + else if (rev) + strbuf_addf(sb, "reset: moving to %s", rev); + else + strbuf_addf(sb, "reset: %s", action); } static void die_if_unmerged_cache(int reset_type) @@ -241,7 +226,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) unsigned char sha1[20], *orig = NULL, sha1_orig[20], *old_orig = NULL, sha1_old_orig[20]; struct commit *commit; - char *reflog_action, msg[1024]; + struct strbuf msg = STRBUF_INIT; const struct option options[] = { OPT__QUIET(&quiet, "be quiet, only report errors"), OPT_SET_INT(0, "mixed", &reset_type, @@ -261,8 +246,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, git_reset_usage, PARSE_OPT_KEEP_DASHDASH); - reflog_action = args_to_str(argv); - setenv("GIT_REFLOG_ACTION", reflog_action, 0); /* * Possible arguments are: @@ -357,13 +340,13 @@ int cmd_reset(int argc, const char **argv, const char *prefix) old_orig = sha1_old_orig; if (!get_sha1("HEAD", sha1_orig)) { orig = sha1_orig; - prepend_reflog_action("updating ORIG_HEAD", msg, sizeof(msg)); - update_ref(msg, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR); + set_reflog_message(&msg, "updating ORIG_HEAD", NULL); + update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR); } else if (old_orig) delete_ref("ORIG_HEAD", old_orig, 0); - prepend_reflog_action("updating HEAD", msg, sizeof(msg)); - update_ref_status = update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR); + set_reflog_message(&msg, "updating HEAD", rev); + update_ref_status = update_ref(msg.buf, "HEAD", sha1, orig, 0, MSG_ON_ERR); switch (reset_type) { case HARD: @@ -380,7 +363,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) remove_branch_state(); - free(reflog_action); + strbuf_release(&msg); return update_ref_status; } diff --git a/builtin/tag.c b/builtin/tag.c index ec926fc8ee..667515e527 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -12,11 +12,13 @@ #include "tag.h" #include "run-command.h" #include "parse-options.h" +#include "diff.h" +#include "revision.h" static const char * const git_tag_usage[] = { "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]", "git tag -d <tagname>...", - "git tag -l [-n[<num>]] [<pattern>]", + "git tag -l [-n[<num>]] [<pattern>...]", "git tag -v <tagname>...", NULL }; @@ -24,17 +26,70 @@ static const char * const git_tag_usage[] = { static char signingkey[1000]; struct tag_filter { - const char *pattern; + const char **patterns; int lines; struct commit_list *with_commit; }; +static int match_pattern(const char **patterns, const char *ref) +{ + /* no pattern means match everything */ + if (!*patterns) + return 1; + for (; *patterns; patterns++) + if (!fnmatch(*patterns, ref, 0)) + return 1; + return 0; +} + +static int in_commit_list(const struct commit_list *want, struct commit *c) +{ + for (; want; want = want->next) + if (!hashcmp(want->item->object.sha1, c->object.sha1)) + return 1; + return 0; +} + +static int contains_recurse(struct commit *candidate, + const struct commit_list *want) +{ + struct commit_list *p; + + /* was it previously marked as containing a want commit? */ + if (candidate->object.flags & TMP_MARK) + return 1; + /* or marked as not possibly containing a want commit? */ + if (candidate->object.flags & UNINTERESTING) + return 0; + /* or are we it? */ + if (in_commit_list(want, candidate)) + return 1; + + if (parse_commit(candidate) < 0) + return 0; + + /* Otherwise recurse and mark ourselves for future traversals. */ + for (p = candidate->parents; p; p = p->next) { + if (contains_recurse(p->item, want)) { + candidate->object.flags |= TMP_MARK; + return 1; + } + } + candidate->object.flags |= UNINTERESTING; + return 0; +} + +static int contains(struct commit *candidate, const struct commit_list *want) +{ + return contains_recurse(candidate, want); +} + static int show_reference(const char *refname, const unsigned char *sha1, int flag, void *cb_data) { struct tag_filter *filter = cb_data; - if (!fnmatch(filter->pattern, refname, 0)) { + if (match_pattern(filter->patterns, refname)) { int i; unsigned long size; enum object_type type; @@ -47,7 +102,7 @@ static int show_reference(const char *refname, const unsigned char *sha1, commit = lookup_commit_reference_gently(sha1, 1); if (!commit) return 0; - if (!is_descendant_of(commit, filter->with_commit)) + if (!contains(commit, filter->with_commit)) return 0; } @@ -88,15 +143,12 @@ static int show_reference(const char *refname, const unsigned char *sha1, return 0; } -static int list_tags(const char *pattern, int lines, +static int list_tags(const char **patterns, int lines, struct commit_list *with_commit) { struct tag_filter filter; - if (pattern == NULL) - pattern = "*"; - - filter.pattern = pattern; + filter.patterns = patterns; filter.lines = lines; filter.with_commit = with_commit; @@ -425,7 +477,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) if (list + delete + verify > 1) usage_with_options(git_tag_usage, options); if (list) - return list_tags(argv[0], lines == -1 ? 0 : lines, + return list_tags(argv, lines == -1 ? 0 : lines, with_commit); if (lines != -1) die(_("-n option is only allowed with -l.")); diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index f63973c914..14e04e6795 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -90,7 +90,7 @@ static void use(int bytes) static void *get_data(unsigned long size) { - z_stream stream; + git_zstream stream; void *buf = xmalloc(size); memset(&stream, 0, sizeof(stream)); diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 76ba1d5881..835c62ab15 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -11,7 +11,7 @@ static const char * const git_update_ref_usage[] = { int cmd_update_ref(int argc, const char **argv, const char *prefix) { - const char *refname, *oldval, *msg=NULL; + const char *refname, *oldval, *msg = NULL; unsigned char sha1[20], oldsha1[20]; int delete = 0, no_deref = 0, flags = 0; struct option options[] = { @@ -16,13 +16,27 @@ #endif #include <zlib.h> -#if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200 -#define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) -#endif - -void git_inflate_init(z_streamp strm); -void git_inflate_end(z_streamp strm); -int git_inflate(z_streamp strm, int flush); +typedef struct git_zstream { + z_stream z; + unsigned long avail_in; + unsigned long avail_out; + unsigned long total_in; + unsigned long total_out; + unsigned char *next_in; + unsigned char *next_out; +} git_zstream; + +void git_inflate_init(git_zstream *); +void git_inflate_init_gzip_only(git_zstream *); +void git_inflate_end(git_zstream *); +int git_inflate(git_zstream *, int flush); + +void git_deflate_init(git_zstream *, int level); +void git_deflate_init_gzip(git_zstream *, int level); +void git_deflate_end(git_zstream *); +int git_deflate_end_gently(git_zstream *); +int git_deflate(git_zstream *, int flush); +unsigned long git_deflate_bound(git_zstream *, unsigned long); #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT) #define DTYPE(de) ((de)->d_type) @@ -420,7 +434,7 @@ extern char *get_index_file(void); extern char *get_graft_file(void); extern int set_git_dir(const char *path); extern const char *get_git_work_tree(void); -extern const char *read_gitfile_gently(const char *path); +extern const char *read_gitfile(const char *path); extern void set_git_work_tree(const char *tree); #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" @@ -1009,7 +1023,7 @@ extern struct packed_git *find_sha1_pack(const unsigned char *sha1, extern void pack_report(void); extern int open_pack_index(struct packed_git *); extern void close_pack_index(struct packed_git *); -extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *); +extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *); extern void close_pack_windows(struct packed_git *); extern void unuse_pack(struct pack_window **); extern void free_pack_by_name(const char *); @@ -1175,7 +1189,7 @@ extern int ws_blank_line(const char *line, int len, unsigned ws_rule); #define ws_tab_width(rule) ((rule) & WS_TAB_WIDTH_MASK) /* ls-files */ -int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset); +int report_path_error(const char *ps_matched, const char **pathspec, const char *prefix); void overlay_tree_on_cache(const char *tree_name, const char *prefix); char *alias_lookup(const char *alias); diff --git a/combine-diff.c b/combine-diff.c index 655fa89d8a..b11eb7102c 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -7,6 +7,7 @@ #include "xdiff-interface.h" #include "log-tree.h" #include "refs.h" +#include "userdiff.h" static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent) { @@ -92,7 +93,9 @@ struct sline { unsigned long *p_lno; }; -static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned long *size) +static char *grab_blob(const unsigned char *sha1, unsigned int mode, + unsigned long *size, struct userdiff_driver *textconv, + const char *path) { char *blob; enum object_type type; @@ -105,6 +108,11 @@ static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned lo /* deleted blob */ *size = 0; return xcalloc(1, 1); + } else if (textconv) { + struct diff_filespec *df = alloc_filespec(path); + fill_filespec(df, sha1, mode); + *size = fill_textconv(textconv, df, &blob); + free_filespec(df); } else { blob = read_sha1_file(sha1, &type, size); if (type != OBJ_BLOB) @@ -204,7 +212,9 @@ static void consume_line(void *state_, char *line, unsigned long len) static void combine_diff(const unsigned char *parent, unsigned int mode, mmfile_t *result_file, struct sline *sline, unsigned int cnt, int n, - int num_parent, int result_deleted) + int num_parent, int result_deleted, + struct userdiff_driver *textconv, + const char *path) { unsigned int p_lno, lno; unsigned long nmask = (1UL << n); @@ -217,7 +227,7 @@ static void combine_diff(const unsigned char *parent, unsigned int mode, if (result_deleted) return; /* result deleted */ - parent_file.ptr = grab_blob(parent, mode, &sz); + parent_file.ptr = grab_blob(parent, mode, &sz, textconv, path); parent_file.size = sz; memset(&xpp, 0, sizeof(xpp)); xpp.flags = 0; @@ -681,8 +691,85 @@ static void dump_quoted_path(const char *head, puts(buf.buf); } +static void show_combined_header(struct combine_diff_path *elem, + int num_parent, + int dense, + struct rev_info *rev, + int mode_differs, + int show_file_header) +{ + struct diff_options *opt = &rev->diffopt; + int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV; + const char *a_prefix = opt->a_prefix ? opt->a_prefix : "a/"; + const char *b_prefix = opt->b_prefix ? opt->b_prefix : "b/"; + int use_color = DIFF_OPT_TST(opt, COLOR_DIFF); + const char *c_meta = diff_get_color(use_color, DIFF_METAINFO); + const char *c_reset = diff_get_color(use_color, DIFF_RESET); + const char *abb; + int added = 0; + int deleted = 0; + int i; + + if (rev->loginfo && !rev->no_commit_id) + show_log(rev); + + dump_quoted_path(dense ? "diff --cc " : "diff --combined ", + "", elem->path, c_meta, c_reset); + printf("%sindex ", c_meta); + for (i = 0; i < num_parent; i++) { + abb = find_unique_abbrev(elem->parent[i].sha1, + abbrev); + printf("%s%s", i ? "," : "", abb); + } + abb = find_unique_abbrev(elem->sha1, abbrev); + printf("..%s%s\n", abb, c_reset); + + if (mode_differs) { + deleted = !elem->mode; + + /* We say it was added if nobody had it */ + added = !deleted; + for (i = 0; added && i < num_parent; i++) + if (elem->parent[i].status != + DIFF_STATUS_ADDED) + added = 0; + if (added) + printf("%snew file mode %06o", + c_meta, elem->mode); + else { + if (deleted) + printf("%sdeleted file ", c_meta); + printf("mode "); + for (i = 0; i < num_parent; i++) { + printf("%s%06o", i ? "," : "", + elem->parent[i].mode); + } + if (elem->mode) + printf("..%06o", elem->mode); + } + printf("%s\n", c_reset); + } + + if (!show_file_header) + return; + + if (added) + dump_quoted_path("--- ", "", "/dev/null", + c_meta, c_reset); + else + dump_quoted_path("--- ", a_prefix, elem->path, + c_meta, c_reset); + if (deleted) + dump_quoted_path("+++ ", "", "/dev/null", + c_meta, c_reset); + else + dump_quoted_path("+++ ", b_prefix, elem->path, + c_meta, c_reset); +} + static void show_patch_diff(struct combine_diff_path *elem, int num_parent, - int dense, struct rev_info *rev) + int dense, int working_tree_file, + struct rev_info *rev) { struct diff_options *opt = &rev->diffopt; unsigned long result_size, cnt, lno; @@ -691,18 +778,22 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, struct sline *sline; /* survived lines */ int mode_differs = 0; int i, show_hunks; - int working_tree_file = is_null_sha1(elem->sha1); - int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV; - const char *a_prefix, *b_prefix; mmfile_t result_file; + struct userdiff_driver *userdiff; + struct userdiff_driver *textconv = NULL; + int is_binary; context = opt->context; - a_prefix = opt->a_prefix ? opt->a_prefix : "a/"; - b_prefix = opt->b_prefix ? opt->b_prefix : "b/"; + userdiff = userdiff_find_by_path(elem->path); + if (!userdiff) + userdiff = userdiff_find_by_name("default"); + if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV)) + textconv = userdiff_get_textconv(userdiff); /* Read the result of merge first */ if (!working_tree_file) - result = grab_blob(elem->sha1, elem->mode, &result_size); + result = grab_blob(elem->sha1, elem->mode, &result_size, + textconv, elem->path); else { /* Used by diff-tree to read from the working tree */ struct stat st; @@ -725,9 +816,16 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, } else if (S_ISDIR(st.st_mode)) { unsigned char sha1[20]; if (resolve_gitlink_ref(elem->path, "HEAD", sha1) < 0) - result = grab_blob(elem->sha1, elem->mode, &result_size); + result = grab_blob(elem->sha1, elem->mode, + &result_size, NULL, NULL); else - result = grab_blob(sha1, elem->mode, &result_size); + result = grab_blob(sha1, elem->mode, + &result_size, NULL, NULL); + } else if (textconv) { + struct diff_filespec *df = alloc_filespec(elem->path); + fill_filespec(df, null_sha1, st.st_mode); + result_size = fill_textconv(textconv, df, &result); + free_filespec(df); } else if (0 <= (fd = open(elem->path, O_RDONLY))) { size_t len = xsize_t(st.st_size); ssize_t done; @@ -777,6 +875,38 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, close(fd); } + for (i = 0; i < num_parent; i++) { + if (elem->parent[i].mode != elem->mode) { + mode_differs = 1; + break; + } + } + + if (textconv) + is_binary = 0; + else if (userdiff->binary != -1) + is_binary = userdiff->binary; + else { + is_binary = buffer_is_binary(result, result_size); + for (i = 0; !is_binary && i < num_parent; i++) { + char *buf; + unsigned long size; + buf = grab_blob(elem->parent[i].sha1, + elem->parent[i].mode, + &size, NULL, NULL); + if (buffer_is_binary(buf, size)) + is_binary = 1; + free(buf); + } + } + if (is_binary) { + show_combined_header(elem, num_parent, dense, rev, + mode_differs, 0); + printf("Binary files differ\n"); + free(result); + return; + } + for (cnt = 0, cp = result; cp < result + result_size; cp++) { if (*cp == '\n') cnt++; @@ -824,71 +954,15 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, combine_diff(elem->parent[i].sha1, elem->parent[i].mode, &result_file, sline, - cnt, i, num_parent, result_deleted); - if (elem->parent[i].mode != elem->mode) - mode_differs = 1; + cnt, i, num_parent, result_deleted, + textconv, elem->path); } show_hunks = make_hunks(sline, cnt, num_parent, dense); if (show_hunks || mode_differs || working_tree_file) { - const char *abb; - int use_color = DIFF_OPT_TST(opt, COLOR_DIFF); - const char *c_meta = diff_get_color(use_color, DIFF_METAINFO); - const char *c_reset = diff_get_color(use_color, DIFF_RESET); - int added = 0; - int deleted = 0; - - if (rev->loginfo && !rev->no_commit_id) - show_log(rev); - dump_quoted_path(dense ? "diff --cc " : "diff --combined ", - "", elem->path, c_meta, c_reset); - printf("%sindex ", c_meta); - for (i = 0; i < num_parent; i++) { - abb = find_unique_abbrev(elem->parent[i].sha1, - abbrev); - printf("%s%s", i ? "," : "", abb); - } - abb = find_unique_abbrev(elem->sha1, abbrev); - printf("..%s%s\n", abb, c_reset); - - if (mode_differs) { - deleted = !elem->mode; - - /* We say it was added if nobody had it */ - added = !deleted; - for (i = 0; added && i < num_parent; i++) - if (elem->parent[i].status != - DIFF_STATUS_ADDED) - added = 0; - if (added) - printf("%snew file mode %06o", - c_meta, elem->mode); - else { - if (deleted) - printf("%sdeleted file ", c_meta); - printf("mode "); - for (i = 0; i < num_parent; i++) { - printf("%s%06o", i ? "," : "", - elem->parent[i].mode); - } - if (elem->mode) - printf("..%06o", elem->mode); - } - printf("%s\n", c_reset); - } - if (added) - dump_quoted_path("--- ", "", "/dev/null", - c_meta, c_reset); - else - dump_quoted_path("--- ", a_prefix, elem->path, - c_meta, c_reset); - if (deleted) - dump_quoted_path("+++ ", "", "/dev/null", - c_meta, c_reset); - else - dump_quoted_path("+++ ", b_prefix, elem->path, - c_meta, c_reset); + show_combined_header(elem, num_parent, dense, rev, + mode_differs, 1); dump_sline(sline, cnt, num_parent, DIFF_OPT_TST(opt, COLOR_DIFF), result_deleted); } @@ -954,6 +1028,12 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re write_name_quoted(p->path, stdout, line_termination); } +/* + * The result (p->elem) is from the working tree and their + * parents are typically from multiple stages during a merge + * (i.e. diff-files) or the state in HEAD and in the index + * (i.e. diff-index). + */ void show_combined_diff(struct combine_diff_path *p, int num_parent, int dense, @@ -967,7 +1047,7 @@ void show_combined_diff(struct combine_diff_path *p, DIFF_FORMAT_NAME_STATUS)) show_raw_diff(p, num_parent, rev); else if (opt->output_format & DIFF_FORMAT_PATCH) - show_patch_diff(p, num_parent, dense, rev); + show_patch_diff(p, num_parent, dense, 1, rev); } void diff_tree_combined(const unsigned char *sha1, @@ -1035,7 +1115,7 @@ void diff_tree_combined(const unsigned char *sha1, for (p = paths; p; p = p->next) { if (p->len) show_patch_diff(p, num_parent, dense, - rev); + 0, rev); } } } @@ -515,7 +515,7 @@ void sort_in_topological_order(struct commit_list ** list, int lifo) commit = work_item->item; for (parents = commit->parents; parents ; parents = parents->next) { - struct commit *parent=parents->item; + struct commit *parent = parents->item; if (!parent->indegree) continue; diff --git a/compat/cygwin.c b/compat/cygwin.c index b4a51b958c..ba3327f1f9 100644 --- a/compat/cygwin.c +++ b/compat/cygwin.c @@ -101,7 +101,7 @@ static int cygwin_stat(const char *path, struct stat *buf) * and calling git_default_config() from here would break such variables. */ static int native_stat = 1; -static int core_filemode; +static int core_filemode = 1; /* matches trust_executable_bit default */ static int git_cygwin_config(const char *var, const char *value, void *cb) { @@ -42,10 +42,10 @@ void git_config_push_parameter(const char *text) static int git_config_parse_parameter(const char *text, config_fn_t fn, void *data) { - struct strbuf tmp = STRBUF_INIT; struct strbuf **pair; - strbuf_addstr(&tmp, text); - pair = strbuf_split(&tmp, '='); + pair = strbuf_split_str(text, '=', 2); + if (!pair[0]) + return error("bogus config parameter: %s", text); if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=') strbuf_setlen(pair[0], pair[0]->len - 1); strbuf_trim(pair[0]); @@ -856,7 +856,7 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config) switch (git_config_from_parameters(fn, data)) { case -1: /* error */ - ret--; + die("unable to parse command-line config"); break; case 0: /* found nothing */ break; @@ -1479,10 +1479,10 @@ int git_config_rename_section(const char *old_name, const char *new_name) } } fclose(config_file); - unlock_and_out: +unlock_and_out: if (commit_lock_file(lock) < 0) ret = error("could not commit config file %s", config_filename); - out: +out: free(config_filename); return ret; } @@ -192,7 +192,8 @@ static const char *ai_name(const struct addrinfo *ai) */ static int git_tcp_connect_sock(char *host, int flags) { - int sockfd = -1, saved_errno = 0; + struct strbuf error_message = STRBUF_INIT; + int sockfd = -1; const char *port = STR(DEFAULT_GIT_PORT); struct addrinfo hints, *ai0, *ai; int gai; @@ -216,21 +217,15 @@ static int git_tcp_connect_sock(char *host, int flags) if (flags & CONNECT_VERBOSE) fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port); - for (ai0 = ai; ai; ai = ai->ai_next) { + for (ai0 = ai; ai; ai = ai->ai_next, cnt++) { sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sockfd < 0) { - saved_errno = errno; - continue; - } - if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { - saved_errno = errno; - fprintf(stderr, "%s[%d: %s]: errno=%s\n", - host, - cnt, - ai_name(ai), - strerror(saved_errno)); - close(sockfd); + if ((sockfd < 0) || + (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)) { + strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n", + host, cnt, ai_name(ai), strerror(errno)); + if (0 <= sockfd) + close(sockfd); sockfd = -1; continue; } @@ -242,11 +237,13 @@ static int git_tcp_connect_sock(char *host, int flags) freeaddrinfo(ai0); if (sockfd < 0) - die("unable to connect a socket (%s)", strerror(saved_errno)); + die("unable to connect to %s:\n%s", host, error_message.buf); if (flags & CONNECT_VERBOSE) fprintf(stderr, "done.\n"); + strbuf_release(&error_message); + return sockfd; } diff --git a/contrib/convert-objects/git-convert-objects.txt b/contrib/convert-objects/git-convert-objects.txt index 9718abf86d..0565d83fc4 100644 --- a/contrib/convert-objects/git-convert-objects.txt +++ b/contrib/convert-objects/git-convert-objects.txt @@ -8,6 +8,7 @@ git-convert-objects - Converts old-style git repository SYNOPSIS -------- +[verse] 'git-convert-objects' DESCRIPTION diff --git a/contrib/gitview/gitview.txt b/contrib/gitview/gitview.txt index 77c29de305..9e12f97842 100644 --- a/contrib/gitview/gitview.txt +++ b/contrib/gitview/gitview.txt @@ -7,6 +7,7 @@ gitview - A GTK based repository browser for git SYNOPSIS -------- +[verse] 'gitview' [options] [args] DESCRIPTION diff --git a/contrib/svn-fe/svn-fe.txt b/contrib/svn-fe/svn-fe.txt index cd075b96c5..72ffea0b3a 100644 --- a/contrib/svn-fe/svn-fe.txt +++ b/contrib/svn-fe/svn-fe.txt @@ -7,6 +7,7 @@ svn-fe - convert an SVN "dumpfile" to a fast-import stream SYNOPSIS -------- +[verse] svnadmin dump --incremental REPO | svn-fe [url] | git fast-import DESCRIPTION diff --git a/diff-lib.c b/diff-lib.c index 9c29293bbc..b3797592c6 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -379,7 +379,8 @@ static void do_oneway_diff(struct unpack_trees_options *o, if (cached && idx && ce_stage(idx)) { struct diff_filepair *pair; pair = diff_unmerge(&revs->diffopt, idx->name); - fill_filespec(pair->one, idx->sha1, idx->ce_mode); + if (tree) + fill_filespec(pair->one, tree->sha1, tree->ce_mode); return; } @@ -433,8 +434,13 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o) if (tree == o->df_conflict_entry) tree = NULL; - if (ce_path_match(idx ? idx : tree, &revs->prune_data)) + if (ce_path_match(idx ? idx : tree, &revs->prune_data)) { do_oneway_diff(o, idx, tree); + if (diff_can_quit_early(&revs->diffopt)) { + o->exiting_early = 1; + return -1; + } + } return 0; } @@ -1839,20 +1839,20 @@ static unsigned char *deflate_it(char *data, { int bound; unsigned char *deflated; - z_stream stream; + git_zstream stream; memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, zlib_compression_level); - bound = deflateBound(&stream, size); + git_deflate_init(&stream, zlib_compression_level); + bound = git_deflate_bound(&stream, size); deflated = xmalloc(bound); stream.next_out = deflated; stream.avail_out = bound; stream.next_in = (unsigned char *)data; stream.avail_in = size; - while (deflate(&stream, Z_FINISH) == Z_OK) + while (git_deflate(&stream, Z_FINISH) == Z_OK) ; /* nothing */ - deflateEnd(&stream); + git_deflate_end(&stream); *result_size = stream.total_out; return deflated; } @@ -1984,19 +1984,7 @@ struct userdiff_driver *get_textconv(struct diff_filespec *one) return NULL; diff_filespec_load_driver(one); - if (!one->driver->textconv) - return NULL; - - if (one->driver->textconv_want_cache && !one->driver->textconv_cache) { - struct notes_cache *c = xmalloc(sizeof(*c)); - struct strbuf name = STRBUF_INIT; - - strbuf_addf(&name, "textconv/%s", one->driver->name); - notes_cache_init(c, name.buf, one->driver->textconv); - one->driver->textconv_cache = c; - } - - return one->driver; + return userdiff_get_textconv(one->driver); } static void builtin_diff(const char *name_a, diff --git a/environment.c b/environment.c index 94d58fd244..2228c4e9a1 100644 --- a/environment.c +++ b/environment.c @@ -91,7 +91,7 @@ static void setup_git_env(void) git_dir = getenv(GIT_DIR_ENVIRONMENT); git_dir = git_dir ? xstrdup(git_dir) : NULL; if (!git_dir) { - git_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT); + git_dir = read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT); git_dir = git_dir ? xstrdup(git_dir) : NULL; } if (!git_dir) diff --git a/fast-import.c b/fast-import.c index 78d978684d..1d5e3336a5 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1017,7 +1017,7 @@ static int store_object( unsigned char sha1[20]; unsigned long hdrlen, deltalen; git_SHA_CTX c; - z_stream s; + git_zstream s; hdrlen = sprintf((char *)hdr,"%s %lu", typename(type), (unsigned long)dat->len) + 1; @@ -1050,7 +1050,7 @@ static int store_object( delta = NULL; memset(&s, 0, sizeof(s)); - deflateInit(&s, pack_compression_level); + git_deflate_init(&s, pack_compression_level); if (delta) { s.next_in = delta; s.avail_in = deltalen; @@ -1058,11 +1058,11 @@ static int store_object( s.next_in = (void *)dat->buf; s.avail_in = dat->len; } - s.avail_out = deflateBound(&s, s.avail_in); + s.avail_out = git_deflate_bound(&s, s.avail_in); s.next_out = out = xmalloc(s.avail_out); - while (deflate(&s, Z_FINISH) == Z_OK) - /* nothing */; - deflateEnd(&s); + while (git_deflate(&s, Z_FINISH) == Z_OK) + ; /* nothing */ + git_deflate_end(&s); /* Determine if we should auto-checkpoint. */ if ((max_packsize && (pack_size + 60 + s.total_out) > max_packsize) @@ -1078,14 +1078,14 @@ static int store_object( delta = NULL; memset(&s, 0, sizeof(s)); - deflateInit(&s, pack_compression_level); + git_deflate_init(&s, pack_compression_level); s.next_in = (void *)dat->buf; s.avail_in = dat->len; - s.avail_out = deflateBound(&s, s.avail_in); + s.avail_out = git_deflate_bound(&s, s.avail_in); s.next_out = out = xrealloc(out, s.avail_out); - while (deflate(&s, Z_FINISH) == Z_OK) - /* nothing */; - deflateEnd(&s); + while (git_deflate(&s, Z_FINISH) == Z_OK) + ; /* nothing */ + git_deflate_end(&s); } } @@ -1163,7 +1163,7 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark) off_t offset; git_SHA_CTX c; git_SHA_CTX pack_file_ctx; - z_stream s; + git_zstream s; int status = Z_OK; /* Determine if we should auto-checkpoint. */ @@ -1187,7 +1187,7 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark) crc32_begin(pack_file); memset(&s, 0, sizeof(s)); - deflateInit(&s, pack_compression_level); + git_deflate_init(&s, pack_compression_level); hdrlen = encode_in_pack_object_header(OBJ_BLOB, len, out_buf); if (out_sz <= hdrlen) @@ -1209,7 +1209,7 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark) len -= n; } - status = deflate(&s, len ? 0 : Z_FINISH); + status = git_deflate(&s, len ? 0 : Z_FINISH); if (!s.avail_out || status == Z_STREAM_END) { size_t n = s.next_out - out_buf; @@ -1228,7 +1228,7 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark) die("unexpected deflate failure: %d", status); } } - deflateEnd(&s); + git_deflate_end(&s); git_SHA1_Final(sha1, &c); if (sha1out) @@ -305,7 +305,8 @@ split_patches () { msgnum= ;; *) - if test -n "$parse_patch" ; then + if test -n "$patch_format" + then clean_abort "Patch format $patch_format is not supported." else clean_abort "Patch format detection failed." @@ -507,6 +508,8 @@ else fi fi +git update-index -q --refresh + case "$resolved" in '') case "$HAS_HEAD" in diff --git a/git-compat-util.h b/git-compat-util.h index e0bb81ed8d..041cbdb93e 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -236,6 +236,7 @@ extern char *gitbasename(char *); /* General helper functions */ extern void vreportf(const char *prefix, const char *err, va_list params); +extern void vwritef(int fd, const char *prefix, const char *err, va_list params); extern NORETURN void usage(const char *err); extern NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2))); extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2))); @@ -244,6 +245,7 @@ extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params)); +extern void set_error_routine(void (*routine)(const char *err, va_list params)); extern int prefixcmp(const char *str, const char *prefix); extern int suffixcmp(const char *str, const char *suffix); diff --git a/git-filter-branch.sh b/git-filter-branch.sh index 962a93b586..6b5f2251b6 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -363,7 +363,7 @@ while read commit parents; do sed -e '1,/^$/d' <../commit | \ eval "$filter_msg" > ../message || die "msg filter failed: $filter_msg" - @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \ + workdir=$workdir @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \ $(git write-tree) $parentstr < ../message > ../map/$commit || die "could not write rewritten commit" done <../revs diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh index 4db9212331..a79a2ecd49 100644 --- a/git-mergetool--lib.sh +++ b/git-mergetool--lib.sh @@ -38,7 +38,7 @@ check_unchanged () { while true; do echo "$MERGED seems unchanged." printf "Was the merge successful? [y/n] " - read answer + read answer || return 1 case "$answer" in y*|Y*) status=0; break ;; n*|N*) status=1; break ;; diff --git a/git-mergetool.sh b/git-mergetool.sh index 3aab5aae84..b6d463f0d0 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -72,7 +72,7 @@ describe_file () { resolve_symlink_merge () { while true; do printf "Use (l)ocal or (r)emote, or (a)bort? " - read ans + read ans || return 1 case "$ans" in [lL]*) git checkout-index -f --stage=2 -- "$MERGED" @@ -100,7 +100,7 @@ resolve_deleted_merge () { else printf "Use (c)reated or (d)eleted file, or (a)bort? " fi - read ans + read ans || return 1 case "$ans" in [mMcC]*) git add -- "$MERGED" @@ -122,7 +122,7 @@ resolve_deleted_merge () { resolve_submodule_merge () { while true; do printf "Use (l)ocal or (r)emote, or (a)bort? " - read ans + read ans || return 1 case "$ans" in [lL]*) if ! local_present; then @@ -249,7 +249,7 @@ merge_file () { describe_file "$remote_mode" "remote" "$REMOTE" if "$prompt" = true; then printf "Hit return to start merge resolution tool (%s): " "$merge_tool" - read ans + read ans || return 1 fi if base_present; then @@ -320,7 +320,7 @@ done prompt_after_failed_merge() { while true; do printf "Continue merging other unresolved paths (y/n) ? " - read ans + read ans || return 1 case "$ans" in [yY]*) diff --git a/git-pull.sh b/git-pull.sh index fb9e2df931..28441aca8a 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -9,7 +9,7 @@ LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEA SUBDIRECTORY_OK=Yes OPTIONS_SPEC= . git-sh-setup -set_reflog_action "pull $*" +set_reflog_action "pull${1+ $*}" require_work_tree cd_to_toplevel diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 65690af893..c6ba7c1551 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -713,7 +713,6 @@ then # parents to rewrite and skipping dropped commits would # prematurely end our probe merges_option= - first_after_upstream="$(git rev-list --reverse --first-parent $upstream..$orig_head | head -n 1)" else merges_option="--no-merges --cherry-pick" fi @@ -746,7 +745,7 @@ do preserve=t for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-) do - if test -f "$rewritten"/$p -a \( $p != $onto -o $sha1 = $first_after_upstream \) + if test -f "$rewritten"/$p then preserve=f fi diff --git a/git-rebase.sh b/git-rebase.sh index d7855ea1c6..38cbee7dce 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -13,7 +13,7 @@ It then attempts to create a new commit for each commit from the original It is possible that a merge failure will prevent this process from being completely automatic. You will have to resolve any such merge failure and run git rebase --continue. Another option is to bypass the commit -that caused the merge failure with git rebase --skip. To restore the +that caused the merge failure with git rebase --skip. To check out the original <branch> and remove the .git/rebase-apply working files, use the command git rebase --abort instead. @@ -57,9 +57,9 @@ whitespace=! passed to 'git apply' ignore-whitespace! passed to 'git apply' C=! passed to 'git apply' Actions: -continue! continue rebasing process -abort! abort rebasing process and restore original branch -skip! skip current patch and continue rebasing process +continue! continue +abort! abort and check out the original branch +skip! skip current patch and continue " . git-sh-setup set_reflog_action rebase @@ -72,7 +72,7 @@ ok_to_skip_pre_rebase= resolvemsg=" When you have resolved this problem run \"git rebase --continue\". If you would prefer to skip this patch, instead run \"git rebase --skip\". -To restore the original branch and stop rebasing run \"git rebase --abort\". +To check out the original branch and stop rebasing run \"git rebase --abort\". " unset onto strategy= diff --git a/git-submodule.sh b/git-submodule.sh index d189a24c71..c94218b877 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -34,7 +34,7 @@ resolve_relative_url () { remote=$(get_default_remote) remoteurl=$(git config "remote.$remote.url") || - die "remote ($remote) does not have a url defined in .git/config" + remoteurl=$(pwd) # the repository is its own authoritative upstream url="$1" remoteurl=${remoteurl%/} sep=/ @@ -121,12 +121,17 @@ module_clone() path=$1 url=$2 reference="$3" + quiet= + if test -n "$GIT_QUIET" + then + quiet=-q + fi if test -n "$reference" then - git-clone "$reference" -n "$url" "$path" + git-clone $quiet "$reference" -n "$url" "$path" else - git-clone -n "$url" "$path" + git-clone $quiet -n "$url" "$path" fi || die "Clone of '$url' into submodule path '$path' failed" } @@ -238,15 +243,6 @@ cmd_add() die "'$path' already exists and is not a valid git repo" fi - case "$repo" in - ./*|../*) - url=$(resolve_relative_url "$repo") || exit - ;; - *) - url="$repo" - ;; - esac - git config submodule."$path".url "$url" else module_clone "$path" "$realrepo" "$reference" || exit @@ -260,6 +256,7 @@ cmd_add() esac ) || die "Unable to checkout submodule '$path'" fi + git config submodule."$path".url "$realrepo" git add $force "$path" || die "Failed to add submodule '$path'" @@ -300,6 +297,10 @@ cmd_foreach() toplevel=$(pwd) + # dup stdin so that it can be restored when running the external + # command in the subshell (and a recursive call to this function) + exec 3<&0 + module_list | while read mode sha1 stage path do @@ -316,7 +317,7 @@ cmd_foreach() then cmd_foreach "--recursive" "$@" fi - ) || + ) <&3 3<&- || die "Stopping at '$path'; script returned non-zero status." fi done @@ -355,25 +356,26 @@ cmd_init() do # Skip already registered paths name=$(module_name "$path") || exit - url=$(git config submodule."$name".url) - test -z "$url" || continue - - url=$(git config -f .gitmodules submodule."$name".url) - test -z "$url" && - die "No url found for submodule path '$path' in .gitmodules" - - # Possibly a url relative to parent - case "$url" in - ./*|../*) - url=$(resolve_relative_url "$url") || exit - ;; - esac - - git config submodule."$name".url "$url" || - die "Failed to register url for submodule path '$path'" + if test -z "$(git config "submodule.$name.url")" + then + url=$(git config -f .gitmodules submodule."$name".url) + test -z "$url" && + die "No url found for submodule path '$path' in .gitmodules" + + # Possibly a url relative to parent + case "$url" in + ./*|../*) + url=$(resolve_relative_url "$url") || exit + ;; + esac + git config submodule."$name".url "$url" || + die "Failed to register url for submodule path '$path'" + fi + # Copy "update" setting when it is not set yet upd="$(git config -f .gitmodules submodule."$name".update)" test -z "$upd" || + test -n "$(git config submodule."$name".update)" || git config submodule."$name".update "$upd" || die "Failed to register update mode for submodule path '$path'" @@ -874,17 +876,20 @@ cmd_sync() ;; esac - say "Synchronizing submodule url for '$name'" - git config submodule."$name".url "$url" - - if test -e "$path"/.git + if git config "submodule.$name.url" >/dev/null 2>/dev/null then - ( - clear_local_git_env - cd "$path" - remote=$(get_default_remote) - git config remote."$remote".url "$url" - ) + say "Synchronizing submodule url for '$name'" + git config submodule."$name".url "$url" + + if test -e "$path"/.git + then + ( + clear_local_git_env + cd "$path" + remote=$(get_default_remote) + git config remote."$remote".url "$url" + ) + fi fi done } diff --git a/git-svn.perl b/git-svn.perl index 7849cfc141..89f83fd27a 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -3124,8 +3124,12 @@ sub lookup_svn_merge { next; } - push @merged_commit_ranges, - "$bottom_commit^..$top_commit"; + if (scalar(command('rev-parse', "$bottom_commit^@"))) { + push @merged_commit_ranges, + "$bottom_commit^..$top_commit"; + } else { + push @merged_commit_ranges, "$top_commit"; + } if ( !defined $tip or $top > $tip ) { $tip = $top; @@ -3154,9 +3158,9 @@ sub check_cherry_pick { my $parents = shift; my @ranges = @_; my %commits = map { $_ => 1 } - _rev_list("--no-merges", $tip, "--not", $base, @$parents); + _rev_list("--no-merges", $tip, "--not", $base, @$parents, "--"); for my $range ( @ranges ) { - delete @commits{_rev_list($range)}; + delete @commits{_rev_list($range, "--")}; } for my $commit (keys %commits) { if (has_no_changes($commit)) { diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 81dacf2b6a..50a835a5bf 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6129,7 +6129,16 @@ sub git_blob_plain { # want to be sure not to break that by serving the image as an # attachment (though Firefox 3 doesn't seem to care). my $sandbox = $prevent_xss && - $type !~ m!^(?:text/plain|image/(?:gif|png|jpeg))(?:[ ;]|$)!; + $type !~ m!^(?:text/[a-z]+|image/(?:gif|png|jpeg))(?:[ ;]|$)!; + + # serve text/* as text/plain + if ($prevent_xss && + ($type =~ m!^text/[a-z]+\b(.*)$! || + ($type =~ m!^[a-z]+/[a-z]\+xml\b(.*)$! && -T $fd))) { + my $rest = $1; + $rest = defined $rest ? $rest : ''; + $type = "text/plain$rest"; + } print $cgi->header( -type => $type, @@ -302,6 +302,10 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) #define SIMILARITY_FLOOR 7 #define SIMILAR_ENOUGH(x) ((x) < SIMILARITY_FLOOR) +static const char bad_interpreter_advice[] = + N_("'%s' appears to be a git command, but we were not\n" + "able to execute it. Maybe git-%s is broken?"); + const char *help_unknown_cmd(const char *cmd) { int i, n, best_similarity = 0; @@ -326,6 +330,14 @@ const char *help_unknown_cmd(const char *cmd) int cmp = 0; /* avoid compiler stupidity */ const char *candidate = main_cmds.names[i]->name; + /* + * An exact match means we have the command, but + * for some reason exec'ing it gave us ENOENT; probably + * it's a bad interpreter in the #! line. + */ + if (!strcmp(candidate, cmd)) + die(_(bad_interpreter_advice), cmd, cmd); + /* Does the candidate appear in common_cmds list? */ while (n < ARRAY_SIZE(common_cmds) && (cmp = strcmp(common_cmds[n].name, candidate)) < 0) diff --git a/http-backend.c b/http-backend.c index 85015048dd..59ad7da605 100644 --- a/http-backend.c +++ b/http-backend.c @@ -271,16 +271,13 @@ static struct rpc_service *select_service(const char *name) static void inflate_request(const char *prog_name, int out) { - z_stream stream; + git_zstream stream; unsigned char in_buf[8192]; unsigned char out_buf[8192]; unsigned long cnt = 0; - int ret; memset(&stream, 0, sizeof(stream)); - ret = inflateInit2(&stream, (15 + 16)); - if (ret != Z_OK) - die("cannot start zlib inflater, zlib err %d", ret); + git_inflate_init_gzip_only(&stream); while (1) { ssize_t n = xread(0, in_buf, sizeof(in_buf)); @@ -296,7 +293,7 @@ static void inflate_request(const char *prog_name, int out) stream.next_out = out_buf; stream.avail_out = sizeof(out_buf); - ret = inflate(&stream, Z_NO_FLUSH); + ret = git_inflate(&stream, Z_NO_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) die("zlib error inflating request, result %d", ret); @@ -311,7 +308,7 @@ static void inflate_request(const char *prog_name, int out) } done: - inflateEnd(&stream); + git_inflate_end(&stream); close(out); } diff --git a/http-push.c b/http-push.c index 28bfe768f7..376331a76f 100644 --- a/http-push.c +++ b/http-push.c @@ -377,15 +377,15 @@ static void start_put(struct transfer_request *request) unsigned long len; int hdrlen; ssize_t size; - z_stream stream; + git_zstream stream; unpacked = read_sha1_file(request->obj->sha1, &type, &len); hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1; /* Set it up */ memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, zlib_compression_level); - size = deflateBound(&stream, len + hdrlen); + git_deflate_init(&stream, zlib_compression_level); + size = git_deflate_bound(&stream, len + hdrlen); strbuf_init(&request->buffer.buf, size); request->buffer.posn = 0; @@ -396,15 +396,15 @@ static void start_put(struct transfer_request *request) /* First header.. */ stream.next_in = (void *)hdr; stream.avail_in = hdrlen; - while (deflate(&stream, 0) == Z_OK) - /* nothing */; + while (git_deflate(&stream, 0) == Z_OK) + ; /* nothing */ /* Then the data itself.. */ stream.next_in = unpacked; stream.avail_in = len; - while (deflate(&stream, Z_FINISH) == Z_OK) - /* nothing */; - deflateEnd(&stream); + while (git_deflate(&stream, Z_FINISH) == Z_OK) + ; /* nothing */ + git_deflate_end(&stream); free(unpacked); request->buffer.buf.len = stream.total_out; @@ -1655,7 +1655,7 @@ static int delete_remote_branch(const char *pattern, int force) return error("Remote HEAD is not a symref"); /* Remote branch must not be the remote HEAD */ - for (i=0; symref && i<MAXDEPTH; i++) { + for (i = 0; symref && i < MAXDEPTH; i++) { if (!strcmp(remote_ref->name, symref)) return error("Remote branch %s is the current HEAD", remote_ref->name); @@ -172,7 +172,7 @@ struct http_object_request { unsigned char sha1[20]; unsigned char real_sha1[20]; git_SHA_CTX c; - z_stream stream; + git_zstream stream; int zret; int rename; struct active_request_slot *slot; @@ -1105,7 +1105,7 @@ int remove_note(struct notes_tree *t, const unsigned char *object_sha1) hashcpy(l.key_sha1, object_sha1); hashclr(l.val_sha1); note_tree_remove(t, t->root, 0, &l); - if (is_null_sha1(l.val_sha1)) // no note was removed + if (is_null_sha1(l.val_sha1)) /* no note was removed */ return 1; t->dirty = 1; return 0; diff --git a/pack-check.c b/pack-check.c index a1a521648d..0c19b6e5a5 100644 --- a/pack-check.c +++ b/pack-check.c @@ -26,7 +26,7 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, uint32_t data_crc = crc32(0, NULL, 0); do { - unsigned int avail; + unsigned long avail; void *data = use_pack(p, w_curs, offset, &avail); if (avail > len) avail = len; @@ -61,7 +61,7 @@ static int verify_packfile(struct packed_git *p, git_SHA1_Init(&ctx); do { - unsigned int remaining; + unsigned long remaining; unsigned char *in = use_pack(p, w_curs, offset, &remaining); offset += remaining; if (!pack_sig_ofs) @@ -139,7 +139,7 @@ char *git_path_submodule(const char *path, const char *fmt, ...) strbuf_addch(&buf, '/'); strbuf_addstr(&buf, ".git"); - git_dir = read_gitfile_gently(buf.buf); + git_dir = read_gitfile(buf.buf); if (git_dir) { strbuf_reset(&buf); strbuf_addstr(&buf, git_dir); @@ -325,8 +325,12 @@ static const char *path_relative(const char *in, int len, if (len < 0) len = strlen(in); - if (prefix && prefix_len < 0) - prefix_len = strlen(prefix); + if (prefix_len < 0) { + if (prefix) + prefix_len = strlen(prefix); + else + prefix_len = 0; + } off = 0; i = 0; diff --git a/read-cache.c b/read-cache.c index 4ac9a037f4..0a641034ce 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1087,7 +1087,7 @@ static void show_file(const char * fmt, const char * name, int in_porcelain, { if (in_porcelain && *first && header_msg) { printf("%s\n", header_msg); - *first=0; + *first = 0; } printf(fmt, name); } @@ -451,7 +451,7 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *re memcpy(gitdir + len, "/.git", 6); len += 5; - tmp = read_gitfile_gently(gitdir); + tmp = read_gitfile(gitdir); if (tmp) { free(gitdir); len = strlen(tmp); @@ -837,7 +837,7 @@ int for_each_rawref(each_ref_fn fn, void *cb_data) static inline int bad_ref_char(int ch) { - if (((unsigned) ch) <= ' ' || + if (((unsigned) ch) <= ' ' || ch == 0x7f || ch == '~' || ch == '^' || ch == ':' || ch == '\\') return 1; /* 2.13 Pattern Matching Notation */ @@ -1826,6 +1826,12 @@ int update_ref(const char *action, const char *refname, return 0; } +int ref_exists(char *refname) +{ + unsigned char sha1[20]; + return !!resolve_ref(refname, sha1, 1, NULL); +} + struct ref *find_ref_by_name(const struct ref *list, const char *name) { for ( ; list; list = list->next) @@ -54,6 +54,7 @@ extern void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refn */ extern void add_extra_ref(const char *refname, const unsigned char *sha1, int flags); extern void clear_extra_refs(void); +extern int ref_exists(char *); extern int peel_ref(const char *, unsigned char *); diff --git a/remote-curl.c b/remote-curl.c index b5be25ce96..69831e931a 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -227,6 +227,8 @@ static struct ref *parse_info_refs(struct discovery *heads) if (data[i] == '\t') mid = &data[i]; if (data[i] == '\n') { + if (mid - start != 40) + die("%sinfo/refs not valid: is this a git repository?", url); data[i] = 0; ref_name = mid + 1; ref = xmalloc(sizeof(struct ref) + @@ -471,16 +473,12 @@ static int post_rpc(struct rpc_state *rpc) * the transfer time. */ size_t size; - z_stream stream; + git_zstream stream; int ret; memset(&stream, 0, sizeof(stream)); - ret = deflateInit2(&stream, Z_BEST_COMPRESSION, - Z_DEFLATED, (15 + 16), - 8, Z_DEFAULT_STRATEGY); - if (ret != Z_OK) - die("cannot deflate request; zlib init error %d", ret); - size = deflateBound(&stream, rpc->len); + git_deflate_init_gzip(&stream, Z_BEST_COMPRESSION); + size = git_deflate_bound(&stream, rpc->len); gzip_body = xmalloc(size); stream.next_in = (unsigned char *)rpc->buf; @@ -488,11 +486,11 @@ static int post_rpc(struct rpc_state *rpc) stream.next_out = (unsigned char *)gzip_body; stream.avail_out = size; - ret = deflate(&stream, Z_FINISH); + ret = git_deflate(&stream, Z_FINISH); if (ret != Z_STREAM_END) die("cannot deflate request; zlib deflate error %d", ret); - ret = deflateEnd(&stream); + ret = git_deflate_end_gently(&stream); if (ret != Z_OK) die("cannot deflate request; zlib end error %d", ret); diff --git a/run-command.c b/run-command.c index 70e8a249d0..a2796c4cae 100644 --- a/run-command.c +++ b/run-command.c @@ -77,16 +77,14 @@ static void notify_parent(void) static NORETURN void die_child(const char *err, va_list params) { - char msg[4096]; - int len = vsnprintf(msg, sizeof(msg), err, params); - if (len > sizeof(msg)) - len = sizeof(msg); - - write_in_full(child_err, "fatal: ", 7); - write_in_full(child_err, msg, len); - write_in_full(child_err, "\n", 1); + vwritef(child_err, "fatal: ", err, params); exit(128); } + +static void error_child(const char *err, va_list params) +{ + vwritef(child_err, "error: ", err, params); +} #endif static inline void set_cloexec(int fd) @@ -127,9 +125,6 @@ static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure) if (code == 127) { code = -1; failed_errno = ENOENT; - if (!silent_exec_failure) - error("cannot run %s: %s", argv0, - strerror(ENOENT)); } } else { error("waitpid is confused (%s)", argv0); @@ -217,6 +212,7 @@ fail_pipe: set_cloexec(child_err); } set_die_routine(die_child); + set_error_routine(error_child); close(notify_pipe[0]); set_cloexec(notify_pipe[1]); @@ -283,14 +279,14 @@ fail_pipe: } else { execvp(cmd->argv[0], (char *const*) cmd->argv); } - /* - * Do not check for cmd->silent_exec_failure; the parent - * process will check it when it sees this exit code. - */ - if (errno == ENOENT) + if (errno == ENOENT) { + if (!cmd->silent_exec_failure) + error("cannot run %s: %s", cmd->argv[0], + strerror(ENOENT)); exit(127); - else + } else { die_errno("cannot exec '%s'", cmd->argv[0]); + } } if (cmd->pid < 0) error("cannot fork() for %s: %s", cmd->argv[0], @@ -375,7 +375,7 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok) * Try to read the location of the git directory from the .git file, * return path to git directory if found. */ -const char *read_gitfile_gently(const char *path) +const char *read_gitfile(const char *path) { char *buf; char *dir; @@ -437,7 +437,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv, if (PATH_MAX - 40 < strlen(gitdirenv)) die("'$%s' too big", GIT_DIR_ENVIRONMENT); - gitfile = (char*)read_gitfile_gently(gitdirenv); + gitfile = (char*)read_gitfile(gitdirenv); if (gitfile) { gitfile = xstrdup(gitfile); gitdirenv = gitfile; @@ -661,7 +661,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok) if (one_filesystem) current_device = get_device_or_die(".", NULL); for (;;) { - gitfile = (char*)read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT); + gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT); if (gitfile) gitdirenv = gitfile = xstrdup(gitfile); else { diff --git a/sha1_file.c b/sha1_file.c index 064a330408..32268d11d0 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -380,7 +380,7 @@ void add_to_alternates_file(const char *reference) { struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); int fd = hold_lock_file_for_append(lock, git_path("objects/info/alternates"), LOCK_DIE_ON_ERROR); - char *alt = mkpath("%s/objects\n", reference); + char *alt = mkpath("%s\n", reference); write_or_die(fd, alt, strlen(alt)); if (commit_lock_file(lock)) die("could not close alternates file"); @@ -834,7 +834,7 @@ static int in_window(struct pack_window *win, off_t offset) unsigned char *use_pack(struct packed_git *p, struct pack_window **w_cursor, off_t offset, - unsigned int *left) + unsigned long *left) { struct pack_window *win = *w_cursor; @@ -1205,20 +1205,29 @@ static void *map_sha1_file(const unsigned char *sha1, unsigned long *size) return map; } -static int legacy_loose_object(unsigned char *map) +/* + * There used to be a second loose object header format which + * was meant to mimic the in-pack format, allowing for direct + * copy of the object data. This format turned up not to be + * really worth it and we no longer write loose objects in that + * format. + */ +static int experimental_loose_object(unsigned char *map) { unsigned int word; /* * Is it a zlib-compressed buffer? If so, the first byte * must be 0x78 (15-bit window size, deflated), and the - * first 16-bit word is evenly divisible by 31 + * first 16-bit word is evenly divisible by 31. If so, + * we are looking at the official format, not the experimental + * one. */ word = (map[0] << 8) + map[1]; if (map[0] == 0x78 && !(word % 31)) - return 1; - else return 0; + else + return 1; } unsigned long unpack_object_header_buffer(const unsigned char *buf, @@ -1245,7 +1254,7 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf, return used; } -static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz) +static int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz) { unsigned long size, used; static const char valid_loose_object_type[8] = { @@ -1262,37 +1271,32 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon stream->next_out = buffer; stream->avail_out = bufsiz; - if (legacy_loose_object(map)) { - git_inflate_init(stream); - return git_inflate(stream, 0); - } - + if (experimental_loose_object(map)) { + /* + * The old experimental format we no longer produce; + * we can still read it. + */ + used = unpack_object_header_buffer(map, mapsize, &type, &size); + if (!used || !valid_loose_object_type[type]) + return -1; + map += used; + mapsize -= used; - /* - * There used to be a second loose object header format which - * was meant to mimic the in-pack format, allowing for direct - * copy of the object data. This format turned up not to be - * really worth it and we don't write it any longer. But we - * can still read it. - */ - used = unpack_object_header_buffer(map, mapsize, &type, &size); - if (!used || !valid_loose_object_type[type]) - return -1; - map += used; - mapsize -= used; + /* Set up the stream for the rest.. */ + stream->next_in = map; + stream->avail_in = mapsize; + git_inflate_init(stream); - /* Set up the stream for the rest.. */ - stream->next_in = map; - stream->avail_in = mapsize; + /* And generate the fake traditional header */ + stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", + typename(type), size); + return 0; + } git_inflate_init(stream); - - /* And generate the fake traditional header */ - stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", - typename(type), size); - return 0; + return git_inflate(stream, 0); } -static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size, const unsigned char *sha1) +static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long size, const unsigned char *sha1) { int bytes = strlen(buffer) + 1; unsigned char *buf = xmallocz(size); @@ -1391,7 +1395,7 @@ static int parse_sha1_header(const char *hdr, unsigned long *sizep) static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1) { int ret; - z_stream stream; + git_zstream stream; char hdr[8192]; ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)); @@ -1407,7 +1411,7 @@ unsigned long get_size_from_delta(struct packed_git *p, { const unsigned char *data; unsigned char delta_head[20], *in; - z_stream stream; + git_zstream stream; int st; memset(&stream, 0, sizeof(stream)); @@ -1529,7 +1533,7 @@ static int unpack_object_header(struct packed_git *p, unsigned long *sizep) { unsigned char *base; - unsigned int left; + unsigned long left; unsigned long used; enum object_type type; @@ -1642,7 +1646,7 @@ static void *unpack_compressed_entry(struct packed_git *p, unsigned long size) { int st; - z_stream stream; + git_zstream stream; unsigned char *buffer, *in; buffer = xmallocz(size); @@ -2075,7 +2079,7 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size int status; unsigned long mapsize, size; void *map; - z_stream stream; + git_zstream stream; char hdr[32]; map = map_sha1_file(sha1, &mapsize); @@ -2424,7 +2428,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen, { int fd, ret; unsigned char compressed[4096]; - z_stream stream; + git_zstream stream; git_SHA_CTX c; unsigned char parano_sha1[20]; char *filename; @@ -2441,7 +2445,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen, /* Set it up */ memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, zlib_compression_level); + git_deflate_init(&stream, zlib_compression_level); stream.next_out = compressed; stream.avail_out = sizeof(compressed); git_SHA1_Init(&c); @@ -2449,8 +2453,8 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen, /* First header.. */ stream.next_in = (unsigned char *)hdr; stream.avail_in = hdrlen; - while (deflate(&stream, 0) == Z_OK) - /* nothing */; + while (git_deflate(&stream, 0) == Z_OK) + ; /* nothing */ git_SHA1_Update(&c, hdr, hdrlen); /* Then the data itself.. */ @@ -2458,7 +2462,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen, stream.avail_in = len; do { unsigned char *in0 = stream.next_in; - ret = deflate(&stream, Z_FINISH); + ret = git_deflate(&stream, Z_FINISH); git_SHA1_Update(&c, in0, stream.next_in - in0); if (write_buffer(fd, compressed, stream.next_out - compressed) < 0) die("unable to write sha1 file"); @@ -2468,7 +2472,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen, if (ret != Z_STREAM_END) die("unable to deflate new object %s (%d)", sha1_to_hex(sha1), ret); - ret = deflateEnd(&stream); + ret = git_deflate_end_gently(&stream); if (ret != Z_OK) die("deflateEnd on object %s failed (%d)", sha1_to_hex(sha1), ret); git_SHA1_Final(parano_sha1, &c); @@ -103,24 +103,27 @@ void strbuf_ltrim(struct strbuf *sb) sb->buf[sb->len] = '\0'; } -struct strbuf **strbuf_split(const struct strbuf *sb, int delim) +struct strbuf **strbuf_split_buf(const char *str, size_t slen, int delim, int max) { int alloc = 2, pos = 0; - char *n, *p; + const char *n, *p; struct strbuf **ret; struct strbuf *t; ret = xcalloc(alloc, sizeof(struct strbuf *)); - p = n = sb->buf; - while (n < sb->buf + sb->len) { + p = n = str; + while (n < str + slen) { int len; - n = memchr(n, delim, sb->len - (n - sb->buf)); + if (max <= 0 || pos + 1 < max) + n = memchr(n, delim, slen - (n - str)); + else + n = NULL; if (pos + 1 >= alloc) { alloc = alloc * 2; ret = xrealloc(ret, sizeof(struct strbuf *) * alloc); } if (!n) - n = sb->buf + sb->len - 1; + n = str + slen - 1; len = n - p + 1; t = xmalloc(sizeof(struct strbuf)); strbuf_init(t, len); @@ -44,7 +44,22 @@ extern void strbuf_rtrim(struct strbuf *); extern void strbuf_ltrim(struct strbuf *); extern int strbuf_cmp(const struct strbuf *, const struct strbuf *); -extern struct strbuf **strbuf_split(const struct strbuf *, int delim); +extern struct strbuf **strbuf_split_buf(const char *, size_t, + int delim, int max); +static inline struct strbuf **strbuf_split_str(const char *str, + int delim, int max) +{ + return strbuf_split_buf(str, strlen(str), delim, max); +} +static inline struct strbuf **strbuf_split_max(const struct strbuf *sb, + int delim, int max) +{ + return strbuf_split_buf(sb->buf, sb->len, delim, max); +} +static inline struct strbuf **strbuf_split(const struct strbuf *sb, int delim) +{ + return strbuf_split_max(sb, delim, 0); +} extern void strbuf_list_free(struct strbuf **); /*----- add data in your buffer -----*/ diff --git a/submodule.c b/submodule.c index b6dec70bd1..11de09ae97 100644 --- a/submodule.c +++ b/submodule.c @@ -32,7 +32,7 @@ static int add_submodule_odb(const char *path) const char *git_dir; strbuf_addf(&objects_directory, "%s/.git", path); - git_dir = read_gitfile_gently(objects_directory.buf); + git_dir = read_gitfile(objects_directory.buf); if (git_dir) { strbuf_reset(&objects_directory); strbuf_addstr(&objects_directory, git_dir); @@ -373,6 +373,10 @@ void check_for_new_submodule_commits(unsigned char new_sha1[20]) const char *argv[] = {NULL, NULL, "--not", "--all", NULL}; int argc = ARRAY_SIZE(argv) - 1; + /* No need to check if there are no submodules configured */ + if (!config_name_for_path.nr) + return; + init_revisions(&rev, NULL); argv[1] = xstrdup(sha1_to_hex(new_sha1)); setup_revisions(argc, argv, &rev, NULL); @@ -388,6 +392,7 @@ void check_for_new_submodule_commits(unsigned char new_sha1[20]) while (parent) { struct diff_options diff_opts; diff_setup(&diff_opts); + DIFF_OPT_SET(&diff_opts, RECURSIVE); diff_opts.output_format |= DIFF_FORMAT_CALLBACK; diff_opts.format_callback = submodule_collect_changed_cb; if (diff_setup_done(&diff_opts) < 0) @@ -478,7 +483,7 @@ int fetch_populated_submodules(int num_options, const char **options, strbuf_addf(&submodule_path, "%s/%s", work_tree, ce->name); strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf); strbuf_addf(&submodule_prefix, "%s%s/", prefix, ce->name); - git_dir = read_gitfile_gently(submodule_git_dir.buf); + git_dir = read_gitfile(submodule_git_dir.buf); if (!git_dir) git_dir = submodule_git_dir.buf; if (is_directory(git_dir)) { @@ -516,7 +521,7 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked) const char *git_dir; strbuf_addf(&buf, "%s/.git", path); - git_dir = read_gitfile_gently(buf.buf); + git_dir = read_gitfile(buf.buf); if (!git_dir) git_dir = buf.buf; if (!is_directory(git_dir)) { diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh index d206b7c4cf..7913e206ed 100755 --- a/t/aggregate-results.sh +++ b/t/aggregate-results.sh @@ -1,5 +1,6 @@ #!/bin/sh +failed_tests= fixed=0 success=0 failed=0 @@ -18,7 +19,13 @@ do success) success=$(($success + $value)) ;; failed) - failed=$(($failed + $value)) ;; + failed=$(($failed + $value)) + if test $value != 0 + then + testnum=$(expr "$file" : 'test-results/\(t[0-9]*\)-') + failed_tests="$failed_tests $testnum" + fi + ;; broken) broken=$(($broken + $value)) ;; total) @@ -27,6 +34,11 @@ do done <"$file" done +if test -n "$failed_tests" +then + printf "\nfailed test(s):$failed_tests\n\n" +fi + printf "%-8s%d\n" fixed $fixed printf "%-8s%d\n" success $success printf "%-8s%d\n" failed $failed diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh index 143eb1f240..292753f77c 100644 --- a/t/gitweb-lib.sh +++ b/t/gitweb-lib.sh @@ -107,4 +107,9 @@ perl -MEncode -e '$e="";decode_utf8($e, Encode::FB_CROAK)' >/dev/null 2>&1 || { test_done } +perl -MCGI -MCGI::Util -MCGI::Carp -e 0 >/dev/null 2>&1 || { + skip_all='skipping gitweb tests, CGI module unusable' + test_done +} + gitweb_init diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 3db56267ee..3e140c18f4 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -904,4 +904,22 @@ test_expect_success 'git -c works with aliases of builtins' ' test_cmp expect actual ' +test_expect_success 'git -c does not split values on equals' ' + echo "value with = in it" >expect && + git -c core.foo="value with = in it" config core.foo >actual && + test_cmp expect actual +' + +test_expect_success 'git -c dies on bogus config' ' + test_must_fail git -c core.bare=foo rev-parse +' + +test_expect_success 'git -c complains about empty key' ' + test_must_fail git -c "=foo" rev-parse +' + +test_expect_success 'git -c complains about empty key and value' ' + test_must_fail git -c "" rev-parse +' + test_done diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index 1b0f82fa4c..ed4275afe3 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -18,6 +18,9 @@ invalid_ref 'foo' valid_ref 'foo/bar/baz' valid_ref 'refs///heads/foo' invalid_ref 'heads/foo/' +valid_ref '/heads/foo' +valid_ref '///heads/foo' +invalid_ref '/foo' invalid_ref './foo' invalid_ref '.refs/foo' invalid_ref 'heads/foo..bar' @@ -27,6 +30,9 @@ invalid_ref 'heads/foo.lock' valid_ref 'heads/foo@bar' invalid_ref 'heads/v@{ation' invalid_ref 'heads/foo\bar' +invalid_ref "$(printf 'heads/foo\t')" +invalid_ref "$(printf 'heads/foo\177')" +valid_ref "$(printf 'heads/fu\303\237')" test_expect_success "check-ref-format --branch @{-1}" ' T=$(git write-tree) && @@ -70,7 +76,10 @@ invalid_ref_normalized() { valid_ref_normalized 'heads/foo' 'heads/foo' valid_ref_normalized 'refs///heads/foo' 'refs/heads/foo' +valid_ref_normalized '/heads/foo' 'heads/foo' +valid_ref_normalized '///heads/foo' 'heads/foo' invalid_ref_normalized 'foo' +invalid_ref_normalized '/foo' invalid_ref_normalized 'heads/foo/../bar' invalid_ref_normalized 'heads/./foo' invalid_ref_normalized 'heads\foo' diff --git a/t/t1412-reflog-loop.sh b/t/t1412-reflog-loop.sh index 7f519e5ebe..647d888507 100755 --- a/t/t1412-reflog-loop.sh +++ b/t/t1412-reflog-loop.sh @@ -21,10 +21,10 @@ test_expect_success 'setup reflog with alternating commits' ' test_expect_success 'reflog shows all entries' ' cat >expect <<-\EOF - topic@{0} two: updating HEAD - topic@{1} one: updating HEAD - topic@{2} two: updating HEAD - topic@{3} one: updating HEAD + topic@{0} reset: moving to two + topic@{1} reset: moving to one + topic@{2} reset: moving to two + topic@{3} reset: moving to one topic@{4} branch: Created from HEAD EOF git log -g --format="%gd %gs" topic >actual && diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index fa69016381..a42e03967b 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -169,4 +169,15 @@ test_expect_success 'checkout -f -B to an existing branch with mergeable changes test_must_fail test_dirty_mergeable ' +test_expect_success 'checkout -b <describe>' ' + git tag -f -m "First commit" initial initial && + git checkout -f change1 && + name=$(git describe) && + git checkout -b $name && + git diff --exit-code change1 && + echo "refs/heads/$name" >expect && + git symbolic-ref HEAD >actual && + test_cmp expect actual +' + test_done diff --git a/t/t3005-ls-files-relative.sh b/t/t3005-ls-files-relative.sh new file mode 100755 index 0000000000..377869432e --- /dev/null +++ b/t/t3005-ls-files-relative.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +test_description='ls-files tests with relative paths + +This test runs git ls-files with various relative path arguments. +' + +. ./test-lib.sh + +new_line=' +' +sq=\' + +test_expect_success 'prepare' ' + : >never-mind-me && + git add never-mind-me && + mkdir top && + ( + cd top && + mkdir sub && + x="x xa xbc xdef xghij xklmno" && + y=$(echo "$x" | tr x y) && + touch $x && + touch $y && + cd sub && + git add ../x* + ) +' + +test_expect_success 'ls-files with mixed levels' ' + ( + cd top/sub && + cat >expect <<-EOF && + ../../never-mind-me + ../x + EOF + git ls-files $(cat expect) >actual && + test_cmp expect actual + ) +' + +test_expect_success 'ls-files -c' ' + ( + cd top/sub && + for f in ../y* + do + echo "error: pathspec $sq$f$sq did not match any file(s) known to git." + done >expect.err && + echo "Did you forget to ${sq}git add${sq}?" >>expect.err && + ls ../x* >expect.out && + test_must_fail git ls-files -c --error-unmatch ../[xy]* >actual.out 2>actual.err && + test_cmp expect.out actual.out && + test_cmp expect.err actual.err + ) +' + +test_expect_success 'ls-files -o' ' + ( + cd top/sub && + for f in ../x* + do + echo "error: pathspec $sq$f$sq did not match any file(s) known to git." + done >expect.err && + echo "Did you forget to ${sq}git add${sq}?" >>expect.err && + ls ../y* >expect.out && + test_must_fail git ls-files -o --error-unmatch ../[xy]* >actual.out 2>actual.err && + test_cmp expect.out actual.out && + test_cmp expect.err actual.err + ) +' + +test_done diff --git a/t/t3103-ls-tree-misc.sh b/t/t3103-ls-tree-misc.sh new file mode 100755 index 0000000000..09dcf043fd --- /dev/null +++ b/t/t3103-ls-tree-misc.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +test_description=' +Miscellaneous tests for git ls-tree. + + 1. git ls-tree fails in presence of tree damage. + +' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir a && + touch a/one && + git add a/one && + git commit -m test +' + +test_expect_success 'ls-tree fails with non-zero exit code on broken tree' ' + rm -f .git/objects/5f/cffbd6e4c5c5b8d81f5e9314b20e338e3ffff5 && + test_must_fail git ls-tree -r HEAD +' + +test_done diff --git a/t/t3307-notes-man.sh b/t/t3307-notes-man.sh index 2ea3be6546..1aa366a410 100755 --- a/t/t3307-notes-man.sh +++ b/t/t3307-notes-man.sh @@ -26,13 +26,13 @@ test_expect_success 'example 1: notes to add an Acked-by line' ' ' test_expect_success 'example 2: binary notes' ' - cp "$TEST_DIRECTORY"/test4012.png . && + cp "$TEST_DIRECTORY"/test-binary-1.png . && git checkout B && - blob=$(git hash-object -w test4012.png) && + blob=$(git hash-object -w test-binary-1.png) && git notes --ref=logo add -C "$blob" && git notes --ref=logo copy B C && git notes --ref=logo show C >actual && - test_cmp test4012.png actual + test_cmp test-binary-1.png actual ' test_done diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 47c8371c7e..8538813d1d 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -295,7 +295,7 @@ test_expect_success 'preserve merges with -p' ' ' test_expect_success 'edit ancestor with -p' ' - FAKE_LINES="1 edit 2 3 4" git rebase -i -p HEAD~3 && + FAKE_LINES="1 2 edit 3 4" git rebase -i -p HEAD~3 && echo 2 > unrelated-file && test_tick && git commit -m L2-modified --amend unrelated-file && diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh index 08201e2331..6de4e2263f 100755 --- a/t/t3409-rebase-preserve-merges.sh +++ b/t/t3409-rebase-preserve-merges.sh @@ -37,7 +37,15 @@ export GIT_AUTHOR_EMAIL # \ # B2 <-- origin/topic # -# In all cases, 'topic' is rebased onto 'origin/topic'. +# Clone 4 (merge using second parent as base): +# +# A1--A2--B3 <-- origin/master +# \ +# B1--A3--M <-- topic +# \ / +# \--A4 <-- topic2 +# \ +# B2 <-- origin/topic test_expect_success 'setup for merge-preserving rebase' \ 'echo First > A && @@ -57,6 +65,13 @@ test_expect_success 'setup for merge-preserving rebase' \ git merge origin/master ) && + git clone ./. clone4 && + ( + cd clone4 && + git checkout -b topic origin/topic && + git merge origin/master + ) && + echo Fifth > B && git add B && git commit -m "Add different B" && @@ -123,4 +138,15 @@ test_expect_success 'rebase -p preserves no-ff merges' ' ) ' +test_expect_success 'rebase -p works when base inside second parent' ' + ( + cd clone4 && + git fetch && + git rebase -p HEAD^2 && + test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) && + test 1 = $(git rev-list --all --pretty=oneline | grep "Modify B" | wc -l) && + test 1 = $(git rev-list --all --pretty=oneline | grep "Merge remote-tracking branch " | wc -l) + ) +' + test_done diff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh index 14a23cd872..ace8e54e9b 100755 --- a/t/t3411-rebase-preserve-around-merges.sh +++ b/t/t3411-rebase-preserve-around-merges.sh @@ -37,7 +37,7 @@ test_expect_success 'setup' ' # -- C1 -- # test_expect_success 'squash F1 into D1' ' - FAKE_LINES="1 squash 3 2" git rebase -i -p B1 && + FAKE_LINES="1 squash 4 2 3" git rebase -i -p B1 && test "$(git rev-parse HEAD^2)" = "$(git rev-parse C1)" && test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" && git tag E2 diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh index 05ec062832..2d9f9a0cf1 100755 --- a/t/t4012-diff-binary.sh +++ b/t/t4012-diff-binary.sh @@ -12,7 +12,7 @@ test_expect_success 'prepare repository' \ 'echo AIT >a && echo BIT >b && echo CIT >c && echo DIT >d && git update-index --add a b c d && echo git >a && - cat "$TEST_DIRECTORY"/test4012.png >b && + cat "$TEST_DIRECTORY"/test-binary-1.png >b && echo git >c && cat b b >d' diff --git a/t/t4048-diff-combined-binary.sh b/t/t4048-diff-combined-binary.sh new file mode 100755 index 0000000000..87a8949500 --- /dev/null +++ b/t/t4048-diff-combined-binary.sh @@ -0,0 +1,212 @@ +#!/bin/sh + +test_description='combined and merge diff handle binary files and textconv' +. ./test-lib.sh + +test_expect_success 'setup binary merge conflict' ' + echo oneQ1 | q_to_nul >binary && + git add binary && + git commit -m one && + echo twoQ2 | q_to_nul >binary && + git commit -a -m two && + git checkout -b branch-binary HEAD^ && + echo threeQ3 | q_to_nul >binary && + git commit -a -m three && + test_must_fail git merge master && + echo resolvedQhooray | q_to_nul >binary && + git commit -a -m resolved +' + +cat >expect <<'EOF' +resolved + +diff --git a/binary b/binary +index 7ea6ded..9563691 100644 +Binary files a/binary and b/binary differ +resolved + +diff --git a/binary b/binary +index 6197570..9563691 100644 +Binary files a/binary and b/binary differ +EOF +test_expect_success 'diff -m indicates binary-ness' ' + git show --format=%s -m >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --combined binary +index 7ea6ded,6197570..9563691 +Binary files differ +EOF +test_expect_success 'diff -c indicates binary-ness' ' + git show --format=%s -c >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --cc binary +index 7ea6ded,6197570..9563691 +Binary files differ +EOF +test_expect_success 'diff --cc indicates binary-ness' ' + git show --format=%s --cc >actual && + test_cmp expect actual +' + +test_expect_success 'setup non-binary with binary attribute' ' + git checkout master && + test_commit one text && + test_commit two text && + git checkout -b branch-text HEAD^ && + test_commit three text && + test_must_fail git merge master && + test_commit resolved text && + echo text -diff >.gitattributes +' + +cat >expect <<'EOF' +resolved + +diff --git a/text b/text +index 2bdf67a..2ab19ae 100644 +Binary files a/text and b/text differ +resolved + +diff --git a/text b/text +index f719efd..2ab19ae 100644 +Binary files a/text and b/text differ +EOF +test_expect_success 'diff -m respects binary attribute' ' + git show --format=%s -m >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --combined text +index 2bdf67a,f719efd..2ab19ae +Binary files differ +EOF +test_expect_success 'diff -c respects binary attribute' ' + git show --format=%s -c >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --cc text +index 2bdf67a,f719efd..2ab19ae +Binary files differ +EOF +test_expect_success 'diff --cc respects binary attribute' ' + git show --format=%s --cc >actual && + test_cmp expect actual +' + +test_expect_success 'setup textconv attribute' ' + echo "text diff=upcase" >.gitattributes && + git config diff.upcase.textconv "tr a-z A-Z <" +' + +cat >expect <<'EOF' +resolved + +diff --git a/text b/text +index 2bdf67a..2ab19ae 100644 +--- a/text ++++ b/text +@@ -1 +1 @@ +-THREE ++RESOLVED +resolved + +diff --git a/text b/text +index f719efd..2ab19ae 100644 +--- a/text ++++ b/text +@@ -1 +1 @@ +-TWO ++RESOLVED +EOF +test_expect_success 'diff -m respects textconv attribute' ' + git show --format=%s -m >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --combined text +index 2bdf67a,f719efd..2ab19ae +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,1 @@@ +- THREE + -TWO +++RESOLVED +EOF +test_expect_success 'diff -c respects textconv attribute' ' + git show --format=%s -c >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --cc text +index 2bdf67a,f719efd..2ab19ae +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,1 @@@ +- THREE + -TWO +++RESOLVED +EOF +test_expect_success 'diff --cc respects textconv attribute' ' + git show --format=%s --cc >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +diff --combined text +index 2bdf67a,f719efd..2ab19ae +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,1 @@@ +- three + -two +++resolved +EOF +test_expect_success 'diff-tree plumbing does not respect textconv' ' + git diff-tree HEAD -c -p >full && + tail -n +2 full >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +diff --cc text +index 2bdf67a,f719efd..0000000 +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,5 @@@ +++<<<<<<< HEAD + +THREE +++======= ++ TWO +++>>>>>>> MASTER +EOF +test_expect_success 'diff --cc respects textconv on worktree file' ' + git reset --hard HEAD^ && + test_must_fail git merge master && + git diff >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh index a1fddd4d15..ca5b027c55 100755 --- a/t/t5526-fetch-submodules.sh +++ b/t/t5526-fetch-submodules.sh @@ -47,7 +47,7 @@ test_expect_success setup ' git init && echo subcontent > subfile && git add subfile && - git submodule add "$pwd/deepsubmodule" deepsubmodule && + git submodule add "$pwd/deepsubmodule" subdir/deepsubmodule && git commit -a -m new ) && git submodule add "$pwd/submodule" submodule && @@ -58,7 +58,7 @@ test_expect_success setup ' git submodule update --init --recursive ) && echo "Fetching submodule submodule" > expect.out && - echo "Fetching submodule submodule/deepsubmodule" >> expect.out + echo "Fetching submodule submodule/subdir/deepsubmodule" >> expect.out ' test_expect_success "fetch --recurse-submodules recurses into submodules" ' @@ -277,12 +277,12 @@ test_expect_success "Recursion picks up all submodules when necessary" ' ( cd submodule && ( - cd deepsubmodule && + cd subdir/deepsubmodule && git fetch && git checkout -q FETCH_HEAD ) && head1=$(git rev-parse --short HEAD^) && - git add deepsubmodule && + git add subdir/deepsubmodule && git commit -m "new deepsubmodule" head2=$(git rev-parse --short HEAD) && echo "From $pwd/submodule" > ../expect.err.sub && @@ -309,12 +309,12 @@ test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no ne ( cd submodule && ( - cd deepsubmodule && + cd subdir/deepsubmodule && git fetch && git checkout -q FETCH_HEAD ) && head1=$(git rev-parse --short HEAD^) && - git add deepsubmodule && + git add subdir/deepsubmodule && git commit -m "new deepsubmodule" head2=$(git rev-parse --short HEAD) && echo "From $pwd/submodule" > ../expect.err.sub && @@ -345,13 +345,13 @@ test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necess git config fetch.recurseSubmodules false && ( cd submodule && - git config -f .gitmodules submodule.deepsubmodule.fetchRecursive false + git config -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive false ) && git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err && git config --unset fetch.recurseSubmodules ( cd submodule && - git config --unset -f .gitmodules submodule.deepsubmodule.fetchRecursive + git config --unset -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive ) ) && test_i18ncmp expect.out actual.out && diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index 151ea531bd..e8103144bb 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -202,9 +202,36 @@ test_expect_success 'clone separate gitdir: output' ' test_cmp expected dst/.git ' +test_expect_success 'clone from .git file' ' + git clone dst/.git dst2 +' + test_expect_success 'clone separate gitdir where target already exists' ' rm -rf dst && test_must_fail git clone --separate-git-dir realgitdir src dst ' +test_expect_success 'clone --reference from original' ' + git clone --shared --bare src src-1 && + git clone --bare src src-2 && + git clone --reference=src-2 --bare src-1 target-8 && + grep /src-2/ target-8/objects/info/alternates +' + +test_expect_success 'clone with more than one --reference' ' + git clone --bare src src-3 && + git clone --bare src src-4 && + git clone --reference=src-3 --reference=src-4 src target-9 && + grep /src-3/ target-9/.git/objects/info/alternates && + grep /src-4/ target-9/.git/objects/info/alternates +' + +test_expect_success 'clone from original with relative alternate' ' + mkdir nest && + git clone --bare src nest/src-5 && + echo ../../../src/.git/objects >nest/src-5/objects/info/alternates && + git clone --bare nest/src-5 target-10 && + grep /src/\\.git/objects target-10/objects/info/alternates +' + test_done diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh index d9f343942c..432f086c06 100755 --- a/t/t6023-merge-file.sh +++ b/t/t6023-merge-file.sh @@ -154,7 +154,7 @@ test_expect_success "expected conflict markers" "test_cmp expect out" test_expect_success 'binary files cannot be merged' ' test_must_fail git merge-file -p \ - orig.txt "$TEST_DIRECTORY"/test4012.png new1.txt 2> merge.err && + orig.txt "$TEST_DIRECTORY"/test-binary-1.png new1.txt 2> merge.err && grep "Cannot merge binary files" merge.err ' diff --git a/t/t6027-merge-binary.sh b/t/t6027-merge-binary.sh index b519626ca0..07735410b9 100755 --- a/t/t6027-merge-binary.sh +++ b/t/t6027-merge-binary.sh @@ -6,7 +6,7 @@ test_description='ask merge-recursive to merge binary files' test_expect_success setup ' - cat "$TEST_DIRECTORY"/test4012.png >m && + cat "$TEST_DIRECTORY"/test-binary-1.png >m && git add m && git ls-files -s | sed -e "s/ 0 / 1 /" >E1 && test_tick && diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh index a9b0ac1efc..19de5b16eb 100755 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@ -110,4 +110,18 @@ test_expect_success '--set-upstream does not change branch' ' grep -q "^refs/heads/master$" actual && cmp expect2 actual2 ' + +test_expect_success '--set-upstream @{-1}' ' + git checkout from-master && + git checkout from-master2 && + git config branch.from-master2.merge > expect2 && + git branch --set-upstream @{-1} follower && + git config branch.from-master.merge > actual && + git config branch.from-master2.merge > actual2 && + git branch --set-upstream from-master follower && + git config branch.from-master.merge > expect && + test_cmp expect2 actual2 && + test_cmp expect actual +' + test_done diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 2ac1c66079..097ce2bc83 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -257,6 +257,11 @@ test_expect_success \ test_cmp expect actual ' +test_expect_success 'tag -l can accept multiple patterns' ' + git tag -l "v1*" "v0*" >actual && + test_cmp expect actual +' + # creating and verifying lightweight tags: test_expect_success \ diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index f1cfc9ac95..b096dc88c2 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -429,6 +429,21 @@ test_expect_success '--mixed refreshes the index' ' test_i18ncmp expect output ' +test_expect_success 'resetting specific path that is unmerged' ' + git rm --cached file2 && + F1=$(git rev-parse HEAD:file1) && + F2=$(git rev-parse HEAD:file2) && + F3=$(git rev-parse HEAD:secondfile) && + { + echo "100644 $F1 1 file2" && + echo "100644 $F2 2 file2" && + echo "100644 $F3 3 file2" + } | git update-index --index-info && + git ls-files -u && + test_must_fail git reset HEAD file2 && + git diff-index --exit-code --cached HEAD +' + test_expect_success 'disambiguation (1)' ' git reset --hard && diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 874279e32d..c22916ddd9 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -47,8 +47,10 @@ test_expect_success 'setup - repository to add submodules to' ' ' # The 'submodule add' tests need some repository to add as a submodule. -# The trash directory is a good one as any. -submodurl=$TRASH_DIRECTORY +# The trash directory is a good one as any. We need to canonicalize +# the name, though, as some tests compare it to the absolute path git +# generates, which will expand symbolic links. +submodurl=$(pwd -P) listbranches() { git for-each-ref --format='%(refname)' 'refs/heads/*' @@ -75,7 +77,8 @@ test_expect_success 'submodule add' ' ( cd addtest && - git submodule add "$submodurl" submod && + git submodule add -q "$submodurl" submod >actual && + test ! -s actual && git submodule init ) && @@ -273,7 +276,8 @@ test_expect_success 'update should work when path is an empty dir' ' echo "$rev1" >expect && mkdir init && - git submodule update && + git submodule update -q >update.out && + test ! -s update.out && inspect init && test_cmp expect head-sha1 @@ -446,6 +450,16 @@ test_expect_success 'add should fail when path is used by an existing directory' ) ' +test_expect_success 'use superproject as upstream when path is relative and no url is set there' ' + ( + cd addtest && + git submodule add ../repo relative && + test "$(git config -f .gitmodules submodule.relative.url)" = ../repo && + git submodule sync relative && + test "$(git config submodule.relative.url)" = "$submodurl/repo" + ) +' + test_expect_success 'set up for relative path tests' ' mkdir reltest && ( diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index d600583cef..95ffe349a7 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -25,7 +25,8 @@ test_expect_success setup ' git clone super super-clone && (cd super-clone && git submodule update --init) && git clone super empty-clone && - (cd empty-clone && git submodule init) + (cd empty-clone && git submodule init) && + git clone super top-only-clone ' test_expect_success 'change submodule' ' @@ -66,7 +67,7 @@ test_expect_success '"git submodule sync" should update submodule URLs' ' ) ' -test_expect_success '"git submodule sync" should update submodule URLs if not yet cloned' ' +test_expect_success '"git submodule sync" should update known submodule URLs' ' (cd empty-clone && git pull && git submodule sync && @@ -74,4 +75,14 @@ test_expect_success '"git submodule sync" should update submodule URLs if not ye ) ' +test_expect_success '"git submodule sync" should not vivify uninteresting submodule' ' + (cd top-only-clone && + git pull && + git submodule sync && + test -z "$(git config submodule.submodule.url)" && + git submodule sync submodule && + test -z "$(git config submodule.submodule.url)" + ) +' + test_done diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index e5be13c271..835a506241 100755 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@ -292,4 +292,22 @@ test_expect_success 'use "update --recursive nested1" to checkout all submodules ) ' +test_expect_success 'command passed to foreach retains notion of stdin' ' + ( + cd super && + git submodule foreach echo success >../expected && + yes | git submodule foreach "read y && test \"x\$y\" = xy && echo success" >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'command passed to foreach --recursive retains notion of stdin' ' + ( + cd clone2 && + git submodule foreach --recursive echo success >../expected && + yes | git submodule foreach --recursive "read y && test \"x\$y\" = xy && echo success" >../actual + ) && + test_cmp expected actual +' + test_done diff --git a/t/t7508-status.sh b/t/t7508-status.sh index 1fdfbd3865..905255adf0 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -131,6 +131,127 @@ test_expect_success 'status -s' ' ' +test_expect_success 'status with gitignore' ' + { + echo ".gitignore" && + echo "expect" && + echo "output" && + echo "untracked" + } >.gitignore && + + cat >expect <<-\EOF && + M dir1/modified + A dir2/added + ?? dir2/modified + EOF + git status -s >output && + test_cmp expect output && + + cat >expect <<-\EOF && + M dir1/modified + A dir2/added + ?? dir2/modified + !! .gitignore + !! dir1/untracked + !! dir2/untracked + !! expect + !! output + !! untracked + EOF + git status -s --ignored >output && + test_cmp expect output && + + cat >expect <<-\EOF && + # On branch master + # Changes to be committed: + # (use "git reset HEAD <file>..." to unstage) + # + # new file: dir2/added + # + # Changes not staged for commit: + # (use "git add <file>..." to update what will be committed) + # (use "git checkout -- <file>..." to discard changes in working directory) + # + # modified: dir1/modified + # + # Untracked files: + # (use "git add <file>..." to include in what will be committed) + # + # dir2/modified + # Ignored files: + # (use "git add -f <file>..." to include in what will be committed) + # + # .gitignore + # dir1/untracked + # dir2/untracked + # expect + # output + # untracked + EOF + git status --ignored >output && + test_cmp expect output +' + +test_expect_success 'status with gitignore (nothing untracked)' ' + { + echo ".gitignore" && + echo "expect" && + echo "dir2/modified" && + echo "output" && + echo "untracked" + } >.gitignore && + + cat >expect <<-\EOF && + M dir1/modified + A dir2/added + EOF + git status -s >output && + test_cmp expect output && + + cat >expect <<-\EOF && + M dir1/modified + A dir2/added + !! .gitignore + !! dir1/untracked + !! dir2/modified + !! dir2/untracked + !! expect + !! output + !! untracked + EOF + git status -s --ignored >output && + test_cmp expect output && + + cat >expect <<-\EOF && + # On branch master + # Changes to be committed: + # (use "git reset HEAD <file>..." to unstage) + # + # new file: dir2/added + # + # Changes not staged for commit: + # (use "git add <file>..." to update what will be committed) + # (use "git checkout -- <file>..." to discard changes in working directory) + # + # modified: dir1/modified + # + # Ignored files: + # (use "git add -f <file>..." to include in what will be committed) + # + # .gitignore + # dir1/untracked + # dir2/modified + # dir2/untracked + # expect + # output + # untracked + EOF + git status --ignored >output && + test_cmp expect output +' + +rm -f .gitignore + cat >expect <<\EOF ## master M dir1/modified diff --git a/t/t9159-git-svn-no-parent-mergeinfo.sh b/t/t9159-git-svn-no-parent-mergeinfo.sh new file mode 100755 index 0000000000..85120b70db --- /dev/null +++ b/t/t9159-git-svn-no-parent-mergeinfo.sh @@ -0,0 +1,33 @@ +#!/bin/sh +test_description='git svn handling of root commits in merge ranges' +. ./lib-git-svn.sh + +test_expect_success 'test handling of root commits in merge ranges' ' + mkdir -p init/trunk init/branches init/tags && + echo "r1" > init/trunk/file.txt && + svn_cmd import -m "initial import" init "$svnrepo" && + svn_cmd co "$svnrepo" tmp && + ( + cd tmp && + echo "r2" > trunk/file.txt && + svn_cmd commit -m "Modify file.txt on trunk" && + svn_cmd cp trunk@1 branches/a && + svn_cmd commit -m "Create branch a from trunk r1" && + svn_cmd propset svn:mergeinfo /trunk:1-2 branches/a && + svn_cmd commit -m "Fake merge of trunk r2 into branch a" && + mkdir branches/b && + echo "r5" > branches/b/file2.txt && + svn_cmd add branches/b && + svn_cmd commit -m "Create branch b from thin air" && + echo "r6" > branches/b/file2.txt && + svn_cmd commit -m "Modify file2.txt on branch b" && + svn_cmd cp branches/b@5 branches/c && + svn_cmd commit -m "Create branch c from branch b r5" && + svn_cmd propset svn:mergeinfo /branches/b:5-6 branches/c && + svn_cmd commit -m "Fake merge of branch b r6 into branch c" + ) && + git svn init -s "$svnrepo" && + git svn fetch + ' + +test_done diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh index e5da65b99f..41db05cb4a 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -50,8 +50,8 @@ test_expect_success \ 'mkdir A B C D E F && echo hello1 >A/newfile1.txt && echo hello2 >B/newfile2.txt && - cp "$TEST_DIRECTORY"/test9200a.png C/newfile3.png && - cp "$TEST_DIRECTORY"/test9200a.png D/newfile4.png && + cp "$TEST_DIRECTORY"/test-binary-1.png C/newfile3.png && + cp "$TEST_DIRECTORY"/test-binary-1.png D/newfile4.png && git add A/newfile1.txt && git add B/newfile2.txt && git add C/newfile3.png && @@ -76,8 +76,8 @@ test_expect_success \ rm -f B/newfile2.txt && rm -f C/newfile3.png && echo Hello5 >E/newfile5.txt && - cp "$TEST_DIRECTORY"/test9200b.png D/newfile4.png && - cp "$TEST_DIRECTORY"/test9200a.png F/newfile6.png && + cp "$TEST_DIRECTORY"/test-binary-2.png D/newfile4.png && + cp "$TEST_DIRECTORY"/test-binary-1.png F/newfile6.png && git add E/newfile5.txt && git add F/newfile6.png && git commit -a -m "Test: Remove, add and update" && @@ -165,7 +165,7 @@ test_expect_success \ 'mkdir "G g" && echo ok then >"G g/with spaces.txt" && git add "G g/with spaces.txt" && \ - cp "$TEST_DIRECTORY"/test9200a.png "G g/with spaces.png" && \ + cp "$TEST_DIRECTORY"/test-binary-1.png "G g/with spaces.png" && \ git add "G g/with spaces.png" && git commit -a -m "With spaces" && id=$(git rev-list --max-count=1 HEAD) && @@ -177,7 +177,7 @@ test_expect_success \ test_expect_success \ 'Update file with spaces in file name' \ 'echo Ok then >>"G g/with spaces.txt" && - cat "$TEST_DIRECTORY"/test9200a.png >>"G g/with spaces.png" && \ + cat "$TEST_DIRECTORY"/test-binary-1.png >>"G g/with spaces.png" && \ git add "G g/with spaces.png" && git commit -a -m "Update with spaces" && id=$(git rev-list --max-count=1 HEAD) && @@ -202,7 +202,7 @@ test_expect_success \ 'mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö && echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt && git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt && - cp "$TEST_DIRECTORY"/test9200a.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && + cp "$TEST_DIRECTORY"/test-binary-1.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && git commit -a -m "Går det så går det" && \ id=$(git rev-list --max-count=1 HEAD) && diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index f823c05305..950d0ff498 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -228,7 +228,7 @@ test_expect_success 'fast-export -C -C | fast-import' ' mkdir new && git --git-dir=new/.git init && git fast-export -C -C --signed-tags=strip --all > output && - grep "^C \"file6\" \"file7\"\$" output && + grep "^C file6 file7\$" output && cat output | (cd new && git fast-import && @@ -414,4 +414,30 @@ test_expect_success SYMLINKS 'directory becomes symlink' ' (cd result && git show master:foo) ' +test_expect_success 'fast-export quotes pathnames' ' + git init crazy-paths && + (cd crazy-paths && + blob=`echo foo | git hash-object -w --stdin` && + git update-index --add \ + --cacheinfo 100644 $blob "$(printf "path with\\nnewline")" \ + --cacheinfo 100644 $blob "path with \"quote\"" \ + --cacheinfo 100644 $blob "path with \\backslash" \ + --cacheinfo 100644 $blob "path with space" && + git commit -m addition && + git ls-files -z -s | perl -0pe "s{\\t}{$&subdir/}" >index && + git read-tree --empty && + git update-index -z --index-info <index && + git commit -m rename && + git read-tree --empty && + git commit -m deletion && + git fast-export HEAD >export.out && + git rev-list HEAD >expect && + git init result && + cd result && + git fast-import <../export.out && + git rev-list HEAD >actual && + test_cmp ../expect actual + ) +' + test_done diff --git a/t/test4012.png b/t/test-binary-1.png Binary files differindex 7b181d15ce..7b181d15ce 100644 --- a/t/test4012.png +++ b/t/test-binary-1.png diff --git a/t/test9200b.png b/t/test-binary-2.png Binary files differindex ac22ccbd3e..ac22ccbd3e 100644 --- a/t/test9200b.png +++ b/t/test-binary-2.png diff --git a/t/test-lib.sh b/t/test-lib.sh index 8c57a00595..df25f17929 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -446,9 +446,14 @@ test_debug () { test_run_ () { test_cleanup=: + expecting_failure=$2 eval >&3 2>&4 "$1" eval_ret=$? - eval >&3 2>&4 "$test_cleanup" + + if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure" + then + eval >&3 2>&4 "$test_cleanup" + fi if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then echo "" fi @@ -497,7 +502,7 @@ test_expect_failure () { if ! test_skip "$@" then say >&3 "checking known breakage: $2" - test_run_ "$2" + test_run_ "$2" expecting_failure if [ "$?" = 0 -a "$eval_ret" = 0 ] then test_known_broken_ok_ "$1" @@ -774,6 +779,9 @@ test_cmp() { # # except that the greeting and config --unset must both succeed for # the test to pass. +# +# Note that under --immediate mode, no clean-up is done to help diagnose +# what went wrong. test_when_finished () { test_cleanup="{ $* diff --git a/t/test9200a.png b/t/test9200a.png Binary files differdeleted file mode 100644 index 7b181d15ce..0000000000 --- a/t/test9200a.png +++ /dev/null diff --git a/templates/hooks--pre-commit.sample b/templates/hooks--pre-commit.sample index b187c4bb1f..18c4829765 100755 --- a/templates/hooks--pre-commit.sample +++ b/templates/hooks--pre-commit.sample @@ -18,6 +18,9 @@ fi # If you want to allow non-ascii filenames set this variable to true. allownonascii=$(git config hooks.allownonascii) +# Redirect output to stderr. +exec 1>&2 + # Cross platform projects tend to avoid non-ascii filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. @@ -25,8 +28,8 @@ if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. - test "$(git diff --cached --name-only --diff-filter=A -z $against | - LC_ALL=C tr -d '[ -~]\0')" + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then echo "Error: Attempt to add a non-ascii file name." echo @@ -43,4 +46,5 @@ then exit 1 fi +# If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against -- diff --git a/unpack-trees.c b/unpack-trees.c index cad8870720..c3d3436add 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -593,7 +593,7 @@ static int unpack_nondirectories(int n, unsigned long mask, static int unpack_failed(struct unpack_trees_options *o, const char *message) { discard_index(&o->result); - if (!o->gently) { + if (!o->gently && !o->exiting_early) { if (message) return error("%s", message); return -1; @@ -1133,6 +1133,8 @@ return_failed: display_error_msgs(o); mark_all_ce_unused(o->src_index); ret = unpack_failed(o, NULL); + if (o->exiting_early) + ret = 0; goto done; } @@ -1166,11 +1168,22 @@ static int verify_uptodate_1(struct cache_entry *ce, { struct stat st; - if (o->index_only || (!((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) && (o->reset || ce_uptodate(ce)))) + if (o->index_only) + return 0; + + /* + * CE_VALID and CE_SKIP_WORKTREE cheat, we better check again + * if this entry is truly up-to-date because this file may be + * overwritten. + */ + if ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) + ; /* keep checking */ + else if (o->reset || ce_uptodate(ce)) return 0; if (!lstat(ce->name, &st)) { - unsigned changed = ie_match_stat(o->src_index, ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE); + int flags = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE; + unsigned changed = ie_match_stat(o->src_index, ce, &st, flags); if (!changed) return 0; /* diff --git a/unpack-trees.h b/unpack-trees.h index 64f02cb03a..7998948307 100644 --- a/unpack-trees.h +++ b/unpack-trees.h @@ -46,6 +46,7 @@ struct unpack_trees_options { debug_unpack, skip_sparse_checkout, gently, + exiting_early, show_all_errors, dry_run; const char *prefix; diff --git a/upload-pack.c b/upload-pack.c index ce5cbbea6b..03adf28550 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -10,6 +10,7 @@ #include "revision.h" #include "list-objects.h" #include "run-command.h" +#include "sigchain.h" static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<n>] <dir>"; @@ -498,11 +499,97 @@ static int get_common_commits(void) } } +static void check_non_tip(void) +{ + static const char *argv[] = { + "rev-list", "--stdin", NULL, + }; + static struct child_process cmd; + struct object *o; + char namebuf[42]; /* ^ + SHA-1 + LF */ + int i; + + /* In the normal in-process case non-tip request can never happen */ + if (!stateless_rpc) + goto error; + + cmd.argv = argv; + cmd.git_cmd = 1; + cmd.no_stderr = 1; + cmd.in = -1; + cmd.out = -1; + + if (start_command(&cmd)) + goto error; + + /* + * If rev-list --stdin encounters an unknown commit, it + * terminates, which will cause SIGPIPE in the write loop + * below. + */ + sigchain_push(SIGPIPE, SIG_IGN); + + namebuf[0] = '^'; + namebuf[41] = '\n'; + for (i = get_max_object_index(); 0 < i; ) { + o = get_indexed_object(--i); + if (!o) + continue; + if (!(o->flags & OUR_REF)) + continue; + memcpy(namebuf + 1, sha1_to_hex(o->sha1), 40); + if (write_in_full(cmd.in, namebuf, 42) < 0) + goto error; + } + namebuf[40] = '\n'; + for (i = 0; i < want_obj.nr; i++) { + o = want_obj.objects[i].item; + if (o->flags & OUR_REF) + continue; + memcpy(namebuf, sha1_to_hex(o->sha1), 40); + if (write_in_full(cmd.in, namebuf, 41) < 0) + goto error; + } + close(cmd.in); + + sigchain_pop(SIGPIPE); + + /* + * The commits out of the rev-list are not ancestors of + * our ref. + */ + i = read_in_full(cmd.out, namebuf, 1); + if (i) + goto error; + close(cmd.out); + + /* + * rev-list may have died by encountering a bad commit + * in the history, in which case we do want to bail out + * even when it showed no commit. + */ + if (finish_command(&cmd)) + goto error; + + /* All the non-tip ones are ancestors of what we advertised */ + return; + +error: + /* Pick one of them (we know there at least is one) */ + for (i = 0; i < want_obj.nr; i++) { + o = want_obj.objects[i].item; + if (!(o->flags & OUR_REF)) + die("git upload-pack: not our ref %s", + sha1_to_hex(o->sha1)); + } +} + static void receive_needs(void) { struct object_array shallows = OBJECT_ARRAY_INIT; static char line[1000]; int len, depth = 0; + int has_non_tip = 0; shallow_nr = 0; if (debug_fd) @@ -559,26 +646,30 @@ static void receive_needs(void) if (strstr(line+45, "include-tag")) use_include_tag = 1; - /* We have sent all our refs already, and the other end - * should have chosen out of them; otherwise they are - * asking for nonsense. - * - * Hmph. We may later want to allow "want" line that - * asks for something like "master~10" (symbolic)... - * would it make sense? I don't know. - */ o = lookup_object(sha1_buf); - if (!o || !(o->flags & OUR_REF)) + if (!o) die("git upload-pack: not our ref %s", sha1_to_hex(sha1_buf)); if (!(o->flags & WANTED)) { o->flags |= WANTED; + if (!(o->flags & OUR_REF)) + has_non_tip = 1; add_object_array(o, NULL, &want_obj); } } if (debug_fd) write_str_in_full(debug_fd, "#E\n"); + /* + * We have sent all our refs already, and the other end + * should have chosen out of them. When we are operating + * in the stateless RPC mode, however, their choice may + * have been based on the set of older refs advertised + * by another process that handled the initial request. + */ + if (has_non_tip) + check_non_tip(); + if (!use_sideband && daemon_mode) no_progress = 1; @@ -4,6 +4,7 @@ * Copyright (C) Linus Torvalds, 2005 */ #include "git-compat-util.h" +#include "cache.h" void vreportf(const char *prefix, const char *err, va_list params) { @@ -12,6 +13,18 @@ void vreportf(const char *prefix, const char *err, va_list params) fprintf(stderr, "%s%s\n", prefix, msg); } +void vwritef(int fd, const char *prefix, const char *err, va_list params) +{ + char msg[4096]; + int len = vsnprintf(msg, sizeof(msg), err, params); + if (len > sizeof(msg)) + len = sizeof(msg); + + write_in_full(fd, prefix, strlen(prefix)); + write_in_full(fd, msg, len); + write_in_full(fd, "\n", 1); +} + static NORETURN void usage_builtin(const char *err, va_list params) { vreportf("usage: ", err, params); @@ -46,6 +59,11 @@ void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list param die_routine = routine; } +void set_error_routine(void (*routine)(const char *err, va_list params)) +{ + error_routine = routine; +} + void NORETURN usagef(const char *err, ...) { va_list params; diff --git a/userdiff.c b/userdiff.c index e55310cd02..01d3a8b81e 100644 --- a/userdiff.c +++ b/userdiff.c @@ -281,3 +281,20 @@ struct userdiff_driver *userdiff_find_by_path(const char *path) return NULL; return userdiff_find_by_name(check.value); } + +struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver) +{ + if (!driver->textconv) + return NULL; + + if (driver->textconv_want_cache && !driver->textconv_cache) { + struct notes_cache *c = xmalloc(sizeof(*c)); + struct strbuf name = STRBUF_INIT; + + strbuf_addf(&name, "textconv/%s", driver->name); + notes_cache_init(c, name.buf, driver->textconv); + driver->textconv_cache = c; + } + + return driver; +} diff --git a/userdiff.h b/userdiff.h index 942d594950..4a7e78ffbc 100644 --- a/userdiff.h +++ b/userdiff.h @@ -23,4 +23,6 @@ int userdiff_config(const char *k, const char *v); struct userdiff_driver *userdiff_find_by_name(const char *name); struct userdiff_driver *userdiff_find_by_path(const char *path); +struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver); + #endif /* USERDIFF */ diff --git a/wt-status.c b/wt-status.c index 9f4e0ba9c1..c01838c5ad 100644 --- a/wt-status.c +++ b/wt-status.c @@ -394,7 +394,7 @@ static void wt_status_collect_changes_worktree(struct wt_status *s) if (s->ignore_submodule_arg) { DIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG); handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg); - } + } rev.diffopt.format_callback = wt_status_collect_changed_cb; rev.diffopt.format_callback_data = s; init_pathspec(&rev.prune_data, s->pathspec); @@ -642,7 +642,7 @@ static void wt_status_print_other(struct wt_status *s, int i; struct strbuf buf = STRBUF_INIT; - if (!s->untracked.nr) + if (!l->nr) return; wt_status_print_other_header(s, what, how); @@ -4,58 +4,248 @@ */ #include "cache.h" -void git_inflate_init(z_streamp strm) +static const char *zerr_to_string(int status) { - const char *err; + switch (status) { + case Z_MEM_ERROR: + return "out of memory"; + case Z_VERSION_ERROR: + return "wrong version"; + case Z_NEED_DICT: + return "needs dictionary"; + case Z_DATA_ERROR: + return "data stream error"; + case Z_STREAM_ERROR: + return "stream consistency error"; + default: + return "unknown error"; + } +} - switch (inflateInit(strm)) { - case Z_OK: +/* + * avail_in and avail_out in zlib are counted in uInt, which typically + * limits the size of the buffer we can use to 4GB when interacting + * with zlib in a single call to inflate/deflate. + */ +/* #define ZLIB_BUF_MAX ((uInt)-1) */ +#define ZLIB_BUF_MAX ((uInt) 1024 * 1024 * 1024) /* 1GB */ +static inline uInt zlib_buf_cap(unsigned long len) +{ + return (ZLIB_BUF_MAX < len) ? ZLIB_BUF_MAX : len; +} + +static void zlib_pre_call(git_zstream *s) +{ + s->z.next_in = s->next_in; + s->z.next_out = s->next_out; + s->z.total_in = s->total_in; + s->z.total_out = s->total_out; + s->z.avail_in = zlib_buf_cap(s->avail_in); + s->z.avail_out = zlib_buf_cap(s->avail_out); +} + +static void zlib_post_call(git_zstream *s) +{ + unsigned long bytes_consumed; + unsigned long bytes_produced; + + bytes_consumed = s->z.next_in - s->next_in; + bytes_produced = s->z.next_out - s->next_out; + if (s->z.total_out != s->total_out + bytes_produced) + die("BUG: total_out mismatch"); + if (s->z.total_in != s->total_in + bytes_consumed) + die("BUG: total_in mismatch"); + + s->total_out = s->z.total_out; + s->total_in = s->z.total_in; + s->next_in = s->z.next_in; + s->next_out = s->z.next_out; + s->avail_in -= bytes_consumed; + s->avail_out -= bytes_produced; +} + +void git_inflate_init(git_zstream *strm) +{ + int status; + + zlib_pre_call(strm); + status = inflateInit(&strm->z); + zlib_post_call(strm); + if (status == Z_OK) return; + die("inflateInit: %s (%s)", zerr_to_string(status), + strm->z.msg ? strm->z.msg : "no message"); +} - case Z_MEM_ERROR: - err = "out of memory"; - break; - case Z_VERSION_ERROR: - err = "wrong version"; +void git_inflate_init_gzip_only(git_zstream *strm) +{ + /* + * Use default 15 bits, +16 is to accept only gzip and to + * yield Z_DATA_ERROR when fed zlib format. + */ + const int windowBits = 15 + 16; + int status; + + zlib_pre_call(strm); + status = inflateInit2(&strm->z, windowBits); + zlib_post_call(strm); + if (status == Z_OK) + return; + die("inflateInit2: %s (%s)", zerr_to_string(status), + strm->z.msg ? strm->z.msg : "no message"); +} + +void git_inflate_end(git_zstream *strm) +{ + int status; + + zlib_pre_call(strm); + status = inflateEnd(&strm->z); + zlib_post_call(strm); + if (status == Z_OK) + return; + error("inflateEnd: %s (%s)", zerr_to_string(status), + strm->z.msg ? strm->z.msg : "no message"); +} + +int git_inflate(git_zstream *strm, int flush) +{ + int status; + + for (;;) { + zlib_pre_call(strm); + /* Never say Z_FINISH unless we are feeding everything */ + status = inflate(&strm->z, + (strm->z.avail_in != strm->avail_in) + ? 0 : flush); + if (status == Z_MEM_ERROR) + die("inflate: out of memory"); + zlib_post_call(strm); + + /* + * Let zlib work another round, while we can still + * make progress. + */ + if ((strm->avail_out && !strm->z.avail_out) && + (status == Z_OK || status == Z_BUF_ERROR)) + continue; break; + } + + switch (status) { + /* Z_BUF_ERROR: normal, needs more space in the output buffer */ + case Z_BUF_ERROR: + case Z_OK: + case Z_STREAM_END: + return status; default: - err = "error"; + break; } - die("inflateInit: %s (%s)", err, strm->msg ? strm->msg : "no message"); + error("inflate: %s (%s)", zerr_to_string(status), + strm->z.msg ? strm->z.msg : "no message"); + return status; } -void git_inflate_end(z_streamp strm) +#if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200 +#define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) +#endif + +unsigned long git_deflate_bound(git_zstream *strm, unsigned long size) { - if (inflateEnd(strm) != Z_OK) - error("inflateEnd: %s", strm->msg ? strm->msg : "failed"); + return deflateBound(&strm->z, size); } -int git_inflate(z_streamp strm, int flush) +void git_deflate_init(git_zstream *strm, int level) { - int ret = inflate(strm, flush); - const char *err; + int status; - switch (ret) { - /* Out of memory is fatal. */ - case Z_MEM_ERROR: - die("inflate: out of memory"); + zlib_pre_call(strm); + status = deflateInit(&strm->z, level); + zlib_post_call(strm); + if (status == Z_OK) + return; + die("deflateInit: %s (%s)", zerr_to_string(status), + strm->z.msg ? strm->z.msg : "no message"); +} - /* Data corruption errors: we may want to recover from them (fsck) */ - case Z_NEED_DICT: - err = "needs dictionary"; break; - case Z_DATA_ERROR: - err = "data stream error"; break; - case Z_STREAM_ERROR: - err = "stream consistency error"; break; - default: - err = "unknown error"; break; +void git_deflate_init_gzip(git_zstream *strm, int level) +{ + /* + * Use default 15 bits, +16 is to generate gzip header/trailer + * instead of the zlib wrapper. + */ + const int windowBits = 15 + 16; + int status; + zlib_pre_call(strm); + status = deflateInit2(&strm->z, level, + Z_DEFLATED, windowBits, + 8, Z_DEFAULT_STRATEGY); + zlib_post_call(strm); + if (status == Z_OK) + return; + die("deflateInit2: %s (%s)", zerr_to_string(status), + strm->z.msg ? strm->z.msg : "no message"); +} + +void git_deflate_end(git_zstream *strm) +{ + int status; + + zlib_pre_call(strm); + status = deflateEnd(&strm->z); + zlib_post_call(strm); + if (status == Z_OK) + return; + error("deflateEnd: %s (%s)", zerr_to_string(status), + strm->z.msg ? strm->z.msg : "no message"); +} + +int git_deflate_end_gently(git_zstream *strm) +{ + int status; + + zlib_pre_call(strm); + status = deflateEnd(&strm->z); + zlib_post_call(strm); + return status; +} + +int git_deflate(git_zstream *strm, int flush) +{ + int status; + + for (;;) { + zlib_pre_call(strm); + + /* Never say Z_FINISH unless we are feeding everything */ + status = deflate(&strm->z, + (strm->z.avail_in != strm->avail_in) + ? 0 : flush); + if (status == Z_MEM_ERROR) + die("deflate: out of memory"); + zlib_post_call(strm); + + /* + * Let zlib work another round, while we can still + * make progress. + */ + if ((strm->avail_out && !strm->z.avail_out) && + (status == Z_OK || status == Z_BUF_ERROR)) + continue; + break; + } + + switch (status) { /* Z_BUF_ERROR: normal, needs more space in the output buffer */ case Z_BUF_ERROR: case Z_OK: case Z_STREAM_END: - return ret; + return status; + default: + break; } - error("inflate: %s (%s)", err, strm->msg ? strm->msg : "no message"); - return ret; + error("deflate: %s (%s)", zerr_to_string(status), + strm->z.msg ? strm->z.msg : "no message"); + return status; } |