Merge branch 'jc/maint-split-diff-metainfo' into maint
authorJunio C Hamano <gitster@pobox.com>
Fri, 6 Feb 2009 01:54:17 +0000 (17:54 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 6 Feb 2009 01:54:17 +0000 (17:54 -0800)
* jc/maint-split-diff-metainfo:
diff.c: output correct index lines for a split diff

38 files changed:
Documentation/RelNotes-1.6.1.2.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-ls-tree.txt
Documentation/technical/api-strbuf.txt
Documentation/urls.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
RelNotes
builtin-apply.c
builtin-commit.c
builtin-gc.c
builtin-grep.c
builtin-log.c
builtin-ls-tree.c
builtin-mv.c
builtin-send-pack.c
bundle.c
diffcore-rename.c
dump-cache-tree.c [deleted file]
git-sh-setup.sh
object.c
object.h
revision.c
sha1_file.c
sha1_name.c
t/t2300-cd-to-toplevel.sh
t/t4014-format-patch.sh
t/t4015-diff-whitespace.sh
t/t5519-push-alternates.sh [new file with mode: 0755]
t/t5701-clone-local.sh
t/t6014-rev-list-all.sh [new file with mode: 0755]
t/t7001-mv.sh
t/t7002-grep.sh
test-dump-cache-tree.c [new file with mode: 0644]
test-path-utils.c
unpack-trees.c
xdiff/xutils.c
diff --git a/Documentation/RelNotes-1.6.1.2.txt b/Documentation/RelNotes-1.6.1.2.txt
new file mode 100644 (file)
index 0000000..230aa3d
--- /dev/null
@@ -0,0 +1,39 @@
+GIT v1.6.1.2 Release Notes
+==========================
+
+Fixes since v1.6.1.1
+--------------------
+
+* The logic for rename detectin in internal diff used by commands like
+  "git diff" and "git blame" have been optimized to avoid loading the same
+  blob repeatedly.
+
+* We did not allow writing out a blob that is larger than 2GB for no good
+  reason.
+
+* "git format-patch -o $dir", when $dir is a relative directory, used it
+  as relative to the root of the work tree, not relative to the current
+  directory.
+
+* v1.6.1 introduced an optimization for "git push" into a repository (A)
+  that borrows its objects from another repository (B) to avoid sending
+  objects that are available in repository B, when they are not yet used
+  by repository A.  However the code on the "git push" sender side was
+  buggy and did not work when repository B had new objects that are not
+  known by the sender.  This caused pushing into a "forked" repository
+  served by v1.6.1 software using "git push" from v1.6.1 sometimes did not
+  work.  The bug was purely on the "git push" sender side, and has been
+  corrected.
+
+* "git status -v" did not paint its diff output in colour even when
+  color.ui configuration was set.
+
+* "git ls-tree" learned --full-tree option to help Porcelain scripts that
+  want to always see the full path regardless of the current working
+  directory.
+
+* "git grep" incorrectly searched in work tree paths even when they are
+  marked as assume-unchanged.  It now searches in the index entries.
+
+* "git gc" with no grace period needlessly ejected packed but unreachable
+  objects in their loose form, only to delete them right away.
index 26551ea6e1bba817bc272243368e082fecaca2f1..2ed868c81a09af9176bd805f819c0b312556891a 100644 (file)
@@ -702,7 +702,9 @@ gc.packrefs::
 
 gc.pruneexpire::
        When 'git-gc' is run, it will call 'prune --expire 2.weeks.ago'.
-       Override the grace period with this config variable.
+       Override the grace period with this config variable.  The value
+       "now" may be used to disable this  grace period and always prune
+       unreachable objects immediately.
 
 gc.reflogexpire::
        'git-reflog expire' removes reflog entries older than
index 4c7262f1cd82ca8d9ea6be638d23b18d9bba3738..db6ebccd6dc51d9f1463710f29a8f821f13fd412 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git ls-tree' [-d] [-r] [-t] [-l] [-z]
-           [--name-only] [--name-status] [--full-name] [--abbrev=[<n>]]
+           [--name-only] [--name-status] [--full-name] [--full-tree] [--abbrev=[<n>]]
            <tree-ish> [paths...]
 
 DESCRIPTION
@@ -30,6 +30,8 @@ in the current working directory.  Note that:
    'sub/dir' in 'HEAD').  You don't want to give a tree that is not at the
    root level (e.g. 'git ls-tree -r HEAD:sub dir') in this case, as that
    would result in asking for 'sub/sub/dir' in the 'HEAD' commit.
+   However, the current working directory can be ignored by passing
+   --full-tree option.
 
 OPTIONS
 -------
@@ -66,6 +68,10 @@ OPTIONS
        Instead of showing the path names relative to the current working
        directory, show the full path names.
 
+--full-tree::
+       Do not limit the listing to the current working directory.
+       Implies --full-name.
+
 paths::
        When paths are given, show them (note that this isn't really raw
        pathnames, but rather a list of patterns to match).  Otherwise
index a8ee2fe6a1504b943ff9c3c51807bf0f839182b1..985800e43a9b91256c35df60f67c36994142b94c 100644 (file)
@@ -21,7 +21,7 @@ allocated memory or not), use `strbuf_detach()` to unwrap a memory
 buffer from its strbuf shell in a safe way. That is the sole supported
 way. This will give you a malloced buffer that you can later `free()`.
 +
-However, it it totally safe to modify anything in the string pointed by
+However, it is totally safe to modify anything in the string pointed by
 the `buf` member, between the indices `0` and `len-1` (inclusive).
 
 . The `buf` member is a byte array that has at least `len + 1` bytes
index fa34c6747194aaecf9e8124462129b8bbc9ae7d4..5355ebc0f39114823f830e0651078a99f0ac2e70 100644 (file)
@@ -6,10 +6,10 @@ to name the remote repository:
 
 ===============================================================
 - rsync://host.xz/path/to/repo.git/
-- http://host.xz/path/to/repo.git/
-- https://host.xz/path/to/repo.git/
-- git://host.xz/path/to/repo.git/
-- git://host.xz/~user/path/to/repo.git/
+- http://host.xz{startsb}:port{endsb}/path/to/repo.git/
+- https://host.xz{startsb}:port{endsb}/path/to/repo.git/
+- git://host.xz{startsb}:port{endsb}/path/to/repo.git/
+- git://host.xz{startsb}:port{endsb}/~user/path/to/repo.git/
 - ssh://{startsb}user@{endsb}host.xz{startsb}:port{endsb}/path/to/repo.git/
 - ssh://{startsb}user@{endsb}host.xz/path/to/repo.git/
 - ssh://{startsb}user@{endsb}host.xz/~user/path/to/repo.git/
index 19f571ae3bcab2fd96288dfa156062a7fbf89b5e..96af8977f6cae5382728f13116ea24ba2d130bef 100644 (file)
@@ -1507,7 +1507,7 @@ so on a different branch and then coming back), unstash the
 work-in-progress changes.
 
 ------------------------------------------------
-$ git stash "work in progress for foo feature"
+$ git stash save "work in progress for foo feature"
 ------------------------------------------------
 
 This command will save your changes away to the `stash`, and
index fe496e5fca57cba6d00b3d29589dd9c600276bfd..3697edc72e2b47c1262835be205f12f3a6ad687e 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.6.1.1.GIT
+DEF_VER=v1.6.1.2.GIT
 
 LF='
 '
index aabf0130b99bee5204c8e668ba8f40caea77dae2..01242889eb888d35e28249a78d54584ebca4bb24 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1353,7 +1353,7 @@ endif
 
 ### Testing rules
 
-TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
+TEST_PROGRAMS = test-chmtime$X test-dump-cache-tree$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
 
 all:: $(TEST_PROGRAMS)
 
index 2ebf251ddf3c4091ad6b55aef86bfccbd1c612f2..da6e81321a332fc7c7229c04e438f4161f27755d 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.1.1.txt
\ No newline at end of file
+Documentation/RelNotes-1.6.1.2.txt
\ No newline at end of file
index a8f75ed3ed411d8cf7a3ec9dfefef7407c50f447..3b6cd6dfaea0c8c427ab1a80ed11cabe60a5b32d 100644 (file)
@@ -2435,7 +2435,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
                return error("%s: %s", old_name, strerror(errno));
        }
 
-       if (!cached)
+       if (!cached && !tpatch)
                st_mode = ce_mode_from_stat(*ce, st->st_mode);
 
        if (patch->is_new < 0)
index 977ea09c51269e897ea09ceb4060661a0278e515..2f0b00a174ff970939d2758334cb8d1dca41cb42 100644 (file)
@@ -865,6 +865,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        if (wt_status_use_color == -1)
                wt_status_use_color = git_use_color_default;
 
+       if (diff_use_color_default == -1)
+               diff_use_color_default = git_use_color_default;
+
        argc = parse_and_validate_options(argc, argv, builtin_status_usage, prefix);
 
        index_file = prepare_index(argc, argv, prefix);
@@ -944,6 +947,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 
        git_config(git_commit_config, NULL);
 
+       if (wt_status_use_color == -1)
+               wt_status_use_color = git_use_color_default;
+
        argc = parse_and_validate_options(argc, argv, builtin_commit_usage, prefix);
 
        index_file = prepare_index(argc, argv, prefix);
index 781df601c5f95e874297e0e8bec3fddeb929cc2d..f8eae4adb41d9c338c07aa161e7305bb16742a1e 100644 (file)
@@ -188,7 +188,9 @@ static int need_to_gc(void)
         * there is no need.
         */
        if (too_many_packs())
-               append_option(argv_repack, "-A", MAX_ADD);
+               append_option(argv_repack,
+                             !strcmp(prune_expire, "now") ? "-a" : "-A",
+                             MAX_ADD);
        else if (!too_many_loose_objects())
                return 0;
 
@@ -243,7 +245,9 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                        "run \"git gc\" manually. See "
                        "\"git help gc\" for more information.\n");
        } else
-               append_option(argv_repack, "-A", MAX_ADD);
+               append_option(argv_repack,
+                             !strcmp(prune_expire, "now") ? "-a" : "-A",
+                             MAX_ADD);
 
        if (pack_refs && run_command_v_opt(argv_pack_refs, RUN_GIT_CMD))
                return error(FAILED_RUN, argv_pack_refs[0]);
index 624f86e287cf6304d122850f8258444c5f916702..3f12ba382690699d96580c3ddb1a61c79520e694 100644 (file)
@@ -20,6 +20,8 @@
 #endif
 #endif
 
+static int builtin_grep;
+
 /*
  * git grep pathspecs are somewhat different from diff-tree pathspecs;
  * pathname wildcards are allowed.
@@ -289,6 +291,8 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
                push_arg("-E");
        if (opt->regflags & REG_ICASE)
                push_arg("-i");
+       if (opt->binary == GREP_BINARY_NOMATCH)
+               push_arg("-I");
        if (opt->word_regexp)
                push_arg("-w");
        if (opt->name_only)
@@ -389,7 +393,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
         * we grep through the checked-out files. It tends to
         * be a lot more optimized
         */
-       if (!cached) {
+       if (!cached && !builtin_grep) {
                hit = external_grep(opt, paths, cached);
                if (hit >= 0)
                        return hit;
@@ -402,7 +406,12 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
                        continue;
                if (!pathspec_matches(paths, ce->name))
                        continue;
-               if (cached) {
+               /*
+                * If CE_VALID is on, we assume worktree file and its cache entry
+                * are identical, even if worktree file has been modified, so use
+                * cache version instead
+                */
+               if (cached || (ce->ce_flags & CE_VALID)) {
                        if (ce_stage(ce))
                                continue;
                        hit |= grep_sha1(opt, ce->sha1, ce->name, 0);
@@ -545,6 +554,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                        cached = 1;
                        continue;
                }
+               if (!strcmp("--no-ext-grep", arg)) {
+                       builtin_grep = 1;
+                       continue;
+               }
                if (!strcmp("-a", arg) ||
                    !strcmp("--text", arg)) {
                        opt.binary = GREP_BINARY_TEXT;
index 4420b4fd4f871d1284b90e80fa58fbe529b61592..60f8dd86048fd3a4ec51d7296b85984a0cefd602 100644 (file)
@@ -553,6 +553,7 @@ static const char *get_oneline_for_filename(struct commit *commit,
 
 static FILE *realstdout = NULL;
 static const char *output_directory = NULL;
+static int outdir_offset;
 
 static int reopen_stdout(const char *oneline, int nr, int total)
 {
@@ -579,7 +580,7 @@ static int reopen_stdout(const char *oneline, int nr, int total)
                strcpy(filename + len, fmt_patch_suffix);
        }
 
-       fprintf(realstdout, "%s\n", filename);
+       fprintf(realstdout, "%s\n", filename + outdir_offset);
        if (freopen(filename, "w", stdout) == NULL)
                return error("Cannot open patch file %s",filename);
 
@@ -740,6 +741,27 @@ static const char *clean_message_id(const char *msg_id)
        return xmemdupz(a, z - a);
 }
 
+static const char *set_outdir(const char *prefix, const char *output_directory)
+{
+       if (output_directory && is_absolute_path(output_directory))
+               return output_directory;
+
+       if (!prefix || !*prefix) {
+               if (output_directory)
+                       return output_directory;
+               /* The user did not explicitly ask for "./" */
+               outdir_offset = 2;
+               return "./";
+       }
+
+       outdir_offset = strlen(prefix);
+       if (!output_directory)
+               return prefix;
+
+       return xstrdup(prefix_filename(prefix, outdir_offset,
+                                      output_directory));
+}
+
 int cmd_format_patch(int argc, const char **argv, const char *prefix)
 {
        struct commit *commit;
@@ -917,8 +939,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff)
                DIFF_OPT_SET(&rev.diffopt, BINARY);
 
-       if (!output_directory && !use_stdout)
-               output_directory = prefix;
+       if (!use_stdout)
+               output_directory = set_outdir(prefix, output_directory);
 
        if (output_directory) {
                if (use_stdout)
index cb61717685b09a2e409440206e27fce68831e04d..5b63e6eada5cd6de764acef694da624a70ce6dab 100644 (file)
@@ -23,7 +23,7 @@ static int chomp_prefix;
 static const char *ls_tree_prefix;
 
 static const char ls_tree_usage[] =
-       "git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
+       "git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--full-tree] [--abbrev[=<n>]] <tree-ish> [path...]";
 
 static int show_recursive(const char *base, int baselen, const char *pathname)
 {
@@ -156,6 +156,11 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
                                chomp_prefix = 0;
                                break;
                        }
+                       if (!strcmp(argv[1]+2, "full-tree")) {
+                               ls_tree_prefix = prefix = NULL;
+                               chomp_prefix = 0;
+                               break;
+                       }
                        if (!prefixcmp(argv[1]+2, "abbrev=")) {
                                abbrev = strtoul(argv[1]+9, NULL, 10);
                                if (abbrev && abbrev < MINIMUM_ABBREV)
index bce9959293e30925c4b16c40ac33a3f2e0474e30..01270fefdfb04ed27379b1ca761a811b929ce887 100644 (file)
@@ -162,7 +162,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                                }
                                argc += last - first;
                        }
-               } else if (lstat(dst, &st) == 0) {
+               } else if (cache_name_pos(src, length) < 0)
+                       bad = "not under version control";
+               else if (lstat(dst, &st) == 0) {
                        bad = "destination exists";
                        if (force) {
                                /*
@@ -177,9 +179,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                                } else
                                        bad = "Cannot overwrite";
                        }
-               } else if (cache_name_pos(src, length) < 0)
-                       bad = "not under version control";
-               else if (string_list_has_string(&src_for_dst, dst))
+               } else if (string_list_has_string(&src_for_dst, dst))
                        bad = "multiple sources for the same target";
                else
                        string_list_insert(dst, &src_for_dst);
index a9fdbf9d45ddd84e6397ab3e559b06e105c52a19..d65d01969252332eeee12b0419e4ba3a806952b1 100644 (file)
@@ -15,6 +15,20 @@ static struct send_pack_args args = {
        /* .receivepack = */ "git-receive-pack",
 };
 
+static int feed_object(const unsigned char *sha1, int fd, int negative)
+{
+       char buf[42];
+
+       if (negative && !has_sha1_file(sha1))
+               return 1;
+
+       memcpy(buf + negative, sha1_to_hex(sha1), 40);
+       if (negative)
+               buf[0] = '^';
+       buf[40 + negative] = '\n';
+       return write_or_whine(fd, buf, 41 + negative, "send-pack: send refs");
+}
+
 /*
  * Make a pack stream and spit it out into file descriptor fd
  */
@@ -35,7 +49,6 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
        };
        struct child_process po;
        int i;
-       char buf[42];
 
        if (args.use_thin_pack)
                argv[4] = "--thin";
@@ -51,31 +64,17 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
         * We feed the pack-objects we just spawned with revision
         * parameters by writing to the pipe.
         */
-       for (i = 0; i < extra->nr; i++) {
-               memcpy(buf + 1, sha1_to_hex(&extra->array[i][0]), 40);
-               buf[0] = '^';
-               buf[41] = '\n';
-               if (!write_or_whine(po.in, buf, 42, "send-pack: send refs"))
+       for (i = 0; i < extra->nr; i++)
+               if (!feed_object(extra->array[i], po.in, 1))
                        break;
-       }
 
        while (refs) {
                if (!is_null_sha1(refs->old_sha1) &&
-                   has_sha1_file(refs->old_sha1)) {
-                       memcpy(buf + 1, sha1_to_hex(refs->old_sha1), 40);
-                       buf[0] = '^';
-                       buf[41] = '\n';
-                       if (!write_or_whine(po.in, buf, 42,
-                                               "send-pack: send refs"))
-                               break;
-               }
-               if (!is_null_sha1(refs->new_sha1)) {
-                       memcpy(buf, sha1_to_hex(refs->new_sha1), 40);
-                       buf[40] = '\n';
-                       if (!write_or_whine(po.in, buf, 41,
-                                               "send-pack: send refs"))
-                               break;
-               }
+                   !feed_object(refs->old_sha1, po.in, 1))
+                       break;
+               if (!is_null_sha1(refs->new_sha1) &&
+                   !feed_object(refs->new_sha1, po.in, 0))
+                       break;
                refs = refs->next;
        }
 
index daecd8e1cad4a301e2faa3888c561746d029f09d..b20f2101f265786ed61e2ca08764aae249bad9d4 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -240,6 +240,8 @@ int create_bundle(struct bundle_header *header, const char *path,
                return error("unrecognized argument: %s'", argv[i]);
        }
 
+       object_array_remove_duplicates(&revs.pending);
+
        for (i = 0; i < revs.pending.nr; i++) {
                struct object_array_entry *e = revs.pending.objects + i;
                unsigned char sha1[20];
index 168a95b541c2d6a4679115ebc9f30b1016645b19..0b0d6b8c8c2ab8833bb5d929ef0d3cb7891ec582 100644 (file)
@@ -153,9 +153,9 @@ static int estimate_similarity(struct diff_filespec *src,
         * is a possible size - we really should have a flag to
         * say whether the size is valid or not!)
         */
-       if (!src->cnt_data && diff_populate_filespec(src, 0))
+       if (!src->cnt_data && diff_populate_filespec(src, 1))
                return 0;
-       if (!dst->cnt_data && diff_populate_filespec(dst, 0))
+       if (!dst->cnt_data && diff_populate_filespec(dst, 1))
                return 0;
 
        max_size = ((src->size > dst->size) ? src->size : dst->size);
@@ -173,6 +173,11 @@ static int estimate_similarity(struct diff_filespec *src,
        if (base_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE)
                return 0;
 
+       if (!src->cnt_data && diff_populate_filespec(src, 0))
+               return 0;
+       if (!dst->cnt_data && diff_populate_filespec(dst, 0))
+               return 0;
+
        delta_limit = (unsigned long)
                (base_size * (MAX_SCORE-minimum_score) / MAX_SCORE);
        if (diffcore_count_changes(src, dst,
diff --git a/dump-cache-tree.c b/dump-cache-tree.c
deleted file mode 100644 (file)
index 1f73f1e..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#include "cache.h"
-#include "tree.h"
-#include "cache-tree.h"
-
-
-static void dump_one(struct cache_tree *it, const char *pfx, const char *x)
-{
-       if (it->entry_count < 0)
-               printf("%-40s %s%s (%d subtrees)\n",
-                      "invalid", x, pfx, it->subtree_nr);
-       else
-               printf("%s %s%s (%d entries, %d subtrees)\n",
-                      sha1_to_hex(it->sha1), x, pfx,
-                      it->entry_count, it->subtree_nr);
-}
-
-static int dump_cache_tree(struct cache_tree *it,
-                          struct cache_tree *ref,
-                          const char *pfx)
-{
-       int i;
-       int errs = 0;
-
-       if (!it || !ref)
-               /* missing in either */
-               return 0;
-
-       if (it->entry_count < 0) {
-               dump_one(it, pfx, "");
-               dump_one(ref, pfx, "#(ref) ");
-               if (it->subtree_nr != ref->subtree_nr)
-                       errs = 1;
-       }
-       else {
-               dump_one(it, pfx, "");
-               if (hashcmp(it->sha1, ref->sha1) ||
-                   ref->entry_count != it->entry_count ||
-                   ref->subtree_nr != it->subtree_nr) {
-                       dump_one(ref, pfx, "#(ref) ");
-                       errs = 1;
-               }
-       }
-
-       for (i = 0; i < it->subtree_nr; i++) {
-               char path[PATH_MAX];
-               struct cache_tree_sub *down = it->down[i];
-               struct cache_tree_sub *rdwn;
-
-               rdwn = cache_tree_sub(ref, down->name);
-               sprintf(path, "%s%.*s/", pfx, down->namelen, down->name);
-               if (dump_cache_tree(down->cache_tree, rdwn->cache_tree, path))
-                       errs = 1;
-       }
-       return errs;
-}
-
-int main(int ac, char **av)
-{
-       struct cache_tree *another = cache_tree();
-       if (read_cache() < 0)
-               die("unable to read index file");
-       cache_tree_update(another, active_cache, active_nr, 0, 1);
-       return dump_cache_tree(active_cache_tree, another, "");
-}
index f07d96b9b5e3997b21736893be39ce91950f4878..2142308bcc6d2e2c4962859d18e12070cd4c1b1d 100755 (executable)
@@ -96,7 +96,7 @@ cd_to_toplevel () {
                ..|../*|*/..|*/../*)
                        # Interpret $cdup relative to the physical, not logical, cwd.
                        # Probably /bin/pwd is more portable than passing -P to cd or pwd.
-                       phys="$(/bin/pwd)/$cdup"
+                       phys="$(unset PWD; /bin/pwd)/$cdup"
                        ;;
                *)
                        # There's no "..", so no need to make things absolute.
index 50b6528001fe4bafdfe70126dc2078860c3d1969..7e6a92c88e7b139ec03e0ff26e97e1559a06a220 100644 (file)
--- a/object.c
+++ b/object.c
@@ -268,3 +268,22 @@ void add_object_array_with_mode(struct object *obj, const char *name, struct obj
        objects[nr].mode = mode;
        array->nr = ++nr;
 }
+
+void object_array_remove_duplicates(struct object_array *array)
+{
+       int ref, src, dst;
+       struct object_array_entry *objects = array->objects;
+
+       for (ref = 0; ref < array->nr - 1; ref++) {
+               for (src = ref + 1, dst = src;
+                    src < array->nr;
+                    src++) {
+                       if (!strcmp(objects[ref].name, objects[src].name))
+                               continue;
+                       if (src != dst)
+                               objects[dst] = objects[src];
+                       dst++;
+               }
+               array->nr = dst;
+       }
+}
index d962ff11d1b2f810e21b049c7dbfed104cc199cb..89dd0c47a6c86fd3a63370c84e574e799830e1d3 100644 (file)
--- a/object.h
+++ b/object.h
@@ -82,5 +82,6 @@ int object_list_contains(struct object_list *list, struct object *obj);
 /* Object array handling .. */
 void add_object_array(struct object *obj, const char *name, struct object_array *array);
 void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode);
+void object_array_remove_duplicates(struct object_array *);
 
 #endif /* OBJECT_H */
index db60f06c98137f6e6e95727450d2842a0d4fb2a6..b0651845bf627cdfbd0aeebc4abc6366347b2433 100644 (file)
@@ -1263,6 +1263,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
 
                        if (!strcmp(arg, "--all")) {
                                handle_refs(revs, flags, for_each_ref);
+                               handle_refs(revs, flags, head_ref);
                                continue;
                        }
                        if (!strcmp(arg, "--branches")) {
index 52d1ead15b4db62138d9cedd5fe04068bcd10461..ce5ea12c4462eef27ddeb587b4f9937a63178adf 100644 (file)
@@ -2337,7 +2337,8 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
 static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
                              void *buf, unsigned long len, time_t mtime)
 {
-       int fd, size, ret;
+       int fd, ret;
+       size_t size;
        unsigned char *compressed;
        z_stream stream;
        char *filename;
index 159c2ab84fa2cdde0e540024a1ca22e0bbb43af8..722fc35a6d98e1c260c6e14738ad3b2d41d924aa 100644 (file)
@@ -309,7 +309,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 
        /* basic@{time or number} format to query ref-log */
        reflog_len = at = 0;
-       if (str[len-1] == '}') {
+       if (len && str[len-1] == '}') {
                for (at = 0; at < len - 1; at++) {
                        if (str[at] == '@' && str[at+1] == '{') {
                                reflog_len = (len-1) - (at+2);
index beddb4e9f26cb3ade276825a204d950d3173d583..e42cbfe6c61951c6887a363cb668d26a7adcf20c 100755 (executable)
@@ -10,12 +10,12 @@ test_cd_to_toplevel () {
                        cd '"'$1'"' &&
                        . git-sh-setup &&
                        cd_to_toplevel &&
-                       [ "$(/bin/pwd)" = "$TOPLEVEL" ]
+                       [ "$(unset PWD; /bin/pwd)" = "$TOPLEVEL" ]
                )
        '
 }
 
-TOPLEVEL="$(/bin/pwd)/repo"
+TOPLEVEL="$(unset PWD; /bin/pwd)/repo"
 mkdir -p repo/sub/dir
 mv .git repo/
 SUBDIRECTORY_OK=1
index 9d99dc28879d4f7f35001e0785f97f319fe13b40..f045898fe3196b068d03a66fd9edeea6f32add30 100755 (executable)
@@ -3,7 +3,7 @@
 # Copyright (c) 2006 Junio C Hamano
 #
 
-test_description='Format-patch skipping already incorporated patches'
+test_description='various format-patch tests'
 
 . ./test-lib.sh
 
@@ -255,4 +255,54 @@ test_expect_success 'format-patch respects -U' '
 
 '
 
+test_expect_success 'format-patch from a subdirectory (1)' '
+       filename=$(
+               rm -rf sub &&
+               mkdir -p sub/dir &&
+               cd sub/dir &&
+               git format-patch -1
+       ) &&
+       case "$filename" in
+       0*)
+               ;; # ok
+       *)
+               echo "Oops? $filename"
+               false
+               ;;
+       esac &&
+       test -f "$filename"
+'
+
+test_expect_success 'format-patch from a subdirectory (2)' '
+       filename=$(
+               rm -rf sub &&
+               mkdir -p sub/dir &&
+               cd sub/dir &&
+               git format-patch -1 -o ..
+       ) &&
+       case "$filename" in
+       ../0*)
+               ;; # ok
+       *)
+               echo "Oops? $filename"
+               false
+               ;;
+       esac &&
+       basename=$(expr "$filename" : ".*/\(.*\)") &&
+       test -f "sub/$basename"
+'
+
+test_expect_success 'format-patch from a subdirectory (3)' '
+       here="$TEST_DIRECTORY/$test" &&
+       rm -f 0* &&
+       filename=$(
+               rm -rf sub &&
+               mkdir -p sub/dir &&
+               cd sub/dir &&
+               git format-patch -1 -o "$here"
+       ) &&
+       basename=$(expr "$filename" : ".*/\(.*\)") &&
+       test -f "$basename"
+'
+
 test_done
index fc2307eaa3b4e8b1481fd7aa5ae0f93d085338af..6d13da30dad5a78fb17a01e86ef33072ea9e6250 100755 (executable)
@@ -98,6 +98,12 @@ index d99af23..8b32fb5 100644
 EOF
 git diff -w > out
 test_expect_success 'another test, with -w' 'test_cmp expect out'
+git diff -w -b > out
+test_expect_success 'another test, with -w -b' 'test_cmp expect out'
+git diff -w --ignore-space-at-eol > out
+test_expect_success 'another test, with -w --ignore-space-at-eol' 'test_cmp expect out'
+git diff -w -b --ignore-space-at-eol > out
+test_expect_success 'another test, with -w -b --ignore-space-at-eol' 'test_cmp expect out'
 
 tr 'Q' '\015' << EOF > expect
 diff --git a/x b/x
@@ -116,6 +122,27 @@ index d99af23..8b32fb5 100644
 EOF
 git diff -b > out
 test_expect_success 'another test, with -b' 'test_cmp expect out'
+git diff -b --ignore-space-at-eol > out
+test_expect_success 'another test, with -b --ignore-space-at-eol' 'test_cmp expect out'
+
+tr 'Q' '\015' << EOF > expect
+diff --git a/x b/x
+index d99af23..8b32fb5 100644
+--- a/x
++++ b/x
+@@ -1,6 +1,6 @@
+-whitespace at beginning
+-whitespace change
+-whitespace in the middle
++      whitespace at beginning
++whitespace     change
++white space in the middle
+ whitespace at end
+ unchanged line
+ CR at endQ
+EOF
+git diff --ignore-space-at-eol > out
+test_expect_success 'another test, with --ignore-space-at-eol' 'test_cmp expect out'
 
 test_expect_success 'check mixed spaces and tabs in indent' '
 
diff --git a/t/t5519-push-alternates.sh b/t/t5519-push-alternates.sh
new file mode 100755 (executable)
index 0000000..6dfc55a
--- /dev/null
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+test_description='push to a repository that borrows from elsewhere'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+       mkdir alice-pub &&
+       (
+               cd alice-pub &&
+               GIT_DIR=. git init
+       ) &&
+       mkdir alice-work &&
+       (
+               cd alice-work &&
+               git init &&
+               >file &&
+               git add . &&
+               git commit -m initial &&
+               git push ../alice-pub master
+       ) &&
+
+       # Project Bob is a fork of project Alice
+       mkdir bob-pub &&
+       (
+               cd bob-pub &&
+               GIT_DIR=. git init &&
+               mkdir -p objects/info &&
+               echo ../../alice-pub/objects >objects/info/alternates
+       ) &&
+       git clone alice-pub bob-work &&
+       (
+               cd bob-work &&
+               git push ../bob-pub master
+       )
+'
+
+test_expect_success 'alice works and pushes' '
+       (
+               cd alice-work &&
+               echo more >file &&
+               git commit -a -m second &&
+               git push ../alice-pub
+       )
+'
+
+test_expect_success 'bob fetches from alice, works and pushes' '
+       (
+               # Bob acquires what Alice did in his work tree first.
+               # Even though these objects are not directly in
+               # the public repository of Bob, this push does not
+               # need to send the commit Bob received from Alice
+               # to his public repository, as all the object Alice
+               # has at her public repository are available to it
+               # via its alternates.
+               cd bob-work &&
+               git pull ../alice-pub master &&
+               echo more bob >file &&
+               git commit -a -m third &&
+               git push ../bob-pub
+       ) &&
+
+       # Check that the second commit by Alice is not sent
+       # to ../bob-pub
+       (
+               cd bob-pub &&
+               second=$(git rev-parse HEAD^) &&
+               rm -f objects/info/alternates &&
+               test_must_fail git cat-file -t $second &&
+               echo ../../alice-pub/objects >objects/info/alternates
+       )
+'
+
+test_expect_success 'clean-up in case the previous failed' '
+       (
+               cd bob-pub &&
+               echo ../../alice-pub/objects >objects/info/alternates
+       )
+'
+
+test_expect_success 'alice works and pushes again' '
+       (
+               # Alice does not care what Bob does.  She does not
+               # even have to be aware of his existence.  She just
+               # keeps working and pushing
+               cd alice-work &&
+               echo more alice >file &&
+               git commit -a -m fourth &&
+               git push ../alice-pub
+       )
+'
+
+test_expect_success 'bob works and pushes' '
+       (
+               # This time Bob does not pull from Alice, and
+               # the master branch at her public repository points
+               # at a commit Bob does not know about.  This should
+               # not prevent the push by Bob from succeeding.
+               cd bob-work &&
+               echo yet more bob >file &&
+               git commit -a -m fifth &&
+               git push ../bob-pub
+       )
+'
+
+test_done
index 8dfaaa456e115e85e36c438bb998d8053534104e..fe0fda282ca4f085f506c743848966fa6bb93591 100755 (executable)
@@ -11,8 +11,8 @@ test_expect_success 'preparing origin repository' '
        git clone --bare . x &&
        test "$(GIT_CONFIG=a.git/config git config --bool core.bare)" = true &&
        test "$(GIT_CONFIG=x/config git config --bool core.bare)" = true
-       git bundle create b1.bundle --all HEAD &&
-       git bundle create b2.bundle --all &&
+       git bundle create b1.bundle --all &&
+       git bundle create b2.bundle master &&
        mkdir dir &&
        cp b1.bundle dir/b3
        cp b1.bundle b4
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
new file mode 100755 (executable)
index 0000000..991ab4a
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+test_description='--all includes detached HEADs'
+
+. ./test-lib.sh
+
+
+commit () {
+       test_tick &&
+       echo $1 > foo &&
+       git add foo &&
+       git commit -m "$1"
+}
+
+test_expect_success 'setup' '
+
+       commit one &&
+       commit two &&
+       git checkout HEAD^ &&
+       commit detached
+
+'
+
+test_expect_success 'rev-list --all lists detached HEAD' '
+
+       test 3 = $(git rev-list --all | wc -l)
+
+'
+
+test_expect_success 'repack does not lose detached HEAD' '
+
+       git gc &&
+       git prune --expire=now &&
+       git show HEAD
+
+'
+
+test_done
index ef2e78f9df951cfacf5914dfff2a218d2e6f89f7..8fb3a56838dd476b9b0923f835ce70bd95499f2b 100755 (executable)
@@ -55,9 +55,17 @@ test_expect_success \
      git mv -k untracked1 untracked2 path0 &&
      test -f untracked1 &&
      test -f untracked2 &&
-     test ! -f path0/untracked1
+     test ! -f path0/untracked1 &&
      test ! -f path0/untracked2'
 
+test_expect_success \
+    'checking -f on untracked file with existing target' \
+    'touch path0/untracked1 &&
+     git mv -f untracked1 path0
+     test ! -f .git/index.lock &&
+     test -f untracked1 &&
+     test -f path0/untracked1'
+
 # clean up the mess in case bad things happen
 rm -f idontexist untracked1 untracked2 \
      path0/idontexist path0/untracked1 path0/untracked2 \
index 18fe6f2d576d35706b1a712292b58155680cc9dc..c4938544d4ca7c5e7e886a59144c9b10b7971748 100755 (executable)
@@ -161,7 +161,14 @@ test_expect_success 'log grep (6)' '
        git log --author=-0700  --pretty=tformat:%s >actual &&
        >expect &&
        test_cmp expect actual
+'
 
+test_expect_success 'grep with CE_VALID file' '
+       git update-index --assume-unchanged t/t &&
+       rm t/t &&
+       test "$(git grep --no-ext-grep t)" = "t/t:test" &&
+       git update-index --no-assume-unchanged t/t &&
+       git checkout t/t
 '
 
 test_done
diff --git a/test-dump-cache-tree.c b/test-dump-cache-tree.c
new file mode 100644 (file)
index 0000000..1f73f1e
--- /dev/null
@@ -0,0 +1,64 @@
+#include "cache.h"
+#include "tree.h"
+#include "cache-tree.h"
+
+
+static void dump_one(struct cache_tree *it, const char *pfx, const char *x)
+{
+       if (it->entry_count < 0)
+               printf("%-40s %s%s (%d subtrees)\n",
+                      "invalid", x, pfx, it->subtree_nr);
+       else
+               printf("%s %s%s (%d entries, %d subtrees)\n",
+                      sha1_to_hex(it->sha1), x, pfx,
+                      it->entry_count, it->subtree_nr);
+}
+
+static int dump_cache_tree(struct cache_tree *it,
+                          struct cache_tree *ref,
+                          const char *pfx)
+{
+       int i;
+       int errs = 0;
+
+       if (!it || !ref)
+               /* missing in either */
+               return 0;
+
+       if (it->entry_count < 0) {
+               dump_one(it, pfx, "");
+               dump_one(ref, pfx, "#(ref) ");
+               if (it->subtree_nr != ref->subtree_nr)
+                       errs = 1;
+       }
+       else {
+               dump_one(it, pfx, "");
+               if (hashcmp(it->sha1, ref->sha1) ||
+                   ref->entry_count != it->entry_count ||
+                   ref->subtree_nr != it->subtree_nr) {
+                       dump_one(ref, pfx, "#(ref) ");
+                       errs = 1;
+               }
+       }
+
+       for (i = 0; i < it->subtree_nr; i++) {
+               char path[PATH_MAX];
+               struct cache_tree_sub *down = it->down[i];
+               struct cache_tree_sub *rdwn;
+
+               rdwn = cache_tree_sub(ref, down->name);
+               sprintf(path, "%s%.*s/", pfx, down->namelen, down->name);
+               if (dump_cache_tree(down->cache_tree, rdwn->cache_tree, path))
+                       errs = 1;
+       }
+       return errs;
+}
+
+int main(int ac, char **av)
+{
+       struct cache_tree *another = cache_tree();
+       if (read_cache() < 0)
+               die("unable to read index file");
+       cache_tree_update(another, active_cache, active_nr, 0, 1);
+       return dump_cache_tree(active_cache_tree, another, "");
+}
index a0bcb0e210523124fa977c8bf46667cf25d0335f..2c0f5a37e8b9051b1db80aa04e9ea763fb8d772b 100644 (file)
@@ -3,7 +3,7 @@
 int main(int argc, char **argv)
 {
        if (argc == 3 && !strcmp(argv[1], "normalize_absolute_path")) {
-               char *buf = xmalloc(strlen(argv[2])+1);
+               char *buf = xmalloc(PATH_MAX + 1);
                int rv = normalize_absolute_path(buf, argv[2]);
                assert(strlen(buf) == rv);
                puts(buf);
index 15c9ef592b393410354496c577a6e8c2dfb39940..3a4e181af43add517a7a86511c17e4198552289c 100644 (file)
@@ -240,8 +240,11 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info, con
        return ce;
 }
 
-static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmask, struct cache_entry *src[5],
-       const struct name_entry *names, const struct traverse_info *info)
+static int unpack_nondirectories(int n, unsigned long mask,
+                                unsigned long dirmask,
+                                struct cache_entry **src,
+                                const struct name_entry *names,
+                                const struct traverse_info *info)
 {
        int i;
        struct unpack_trees_options *o = info->data;
@@ -291,7 +294,7 @@ static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmas
 
 static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *names, struct traverse_info *info)
 {
-       struct cache_entry *src[5] = { NULL, };
+       struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
        struct unpack_trees_options *o = info->data;
        const struct name_entry *p = names;
 
index d7974d1a3e612a235b0c8adfde08ba802e782b5a..04ad468702209b77427e635370d41001986042ce 100644 (file)
@@ -245,12 +245,14 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
                        while (ptr + 1 < top && isspace(ptr[1])
                                        && ptr[1] != '\n')
                                ptr++;
-                       if (flags & XDF_IGNORE_WHITESPACE_CHANGE
+                       if (flags & XDF_IGNORE_WHITESPACE)
+                               ; /* already handled */
+                       else if (flags & XDF_IGNORE_WHITESPACE_CHANGE
                                        && ptr[1] != '\n') {
                                ha += (ha << 5);
                                ha ^= (unsigned long) ' ';
                        }
-                       if (flags & XDF_IGNORE_WHITESPACE_AT_EOL
+                       else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL
                                        && ptr[1] != '\n') {
                                while (ptr2 != ptr + 1) {
                                        ha += (ha << 5);