diff options
104 files changed, 1364 insertions, 308 deletions
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines new file mode 100644 index 0000000000..3b042db624 --- /dev/null +++ b/Documentation/CodingGuidelines @@ -0,0 +1,112 @@ +Like other projects, we also have some guidelines to keep to the +code. For git in general, three rough rules are: + + - Most importantly, we never say "It's in POSIX; we'll happily + ignore your needs should your system not conform to it." + We live in the real world. + + - However, we often say "Let's stay away from that construct, + it's not even in POSIX". + + - In spite of the above two rules, we sometimes say "Although + this is not in POSIX, it (is so convenient | makes the code + much more readable | has other good characteristics) and + practically all the platforms we care about support it, so + let's use it". + + Again, we live in the real world, and it is sometimes a + judgement call, the decision based more on real world + constraints people face than what the paper standard says. + + +As for more concrete guidelines, just imitate the existing code +(this is a good guideline, no matter which project you are +contributing to). But if you must have a list of rules, +here they are. + +For shell scripts specifically (not exhaustive): + + - We prefer $( ... ) for command substitution; unlike ``, it + properly nests. It should have been the way Bourne spelled + it from day one, but unfortunately isn't. + + - We use ${parameter-word} and its [-=?+] siblings, and their + colon'ed "unset or null" form. + + - We use ${parameter#word} and its [#%] siblings, and their + doubled "longest matching" form. + + - We use Arithmetic Expansion $(( ... )). + + - No "Substring Expansion" ${parameter:offset:length}. + + - No shell arrays. + + - No strlen ${#parameter}. + + - No regexp ${parameter/pattern/string}. + + - We do not use Process Substitution <(list) or >(list). + + - We prefer "test" over "[ ... ]". + + - We do not write the noiseword "function" in front of shell + functions. + +For C programs: + + - We use tabs to indent, and interpret tabs as taking up to + 8 spaces. + + - We try to keep to at most 80 characters per line. + + - When declaring pointers, the star sides with the variable + name, i.e. "char *string", not "char* string" or + "char * string". This makes it easier to understand code + like "char *string, c;". + + - We avoid using braces unnecessarily. I.e. + + if (bla) { + x = 1; + } + + is frowned upon. A gray area is when the statement extends + over a few lines, and/or you have a lengthy comment atop of + it. Also, like in the Linux kernel, if there is a long list + of "else if" statements, it can make sense to add braces to + single line blocks. + + - Try to make your code understandable. You may put comments + in, but comments invariably tend to stale out when the code + they were describing changes. Often splitting a function + into two makes the intention of the code much clearer. + + - Double negation is often harder to understand than no negation + at all. + + - Some clever tricks, like using the !! operator with arithmetic + constructs, can be extremely confusing to others. Avoid them, + unless there is a compelling reason to use them. + + - Use the API. No, really. We have a strbuf (variable length + string), several arrays with the ALLOC_GROW() macro, a + path_list for sorted string lists, a hash map (mapping struct + objects) named "struct decorate", amongst other things. + + - When you come up with an API, document it. + + - The first #include in C files, except in platform specific + compat/ implementations, should be git-compat-util.h or another + header file that includes it, such as cache.h or builtin.h. + + - If you are planning a new command, consider writing it in shell + or perl first, so that changes in semantics can be easily + changed and discussed. Many git commands started out like + that, and a few are still scripts. + + - Avoid introducing a new dependency into git. This means you + usually should stay away from scripting languages not already + used in the git core command set (unless your command is clearly + separate from it, such as an importer to convert random-scm-X + repositories to git). diff --git a/Documentation/Makefile b/Documentation/Makefile index 39ec0ede02..d88664177d 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -37,9 +37,6 @@ man7dir=$(mandir)/man7 ASCIIDOC=asciidoc ASCIIDOC_EXTRA = -ifdef ASCIIDOC8 -ASCIIDOC_EXTRA += -a asciidoc7compatible -endif INSTALL?=install RM ?= rm -f DOC_REF = origin/man @@ -52,6 +49,13 @@ DOCBOOK2X_TEXI=docbook2x-texi -include ../config.mak.autogen -include ../config.mak +ifdef ASCIIDOC8 +ASCIIDOC_EXTRA += -a asciidoc7compatible +endif +ifdef DOCBOOK_XSL_172 +ASCIIDOC_EXTRA += -a docbook-xsl-172 +endif + # # Please note that there is a minor bug in asciidoc. # The version after 6.0.3 _will_ include the patch found here: diff --git a/Documentation/RelNotes-1.5.3.5.txt b/Documentation/RelNotes-1.5.3.5.txt index f99a2cd650..7ff1d5d0d1 100644 --- a/Documentation/RelNotes-1.5.3.5.txt +++ b/Documentation/RelNotes-1.5.3.5.txt @@ -90,5 +90,5 @@ Fixes since v1.5.3.4 * "git-send-pack $remote frotz" segfaulted when there is nothing named 'frotz' on the local end. - * "git-rebase -interactive" did not handle its "--strategy" option + * "git-rebase --interactive" did not handle its "--strategy" option properly. diff --git a/Documentation/RelNotes-1.5.3.6.txt b/Documentation/RelNotes-1.5.3.6.txt new file mode 100644 index 0000000000..069a2b2cf9 --- /dev/null +++ b/Documentation/RelNotes-1.5.3.6.txt @@ -0,0 +1,48 @@ +GIT v1.5.3.6 Release Notes +========================== + +Fixes since v1.5.3.5 +-------------------- + + * git-cvsexportcommit handles root commits better. + + * git-svn dcommit used to clobber when sending a series of + patches. + + * git-svn dcommit failed after attempting to rebase when + started with a dirty index; now it stops upfront. + + * git-grep sometimes refused to work when your index was + unmerged. + + * "git-grep -A1 -B2" acted as if it was told to run "git -A1 -B21". + + * git-hash-object did not honor configuration variables, such as + core.compression. + + * git-index-pack choked on a huge pack on 32-bit machines, even when + large file offsets are supported. + + * atom feeds from git-web said "10" for the month of November. + + * a memory leak in commit walker was plugged. + + * When git-send-email inserted the original author's From: + address in body, it did not mark the message with + Content-type: as needed. + + * git-revert and git-cherry-pick incorrectly refused to start + when the work tree was dirty. + + * git-clean did not honor core.excludesfile configuration. + + * git-add mishandled ".gitignore" files when applying them to + subdirectories. + + * While importing a too branchy history, git-fastimport did not + honor delta depth limit properly. + + * Support for zlib implementations that lack ZLIB_VERNUM and definition + of deflateBound() has been added. + + * Quite a lot of documentation clarifications. diff --git a/Documentation/RelNotes-1.5.3.7.txt b/Documentation/RelNotes-1.5.3.7.txt new file mode 100644 index 0000000000..2f690616c8 --- /dev/null +++ b/Documentation/RelNotes-1.5.3.7.txt @@ -0,0 +1,45 @@ +GIT v1.5.3.7 Release Notes +========================== + +Fixes since v1.5.3.6 +-------------------- + + * git-send-email added 8-bit contents to the payload without + marking it as 8-bit in a CTE header. + + * "git-bundle create a.bndl HEAD" dereferenced the symref and + did not record the ref as 'HEAD'; this prevented a bundle + from being used as a normal source of git-clone. + + * The code to reject nonsense command line of the form + "git-commit -a paths..." and "git-commit --interactive + paths..." were broken. + + * Adding a signature that is not ASCII-only to an original + commit that is ASCII-only would make the result non-ASCII. + "git-format-patch -s" did not mark such a message correctly + with MIME encoding header. + + * git-add sometimes did not mark the resulting index entry + stat-clean. This affected only cases when adding the + contents with the same length as the previously staged + contents, and the previous staging made the index entry + "racily clean". + + * git-commit did not honor GIT_INDEX_FILE the user had in the + environment. + + * When checking out a revision, git-checkout did not report where the + updated HEAD is if you happened to have a file called HEAD in the + work tree. + + * "git-rev-list --objects" mishandled a tree that points at a + submodule. + + * "git cvsimport" was not ready for packed refs that "git gc" can + produce and gave incorrect results. + + * Many scripted Porcelains were confused when you happened to have a + file called "HEAD" in your work tree. + +Also it contains updates to the user manual and documentation. diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 61635bf04d..83bf54c7ac 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -20,9 +20,6 @@ Checklist (and a short version for the impatient): Patch: - use "git format-patch -M" to create the patch - - send your patch to <git@vger.kernel.org>. If you use - git-send-email(1), please test it first by sending - email to yourself. - do not PGP sign your patch - do not attach your patch, but read in the mail body, unless you cannot teach your mailer to @@ -31,13 +28,15 @@ Checklist (and a short version for the impatient): corrupt whitespaces. - provide additional information (which is unsuitable for the commit message) between the "---" and the diffstat - - send the patch to the list (git@vger.kernel.org) and the - maintainer (gitster@pobox.com). - if you change, add, or remove a command line option or make some other user interface change, the associated documentation should be updated as well. - if your name is not writable in ASCII, make sure that you send off a message in the correct encoding. + - send the patch to the list (git@vger.kernel.org) and the + maintainer (gitster@pobox.com). If you use + git-send-email(1), please test it first by sending + email to yourself. Long version: diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index af5b1558a6..99d8874aa0 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -23,7 +23,9 @@ ifdef::backend-docbook[] endif::backend-docbook[] ifdef::backend-docbook[] +ifndef::docbook-xsl-172[] # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. +# v1.72 breaks with this because it replaces dots not in roff requests. [listingblock] <example><title>{title}</title> <literallayout> @@ -36,6 +38,7 @@ ifdef::doctype-manpage[] endif::doctype-manpage[] </literallayout> {title#}</example> +endif::docbook-xsl-172[] endif::backend-docbook[] ifdef::doctype-manpage[] diff --git a/Documentation/config.txt b/Documentation/config.txt index 7ee97df8a7..83bc33c421 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -226,13 +226,15 @@ core.compression:: An integer -1..9, indicating a default compression level. -1 is the zlib default. 0 means no compression, and 1..9 are various speed/size tradeoffs, 9 being slowest. + If set, this provides a default to other compression variables, + such as 'core.loosecompression' and 'pack.compression'. core.loosecompression:: An integer -1..9, indicating the compression level for objects that are not in a pack file. -1 is the zlib default. 0 means no compression, and 1..9 are various speed/size tradeoffs, 9 being slowest. If not set, defaults to core.compression. If that is - not set, defaults to 0 (best speed). + not set, defaults to 1 (best speed). core.packedGitWindowSize:: Number of bytes of a pack file to map into memory in a @@ -622,7 +624,9 @@ pack.compression:: in a pack file. -1 is the zlib default. 0 means no compression, and 1..9 are various speed/size tradeoffs, 9 being slowest. If not set, defaults to core.compression. If that is - not set, defaults to -1. + not set, defaults to -1, the zlib default, which is "a default + compromise between speed and compression (currently equivalent + to level 6)." pack.deltaCacheSize:: The maximum memory in bytes used for caching deltas in diff --git a/Documentation/core-tutorial.txt b/Documentation/core-tutorial.txt index 67064dd31a..c3f0be535d 100644 --- a/Documentation/core-tutorial.txt +++ b/Documentation/core-tutorial.txt @@ -1082,11 +1082,6 @@ server like git Native transport does. Any stock HTTP server that does not even support directory index would suffice. But you must prepare your repository with `git-update-server-info` to help dumb transport downloaders. -+ -There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload` -programs, which are 'commit walkers'; they outlived their -usefulness when git Native and SSH transports were introduced, -and not used by `git pull` or `git push` scripts. Once you fetch from the remote repository, you `merge` that with your current branch. @@ -1149,7 +1144,7 @@ back to the earlier repository with "hello" and "example" file, and bring ourselves back to the pre-merge state: ------------ -$ git show-branch --more=3 master mybranch +$ git show-branch --more=2 master mybranch ! [master] Merge work in mybranch * [mybranch] Merge work in mybranch -- @@ -1212,7 +1207,7 @@ $ git-read-tree -m -u $mb HEAD mybranch This is the same `git-read-tree` command we have already seen, but it takes three trees, unlike previous examples. This reads the contents of each tree into different 'stage' in the index -file (the first tree goes to stage 1, the second stage 2, +file (the first tree goes to stage 1, the second to stage 2, etc.). After reading three trees into three stages, the paths that are the same in all three stages are 'collapsed' into stage 0. Also paths that are the same in two of three stages are diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index 001503205b..9709c35c98 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -1,5 +1,5 @@ -The output format from "git-diff-index", "git-diff-tree" and -"git-diff-files" are very similar. +The output format from "git-diff-index", "git-diff-tree", +"git-diff-files" and "git diff --raw" are very similar. These commands all compare two sets of things; what is compared differs: @@ -62,7 +62,8 @@ respectively. diff format for merges ---------------------- -"git-diff-tree" and "git-diff-files" can take '-c' or '--cc' option +"git-diff-tree", "git-diff-files" and "git-diff --raw" +can take '-c' or '--cc' option to generate diff output also for merge commits. The output differs from the format described above in the following way: @@ -86,10 +87,10 @@ Generating patches with -p -------------------------- When "git-diff-index", "git-diff-tree", or "git-diff-files" are run -with a '-p' option, they do not produce the output described above; -instead they produce a patch file. You can customize the creation -of such patches via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS -environment variables. +with a '-p' option, or "git diff" without the '--raw' option, they +do not produce the output described above; instead they produce a +patch file. You can customize the creation of such patches via the +GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables. What the -p option produces is slightly different from the traditional diff format. @@ -137,8 +138,8 @@ file made it into the new one. combined diff format -------------------- -git-diff-tree and git-diff-files can take '-c' or '--cc' option -to produce 'combined diff', which looks like this: +"git-diff-tree", "git-diff-files" and "git-diff" can take '-c' or +'--cc' option to produce 'combined diff', which looks like this: ------------ diff --combined describe.c diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 2fe7355555..fd82fc19b5 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -224,6 +224,7 @@ See Also -------- gitlink:git-status[1] gitlink:git-rm[1] +gitlink:git-reset[1] gitlink:git-mv[1] gitlink:git-commit[1] gitlink:git-update-index[1] diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index b7285bcdbc..d64ad25028 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -45,17 +45,22 @@ to happen. With a `-d` or `-D` option, `<branchname>` will be deleted. You may specify more than one branch for deletion. If the branch currently -has a reflog then the reflog will also be deleted. Use -r together with -d -to delete remote-tracking branches. +has a reflog then the reflog will also be deleted. + +Use -r together with -d to delete remote-tracking branches. Note, that it +only makes sense to delete remote-tracking branches if they no longer exist +in remote repository or if gitlink:git-fetch[1] was configured not to fetch +them again. See also 'prune' subcommand of gitlink:git-remote[1] for way to +clean up all obsolete remote-tracking branches. OPTIONS ------- -d:: - Delete a branch. The branch must be fully merged. + Delete a branch. The branch must be fully merged in HEAD. -D:: - Delete a branch irrespective of its index status. + Delete a branch irrespective of its merged status. -l:: Create the branch's reflog. This activates recording of @@ -105,7 +110,7 @@ OPTIONS '--track' were given. --no-track:: - When -b is given and a branch is created off a remote branch, + When a branch is created off a remote branch, set up configuration so that git-pull will not retrieve data from the remote branch, ignoring the branch.autosetupmerge configuration variable. @@ -153,9 +158,11 @@ $ git branch -d -r origin/todo origin/html origin/man <1> $ git branch -D test <2> ------------ + -<1> Delete remote-tracking branches "todo", "html", "man" -<2> Delete "test" branch even if the "master" branch does not have all -commits from test branch. +<1> Delete remote-tracking branches "todo", "html", "man". Next 'fetch' or +'pull' will create them again unless you configure them not to. See +gitlink:git-fetch[1]. +<2> Delete "test" branch even if the "master" branch (or whichever branch is +currently checked out) does not have all commits from test branch. Notes diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index e54fb12103..d4bfd49ce1 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -154,10 +154,13 @@ EXAMPLES -------- 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 gitlink:git-add[1]. Removal -of a file is staged with gitlink:git-rm[1]. After building the -state to be committed incrementally with these commands, `git -commit` (without any pathname parameter) is used to record what +called the "index" with gitlink:git-add[1]. 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>`, +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, +`git commit` (without any pathname parameter) is used to record what has been staged so far. This is the most basic form of the command. An example: diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt index db2eb46a19..201d5daf1a 100644 --- a/Documentation/git-diff.txt +++ b/Documentation/git-diff.txt @@ -82,6 +82,9 @@ include::diff-options.txt[] the diff to the named paths (you can give directory names and get diff for all files under them). +Output format +------------- +include::diff-format.txt[] EXAMPLES -------- diff --git a/Documentation/git-get-tar-commit-id.txt b/Documentation/git-get-tar-commit-id.txt index 9b5f86fc30..60d1c52f44 100644 --- a/Documentation/git-get-tar-commit-id.txt +++ b/Documentation/git-get-tar-commit-id.txt @@ -3,7 +3,7 @@ git-get-tar-commit-id(1) NAME ---- -git-get-tar-commit-id - Extract commit ID from an archive created using git-tar-tree +git-get-tar-commit-id - Extract commit ID from an archive created using git-archive SYNOPSIS @@ -14,12 +14,12 @@ SYNOPSIS DESCRIPTION ----------- Acts as a filter, extracting the commit ID stored in archives created by -git-tar-tree. It reads only the first 1024 bytes of input, thus its +gitlink:git-archive[1]. It reads only the first 1024 bytes of input, thus its runtime is not influenced by the size of <tarfile> very much. If no commit ID is found, git-get-tar-commit-id quietly exists with a return code of 1. This can happen if <tarfile> had not been created -using git-tar-tree or if the first parameter of git-tar-tree had been +using git-archive or if the first parameter of git-archive had been a tree ID instead of a commit ID or tag. diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt index 5c7316ceb8..25003c3866 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.txt @@ -19,7 +19,7 @@ depending on the subcommand: git reflog expire [--dry-run] [--stale-fix] [--verbose] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>... -git reflog [show] [log-options] +git reflog [show] [log-options] [<ref>] Reflog is a mechanism to record when the tip of branches are updated. This command is to manage the information recorded in it. @@ -32,9 +32,16 @@ directly by the end users -- instead, see gitlink:git-gc[1]. The subcommand "show" (which is also the default, in the absence of any subcommands) will take all the normal log options, and show the log of -`HEAD`, which will cover all recent actions, including branch switches. -It is basically an alias for 'git log -g --abbrev-commit ---pretty=oneline', see gitlink:git-log[1]. +the reference provided in the command-line (or `HEAD`, by default). +The reflog will cover all recent actions (HEAD reflog records branch switching +as well). It is an alias for 'git log -g --abbrev-commit --pretty=oneline'; +see gitlink:git-log[1]. + +The reflog is useful in various git commands, to specify the old value +of a reference. For example, `HEAD@\{2\}` means "where HEAD used to be +two moves ago", `master@\{one.week.ago\}` means "where master used to +point to one week ago", and so on. See gitlink:git-rev-parse[1] for +more details. OPTIONS diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 61a6022ce8..886bc03c4a 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -69,7 +69,7 @@ caution. Fetch updates for a named set of remotes in the repository as defined by remotes.<group>. If a named group is not specified on the command line, the configuration parameter remotes.default will get used; if -remotes.default is not defined, all remotes which do not the +remotes.default is not defined, all remotes which do not have the configuration parameter remote.<name>.skipDefaultUpdate set to true will be updated. (See gitlink:git-config[1]). @@ -91,7 +91,7 @@ $ git remote origin $ git branch -r origin/master -$ git remote add linux-nfs git://linux-nfs.org/pub/nfs-2.6.git +$ git remote add linux-nfs git://linux-nfs.org/pub/linux/nfs-2.6.git $ git remote linux-nfs origin diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index dd51aa11ea..cf4ee2ebe5 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -148,22 +148,23 @@ with `$Id$` upon check-in. `filter` ^^^^^^^^ -A `filter` attribute can be set to a string value. This names +A `filter` attribute can be set to a string value that names a filter driver specified in the configuration. -A filter driver consists of `clean` command and `smudge` +A filter driver consists of a `clean` command and a `smudge` command, either of which can be left unspecified. Upon -checkout, when `smudge` command is specified, the command is fed -the blob object from its standard input, and its standard output -is used to update the worktree file. Similarly, `clean` command -is used to convert the contents of worktree file upon checkin. +checkout, when the `smudge` command is specified, the command is +fed the blob object from its standard input, and its standard +output is used to update the worktree file. Similarly, the +`clean` command is used to convert the contents of worktree file +upon checkin. -Missing filter driver definition in the config is not an error +A missing filter driver definition in the config is not an error but makes the filter a no-op passthru. The content filtering is done to massage the content into a shape that is more convenient for the platform, filesystem, and -the user to use. The keyword here is "more convenient" and not +the user to use. The key phrase here is "more convenient" and not "turning something unusable into usable". In other words, the intent is that if someone unsets the filter driver definition, or does not have the appropriate filter program, the project diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index c7fdf25e27..159de30e19 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -56,11 +56,12 @@ $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git The initial clone may be time-consuming for a large project, but you will only need to clone once. -The clone command creates a new directory named after the project -("git" or "linux-2.6" in the examples above). After you cd into this +The clone command creates a new directory named after the project ("git" +or "linux-2.6" in the examples above). After you cd into this directory, you will see that it contains a copy of the project files, -together with a special top-level directory named ".git", which -contains all the information about the history of the project. +called the <<def_working_tree,working tree>>, together with a special +top-level directory named ".git", which contains all the information +about the history of the project. [[how-to-check-out]] How to check out a different version of a project @@ -71,8 +72,13 @@ of files. It stores the history as a compressed collection of interrelated snapshots of the project's contents. In git each such version is called a <<def_commit,commit>>. -A single git repository may contain multiple branches. It keeps track -of them by keeping a list of <<def_head,heads>> which reference the +Those snapshots aren't necessarily all arranged in a single line from +oldest to newest; instead, work may simultaneously proceed along +parallel lines of development, called <def_branch,branches>>, which may +merge and diverge. + +A single git repository can track development on multiple branches. It +does this by keeping a list of <<def_head,heads>> which reference the latest commit on each branch; the gitlink:git-branch[1] command shows you the list of branch heads: @@ -658,16 +664,23 @@ gitlink:git-diff[1]: $ git diff master..test ------------------------------------------------- -Sometimes what you want instead is a set of patches: +That will produce the diff between the tips of the two branches. If +you'd prefer to find the diff from their common ancestor to test, you +can use three dots instead of two: + +------------------------------------------------- +$ git diff master...test +------------------------------------------------- + +Sometimes what you want instead is a set of patches; for this you can +use gitlink:git-format-patch[1]: ------------------------------------------------- $ git format-patch master..test ------------------------------------------------- will generate a file with a patch for each commit reachable from test -but not from master. Note that if master also has commits which are -not reachable from test, then the combined result of these patches -will not be the same as the diff produced by the git-diff example. +but not from master. [[viewing-old-file-versions]] Viewing old file versions @@ -1403,8 +1416,8 @@ with the changes to be reverted, then you will be asked to fix conflicts manually, just as in the case of <<resolving-a-merge, resolving a merge>>. -[[fixing-a-mistake-by-editing-history]] -Fixing a mistake by editing history +[[fixing-a-mistake-by-rewriting-history]] +Fixing a mistake by rewriting history ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If the problematic commit is the most recent commit, and you have not @@ -1427,7 +1440,7 @@ Again, you should never do this to a commit that may already have been merged into another branch; use gitlink:git-revert[1] instead in that case. -It is also possible to edit commits further back in the history, but +It is also possible to replace commits further back in the history, but this is an advanced topic to be left for <<cleaning-up-history,another chapter>>. @@ -1547,6 +1560,11 @@ This may be time-consuming. Unlike most other git operations (including git-gc when run without any options), it is not safe to prune while other git operations are in progress in the same repository. +If gitlink:git-fsck[1] complains about sha1 mismatches or missing +objects, you may have a much more serious problem; your best option is +probably restoring from backups. See +<<recovering-from-repository-corruption>> for a detailed discussion. + [[recovering-lost-changes]] Recovering lost changes ~~~~~~~~~~~~~~~~~~~~~~~ @@ -1916,15 +1934,9 @@ or just $ git push ssh://yourserver.com/~you/proj.git master ------------------------------------------------- -As with git-fetch, git-push will complain if this does not result in -a <<fast-forwards,fast forward>>. Normally this is a sign of -something wrong. However, if you are sure you know what you're -doing, you may force git-push to perform the update anyway by -proceeding the branch name by a plus sign: - -------------------------------------------------- -$ git push ssh://yourserver.com/~you/proj.git +master -------------------------------------------------- +As with git-fetch, git-push will complain if this does not result in a +<<fast-forwards,fast forward>>; see the following section for details on +handling this case. Note that the target of a "push" is normally a <<def_bare_repository,bare>> repository. You can also push to a @@ -1952,6 +1964,52 @@ See the explanations of the remote.<name>.url, branch.<name>.remote, and remote.<name>.push options in gitlink:git-config[1] for details. +[[forcing-push]] +What to do when a push fails +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a push would not result in a <<fast-forwards,fast forward>> of the +remote branch, then it will fail with an error like: + +------------------------------------------------- +error: remote 'refs/heads/master' is not an ancestor of + local 'refs/heads/master'. + Maybe you are not up-to-date and need to pull first? +error: failed to push to 'ssh://yourserver.com/~you/proj.git' +------------------------------------------------- + +This can happen, for example, if you: + + - use `git reset --hard` to remove already-published commits, or + - use `git commit --amend` to replace already-published commits + (as in <<fixing-a-mistake-by-rewriting-history>>), or + - use `git rebase` to rebase any already-published commits (as + in <<using-git-rebase>>). + +You may force git-push to perform the update anyway by preceding the +branch name with a plus sign: + +------------------------------------------------- +$ git push ssh://yourserver.com/~you/proj.git +master +------------------------------------------------- + +Normally whenever a branch head in a public repository is modified, it +is modified to point to a descendent of the commit that it pointed to +before. By forcing a push in this situation, you break that convention. +(See <<problems-with-rewriting-history>>.) + +Nevertheless, this is a common practice for people that need a simple +way to publish a work-in-progress patch series, and it is an acceptable +compromise as long as you warn other developers that this is how you +intend to manage the branch. + +It's also possible for a push to fail in this way when other people have +the right to push to the same repository. In that case, the correct +solution is to retry the push after first updating your work by either a +pull or a fetch followed by a rebase; see the +<<setting-up-a-shared-repository,next section>> and +link:cvs-migration.html[git for CVS users] for more. + [[setting-up-a-shared-repository]] Setting up a shared repository ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2419,11 +2477,11 @@ return mywork to the state it had before you started the rebase: $ git rebase --abort ------------------------------------------------- -[[modifying-one-commit]] -Modifying a single commit +[[rewriting-one-commit]] +Rewriting a single commit ------------------------- -We saw in <<fixing-a-mistake-by-editing-history>> that you can replace the +We saw in <<fixing-a-mistake-by-rewriting-history>> that you can replace the most recent commit using ------------------------------------------------- @@ -2433,8 +2491,10 @@ $ git commit --amend which will replace the old commit by a new commit incorporating your changes, giving you a chance to edit the old commit message first. -You can also use a combination of this and gitlink:git-rebase[1] to edit -commits further back in your history. First, tag the problematic commit with +You can also use a combination of this and gitlink:git-rebase[1] to +replace a commit further back in your history and recreate the +intervening changes on top of it. First, tag the problematic commit +with ------------------------------------------------- $ git tag bad mywork~5 @@ -2554,6 +2614,72 @@ branches into their own work. For true distributed development that supports proper merging, published branches should never be rewritten. +[[bisect-merges]] +Why bisecting merge commits can be harder than bisecting linear history +----------------------------------------------------------------------- + +The gitlink:git-bisect[1] command correctly handles history that +includes merge commits. However, when the commit that it finds is a +merge commit, the user may need to work harder than usual to figure out +why that commit introduced a problem. + +Imagine this history: + +................................................ + ---Z---o---X---...---o---A---C---D + \ / + o---o---Y---...---o---B +................................................ + +Suppose that on the upper line of development, the meaning of one +of the functions that exists at Z is changed at commit X. The +commits from Z leading to A change both the function's +implementation and all calling sites that exist at Z, as well +as new calling sites they add, to be consistent. There is no +bug at A. + +Suppose that in the meantime on the lower line of development somebody +adds a new calling site for that function at commit Y. The +commits from Z leading to B all assume the old semantics of that +function and the callers and the callee are consistent with each +other. There is no bug at B, either. + +Suppose further that the two development lines merge cleanly at C, +so no conflict resolution is required. + +Nevertheless, the code at C is broken, because the callers added +on the lower line of development have not been converted to the new +semantics introduced on the upper line of development. So if all +you know is that D is bad, that Z is good, and that +gitlink:git-bisect[1] identifies C as the culprit, how will you +figure out that the problem is due to this change in semantics? + +When the result of a git-bisect is a non-merge commit, you should +normally be able to discover the problem by examining just that commit. +Developers can make this easy by breaking their changes into small +self-contained commits. That won't help in the case above, however, +because the problem isn't obvious from examination of any single +commit; instead, a global view of the development is required. To +make matters worse, the change in semantics in the problematic +function may be just one small part of the changes in the upper +line of development. + +On the other hand, if instead of merging at C you had rebased the +history between Z to B on top of A, you would have gotten this +linear history: + +................................................................ + ---Z---o---X--...---o---A---o---o---Y*--...---o---B*--D* +................................................................ + +Bisecting between Z and D* would hit a single culprit commit Y*, +and understanding why Y* was broken would probably be easier. + +Partly for this reason, many experienced git users, even when +working on an otherwise merge-heavy project, keep the history +linear by rebasing against the latest upstream version before +publishing. + [[advanced-branch-management]] Advanced branch management ========================== @@ -3099,6 +3225,127 @@ confusing and scary messages, but it won't actually do anything bad. In contrast, running "git prune" while somebody is actively changing the repository is a *BAD* idea). +[[recovering-from-repository-corruption]] +Recovering from repository corruption +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By design, git treats data trusted to it with caution. However, even in +the absence of bugs in git itself, it is still possible that hardware or +operating system errors could corrupt data. + +The first defense against such problems is backups. You can back up a +git directory using clone, or just using cp, tar, or any other backup +mechanism. + +As a last resort, you can search for the corrupted objects and attempt +to replace them by hand. Back up your repository before attempting this +in case you corrupt things even more in the process. + +We'll assume that the problem is a single missing or corrupted blob, +which is sometimes a solveable problem. (Recovering missing trees and +especially commits is *much* harder). + +Before starting, verify that there is corruption, and figure out where +it is with gitlink:git-fsck[1]; this may be time-consuming. + +Assume the output looks like this: + +------------------------------------------------ +$ git-fsck --full +broken link from tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8 + to blob 4b9458b3786228369c63936db65827de3cc06200 +missing blob 4b9458b3786228369c63936db65827de3cc06200 +------------------------------------------------ + +(Typically there will be some "dangling object" messages too, but they +aren't interesting.) + +Now you know that blob 4b9458b3 is missing, and that the tree 2d9263c6 +points to it. If you could find just one copy of that missing blob +object, possibly in some other repository, you could move it into +.git/objects/4b/9458b3... and be done. Suppose you can't. You can +still examine the tree that pointed to it with gitlink:git-ls-tree[1], +which might output something like: + +------------------------------------------------ +$ git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8 +100644 blob 8d14531846b95bfa3564b58ccfb7913a034323b8 .gitignore +100644 blob ebf9bf84da0aab5ed944264a5db2a65fe3a3e883 .mailmap +100644 blob ca442d313d86dc67e0a2e5d584b465bd382cbf5c COPYING +... +100644 blob 4b9458b3786228369c63936db65827de3cc06200 myfile +... +------------------------------------------------ + +So now you know that the missing blob was the data for a file named +"myfile". And chances are you can also identify the directory--let's +say it's in "somedirectory". If you're lucky the missing copy might be +the same as the copy you have checked out in your working tree at +"somedirectory/myfile"; you can test whether that's right with +gitlink:git-hash-object[1]: + +------------------------------------------------ +$ git hash-object -w somedirectory/myfile +------------------------------------------------ + +which will create and store a blob object with the contents of +somedirectory/myfile, and output the sha1 of that object. if you're +extremely lucky it might be 4b9458b3786228369c63936db65827de3cc06200, in +which case you've guessed right, and the corruption is fixed! + +Otherwise, you need more information. How do you tell which version of +the file has been lost? + +The easiest way to do this is with: + +------------------------------------------------ +$ git log --raw --all --full-history -- somedirectory/myfile +------------------------------------------------ + +Because you're asking for raw output, you'll now get something like + +------------------------------------------------ +commit abc +Author: +Date: +... +:100644 100644 4b9458b... newsha... M somedirectory/myfile + + +commit xyz +Author: +Date: + +... +:100644 100644 oldsha... 4b9458b... M somedirectory/myfile +------------------------------------------------ + +This tells you that the immediately preceding version of the file was +"newsha", and that the immediately following version was "oldsha". +You also know the commit messages that went with the change from oldsha +to 4b9458b and with the change from 4b9458b to newsha. + +If you've been committing small enough changes, you may now have a good +shot at reconstructing the contents of the in-between state 4b9458b. + +If you can do that, you can now recreate the missing object with + +------------------------------------------------ +$ git hash-object -w <recreated-file> +------------------------------------------------ + +and your repository is good again! + +(Btw, you could have ignored the fsck, and started with doing a + +------------------------------------------------ +$ git log --raw --all +------------------------------------------------ + +and just looked for the sha of the missing object (4b9458b..) in that +whole thing. It's up to you - git does *have* a lot of information, it is +just missing one particular blob version. + [[the-index]] The index ----------- @@ -3459,7 +3706,7 @@ should use the `--remove` and `--add` flags respectively. NOTE! A `--remove` flag does 'not' mean that subsequent filenames will necessarily be removed: if the files still exist in your directory structure, the index will be updated with their new status, not -removed. The only thing `--remove` means is that update-cache will be +removed. The only thing `--remove` means is that update-index will be considering a removed file to be a valid thing, and if the file really does not exist any more, it will update the index accordingly. @@ -4308,4 +4555,7 @@ Write a chapter on using plumbing and writing scripts. Alternates, clone -reference, etc. -git unpack-objects -r for recovery +More on recovery from repository corruption. See: + http://marc.theaimsgroup.com/?l=git&m=117263864820799&w=2 + http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2 + http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2 diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 88a4acad15..85314ebd67 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.3.5.GIT +DEF_VER=v1.5.3.7.GIT LF=' ' @@ -94,6 +94,8 @@ all:: # Define OLD_ICONV if your library has an old iconv(), where the second # (input buffer pointer) parameter is declared with type (const char **). # +# Define NO_DEFLATE_BOUND if your zlib does not have deflateBound. +# # Define NO_R_TO_GCC_LINKER if your gcc does not like "-R/path/lib" # that tells runtime paths to dynamic libraries; # "-Wl,-rpath=/path/lib" is used instead. @@ -105,10 +107,12 @@ all:: # times (my ext3 doesn't). # # Define USE_STDEV below if you want git to care about the underlying device -# change being considered an inode change from the update-cache perspective. +# change being considered an inode change from the update-index perspective. # # Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8 # +# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72. +# # Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's # MakeMaker (e.g. using ActiveState under Cygwin). # @@ -637,6 +641,10 @@ ifdef OLD_ICONV BASIC_CFLAGS += -DOLD_ICONV endif +ifdef NO_DEFLATE_BOUND + BASIC_CFLAGS += -DNO_DEFLATE_BOUND +endif + ifdef PPC_SHA1 SHA1_HEADER = "ppc/sha1.h" LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o @@ -894,6 +902,7 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS) $(LIB_OBJS) $(BUILTIN_OBJS) fetch.o: $(LIB_H) $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) $(DIFF_OBJS): diffcore.h +builtin-revert.o builtin-runstatus.o wt-status.o: wt-status.h $(LIB_FILE): $(LIB_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) @@ -1 +1 @@ -Documentation/RelNotes-1.5.3.5.txt
\ No newline at end of file +Documentation/RelNotes-1.5.3.7.txt
\ No newline at end of file diff --git a/builtin-add.c b/builtin-add.c index 373f87f9f2..4fc9d6f7cc 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -17,7 +17,6 @@ static const char builtin_add_usage[] = "git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] [--] <filepattern>..."; static int take_worktree_changes; -static const char *excludes_file; static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) { @@ -57,12 +56,7 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec, memset(dir, 0, sizeof(*dir)); if (!ignored_too) { dir->collect_ignored = 1; - dir->exclude_per_dir = ".gitignore"; - path = git_path("info/exclude"); - if (!access(path, R_OK)) - add_excludes_from_file(dir, path); - if (excludes_file != NULL && !access(excludes_file, R_OK)) - add_excludes_from_file(dir, excludes_file); + setup_standard_excludes(dir); } /* @@ -123,7 +117,7 @@ static void update(int verbose, const char *prefix, const char **files) rev.diffopt.format_callback_data = &verbose; if (read_cache() < 0) die("index file corrupt"); - run_diff_files(&rev, 0); + run_diff_files(&rev, DIFF_RACY_IS_MODIFIED); } static void refresh(int verbose, const char **pathspec) @@ -144,18 +138,6 @@ static void refresh(int verbose, const char **pathspec) free(seen); } -static int git_add_config(const char *var, const char *value) -{ - if (!strcmp(var, "core.excludesfile")) { - if (!value) - die("core.excludesfile without value"); - excludes_file = xstrdup(value); - return 0; - } - - return git_default_config(var, value); -} - static struct lock_file lock_file; static const char ignore_error[] = @@ -183,7 +165,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) exit(1); } - git_config(git_add_config); + git_config(git_default_config); newfd = hold_locked_index(&lock_file, 1); diff --git a/builtin-apply.c b/builtin-apply.c index 5cc90e68f8..0fff02e0d8 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -2099,7 +2099,7 @@ static int verify_index_match(struct cache_entry *ce, struct stat *st) return -1; return 0; } - return ce_match_stat(ce, st, 1); + return ce_match_stat(ce, st, CE_MATCH_IGNORE_VALID); } static int check_patch(struct patch *patch, struct patch *prev_patch) diff --git a/builtin-branch.c b/builtin-branch.c index 5f5c1823cb..c1e9a61ea5 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -276,7 +276,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose, if (commit && !parse_commit(commit)) { pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, &subject, &subject_len, 0, - NULL, NULL, 0); + NULL, NULL, 0, 0); sub = subject; } printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color), diff --git a/builtin-bundle.c b/builtin-bundle.c index 1b650069c9..d1840555d6 100644 --- a/builtin-bundle.c +++ b/builtin-bundle.c @@ -6,6 +6,7 @@ #include "revision.h" #include "list-objects.h" #include "run-command.h" +#include "refs.h" /* * Basic handler for bundle files to connect repositories via sneakernet. @@ -253,11 +254,17 @@ static int create_bundle(struct bundle_header *header, const char *path, struct object_array_entry *e = revs.pending.objects + i; unsigned char sha1[20]; char *ref; + const char *display_ref; + int flag; if (e->item->flags & UNINTERESTING) continue; if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1) continue; + if (!resolve_ref(e->name, sha1, 1, &flag)) + flag = 0; + display_ref = (flag & REF_ISSYMREF) ? e->name : ref; + /* * Make sure the refs we wrote out is correct; --max-count and * other limiting options could have prevented all the tips @@ -308,7 +315,7 @@ static int create_bundle(struct bundle_header *header, const char *path, ref_count++; write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40); write_or_die(bundle_fd, " ", 1); - write_or_die(bundle_fd, ref, strlen(ref)); + write_or_die(bundle_fd, display_ref, strlen(display_ref)); write_or_die(bundle_fd, "\n", 1); free(ref); } diff --git a/builtin-diff.c b/builtin-diff.c index f77352b40d..f557d21929 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -200,15 +200,11 @@ static void refresh_index_quietly(void) discard_cache(); read_cache(); refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED); - if (active_cache_changed) { - if (write_cache(fd, active_cache, active_nr) || - close(fd) || - commit_locked_index(lock_file)) - ; /* - * silently ignore it -- we haven't mucked - * with the real index. - */ - } + + if (active_cache_changed && + !write_cache(fd, active_cache, active_nr) && !close(fd)) + commit_locked_index(lock_file); + rollback_lock_file(lock_file); } diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index 29f70aabc3..0327f40306 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -297,7 +297,7 @@ static const char *find_wholine(const char *who, int wholen, const char *buf, un if (!eol) return ""; eol++; - if (eol[1] == '\n') + if (*eol == '\n') return ""; /* end of header */ buf = eol; } diff --git a/builtin-grep.c b/builtin-grep.c index c7b45c4d58..bbf747fc7b 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -294,7 +294,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) if (opt->pre_context) { push_arg("-B"); len += snprintf(argptr, sizeof(randarg)-len, - "%u", opt->pre_context); + "%u", opt->pre_context) + 1; if (sizeof(randarg) <= len) die("maximum length of args exceeded"); push_arg(argptr); @@ -303,7 +303,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) if (opt->post_context) { push_arg("-A"); len += snprintf(argptr, sizeof(randarg)-len, - "%u", opt->post_context); + "%u", opt->post_context) + 1; if (sizeof(randarg) <= len) die("maximum length of args exceeded"); push_arg(argptr); @@ -313,7 +313,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) else { push_arg("-C"); len += snprintf(argptr, sizeof(randarg)-len, - "%u", opt->post_context); + "%u", opt->post_context) + 1; if (sizeof(randarg) <= len) die("maximum length of args exceeded"); push_arg(argptr); @@ -343,7 +343,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) memcpy(name + 2, ce->name, len + 1); } argv[argc++] = name; - if (argc < MAXARGS && !ce_stage(ce)) + if (argc < MAXARGS) continue; status = flush_grep(opt, argc, nr, argv, &kept); if (0 < status) diff --git a/builtin-log.c b/builtin-log.c index c6cc3aef52..070886ae57 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -795,7 +795,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) char *buf = NULL; unsigned long buflen = 0; pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, - &buf, &buflen, 0, NULL, NULL, 0); + &buf, &buflen, 0, NULL, NULL, 0, 0); printf("%c %s %s\n", sign, sha1_to_hex(commit->object.sha1), buf); free(buf); diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c index 43fc373a15..10fa177340 100644 --- a/builtin-mailsplit.c +++ b/builtin-mailsplit.c @@ -101,20 +101,29 @@ static int populate_maildir_list(struct path_list *list, const char *path) { DIR *dir; struct dirent *dent; + char name[PATH_MAX]; + char *subs[] = { "cur", "new", NULL }; + char **sub; + + for (sub = subs; *sub; ++sub) { + snprintf(name, sizeof(name), "%s/%s", path, *sub); + if ((dir = opendir(name)) == NULL) { + if (errno == ENOENT) + continue; + error("cannot opendir %s (%s)", name, strerror(errno)); + return -1; + } - if ((dir = opendir(path)) == NULL) { - error("cannot opendir %s (%s)", path, strerror(errno)); - return -1; - } + while ((dent = readdir(dir)) != NULL) { + if (dent->d_name[0] == '.') + continue; + snprintf(name, sizeof(name), "%s/%s", *sub, dent->d_name); + path_list_insert(name, list); + } - while ((dent = readdir(dir)) != NULL) { - if (dent->d_name[0] == '.') - continue; - path_list_insert(dent->d_name, list); + closedir(dir); } - closedir(dir); - return 0; } @@ -122,19 +131,17 @@ static int split_maildir(const char *maildir, const char *dir, int nr_prec, int skip) { char file[PATH_MAX]; - char curdir[PATH_MAX]; char name[PATH_MAX]; int ret = -1; int i; struct path_list list = {NULL, 0, 0, 1}; - snprintf(curdir, sizeof(curdir), "%s/cur", maildir); - if (populate_maildir_list(&list, curdir) < 0) + if (populate_maildir_list(&list, maildir) < 0) goto out; for (i = 0; i < list.nr; i++) { FILE *f; - snprintf(file, sizeof(file), "%s/%s", curdir, list.items[i].path); + snprintf(file, sizeof(file), "%s/%s", maildir, list.items[i].path); f = fopen(file, "r"); if (!f) { error("cannot open mail %s (%s)", file, strerror(errno)); @@ -152,10 +159,9 @@ static int split_maildir(const char *maildir, const char *dir, fclose(f); } - path_list_clear(&list, 1); - ret = skip; out: + path_list_clear(&list, 1); return ret; } diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 12509faa77..228040486e 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -989,7 +989,7 @@ static void add_pbase_object(struct tree_desc *tree, return; if (name[cmplen] != '/') { add_object_entry(entry.sha1, - S_ISDIR(entry.mode) ? OBJ_TREE : OBJ_BLOB, + object_type(entry.mode), fullname, 1); return; } diff --git a/builtin-rev-list.c b/builtin-rev-list.c index ac551d59f3..9dbfae416c 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -84,7 +84,7 @@ static void show_commit(struct commit *commit) unsigned long buflen = 0; pretty_print_commit(revs.commit_format, commit, ~0, &buf, &buflen, - revs.abbrev, NULL, NULL, revs.date_mode); + revs.abbrev, NULL, NULL, revs.date_mode, 0); printf("%s%c", buf, hdr_termination); free(buf); } diff --git a/builtin-revert.c b/builtin-revert.c index eafafbc333..94e77771d2 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -264,7 +264,7 @@ static int revert_or_cherry_pick(int argc, const char **argv) if (get_sha1("HEAD", head)) die ("You do not have a valid HEAD"); wt_status_prepare(&s); - if (s.commitable || s.workdir_dirty) + if (s.commitable) die ("Dirty index: cannot %s", me); discard_cache(); } diff --git a/builtin-show-branch.c b/builtin-show-branch.c index 4fa87f6081..b9cf1b379f 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -267,7 +267,7 @@ static void show_one_commit(struct commit *commit, int no_name) if (commit->object.parsed) { pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, &pretty, &pretty_len, - 0, NULL, NULL, 0); + 0, NULL, NULL, 0, 0); pretty_str = pretty; } if (!prefixcmp(pretty_str, "[PATCH] ")) @@ -6,7 +6,7 @@ #include SHA1_HEADER #include <zlib.h> -#if ZLIB_VERNUM < 0x1200 +#if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200 #define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) #endif @@ -174,8 +174,8 @@ extern struct index_state the_index; #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path)) #define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose)) #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL) -#define ce_match_stat(ce, st, really) ie_match_stat(&the_index, (ce), (st), (really)) -#define ce_modified(ce, st, really) ie_modified(&the_index, (ce), (st), (really)) +#define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options)) +#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options)) #endif enum object_type { @@ -266,8 +266,14 @@ extern int remove_file_from_index(struct index_state *, const char *path); extern int add_file_to_index(struct index_state *, const char *path, int verbose); extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh); extern int ce_same_name(struct cache_entry *a, struct cache_entry *b); -extern int ie_match_stat(struct index_state *, struct cache_entry *, struct stat *, int); -extern int ie_modified(struct index_state *, struct cache_entry *, struct stat *, int); + +/* do stat comparison even if CE_VALID is true */ +#define CE_MATCH_IGNORE_VALID 01 +/* do not check the contents but report dirty on racily-clean entries */ +#define CE_MATCH_RACY_IS_DIRTY 02 +extern int ie_match_stat(struct index_state *, struct cache_entry *, struct stat *, unsigned int); +extern int ie_modified(struct index_state *, struct cache_entry *, struct stat *, unsigned int); + extern int ce_path_match(const struct cache_entry *ce, const char **pathspec); extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path); extern int read_fd(int fd, char **return_buf, unsigned long *return_size); @@ -571,6 +577,7 @@ extern int pager_in_use; extern int pager_use_color; extern char *editor_program; +extern char *excludes_file; /* base85 */ int decode_85(char *dst, const char *line, int linelen); diff --git a/check-racy.c b/check-racy.c index d6a08b4a55..00d92a1663 100644 --- a/check-racy.c +++ b/check-racy.c @@ -18,7 +18,7 @@ int main(int ac, char **av) if (ce_match_stat(ce, &st, 0)) dirty++; - else if (ce_match_stat(ce, &st, 2)) + else if (ce_match_stat(ce, &st, CE_MATCH_RACY_IS_DIRTY)) racy++; else clean++; @@ -479,7 +479,7 @@ static int get_one_line(const char *msg, unsigned long len) } /* High bit set, or ISO-2022-INT */ -static int non_ascii(int ch) +int non_ascii(int ch) { ch = (ch & 0xff); return ((ch & 0x80) || (ch == 0x1b)); @@ -1158,13 +1158,13 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, - enum date_mode dmode) + enum date_mode dmode, + int plain_non_ascii) { unsigned long offset = 0; unsigned long beginning_of_body; int indent = 4; const char *msg = commit->buffer; - int plain_non_ascii = 0; char *reencoded; const char *encoding; char *buf; @@ -60,8 +60,9 @@ enum cmit_fmt { CMIT_FMT_UNSPECIFIED, }; +extern int non_ascii(int); extern enum cmit_fmt get_commit_format(const char *arg); -extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode); +extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode, int non_ascii_present); /** Removes the first commit from a list sorted by date, and adds all * of its parents. diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c index 4d7ab9d975..f44498258d 100644 --- a/compat/inet_ntop.c +++ b/compat/inet_ntop.c @@ -18,7 +18,6 @@ #include <errno.h> #include <sys/types.h> #include <sys/socket.h> -#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> diff --git a/compat/inet_pton.c b/compat/inet_pton.c index 5704e0d2b6..4078fc0877 100644 --- a/compat/inet_pton.c +++ b/compat/inet_pton.c @@ -18,7 +18,6 @@ #include <errno.h> #include <sys/types.h> #include <sys/socket.h> -#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> @@ -431,6 +431,13 @@ int git_default_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.excludesfile")) { + if (!value) + die("core.excludesfile without value"); + excludes_file = xstrdup(value); + return 0; + } + /* Add other config variables here and to Documentation/config.txt. */ return 0; } diff --git a/config.mak.in b/config.mak.in index a3032e389f..776b805659 100644 --- a/config.mak.in +++ b/config.mak.in @@ -38,3 +38,4 @@ NO_STRCASESTR=@NO_STRCASESTR@ NO_STRLCPY=@NO_STRLCPY@ NO_SETENV=@NO_SETENV@ NO_ICONV=@NO_ICONV@ +NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@ diff --git a/configure.ac b/configure.ac index ed7cc895d2..8dfe9a0e12 100644 --- a/configure.ac +++ b/configure.ac @@ -182,6 +182,26 @@ AC_SUBST(NEEDS_LIBICONV) AC_SUBST(NO_ICONV) test -n "$NEEDS_LIBICONV" && LIBS="$LIBS -liconv" # +# Define NO_DEFLATE_BOUND if deflateBound is missing from zlib. +AC_DEFUN([ZLIBTEST_SRC], [ +#include <zlib.h> + +int main(void) +{ + deflateBound(0, 0); + return 0; +} +]) +AC_MSG_CHECKING([for deflateBound in -lz]) +old_LIBS="$LIBS" +LIBS="$LIBS -lz" +AC_LINK_IFELSE(ZLIBTEST_SRC, + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + NO_DEFLATE_BOUND=yes]) +LIBS="$old_LIBS" +AC_SUBST(NO_DEFLATE_BOUND) +# # Define NEEDS_SOCKET if linking with libc is not enough (SunOS, # Patrick Mauritz). AC_CHECK_LIB([c], [socket], @@ -377,7 +397,7 @@ GIT_PARSE_WITH(iconv)) # times (my ext3 doesn't). # # Define USE_STDEV below if you want git to care about the underlying device -# change being considered an inode change from the update-cache perspective. +# change being considered an inode change from the update-index perspective. ## Output files @@ -540,7 +540,7 @@ static int execute(struct sockaddr *addr) if (addr->sa_family == AF_INET) { struct sockaddr_in *sin_addr = (void *) addr; inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf)); - port = sin_addr->sin_port; + port = ntohs(sin_addr->sin_port); #ifndef NO_IPV6 } else if (addr && addr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6_addr = (void *) addr; @@ -550,7 +550,7 @@ static int execute(struct sockaddr *addr) inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1); strcat(buf, "]"); - port = sin6_addr->sin6_port; + port = ntohs(sin6_addr->sin6_port); #endif } loginfo("Connection from %s:%d", addrbuf, port); diff --git a/diff-lib.c b/diff-lib.c index da5571302d..ec1b5e3d44 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -173,9 +173,10 @@ static int is_in_index(const char *path) } static int handle_diff_files_args(struct rev_info *revs, - int argc, const char **argv, int *silent) + int argc, const char **argv, + unsigned int *options) { - *silent = 0; + *options = 0; /* revs->max_count == -2 means --no-index */ while (1 < argc && argv[1][0] == '-') { @@ -192,7 +193,7 @@ static int handle_diff_files_args(struct rev_info *revs, revs->diffopt.no_index = 1; } else if (!strcmp(argv[1], "-q")) - *silent = 1; + *options |= DIFF_SILENT_ON_REMOVED; else return error("invalid option: %s", argv[1]); argv++; argc--; @@ -305,9 +306,9 @@ int setup_diff_no_index(struct rev_info *revs, int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv) { - int silent_on_removed; + unsigned int options; - if (handle_diff_files_args(revs, argc, argv, &silent_on_removed)) + if (handle_diff_files_args(revs, argc, argv, &options)) return -1; if (revs->diffopt.no_index) { @@ -329,13 +330,16 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv) perror("read_cache"); return -1; } - return run_diff_files(revs, silent_on_removed); + return run_diff_files(revs, options); } -int run_diff_files(struct rev_info *revs, int silent_on_removed) +int run_diff_files(struct rev_info *revs, unsigned int option) { int entries, i; int diff_unmerged_stage = revs->max_count; + int silent_on_removed = option & DIFF_SILENT_ON_REMOVED; + unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED) + ? CE_MATCH_RACY_IS_DIRTY : 0); if (diff_unmerged_stage < 0) diff_unmerged_stage = 2; @@ -441,7 +445,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed) ce->sha1, ce->name, NULL); continue; } - changed = ce_match_stat(ce, &st, 0); + changed = ce_match_stat(ce, &st, ce_option); if (!changed && !revs->diffopt.find_copies_harder) continue; oldmode = ntohl(ce->ce_mode); @@ -224,7 +224,11 @@ extern void diff_flush(struct diff_options*); extern const char *diff_unique_abbrev(const unsigned char *, int); -extern int run_diff_files(struct rev_info *revs, int silent_on_removed); +/* do not report anything on removed paths */ +#define DIFF_SILENT_ON_REMOVED 01 +/* report racily-clean paths as modified */ +#define DIFF_RACY_IS_MODIFIED 02 +extern int run_diff_files(struct rev_info *revs, unsigned int option); extern int setup_diff_no_index(struct rev_info *revs, int argc, const char ** argv, int nongit, const char *prefix); extern int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv); @@ -626,6 +626,7 @@ static void free_simplify(struct path_simplify *simplify) int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec) { struct path_simplify *simplify = create_simplify(pathspec); + char *pp = NULL; /* * Make sure to do the per-directory exclude for all the @@ -633,7 +634,8 @@ int read_directory(struct dir_struct *dir, const char *path, const char *base, i */ if (baselen) { if (dir->exclude_per_dir) { - char *p, *pp = xmalloc(baselen+1); + char *p; + pp = xmalloc(baselen+1); memcpy(pp, base, baselen+1); p = pp; while (1) { @@ -649,12 +651,12 @@ int read_directory(struct dir_struct *dir, const char *path, const char *base, i else p = pp + baselen; } - free(pp); } } read_directory_recursive(dir, path, base, baselen, 0, simplify); free_simplify(simplify); + free(pp); qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name); qsort(dir->ignored, dir->ignored_nr, sizeof(struct dir_entry *), cmp_name); return dir->nr; @@ -709,3 +711,15 @@ int is_inside_dir(const char *dir) char buffer[PATH_MAX]; return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL; } + +void setup_standard_excludes(struct dir_struct *dir) +{ + const char *path; + + dir->exclude_per_dir = ".gitignore"; + path = git_path("info/exclude"); + if (!access(path, R_OK)) + add_excludes_from_file(dir, path); + if (excludes_file && !access(excludes_file, R_OK)) + add_excludes_from_file(dir, excludes_file); +} @@ -64,4 +64,6 @@ extern struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna extern char *get_relative_cwd(char *buffer, int size, const char *dir); extern int is_inside_dir(const char *dir); +extern void setup_standard_excludes(struct dir_struct *dir); + #endif @@ -200,7 +200,7 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t strcpy(path + len, ce->name); if (!lstat(path, &st)) { - unsigned changed = ce_match_stat(ce, &st, 1); + unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID); if (!changed) return 0; if (!state->force) { diff --git a/environment.c b/environment.c index b5a6c69f7c..1dab72ec15 100644 --- a/environment.c +++ b/environment.c @@ -34,6 +34,7 @@ char *pager_program; int pager_in_use; int pager_use_color = 1; char *editor_program; +char *excludes_file; int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */ /* This is set by setup_git_dir_gently() and/or git_default_config() */ diff --git a/fast-import.c b/fast-import.c index c07e3d8ef0..5e83296bf4 100644 --- a/fast-import.c +++ b/fast-import.c @@ -154,13 +154,16 @@ Format of STDIN stream: #define PACK_ID_BITS 16 #define MAX_PACK_ID ((1<<PACK_ID_BITS)-1) +#define DEPTH_BITS 13 +#define MAX_DEPTH ((1<<DEPTH_BITS)-1) struct object_entry { struct object_entry *next; uint32_t offset; - unsigned type : TYPE_BITS; - unsigned pack_id : PACK_ID_BITS; + uint32_t type : TYPE_BITS, + pack_id : PACK_ID_BITS, + depth : DEPTH_BITS; unsigned char sha1[20]; }; @@ -1105,7 +1108,7 @@ static int store_object( unsigned pos = sizeof(hdr) - 1; delta_count_by_type[type]++; - last->depth++; + e->depth = last->depth + 1; hdrlen = encode_header(OBJ_OFS_DELTA, deltalen, hdr); write_or_die(pack_data->pack_fd, hdr, hdrlen); @@ -1117,8 +1120,7 @@ static int store_object( write_or_die(pack_data->pack_fd, hdr + pos, sizeof(hdr) - pos); pack_size += sizeof(hdr) - pos; } else { - if (last) - last->depth = 0; + e->depth = 0; hdrlen = encode_header(type, datlen, hdr); write_or_die(pack_data->pack_fd, hdr, hdrlen); pack_size += hdrlen; @@ -1134,6 +1136,7 @@ static int store_object( free(last->data); last->data = dat; last->offset = e->offset; + last->depth = e->depth; last->len = datlen; } return 0; @@ -1181,7 +1184,7 @@ static void load_tree(struct tree_entry *root) if (myoe && myoe->pack_id != MAX_PACK_ID) { if (myoe->type != OBJ_TREE) die("Not a tree: %s", sha1_to_hex(sha1)); - t->delta_depth = 0; + t->delta_depth = myoe->depth; buf = gfi_unpack_entry(myoe, &size); } else { enum object_type type; @@ -2347,8 +2350,11 @@ int main(int argc, const char **argv) } else if (!prefixcmp(a, "--max-pack-size=")) max_packsize = strtoumax(a + 16, NULL, 0) * 1024 * 1024; - else if (!prefixcmp(a, "--depth=")) + else if (!prefixcmp(a, "--depth=")) { max_depth = strtoul(a + 8, NULL, 0); + if (max_depth > MAX_DEPTH) + die("--depth cannot exceed %u", MAX_DEPTH); + } else if (!prefixcmp(a, "--active-branches=")) max_active_branches = strtoul(a + 18, NULL, 0); else if (!prefixcmp(a, "--import-marks=")) @@ -214,7 +214,7 @@ fi case "$resolved" in '') - files=$(git diff-index --cached --name-only HEAD) || exit + files=$(git diff-index --cached --name-only HEAD --) || exit if [ "$files" ]; then echo "Dirty index: cannot apply patches (dirty: $files)" >&2 exit 1 @@ -348,7 +348,7 @@ do case "$resolved$interactive" in tt) # This is used only for interactive view option. - git diff-index -p --cached HEAD >"$dotest/patch" + git diff-index -p --cached HEAD -- >"$dotest/patch" ;; esac esac @@ -409,7 +409,7 @@ do # trust what the user has in the index file and the # working tree. resolved= - git diff-index --quiet --cached HEAD && { + git diff-index --quiet --cached HEAD -- && { echo "No changes - did you forget to use 'git add'?" stop_here_user_resolve $this } @@ -431,7 +431,7 @@ do then # Applying the patch to an earlier tree and merging the # result may have produced the same tree as ours. - git diff-index --quiet --cached HEAD && { + git diff-index --quiet --cached HEAD -- && { echo No changes -- Patch already applied. go_next continue diff --git a/git-checkout.sh b/git-checkout.sh index 17f43927aa..5ca71242e7 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -169,7 +169,7 @@ detach_warn= describe_detached_head () { test -n "$quiet" || { printf >&2 "$1 " - GIT_PAGER= git log >&2 -1 --pretty=oneline --abbrev-commit "$2" + GIT_PAGER= git log >&2 -1 --pretty=oneline --abbrev-commit "$2" -- } } diff --git a/git-clean.sh b/git-clean.sh index 4491738186..931d1aa4e4 100755 --- a/git-clean.sh +++ b/git-clean.sh @@ -75,15 +75,22 @@ esac if [ -z "$ignored" ]; then excl="--exclude-per-directory=.gitignore" + excl_info= excludes_file= if [ -f "$GIT_DIR/info/exclude" ]; then excl_info="--exclude-from=$GIT_DIR/info/exclude" fi + if cfg_excl=$(git config core.excludesfile) && test -f "$cfg_excl" + then + excludes_file="--exclude-from=$cfg_excl" + fi if [ "$ignoredonly" ]; then excl="$excl --ignored" fi fi -git ls-files --others --directory $excl ${excl_info:+"$excl_info"} -- "$@" | +git ls-files --others --directory \ + $excl ${excl_info:+"$excl_info"} ${excludes_file:+"$excludes_file"} \ + -- "$@" | while read -r file; do if [ -d "$file" -a ! -L "$file" ]; then if [ -z "$cleandir" ]; then diff --git a/git-commit.sh b/git-commit.sh index ab43217be4..1c0c6b9e41 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -26,7 +26,7 @@ refuse_partial () { } TMP_INDEX= -THIS_INDEX="$GIT_DIR/index" +THIS_INDEX="${GIT_INDEX_FILE:-$GIT_DIR/index}" NEXT_INDEX="$GIT_DIR/next-index$$" rm -f "$NEXT_INDEX" save_index () { @@ -322,9 +322,9 @@ unset only case "$all,$interactive,$also,$#" in *t,*t,*) die "Cannot use -a, --interactive or -i at the same time." ;; -t,,[1-9]*) +t,,,[1-9]*) die "Paths with -a does not make sense." ;; -,t,[1-9]*) +,t,,[1-9]*) die "Paths with --interactive does not make sense." ;; ,,t,0) die "No paths with -i does not make sense." ;; diff --git a/git-cvsimport.perl b/git-cvsimport.perl index e4bc2b54f6..d565091c35 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -108,10 +108,6 @@ sub read_repo_config { } } } - if (@ARGV == 0) { - chomp(my $module = `git-repo-config --get cvsimport.module`); - push(@ARGV, $module); - } } my $opts = "haivmkuo:d:p:r:C:z:s:M:P:A:S:L:"; @@ -119,6 +115,10 @@ read_repo_config($opts); getopts($opts) or usage(); usage if $opt_h; +if (@ARGV == 0) { + chomp(my $module = `git-repo-config --get cvsimport.module`); + push(@ARGV, $module) if $? == 0; +} @ARGV <= 1 or usage("You can't specify more than one CVS module"); if ($opt_d) { @@ -526,18 +526,12 @@ sub is_sha1 { return $s =~ /^[a-f0-9]{40}$/; } -sub get_headref ($$) { - my $name = shift; - my $git_dir = shift; - - my $f = "$git_dir/$remote/$name"; - if (open(my $fh, $f)) { - chomp(my $r = <$fh>); - is_sha1($r) or die "Cannot get head id for $name ($r): $!"; - return $r; - } - die "unable to open $f: $!" unless $! == POSIX::ENOENT; - return undef; +sub get_headref ($) { + my $name = shift; + my $r = `git rev-parse --verify '$name' 2>/dev/null`; + return undef unless $? == 0; + chomp $r; + return $r; } -d $git_tree @@ -697,7 +691,8 @@ my (@old,@new,@skipped,%ignorebranch); $ignorebranch{'#CVSPS_NO_BRANCH'} = 1; sub commit { - if ($branch eq $opt_o && !$index{branch} && !get_headref($branch, $git_dir)) { + if ($branch eq $opt_o && !$index{branch} && + !get_headref("$remote/$branch")) { # looks like an initial commit # use the index primed by git-init $ENV{GIT_INDEX_FILE} = "$git_dir/index"; @@ -721,7 +716,7 @@ sub commit { update_index(@old, @new); @old = @new = (); my $tree = write_tree(); - my $parent = get_headref($last_branch, $git_dir); + my $parent = get_headref("$remote/$last_branch"); print "Parent ID " . ($parent ? $parent : "(empty)") . "\n" if $opt_v; my @commit_args; @@ -732,7 +727,7 @@ sub commit { foreach my $rx (@mergerx) { next unless $logmsg =~ $rx && $1; my $mparent = $1 eq 'HEAD' ? $opt_o : $1; - if (my $sha1 = get_headref($mparent, $git_dir)) { + if (my $sha1 = get_headref("$remote/$mparent")) { push @commit_args, '-p', $mparent; print "Merge parent branch: $mparent\n" if $opt_v; } @@ -869,29 +864,27 @@ while (<CVS>) { print STDERR "Branch $branch erroneously stems from itself -- changed ancestor to $opt_o\n"; $ancestor = $opt_o; } - if (-f "$git_dir/$remote/$branch") { + if (defined get_headref("$remote/$branch")) { print STDERR "Branch $branch already exists!\n"; $state=11; next; } - unless (open(H,"$git_dir/$remote/$ancestor")) { + my $id = get_headref("$remote/$ancestor"); + if (!$id) { print STDERR "Branch $ancestor does not exist!\n"; $ignorebranch{$branch} = 1; $state=11; next; } - chomp(my $id = <H>); - close(H); - unless (open(H,"> $git_dir/$remote/$branch")) { - print STDERR "Could not create branch $branch: $!\n"; + + system(qw(git update-ref -m cvsimport), + "$remote/$branch", $id); + if($? != 0) { + print STDERR "Could not create branch $branch\n"; $ignorebranch{$branch} = 1; $state=11; next; } - print H "$id\n" - or die "Could not write branch $branch: $!"; - close(H) - or die "Could not write branch $branch: $!"; } $last_branch = $branch if $branch ne $last_branch; $state = 9; @@ -1003,7 +996,7 @@ if ($orig_branch) { $orig_branch = "master"; print "DONE; creating $orig_branch branch\n" if $opt_v; system("git-update-ref", "refs/heads/master", "$remote/$opt_o") - unless -f "$git_dir/refs/heads/master"; + unless defined get_headref('refs/heads/master'); system("git-symbolic-ref", "$remote/HEAD", "$remote/$opt_o") if ($opt_r && $opt_o ne 'HEAD'); system('git-update-ref', 'HEAD', "$orig_branch"); diff --git a/git-filter-branch.sh b/git-filter-branch.sh index ffcc408ee5..dbab1a9a4a 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -95,7 +95,7 @@ USAGE="[--env-filter <command>] [--tree-filter <command>] \ . git-sh-setup git diff-files --quiet && - git diff-index --cached --quiet HEAD || + git diff-index --cached --quiet HEAD -- || die "Cannot rewrite branch(es) with a dirty working directory." tempdir=.git-rewrite diff --git a/git-instaweb.sh b/git-instaweb.sh index 41ff08f8e4..2ca487d7d5 100755 --- a/git-instaweb.sh +++ b/git-instaweb.sh @@ -15,7 +15,7 @@ browser="`git config --get instaweb.browser`" port=`git config --get instaweb.port` module_path="`git config --get instaweb.modulepath`" -conf=$GIT_DIR/gitweb/httpd.conf +conf="$GIT_DIR/gitweb/httpd.conf" # Defaults: @@ -32,7 +32,7 @@ start_httpd () { httpd_only="`echo $httpd | cut -f1 -d' '`" if case "$httpd_only" in /*) : ;; *) which $httpd_only >/dev/null;; esac then - $httpd $fqgitdir/gitweb/httpd.conf + $httpd "$fqgitdir/gitweb/httpd.conf" else # many httpds are installed in /usr/sbin or /usr/local/sbin # these days and those are not in most users $PATHs @@ -146,14 +146,14 @@ server.pid-file = "$fqgitdir/pid" cgi.assign = ( ".cgi" => "" ) mimetype.assign = ( ".css" => "text/css" ) EOF - test "$local" = true && echo 'server.bind = "127.0.0.1"' >> "$conf" + test x"$local" = xtrue && echo 'server.bind = "127.0.0.1"' >> "$conf" } apache2_conf () { test -z "$module_path" && module_path=/usr/lib/apache2/modules mkdir -p "$GIT_DIR/gitweb/logs" bind= - test "$local" = true && bind='127.0.0.1:' + test x"$local" = xtrue && bind='127.0.0.1:' echo 'text/css css' > $fqgitdir/mime.types cat > "$conf" <<EOF ServerName "git-instaweb" @@ -206,7 +206,7 @@ EOF } script=' -s#^\(my\|our\) $projectroot =.*#\1 $projectroot = "'`dirname $fqgitdir`'";# +s#^\(my\|our\) $projectroot =.*#\1 $projectroot = "'$(dirname "$fqgitdir")'";# s#\(my\|our\) $gitbin =.*#\1 $gitbin = "'$GIT_EXEC_PATH'";# s#\(my\|our\) $projects_list =.*#\1 $projects_list = $projectroot;# s#\(my\|our\) $git_temp =.*#\1 $git_temp = "'$fqgitdir/gitweb/tmp'";#' @@ -226,8 +226,8 @@ gitweb_css () { EOFGITWEB } -gitweb_cgi $GIT_DIR/gitweb/gitweb.cgi -gitweb_css $GIT_DIR/gitweb/gitweb.css +gitweb_cgi "$GIT_DIR/gitweb/gitweb.cgi" +gitweb_css "$GIT_DIR/gitweb/gitweb.css" case "$httpd" in *lighttpd*) @@ -243,6 +243,5 @@ case "$httpd" in esac start_httpd -test -z "$browser" && browser=echo url=http://127.0.0.1:$port -$browser $url || echo $url +"$browser" $url || echo $url diff --git a/git-merge-ours.sh b/git-merge-ours.sh index c81a790aa6..29dba4ba3a 100755 --- a/git-merge-ours.sh +++ b/git-merge-ours.sh @@ -9,6 +9,6 @@ # because the current index is what we will be committing as the # merge result. -git diff-index --quiet --cached HEAD || exit 2 +git diff-index --quiet --cached HEAD -- || exit 2 exit 0 diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index f28c3df204..ff38a22edf 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -52,7 +52,7 @@ require_clean_work_tree () { git rev-parse --verify HEAD > /dev/null && git update-index --refresh && git diff-files --quiet && - git diff-index --cached --quiet HEAD || + git diff-index --cached --quiet HEAD -- || die "Working tree is dirty" } @@ -331,7 +331,7 @@ do git rev-parse --verify HEAD > /dev/null && git update-index --refresh && git diff-files --quiet && - ! git diff-index --cached --quiet HEAD && + ! git diff-index --cached --quiet HEAD -- && . "$DOTEST"/author-script && export GIT_AUTHOR_NAME GIT_AUTHOR_NAME GIT_AUTHOR_DATE && git commit -F "$DOTEST"/message -e @@ -361,7 +361,7 @@ do -s|--strategy) case "$#,$1" in *,*=*) - STRATEGY="-s `expr "z$1" : 'z-[^=]*=\(.*\)'`" ;; + STRATEGY="-s "$(expr "z$1" : 'z-[^=]*=\(.*\)') ;; 1,*) usage ;; *) diff --git a/git-rebase.sh b/git-rebase.sh index b0c8ac1c8d..c9b284c751 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -60,7 +60,7 @@ continue_merge () { fi cmt=`cat "$dotest/current"` - if ! git diff-index --quiet HEAD + if ! git diff-index --quiet HEAD -- then if ! git-commit -C "$cmt" then @@ -253,7 +253,7 @@ fi # The tree must be really really clean. git update-index --refresh || exit -diff=$(git diff-index --cached --name-status -r HEAD) +diff=$(git diff-index --cached --name-status -r HEAD --) case "$diff" in ?*) echo "cannot rebase: your index is not up-to-date" echo "$diff" diff --git a/git-request-pull.sh b/git-request-pull.sh index a992430679..95ad66630f 100755 --- a/git-request-pull.sh +++ b/git-request-pull.sh @@ -24,13 +24,13 @@ headrev=`git rev-parse --verify "$head"^0` || exit merge_base=`git merge-base $baserev $headrev` || die "fatal: No commits in common between $base and $head" -url="`get_remote_url "$url"`" -branch=`git peek-remote "$url" \ +url=$(get_remote_url "$url") +branch=$(git peek-remote "$url" \ | sed -n -e "/^$headrev refs.heads./{ s/^.* refs.heads.// p q - }"` + }") if [ -z "$branch" ]; then echo "warn: No branch of $url is at:" >&2 git log --max-count=1 --pretty='format:warn: %h: %s' $headrev >&2 diff --git a/git-send-email.perl b/git-send-email.perl index 9547cc37a1..b03297c9d7 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -303,7 +303,7 @@ sub expand_aliases { if (!defined $initial_subject && $compose) { do { - $_ = $term->readline("What subject should the emails start with? ", + $_ = $term->readline("What subject should the initial email start with? ", $initial_subject); } while (!defined $_); $initial_subject = $_; @@ -468,11 +468,13 @@ $time = time - scalar $#files; sub unquote_rfc2047 { local ($_) = @_; - if (s/=\?utf-8\?q\?(.*)\?=/$1/g) { + my $encoding; + if (s/=\?([^?]+)\?q\?(.*)\?=/$2/g) { + $encoding = $1; s/_/ /g; s/=([0-9A-F]{2})/chr(hex($1))/eg; } - return "$_"; + return wantarray ? ($_, $encoding) : $_; } # use the simplest quoting being able to handle the recipient @@ -599,6 +601,9 @@ foreach my $t (@files) { open(F,"<",$t) or die "can't open file $t"; my $author = undef; + my $author_encoding; + my $has_content_type; + my $body_encoding; @cc = @initial_cc; @xh = (); my $input_format = undef; @@ -624,12 +629,20 @@ foreach my $t (@files) { next if ($suppress_from); } elsif ($1 eq 'From') { - $author = unquote_rfc2047($2); + ($author, $author_encoding) + = unquote_rfc2047($2); } printf("(mbox) Adding cc: %s from line '%s'\n", $2, $_) unless $quiet; push @cc, $2; } + elsif (/^Content-type:/i) { + $has_content_type = 1; + if (/charset="?[^ "]+/) { + $body_encoding = $1; + } + push @xh, $_; + } elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) { push @xh, $_; } @@ -686,6 +699,22 @@ foreach my $t (@files) { if (defined $author) { $message = "From: $author\n\n$message"; + if (defined $author_encoding) { + if ($has_content_type) { + if ($body_encoding eq $author_encoding) { + # ok, we already have the right encoding + } + else { + # uh oh, we should re-encode + } + } + else { + push @xh, + 'MIME-Version: 1.0', + "Content-Type: text/plain; charset=$author_encoding", + 'Content-Transfer-Encoding: 8bit'; + } + } } send_message(); diff --git a/git-stash.sh b/git-stash.sh index 5bbda47b7b..77c94210b7 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -14,7 +14,7 @@ trap 'rm -f "$TMP-*"' 0 ref_stash=refs/stash no_changes () { - git diff-index --quiet --cached HEAD && + git diff-index --quiet --cached HEAD -- && git diff-files --quiet } diff --git a/git-submodule.sh b/git-submodule.sh index 673aa27a45..b91d62632c 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -47,7 +47,7 @@ get_repo_base() { module_name() { # Do we have "submodule.<something>.path = $1" defined in .gitmodules file? - re=$(printf '%s' "$1" | sed -e 's/\([^a-zA-Z0-9_]\)/\\\1/g') + re=$(printf '%s' "$1" | sed -e 's/[].[^$\\*]/\\&/g') name=$( GIT_CONFIG=.gitmodules \ git config --get-regexp '^submodule\..*\.path$' | sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' ) diff --git a/git-svn.perl b/git-svn.perl index c015ea8580..4c779b6c6d 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -374,6 +374,9 @@ sub cmd_set_tree { sub cmd_dcommit { my $head = shift; + git_cmd_try { command_oneline(qw/diff-index --quiet HEAD/) } + 'Cannot dcommit with a dirty index. Commit your changes first' + . "or stash them with `git stash'.\n"; $head ||= 'HEAD'; my @refs; my ($url, $rev, $uuid, $gs) = working_head_info($head, \@refs); @@ -390,7 +393,8 @@ sub cmd_dcommit { "If these changes depend on each other, re-running ", "without --no-rebase will be required." } - foreach my $d (@$linear_refs) { + while (1) { + my $d = shift @$linear_refs or last; unless (defined $last_rev) { (undef, $last_rev, undef) = cmt_metadata("$d~1"); unless (defined $last_rev) { @@ -423,14 +427,14 @@ sub cmd_dcommit { # we always want to rebase against the current HEAD, # not any head that was passed to us - my @diff = command('diff-tree', 'HEAD', + my @diff = command('diff-tree', $d, $gs->refname, '--'); my @finish; if (@diff) { @finish = rebase_cmd(); - print STDERR "W: HEAD and ", $gs->refname, + print STDERR "W: $d and ", $gs->refname, " differ, using @finish:\n", - "@diff"; + join("\n", @diff), "\n"; } else { print "No changes between current HEAD and ", $gs->refname, @@ -439,6 +443,45 @@ sub cmd_dcommit { @finish = qw/reset --mixed/; } command_noisy(@finish, $gs->refname); + if (@diff) { + @refs = (); + my ($url_, $rev_, $uuid_, $gs_) = + working_head_info($head, \@refs); + my ($linear_refs_, $parents_) = + linearize_history($gs_, \@refs); + if (scalar(@$linear_refs) != + scalar(@$linear_refs_)) { + fatal "# of revisions changed ", + "\nbefore:\n", + join("\n", @$linear_refs), + "\n\nafter:\n", + join("\n", @$linear_refs_), "\n", + 'If you are attempting to commit ', + "merges, try running:\n\t", + 'git rebase --interactive', + '--preserve-merges ', + $gs->refname, + "\nBefore dcommitting"; + } + if ($url_ ne $url) { + fatal "URL mismatch after rebase: ", + "$url_ != $url"; + } + if ($uuid_ ne $uuid) { + fatal "uuid mismatch after rebase: ", + "$uuid_ != $uuid"; + } + # remap parents + my (%p, @l, $i); + for ($i = 0; $i < scalar @$linear_refs; $i++) { + my $new = $linear_refs_->[$i] or next; + $p{$new} = + $parents->{$linear_refs->[$i]}; + push @l, $new; + } + $parents = \%p; + $linear_refs = \@l; + } $last_rev = $cmt_rev; } } diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3064298f28..9deefce0a6 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1713,7 +1713,7 @@ sub parse_date { $date{'mday-time'} = sprintf "%d %s %02d:%02d", $mday, $months[$mon], $hour ,$min; $date{'iso-8601'} = sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ", - 1900+$year, $mon, $mday, $hour ,$min, $sec; + 1900+$year, 1+$mon, $mday, $hour ,$min, $sec; $tz =~ m/^([+\-][0-9][0-9])([0-9][0-9])$/; my $local = $epoch + ((int $1 + ($2/60)) * 3600); diff --git a/hash-object.c b/hash-object.c index 18f5017f51..0a58f3f126 100644 --- a/hash-object.c +++ b/hash-object.c @@ -42,6 +42,8 @@ int main(int argc, char **argv) int prefix_length = -1; int no_more_flags = 0; + git_config(git_default_config); + for (i = 1 ; i < argc; i++) { if (!no_more_flags && argv[i][0] == '-') { if (!strcmp(argv[i], "-t")) { diff --git a/index-pack.c b/index-pack.c index db58e05041..c232e3fc78 100644 --- a/index-pack.c +++ b/index-pack.c @@ -254,7 +254,7 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_ static void *get_data_from_pack(struct object_entry *obj) { - unsigned long from = obj[0].idx.offset + obj[0].hdr_size; + off_t from = obj[0].idx.offset + obj[0].hdr_size; unsigned long len = obj[1].idx.offset - from; unsigned long rdy = 0; unsigned char *src, *data; diff --git a/list-objects.c b/list-objects.c index e5c88c278f..4ef58e7ec0 100644 --- a/list-objects.c +++ b/list-objects.c @@ -170,4 +170,11 @@ void traverse_commit_list(struct rev_info *revs, } for (i = 0; i < objects.nr; i++) show_object(&objects.objects[i]); + free(objects.objects); + if (revs->pending.nr) { + free(revs->pending.objects); + revs->pending.nr = 0; + revs->pending.alloc = 0; + revs->pending.objects = NULL; + } } diff --git a/log-tree.c b/log-tree.c index b509c0c7ec..9ebc24b687 100644 --- a/log-tree.c +++ b/log-tree.c @@ -140,6 +140,18 @@ static unsigned int digits_in_number(unsigned int number) return result; } +static int has_non_ascii(const char *s) +{ + int ch; + if (!s) + return 0; + while ((ch = *s++) != '\0') { + if (non_ascii(ch)) + return 1; + } + return 0; +} + void show_log(struct rev_info *opt, const char *sep) { char *msgbuf = NULL; @@ -290,7 +302,8 @@ void show_log(struct rev_info *opt, const char *sep) */ len = pretty_print_commit(opt->commit_format, commit, ~0u, &msgbuf, &msgbuf_len, abbrev, subject, - extra_headers, opt->date_mode); + extra_headers, opt->date_mode, + has_non_ascii(opt->add_signoff)); if (opt->add_signoff) len = append_signoff(&msgbuf, &msgbuf_len, len, diff --git a/perl/Git.pm b/perl/Git.pm index 3f4080cbf8..dca92c8adb 100644 --- a/perl/Git.pm +++ b/perl/Git.pm @@ -812,7 +812,7 @@ sub _cmd_exec { $self->wc_subdir() and chdir($self->wc_subdir()); } _execv_git_cmd(@args); - die "exec failed: $!"; + die qq[exec "@args" failed: $!]; } # Execute the given Git command ($_[0]) with arguments ($_[1..]) diff --git a/read-cache.c b/read-cache.c index 928e8fa1ae..c3dbf89426 100644 --- a/read-cache.c +++ b/read-cache.c @@ -194,11 +194,12 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st) } int ie_match_stat(struct index_state *istate, - struct cache_entry *ce, struct stat *st, int options) + struct cache_entry *ce, struct stat *st, + unsigned int options) { unsigned int changed; - int ignore_valid = options & 01; - int assume_racy_is_modified = options & 02; + int ignore_valid = options & CE_MATCH_IGNORE_VALID; + int assume_racy_is_modified = options & CE_MATCH_RACY_IS_DIRTY; /* * If it's marked as always valid in the index, it's @@ -238,10 +239,11 @@ int ie_match_stat(struct index_state *istate, } int ie_modified(struct index_state *istate, - struct cache_entry *ce, struct stat *st, int really) + struct cache_entry *ce, struct stat *st, unsigned int options) { int changed, changed_fs; - changed = ie_match_stat(istate, ce, st, really); + + changed = ie_match_stat(istate, ce, st, options); if (!changed) return 0; /* @@ -386,6 +388,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose) int size, namelen, pos; struct stat st; struct cache_entry *ce; + unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY; if (lstat(path, &st)) die("%s: unable to stat (%s)", path, strerror(errno)); @@ -420,7 +423,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose) pos = index_name_pos(istate, ce->name, namelen); if (0 <= pos && !ce_stage(istate->cache[pos]) && - !ie_modified(istate, istate->cache[pos], &st, 1)) { + !ie_match_stat(istate, istate->cache[pos], &st, ce_option)) { /* Nothing changed, really */ free(ce); return 0; @@ -782,11 +785,13 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti * to link up the stat cache details with the proper files. */ static struct cache_entry *refresh_cache_ent(struct index_state *istate, - struct cache_entry *ce, int really, int *err) + struct cache_entry *ce, + unsigned int options, int *err) { struct stat st; struct cache_entry *updated; int changed, size; + int ignore_valid = options & CE_MATCH_IGNORE_VALID; if (lstat(ce->name, &st) < 0) { if (err) @@ -794,16 +799,23 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate, return NULL; } - changed = ie_match_stat(istate, ce, &st, really); + changed = ie_match_stat(istate, ce, &st, options); if (!changed) { - if (really && assume_unchanged && + /* + * The path is unchanged. If we were told to ignore + * valid bit, then we did the actual stat check and + * found that the entry is unmodified. If the entry + * is not marked VALID, this is the place to mark it + * valid again, under "assume unchanged" mode. + */ + if (ignore_valid && assume_unchanged && !(ce->ce_flags & htons(CE_VALID))) ; /* mark this one VALID again */ else return ce; } - if (ie_modified(istate, ce, &st, really)) { + if (ie_modified(istate, ce, &st, options)) { if (err) *err = EINVAL; return NULL; @@ -814,13 +826,14 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate, memcpy(updated, ce, size); fill_stat_cache_info(updated, &st); - /* In this case, if really is not set, we should leave - * CE_VALID bit alone. Otherwise, paths marked with - * --no-assume-unchanged (i.e. things to be edited) will - * reacquire CE_VALID bit automatically, which is not - * really what we want. + /* + * If ignore_valid is not set, we should leave CE_VALID bit + * alone. Otherwise, paths marked with --no-assume-unchanged + * (i.e. things to be edited) will reacquire CE_VALID bit + * automatically, which is not really what we want. */ - if (!really && assume_unchanged && !(ce->ce_flags & htons(CE_VALID))) + if (!ignore_valid && assume_unchanged && + !(ce->ce_flags & htons(CE_VALID))) updated->ce_flags &= ~htons(CE_VALID); return updated; @@ -834,6 +847,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p int allow_unmerged = (flags & REFRESH_UNMERGED) != 0; int quiet = (flags & REFRESH_QUIET) != 0; int not_new = (flags & REFRESH_IGNORE_MISSING) != 0; + unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0; for (i = 0; i < istate->cache_nr; i++) { struct cache_entry *ce, *new; @@ -855,7 +869,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p if (pathspec && !match_pathspec(pathspec, ce->name, strlen(ce->name), 0, seen)) continue; - new = refresh_cache_ent(istate, ce, really, &cache_errno); + new = refresh_cache_ent(istate, ce, options, &cache_errno); if (new == ce) continue; if (!new) { diff --git a/revision.c b/revision.c index 48756b5d44..0ba0729b08 100644 --- a/revision.c +++ b/revision.c @@ -65,10 +65,17 @@ void mark_tree_uninteresting(struct tree *tree) init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { - if (S_ISDIR(entry.mode)) + switch (object_type(entry.mode)) { + case OBJ_TREE: mark_tree_uninteresting(lookup_tree(entry.sha1)); - else + break; + case OBJ_BLOB: mark_blob_uninteresting(lookup_blob(entry.sha1)); + break; + default: + /* Subproject commit - not in this repository */ + break; + } } /* diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index ce045b2a57..a90824ba8a 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -205,7 +205,7 @@ test_expect_success \ echo $h_TEST >.git/MERGE_HEAD && GIT_AUTHOR_DATE="2005-05-26 23:45" \ GIT_COMMITTER_DATE="2005-05-26 23:45" git-commit -F M && - h_MERGED=$(git rev-parse --verify HEAD) + h_MERGED=$(git rev-parse --verify HEAD) && rm -f M' cat >expect <<EOF diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index eb1ced3c37..24f892f793 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git add -u with path limiting +test_description='git add -u This test creates a working tree state with three files: @@ -9,7 +9,10 @@ This test creates a working tree state with three files: dir/other (untracked) and issues a git add -u with path limiting on "dir" to add -only the updates to dir/sub.' +only the updates to dir/sub. + +Also tested are "git add -u" without limiting, and "git add -u" +without contents changes.' . ./test-lib.sh @@ -85,4 +88,27 @@ test_expect_success 'replace a file with a symlink' ' ' +test_expect_success 'add everything changed' ' + + git add -u && + test -z "$(git diff-files)" + +' + +test_expect_success 'touch and then add -u' ' + + touch check && + git add -u && + test -z "$(git diff-files)" + +' + +test_expect_success 'touch and then add explicitly' ' + + touch check && + git add check && + test -z "$(git diff-files)" + +' + test_done diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 6c92d61192..984146b5c2 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -149,7 +149,7 @@ test_expect_success 'stop on conflicting pick' ' diff -u expect .git/.dotest-merge/patch && diff -u expect2 file1 && test 4 = $(grep -v "^#" < .git/.dotest-merge/done | wc -l) && - test 0 = $(grep -v "^#" < .git/.dotest-merge/todo | wc -l) + test 0 = $(grep -v "^#" < .git/.dotest-merge/git-rebase-todo | wc -l) ' test_expect_success 'abort' ' diff --git a/t/t3700-add.sh b/t/t3700-add.sh index a328bf57eb..287e058e37 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -104,9 +104,33 @@ test_expect_success 'add ignored ones with -f' ' git ls-files --error-unmatch d.ig/d.if d.ig/d.ig ' +test_expect_success 'add ignored ones with -f' ' + rm -f .git/index && + git add -f d.?? && + git ls-files --error-unmatch d.ig/d.if d.ig/d.ig +' + +test_expect_success '.gitignore with subdirectory' ' + + rm -f .git/index && + mkdir -p sub/dir && + echo "!dir/a.*" >sub/.gitignore && + >sub/a.ig && + >sub/dir/a.ig && + git add sub/dir && + git ls-files --error-unmatch sub/dir/a.ig && + rm -f .git/index && + ( + cd sub/dir && + git add . + ) && + git ls-files --error-unmatch sub/dir/a.ig +' + mkdir 1 1/2 1/3 touch 1/2/a 1/3/b 1/2/c test_expect_success 'check correct prefix detection' ' + rm -f .git/index && git add 1/2/a 1/3/b 1/2/c ' diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh index 7d92ae3e99..c44b27aeb2 100755 --- a/t/t4000-diff-format.sh +++ b/t/t4000-diff-format.sh @@ -16,7 +16,7 @@ cat path0 >path1 chmod +x path1 test_expect_success \ - 'update-cache --add two files with and without +x.' \ + 'update-index --add two files with and without +x.' \ 'git update-index --add path0 path1' mv path0 path0- diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh index 063e79257a..2fe50bc7ce 100755 --- a/t/t4001-diff-rename.sh +++ b/t/t4001-diff-rename.sh @@ -27,7 +27,7 @@ Line 15 ' test_expect_success \ - 'update-cache --add a file.' \ + 'update-index --add a file.' \ 'git update-index --add path0' test_expect_success \ diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh index 5836e3a899..1287d2ad17 100755 --- a/t/t4008-diff-break-rewrite.sh +++ b/t/t4008-diff-break-rewrite.sh @@ -119,7 +119,7 @@ test_expect_success \ 'compare_diff_raw expected current' test_expect_success \ - 'run diff with -B' \ + 'run diff with -B -M' \ 'git diff-index -B -M "$tree" >current' # This should not mistake file0 as the copy source of new file1 diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index f9db81d3ab..f9db81d3ab 100644..100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh diff --git a/t/t4021-format-patch-signer-mime.sh b/t/t4021-format-patch-signer-mime.sh new file mode 100755 index 0000000000..67a70fadab --- /dev/null +++ b/t/t4021-format-patch-signer-mime.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +test_description='format-patch -s should force MIME encoding as needed' + +. ./test-lib.sh + +test_expect_success setup ' + + >F && + git add F && + git commit -m initial && + echo new line >F && + + test_tick && + git commit -m "This adds some lines to F" F + +' + +test_expect_success 'format normally' ' + + git format-patch --stdout -1 >output && + ! grep Content-Type output + +' + +test_expect_success 'format with signoff without funny signer name' ' + + git format-patch -s --stdout -1 >output && + ! grep Content-Type output + +' + +test_expect_success 'format with non ASCII signer name' ' + + GIT_COMMITTER_NAME="はまの ふにおう瘢雹" \ + git format-patch -s --stdout -1 >output && + grep Content-Type output + +' + +test_done + diff --git a/t/t4100/t-apply-1.patch b/t/t4100/t-apply-1.patch index de587517f4..90ab54f0f5 100644 --- a/t/t4100/t-apply-1.patch +++ b/t/t4100/t-apply-1.patch @@ -90,7 +90,7 @@ diff --git a/Documentation/git.txt b/Documentation/git.txt diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile -@@ -30,7 +30,7 @@ PROG= git-update-cache git-diff-files +@@ -30,7 +30,7 @@ PROG= git-update-index git-diff-files git-checkout-cache git-diff-tree git-rev-tree git-ls-files \ git-check-files git-ls-tree git-merge-base git-merge-cache \ git-unpack-file git-export git-diff-cache git-convert-cache \ diff --git a/t/t4100/t-apply-2.patch b/t/t4100/t-apply-2.patch index cfdc80885b..f5c7d601fc 100644 --- a/t/t4100/t-apply-2.patch +++ b/t/t4100/t-apply-2.patch @@ -9,7 +9,7 @@ diff --git a/Makefile b/Makefile - git-deltafy-script + git-deltafy-script git-fetch-script - PROG= git-update-cache git-diff-files git-init-db git-write-tree \ + PROG= git-update-index git-diff-files git-init-db git-write-tree \ git-read-tree git-commit-tree git-cat-file git-fsck-cache \ diff --git a/git-pull-script b/git-fetch-script similarity index 87% diff --git a/t/t4100/t-apply-5.patch b/t/t4100/t-apply-5.patch index de11623d1b..5f6ddc1059 100644 --- a/t/t4100/t-apply-5.patch +++ b/t/t4100/t-apply-5.patch @@ -200,7 +200,7 @@ diff a/Documentation/git.txt b/Documentation/git.txt diff a/Makefile b/Makefile --- a/Makefile +++ b/Makefile -@@ -30,7 +30,7 @@ PROG= git-update-cache git-diff-files +@@ -30,7 +30,7 @@ PROG= git-update-index git-diff-files git-checkout-cache git-diff-tree git-rev-tree git-ls-files \ git-check-files git-ls-tree git-merge-base git-merge-cache \ git-unpack-file git-export git-diff-cache git-convert-cache \ diff --git a/t/t4100/t-apply-6.patch b/t/t4100/t-apply-6.patch index d9753637fc..a72729a712 100644 --- a/t/t4100/t-apply-6.patch +++ b/t/t4100/t-apply-6.patch @@ -8,7 +8,7 @@ diff a/Makefile b/Makefile - git-deltafy-script + git-deltafy-script git-fetch-script - PROG= git-update-cache git-diff-files git-init-db git-write-tree \ + PROG= git-update-index git-diff-files git-init-db git-write-tree \ git-read-tree git-commit-tree git-cat-file git-fsck-cache \ diff a/git-fetch-script b/git-fetch-script --- /dev/null diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 439430f569..7406de35ae 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -153,4 +153,17 @@ test_expect_success 'bundle should be able to create a full history' ' ' +test_expect_success 'bundle should record HEAD correctly' ' + + cd "$D" && + git bundle create bundle5 HEAD master && + git bundle list-heads bundle5 >actual && + for h in HEAD refs/heads/master + do + echo "$(git rev-parse --verify $h) $h" + done >expect && + diff -u expect actual + +' + test_done diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh new file mode 100755 index 0000000000..88e96fb91b --- /dev/null +++ b/t/t6008-rev-list-submodule.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='git rev-list involving submodules that this repo has' + +. ./test-lib.sh + +test_expect_success 'setup' ' + : > file && + git add file && + test_tick && + git commit -m initial && + echo 1 > file && + test_tick && + git commit -m second file && + echo 2 > file && + test_tick && + git commit -m third file && + + rm .git/index && + + : > super-file && + git add super-file && + git submodule add . sub && + git symbolic-ref HEAD refs/heads/super && + test_tick && + git commit -m super-initial && + echo 1 > super-file && + test_tick && + git commit -m super-first super-file && + echo 2 > super-file && + test_tick && + git commit -m super-second super-file +' + +test_expect_success "Ilari's test" ' + git rev-list --objects super master ^super^ +' + +test_done diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 2089351f7d..5f60b22d87 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -114,7 +114,7 @@ test_expect_success 'use index-filter to move into a subdirectory' ' test_expect_success 'stops when msg filter fails' ' old=$(git rev-parse HEAD) && - ! git-filter-branch -f --msg-filter false && + ! git-filter-branch -f --msg-filter false HEAD && test $old = $(git rev-parse HEAD) && rm -rf .git-rewrite ' diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh index 28643b0da4..ed416e14e0 100755 --- a/t/t7005-editor.sh +++ b/t/t7005-editor.sh @@ -13,7 +13,6 @@ do done unset vi mv e-vi.sh vi -PATH=".:$PATH" unset EDITOR VISUAL GIT_EDITOR test_expect_success setup ' @@ -59,7 +58,7 @@ do ;; esac test_expect_success "Using $i" ' - git commit --amend && + git --exec-path=. commit --amend && git show -s --pretty=oneline | sed -e "s/^[0-9a-f]* //" >actual && diff actual expect @@ -81,7 +80,7 @@ do ;; esac test_expect_success "Using $i (override)" ' - git commit --amend && + git --exec-path=. commit --amend && git show -s --pretty=oneline | sed -e "s/^[0-9a-f]* //" >actual && diff actual expect diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index eb0847afe9..0ed4ae2827 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -177,4 +177,15 @@ test_expect_success 'clean.requireForce and -f' ' ' +test_expect_success 'core.excludesfile' ' + + echo excludes >excludes && + echo included >included && + git config core.excludesfile excludes && + output=$(git clean -n excludes included 2>&1) && + expr "$output" : ".*included" >/dev/null && + ! expr "$output" : ".*excludes" >/dev/null + +' + test_done diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh index f11ada8617..26bd8ee469 100755 --- a/t/t7500-commit.sh +++ b/t/t7500-commit.sh @@ -93,4 +93,36 @@ test_expect_success 'commit message from file should override template' ' commit_msg_is "standard input msg<unknown>" ' +test_expect_success 'using alternate GIT_INDEX_FILE (1)' ' + + cp .git/index saved-index && + ( + echo some new content >file && + GIT_INDEX_FILE=.git/another_index && + export GIT_INDEX_FILE && + git add file && + git commit -m "commit using another index" && + git diff-index --exit-code HEAD && + git diff-files --exit-code + ) && + cmp .git/index saved-index >/dev/null + +' + +test_expect_success 'using alternate GIT_INDEX_FILE (2)' ' + + cp .git/index saved-index && + ( + rm -f .git/no-such-index && + GIT_INDEX_FILE=.git/no-such-index && + export GIT_INDEX_FILE && + git commit -m "commit using nonexistent index" && + test -z "$(git ls-files)" && + test -z "$(git ls-tree HEAD)" + + ) && + cmp .git/index saved-index >/dev/null + +' + test_done diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index b151b51a34..7f25689bb7 100644..100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -34,6 +34,16 @@ test_expect_failure \ "git-commit -C HEAD -m illegal" test_expect_failure \ + "using paths with -a" \ + "echo King of the bongo >file && + git-commit -m foo -a file" + +test_expect_failure \ + "using paths with --interactive" \ + "echo bong-o-bong >file && + echo 7 | git-commit -m foo --interactive file" + +test_expect_failure \ "using invalid commit with -C" \ "git-commit -C bogus" diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh index 622ea1c0df..02c41697de 100755 --- a/t/t9101-git-svn-props.sh +++ b/t/t9101-git-svn-props.sh @@ -48,7 +48,7 @@ EOF printf "\r\n" > empty_crlf a_empty_crlf=`git-hash-object -w empty_crlf` - svn import -m 'import for git-svn' . "$svnrepo" >/dev/null + svn import --no-auto-props -m 'import for git-svn' . "$svnrepo" >/dev/null cd .. rm -rf import diff --git a/t/t9106-git-svn-dcommit-clobber-series.sh b/t/t9106-git-svn-dcommit-clobber-series.sh new file mode 100755 index 0000000000..d59acc8d1a --- /dev/null +++ b/t/t9106-git-svn-dcommit-clobber-series.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +test_description='git-svn dcommit clobber series' +. ./lib-git-svn.sh + +test_expect_success 'initialize repo' " + mkdir import && + cd import && + awk 'BEGIN { for (i = 1; i < 64; i++) { print i } }' > file + svn import -m 'initial' . $svnrepo && + cd .. && + git svn init $svnrepo && + git svn fetch && + test -e file + " + +test_expect_success '(supposedly) non-conflicting change from SVN' " + test x\"\`sed -n -e 58p < file\`\" = x58 && + test x\"\`sed -n -e 61p < file\`\" = x61 && + svn co $svnrepo tmp && + cd tmp && + perl -i -p -e 's/^58\$/5588/' file && + perl -i -p -e 's/^61\$/6611/' file && + test x\"\`sed -n -e 58p < file\`\" = x5588 && + test x\"\`sed -n -e 61p < file\`\" = x6611 && + svn commit -m '58 => 5588, 61 => 6611' && + cd .. + " + +test_expect_success 'some unrelated changes to git' " + echo hi > life && + git update-index --add life && + git commit -m hi-life && + echo bye >> life && + git commit -m bye-life life + " + +test_expect_success 'change file but in unrelated area' " + test x\"\`sed -n -e 4p < file\`\" = x4 && + test x\"\`sed -n -e 7p < file\`\" = x7 && + perl -i -p -e 's/^4\$/4444/' file && + perl -i -p -e 's/^7\$/7777/' file && + test x\"\`sed -n -e 4p < file\`\" = x4444 && + test x\"\`sed -n -e 7p < file\`\" = x7777 && + git commit -m '4 => 4444, 7 => 7777' file && + git svn dcommit && + svn up tmp && + cd tmp && + test x\"\`sed -n -e 4p < file\`\" = x4444 && + test x\"\`sed -n -e 7p < file\`\" = x7777 && + test x\"\`sed -n -e 58p < file\`\" = x5588 && + test x\"\`sed -n -e 61p < file\`\" = x6611 + " + +test_expect_failure 'attempt to dcommit with a dirty index' ' + echo foo >>file && + git add file && + git svn dcommit +' + +test_done diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh index d6ca955081..225060b88b 100755 --- a/t/t9114-git-svn-dcommit-merge.sh +++ b/t/t9114-git-svn-dcommit-merge.sh @@ -86,4 +86,9 @@ test_expect_success 'verify post-merge ancestry' " git cat-file commit refs/heads/svn^ | grep '^friend$' " +test_expect_success 'verify merge commit message' " + git rev-list --pretty=raw -1 refs/heads/svn | \ + grep \" Merge branch 'merge' into svn\" + " + test_done diff --git a/t/t9600-cvsimport.sh b/t/t9600-cvsimport.sh new file mode 100755 index 0000000000..08f0f2a3a3 --- /dev/null +++ b/t/t9600-cvsimport.sh @@ -0,0 +1,134 @@ +#!/bin/sh + +test_description='git-cvsimport basic tests' +. ./test-lib.sh + +if ! ( type cvs && type cvsps ) >/dev/null 2>&1 +then + test_expect_success 'skipping cvsimport tests, cvs/cvsps not found' '' + test_done + exit +fi + +CVSROOT=$(pwd)/cvsroot +export CVSROOT +# for clean cvsps cache +HOME=$(pwd) +export HOME + +test_expect_success 'setup cvsroot' 'cvs init' + +test_expect_success 'setup a cvs module' ' + + mkdir $CVSROOT/module && + cvs co -d module-cvs module && + cd module-cvs && + cat <<EOF >o_fortuna && +O Fortuna +velut luna +statu variabilis, + +semper crescis +aut decrescis; +vita detestabilis + +nunc obdurat +et tunc curat +ludo mentis aciem, + +egestatem, +potestatem +dissolvit ut glaciem. +EOF + cvs add o_fortuna && + cat <<EOF >message && +add "O Fortuna" lyrics + +These public domain lyrics make an excellent sample text. +EOF + cvs commit -F message && + cd .. +' + +test_expect_success 'import a trivial module' ' + + git cvsimport -a -z 0 -C module-git module && + git diff module-cvs/o_fortuna module-git/o_fortuna + +' + +test_expect_success 'pack refs' 'cd module-git && git gc && cd ..' + +test_expect_success 'update cvs module' ' + + cd module-cvs && + cat <<EOF >o_fortuna && +O Fortune, +like the moon +you are changeable, + +ever waxing +and waning; +hateful life + +first oppresses +and then soothes +as fancy takes it; + +poverty +and power +it melts them like ice. +EOF + cat <<EOF >message && +translate to English + +My Latin is terrible. +EOF + cvs commit -F message && + cd .. +' + +test_expect_success 'update git module' ' + + cd module-git && + git cvsimport -a -z 0 module && + git merge origin && + cd .. && + git diff module-cvs/o_fortuna module-git/o_fortuna + +' + +test_expect_success 'update cvs module' ' + + cd module-cvs && + echo 1 >tick && + cvs add tick && + cvs commit -m 1 + cd .. + +' + +test_expect_success 'cvsimport.module config works' ' + + cd module-git && + git config cvsimport.module module && + git cvsimport -a -z0 && + git merge origin && + cd .. && + git diff module-cvs/tick module-git/tick + +' + +test_expect_success 'import from a CVS working tree' ' + + cvs co -d import-from-wt module && + cd import-from-wt && + git cvsimport -a -z0 && + echo 1 >expect && + git log -1 --pretty=format:%s%n >actual && + git diff actual expect && + cd .. + +' + +test_done diff --git a/templates/hooks--pre-commit b/templates/hooks--pre-commit index 18b87309f6..8b057be304 100644 --- a/templates/hooks--pre-commit +++ b/templates/hooks--pre-commit @@ -13,7 +13,7 @@ if git-rev-parse --verify HEAD 2>/dev/null then - git-diff-index -p -M --cached HEAD + git-diff-index -p -M --cached HEAD -- else # NEEDSWORK: we should produce a diff with an empty tree here # if we want to do the same verification for the initial import. diff --git a/tree-walk.h b/tree-walk.h index db0fbdc701..903a7b0f48 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -7,6 +7,13 @@ struct name_entry { unsigned int mode; }; +static inline enum object_type object_type(unsigned int mode) +{ + return S_ISDIR(mode) ? OBJ_TREE : + S_ISGITLINK(mode) ? OBJ_COMMIT : + OBJ_BLOB; +} + struct tree_desc { const void *buffer; struct name_entry entry; diff --git a/unpack-trees.c b/unpack-trees.c index ccfeb6e245..9411c67a06 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -406,7 +406,7 @@ static void verify_uptodate(struct cache_entry *ce, return; if (!lstat(ce->name, &st)) { - unsigned changed = ce_match_stat(ce, &st, 1); + unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID); if (!changed) return; /* @@ -927,7 +927,7 @@ int oneway_merge(struct cache_entry **src, if (o->reset) { struct stat st; if (lstat(old->name, &st) || - ce_match_stat(old, &st, 1)) + ce_match_stat(old, &st, CE_MATCH_IGNORE_VALID)) old->ce_flags |= htons(CE_UPDATE); } return keep_entry(old, o); @@ -7,9 +7,9 @@ static void report(const char *prefix, const char *err, va_list params) { - fputs(prefix, stderr); - vfprintf(stderr, err, params); - fputs("\n", stderr); + char msg[256]; + vsnprintf(msg, sizeof(msg), err, params); + fprintf(stderr, "%s%s\n", prefix, msg); } static NORETURN void usage_builtin(const char *err) diff --git a/wt-status.c b/wt-status.c index 10ce6eedc7..58dd716a4e 100644 --- a/wt-status.c +++ b/wt-status.c @@ -22,7 +22,6 @@ static const char use_add_rm_msg[] = "use \"git add/rm <file>...\" to update what will be committed"; static const char use_add_to_include_msg[] = "use \"git add <file>...\" to include in what will be committed"; -static const char *excludes_file; static int parse_status_slot(const char *var, int offset) { @@ -247,22 +246,16 @@ static void wt_status_print_changed(struct wt_status *s) static void wt_status_print_untracked(struct wt_status *s) { struct dir_struct dir; - const char *x; int i; int shown_header = 0; memset(&dir, 0, sizeof(dir)); - dir.exclude_per_dir = ".gitignore"; if (!s->untracked) { dir.show_other_directories = 1; dir.hide_empty_directories = 1; } - x = git_path("info/exclude"); - if (file_exists(x)) - add_excludes_from_file(&dir, x); - if (excludes_file && file_exists(excludes_file)) - add_excludes_from_file(&dir, excludes_file); + setup_standard_excludes(&dir); read_directory(&dir, ".", "", 0, NULL); for(i = 0; i < dir.nr; i++) { @@ -360,11 +353,5 @@ int git_status_config(const char *k, const char *v) int slot = parse_status_slot(k, 13); color_parse(v, k, wt_status_colors[slot]); } - if (!strcmp(k, "core.excludesfile")) { - if (!v) - die("core.excludesfile without value"); - excludes_file = xstrdup(v); - return 0; - } return git_default_config(k, v); } |