Merge branch 'sb/maint-octopus' into maint-1.6.5
authorJunio C Hamano <gitster@pobox.com>
Mon, 1 Feb 2010 08:06:11 +0000 (00:06 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 1 Feb 2010 08:06:11 +0000 (00:06 -0800)
* sb/maint-octopus:
octopus: remove dead code
octopus: reenable fast-forward merges
octopus: make merge process simpler to follow

31 files changed:
Documentation/RelNotes-1.6.5.7.txt [new file with mode: 0644]
Documentation/RelNotes-1.6.5.8.txt [new file with mode: 0644]
Documentation/git-add.txt
Documentation/git-rm.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/technical/api-hash.txt
Documentation/technical/api-strbuf.txt
GIT-VERSION-GEN
RelNotes
base85.c
builtin-blame.c
builtin-branch.c
builtin-checkout.c
builtin-commit.c
builtin-count-objects.c
builtin-grep.c
builtin-reset.c
commit.c
contrib/completion/git-completion.bash
diff.c
fast-import.c
git-rebase--interactive.sh
help.c
setup.c
t/t1501-worktree.sh
t/t4026-color.sh
t/t5403-post-checkout-hook.sh
t/t7102-reset.sh
t/t7103-reset-bare.sh
t/t8003-blame.sh
diff --git a/Documentation/RelNotes-1.6.5.7.txt b/Documentation/RelNotes-1.6.5.7.txt
new file mode 100644 (file)
index 0000000..5b49ea5
--- /dev/null
@@ -0,0 +1,19 @@
+Git v1.6.5.7 Release Notes
+==========================
+
+Fixes since v1.6.5.6
+--------------------
+
+* If a user specifies a color for a <slot> (i.e. a class of things to show
+  in a particular color) that is known only by newer versions of git
+  (e.g. "color.diff.func" was recently added for upcoming 1.6.6 release),
+  an older version of git should just ignore them.  Instead we diagnosed
+  it as an error.
+
+* With help.autocorrect set to non-zero value, the logic to guess typoes
+  in the subcommand name misfired and ran a random nonsense command.
+
+* If a command is run with an absolute path as a pathspec inside a bare
+  repository, e.g. "rev-list HEAD -- /home", the code tried to run
+  strlen() on NULL, which is the result of get_git_work_tree(), and
+  segfaulted.
diff --git a/Documentation/RelNotes-1.6.5.8.txt b/Documentation/RelNotes-1.6.5.8.txt
new file mode 100644 (file)
index 0000000..8b24beb
--- /dev/null
@@ -0,0 +1,28 @@
+Git v1.6.5.8 Release Notes
+==========================
+
+Fixes since v1.6.5.7
+--------------------
+
+* "git count-objects" did not handle packfiles that are bigger than 4G on
+  platforms with 32-bit off_t.
+
+* "git rebase -i" did not abort cleanly if it failed to launch the editor.
+
+* "git blame" did not work well when commit lacked the author name.
+
+* "git fast-import" choked when handling a tag that points at an object
+  that is not a commit.
+
+* "git reset --hard" did not work correctly when GIT_WORK_TREE environment
+  variable is used to point at the root of the true work tree.
+
+* "git grep" fed a buffer that is not NUL-terminated to underlying
+  regexec().
+
+* "git checkout -m other" while on a branch that does not have any commit
+  segfaulted, instead of failing.
+
+* "git branch -a other" should have diagnosed the command as an error.
+
+Other minor documentation updates are also included.
index e93e606f458356275964d0d7b438ca772abba47c..1f1b19996baa34b20bf08f4eb2889403cbc4c45d 100644 (file)
@@ -14,28 +14,32 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-This command adds the current content of new or modified files to the
-index, thus staging that content for inclusion in the next commit.
+This command updates the index using the current content found in
+the working tree, to prepare the content staged for the next commit.
+It typically adds the current content of existing paths as a whole,
+but with some options it can also be used to add content with
+only part of the changes made to the working tree files applied, or
+remove paths that do not exist in the working tree anymore.
 
 The "index" holds a snapshot of the content of the working tree, and it
 is this snapshot that is taken as the contents of the next commit.  Thus
 after making any changes to the working directory, and before running
-the commit command, you must use the 'add' command to add any new or
+the commit command, you must use the `add` command to add any new or
 modified files to the index.
 
 This command can be performed multiple times before a commit.  It only
 adds the content of the specified file(s) at the time the add command is
 run; if you want subsequent changes included in the next commit, then
-you must run 'git add' again to add the new content to the index.
+you must run `git add` again to add the new content to the index.
 
-The 'git status' command can be used to obtain a summary of which
+The `git status` command can be used to obtain a summary of which
 files have changes that are staged for the next commit.
 
-The 'git add' command will not add ignored files by default.  If any
-ignored files were explicitly specified on the command line, 'git add'
+The `git add` command will not add ignored files by default.  If any
+ignored files were explicitly specified on the command line, `git add`
 will fail with a list of ignored files.  Ignored files reached by
 directory recursion or filename globbing performed by Git (quote your
-globs before the shell) will be silently ignored.  The 'add' command can
+globs before the shell) will be silently ignored.  The `add` command can
 be used to add ignored files with the `-f` (force) option.
 
 Please see linkgit:git-commit[1] for alternative ways to add content to a
@@ -92,28 +96,31 @@ apply.
 
 -u::
 --update::
-       Update only files that git already knows about, staging modified
-       content for commit and marking deleted files for removal. This
-       is similar
-       to what "git commit -a" does in preparation for making a commit,
-       except that the update is limited to paths specified on the
-       command line. If no paths are specified, all tracked files in the
-       current directory and its subdirectories are updated.
+       Only match <filepattern> against already tracked files in
+       the index rather than the working tree. That means that it
+       will never stage new files, but that it will stage modified
+       new contents of tracked files and that it will remove files
+       from the index if the corresponding files in the working tree
+       have been removed.
++
+If no <filepattern> is given, default to "."; in other words,
+update all tracked files in the current directory and its
+subdirectories.
 
 -A::
 --all::
-       Update files that git already knows about (same as '\--update')
-       and add all untracked files that are not ignored by '.gitignore'
-       mechanism.
-
+       Like `-u`, but match <filepattern> against files in the
+       working tree in addition to the index. That means that it
+       will find new files as well as staging modified content and
+       removing files that are no longer in the working tree.
 
 -N::
 --intent-to-add::
        Record only the fact that the path will be added later. An entry
        for the path is placed in the index with no content. This is
        useful for, among other things, showing the unstaged content of
-       such files with 'git diff' and committing them with 'git commit
-       -a'.
+       such files with `git diff` and committing them with `git commit
+       -a`.
 
 --refresh::
        Don't add the file(s), but only refresh their stat()
@@ -133,7 +140,7 @@ apply.
 Configuration
 -------------
 
-The optional configuration variable 'core.excludesfile' indicates a path to a
+The optional configuration variable `core.excludesfile` indicates a path to a
 file containing patterns of file names to exclude from git-add, similar to
 $GIT_DIR/info/exclude.  Patterns in the exclude file are used in addition to
 those in info/exclude.  See linkgit:gitrepository-layout[5].
@@ -181,7 +188,7 @@ and type return, like this:
     What now> 1
 ------------
 
-You also could say "s" or "sta" or "status" above as long as the
+You also could say `s` or `sta` or `status` above as long as the
 choice is unique.
 
 The main command loop has 6 subcommands (plus help and quit).
@@ -189,9 +196,9 @@ The main command loop has 6 subcommands (plus help and quit).
 status::
 
    This shows the change between HEAD and index (i.e. what will be
-   committed if you say "git commit"), and between index and
+   committed if you say `git commit`), and between index and
    working tree files (i.e. what you could stage further before
-   "git commit" using "git-add") for each path.  A sample output
+   `git commit` using `git add`) for each path.  A sample output
    looks like this:
 +
 ------------
index 5afb1e7428126c79171cf7e7b1fb027e1de64c86..c21d19e573d5192597b4766d8d87d17ab8f1c0f3 100644 (file)
@@ -12,13 +12,13 @@ SYNOPSIS
 DESCRIPTION
 -----------
 Remove files from the index, or from the working tree and the index.
-'git-rm' will not remove a file from just your working directory.
-(There is no option to remove a file only from the work tree
+`git rm` will not remove a file from just your working directory.
+(There is no option to remove a file only from the working tree
 and yet keep it in the index; use `/bin/rm` if you want to do that.)
 The files being removed have to be identical to the tip of the branch,
 and no updates to their contents can be staged in the index,
 though that default behavior can be overridden with the `-f` option.
-When '--cached' is given, the staged content has to
+When `--cached` is given, the staged content has to
 match either the tip of the branch or the file on disk,
 allowing the file to be removed from just the index.
 
@@ -64,7 +64,7 @@ OPTIONS
 
 -q::
 --quiet::
-       'git-rm' normally outputs one line (in the form of an "rm" command)
+       `git rm` normally outputs one line (in the form of an `rm` command)
        for each file removed. This option suppresses that output.
 
 
@@ -81,6 +81,58 @@ two directories `d` and `d2`, there is a difference between
 using `git rm \'d\*\'` and `git rm \'d/\*\'`, as the former will
 also remove all of directory `d2`.
 
+REMOVING FILES THAT HAVE DISAPPEARED FROM THE FILESYSTEM
+--------------------------------------------------------
+There is no option for `git rm` to remove from the index only
+the paths that have disappeared from the filesystem. However,
+depending on the use case, there are several ways that can be
+done.
+
+Using "git commit -a"
+~~~~~~~~~~~~~~~~~~~~~
+If you intend that your next commit should record all modifications
+of tracked files in the working tree and record all removals of
+files that have been removed from the working tree with `rm`
+(as opposed to `git rm`), use `git commit -a`, as it will
+automatically notice and record all removals.  You can also have a
+similar effect without committing by using `git add -u`.
+
+Using "git add -A"
+~~~~~~~~~~~~~~~~~~
+When accepting a new code drop for a vendor branch, you probably
+want to record both the removal of paths and additions of new paths
+as well as modifications of existing paths.
+
+Typically you would first remove all tracked files from the working
+tree using this command:
+
+----------------
+git ls-files -z | xargs -0 rm -f
+----------------
+
+and then "untar" the new code in the working tree. Alternately
+you could "rsync" the changes into the working tree.
+
+After that, the easiest way to record all removals, additions, and
+modifications in the working tree is:
+
+----------------
+git add -A
+----------------
+
+See linkgit:git-add[1].
+
+Other ways
+~~~~~~~~~~
+If all you really want to do is to remove from the index the files
+that are no longer present in the working tree (perhaps because
+your working tree is dirty so that you cannot use `git commit -a`),
+use the following command:
+
+----------------
+git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached
+----------------
+
 EXAMPLES
 --------
 git rm Documentation/\\*.txt::
index c1fcfffebdddf216f63f1eb65a8b7f9495c643ae..46558c8a49c0bbf9b18a1670610c4fd9e53d1e01 100644 (file)
@@ -43,9 +43,11 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.6.5.6/git.html[documentation for release 1.6.5.6]
+* link:v1.6.5.8/git.html[documentation for release 1.6.5.8]
 
 * release notes for
+  link:RelNotes-1.6.5.8.txt[1.6.5.8],
+  link:RelNotes-1.6.5.7.txt[1.6.5.7],
   link:RelNotes-1.6.5.6.txt[1.6.5.6],
   link:RelNotes-1.6.5.5.txt[1.6.5.5],
   link:RelNotes-1.6.5.4.txt[1.6.5.4],
index 1f472cea59a64023d91d25b09cc4d6f0aa39bc28..5a45e51890b1f4b13db3d8082da83731dc76ceac 100644 (file)
@@ -197,6 +197,25 @@ intent is that if someone unsets the filter driver definition,
 or does not have the appropriate filter program, the project
 should still be usable.
 
+For example, in .gitattributes, you would assign the `filter`
+attribute for paths.
+
+------------------------
+*.c    filter=indent
+------------------------
+
+Then you would define a "filter.indent.clean" and "filter.indent.smudge"
+configuration in your .git/config to specify a pair of commands to
+modify the contents of C programs when the source files are checked
+in ("clean" is run) and checked out (no change is made because the
+command is "cat").
+
+------------------------
+[filter "indent"]
+       clean = indent
+       smudge = cat
+------------------------
+
 
 Interaction between checkin/checkout attributes
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index c784d3edcb2537b84bfb5db3da55faaf45995155..e5061e0677e05f8127b0808104269961ee21f830 100644 (file)
@@ -1,6 +1,52 @@
 hash API
 ========
 
-Talk about <hash.h>
+The hash API is a collection of simple hash table functions. Users are expected
+to implement their own hashing.
 
-(Linus)
+Data Structures
+---------------
+
+`struct hash_table`::
+
+       The hash table structure. The `array` member points to the hash table
+       entries. The `size` member counts the total number of valid and invalid
+       entries in the table. The `nr` member keeps track of the number of
+       valid entries.
+
+`struct hash_table_entry`::
+
+       An opaque structure representing an entry in the hash table. The `hash`
+       member is the entry's hash key and the `ptr` member is the entry's
+       value.
+
+Functions
+---------
+
+`init_hash`::
+
+       Initialize the hash table.
+
+`free_hash`::
+
+       Release memory associated with the hash table.
+
+`insert_hash`::
+
+       Insert a pointer into the hash table. If an entry with that hash
+       already exists, a pointer to the existing entry's value is returned.
+       Otherwise NULL is returned.  This allows callers to implement
+       chaining, etc.
+
+`lookup_hash`::
+
+       Lookup an entry in the hash table. If an entry with that hash exists
+       the entry's value is returned. Otherwise NULL is returned.
+
+`for_each_hash`::
+
+       Call a function for each entry in the hash table. The function is
+       expected to take the entry's value as its only argument and return an
+       int. If the function returns a negative int the loop is aborted
+       immediately.  Otherwise, the return value is accumulated and the sum
+       returned upon completion of the loop.
index 7438149249364ca8837811771b072b20990b3a5d..a0e0f850f83fe164dd7c1ca87d001fe485ba2ec2 100644 (file)
@@ -12,7 +12,7 @@ strbuf API actually relies on the string being free of NULs.
 
 strbufs has some invariants that are very important to keep in mind:
 
-. The `buf` member is never NULL, so you it can be used in any usual C
+. The `buf` member is never NULL, so it can be used in any usual C
 string operations safely. strbuf's _have_ to be initialized either by
 `strbuf_init()` or by `= STRBUF_INIT` before the invariants, though.
 +
@@ -55,7 +55,7 @@ Data structures
 
 * `struct strbuf`
 
-This is string buffer structure. The `len` member can be used to
+This is the string buffer structure. The `len` member can be used to
 determine the current length of the string, and `buf` member provides access to
 the string itself.
 
@@ -253,3 +253,9 @@ same behaviour as well.
        comments are considered contents to be removed or not.
 
 `launch_editor`::
+
+       Launch the user preferred editor to edit a file and fill the buffer
+       with the file's contents upon the user completing their editing. The
+       third argument can be used to set the environment which the editor is
+       run in. If the buffer is NULL the editor is launched as usual but the
+       file's contents are not read into the buffer upon completion.
index 9c945d91cb7eb3898d4ff09f457e7f529cf67121..52b058a5868e904f6384a922e7edd0ced5f70d89 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.6.5.6
+DEF_VER=v1.6.5.8
 
 LF='
 '
index 115c33553bb99a5ac6c21c2ac0f33ab7b48a4901..f60e868f4721b24cfe989303193bf0a9be3473a7 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.5.6.txt
\ No newline at end of file
+Documentation/RelNotes-1.6.5.8.txt
\ No newline at end of file
index b417a15bbc83fff7180078a4cf9f73603477a295..e459feebbf90c6557dbf3ff913f83a57a8afb210 100644 (file)
--- a/base85.c
+++ b/base85.c
@@ -57,14 +57,8 @@ int decode_85(char *dst, const char *buffer, int len)
                de = de85[ch];
                if (--de < 0)
                        return error("invalid base85 alphabet %c", ch);
-               /*
-                * Detect overflow.  The largest
-                * 5-letter possible is "|NsC0" to
-                * encode 0xffffffff, and "|NsC" gives
-                * 0x03030303 at this point (i.e.
-                * 0xffffffff = 0x03030303 * 85).
-                */
-               if (0x03030303 < acc ||
+               /* Detect overflow. */
+               if (0xffffffff / 85 < acc ||
                    0xffffffff - de < (acc *= 85))
                        return error("invalid base85 sequence %.5s", buffer-5);
                acc += de;
@@ -84,8 +78,6 @@ int decode_85(char *dst, const char *buffer, int len)
 
 void encode_85(char *buf, const unsigned char *data, int bytes)
 {
-       prep_base85();
-
        say("encode 85");
        while (bytes) {
                unsigned acc = 0;
@@ -118,7 +110,7 @@ int main(int ac, char **av)
                int len = strlen(av[2]);
                encode_85(buf, av[2], len);
                if (len <= 26) len = len + 'A' - 1;
-               else len = len + 'a' - 26 + 1;
+               else len = len + 'a' - 26 - 1;
                printf("encoded: %c%s\n", len, buf);
                return 0;
        }
index dd16b2229763addfba8f02f3d9b3c42dcb995935..98e818ce6a63b352182b428b49464596d37a0617 100644 (file)
@@ -1305,6 +1305,7 @@ static void get_ac_line(const char *inbuf, const char *what,
        error_out:
                /* Ugh */
                *tz = "(unknown)";
+               strcpy(person, *tz);
                strcpy(mail, *tz);
                *time = 0;
                return;
@@ -1314,20 +1315,26 @@ static void get_ac_line(const char *inbuf, const char *what,
        tmp = person;
        tmp += len;
        *tmp = 0;
-       while (*tmp != ' ')
+       while (person < tmp && *tmp != ' ')
                tmp--;
+       if (tmp <= person)
+               goto error_out;
        *tz = tmp+1;
        tzlen = (person+len)-(tmp+1);
 
        *tmp = 0;
-       while (*tmp != ' ')
+       while (person < tmp && *tmp != ' ')
                tmp--;
+       if (tmp <= person)
+               goto error_out;
        *time = strtoul(tmp, NULL, 10);
        timepos = tmp;
 
        *tmp = 0;
-       while (*tmp != ' ')
+       while (person < tmp && *tmp != ' ')
                tmp--;
+       if (tmp <= person)
+               return;
        mailpos = tmp + 1;
        *tmp = 0;
        maillen = timepos - tmp;
index 9f57992062314a3d8d168b5cfb6b3c6737605033..0c84f9f9eb75babf69eb5503f83bce5645477609 100644 (file)
@@ -65,7 +65,7 @@ static int parse_branch_color_slot(const char *var, int ofs)
                return BRANCH_COLOR_LOCAL;
        if (!strcasecmp(var+ofs, "current"))
                return BRANCH_COLOR_CURRENT;
-       die("bad config variable '%s'", var);
+       return -1;
 }
 
 static int git_branch_config(const char *var, const char *value, void *cb)
@@ -76,6 +76,8 @@ static int git_branch_config(const char *var, const char *value, void *cb)
        }
        if (!prefixcmp(var, "color.branch.")) {
                int slot = parse_branch_color_slot(var, 13);
+               if (slot < 0)
+                       return 0;
                if (!value)
                        return config_error_nonbool(var);
                color_parse(value, var, branch_colors[slot]);
@@ -635,10 +637,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                rename_branch(head, argv[0], rename > 1);
        else if (rename && (argc == 2))
                rename_branch(argv[0], argv[1], rename > 1);
-       else if (argc <= 2)
+       else if (argc <= 2) {
+               if (kinds != REF_LOCAL_BRANCH)
+                       die("-a and -r options to 'git branch' do not make sense with a branch name");
                create_branch(head, argv[0], (argc == 2) ? argv[1] : head,
                              force_create, reflog, track);
-       else
+       else
                usage_with_options(builtin_branch_usage, options);
 
        return 0;
index d050c3789fcdaf1b50c12a20c28cbeaf774048eb..f2786fe439f8b6a1f28e8cbf5be6e8727c929b29 100644 (file)
@@ -396,7 +396,7 @@ static int merge_working_tree(struct checkout_opts *opts,
                topts.initial_checkout = is_cache_unborn();
                topts.update = 1;
                topts.merge = 1;
-               topts.gently = opts->merge;
+               topts.gently = opts->merge && old->commit;
                topts.verbose_update = !opts->quiet;
                topts.fn = twoway_merge;
                topts.dir = xcalloc(1, sizeof(*topts.dir));
@@ -421,7 +421,13 @@ static int merge_working_tree(struct checkout_opts *opts,
                        struct merge_options o;
                        if (!opts->merge)
                                return 1;
-                       parse_commit(old->commit);
+
+                       /*
+                        * Without old->commit, the below is the same as
+                        * the two-tree unpack we already tried and failed.
+                        */
+                       if (!old->commit)
+                               return 1;
 
                        /* Do more real merge */
 
index 2299dc75ceebc6792fd51118aaff721cc865f844..c2ab85e1aaefcdc9c59edb7280779ebffdf4e0c5 100644 (file)
@@ -86,8 +86,8 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset)
 static struct option builtin_commit_options[] = {
        OPT__QUIET(&quiet),
        OPT__VERBOSE(&verbose),
-       OPT_GROUP("Commit message options"),
 
+       OPT_GROUP("Commit message options"),
        OPT_FILENAME('F', "file", &logfile, "read log from file"),
        OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
        OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
@@ -96,6 +96,8 @@ static struct option builtin_commit_options[] = {
        OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
        OPT_FILENAME('t', "template", &template_file, "use specified template file"),
        OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
+       OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
+       /* end commit message options */
 
        OPT_GROUP("Commit contents options"),
        OPT_BOOLEAN('a', "all", &all, "commit all changed files"),
@@ -107,7 +109,7 @@ static struct option builtin_commit_options[] = {
        OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
        { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
        OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
-       OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
+       /* end commit contents options */
 
        OPT_END()
 };
@@ -841,7 +843,7 @@ static int parse_status_slot(const char *var, int offset)
                return WT_STATUS_NOBRANCH;
        if (!strcasecmp(var+offset, "unmerged"))
                return WT_STATUS_UNMERGED;
-       die("bad config variable '%s'", var);
+       return -1;
 }
 
 static int git_status_config(const char *k, const char *v, void *cb)
@@ -861,6 +863,8 @@ static int git_status_config(const char *k, const char *v, void *cb)
        }
        if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) {
                int slot = parse_status_slot(k, 13);
+               if (slot < 0)
+                       return 0;
                if (!v)
                        return config_error_nonbool(k);
                color_parse(v, k, s->color_palette[slot]);
index 1b0b6c84ea4279df56b82c5a406adbea59e58513..2bdd8ebde1002e852055385396ef053f26c91ae8 100644 (file)
@@ -11,7 +11,7 @@
 
 static void count_objects(DIR *d, char *path, int len, int verbose,
                          unsigned long *loose,
-                         unsigned long *loose_size,
+                         off_t *loose_size,
                          unsigned long *packed_loose,
                          unsigned long *garbage)
 {
@@ -77,7 +77,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
        int len = strlen(objdir);
        char *path = xmalloc(len + 50);
        unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
-       unsigned long loose_size = 0;
+       off_t loose_size = 0;
        struct option opts[] = {
                OPT__VERBOSE(&verbose),
                OPT_END(),
@@ -103,7 +103,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
        if (verbose) {
                struct packed_git *p;
                unsigned long num_pack = 0;
-               unsigned long size_pack = 0;
+               off_t size_pack = 0;
                if (!packed_git)
                        prepare_packed_git();
                for (p = packed_git; p; p = p->next) {
@@ -116,15 +116,15 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
                        num_pack++;
                }
                printf("count: %lu\n", loose);
-               printf("size: %lu\n", loose_size / 1024);
+               printf("size: %lu\n", (unsigned long) (loose_size / 1024));
                printf("in-pack: %lu\n", packed);
                printf("packs: %lu\n", num_pack);
-               printf("size-pack: %lu\n", size_pack / 1024);
+               printf("size-pack: %lu\n", (unsigned long) (size_pack / 1024));
                printf("prune-packable: %lu\n", packed_loose);
                printf("garbage: %lu\n", garbage);
        }
        else
                printf("%lu objects, %lu kilobytes\n",
-                      loose, loose_size / 1024);
+                      loose, (unsigned long) (loose_size / 1024));
        return 0;
 }
index d79a6260a4b6f9a467356de117e100cd1a457b23..63dc31c45c309c7a2a67977e5631cb5334b32ecf 100644 (file)
@@ -207,6 +207,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
                return 0;
        }
        close(i);
+       data[sz] = 0;
        if (opt->relative && opt->prefix_length)
                filename = quote_path_relative(filename, -1, &buf, opt->prefix);
        i = grep_buffer(opt, filename, data, sz);
index 11d1c6e4d6d2ec0580cae3725f6b3a093e68aa67..e4418bced23807df174e600a4babbf1d604bac8e 100644 (file)
@@ -286,10 +286,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
        if (reset_type == NONE)
                reset_type = MIXED; /* by default */
 
-       if ((reset_type == HARD || reset_type == MERGE)
-           && !is_inside_work_tree())
-               die("%s reset requires a work tree",
-                   reset_type_names[reset_type]);
+       if (reset_type == HARD || reset_type == MERGE)
+               setup_work_tree();
 
        /* Soft reset does not touch the index file nor the working tree
         * at all, but requires them in a good order.  Other resets reset
index 6393e1b36218e5f8970b0c43092b07f5d94b0bce..a51d2cd1bed0c18b26f8f8123f1dab398a5019d8 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -225,7 +225,7 @@ int unregister_shallow(const unsigned char *sha1)
        if (pos < 0)
                return -1;
        if (pos + 1 < commit_graft_nr)
-               memcpy(commit_graft + pos, commit_graft + pos + 1,
+               memmove(commit_graft + pos, commit_graft + pos + 1,
                                sizeof(struct commit_graft *)
                                * (commit_graft_nr - pos - 1));
        commit_graft_nr--;
index 7cf855746832b7400f9923297c4a0170cfacce36..4cb89a1256a7fc7df0fce443f61eb209b82ac8e6 100755 (executable)
@@ -148,11 +148,9 @@ __git_ps1 ()
                elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
                        if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then
                                if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then
-                                       git diff --no-ext-diff --ignore-submodules \
-                                               --quiet --exit-code || w="*"
+                                       git diff --no-ext-diff --quiet --exit-code || w="*"
                                        if git rev-parse --quiet --verify HEAD >/dev/null; then
-                                               git diff-index --cached --quiet \
-                                                       --ignore-submodules HEAD -- || i="+"
+                                               git diff-index --cached --quiet HEAD -- || i="+"
                                        else
                                                i="#"
                                        fi
diff --git a/diff.c b/diff.c
index cc0cb2b31f3f9b4ff00b12ad1d07671c7228749d..17a2b4df2922427920d4bb896f173247f93433e4 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -59,7 +59,7 @@ static int parse_diff_color_slot(const char *var, int ofs)
                return DIFF_COMMIT;
        if (!strcasecmp(var+ofs, "whitespace"))
                return DIFF_WHITESPACE;
-       die("bad config variable '%s'", var);
+       return -1;
 }
 
 static int git_config_rename(const char *var, const char *value)
@@ -118,6 +118,8 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
 
        if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
                int slot = parse_diff_color_slot(var, 11);
+               if (slot < 0)
+                       return 0;
                if (!value)
                        return config_error_nonbool(var);
                color_parse(value, var, diff_colors[slot]);
@@ -3718,11 +3720,13 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
        if (start_command(&child) != 0 ||
            strbuf_read(&buf, child.out, 0) < 0 ||
            finish_command(&child) != 0) {
+               close(child.out);
                strbuf_release(&buf);
                remove_tempfile();
                error("error running textconv command '%s'", pgm);
                return NULL;
        }
+       close(child.out);
        remove_tempfile();
 
        return strbuf_detach(&buf, outsize);
index 6faaaacb68999db294d20ecbb30772223bfc1b57..36c5a8ebd99fb1ec1a250f7f3be1ab13c3eca3a8 100644 (file)
@@ -2225,6 +2225,7 @@ static void parse_new_tag(void)
        struct tag *t;
        uintmax_t from_mark = 0;
        unsigned char sha1[20];
+       enum object_type type;
 
        /* Obtain the new tag name from the rest of our command */
        sp = strchr(command_buf.buf, ' ') + 1;
@@ -2245,19 +2246,18 @@ static void parse_new_tag(void)
        s = lookup_branch(from);
        if (s) {
                hashcpy(sha1, s->sha1);
+               type = OBJ_COMMIT;
        } else if (*from == ':') {
                struct object_entry *oe;
                from_mark = strtoumax(from + 1, NULL, 10);
                oe = find_mark(from_mark);
-               if (oe->type != OBJ_COMMIT)
-                       die("Mark :%" PRIuMAX " not a commit", from_mark);
+               type = oe->type;
                hashcpy(sha1, oe->sha1);
        } else if (!get_sha1(from, sha1)) {
                unsigned long size;
                char *buf;
 
-               buf = read_object_with_reference(sha1,
-                       commit_type, &size, sha1);
+               buf = read_sha1_file(sha1, &type, &size);
                if (!buf || size < 46)
                        die("Not a valid commit: %s", from);
                free(buf);
@@ -2282,7 +2282,7 @@ static void parse_new_tag(void)
                    "object %s\n"
                    "type %s\n"
                    "tag %s\n",
-                   sha1_to_hex(sha1), commit_type, t->name);
+                   sha1_to_hex(sha1), typename(type), t->name);
        if (tagger)
                strbuf_addf(&new_data,
                            "tagger %s\n", tagger);
index 3853b513b55820d316db436373742af5bb26e6b7..5014ae0579753a09d0c52742d0d0ddb8db5ac8c9 100755 (executable)
@@ -770,7 +770,7 @@ EOF
 
                cp "$TODO" "$TODO".backup
                git_editor "$TODO" ||
-                       die "Could not execute editor"
+                       die_abort "Could not execute editor"
 
                has_action "$TODO" ||
                        die_abort "Nothing to do"
diff --git a/help.c b/help.c
index e8db31f60f010887ccb3a943344da566e0937403..9da97d7462040d3935e7eaa95b1167357b38a943 100644 (file)
--- a/help.c
+++ b/help.c
@@ -297,6 +297,9 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
        old->names = NULL;
 }
 
+/* An empirically derived magic number */
+#define SIMILAR_ENOUGH(x) ((x) < 6)
+
 const char *help_unknown_cmd(const char *cmd)
 {
        int i, n, best_similarity = 0;
@@ -331,7 +334,7 @@ const char *help_unknown_cmd(const char *cmd)
        n = 1;
        while (n < main_cmds.cnt && best_similarity == main_cmds.names[n]->len)
                ++n;
-       if (autocorrect && n == 1) {
+       if (autocorrect && n == 1 && SIMILAR_ENOUGH(best_similarity)) {
                const char *assumed = main_cmds.names[0]->name;
                main_cmds.names[0] = NULL;
                clean_cmdnames(&main_cmds);
@@ -349,7 +352,7 @@ const char *help_unknown_cmd(const char *cmd)
 
        fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
 
-       if (best_similarity < 6) {
+       if (SIMILAR_ENOUGH(best_similarity)) {
                fprintf(stderr, "\nDid you mean %s?\n",
                        n < 2 ? "this": "one of these");
 
diff --git a/setup.c b/setup.c
index 029371e5844a1069d62456c6bb51028efbb671c4..4272ec0ef2fd833923a5303286a0dd237ec6eab8 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -18,9 +18,12 @@ const char *prefix_path(const char *prefix, int len, const char *path)
        if (normalize_path_copy(sanitized, sanitized))
                goto error_out;
        if (is_absolute_path(orig)) {
+               size_t len, total;
                const char *work_tree = get_git_work_tree();
-               size_t len = strlen(work_tree);
-               size_t total = strlen(sanitized) + 1;
+               if (!work_tree)
+                       goto error_out;
+               len = strlen(work_tree);
+               total = strlen(sanitized) + 1;
                if (strncmp(sanitized, work_tree, len) ||
                    (sanitized[len] != '\0' && sanitized[len] != '/')) {
                error_out:
index f6a6f839a18de4c3775ea965f164d0d20f2bbe9b..74e6443664010196f2694304179917fdadc53c01 100755 (executable)
@@ -174,4 +174,19 @@ test_expect_success 'git grep' '
        GIT_DIR=../.. GIT_WORK_TREE=.. git grep -l changed | grep dir/tracked)
 '
 
+test_expect_success 'git commit' '
+       (
+               cd repo.git &&
+               GIT_DIR=. GIT_WORK_TREE=work git commit -a -m done
+       )
+'
+
+test_expect_success 'absolute pathspec should fail gracefully' '
+       (
+               cd repo.git || exit 1
+               git config --unset core.worktree
+               test_must_fail git log HEAD -- /home
+       )
+'
+
 test_done
index b61e5169f4e9e8d9f87b9ea16e71dfcf1fb9f340..5ade44c043ca6577b2e331b152515359128dbd32 100755 (executable)
@@ -66,4 +66,21 @@ test_expect_success 'extra character after attribute' '
        invalid_color "dimX"
 '
 
+test_expect_success 'unknown color slots are ignored (diff)' '
+       git config --unset diff.color.new
+       git config color.diff.nosuchslotwilleverbedefined white &&
+       git diff --color
+'
+
+test_expect_success 'unknown color slots are ignored (branch)' '
+       git config color.branch.nosuchslotwilleverbedefined white &&
+       git branch -a
+'
+
+test_expect_success 'unknown color slots are ignored (status)' '
+       git config color.status.nosuchslotwilleverbedefined white || exit
+       git status
+       case $? in 0|1) : ok ;; *) false ;; esac
+'
+
 test_done
index 5858b868ed6ff05d458996cf8c359a7148591582..d05a9138b46eec072750142f912a41caa3e23d83 100755 (executable)
@@ -7,19 +7,19 @@ test_description='Test the post-checkout hook.'
 . ./test-lib.sh
 
 test_expect_success setup '
-        echo Data for commit0. >a &&
-        echo Data for commit0. >b &&
-        git update-index --add a &&
-        git update-index --add b &&
-        tree0=$(git write-tree) &&
-        commit0=$(echo setup | git commit-tree $tree0) &&
-        git update-ref refs/heads/master $commit0 &&
-        git clone ./. clone1 &&
-        git clone ./. clone2 &&
-        GIT_DIR=clone2/.git git branch -a new2 &&
-        echo Data for commit1. >clone2/b &&
-        GIT_DIR=clone2/.git git add clone2/b &&
-        GIT_DIR=clone2/.git git commit -m new2
+       echo Data for commit0. >a &&
+       echo Data for commit0. >b &&
+       git update-index --add a &&
+       git update-index --add b &&
+       tree0=$(git write-tree) &&
+       commit0=$(echo setup | git commit-tree $tree0) &&
+       git update-ref refs/heads/master $commit0 &&
+       git clone ./. clone1 &&
+       git clone ./. clone2 &&
+       GIT_DIR=clone2/.git git branch new2 &&
+       echo Data for commit1. >clone2/b &&
+       GIT_DIR=clone2/.git git add clone2/b &&
+       GIT_DIR=clone2/.git git commit -m new2
 '
 
 for clone in 1 2; do
index e85ff02c3e636567a80586e92fdba1c5382fc995..b8cf2603a195af406d3606712e45fd1195c1588f 100755 (executable)
@@ -139,19 +139,19 @@ test_expect_success \
 test_expect_success \
        'resetting to HEAD with no changes should succeed and do nothing' '
        git reset --hard &&
-               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
        git reset --hard HEAD &&
-               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
        git reset --soft &&
-               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
        git reset --soft HEAD &&
-               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
        git reset --mixed &&
-               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
        git reset --mixed HEAD &&
-               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
        git reset &&
-               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+               check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
        git reset HEAD &&
                check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
index 68041df5f49e046c2b7ccd1f3a1c71071498da39..afb55b3a463f79be83c0e3cc4a8aff8a0c6676be 100755 (executable)
@@ -29,6 +29,12 @@ test_expect_success 'soft reset is ok' '
        (cd .git && git reset --soft)
 '
 
+test_expect_success 'hard reset works with GIT_WORK_TREE' '
+       mkdir worktree &&
+       GIT_WORK_TREE=$PWD/worktree GIT_DIR=$PWD/.git git reset --hard &&
+       test_cmp file worktree/file
+'
+
 test_expect_success 'setup bare' '
        git clone --bare . bare.git &&
        cd bare.git
index 13c25f1d528ca1ec90575e42e0393accff5d8f35..ad834f200ac0d6ecf532374311d896557a9b941d 100755 (executable)
@@ -144,4 +144,17 @@ test_expect_success 'blame path that used to be a directory' '
        git blame HEAD^.. -- path
 '
 
+test_expect_success 'blame to a commit with no author name' '
+  TREE=`git rev-parse HEAD:`
+  cat >badcommit <<EOF
+tree $TREE
+author <noname> 1234567890 +0000
+committer David Reiss <dreiss@facebook.com> 1234567890 +0000
+
+some message
+EOF
+  COMMIT=`git hash-object -t commit -w badcommit`
+  git --no-pager blame $COMMIT -- uno >/dev/null
+'
+
 test_done