summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes-1.6.1.2.txt39
-rw-r--r--Documentation/config.txt4
-rw-r--r--Documentation/git-ls-tree.txt8
-rw-r--r--Documentation/technical/api-strbuf.txt2
-rw-r--r--Documentation/urls.txt8
-rw-r--r--Documentation/user-manual.txt2
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile2
l---------RelNotes2
-rw-r--r--builtin-apply.c7
-rw-r--r--builtin-commit.c6
-rw-r--r--builtin-gc.c8
-rw-r--r--builtin-grep.c17
-rw-r--r--builtin-log.c28
-rw-r--r--builtin-ls-tree.c7
-rw-r--r--builtin-mv.c8
-rw-r--r--builtin-pack-objects.c6
-rw-r--r--builtin-send-pack.c43
-rw-r--r--builtin-unpack-objects.c6
-rw-r--r--bundle.c2
-rw-r--r--cache.h4
-rw-r--r--diff.c146
-rw-r--r--diffcore-rename.c9
-rwxr-xr-xgit-sh-setup.sh2
-rw-r--r--http-push.c8
-rw-r--r--http-walker.c8
-rw-r--r--index-pack.c12
-rw-r--r--object.c19
-rw-r--r--object.h1
-rw-r--r--revision.c1
-rw-r--r--setup.c6
-rw-r--r--sha1_file.c27
-rw-r--r--sha1_name.c2
-rwxr-xr-xt/t1501-worktree.sh7
-rwxr-xr-xt/t2300-cd-to-toplevel.sh4
-rwxr-xr-xt/t4014-format-patch.sh52
-rwxr-xr-xt/t4015-diff-whitespace.sh27
-rwxr-xr-xt/t4030-diff-textconv.sh2
-rwxr-xr-xt/t4114-apply-typechange.sh18
-rwxr-xr-xt/t5519-push-alternates.sh106
-rwxr-xr-xt/t5701-clone-local.sh4
-rwxr-xr-xt/t6014-rev-list-all.sh38
-rwxr-xr-xt/t7001-mv.sh10
-rwxr-xr-xt/t7002-grep.sh7
-rw-r--r--test-dump-cache-tree.c (renamed from dump-cache-tree.c)0
-rw-r--r--test-path-utils.c2
-rw-r--r--unpack-trees.c9
-rw-r--r--wrapper.c60
-rw-r--r--xdiff/xutils.c6
49 files changed, 639 insertions, 165 deletions
diff --git a/Documentation/RelNotes-1.6.1.2.txt b/Documentation/RelNotes-1.6.1.2.txt
new file mode 100644
index 0000000000..230aa3d8e8
--- /dev/null
+++ b/Documentation/RelNotes-1.6.1.2.txt
@@ -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.
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 26551ea6e1..2ed868c81a 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -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
diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt
index 4c7262f1cd..db6ebccd6d 100644
--- a/Documentation/git-ls-tree.txt
+++ b/Documentation/git-ls-tree.txt
@@ -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
diff --git a/Documentation/technical/api-strbuf.txt b/Documentation/technical/api-strbuf.txt
index a8ee2fe6a1..985800e43a 100644
--- a/Documentation/technical/api-strbuf.txt
+++ b/Documentation/technical/api-strbuf.txt
@@ -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
diff --git a/Documentation/urls.txt b/Documentation/urls.txt
index fa34c67471..5355ebc0f3 100644
--- a/Documentation/urls.txt
+++ b/Documentation/urls.txt
@@ -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/
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index 19f571ae3b..96af8977f6 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -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
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index fe496e5fca..3697edc72e 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -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='
'
diff --git a/Makefile b/Makefile
index aabf0130b9..01242889eb 100644
--- 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)
diff --git a/RelNotes b/RelNotes
index 2ebf251ddf..da6e81321a 120000
--- 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
diff --git a/builtin-apply.c b/builtin-apply.c
index a8f75ed3ed..b31007ba99 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -1253,8 +1253,9 @@ static char *inflate_it(const void *data, unsigned long size,
stream.avail_in = size;
stream.next_out = out = xmalloc(inflated_size);
stream.avail_out = inflated_size;
- inflateInit(&stream);
- st = inflate(&stream, Z_FINISH);
+ git_inflate_init(&stream);
+ st = git_inflate(&stream, Z_FINISH);
+ git_inflate_end(&stream);
if ((st != Z_STREAM_END) || stream.total_out != inflated_size) {
free(out);
return NULL;
@@ -2435,7 +2436,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)
diff --git a/builtin-commit.c b/builtin-commit.c
index 977ea09c51..2f0b00a174 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -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);
diff --git a/builtin-gc.c b/builtin-gc.c
index 781df601c5..f8eae4adb4 100644
--- a/builtin-gc.c
+++ b/builtin-gc.c
@@ -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]);
diff --git a/builtin-grep.c b/builtin-grep.c
index 624f86e287..3f12ba3826 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -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;
diff --git a/builtin-log.c b/builtin-log.c
index 4420b4fd4f..60f8dd8604 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -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)
diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c
index cb61717685..5b63e6eada 100644
--- a/builtin-ls-tree.c
+++ b/builtin-ls-tree.c
@@ -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)
diff --git a/builtin-mv.c b/builtin-mv.c
index bce9959293..01270fefdf 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -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);
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index cedef52fd3..b616994f45 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -195,16 +195,16 @@ static int check_pack_inflate(struct packed_git *p,
int st;
memset(&stream, 0, sizeof(stream));
- inflateInit(&stream);
+ git_inflate_init(&stream);
do {
in = use_pack(p, w_curs, offset, &stream.avail_in);
stream.next_in = in;
stream.next_out = fakebuf;
stream.avail_out = sizeof(fakebuf);
- st = inflate(&stream, Z_FINISH);
+ st = git_inflate(&stream, Z_FINISH);
offset += stream.next_in - in;
} while (st == Z_OK || st == Z_BUF_ERROR);
- inflateEnd(&stream);
+ git_inflate_end(&stream);
return (st == Z_STREAM_END &&
stream.total_out == expect &&
stream.total_in == len) ? 0 : -1;
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index a9fdbf9d45..d65d019692 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -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;
}
diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c
index 47ed610677..9a773239ca 100644
--- a/builtin-unpack-objects.c
+++ b/builtin-unpack-objects.c
@@ -99,10 +99,10 @@ static void *get_data(unsigned long size)
stream.avail_out = size;
stream.next_in = fill(1);
stream.avail_in = len;
- inflateInit(&stream);
+ git_inflate_init(&stream);
for (;;) {
- int ret = inflate(&stream, 0);
+ int ret = git_inflate(&stream, 0);
use(len - stream.avail_in);
if (stream.total_out == size && ret == Z_STREAM_END)
break;
@@ -118,7 +118,7 @@ static void *get_data(unsigned long size)
stream.next_in = fill(1);
stream.avail_in = len;
}
- inflateEnd(&stream);
+ git_inflate_end(&stream);
return buf;
}
diff --git a/bundle.c b/bundle.c
index daecd8e1ca..b20f2101f2 100644
--- 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];
diff --git a/cache.h b/cache.h
index 231c06d772..49e54fbe67 100644
--- a/cache.h
+++ b/cache.h
@@ -18,6 +18,10 @@
#define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
#endif
+void git_inflate_init(z_streamp strm);
+void git_inflate_end(z_streamp strm);
+int git_inflate(z_streamp strm, int flush);
+
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
#define DTYPE(de) ((de)->d_type)
#else
diff --git a/diff.c b/diff.c
index 5b85b4077a..416c5aa722 100644
--- a/diff.c
+++ b/diff.c
@@ -1999,16 +1999,86 @@ static void run_external_diff(const char *pgm,
}
}
+static int similarity_index(struct diff_filepair *p)
+{
+ return p->score * 100 / MAX_SCORE;
+}
+
+static void fill_metainfo(struct strbuf *msg,
+ const char *name,
+ const char *other,
+ struct diff_filespec *one,
+ struct diff_filespec *two,
+ struct diff_options *o,
+ struct diff_filepair *p)
+{
+ strbuf_init(msg, PATH_MAX * 2 + 300);
+ switch (p->status) {
+ case DIFF_STATUS_COPIED:
+ strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
+ strbuf_addstr(msg, "\ncopy from ");
+ quote_c_style(name, msg, NULL, 0);
+ strbuf_addstr(msg, "\ncopy to ");
+ quote_c_style(other, msg, NULL, 0);
+ strbuf_addch(msg, '\n');
+ break;
+ case DIFF_STATUS_RENAMED:
+ strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
+ strbuf_addstr(msg, "\nrename from ");
+ quote_c_style(name, msg, NULL, 0);
+ strbuf_addstr(msg, "\nrename to ");
+ quote_c_style(other, msg, NULL, 0);
+ strbuf_addch(msg, '\n');
+ break;
+ case DIFF_STATUS_MODIFIED:
+ if (p->score) {
+ strbuf_addf(msg, "dissimilarity index %d%%\n",
+ similarity_index(p));
+ break;
+ }
+ /* fallthru */
+ default:
+ /* nothing */
+ ;
+ }
+ if (one && two && hashcmp(one->sha1, two->sha1)) {
+ int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
+
+ if (DIFF_OPT_TST(o, BINARY)) {
+ mmfile_t mf;
+ if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) ||
+ (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
+ abbrev = 40;
+ }
+ strbuf_addf(msg, "index %.*s..%.*s",
+ abbrev, sha1_to_hex(one->sha1),
+ abbrev, sha1_to_hex(two->sha1));
+ if (one->mode == two->mode)
+ strbuf_addf(msg, " %06o", one->mode);
+ strbuf_addch(msg, '\n');
+ }
+ if (msg->len)
+ strbuf_setlen(msg, msg->len - 1);
+}
+
static void run_diff_cmd(const char *pgm,
const char *name,
const char *other,
const char *attr_path,
struct diff_filespec *one,
struct diff_filespec *two,
- const char *xfrm_msg,
+ struct strbuf *msg,
struct diff_options *o,
- int complete_rewrite)
+ struct diff_filepair *p)
{
+ const char *xfrm_msg = NULL;
+ int complete_rewrite = (p->status == DIFF_STATUS_MODIFIED) && p->score;
+
+ if (msg) {
+ fill_metainfo(msg, name, other, one, two, o, p);
+ xfrm_msg = msg->len ? msg->buf : NULL;
+ }
+
if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
pgm = NULL;
else {
@@ -2048,11 +2118,6 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
hashclr(one->sha1);
}
-static int similarity_index(struct diff_filepair *p)
-{
- return p->score * 100 / MAX_SCORE;
-}
-
static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
{
/* Strip the prefix but do not molest /dev/null and absolute paths */
@@ -2066,13 +2131,11 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
{
const char *pgm = external_diff();
struct strbuf msg;
- char *xfrm_msg;
struct diff_filespec *one = p->one;
struct diff_filespec *two = p->two;
const char *name;
const char *other;
const char *attr_path;
- int complete_rewrite = 0;
name = p->one->path;
other = (strcmp(name, p->two->path) ? p->two->path : NULL);
@@ -2082,83 +2145,34 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
if (DIFF_PAIR_UNMERGED(p)) {
run_diff_cmd(pgm, name, NULL, attr_path,
- NULL, NULL, NULL, o, 0);
+ NULL, NULL, NULL, o, p);
return;
}
diff_fill_sha1_info(one);
diff_fill_sha1_info(two);
- strbuf_init(&msg, PATH_MAX * 2 + 300);
- switch (p->status) {
- case DIFF_STATUS_COPIED:
- strbuf_addf(&msg, "similarity index %d%%", similarity_index(p));
- strbuf_addstr(&msg, "\ncopy from ");
- quote_c_style(name, &msg, NULL, 0);
- strbuf_addstr(&msg, "\ncopy to ");
- quote_c_style(other, &msg, NULL, 0);
- strbuf_addch(&msg, '\n');
- break;
- case DIFF_STATUS_RENAMED:
- strbuf_addf(&msg, "similarity index %d%%", similarity_index(p));
- strbuf_addstr(&msg, "\nrename from ");
- quote_c_style(name, &msg, NULL, 0);
- strbuf_addstr(&msg, "\nrename to ");
- quote_c_style(other, &msg, NULL, 0);
- strbuf_addch(&msg, '\n');
- break;
- case DIFF_STATUS_MODIFIED:
- if (p->score) {
- strbuf_addf(&msg, "dissimilarity index %d%%\n",
- similarity_index(p));
- complete_rewrite = 1;
- break;
- }
- /* fallthru */
- default:
- /* nothing */
- ;
- }
-
- if (hashcmp(one->sha1, two->sha1)) {
- int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
-
- if (DIFF_OPT_TST(o, BINARY)) {
- mmfile_t mf;
- if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) ||
- (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
- abbrev = 40;
- }
- strbuf_addf(&msg, "index %.*s..%.*s",
- abbrev, sha1_to_hex(one->sha1),
- abbrev, sha1_to_hex(two->sha1));
- if (one->mode == two->mode)
- strbuf_addf(&msg, " %06o", one->mode);
- strbuf_addch(&msg, '\n');
- }
-
- if (msg.len)
- strbuf_setlen(&msg, msg.len - 1);
- xfrm_msg = msg.len ? msg.buf : NULL;
-
if (!pgm &&
DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
(S_IFMT & one->mode) != (S_IFMT & two->mode)) {
- /* a filepair that changes between file and symlink
+ /*
+ * a filepair that changes between file and symlink
* needs to be split into deletion and creation.
*/
struct diff_filespec *null = alloc_filespec(two->path);
run_diff_cmd(NULL, name, other, attr_path,
- one, null, xfrm_msg, o, 0);
+ one, null, &msg, o, p);
free(null);
+ strbuf_release(&msg);
+
null = alloc_filespec(one->path);
run_diff_cmd(NULL, name, other, attr_path,
- null, two, xfrm_msg, o, 0);
+ null, two, &msg, o, p);
free(null);
}
else
run_diff_cmd(pgm, name, other, attr_path,
- one, two, xfrm_msg, o, complete_rewrite);
+ one, two, &msg, o, p);
strbuf_release(&msg);
}
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 168a95b541..0b0d6b8c8c 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -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/git-sh-setup.sh b/git-sh-setup.sh
index f07d96b9b5..2142308bcc 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -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.
diff --git a/http-push.c b/http-push.c
index 6ad853e2d0..cb5bf95a73 100644
--- a/http-push.c
+++ b/http-push.c
@@ -209,7 +209,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
do {
request->stream.next_out = expn;
request->stream.avail_out = sizeof(expn);
- request->zret = inflate(&request->stream, Z_SYNC_FLUSH);
+ request->zret = git_inflate(&request->stream, Z_SYNC_FLUSH);
git_SHA1_Update(&request->c, expn,
sizeof(expn) - request->stream.avail_out);
} while (request->stream.avail_in && request->zret == Z_OK);
@@ -269,7 +269,7 @@ static void start_fetch_loose(struct transfer_request *request)
memset(&request->stream, 0, sizeof(request->stream));
- inflateInit(&request->stream);
+ git_inflate_init(&request->stream);
git_SHA1_Init(&request->c);
@@ -310,7 +310,7 @@ static void start_fetch_loose(struct transfer_request *request)
file; also rewind to the beginning of the local file. */
if (prev_read == -1) {
memset(&request->stream, 0, sizeof(request->stream));
- inflateInit(&request->stream);
+ git_inflate_init(&request->stream);
git_SHA1_Init(&request->c);
if (prev_posn>0) {
prev_posn = 0;
@@ -742,7 +742,7 @@ static void finish_request(struct transfer_request *request)
if (request->http_code == 416)
fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
- inflateEnd(&request->stream);
+ git_inflate_end(&request->stream);
git_SHA1_Final(request->real_sha1, &request->c);
if (request->zret != Z_STREAM_END) {
unlink(request->tmpfile);
diff --git a/http-walker.c b/http-walker.c
index 7271c7d19d..0dbad3c888 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -82,7 +82,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
do {
obj_req->stream.next_out = expn;
obj_req->stream.avail_out = sizeof(expn);
- obj_req->zret = inflate(&obj_req->stream, Z_SYNC_FLUSH);
+ obj_req->zret = git_inflate(&obj_req->stream, Z_SYNC_FLUSH);
git_SHA1_Update(&obj_req->c, expn,
sizeof(expn) - obj_req->stream.avail_out);
} while (obj_req->stream.avail_in && obj_req->zret == Z_OK);
@@ -142,7 +142,7 @@ static void start_object_request(struct walker *walker,
memset(&obj_req->stream, 0, sizeof(obj_req->stream));
- inflateInit(&obj_req->stream);
+ git_inflate_init(&obj_req->stream);
git_SHA1_Init(&obj_req->c);
@@ -183,7 +183,7 @@ static void start_object_request(struct walker *walker,
file; also rewind to the beginning of the local file. */
if (prev_read == -1) {
memset(&obj_req->stream, 0, sizeof(obj_req->stream));
- inflateInit(&obj_req->stream);
+ git_inflate_init(&obj_req->stream);
git_SHA1_Init(&obj_req->c);
if (prev_posn>0) {
prev_posn = 0;
@@ -243,7 +243,7 @@ static void finish_object_request(struct object_request *obj_req)
return;
}
- inflateEnd(&obj_req->stream);
+ git_inflate_end(&obj_req->stream);
git_SHA1_Final(obj_req->real_sha1, &obj_req->c);
if (obj_req->zret != Z_STREAM_END) {
unlink(obj_req->tmpfile);
diff --git a/index-pack.c b/index-pack.c
index 60ed41a993..c0a3d97a12 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -275,10 +275,10 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size)
stream.avail_out = size;
stream.next_in = fill(1);
stream.avail_in = input_len;
- inflateInit(&stream);
+ git_inflate_init(&stream);
for (;;) {
- int ret = inflate(&stream, 0);
+ int ret = git_inflate(&stream, 0);
use(input_len - stream.avail_in);
if (stream.total_out == size && ret == Z_STREAM_END)
break;
@@ -287,7 +287,7 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size)
stream.next_in = fill(1);
stream.avail_in = input_len;
}
- inflateEnd(&stream);
+ git_inflate_end(&stream);
return buf;
}
@@ -382,9 +382,9 @@ static void *get_data_from_pack(struct object_entry *obj)
stream.avail_out = obj->size;
stream.next_in = src;
stream.avail_in = len;
- inflateInit(&stream);
- while ((st = inflate(&stream, Z_FINISH)) == Z_OK);
- inflateEnd(&stream);
+ git_inflate_init(&stream);
+ while ((st = git_inflate(&stream, Z_FINISH)) == Z_OK);
+ git_inflate_end(&stream);
if (st != Z_STREAM_END || stream.total_out != obj->size)
die("serious inflate inconsistency");
free(src);
diff --git a/object.c b/object.c
index 50b6528001..7e6a92c88e 100644
--- 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;
+ }
+}
diff --git a/object.h b/object.h
index d962ff11d1..89dd0c47a6 100644
--- 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 */
diff --git a/revision.c b/revision.c
index db60f06c98..b0651845bf 100644
--- a/revision.c
+++ b/revision.c
@@ -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")) {
diff --git a/setup.c b/setup.c
index 6b277b6a11..dfda532adc 100644
--- a/setup.c
+++ b/setup.c
@@ -456,7 +456,11 @@ const char *setup_git_directory_gently(int *nongit_ok)
inside_git_dir = 1;
if (!work_tree_env)
inside_work_tree = 0;
- setenv(GIT_DIR_ENVIRONMENT, ".", 1);
+ if (offset != len) {
+ cwd[offset] = '\0';
+ setenv(GIT_DIR_ENVIRONMENT, cwd, 1);
+ } else
+ setenv(GIT_DIR_ENVIRONMENT, ".", 1);
check_repository_format_gently(nongit_ok);
return NULL;
}
diff --git a/sha1_file.c b/sha1_file.c
index 52d1ead15b..ced33e837b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1196,8 +1196,8 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
stream->avail_out = bufsiz;
if (legacy_loose_object(map)) {
- inflateInit(stream);
- return inflate(stream, 0);
+ git_inflate_init(stream);
+ return git_inflate(stream, 0);
}
@@ -1217,7 +1217,7 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
/* Set up the stream for the rest.. */
stream->next_in = map;
stream->avail_in = mapsize;
- inflateInit(stream);
+ git_inflate_init(stream);
/* And generate the fake traditional header */
stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu",
@@ -1254,11 +1254,11 @@ static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size
stream->next_out = buf + bytes;
stream->avail_out = size - bytes;
while (status == Z_OK)
- status = inflate(stream, Z_FINISH);
+ status = git_inflate(stream, Z_FINISH);
}
buf[size] = 0;
if (status == Z_STREAM_END && !stream->avail_in) {
- inflateEnd(stream);
+ git_inflate_end(stream);
return buf;
}
@@ -1348,15 +1348,15 @@ unsigned long get_size_from_delta(struct packed_git *p,
stream.next_out = delta_head;
stream.avail_out = sizeof(delta_head);
- inflateInit(&stream);
+ git_inflate_init(&stream);
do {
in = use_pack(p, w_curs, curpos, &stream.avail_in);
stream.next_in = in;
- st = inflate(&stream, Z_FINISH);
+ st = git_inflate(&stream, Z_FINISH);
curpos += stream.next_in - in;
} while ((st == Z_OK || st == Z_BUF_ERROR) &&
stream.total_out < sizeof(delta_head));
- inflateEnd(&stream);
+ git_inflate_end(&stream);
if ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head)) {
error("delta data unpack-initial failed");
return 0;
@@ -1585,14 +1585,14 @@ static void *unpack_compressed_entry(struct packed_git *p,
stream.next_out = buffer;
stream.avail_out = size;
- inflateInit(&stream);
+ git_inflate_init(&stream);
do {
in = use_pack(p, w_curs, curpos, &stream.avail_in);
stream.next_in = in;
- st = inflate(&stream, Z_FINISH);
+ st = git_inflate(&stream, Z_FINISH);
curpos += stream.next_in - in;
} while (st == Z_OK || st == Z_BUF_ERROR);
- inflateEnd(&stream);
+ git_inflate_end(&stream);
if ((st != Z_STREAM_END) || stream.total_out != size) {
free(buffer);
return NULL;
@@ -2017,7 +2017,7 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
status = error("unable to parse %s header", sha1_to_hex(sha1));
else if (sizep)
*sizep = size;
- inflateEnd(&stream);
+ git_inflate_end(&stream);
munmap(map, mapsize);
return status;
}
@@ -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;
diff --git a/sha1_name.c b/sha1_name.c
index 159c2ab84f..722fc35a6d 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -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);
diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh
index f6a6f839a1..27dc6c55d5 100755
--- a/t/t1501-worktree.sh
+++ b/t/t1501-worktree.sh
@@ -92,6 +92,13 @@ cd sub/dir || exit 1
test_rev_parse 'in repo.git/sub/dir' false true true sub/dir/
cd ../../../.. || exit 1
+test_expect_success 'detecting gitdir when cwd is in a subdir of gitdir' '
+ (expected=$(pwd)/repo.git &&
+ cd repo.git/refs &&
+ unset GIT_DIR &&
+ test "$expected" = "$(git rev-parse --git-dir)")
+'
+
test_expect_success 'repo finds its work tree' '
(cd repo.git &&
: > work/sub/dir/untracked &&
diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh
index beddb4e9f2..e42cbfe6c6 100755
--- a/t/t2300-cd-to-toplevel.sh
+++ b/t/t2300-cd-to-toplevel.sh
@@ -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
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 9d99dc2887..f045898fe3 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -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
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index fc2307eaa3..6d13da30da 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -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/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh
index 2f27a0ba9e..a3f0897a52 100755
--- a/t/t4030-diff-textconv.sh
+++ b/t/t4030-diff-textconv.sh
@@ -104,7 +104,7 @@ cat >expect.typechange <<'EOF'
-1
diff --git a/file b/file
new file mode 120000
-index ad8b3d2..67be421
+index 0000000..67be421
--- /dev/null
+++ b/file
@@ -0,0 +1 @@
diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh
index 55334927ab..0f185caa44 100755
--- a/t/t4114-apply-typechange.sh
+++ b/t/t4114-apply-typechange.sh
@@ -25,6 +25,10 @@ test_expect_success 'setup repository and commits' '
git update-index foo &&
git commit -m "foo back to file" &&
git branch foo-back-to-file &&
+ printf "\0" > foo &&
+ git update-index foo &&
+ git commit -m "foo becomes binary" &&
+ git branch foo-becomes-binary &&
rm -f foo &&
git update-index --remove foo &&
mkdir foo &&
@@ -85,6 +89,20 @@ test_expect_success 'symlink becomes file' '
'
test_debug 'cat patch'
+test_expect_success 'binary file becomes symlink' '
+ git checkout -f foo-becomes-binary &&
+ git diff-tree -p --binary HEAD foo-symlinked-to-bar > patch &&
+ git apply --index < patch
+ '
+test_debug 'cat patch'
+
+test_expect_success 'symlink becomes binary file' '
+ git checkout -f foo-symlinked-to-bar &&
+ git diff-tree -p --binary HEAD foo-becomes-binary > patch &&
+ git apply --index < patch
+ '
+test_debug 'cat patch'
+
test_expect_success 'symlink becomes directory' '
git checkout -f foo-symlinked-to-bar &&
diff --git a/t/t5519-push-alternates.sh b/t/t5519-push-alternates.sh
new file mode 100755
index 0000000000..6dfc55ad61
--- /dev/null
+++ b/t/t5519-push-alternates.sh
@@ -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
diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh
index 8dfaaa456e..fe0fda282c 100755
--- a/t/t5701-clone-local.sh
+++ b/t/t5701-clone-local.sh
@@ -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
index 0000000000..991ab4a65b
--- /dev/null
+++ b/t/t6014-rev-list-all.sh
@@ -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
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index ef2e78f9df..8fb3a56838 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -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 \
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index 18fe6f2d57..c4938544d4 100755
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
@@ -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/dump-cache-tree.c b/test-dump-cache-tree.c
index 1f73f1ea7d..1f73f1ea7d 100644
--- a/dump-cache-tree.c
+++ b/test-dump-cache-tree.c
diff --git a/test-path-utils.c b/test-path-utils.c
index a0bcb0e210..2c0f5a37e8 100644
--- a/test-path-utils.c
+++ b/test-path-utils.c
@@ -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);
diff --git a/unpack-trees.c b/unpack-trees.c
index 15c9ef592b..3a4e181af4 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -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;
diff --git a/wrapper.c b/wrapper.c
index 93562f03ee..c85ca52ec6 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -196,3 +196,63 @@ int xmkstemp(char *template)
die("Unable to create temporary file: %s", strerror(errno));
return fd;
}
+
+/*
+ * zlib wrappers to make sure we don't silently miss errors
+ * at init time.
+ */
+void git_inflate_init(z_streamp strm)
+{
+ const char *err;
+
+ switch (inflateInit(strm)) {
+ case Z_OK:
+ return;
+
+ case Z_MEM_ERROR:
+ err = "out of memory";
+ break;
+ case Z_VERSION_ERROR:
+ err = "wrong version";
+ break;
+ default:
+ err = "error";
+ }
+ die("inflateInit: %s (%s)", err, strm->msg ? strm->msg : "no message");
+}
+
+void git_inflate_end(z_streamp strm)
+{
+ if (inflateEnd(strm) != Z_OK)
+ error("inflateEnd: %s", strm->msg ? strm->msg : "failed");
+}
+
+int git_inflate(z_streamp strm, int flush)
+{
+ int ret = inflate(strm, flush);
+ const char *err;
+
+ switch (ret) {
+ /* Out of memory is fatal. */
+ case Z_MEM_ERROR:
+ die("inflate: out of memory");
+
+ /* Data corruption errors: we may want to recover from them (fsck) */
+ case Z_NEED_DICT:
+ err = "needs dictionary"; break;
+ case Z_DATA_ERROR:
+ err = "data stream error"; break;
+ case Z_STREAM_ERROR:
+ err = "stream consistency error"; break;
+ default:
+ err = "unknown error"; break;
+
+ /* Z_BUF_ERROR: normal, needs more space in the output buffer */
+ case Z_BUF_ERROR:
+ case Z_OK:
+ case Z_STREAM_END:
+ return ret;
+ }
+ error("inflate: %s (%s)", err, strm->msg ? strm->msg : "no message");
+ return ret;
+}
diff --git a/xdiff/xutils.c b/xdiff/xutils.c
index d7974d1a3e..04ad468702 100644
--- a/xdiff/xutils.c
+++ b/xdiff/xutils.c
@@ -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);