Merge branch 'jk/deny-push-to-current'
authorJunio C Hamano <gitster@pobox.com>
Thu, 13 Nov 2008 05:56:14 +0000 (21:56 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 13 Nov 2008 05:56:14 +0000 (21:56 -0800)
* jk/deny-push-to-current:
receive-pack: detect push to current branch of non-bare repo
t5516: refactor oddball tests

55 files changed:
Documentation/RelNotes-1.6.0.5.txt [new file with mode: 0644]
Documentation/git-bisect.txt
Documentation/git-check-attr.txt
Documentation/git-diff.txt
Documentation/git-log.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/rev-list-options.txt
Makefile
builtin-check-attr.c
builtin-checkout.c
builtin-diff.c
builtin-log.c
builtin-ls-remote.c
builtin-pack-objects.c
builtin-read-tree.c
builtin-remote.c
builtin-rev-list.c
builtin-tag.c
bundle.c
cache.h
contrib/fast-import/git-p4
diff.c
diff.h
environment.c
fsck.c
git-bisect.sh
git-gui/git-gui.sh
git-gui/lib/blame.tcl
git-gui/lib/choose_repository.tcl
git-gui/lib/search.tcl
git-submodule.sh
grep.c
hash-object.c
log-tree.c
log-tree.h
path.c
read-cache.c
refs.c
revision.c
revision.h
t/t2005-checkout-index-symlinks.sh
t/t2011-checkout-invalid-head.sh [new file with mode: 0755]
t/t2102-update-index-symlinks.sh
t/t4030-diff-textconv.sh [new file with mode: 0755]
t/t5300-pack-object.sh
t/t6025-merge-symlinks.sh
t/t7004-tag.sh
t/t7502-commit.sh
t/t9400-git-cvsserver-server.sh
unpack-trees.c
userdiff.c
userdiff.h
wt-status.c
xdiff/xprepare.c
diff --git a/Documentation/RelNotes-1.6.0.5.txt b/Documentation/RelNotes-1.6.0.5.txt
new file mode 100644 (file)
index 0000000..62f95e6
--- /dev/null
@@ -0,0 +1,21 @@
+GIT v1.6.0.5 Release Notes
+==========================
+
+Fixes since v1.6.0.4
+--------------------
+
+* 'git checkout' used to crash when your HEAD was pointing at a deleted
+  branch.
+
+* 'git checkout' from an un-checked-out state did not allow switching out
+  of the current branch.
+
+* 'git pack-objects' did not make its best effort to honor --max-pack-size
+  option when a single first object already busted the given limit and
+  placed many objects in a single pack.
+
+* 'make check' cannot be run without sparse; people may have meant to say
+  'make test' instead, so suggest that.
+
+* Many unsafe call to sprintf() style varargs functions are corrected.
+
index c7981efcd9b86287bbea9ddcaf187a9bd48c77eb..39034ec7d6dff42f4be282c4216a7e13ff255d91 100644 (file)
@@ -26,7 +26,7 @@ on the subcommand:
  git bisect log
  git bisect run <cmd>...
 
-This command uses 'git-rev-list --bisect' to help drive the
+This command uses 'git rev-list --bisect' to help drive the
 binary search process to find which change introduced a bug, given an
 old "good" commit object name and a later "bad" commit object name.
 
@@ -101,7 +101,7 @@ $ git bisect visualize
 to see the currently remaining suspects in 'gitk'.  `visualize` is a bit
 too long to type and `view` is provided as a synonym.
 
-If 'DISPLAY' environment variable is not set, 'git-log' is used
+If 'DISPLAY' environment variable is not set, 'git log' is used
 instead.  You can even give command line options such as `-p` and
 `--stat`.
 
@@ -215,7 +215,7 @@ tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or
 work around other problem this bisection is not interested in")
 applied to the revision being tested.
 
-To cope with such a situation, after the inner 'git-bisect' finds the
+To cope with such a situation, after the inner 'git bisect' finds the
 next revision to test, with the "run" script, you can apply that tweak
 before compiling, run the real test, and after the test decides if the
 revision (possibly with the needed tweaks) passed the test, rewind the
index 256659a6b0263415553fdddef087d8af44f716da..8c2ac12f5d316a5db8c5a9be2c4d9639ca30653b 100644 (file)
@@ -3,7 +3,7 @@ git-check-attr(1)
 
 NAME
 ----
-git-check-attr - Display gitattributes information.
+git-check-attr - Display gitattributes information
 
 
 SYNOPSIS
index c53eba557d0a242a0d8553d9569ce8b2eb86331b..a2f192fb7519117f8e47f3ec4608e3301c200dc3 100644 (file)
@@ -33,6 +33,7 @@ forced by --no-index.
        commit relative to the named <commit>.  Typically you
        would want comparison with the latest commit, so if you
        do not give <commit>, it defaults to HEAD.
+       --staged is a synonym of --cached.
 
 'git diff' [--options] <commit> [--] [<path>...]::
 
index 93a2a227c4816720b82330aca1b8c3ab0245b1c1..34cf4e5811d1a6f46fcbd333a2ff48c200eadff8 100644 (file)
@@ -40,6 +40,10 @@ include::diff-options.txt[]
 --decorate::
        Print out the ref names of any commits that are shown.
 
+--source::
+       Print out the ref name given on the command line by which each
+       commit was reached.
+
 --full-diff::
        Without this flag, "git log -p <path>..." shows commits that
        touch the specified paths, and diffs about the same specified
index df420aeb331592192ab27d76af780c8c97a95e87..7e0a04143674506e700f35a1d3c47ed871722064 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.0.2/git.html[documentation for release 1.6.0.2]
+* link:v1.6.0.4/git.html[documentation for release 1.6.0.4]
 
 * release notes for
+  link:RelNotes-1.6.0.4.txt[1.6.0.4],
+  link:RelNotes-1.6.0.3.txt[1.6.0.3],
   link:RelNotes-1.6.0.2.txt[1.6.0.2],
   link:RelNotes-1.6.0.1.txt[1.6.0.1],
   link:RelNotes-1.6.0.txt[1.6.0].
index eb648418eedba4f131aec1f18ccba3bd62f53dc2..a172baf993e5171932533ad713a5d0b34cb6850b 100644 (file)
@@ -216,10 +216,12 @@ Generating diff text
 `diff`
 ^^^^^^
 
-The attribute `diff` affects if 'git-diff' generates textual
-patch for the path or just says `Binary files differ`.  It also
-can affect what line is shown on the hunk header `@@ -k,l +n,m @@`
-line.
+The attribute `diff` affects how 'git' generates diffs for particular
+files. It can tell git whether to generate a textual patch for the path
+or to treat the path as a binary file.  It can also affect what line is
+shown on the hunk header `@@ -k,l +n,m @@` line, tell git to use an
+external command to generate the diff, or ask git to convert binary
+files to a text format before generating the diff.
 
 Set::
 
@@ -230,7 +232,8 @@ Set::
 Unset::
 
        A path to which the `diff` attribute is unset will
-       generate `Binary files differ`.
+       generate `Binary files differ` (or a binary patch, if
+       binary patches are enabled).
 
 Unspecified::
 
@@ -241,21 +244,21 @@ Unspecified::
 
 String::
 
-       Diff is shown using the specified custom diff driver.
-       The driver program is given its input using the same
-       calling convention as used for GIT_EXTERNAL_DIFF
-       program.  This name is also used for custom hunk header
-       selection.
+       Diff is shown using the specified diff driver.  Each driver may
+       specify one or more options, as described in the following
+       section. The options for the diff driver "foo" are defined
+       by the configuration variables in the "diff.foo" section of the
+       git config file.
 
 
-Defining a custom diff driver
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Defining an external diff driver
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 The definition of a diff driver is done in `gitconfig`, not
 `gitattributes` file, so strictly speaking this manual page is a
 wrong place to talk about it.  However...
 
-To define a custom diff driver `jcdiff`, add a section to your
+To define an external diff driver `jcdiff`, add a section to your
 `$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this:
 
 ----------------------------------------------------------------
@@ -331,6 +334,43 @@ patterns are available:
 - `tex` suitable for source code for LaTeX documents.
 
 
+Performing text diffs of binary files
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Sometimes it is desirable to see the diff of a text-converted
+version of some binary files. For example, a word processor
+document can be converted to an ASCII text representation, and
+the diff of the text shown. Even though this conversion loses
+some information, the resulting diff is useful for human
+viewing (but cannot be applied directly).
+
+The `textconv` config option is used to define a program for
+performing such a conversion. The program should take a single
+argument, the name of a file to convert, and produce the
+resulting text on stdout.
+
+For example, to show the diff of the exif information of a
+file instead of the binary information (assuming you have the
+exif tool installed):
+
+------------------------
+[diff "jpg"]
+       textconv = exif
+------------------------
+
+NOTE: The text conversion is generally a one-way conversion;
+in this example, we lose the actual image contents and focus
+just on the text data. This means that diffs generated by
+textconv are _not_ suitable for applying. For this reason,
+only `git diff` and the `git log` family of commands (i.e.,
+log, whatchanged, show) will perform text conversion. `git
+format-patch` will never generate this output. If you want to
+send somebody a text-converted diff of a binary file (e.g.,
+because it quickly conveys the changes you have made), you
+should generate it separately and send it as a comment _in
+addition to_ the usual binary diff that you might send.
+
+
 Performing a three-way merge
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
index 966276b169d6fb09c571a05257dfbc1fe3bd4f03..6d7cf6d51fc5c2511c8ed411ed36aefd93d4ad60 100644 (file)
@@ -285,8 +285,52 @@ See also linkgit:git-reflog[1].
 History Simplification
 ~~~~~~~~~~~~~~~~~~~~~~
 
-When optional paths are given, 'git-rev-list' simplifies commits with
-various strategies, according to the options you have selected.
+Sometimes you are only interested in parts of the history, for example the
+commits modifying a particular <path>. But there are two parts of
+'History Simplification', one part is selecting the commits and the other
+is how to do it, as there are various strategies to simplify the history.
+
+The following options select the commits to be shown:
+
+<paths>::
+
+       Commits modifying the given <paths> are selected.
+
+--simplify-by-decoration::
+
+       Commits that are referred by some branch or tag are selected.
+
+Note that extra commits can be shown to give a meaningful history.
+
+The following options affect the way the simplification is performed:
+
+Default mode::
+
+       Simplifies the history to the simplest history explaining the
+       final state of the tree. Simplest because it prunes some side
+       branches if the end result is the same (i.e. merging branches
+       with the same content)
+
+--full-history::
+
+       As the default mode but does not prune some history.
+
+--dense::
+
+       Only the selected commits are shown, plus some to have a
+       meaningful history.
+
+--sparse::
+
+       All commits in the simplified history are shown.
+
+--simplify-merges::
+
+       Additional option to '--full-history' to remove some needless
+       merges from the resulting history, as there are no selected
+       commits contributing to this merge.
+
+A more detailed explanation follows.
 
 Suppose you specified `foo` as the <paths>.  We shall call commits
 that modify `foo` !TREESAME, and the rest TREESAME.  (In a diff
@@ -456,6 +500,14 @@ Note the major differences in `N` and `P` over '\--full-history':
   removed completely, because it had one parent and is TREESAME.
 --
 
+The '\--simplify-by-decoration' option allows you to view only the
+big picture of the topology of the history, by omitting commits
+that are not referenced by tags.  Commits are marked as !TREESAME
+(in other words, kept after history simplification rules described
+above) if (1) they are referenced by tags, or (2) they change the
+contents of the paths given on the command line.  All other
+commits are marked as TREESAME (subject to be simplified away).
+
 ifdef::git-rev-list[]
 Bisection Helpers
 ~~~~~~~~~~~~~~~~~
@@ -466,14 +518,14 @@ Limit output to the one commit object which is roughly halfway between
 the included and excluded commits. Thus, if
 
 -----------------------------------------------------------------------
-       $ git-rev-list --bisect foo ^bar ^baz
+       $ git rev-list --bisect foo ^bar ^baz
 -----------------------------------------------------------------------
 
 outputs 'midpoint', the output of the two commands
 
 -----------------------------------------------------------------------
-       $ git-rev-list foo ^midpoint
-       $ git-rev-list midpoint ^bar ^baz
+       $ git rev-list foo ^midpoint
+       $ git rev-list midpoint ^bar ^baz
 -----------------------------------------------------------------------
 
 would be of roughly the same length.  Finding the change which
index 220de39914c4df3abf394ad052ebb1fd6f62d3f7..920cb4207844648f9a7ae7e74be8b426543ea7e4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1355,7 +1355,16 @@ check-sha1:: test-sha1$X
        ./test-sha1.sh
 
 check: common-cmds.h
-       for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
+       if sparse; \
+       then \
+               for i in *.c; \
+               do \
+                       sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
+               done; \
+       else \
+               echo 2>&1 "Did you mean 'make test'?"; \
+               exit 1; \
+       fi
 
 remove-dashes:
        ./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS)
index 4921341e33033bb4a2449425d6fd76132a67cd16..15a04b7179a09492764d43c16a3ec5ff7cdd1b61 100644 (file)
@@ -97,7 +97,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
        else if (stdin_paths && doubledash < argc)
                errstr = "Can't specify files with --stdin";
        if (errstr) {
-               error (errstr);
+               error("%s", errstr);
                usage_with_options(check_attr_usage, check_attr_options);
        }
 
index 57b94d282931187a0cb6394d4df707237038a7eb..464fd2570735485a35d34c4aa8d50e5a1930228c 100644 (file)
@@ -47,7 +47,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
 
        memset(&proc, 0, sizeof(proc));
        argv[0] = name;
-       argv[1] = xstrdup(sha1_to_hex(old->object.sha1));
+       argv[1] = xstrdup(sha1_to_hex(old ? old->object.sha1 : null_sha1));
        argv[2] = xstrdup(sha1_to_hex(new->object.sha1));
        argv[3] = changed ? "1" : "0";
        argv[4] = NULL;
@@ -397,8 +397,7 @@ static int merge_working_tree(struct checkout_opts *opts,
                }
 
                /* 2-way merge to the new branch */
-               topts.initial_checkout = (!active_nr &&
-                                         (old->commit == new->commit));
+               topts.initial_checkout = is_cache_unborn();
                topts.update = 1;
                topts.merge = 1;
                topts.gently = opts->merge;
@@ -492,10 +491,10 @@ static void update_refs_for_switch(struct checkout_opts *opts,
        }
 
        old_desc = old->name;
-       if (!old_desc)
+       if (!old_desc && old->commit)
                old_desc = sha1_to_hex(old->commit->object.sha1);
        strbuf_addf(&msg, "checkout: moving from %s to %s",
-                   old_desc, new->name);
+                   old_desc ? old_desc : "(invalid)", new->name);
 
        if (new->path) {
                create_symref("HEAD", new->path, msg.buf);
@@ -551,7 +550,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
         * a new commit, we want to mention the old commit once more
         * to remind the user that it might be lost.
         */
-       if (!opts->quiet && !old.path && new->commit != old.commit)
+       if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
                describe_detached_head("Previous HEAD position was", old.commit);
 
        if (!old.commit) {
index 9c8c295732bf12990b8324bf75968fd68dd41d59..7ceceeb6ff49d60468293941b5f37141e8fc01b9 100644 (file)
@@ -118,7 +118,7 @@ static int builtin_diff_index(struct rev_info *revs,
        int cached = 0;
        while (1 < argc) {
                const char *arg = argv[1];
-               if (!strcmp(arg, "--cached"))
+               if (!strcmp(arg, "--cached") || !strcmp(arg, "--staged"))
                        cached = 1;
                else
                        usage(builtin_diff_usage);
@@ -300,6 +300,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
        }
        DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
        DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
+       DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
 
        /*
         * If the user asked for our exit code then don't start a
@@ -319,7 +320,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
                        const char *arg = argv[i];
                        if (!strcmp(arg, "--"))
                                break;
-                       else if (!strcmp(arg, "--cached")) {
+                       else if (!strcmp(arg, "--cached") ||
+                                !strcmp(arg, "--staged")) {
                                add_head_to_pending(&rev);
                                if (!rev.pending.nr)
                                        die("No HEAD commit to compare with (yet)");
index a0944f70a4a3aa4f5fb08c4ac4ae7dc31d25d532..b164717379627b7bfc303bd3fdf360ecd2db152d 100644 (file)
@@ -28,7 +28,6 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
                      struct rev_info *rev)
 {
        int i;
-       int decorate = 0;
 
        rev->abbrev = DEFAULT_ABBREV;
        rev->commit_format = CMIT_FMT_DEFAULT;
@@ -55,10 +54,13 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
                const char *arg = argv[i];
                if (!strcmp(arg, "--decorate")) {
                        load_ref_decorations();
-                       decorate = 1;
+                       rev->show_decorations = 1;
+               } else if (!strcmp(arg, "--source")) {
+                       rev->show_source = 1;
                } else
                        die("unrecognized argument: %s", arg);
        }
+       DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
 }
 
 /*
index c21b841e7c5e8d27a6e66e7f70786d77aa4653b5..78a88f74769645f0be86aa77d3dee3f5e99c916f 100644 (file)
@@ -4,7 +4,7 @@
 #include "remote.h"
 
 static const char ls_remote_usage[] =
-"git ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
+"git ls-remote [--heads] [--tags]  [-u <exec> | --upload-pack <exec>] <repository> <refs>...";
 
 /*
  * Is there one among the list of patterns that match the tail part
index 15b80db5a1a43ae2ae44375c2cb27978c2e70a71..95e6faf1e6228dcee2fed692c9273e1fccbcef16 100644 (file)
@@ -245,8 +245,16 @@ static unsigned long write_object(struct sha1file *f,
        type = entry->type;
 
        /* write limit if limited packsize and not first object */
-       limit = pack_size_limit && nr_written ?
-                       pack_size_limit - write_offset : 0;
+       if (!pack_size_limit || !nr_written)
+               limit = 0;
+       else if (pack_size_limit <= write_offset)
+               /*
+                * the earlier object did not fit the limit; avoid
+                * mistaking this with unlimited (i.e. limit = 0).
+                */
+               limit = 1;
+       else
+               limit = pack_size_limit - write_offset;
 
        if (!entry->delta)
                usable_delta = 0;       /* no delta */
index 0706c958181c54aeb18d91f6e3dbe7c9f572b94d..38fef34d3fb6c24ab89043951f1ecf6c96e9bf51 100644 (file)
@@ -206,7 +206,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
                        break;
                case 2:
                        opts.fn = twoway_merge;
-                       opts.initial_checkout = !active_nr;
+                       opts.initial_checkout = is_cache_unborn();
                        break;
                case 3:
                default:
index e396a3ac9055aa91d0f808abb196fb6ea9a99a29..47deb0a8028760a7195d11b8212904e312a8998c 100644 (file)
@@ -320,7 +320,7 @@ static int add_branch_for_removal(const char *refname,
 
        /* make sure that symrefs are deleted */
        if (flags & REF_ISSYMREF)
-               return unlink(git_path(refname));
+               return unlink(git_path("%s", refname));
 
        item = string_list_append(refname, branches->branches);
        item->util = xmalloc(20);
index 06cdeb7ebe7468911a7bee670bf5ec539185ba54..857742a14f82e049c5b9e8b234dae9e9e1a7dc30 100644 (file)
@@ -100,7 +100,7 @@ static void show_commit(struct commit *commit)
                        children = children->next;
                }
        }
-       show_decorations(commit);
+       show_decorations(&revs, commit);
        if (revs.commit_format == CMIT_FMT_ONELINE)
                putchar(' ');
        else
index 84db156e63681de6322019b9b9ffa15371c443b1..d339971fab896bda0297f04a4f3961bae27b21be 100644 (file)
@@ -344,7 +344,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        const char *object_ref, *tag;
        struct ref_lock *lock;
 
-       int annotate = 0, sign = 0, force = 0, lines = 0,
+       int annotate = 0, sign = 0, force = 0, lines = -1,
                list = 0, delete = 0, verify = 0;
        const char *msgfile = NULL, *keyid = NULL;
        struct msg_arg msg = { 0, STRBUF_INIT };
@@ -380,9 +380,19 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        }
        if (sign)
                annotate = 1;
+       if (argc == 0 && !(delete || verify))
+               list = 1;
 
+       if ((annotate || msg.given || msgfile || force) &&
+           (list || delete || verify))
+               usage_with_options(git_tag_usage, options);
+
+       if (list + delete + verify > 1)
+               usage_with_options(git_tag_usage, options);
        if (list)
-               return list_tags(argv[0], lines);
+               return list_tags(argv[0], lines == -1 ? 0 : lines);
+       if (lines != -1)
+               die("-n option is only allowed with -l.");
        if (delete)
                return for_each_tag_name(argv, delete_tag);
        if (verify)
@@ -406,11 +416,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                }
        }
 
-       if (argc == 0) {
-               if (annotate)
-                       usage_with_options(git_tag_usage, options);
-               return list_tags(NULL, lines);
-       }
        tag = argv[0];
 
        object_ref = argc == 2 ? argv[1] : "HEAD";
index 7d17a1fde16204859849aaf28945739aaa685f91..daecd8e1cad4a301e2faa3888c561746d029f09d 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -114,7 +114,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
                        continue;
                }
                if (++ret == 1)
-                       error(message);
+                       error("%s", message);
                error("%s %s", sha1_to_hex(e->sha1), e->name);
        }
        if (revs.pending.nr != p->nr)
@@ -139,7 +139,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
        for (i = 0; i < req_nr; i++)
                if (!(refs.objects[i].item->flags & SHOWN)) {
                        if (++ret == 1)
-                               error(message);
+                               error("%s", message);
                        error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
                                refs.objects[i].name);
                }
diff --git a/cache.h b/cache.h
index eda7028992421e3946d93179a0dd6539f43967bb..6be60ea3ff445b7edda2fbfccac3b5e45d1110e8 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -262,6 +262,7 @@ static inline void remove_name_hash(struct cache_entry *ce)
 
 #define read_cache() read_index(&the_index)
 #define read_cache_from(path) read_index_from(&the_index, (path))
+#define is_cache_unborn() is_index_unborn(&the_index)
 #define read_cache_unmerged() read_index_unmerged(&the_index)
 #define write_cache(newfd, cache, entries) write_index(&the_index, (newfd))
 #define discard_cache() discard_index(&the_index)
@@ -368,6 +369,7 @@ extern int init_db(const char *template_dir, unsigned int flags);
 /* Initialize and use the cache information */
 extern int read_index(struct index_state *);
 extern int read_index_from(struct index_state *, const char *path);
+extern int is_index_unborn(struct index_state *);
 extern int read_index_unmerged(struct index_state *);
 extern int write_index(const struct index_state *, int newfd);
 extern int discard_index(struct index_state *);
index 2216cacba79ad7171b7b5abbd1ff27e7b1ef84a1..9f0a5f92c1f01f82aba14fbf3b92fd56a1e0674b 100755 (executable)
@@ -316,8 +316,11 @@ def gitBranchExists(branch):
                             stderr=subprocess.PIPE, stdout=subprocess.PIPE);
     return proc.wait() == 0;
 
+_gitConfig = {}
 def gitConfig(key):
-    return read_pipe("git config %s" % key, ignore_error=True).strip()
+    if not _gitConfig.has_key(key):
+        _gitConfig[key] = read_pipe("git config %s" % key, ignore_error=True).strip()
+    return _gitConfig[key]
 
 def p4BranchesInGit(branchesAreInRemotes = True):
     branches = {}
@@ -946,7 +949,7 @@ class P4Sync(Command):
 
             if includeFile:
                 filesForCommit.append(f)
-                if f['action'] != 'delete':
+                if f['action'] not in ('delete', 'purge'):
                     filesToRead.append(f)
 
         filedata = []
@@ -965,11 +968,11 @@ class P4Sync(Command):
         while j < len(filedata):
             stat = filedata[j]
             j += 1
-            text = [];
+            text = ''
             while j < len(filedata) and filedata[j]['code'] in ('text', 'unicode', 'binary'):
-                text.append(filedata[j]['data'])
+                text += filedata[j]['data']
+                del filedata[j]['data']
                 j += 1
-            text = ''.join(text)
 
             if not stat.has_key('depotFile'):
                 sys.stderr.write("p4 print fails with: %s\n" % repr(stat))
@@ -1038,7 +1041,7 @@ class P4Sync(Command):
                 continue
 
             relPath = self.stripRepoPath(file['path'], branchPrefixes)
-            if file["action"] == "delete":
+            if file["action"] in ("delete", "purge"):
                 self.gitStream.write("D %s\n" % relPath)
             else:
                 data = file['data']
@@ -1077,7 +1080,7 @@ class P4Sync(Command):
 
                 cleanedFiles = {}
                 for info in files:
-                    if info["action"] == "delete":
+                    if info["action"] in ("delete", "purge"):
                         continue
                     cleanedFiles[info["depotFile"]] = info["rev"]
 
@@ -1400,7 +1403,7 @@ class P4Sync(Command):
             if change > newestRevision:
                 newestRevision = change
 
-            if info["action"] == "delete":
+            if info["action"] in ("delete", "purge"):
                 # don't increase the file cnt, otherwise details["depotFile123"] will have gaps!
                 #fileCnt = fileCnt + 1
                 continue
diff --git a/diff.c b/diff.c
index 1918b73d5368d1ad89f501e63777e47763d0d0fe..f644947c823e824a294414a660beac02b4182fe4 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -93,12 +93,6 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
        if (!strcmp(var, "diff.external"))
                return git_config_string(&external_diff_cmd_cfg, var, value);
 
-       switch (userdiff_config_porcelain(var, value)) {
-               case 0: break;
-               case -1: return -1;
-               default: return 0;
-       }
-
        return git_diff_basic_config(var, value, cb);
 }
 
@@ -109,6 +103,12 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
+       switch (userdiff_config(var, value)) {
+               case 0: break;
+               case -1: return -1;
+               default: return 0;
+       }
+
        if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
                int slot = parse_diff_color_slot(var, 11);
                if (!value)
@@ -123,12 +123,6 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       switch (userdiff_config_basic(var, value)) {
-               case 0: break;
-               case -1: return -1;
-               default: return 0;
-       }
-
        return git_color_default_config(var, value, cb);
 }
 
@@ -294,18 +288,8 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
        else if (diff_populate_filespec(one, 0))
                return -1;
 
-       diff_filespec_load_driver(one);
-       if (one->driver->textconv) {
-               size_t size;
-               mf->ptr = run_textconv(one->driver->textconv, one, &size);
-               if (!mf->ptr)
-                       return -1;
-               mf->size = size;
-       }
-       else {
-               mf->ptr = one->data;
-               mf->size = one->size;
-       }
+       mf->ptr = one->data;
+       mf->size = one->size;
        return 0;
 }
 
@@ -1283,7 +1267,7 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two)
        emit_binary_diff_body(file, two, one);
 }
 
-void diff_filespec_load_driver(struct diff_filespec *one)
+static void diff_filespec_load_driver(struct diff_filespec *one)
 {
        if (!one->driver)
                one->driver = userdiff_find_by_path(one->path);
@@ -1324,6 +1308,16 @@ void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const
                options->b_prefix = b;
 }
 
+static const char *get_textconv(struct diff_filespec *one)
+{
+       if (!DIFF_FILE_VALID(one))
+               return NULL;
+       if (!S_ISREG(one->mode))
+               return NULL;
+       diff_filespec_load_driver(one);
+       return one->driver->textconv;
+}
+
 static void builtin_diff(const char *name_a,
                         const char *name_b,
                         struct diff_filespec *one,
@@ -1338,6 +1332,7 @@ static void builtin_diff(const char *name_a,
        const char *set = diff_get_color_opt(o, DIFF_METAINFO);
        const char *reset = diff_get_color_opt(o, DIFF_RESET);
        const char *a_prefix, *b_prefix;
+       const char *textconv_one = NULL, *textconv_two = NULL;
 
        diff_set_mnemonic_prefix(o, "a/", "b/");
        if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
@@ -1391,8 +1386,14 @@ static void builtin_diff(const char *name_a,
        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
                die("unable to read files to diff");
 
+       if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
+               textconv_one = get_textconv(one);
+               textconv_two = get_textconv(two);
+       }
+
        if (!DIFF_OPT_TST(o, TEXT) &&
-           (diff_filespec_is_binary(one) || diff_filespec_is_binary(two))) {
+           ( (diff_filespec_is_binary(one) && !textconv_one) ||
+             (diff_filespec_is_binary(two) && !textconv_two) )) {
                /* Quite common confusing case */
                if (mf1.size == mf2.size &&
                    !memcmp(mf1.ptr, mf2.ptr, mf1.size))
@@ -1413,6 +1414,21 @@ static void builtin_diff(const char *name_a,
                struct emit_callback ecbdata;
                const struct userdiff_funcname *pe;
 
+               if (textconv_one) {
+                       size_t size;
+                       mf1.ptr = run_textconv(textconv_one, one, &size);
+                       if (!mf1.ptr)
+                               die("unable to read files to diff");
+                       mf1.size = size;
+               }
+               if (textconv_two) {
+                       size_t size;
+                       mf2.ptr = run_textconv(textconv_two, two, &size);
+                       if (!mf2.ptr)
+                               die("unable to read files to diff");
+                       mf2.size = size;
+               }
+
                pe = diff_funcname_pattern(one);
                if (!pe)
                        pe = diff_funcname_pattern(two);
@@ -1445,6 +1461,10 @@ static void builtin_diff(const char *name_a,
                              &xpp, &xecfg, &ecb);
                if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS))
                        free_diff_words_data(&ecbdata);
+               if (textconv_one)
+                       free(mf1.ptr);
+               if (textconv_two)
+                       free(mf2.ptr);
        }
 
  free_ab_and_return:
diff --git a/diff.h b/diff.h
index a49d865bd9cb0fa5ff27ccad7049074afb0002e9..42582edee68a4a4717ae5debebf37e6b9610fc8f 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -65,6 +65,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
 #define DIFF_OPT_IGNORE_SUBMODULES   (1 << 18)
 #define DIFF_OPT_DIRSTAT_CUMULATIVE  (1 << 19)
 #define DIFF_OPT_DIRSTAT_BY_FILE     (1 << 20)
+#define DIFF_OPT_ALLOW_TEXTCONV      (1 << 21)
 #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)
 #define DIFF_OPT_CLR(opts, flag)    ((opts)->flags &= ~DIFF_OPT_##flag)
index bf93a598d0e2c4aedbc4065a43df0e9750f93a1c..bb96ac0a71bc5614cd3352902586ff0a70a4eece 100644 (file)
@@ -118,7 +118,7 @@ const char *get_git_work_tree(void)
                        work_tree = git_work_tree_cfg;
                        /* make_absolute_path also normalizes the path */
                        if (work_tree && !is_absolute_path(work_tree))
-                               work_tree = xstrdup(make_absolute_path(git_path(work_tree)));
+                               work_tree = xstrdup(make_absolute_path(git_path("%s", work_tree)));
                } else if (work_tree)
                        work_tree = xstrdup(make_absolute_path(work_tree));
                git_work_tree_initialized = 1;
diff --git a/fsck.c b/fsck.c
index 0cf5f012bdfa876fae4e15ed9cb94ed304314bf6..97f76c58155249412d7c59e965b564dfc0f75181 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -326,7 +326,7 @@ int fsck_error_function(struct object *obj, int type, const char *fmt, ...)
                        die("this should not happen, your snprintf is broken");
        }
 
-       error(sb.buf);
+       error("%s", sb.buf);
        strbuf_release(&sb);
        return 1;
 }
index 79de7017e88b746971f5a730b8615290bba2890d..0d0e278c92c39f17b368eb6ead781a877bc8caed 100755 (executable)
@@ -455,7 +455,7 @@ bisect_next() {
        good=$(git for-each-ref --format='^%(objectname)' \
                "refs/bisect/good-*" | tr '\012' ' ') &&
        skip=$(git for-each-ref --format='%(objectname)' \
-               "refs/bisect/skip-*" | tr '\012' ' ') &&
+               "refs/bisect/skip-*" | tr '\012' ' ') || exit
 
        # Maybe some merge bases must be tested first
        check_good_are_ancestors_of_bad "$bad" "$good" "$skip"
index 12b496bec9233a86da18a45073d964bd559f059c..cf9ef6ee07244b28ab7725aec8fb595ee613644a 100755 (executable)
@@ -997,6 +997,17 @@ citool {
 }
 }
 
+######################################################################
+##
+## execution environment
+
+set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
+
+# Suggest our implementation of askpass, if none is set
+if {![info exists env(SSH_ASKPASS)]} {
+       set env(SSH_ASKPASS) [gitexec git-gui--askpass]
+}
+
 ######################################################################
 ##
 ## repository setup
@@ -1073,15 +1084,6 @@ set selected_commit_type new
 set nullid "0000000000000000000000000000000000000000"
 set nullid2 "0000000000000000000000000000000000000001"
 
-set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
-
-######################################################################
-
-# Suggest our implementation of askpass, if none is set
-if {![info exists env(SSH_ASKPASS)]} {
-       set env(SSH_ASKPASS) [gitexec git-gui--askpass]
-}
-
 ######################################################################
 ##
 ## task management
index 765d08c004b68254713e2524b53d6df0bdc0c007..c1cd7f3b92fddb60be9fe261d7b75c5df85b60c1 100644 (file)
@@ -321,7 +321,7 @@ constructor new {i_commit i_path i_jump} {
                        tk_popup $w.ctxm %X %Y
                "
                bind $i <Shift-Tab> "[list focus $w_cviewer];break"
-               bind $i <Tab>       "[list focus $w_cviewer];break"
+               bind $i <Tab>       "[cb _focus_search $w_cviewer];break"
        }
 
        foreach i [concat $w_columns $w_cviewer] {
@@ -337,10 +337,10 @@ constructor new {i_commit i_path i_jump} {
                bind $i <Control-Key-f> {catch {%W yview scroll  1 pages};break}
        }
 
-       bind $w_cviewer <Shift-Tab> "[list focus $w_file];break"
+       bind $w_cviewer <Shift-Tab> "[cb _focus_search $w_file];break"
        bind $w_cviewer <Tab>       "[list focus $w_file];break"
-       bind $w_cviewer <Button-1> [list focus $w_cviewer]
-       bind $w_file    <Visibility> [list focus $w_file]
+       bind $w_cviewer <Button-1>   [list focus $w_cviewer]
+       bind $w_file    <Visibility> [cb _focus_search $w_file]
        bind $top       <F7>         [list searchbar::show $finder]
        bind $top       <Escape>     [list searchbar::hide $finder]
        bind $top       <F3>         [list searchbar::find_next $finder]
@@ -382,6 +382,14 @@ constructor new {i_commit i_path i_jump} {
        _load $this $i_jump
 }
 
+method _focus_search {win} {
+       if {[searchbar::visible $finder]} {
+               focus [searchbar::editor $finder]
+       } else {
+               focus $win
+       }
+}
+
 method _handle_destroy {win} {
        if {$win eq $w} {
                _kill $this
@@ -551,7 +559,7 @@ method _read_file {fd jump} {
 } ifdeleted { catch {close $fd} }
 
 method _exec_blame {cur_w cur_d options cur_s} {
-       lappend options --incremental
+       lappend options --incremental --encoding=utf-8
        if {$commit eq {}} {
                lappend options --contents $path
        } else {
index 909131689ea837cb67bd587a6acc8b5eb3127c4e..f9ff62a3b22fcc481c88dc35268d06d2fc4a5795 100644 (file)
@@ -43,12 +43,18 @@ constructor pick {} {
                        $w.mbar.apple add command \
                                -label [mc "About %s" [appname]] \
                                -command do_about
+                       $w.mbar.apple add command \
+                               -label [mc "Show SSH Key"] \
+                               -command do_ssh_key
                } else {
                        $w.mbar add cascade -label [mc Help] -menu $w.mbar.help
                        menu $w.mbar.help
                        $w.mbar.help add command \
                                -label [mc "About %s" [appname]] \
                                -command do_about
+                       $w.mbar.help add command \
+                               -label [mc "Show SSH Key"] \
+                               -command do_ssh_key
                }
 
                wm protocol $top WM_DELETE_WINDOW exit
index d292f20f66a6319c34c3b38e28ebc120e7dd8400..32c8656fc9b15498073a09e516777f71827dc3b1 100644 (file)
@@ -19,11 +19,11 @@ constructor new {i_w i_text args} {
 
        frame  $w
        label  $w.l       -text [mc Find:]
+       entry  $w.ent -textvariable ${__this}::searchstring -background lightgreen
        button $w.bn      -text [mc Next] -command [cb find_next]
        button $w.bp      -text [mc Prev] -command [cb find_prev]
        checkbutton $w.cs -text [mc Case-Sensitive] \
                -variable ${__this}::casesensitive -command [cb _incrsearch]
-       entry  $w.ent -textvariable ${__this}::searchstring -background lightgreen
        pack   $w.l   -side left
        pack   $w.cs  -side right
        pack   $w.bp  -side right
@@ -40,19 +40,27 @@ constructor new {i_w i_text args} {
 }
 
 method show {} {
-       if {![winfo ismapped $w]} {
+       if {![visible $this]} {
                grid $w
        }
        focus -force $w.ent
 }
 
 method hide {} {
-       if {[winfo ismapped $w]} {
+       if {[visible $this]} {
                focus $ctext
                grid remove $w
        }
 }
 
+method visible {} {
+       return [winfo ismapped $w]
+}
+
+method editor {} {
+       return $w.ent
+}
+
 method _get_new_anchor {} {
        # use start of selection if it is visible,
        # or the bounds of the visible area
index b63e5c30874bfa382c7d6d0ca1942d116930b62a..220d94ec0c53c9d6c4535d1e50f5d1cb9dc99689 100755 (executable)
@@ -323,7 +323,7 @@ cmd_update()
                        # Only mention uninitialized submodules when its
                        # path have been specified
                        test "$#" != "0" &&
-                       say "Submodule path '$path' not initialized"
+                       say "Submodule path '$path' not initialized" &&
                        say "Maybe you want to use 'update --init'?"
                        continue
                fi
diff --git a/grep.c b/grep.c
index e2c190a7f66f9e9311f91d9a41b7dc3f295f00fb..600f69f2fe2a0271f4bdf736f95f70c8f7381aa4 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -514,7 +514,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
                                if (from <= last_shown)
                                        from = last_shown + 1;
                                if (last_shown && from != last_shown + 1)
-                                       printf(hunk_mark);
+                                       fputs(hunk_mark, stdout);
                                while (from < lno) {
                                        pcl = &prev[lno-from-1];
                                        show_line(opt, pcl->bol, pcl->eol,
@@ -524,7 +524,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
                                last_shown = lno-1;
                        }
                        if (last_shown && lno != last_shown + 1)
-                               printf(hunk_mark);
+                               fputs(hunk_mark, stdout);
                        if (!opt->count)
                                show_line(opt, bol, eol, name, lno, ':');
                        last_shown = last_hit = lno;
@@ -535,7 +535,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
                         * we need to show this line.
                         */
                        if (last_shown && lno != last_shown + 1)
-                               printf(hunk_mark);
+                               fputs(hunk_mark, stdout);
                        show_line(opt, bol, eol, name, lno, '-');
                        last_shown = lno;
                }
index 20937ff94c1ce6ab7984d7b6b1903307e303eb60..846e91a23126b747fbea8d9a8511f708c3d70e43 100644 (file)
@@ -110,7 +110,7 @@ int main(int argc, const char **argv)
        }
 
        if (errstr) {
-               error (errstr);
+               error("%s", errstr);
                usage_with_options(hash_object_usage, hash_object_options);
        }
 
index cec3c061360e9d33068fdb6c2555b69cc11f6771..5444f0860b2150d440dfbd5a4be4aa2daa1316fc 100644 (file)
@@ -52,11 +52,15 @@ static void show_parents(struct commit *commit, int abbrev)
        }
 }
 
-void show_decorations(struct commit *commit)
+void show_decorations(struct rev_info *opt, struct commit *commit)
 {
        const char *prefix;
        struct name_decoration *decoration;
 
+       if (opt->show_source && commit->util)
+               printf(" %s", (char *) commit->util);
+       if (!opt->show_decorations)
+               return;
        decoration = lookup_decoration(&name_decoration, &commit->object);
        if (!decoration)
                return;
@@ -279,7 +283,7 @@ void show_log(struct rev_info *opt)
                fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), stdout);
                if (opt->print_parents)
                        show_parents(commit, abbrev_commit);
-               show_decorations(commit);
+               show_decorations(opt, commit);
                if (opt->graph && !graph_is_commit_finished(opt->graph)) {
                        putchar('\n');
                        graph_show_remainder(opt->graph);
@@ -352,7 +356,7 @@ void show_log(struct rev_info *opt)
                        printf(" (from %s)",
                               diff_unique_abbrev(parent->object.sha1,
                                                  abbrev_commit));
-               show_decorations(commit);
+               show_decorations(opt, commit);
                printf("%s", diff_get_color_opt(&opt->diffopt, DIFF_RESET));
                if (opt->commit_format == CMIT_FMT_ONELINE) {
                        putchar(' ');
index 3c8127bb7cc8d27ff1e91ad6c159bc718fb7d9d0..f2a90084ae1874632318c7880e95426eca2682ea 100644 (file)
@@ -12,7 +12,7 @@ int log_tree_diff_flush(struct rev_info *);
 int log_tree_commit(struct rev_info *, struct commit *);
 int log_tree_opt_parse(struct rev_info *, const char **, int);
 void show_log(struct rev_info *opt);
-void show_decorations(struct commit *commit);
+void show_decorations(struct rev_info *opt, struct commit *commit);
 void log_write_email_headers(struct rev_info *opt, const char *name,
                             const char **subject_p,
                             const char **extra_headers_p,
diff --git a/path.c b/path.c
index eb24017535f944a2c5dbc46663c02937cff69cd3..a074aea64921eb1fb90f079ede9087e6b8109f6a 100644 (file)
--- a/path.c
+++ b/path.c
@@ -41,7 +41,7 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...)
        len = vsnprintf(buf, n, fmt, args);
        va_end(args);
        if (len >= n) {
-               snprintf(buf, n, bad_path);
+               strlcpy(buf, bad_path, n);
                return buf;
        }
        return cleanup_path(buf);
@@ -63,7 +63,7 @@ static char *git_vsnpath(char *buf, size_t n, const char *fmt, va_list args)
                goto bad;
        return cleanup_path(buf);
 bad:
-       snprintf(buf, n, bad_path);
+       strlcpy(buf, bad_path, n);
        return buf;
 }
 
index 2c450866ce92eee2ef484dd798f332cb0047a61d..22a814311d2cfc032129b43f6da56706c7026b9c 100644 (file)
@@ -1269,6 +1269,11 @@ int read_index_from(struct index_state *istate, const char *path)
        die("index file corrupt");
 }
 
+int is_index_unborn(struct index_state *istate)
+{
+       return (!istate->cache_nr && !istate->alloc && !istate->timestamp);
+}
+
 int discard_index(struct index_state *istate)
 {
        istate->cache_nr = 0;
diff --git a/refs.c b/refs.c
index 42bde72ddbab4a7b338e9072f3c7ab17549cb361..33ced65a7801f8653d608a9580e237ce8df39ae2 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -940,7 +940,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
                        lock->lk->filename[i] = 0;
                        path = lock->lk->filename;
                } else {
-                       path = git_path(refname);
+                       path = git_path("%s", refname);
                }
                err = unlink(path);
                if (err && errno != ENOENT) {
index 2f646deab09c423143185b7f7928ae46ab9f4c97..9dc55d4003301c0ededbd6059e16cabf5684766b 100644 (file)
@@ -11,6 +11,7 @@
 #include "reflog-walk.h"
 #include "patch-ids.h"
 #include "decorate.h"
+#include "log-tree.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -199,6 +200,8 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object
                        mark_parents_uninteresting(commit);
                        revs->limited = 1;
                }
+               if (revs->show_source && !commit->util)
+                       commit->util = (void *) name;
                return commit;
        }
 
@@ -292,10 +295,31 @@ static void file_change(struct diff_options *options,
        DIFF_OPT_SET(options, HAS_CHANGES);
 }
 
-static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
+static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct commit *commit)
 {
+       struct tree *t1 = parent->tree;
+       struct tree *t2 = commit->tree;
+
        if (!t1)
                return REV_TREE_NEW;
+
+       if (revs->simplify_by_decoration) {
+               /*
+                * If we are simplifying by decoration, then the commit
+                * is worth showing if it has a tag pointing at it.
+                */
+               if (lookup_decoration(&name_decoration, &commit->object))
+                       return REV_TREE_DIFFERENT;
+               /*
+                * A commit that is not pointed by a tag is uninteresting
+                * if we are not limited by path.  This means that you will
+                * see the usual "commits that touch the paths" plus any
+                * tagged commit by specifying both --simplify-by-decoration
+                * and pathspec.
+                */
+               if (!revs->prune_data)
+                       return REV_TREE_SAME;
+       }
        if (!t2)
                return REV_TREE_DIFFERENT;
        tree_difference = REV_TREE_SAME;
@@ -306,12 +330,13 @@ static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree
        return tree_difference;
 }
 
-static int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1)
+static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
 {
        int retval;
        void *tree;
        unsigned long size;
        struct tree_desc empty, real;
+       struct tree *t1 = commit->tree;
 
        if (!t1)
                return 0;
@@ -345,7 +370,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                return;
 
        if (!commit->parents) {
-               if (rev_same_tree_as_empty(revs, commit->tree))
+               if (rev_same_tree_as_empty(revs, commit))
                        commit->object.flags |= TREESAME;
                return;
        }
@@ -365,7 +390,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                        die("cannot simplify commit %s (because of %s)",
                            sha1_to_hex(commit->object.sha1),
                            sha1_to_hex(p->object.sha1));
-               switch (rev_compare_tree(revs, p->tree, commit->tree)) {
+               switch (rev_compare_tree(revs, p, commit)) {
                case REV_TREE_SAME:
                        tree_same = 1;
                        if (!revs->simplify_history || (p->object.flags & UNINTERESTING)) {
@@ -385,7 +410,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
 
                case REV_TREE_NEW:
                        if (revs->remove_empty_trees &&
-                           rev_same_tree_as_empty(revs, p->tree)) {
+                           rev_same_tree_as_empty(revs, p)) {
                                /* We are adding all the specified
                                 * paths from this parent, so the
                                 * history beyond this parent is not
@@ -484,6 +509,8 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
 
                if (parse_commit(p) < 0)
                        return -1;
+               if (revs->show_source && !p->util)
+                       p->util = commit->util;
                p->object.flags |= left_flag;
                if (!(p->object.flags & SEEN)) {
                        p->object.flags |= SEEN;
@@ -1033,6 +1060,14 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->rewrite_parents = 1;
                revs->simplify_history = 0;
                revs->limited = 1;
+       } else if (!strcmp(arg, "--simplify-by-decoration")) {
+               revs->simplify_merges = 1;
+               revs->rewrite_parents = 1;
+               revs->simplify_history = 0;
+               revs->simplify_by_decoration = 1;
+               revs->limited = 1;
+               revs->prune = 1;
+               load_ref_decorations();
        } else if (!strcmp(arg, "--date-order")) {
                revs->lifo = 0;
                revs->topo_order = 1;
index 2fdb2dd0ff3425b68b47aa8fd11155aa881d4a4a..7cf848771b5be811f7741ce988b860760202f6f3 100644 (file)
@@ -43,6 +43,7 @@ struct rev_info {
                        lifo:1,
                        topo_order:1,
                        simplify_merges:1,
+                       simplify_by_decoration:1,
                        tag_objects:1,
                        tree_objects:1,
                        blob_objects:1,
@@ -53,6 +54,8 @@ struct rev_info {
                        left_right:1,
                        rewrite_parents:1,
                        print_parents:1,
+                       show_source:1,
+                       show_decorations:1,
                        reverse:1,
                        reverse_output_stage:1,
                        cherry_pick:1,
index ed12c4d78298dec9c5f1bf83f4f877b07d2659c0..9fa561047430ae40a1860131a024e4fd7744f5cb 100755 (executable)
@@ -13,7 +13,7 @@ file if core.symlinks is false.'
 test_expect_success \
 'preparation' '
 git config core.symlinks false &&
-l=$(echo -n file | git hash-object -t blob -w --stdin) &&
+l=$(printf file | git hash-object -t blob -w --stdin) &&
 echo "120000 $l        symlink" | git update-index --index-info'
 
 test_expect_success \
diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh
new file mode 100755 (executable)
index 0000000..764bb0a
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+test_description='checkout switching away from an invalid branch'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       echo hello >world &&
+       git add world &&
+       git commit -m initial
+'
+
+test_expect_success 'checkout master from invalid HEAD' '
+       echo 0000000000000000000000000000000000000000 >.git/HEAD &&
+       git checkout master --
+'
+
+test_done
index f195aefe3a207fa5bac447b59f16423da25abc21..1ed44ee503f9ecfb5222a9bce3f42ff2aa8127bc 100755 (executable)
@@ -13,12 +13,12 @@ even if a plain file is in the working tree if core.symlinks is false.'
 test_expect_success \
 'preparation' '
 git config core.symlinks false &&
-l=$(echo -n file | git hash-object -t blob -w --stdin) &&
+l=$(printf file | git hash-object -t blob -w --stdin) &&
 echo "120000 $l        symlink" | git update-index --index-info'
 
 test_expect_success \
 'modify the symbolic link' '
-echo -n new-file > symlink &&
+printf new-file > symlink &&
 git update-index symlink'
 
 test_expect_success \
diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh
new file mode 100755 (executable)
index 0000000..03ba26a
--- /dev/null
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+test_description='diff.*.textconv tests'
+. ./test-lib.sh
+
+find_diff() {
+       sed '1,/^index /d' | sed '/^-- $/,$d'
+}
+
+cat >expect.binary <<'EOF'
+Binary files a/file and b/file differ
+EOF
+
+cat >expect.text <<'EOF'
+--- a/file
++++ b/file
+@@ -1 +1,2 @@
+ 0
++1
+EOF
+
+cat >hexdump <<'EOF'
+#!/bin/sh
+perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' "$1"
+EOF
+chmod +x hexdump
+
+test_expect_success 'setup binary file with history' '
+       printf "\\0\\n" >file &&
+       git add file &&
+       git commit -m one &&
+       printf "\\1\\n" >>file &&
+       git add file &&
+       git commit -m two
+'
+
+test_expect_success 'file is considered binary by porcelain' '
+       git diff HEAD^ HEAD >diff &&
+       find_diff <diff >actual &&
+       test_cmp expect.binary actual
+'
+
+test_expect_success 'file is considered binary by plumbing' '
+       git diff-tree -p HEAD^ HEAD >diff &&
+       find_diff <diff >actual &&
+       test_cmp expect.binary actual
+'
+
+test_expect_success 'setup textconv filters' '
+       echo file diff=foo >.gitattributes &&
+       git config diff.foo.textconv "$PWD"/hexdump &&
+       git config diff.fail.textconv false
+'
+
+test_expect_success 'diff produces text' '
+       git diff HEAD^ HEAD >diff &&
+       find_diff <diff >actual &&
+       test_cmp expect.text actual
+'
+
+test_expect_success 'diff-tree produces binary' '
+       git diff-tree -p HEAD^ HEAD >diff &&
+       find_diff <diff >actual &&
+       test_cmp expect.binary actual
+'
+
+test_expect_success 'log produces text' '
+       git log -1 -p >log &&
+       find_diff <log >actual &&
+       test_cmp expect.text actual
+'
+
+test_expect_success 'format-patch produces binary' '
+       git format-patch --no-binary --stdout HEAD^ >patch &&
+       find_diff <patch >actual &&
+       test_cmp expect.binary actual
+'
+
+test_expect_success 'status -v produces text' '
+       git reset --soft HEAD^ &&
+       git status -v >diff &&
+       find_diff <diff >actual &&
+       test_cmp expect.text actual &&
+       git reset --soft HEAD@{1}
+'
+
+cat >expect.stat <<'EOF'
+ file |  Bin 2 -> 4 bytes
+ 1 files changed, 0 insertions(+), 0 deletions(-)
+EOF
+test_expect_success 'diffstat does not run textconv' '
+       echo file diff=fail >.gitattributes &&
+       git diff --stat HEAD^ HEAD >actual &&
+       test_cmp expect.stat actual
+'
+# restore working setup
+echo file diff=foo >.gitattributes
+
+cat >expect.typechange <<'EOF'
+--- a/file
++++ /dev/null
+@@ -1,2 +0,0 @@
+-0
+-1
+diff --git a/file b/file
+new file mode 120000
+index ad8b3d2..67be421
+--- /dev/null
++++ b/file
+@@ -0,0 +1 @@
++frotz
+\ No newline at end of file
+EOF
+# make a symlink the hard way that works on symlink-challenged file systems
+test_expect_success 'textconv does not act on symlinks' '
+       printf frotz > file &&
+       git add file &&
+       git ls-files -s | sed -e s/100644/120000/ |
+               git update-index --index-info &&
+       git commit -m typechange &&
+       git show >diff &&
+       find_diff <diff >actual &&
+       test_cmp expect.typechange actual
+'
+
+test_done
index b335c6b42de59b9632ff29693c2d7c75dae9794a..04522857abb716b8866e0f5153ec33b3ac780536 100755 (executable)
@@ -376,4 +376,10 @@ test_expect_success 'index-pack with --strict' '
        )
 '
 
+test_expect_success 'tolerate absurdly small packsizelimit' '
+       git config pack.packSizeLimit 2 &&
+       packname_9=$(git pack-objects test-9 <obj-list) &&
+       test $(wc -l <obj-list) = $(ls test-9-*.pack | wc -l)
+'
+
 test_done
index 53892a555ce2e4a51db15066771f217a135e15e9..433c4de08f0cc8d220d5368ab2ab0dffde372482 100755 (executable)
@@ -18,11 +18,11 @@ git add file &&
 git commit -m initial &&
 git branch b-symlink &&
 git branch b-file &&
-l=$(echo -n file | git hash-object -t blob -w --stdin) &&
+l=$(printf file | git hash-object -t blob -w --stdin) &&
 echo "120000 $l        symlink" | git update-index --index-info &&
 git commit -m master &&
 git checkout b-symlink &&
-l=$(echo -n file-different | git hash-object -t blob -w --stdin) &&
+l=$(printf file-different | git hash-object -t blob -w --stdin) &&
 echo "120000 $l        symlink" | git update-index --index-info &&
 git commit -m b-symlink &&
 git checkout b-file &&
index f0edbf1a76739177943006461b853ec17e8bbb2b..f377fea4bb1d32c95096defb9fb08b291b67dbff 100755 (executable)
@@ -1090,4 +1090,15 @@ test_expect_success 'filename for the message is relative to cwd' '
        git cat-file tag tag-from-subdir-2 | grep "in sub directory"
 '
 
+# mixing modes and options:
+
+test_expect_success 'mixing incompatibles modes and options is forbidden' '
+       test_must_fail git tag -a
+       test_must_fail git tag -l -v
+       test_must_fail git tag -n 100
+       test_must_fail git tag -l -m msg
+       test_must_fail git tag -l -F some file
+       test_must_fail git tag -v -s
+'
+
 test_done
index 3eb9faedcf75c7b8a535b369e5a19107c6e81026..ad42c78d7c21497a6ebb4e9cef4efd6334f947da 100755 (executable)
@@ -89,6 +89,14 @@ test_expect_success 'verbose' '
 
 '
 
+test_expect_success 'verbose respects diff config' '
+
+       git config color.diff always &&
+       git status -v >actual &&
+       grep "\[1mdiff --git" actual &&
+       git config --unset color.diff
+'
+
 test_expect_success 'cleanup commit messages (verbatim,-t)' '
 
        echo >>negative &&
index c1850d29239f8846c42b4552493d2d4898fa221e..6a37f71d11800f92a117bfdcf38172bfc9000d77 100755 (executable)
@@ -424,7 +424,7 @@ cd "$WORKDIR"
 test_expect_success 'cvs update (-p)' '
     touch really-empty &&
     echo Line 1 > no-lf &&
-    echo -n Line 2 >> no-lf &&
+    printf "Line 2" >> no-lf &&
     git add really-empty no-lf &&
     git commit -q -m "Update -p test" &&
     git push gitcvs.git >/dev/null &&
index e5749ef638b4a9a490894d9d4fc5876d904ab9ac..54f301da67be879c80426bc21776427fdd38c02e 100644 (file)
@@ -352,7 +352,7 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
        discard_index(&o->result);
        if (!o->gently) {
                if (message)
-                       return error(message);
+                       return error("%s", message);
                return -1;
        }
        return -1;
index d95257ab3bd4fafa59b3ed2aa58c480de274227d..3681062ebfef85af08d71ed6e1ff734804906d6a 100644 (file)
@@ -120,7 +120,7 @@ static int parse_tristate(int *b, const char *k, const char *v)
        return 1;
 }
 
-int userdiff_config_basic(const char *k, const char *v)
+int userdiff_config(const char *k, const char *v)
 {
        struct userdiff_driver *drv;
 
@@ -130,14 +130,6 @@ int userdiff_config_basic(const char *k, const char *v)
                return parse_funcname(&drv->funcname, k, v, REG_EXTENDED);
        if ((drv = parse_driver(k, v, "binary")))
                return parse_tristate(&drv->binary, k, v);
-
-       return 0;
-}
-
-int userdiff_config_porcelain(const char *k, const char *v)
-{
-       struct userdiff_driver *drv;
-
        if ((drv = parse_driver(k, v, "command")))
                return parse_string(&drv->external, k, v);
        if ((drv = parse_driver(k, v, "textconv")))
index f29c18ffb302dc009d438a08800c4aa202fd2f12..ba2945770b379f51aa8da45d112a2ef896ec4c10 100644 (file)
@@ -14,8 +14,7 @@ struct userdiff_driver {
        const char *textconv;
 };
 
-int userdiff_config_basic(const char *k, const char *v);
-int userdiff_config_porcelain(const char *k, const char *v);
+int userdiff_config(const char *k, const char *v);
 struct userdiff_driver *userdiff_find_by_name(const char *name);
 struct userdiff_driver *userdiff_find_by_path(const char *path);
 
index c3a9cab8980daa38e647a13eb2f0fcb42fbfbb8e..6a7645ed86fd5879e959460011a8add015d392d9 100644 (file)
@@ -301,8 +301,17 @@ static void wt_status_print_verbose(struct wt_status *s)
        setup_revisions(0, NULL, &rev, s->reference);
        rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
        rev.diffopt.detect_rename = 1;
+       DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
        rev.diffopt.file = s->fp;
        rev.diffopt.close_file = 0;
+       /*
+        * If we're not going to stdout, then we definitely don't
+        * want color, since we are going to the commit message
+        * file (and even the "auto" setting won't work, since it
+        * will have checked isatty on stdout).
+        */
+       if (s->fp != stdout)
+               DIFF_OPT_CLR(&rev.diffopt, COLOR_DIFF);
        run_diff_index(&rev, 1);
 }
 
@@ -422,5 +431,5 @@ int git_status_config(const char *k, const char *v, void *cb)
                        return error("Invalid untracked files mode '%s'", v);
                return 0;
        }
-       return git_color_default_config(k, v, cb);
+       return git_diff_ui_config(k, v, cb);
 }
index e87ab57c652b56b1a684e2a0a56885c1d1b27ef7..a43aa72cd088af07b13a6bc8de304ecc178047e5 100644 (file)
 #include "xinclude.h"
 
 
-
 #define XDL_KPDIS_RUN 4
 #define XDL_MAX_EQLIMIT 1024
-
+#define XDL_SIMSCAN_WINDOW 100
 
 
 typedef struct s_xdlclass {
@@ -312,6 +311,18 @@ void xdl_free_env(xdfenv_t *xe) {
 static int xdl_clean_mmatch(char const *dis, long i, long s, long e) {
        long r, rdis0, rpdis0, rdis1, rpdis1;
 
+       /*
+        * Limits the window the is examined during the similar-lines
+        * scan. The loops below stops when dis[i - r] == 1 (line that
+        * has no match), but there are corner cases where the loop
+        * proceed all the way to the extremities by causing huge
+        * performance penalties in case of big files.
+        */
+       if (i - s > XDL_SIMSCAN_WINDOW)
+               s = i - XDL_SIMSCAN_WINDOW;
+       if (e - i > XDL_SIMSCAN_WINDOW)
+               e = i + XDL_SIMSCAN_WINDOW;
+
        /*
         * Scans the lines before 'i' to find a run of lines that either
         * have no match (dis[j] == 0) or have multiple matches (dis[j] > 1).