Merge branch 'lt/maint-rev-list-gitlink' into maint
authorJunio C Hamano <gitster@pobox.com>
Sun, 25 Nov 2007 02:03:20 +0000 (18:03 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sun, 25 Nov 2007 02:03:20 +0000 (18:03 -0800)
* lt/maint-rev-list-gitlink:
Fix rev-list when showing objects involving submodules

35 files changed:
Documentation/RelNotes-1.5.3.6.txt
Documentation/config.txt
Documentation/core-tutorial.txt
Documentation/git-get-tar-commit-id.txt
Documentation/git-reflog.txt
Documentation/git-remote.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
builtin-add.c
builtin-apply.c
builtin-branch.c
builtin-bundle.c
builtin-grep.c
builtin-log.c
builtin-rev-list.c
builtin-show-branch.c
cache.h
check-racy.c
commit.c
commit.h
diff-lib.c
diff.h
entry.c
git-commit.sh
git-send-email.perl
log-tree.c
read-cache.c
t/t2200-add-update.sh
t/t4018-diff-funcname.sh [changed mode: 0644->0755]
t/t4021-format-patch-signer-mime.sh [new file with mode: 0755]
t/t5510-fetch.sh
t/t7005-editor.sh
t/t7501-commit.sh [changed mode: 0644->0755]
templates/hooks--pre-commit
unpack-trees.c
index c9f948ec0e3586919cedbc4cc26e5c5a3d49de4d..069a2b2cf9e9f28a2f9e6dc0817723a38b25f475 100644 (file)
@@ -4,16 +4,18 @@ GIT v1.5.3.6 Release Notes
 Fixes since v1.5.3.5
 --------------------
 
- * git-cvsexportcommit handles root commits better;
+ * git-cvsexportcommit handles root commits better.
 
  * git-svn dcommit used to clobber when sending a series of
-   patches;
+   patches.
 
  * git-svn dcommit failed after attempting to rebase when
    started with a dirty index; now it stops upfront.
 
  * git-grep sometimes refused to work when your index was
-   unmerged;
+   unmerged.
+
+ * "git-grep -A1 -B2" acted as if it was told to run "git -A1 -B21".
 
  * git-hash-object did not honor configuration variables, such as
    core.compression.
@@ -44,9 +46,3 @@ Fixes since v1.5.3.5
    of deflateBound() has been added.
 
  * Quite a lot of documentation clarifications.
-
---
-exec >/var/tmp/1
-O=v1.5.3.5-57-gb574c8d
-echo O=`git describe refs/heads/maint`
-git shortlog --no-merges $O..refs/heads/maint
index 7ee97df8a70cd6c6b127d7d32f5e325acc405c98..83bc33c421f666367a49da03481608b0638c255e 100644 (file)
@@ -226,13 +226,15 @@ core.compression::
        An integer -1..9, indicating a default compression level.
        -1 is the zlib default. 0 means no compression,
        and 1..9 are various speed/size tradeoffs, 9 being slowest.
+       If set, this provides a default to other compression variables,
+       such as 'core.loosecompression' and 'pack.compression'.
 
 core.loosecompression::
        An integer -1..9, indicating the compression level for objects that
        are not in a pack file. -1 is the zlib default. 0 means no
        compression, and 1..9 are various speed/size tradeoffs, 9 being
        slowest.  If not set,  defaults to core.compression.  If that is
-       not set,  defaults to 0 (best speed).
+       not set,  defaults to 1 (best speed).
 
 core.packedGitWindowSize::
        Number of bytes of a pack file to map into memory in a
@@ -622,7 +624,9 @@ pack.compression::
        in a pack file. -1 is the zlib default. 0 means no
        compression, and 1..9 are various speed/size tradeoffs, 9 being
        slowest.  If not set,  defaults to core.compression.  If that is
-       not set,  defaults to -1.
+       not set,  defaults to -1, the zlib default, which is "a default
+       compromise between speed and compression (currently equivalent
+       to level 6)."
 
 pack.deltaCacheSize::
        The maximum memory in bytes used for caching deltas in
index c126038c1f289c44e5e65bd03f797e11f3353333..c3f0be535d283266492eb21164dc2f243d97b631 100644 (file)
@@ -1082,11 +1082,6 @@ server like git Native transport does.  Any stock HTTP server
 that does not even support directory index would suffice.  But
 you must prepare your repository with `git-update-server-info`
 to help dumb transport downloaders.
-+
-There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload`
-programs, which are 'commit walkers'; they outlived their
-usefulness when git Native and SSH transports were introduced,
-and not used by `git pull` or `git push` scripts.
 
 Once you fetch from the remote repository, you `merge` that
 with your current branch.
index 9b5f86fc30aecc5e1183e514d5d0f81d14a751c3..60d1c52f449ec9e37c2f3d02bc79aa98af86a325 100644 (file)
@@ -3,7 +3,7 @@ git-get-tar-commit-id(1)
 
 NAME
 ----
-git-get-tar-commit-id - Extract commit ID from an archive created using git-tar-tree
+git-get-tar-commit-id - Extract commit ID from an archive created using git-archive
 
 
 SYNOPSIS
@@ -14,12 +14,12 @@ SYNOPSIS
 DESCRIPTION
 -----------
 Acts as a filter, extracting the commit ID stored in archives created by
-git-tar-tree.  It reads only the first 1024 bytes of input, thus its
+gitlink:git-archive[1].  It reads only the first 1024 bytes of input, thus its
 runtime is not influenced by the size of <tarfile> very much.
 
 If no commit ID is found, git-get-tar-commit-id quietly exists with a
 return code of 1.  This can happen if <tarfile> had not been created
-using git-tar-tree or if the first parameter of git-tar-tree had been
+using git-archive or if the first parameter of git-archive had been
 a tree ID instead of a commit ID or tag.
 
 
index 5c7316ceb82fbedc1413dfd8a4b1d8095b4d7a06..25003c38667940528422aab735ec0a4e9a4d5b97 100644 (file)
@@ -19,7 +19,7 @@ depending on the subcommand:
 git reflog expire [--dry-run] [--stale-fix] [--verbose]
        [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...
 
-git reflog [show] [log-options]
+git reflog [show] [log-options] [<ref>]
 
 Reflog is a mechanism to record when the tip of branches are
 updated.  This command is to manage the information recorded in it.
@@ -32,9 +32,16 @@ directly by the end users -- instead, see gitlink:git-gc[1].
 
 The subcommand "show" (which is also the default, in the absence of any
 subcommands) will take all the normal log options, and show the log of
-`HEAD`, which will cover all recent actions, including branch switches.
-It is basically an alias for 'git log -g --abbrev-commit
---pretty=oneline', see gitlink:git-log[1].
+the reference provided in the command-line (or `HEAD`, by default).
+The reflog will cover all recent actions (HEAD reflog records branch switching
+as well).  It is an alias for 'git log -g --abbrev-commit --pretty=oneline';
+see gitlink:git-log[1].
+
+The reflog is useful in various git commands, to specify the old value
+of a reference. For example, `HEAD@\{2\}` means "where HEAD used to be
+two moves ago", `master@\{one.week.ago\}` means "where master used to
+point to one week ago", and so on. See gitlink:git-rev-parse[1] for
+more details.
 
 
 OPTIONS
index c386dd0168d893363cd00c65d90c78254d5a421f..886bc03c4af0c1a9ab8232fc305c68a6a5e10d2a 100644 (file)
@@ -91,7 +91,7 @@ $ git remote
 origin
 $ git branch -r
 origin/master
-$ git remote add linux-nfs git://linux-nfs.org/pub/nfs-2.6.git
+$ git remote add linux-nfs git://linux-nfs.org/pub/linux/nfs-2.6.git
 $ git remote
 linux-nfs
 origin
index c7fdf25e27c94e9b152592a28bf7acc64dfa0e07..c0273533370ac0e5365146ce82b27bc7dfa9862d 100644 (file)
@@ -658,16 +658,23 @@ gitlink:git-diff[1]:
 $ git diff master..test
 -------------------------------------------------
 
-Sometimes what you want instead is a set of patches:
+That will produce the diff between the tips of the two branches.  If
+you'd prefer to find the diff from their common ancestor to test, you
+can use three dots instead of two:
+
+-------------------------------------------------
+$ git diff master...test
+-------------------------------------------------
+
+Sometimes what you want instead is a set of patches; for this you can
+use gitlink:git-format-patch[1]:
 
 -------------------------------------------------
 $ git format-patch master..test
 -------------------------------------------------
 
 will generate a file with a patch for each commit reachable from test
-but not from master.  Note that if master also has commits which are
-not reachable from test, then the combined result of these patches
-will not be the same as the diff produced by the git-diff example.
+but not from master.
 
 [[viewing-old-file-versions]]
 Viewing old file versions
@@ -2554,6 +2561,72 @@ branches into their own work.
 For true distributed development that supports proper merging,
 published branches should never be rewritten.
 
+[[bisect-merges]]
+Why bisecting merge commits can be harder than bisecting linear history
+-----------------------------------------------------------------------
+
+The gitlink:git-bisect[1] command correctly handles history that
+includes merge commits.  However, when the commit that it finds is a
+merge commit, the user may need to work harder than usual to figure out
+why that commit introduced a problem.
+
+Imagine this history:
+
+................................................
+      ---Z---o---X---...---o---A---C---D
+          \                       /
+           o---o---Y---...---o---B
+................................................
+
+Suppose that on the upper line of development, the meaning of one
+of the functions that exists at Z is changed at commit X.  The
+commits from Z leading to A change both the function's
+implementation and all calling sites that exist at Z, as well
+as new calling sites they add, to be consistent.  There is no
+bug at A.
+
+Suppose that in the meantime on the lower line of development somebody
+adds a new calling site for that function at commit Y.  The
+commits from Z leading to B all assume the old semantics of that
+function and the callers and the callee are consistent with each
+other.  There is no bug at B, either.
+
+Suppose further that the two development lines merge cleanly at C,
+so no conflict resolution is required.
+
+Nevertheless, the code at C is broken, because the callers added
+on the lower line of development have not been converted to the new
+semantics introduced on the upper line of development.  So if all
+you know is that D is bad, that Z is good, and that
+gitlink:git-bisect[1] identifies C as the culprit, how will you
+figure out that the problem is due to this change in semantics?
+
+When the result of a git-bisect is a non-merge commit, you should
+normally be able to discover the problem by examining just that commit.
+Developers can make this easy by breaking their changes into small
+self-contained commits.  That won't help in the case above, however,
+because the problem isn't obvious from examination of any single
+commit; instead, a global view of the development is required.  To
+make matters worse, the change in semantics in the problematic
+function may be just one small part of the changes in the upper
+line of development.
+
+On the other hand, if instead of merging at C you had rebased the
+history between Z to B on top of A, you would have gotten this
+linear history:
+
+................................................................
+    ---Z---o---X--...---o---A---o---o---Y*--...---o---B*--D*
+................................................................
+
+Bisecting between Z and D* would hit a single culprit commit Y*,
+and understanding why Y* was broken would probably be easier.
+
+Partly for this reason, many experienced git users, even when
+working on an otherwise merge-heavy project, keep the history
+linear by rebasing against the latest upstream version before
+publishing.
+
 [[advanced-branch-management]]
 Advanced branch management
 ==========================
index 88a4acad151de6705bb54b173c1a0b4983438bcb..fa38f373ac6875d56b40f0ec3efda71627e96075 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.5.3.5.GIT
+DEF_VER=v1.5.3.6.GIT
 
 LF='
 '
index 850e1c23e545e8f84e5a72ea7a7bdd1a99746938..4fc9d6f7ccdd7b989d75ae6e24df997c4deb3505 100644 (file)
@@ -117,7 +117,7 @@ static void update(int verbose, const char *prefix, const char **files)
        rev.diffopt.format_callback_data = &verbose;
        if (read_cache() < 0)
                die("index file corrupt");
-       run_diff_files(&rev, 0);
+       run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
 }
 
 static void refresh(int verbose, const char **pathspec)
index 5cc90e68f880180b072db946080c4168b98603cf..0fff02e0d826115d4b05d8ba6415a0107d3cf22f 100644 (file)
@@ -2099,7 +2099,7 @@ static int verify_index_match(struct cache_entry *ce, struct stat *st)
                        return -1;
                return 0;
        }
-       return ce_match_stat(ce, st, 1);
+       return ce_match_stat(ce, st, CE_MATCH_IGNORE_VALID);
 }
 
 static int check_patch(struct patch *patch, struct patch *prev_patch)
index 5f5c1823cb27cf1173c87f43bd0d2de95a06bf46..c1e9a61ea5642786b9e71fe437853a8ccc532b09 100644 (file)
@@ -276,7 +276,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
                if (commit && !parse_commit(commit)) {
                        pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
                                            &subject, &subject_len, 0,
-                                           NULL, NULL, 0);
+                                           NULL, NULL, 0, 0);
                        sub = subject;
                }
                printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color),
index 1b650069c929744c43f95e62ca49f8a542a70111..d1840555d6ffe589d60add61b172dd329545f376 100644 (file)
@@ -6,6 +6,7 @@
 #include "revision.h"
 #include "list-objects.h"
 #include "run-command.h"
+#include "refs.h"
 
 /*
  * Basic handler for bundle files to connect repositories via sneakernet.
@@ -253,11 +254,17 @@ static int create_bundle(struct bundle_header *header, const char *path,
                struct object_array_entry *e = revs.pending.objects + i;
                unsigned char sha1[20];
                char *ref;
+               const char *display_ref;
+               int flag;
 
                if (e->item->flags & UNINTERESTING)
                        continue;
                if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
                        continue;
+               if (!resolve_ref(e->name, sha1, 1, &flag))
+                       flag = 0;
+               display_ref = (flag & REF_ISSYMREF) ? e->name : ref;
+
                /*
                 * Make sure the refs we wrote out is correct; --max-count and
                 * other limiting options could have prevented all the tips
@@ -308,7 +315,7 @@ static int create_bundle(struct bundle_header *header, const char *path,
                ref_count++;
                write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
                write_or_die(bundle_fd, " ", 1);
-               write_or_die(bundle_fd, ref, strlen(ref));
+               write_or_die(bundle_fd, display_ref, strlen(display_ref));
                write_or_die(bundle_fd, "\n", 1);
                free(ref);
        }
index 185876b0a6dc191bb5adc22cd5c2f012cd70e479..bbf747fc7b66f6b4f19d9dc62a9ba10965199917 100644 (file)
@@ -294,7 +294,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
                        if (opt->pre_context) {
                                push_arg("-B");
                                len += snprintf(argptr, sizeof(randarg)-len,
-                                               "%u", opt->pre_context);
+                                               "%u", opt->pre_context) + 1;
                                if (sizeof(randarg) <= len)
                                        die("maximum length of args exceeded");
                                push_arg(argptr);
@@ -303,7 +303,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
                        if (opt->post_context) {
                                push_arg("-A");
                                len += snprintf(argptr, sizeof(randarg)-len,
-                                               "%u", opt->post_context);
+                                               "%u", opt->post_context) + 1;
                                if (sizeof(randarg) <= len)
                                        die("maximum length of args exceeded");
                                push_arg(argptr);
@@ -313,7 +313,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
                else {
                        push_arg("-C");
                        len += snprintf(argptr, sizeof(randarg)-len,
-                                       "%u", opt->post_context);
+                                       "%u", opt->post_context) + 1;
                        if (sizeof(randarg) <= len)
                                die("maximum length of args exceeded");
                        push_arg(argptr);
index c6cc3aef5270fe64821146376354239d54de5a26..070886ae578257c65d5716d608b61eacd5a535f2 100644 (file)
@@ -795,7 +795,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
                        char *buf = NULL;
                        unsigned long buflen = 0;
                        pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
-                                           &buf, &buflen, 0, NULL, NULL, 0);
+                                           &buf, &buflen, 0, NULL, NULL, 0, 0);
                        printf("%c %s %s\n", sign,
                               sha1_to_hex(commit->object.sha1), buf);
                        free(buf);
index ac551d59f3f6cb209a645ad708c46e4e88791295..9dbfae416c2ed563960e69cc6286891d37d576e0 100644 (file)
@@ -84,7 +84,7 @@ static void show_commit(struct commit *commit)
                unsigned long buflen = 0;
                pretty_print_commit(revs.commit_format, commit, ~0,
                                    &buf, &buflen,
-                                   revs.abbrev, NULL, NULL, revs.date_mode);
+                                   revs.abbrev, NULL, NULL, revs.date_mode, 0);
                printf("%s%c", buf, hdr_termination);
                free(buf);
        }
index 4fa87f6081f74fa667a415038ca64c5f4a7cf775..b9cf1b379f60d42408eb75009e57030173448d8c 100644 (file)
@@ -267,7 +267,7 @@ static void show_one_commit(struct commit *commit, int no_name)
        if (commit->object.parsed) {
                pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
                                    &pretty, &pretty_len,
-                                   0, NULL, NULL, 0);
+                                   0, NULL, NULL, 0, 0);
                pretty_str = pretty;
        }
        if (!prefixcmp(pretty_str, "[PATCH] "))
diff --git a/cache.h b/cache.h
index 60af6d35794beb67dd7165668677cfbca9334f30..c9954d78084588a1541cb45861eb9dbce9a6b7a6 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -174,8 +174,8 @@ extern struct index_state the_index;
 #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))
 #define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose))
 #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)
-#define ce_match_stat(ce, st, really) ie_match_stat(&the_index, (ce), (st), (really))
-#define ce_modified(ce, st, really) ie_modified(&the_index, (ce), (st), (really))
+#define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
+#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
 #endif
 
 enum object_type {
@@ -266,8 +266,14 @@ extern int remove_file_from_index(struct index_state *, const char *path);
 extern int add_file_to_index(struct index_state *, const char *path, int verbose);
 extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
 extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
-extern int ie_match_stat(struct index_state *, struct cache_entry *, struct stat *, int);
-extern int ie_modified(struct index_state *, struct cache_entry *, struct stat *, int);
+
+/* do stat comparison even if CE_VALID is true */
+#define CE_MATCH_IGNORE_VALID          01
+/* do not check the contents but report dirty on racily-clean entries */
+#define CE_MATCH_RACY_IS_DIRTY 02
+extern int ie_match_stat(struct index_state *, struct cache_entry *, struct stat *, unsigned int);
+extern int ie_modified(struct index_state *, struct cache_entry *, struct stat *, unsigned int);
+
 extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
 extern int read_fd(int fd, char **return_buf, unsigned long *return_size);
index d6a08b4a55273af1a5f2933f3b5c6cb818ba74c6..00d92a16631a80ff8ec4e995dafcd3e55434fad5 100644 (file)
@@ -18,7 +18,7 @@ int main(int ac, char **av)
 
                if (ce_match_stat(ce, &st, 0))
                        dirty++;
-               else if (ce_match_stat(ce, &st, 2))
+               else if (ce_match_stat(ce, &st, CE_MATCH_RACY_IS_DIRTY))
                        racy++;
                else
                        clean++;
index 1fbdd2d51b8e798ac73c4b020f8fa47b1d6fb168..10f7b14e763feab4b86d3a8fb1f011cb918312c8 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -479,7 +479,7 @@ static int get_one_line(const char *msg, unsigned long len)
 }
 
 /* High bit set, or ISO-2022-INT */
-static int non_ascii(int ch)
+int non_ascii(int ch)
 {
        ch = (ch & 0xff);
        return ((ch & 0x80) || (ch == 0x1b));
@@ -1158,13 +1158,13 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
                                  char **buf_p, unsigned long *space_p,
                                  int abbrev, const char *subject,
                                  const char *after_subject,
-                                 enum date_mode dmode)
+                                 enum date_mode dmode,
+                                 int plain_non_ascii)
 {
        unsigned long offset = 0;
        unsigned long beginning_of_body;
        int indent = 4;
        const char *msg = commit->buffer;
-       int plain_non_ascii = 0;
        char *reencoded;
        const char *encoding;
        char *buf;
index 467872eecabf05ccedbb9bf8247b6de244416b8f..b897b5730d9b9c220362b0b6a9df7be5d6803df3 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -60,8 +60,9 @@ enum cmit_fmt {
        CMIT_FMT_UNSPECIFIED,
 };
 
+extern int non_ascii(int);
 extern enum cmit_fmt get_commit_format(const char *arg);
-extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode);
+extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode, int non_ascii_present);
 
 /** Removes the first commit from a list sorted by date, and adds all
  * of its parents.
index da5571302df6ed418874fd4d7423853a7de5b52c..ec1b5e3d446c4e5a56fb5f3e4420499c4e8918eb 100644 (file)
@@ -173,9 +173,10 @@ static int is_in_index(const char *path)
 }
 
 static int handle_diff_files_args(struct rev_info *revs,
-               int argc, const char **argv, int *silent)
+                                 int argc, const char **argv,
+                                 unsigned int *options)
 {
-       *silent = 0;
+       *options = 0;
 
        /* revs->max_count == -2 means --no-index */
        while (1 < argc && argv[1][0] == '-') {
@@ -192,7 +193,7 @@ static int handle_diff_files_args(struct rev_info *revs,
                        revs->diffopt.no_index = 1;
                }
                else if (!strcmp(argv[1], "-q"))
-                       *silent = 1;
+                       *options |= DIFF_SILENT_ON_REMOVED;
                else
                        return error("invalid option: %s", argv[1]);
                argv++; argc--;
@@ -305,9 +306,9 @@ int setup_diff_no_index(struct rev_info *revs,
 
 int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
 {
-       int silent_on_removed;
+       unsigned int options;
 
-       if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
+       if (handle_diff_files_args(revs, argc, argv, &options))
                return -1;
 
        if (revs->diffopt.no_index) {
@@ -329,13 +330,16 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
                perror("read_cache");
                return -1;
        }
-       return run_diff_files(revs, silent_on_removed);
+       return run_diff_files(revs, options);
 }
 
-int run_diff_files(struct rev_info *revs, int silent_on_removed)
+int run_diff_files(struct rev_info *revs, unsigned int option)
 {
        int entries, i;
        int diff_unmerged_stage = revs->max_count;
+       int silent_on_removed = option & DIFF_SILENT_ON_REMOVED;
+       unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED)
+                             ? CE_MATCH_RACY_IS_DIRTY : 0);
 
        if (diff_unmerged_stage < 0)
                diff_unmerged_stage = 2;
@@ -441,7 +445,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
                                       ce->sha1, ce->name, NULL);
                        continue;
                }
-               changed = ce_match_stat(ce, &st, 0);
+               changed = ce_match_stat(ce, &st, ce_option);
                if (!changed && !revs->diffopt.find_copies_harder)
                        continue;
                oldmode = ntohl(ce->ce_mode);
diff --git a/diff.h b/diff.h
index 4546aad219742e4ad878937dbd05436c93d298b9..efaa8f711a35c1339aba2bcaffeab6bf95343983 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -224,7 +224,11 @@ extern void diff_flush(struct diff_options*);
 
 extern const char *diff_unique_abbrev(const unsigned char *, int);
 
-extern int run_diff_files(struct rev_info *revs, int silent_on_removed);
+/* do not report anything on removed paths */
+#define DIFF_SILENT_ON_REMOVED 01
+/* report racily-clean paths as modified */
+#define DIFF_RACY_IS_MODIFIED 02
+extern int run_diff_files(struct rev_info *revs, unsigned int option);
 extern int setup_diff_no_index(struct rev_info *revs,
                int argc, const char ** argv, int nongit, const char *prefix);
 extern int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv);
diff --git a/entry.c b/entry.c
index fc3a506ecef4ed654f26c11996df109dd135a4ed..ef88f62ce82e7188a8d1863227a87033543958fb 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -200,7 +200,7 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t
        strcpy(path + len, ce->name);
 
        if (!lstat(path, &st)) {
-               unsigned changed = ce_match_stat(ce, &st, 1);
+               unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID);
                if (!changed)
                        return 0;
                if (!state->force) {
index ab43217be4b49ce71ffee461569e0e4b395dfb5d..5e3908f2cbf5cf96b4f5c3b07d5178b3e2321b58 100755 (executable)
@@ -322,9 +322,9 @@ unset only
 case "$all,$interactive,$also,$#" in
 *t,*t,*)
        die "Cannot use -a, --interactive or -i at the same time." ;;
-t,,[1-9]*)
+t,,,[1-9]*)
        die "Paths with -a does not make sense." ;;
-,t,[1-9]*)
+,t,,[1-9]*)
        die "Paths with --interactive does not make sense." ;;
 ,,t,0)
        die "No paths with -i does not make sense." ;;
index 2b1f1b598c62ddaed693635adef12e490f49838f..b03297c9d7ed40f39b9f805c08bf9c2f17bb7379 100755 (executable)
@@ -711,7 +711,8 @@ sub send_message
                        else {
                                push @xh,
                                  'MIME-Version: 1.0',
-                                 "Content-Type: text/plain; charset=$author_encoding";
+                                 "Content-Type: text/plain; charset=$author_encoding",
+                                 'Content-Transfer-Encoding: 8bit';
                        }
                }
        }
index b509c0c7ec239d4f426807406d94c34feeecf009..9ebc24b68754a422a53270028b032395ad7c754a 100644 (file)
@@ -140,6 +140,18 @@ static unsigned int digits_in_number(unsigned int number)
        return result;
 }
 
+static int has_non_ascii(const char *s)
+{
+       int ch;
+       if (!s)
+               return 0;
+       while ((ch = *s++) != '\0') {
+               if (non_ascii(ch))
+                       return 1;
+       }
+       return 0;
+}
+
 void show_log(struct rev_info *opt, const char *sep)
 {
        char *msgbuf = NULL;
@@ -290,7 +302,8 @@ void show_log(struct rev_info *opt, const char *sep)
         */
        len = pretty_print_commit(opt->commit_format, commit, ~0u,
                                  &msgbuf, &msgbuf_len, abbrev, subject,
-                                 extra_headers, opt->date_mode);
+                                 extra_headers, opt->date_mode,
+                                 has_non_ascii(opt->add_signoff));
 
        if (opt->add_signoff)
                len = append_signoff(&msgbuf, &msgbuf_len, len,
index 928e8fa1aee22a0a79c57ca675576d4998503ea9..c3dbf894261ddae12a48542ba8869cbd8f2ebd50 100644 (file)
@@ -194,11 +194,12 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
 }
 
 int ie_match_stat(struct index_state *istate,
-                 struct cache_entry *ce, struct stat *st, int options)
+                 struct cache_entry *ce, struct stat *st,
+                 unsigned int options)
 {
        unsigned int changed;
-       int ignore_valid = options & 01;
-       int assume_racy_is_modified = options & 02;
+       int ignore_valid = options & CE_MATCH_IGNORE_VALID;
+       int assume_racy_is_modified = options & CE_MATCH_RACY_IS_DIRTY;
 
        /*
         * If it's marked as always valid in the index, it's
@@ -238,10 +239,11 @@ int ie_match_stat(struct index_state *istate,
 }
 
 int ie_modified(struct index_state *istate,
-               struct cache_entry *ce, struct stat *st, int really)
+               struct cache_entry *ce, struct stat *st, unsigned int options)
 {
        int changed, changed_fs;
-       changed = ie_match_stat(istate, ce, st, really);
+
+       changed = ie_match_stat(istate, ce, st, options);
        if (!changed)
                return 0;
        /*
@@ -386,6 +388,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)
        int size, namelen, pos;
        struct stat st;
        struct cache_entry *ce;
+       unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;
 
        if (lstat(path, &st))
                die("%s: unable to stat (%s)", path, strerror(errno));
@@ -420,7 +423,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)
        pos = index_name_pos(istate, ce->name, namelen);
        if (0 <= pos &&
            !ce_stage(istate->cache[pos]) &&
-           !ie_modified(istate, istate->cache[pos], &st, 1)) {
+           !ie_match_stat(istate, istate->cache[pos], &st, ce_option)) {
                /* Nothing changed, really */
                free(ce);
                return 0;
@@ -782,11 +785,13 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti
  * to link up the stat cache details with the proper files.
  */
 static struct cache_entry *refresh_cache_ent(struct index_state *istate,
-                                            struct cache_entry *ce, int really, int *err)
+                                            struct cache_entry *ce,
+                                            unsigned int options, int *err)
 {
        struct stat st;
        struct cache_entry *updated;
        int changed, size;
+       int ignore_valid = options & CE_MATCH_IGNORE_VALID;
 
        if (lstat(ce->name, &st) < 0) {
                if (err)
@@ -794,16 +799,23 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
                return NULL;
        }
 
-       changed = ie_match_stat(istate, ce, &st, really);
+       changed = ie_match_stat(istate, ce, &st, options);
        if (!changed) {
-               if (really && assume_unchanged &&
+               /*
+                * The path is unchanged.  If we were told to ignore
+                * valid bit, then we did the actual stat check and
+                * found that the entry is unmodified.  If the entry
+                * is not marked VALID, this is the place to mark it
+                * valid again, under "assume unchanged" mode.
+                */
+               if (ignore_valid && assume_unchanged &&
                    !(ce->ce_flags & htons(CE_VALID)))
                        ; /* mark this one VALID again */
                else
                        return ce;
        }
 
-       if (ie_modified(istate, ce, &st, really)) {
+       if (ie_modified(istate, ce, &st, options)) {
                if (err)
                        *err = EINVAL;
                return NULL;
@@ -814,13 +826,14 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
        memcpy(updated, ce, size);
        fill_stat_cache_info(updated, &st);
 
-       /* In this case, if really is not set, we should leave
-        * CE_VALID bit alone.  Otherwise, paths marked with
-        * --no-assume-unchanged (i.e. things to be edited) will
-        * reacquire CE_VALID bit automatically, which is not
-        * really what we want.
+       /*
+        * If ignore_valid is not set, we should leave CE_VALID bit
+        * alone.  Otherwise, paths marked with --no-assume-unchanged
+        * (i.e. things to be edited) will reacquire CE_VALID bit
+        * automatically, which is not really what we want.
         */
-       if (!really && assume_unchanged && !(ce->ce_flags & htons(CE_VALID)))
+       if (!ignore_valid && assume_unchanged &&
+           !(ce->ce_flags & htons(CE_VALID)))
                updated->ce_flags &= ~htons(CE_VALID);
 
        return updated;
@@ -834,6 +847,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p
        int allow_unmerged = (flags & REFRESH_UNMERGED) != 0;
        int quiet = (flags & REFRESH_QUIET) != 0;
        int not_new = (flags & REFRESH_IGNORE_MISSING) != 0;
+       unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0;
 
        for (i = 0; i < istate->cache_nr; i++) {
                struct cache_entry *ce, *new;
@@ -855,7 +869,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p
                if (pathspec && !match_pathspec(pathspec, ce->name, strlen(ce->name), 0, seen))
                        continue;
 
-               new = refresh_cache_ent(istate, ce, really, &cache_errno);
+               new = refresh_cache_ent(istate, ce, options, &cache_errno);
                if (new == ce)
                        continue;
                if (!new) {
index eb1ced3c371ecaeab9d0dc14be888bf7df110483..24f892f79386478fd5f1162654cb9b72d940bbe4 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description='git add -u with path limiting
+test_description='git add -u
 
 This test creates a working tree state with three files:
 
@@ -9,7 +9,10 @@ This test creates a working tree state with three files:
   dir/other (untracked)
 
 and issues a git add -u with path limiting on "dir" to add
-only the updates to dir/sub.'
+only the updates to dir/sub.
+
+Also tested are "git add -u" without limiting, and "git add -u"
+without contents changes.'
 
 . ./test-lib.sh
 
@@ -85,4 +88,27 @@ test_expect_success 'replace a file with a symlink' '
 
 '
 
+test_expect_success 'add everything changed' '
+
+       git add -u &&
+       test -z "$(git diff-files)"
+
+'
+
+test_expect_success 'touch and then add -u' '
+
+       touch check &&
+       git add -u &&
+       test -z "$(git diff-files)"
+
+'
+
+test_expect_success 'touch and then add explicitly' '
+
+       touch check &&
+       git add check &&
+       test -z "$(git diff-files)"
+
+'
+
 test_done
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/t/t4021-format-patch-signer-mime.sh b/t/t4021-format-patch-signer-mime.sh
new file mode 100755 (executable)
index 0000000..67a70fa
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+test_description='format-patch -s should force MIME encoding as needed'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+       >F &&
+       git add F &&
+       git commit -m initial &&
+       echo new line >F &&
+
+       test_tick &&
+       git commit -m "This adds some lines to F" F
+
+'
+
+test_expect_success 'format normally' '
+
+       git format-patch --stdout -1 >output &&
+       ! grep Content-Type output
+
+'
+
+test_expect_success 'format with signoff without funny signer name' '
+
+       git format-patch -s --stdout -1 >output &&
+       ! grep Content-Type output
+
+'
+
+test_expect_success 'format with non ASCII signer name' '
+
+       GIT_COMMITTER_NAME="\e$B$O$^$N\e(B \e$B$U$K$*$&\e(B" \
+       git format-patch -s --stdout -1 >output &&
+       grep Content-Type output
+
+'
+
+test_done
+
index 439430f569ca70b5e3b08ef07996949d7259c9b7..7406de35ae35bbb0d3a97016046c047e25822671 100755 (executable)
@@ -153,4 +153,17 @@ test_expect_success 'bundle should be able to create a full history' '
 
 '
 
+test_expect_success 'bundle should record HEAD correctly' '
+
+       cd "$D" &&
+       git bundle create bundle5 HEAD master &&
+       git bundle list-heads bundle5 >actual &&
+       for h in HEAD refs/heads/master
+       do
+               echo "$(git rev-parse --verify $h) $h"
+       done >expect &&
+       diff -u expect actual
+
+'
+
 test_done
index 28643b0da41cab7af9464adbaae59a88820b1ebe..ed416e14e07950d9c7a0d0b85cd9e0307dd55a65 100755 (executable)
@@ -13,7 +13,6 @@ do
 done
 unset vi
 mv e-vi.sh vi
-PATH=".:$PATH"
 unset EDITOR VISUAL GIT_EDITOR
 
 test_expect_success setup '
@@ -59,7 +58,7 @@ do
                ;;
        esac
        test_expect_success "Using $i" '
-               git commit --amend &&
+               git --exec-path=. commit --amend &&
                git show -s --pretty=oneline |
                sed -e "s/^[0-9a-f]* //" >actual &&
                diff actual expect
@@ -81,7 +80,7 @@ do
                ;;
        esac
        test_expect_success "Using $i (override)" '
-               git commit --amend &&
+               git --exec-path=. commit --amend &&
                git show -s --pretty=oneline |
                sed -e "s/^[0-9a-f]* //" >actual &&
                diff actual expect
old mode 100644 (file)
new mode 100755 (executable)
index b151b51..7f25689
@@ -33,6 +33,16 @@ test_expect_failure \
        "invalid options 2" \
        "git-commit -C HEAD -m illegal"
 
+test_expect_failure \
+       "using paths with -a" \
+       "echo King of the bongo >file &&
+       git-commit -m foo -a file"
+
+test_expect_failure \
+       "using paths with --interactive" \
+       "echo bong-o-bong >file &&
+       echo 7 | git-commit -m foo --interactive file"
+
 test_expect_failure \
        "using invalid commit with -C" \
        "git-commit -C bogus"
index 18b87309f65be23794b87260e08c547f5deeefce..8b057be30411e3f0074599778666c1254d82329e 100644 (file)
@@ -13,7 +13,7 @@
 
 if git-rev-parse --verify HEAD 2>/dev/null
 then
-       git-diff-index -p -M --cached HEAD
+       git-diff-index -p -M --cached HEAD --
 else
        # NEEDSWORK: we should produce a diff with an empty tree here
        # if we want to do the same verification for the initial import.
index ccfeb6e245f32d88170ae51f0367ee15aa950a37..9411c67a067e109621d310edfa4a66df99b7eb89 100644 (file)
@@ -406,7 +406,7 @@ static void verify_uptodate(struct cache_entry *ce,
                return;
 
        if (!lstat(ce->name, &st)) {
-               unsigned changed = ce_match_stat(ce, &st, 1);
+               unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID);
                if (!changed)
                        return;
                /*
@@ -927,7 +927,7 @@ int oneway_merge(struct cache_entry **src,
                if (o->reset) {
                        struct stat st;
                        if (lstat(old->name, &st) ||
-                           ce_match_stat(old, &st, 1))
+                           ce_match_stat(old, &st, CE_MATCH_IGNORE_VALID))
                                old->ce_flags |= htons(CE_UPDATE);
                }
                return keep_entry(old, o);