--- /dev/null
+Git v2.7.3 Release Notes
+========================
+
+Fixes since v2.7.2
+------------------
+
+ * Traditionally, the tests that try commands that work on the
+ contents in the working tree were named with "worktree" in their
+ filenames, but with the recent addition of "git worktree"
+ subcommand, whose tests are also named similarly, it has become
+ harder to tell them apart. The traditional tests have been renamed
+ to use "work-tree" instead in an attempt to differentiate them.
+
+ * Many codepaths forget to check return value from git_config_set();
+ the function is made to die() to make sure we do not proceed when
+ setting a configuration variable failed.
+
+ * Handling of errors while writing into our internal asynchronous
+ process has been made more robust, which reduces flakiness in our
+ tests.
+
+ * "git show 'HEAD:Foo[BAR]Baz'" did not interpret the argument as a
+ rev, i.e. the object named by the the pathname with wildcard
+ characters in a tree object.
+
+ * "git rev-parse --git-common-dir" used in the worktree feature
+ misbehaved when run from a subdirectory.
+
+ * The "v(iew)" subcommand of the interactive "git am -i" command was
+ broken in 2.6.0 timeframe when the command was rewritten in C.
+
+ * "git merge-tree" used to mishandle "both sides added" conflict with
+ its own "create a fake ancestor file that has the common parts of
+ what both sides have added and do a 3-way merge" logic; this has
+ been updated to use the usual "3-way merge with an empty blob as
+ the fake common ancestor file" approach used in the rest of the
+ system.
+
+ * The memory ownership rule of fill_textconv() API, which was a bit
+ tricky, has been documented a bit better.
+
+ * The documentation did not clearly state that the 'simple' mode is
+ now the default for "git push" when push.default configuration is
+ not set.
+
+ * Recent versions of GNU grep are pickier when their input contains
+ arbitrary binary data, which some of our tests uses. Rewrite the
+ tests to sidestep the problem.
+
+ * A helper function "git submodule" uses since v2.7.0 to list the
+ modules that match the pathspec argument given to its subcommands
+ (e.g. "submodule add <repo> <path>") has been fixed.
+
+ * "git config section.var value" to set a value in per-repository
+ configuration file failed when it was run outside any repository,
+ but didn't say the reason correctly.
+
+ * The code to read the pack data using the offsets stored in the pack
+ idx file has been made more carefully check the validity of the
+ data in the idx.
+
+Also includes documentation and test updates.
* There is a new DEVELOPER knob that enables many compiler warning
options in the Makefile.
+ * The way the test scripts configure the Apache web server has been
+ updated to work also for Apache 2.4 running on RedHat derived
+ distros.
+
+ * Out of maintenance gcc on OSX 10.6 fails to compile the code in
+ 'master'; work it around by using clang by default on the platform.
+
Also contains various documentation updates and code clean-ups.
listing and sparse checkout selection areas in 2.7.0; the change
that is responsible for the regression has been reverted.
+ * Another try to improve the ignore mechanism that lets you say "this
+ is excluded" and then later say "oh, no, this part (that is a
+ subset of the previous part) is not excluded". This has still a
+ known limitation, though.
+
* Some codepaths used fopen(3) when opening a fixed path in $GIT_DIR
(e.g. COMMIT_EDITMSG) that is meant to be left after the command is
done. This however did not work well if the repository is set to
misbehaved when run from a subdirectory.
(merge 17f1365 nd/git-common-dir-fix later to maint).
- * Another try to add support to the ignore mechanism that lets you
- say "this is excluded" and then later say "oh, no, this part (that
- is a subset of the previous part) is not excluded".
-
* "git worktree add -B <branchname>" did not work.
* The "v(iew)" subcommand of the interactive "git am -i" command was
but didn't say the reason correctly.
(merge 638fa62 js/config-set-in-non-repository later to maint).
+ * The code to read the pack data using the offsets stored in the pack
+ idx file has been made more carefully check the validity of the
+ data in the idx.
+ (merge 7465feb jk/pack-idx-corruption-safety later to maint).
+
* Other minor clean-ups and documentation updates
(merge f459823 ak/extract-argv0-last-dir-sep later to maint).
(merge 63ca1c0 ak/git-strip-extension-from-dashed-command later to maint).
<eolinfo> is either "-text", "none", "lf", "crlf", "mixed" or "".
+
"" means the file is not a regular file, it is not in the index or
-not accessable in the working tree.
+not accessible in the working tree.
+
<eolattr> is the attribute that is used when checking out or committing,
it is either "", "-text", "text", "text=auto", "text eol=lf", "text eol=crlf".
NAME
----
-git-rebase - Forward-port local commits to the updated upstream head
+git-rebase - Reapply commits on top of another base tip
SYNOPSIS
--------
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v2.7.2/git.html[documentation for release 2.7.2]
+* link:v2.7.3/git.html[documentation for release 2.7.3]
* release notes for
+ link:RelNotes/2.7.3.txt[2.7.3],
link:RelNotes/2.7.2.txt[2.7.2],
link:RelNotes/2.7.1.txt[2.7.1],
link:RelNotes/2.7.0.txt[2.7].
be in the same .gitignore file.
- The directory part in the re-include rules must be literal (i.e. no
- wildcards)
+ wildcards and has to start with a `/`).
+
+A re-inclusion of a directory makes all files in the directory
+unignored. For example, suppose you have files `.gitignore`,
+`dir/file1`, `dir/file2`, and `dir/file3`, and have the following in
+your `.gitignore`:
+
+----------------
+# .gitignore is not mentioned in .gitignore
+*
+!/dir
+# dir/file1 is not mentioned in .gitignore
+dir/file2
+!dir/file3
+----------------
+
+Then:
+
+ - `.gitignore` gets ignored, because it matches the `*` at the top
+ level;
+
+ - `dir/file1` does not get ignored, because `/dir` marks everything
+ underneath `dir/` directory to be 're-included' unless otherwise
+ specified;
+
+ - `dir/file2` gets ignored, because `dir/file2` matches it.
+
+ - `dir/file3` does not get ignored, because `!dir/file3` matches it.
+ Note that the entry `!dir/file3` is redundant because everything
+ underneath `dir/` is marked to be 're-included' already.
+
+Some earlier versions of Git treated `!/dir` above differently in
+that it did not cause the paths under it unignored (but merely told
+Git that patterns that begin with dir/ should not be ignored), but
+this has been corrected to be consistent with `/dir` that says "the
+directory `dir/` and everything below are ignored."
+
EXAMPLES
--------
instaweb is lighttpd.
See the file gitweb/INSTALL in the Git source tree and
-linkgit:gitweb[1] for instructions on details setting up a permament
+linkgit:gitweb[1] for instructions on details setting up a permanent
installation with a CGI or Perl capable server.
[[how-to-get-a-git-repository-with-minimal-history]]
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.8.0-rc0
+DEF_VER=v2.8.0-rc2
LF='
'
}
} else if (new->path) { /* Switch branches. */
if (create_symref("HEAD", new->path, msg.buf) < 0)
- die("unable to update HEAD");
+ die(_("unable to update HEAD"));
if (!opts->quiet) {
if (old->path && !strcmp(new->path, old->path)) {
if (opts->new_branch_force)
strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
if (!len || (len == 1 && *start == '/'))
- die("No directory name could be guessed.\n"
- "Please specify a directory on the command line");
+ die(_("No directory name could be guessed.\n"
+ "Please specify a directory on the command line"));
if (is_bare)
dir = xstrfmt("%.*s.git", (int)len, start);
if (create_symref(head_ref.buf,
remote_head_points_at->peer_ref->name,
msg) < 0)
- die("unable to update %s", head_ref.buf);
+ die(_("unable to update %s"), head_ref.buf);
strbuf_release(&head_ref);
}
}
if (our && skip_prefix(our->name, "refs/heads/", &head)) {
/* Local default branch link */
if (create_symref("HEAD", our->name, NULL) < 0)
- die("unable to update HEAD");
+ die(_("unable to update HEAD"));
if (!option_bare) {
update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0,
UPDATE_REFS_DIE_ON_ERR);
for (i = 0; i < config->nr; i++) {
if (git_config_parse_parameter(config->items[i].string,
write_one_config, NULL) < 0)
- die("unable to write parameters to config file");
+ die(_("unable to write parameters to config file"));
}
}
if (!(off & 0x80000000))
continue;
off = off & 0x7fffffff;
+ check_pack_index_ptr(p, &idx2[off * 2]);
if (idx2[off * 2])
continue;
/*
extern void clear_delta_base_cache(void);
extern struct packed_git *add_packed_git(const char *path, size_t path_len, int local);
+/*
+ * Make sure that a pointer access into an mmap'd index file is within bounds,
+ * and can provide at least 8 bytes of data.
+ *
+ * Note that this is only necessary for variable-length segments of the file
+ * (like the 64-bit extended offset table), as we compare the size to the
+ * fixed-length parts when we open the file.
+ */
+extern void check_pack_index_ptr(const struct packed_git *p, const void *ptr);
+
/*
* Return the SHA-1 of the nth object within the specified packfile.
* Open the index if it is not already open. The return value points
free(quoted);
}
- wargs = xmalloc_array(st_add(st_mult(2, args.len), 1), sizeof(wchar_t));
+ ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1));
xutftowcs(wargs, args.buf, 2 * args.len + 1);
strbuf_release(&args);
#define pthread_equal(t1, t2) ((t1).tid == (t2).tid)
extern pthread_t pthread_self(void);
-static inline int pthread_exit(void *ret)
+static inline void NORETURN pthread_exit(void *ret)
{
ExitThread((DWORD)(intptr_t)ret);
}
ifeq ($(shell expr "$(uname_R)" : '[15]\.'),2)
NO_STRLCPY = YesPlease
endif
+ ifeq ($(shell test "`expr "$(uname_R)" : '\([0-9][0-9]*\)\.'`" -eq 10 && echo 1),1)
+ CC = clang
+ endif
ifeq ($(shell test "`expr "$(uname_R)" : '\([0-9][0-9]*\)\.'`" -ge 11 && echo 1),1)
HAVE_GETDELIM = YesPlease
endif
static long curl_low_speed_time = -1;
static int curl_ftp_no_epsv;
static const char *curl_http_proxy;
+static const char *curl_no_proxy;
static const char *http_proxy_authmethod;
static struct {
const char *name;
}
curl_easy_setopt(result, CURLOPT_PROXY, proxy_auth.host);
+#if LIBCURL_VERSION_NUM >= 0x071304
+ var_override(&curl_no_proxy, getenv("NO_PROXY"));
+ var_override(&curl_no_proxy, getenv("no_proxy"));
+ curl_easy_setopt(result, CURLOPT_NOPROXY, curl_no_proxy);
+#endif
}
init_curl_proxy_auth(result);
static void body_atom_parser(struct used_atom *atom, const char *arg)
{
if (arg)
- die("%%(body) does not take arguments");
+ die(_("%%(body) does not take arguments"));
atom->u.contents.option = C_BODY_DEP;
}
static void subject_atom_parser(struct used_atom *atom, const char *arg)
{
if (arg)
- die("%%(subject) does not take arguments");
+ die(_("%%(subject) does not take arguments"));
atom->u.contents.option = C_SUB;
}
if (*sp == '*' && sp < ep)
sp++; /* deref */
if (ep <= sp)
- die("malformed field name: %.*s", (int)(ep-atom), atom);
+ die(_("malformed field name: %.*s"), (int)(ep-atom), atom);
/* Do we have the atom already used elsewhere? */
for (i = 0; i < used_atom_cnt; i++) {
}
if (ARRAY_SIZE(valid_atom) <= i)
- die("unknown field name: %.*s", (int)(ep-atom), atom);
+ die(_("unknown field name: %.*s"), (int)(ep-atom), atom);
/* Add it in, including the deref prefix */
at = used_atom_cnt;
int at;
if (!ep)
- return error("malformed format string %s", sp);
+ return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
at = parse_ref_filter_atom(sp + 2, ep);
cp = ep + 1;
const char *start = refname;
if (nr < 1 || *end != '\0')
- die(":strip= requires a positive integer argument");
+ die(_(":strip= requires a positive integer argument"));
while (remaining) {
switch (*start++) {
case '\0':
- die("ref '%s' does not have %ld components to :strip",
+ die(_("ref '%s' does not have %ld components to :strip"),
refname, nr);
case '/':
remaining--;
else if (skip_prefix(formatp, "strip=", &arg))
refname = strip_ref_components(refname, arg);
else
- die("unknown %.*s format %s",
+ die(_("unknown %.*s format %s"),
(int)(formatp - name), name, formatp);
}
need_obj:
buf = get_obj(ref->objectname, &obj, &size, &eaten);
if (!buf)
- die("missing object %s for %s",
+ die(_("missing object %s for %s"),
sha1_to_hex(ref->objectname), ref->refname);
if (!obj)
- die("parse_object_buffer failed on %s for %s",
+ die(_("parse_object_buffer failed on %s for %s"),
sha1_to_hex(ref->objectname), ref->refname);
grab_values(ref->value, 0, obj, buf, size);
*/
buf = get_obj(tagged, &obj, &size, &eaten);
if (!buf)
- die("missing object %s for %s",
+ die(_("missing object %s for %s"),
sha1_to_hex(tagged), ref->refname);
if (!obj)
- die("parse_object_buffer failed on %s for %s",
+ die(_("parse_object_buffer failed on %s for %s"),
sha1_to_hex(tagged), ref->refname);
grab_values(ref->value, 1, obj, buf, size);
if (!eaten)
unsigned int kind;
if (flag & REF_BAD_NAME) {
- warning("ignoring ref with broken name %s", refname);
+ warning(_("ignoring ref with broken name %s"), refname);
return 0;
}
if (flag & REF_ISBROKEN) {
- warning("ignoring broken ref %s", refname);
+ warning(_("ignoring broken ref %s"), refname);
return 0;
}
struct strbuf buffered_output; /* of finished children */
};
-static int default_start_failure(struct child_process *cp,
- struct strbuf *err,
+static int default_start_failure(struct strbuf *err,
void *pp_cb,
void *pp_task_cb)
{
- int i;
-
- strbuf_addstr(err, "Starting a child failed:");
- for (i = 0; cp->argv[i]; i++)
- strbuf_addf(err, " %s", cp->argv[i]);
-
return 0;
}
static int default_task_finished(int result,
- struct child_process *cp,
struct strbuf *err,
void *pp_cb,
void *pp_task_cb)
{
- int i;
-
- if (!result)
- return 0;
-
- strbuf_addf(err, "A child failed with return code %d:", result);
- for (i = 0; cp->argv[i]; i++)
- strbuf_addf(err, " %s", cp->argv[i]);
-
return 0;
}
pp->children[i].process.no_stdin = 1;
if (start_command(&pp->children[i].process)) {
- code = pp->start_failure(&pp->children[i].process,
- &pp->children[i].err,
+ code = pp->start_failure(&pp->children[i].err,
pp->data,
&pp->children[i].data);
strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
code = finish_command(&pp->children[i].process);
- code = pp->task_finished(code, &pp->children[i].process,
+ code = pp->task_finished(code,
&pp->children[i].err, pp->data,
&pp->children[i].data);
* To send a signal to other child processes for abortion, return
* the negative signal number.
*/
-typedef int (*start_failure_fn)(struct child_process *cp,
- struct strbuf *err,
+typedef int (*start_failure_fn)(struct strbuf *err,
void *pp_cb,
void *pp_task_cb);
* the negative signal number.
*/
typedef int (*task_finished_fn)(int result,
- struct child_process *cp,
struct strbuf *err,
void *pp_cb,
void *pp_task_cb);
* (both stdout and stderr) is routed to stderr in a manner that output
* from different tasks does not interleave.
*
- * If start_failure_fn or task_finished_fn are NULL, default handlers
- * will be used. The default handlers will print an error message on
- * error without issuing an emergency stop.
+ * start_failure_fn and task_finished_fn can be NULL to omit any
+ * special handling.
*/
int run_processes_parallel(int n,
get_next_task_fn,
die("packfile %s cannot be accessed", p->pack_name);
if (offset > (p->pack_size - 20))
die("offset beyond end of packfile (truncated pack?)");
+ if (offset < 0)
+ die(_("offset before end of packfile (broken .idx?)"));
if (!win || !in_window(win, offset)) {
if (win)
}
}
+void check_pack_index_ptr(const struct packed_git *p, const void *vptr)
+{
+ const unsigned char *ptr = vptr;
+ const unsigned char *start = p->index_data;
+ const unsigned char *end = start + p->index_size;
+ if (ptr < start)
+ die(_("offset before start of pack index for %s (corrupt index?)"),
+ p->pack_name);
+ /* No need to check for underflow; .idx files must be at least 8 bytes */
+ if (ptr >= end - 8)
+ die(_("offset beyond end of pack index for %s (truncated index?)"),
+ p->pack_name);
+}
+
off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
{
const unsigned char *index = p->index_data;
if (!(off & 0x80000000))
return off;
index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
+ check_pack_index_ptr(p, index);
return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
ntohl(*((uint32_t *)(index + 4)));
}
return 0;
}
-static int fetch_start_failure(struct child_process *cp,
- struct strbuf *err,
+static int fetch_start_failure(struct strbuf *err,
void *cb, void *task_cb)
{
struct submodule_parallel_fetch *spf = cb;
return 0;
}
-static int fetch_finish(int retvalue, struct child_process *cp,
- struct strbuf *err, void *cb, void *task_cb)
+static int fetch_finish(int retvalue, struct strbuf *err,
+ void *cb, void *task_cb)
{
struct submodule_parallel_fetch *spf = cb;
<IfModule !mod_mpm_prefork.c>
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
</IfModule>
+<IfModule !mod_unixd.c>
+ LoadModule unixd_module modules/mod_unixd.so
+</IfModule>
</IfVersion>
PassEnv GIT_VALGRIND
'
test_expect_success 'No extra GIT_* on alias scripts' '
- (
- env | sed -ne "/^GIT_/s/=.*//p" &&
- echo GIT_PREFIX && # setup.c
- echo GIT_TEXTDOMAINDIR # wrapper-for-bin.sh
- ) | sort | uniq >expected &&
- cat <<-\EOF >script &&
- #!/bin/sh
- env | sed -ne "/^GIT_/s/=.*//p" | sort >actual
- exit 0
+ write_script script <<-\EOF &&
+ env |
+ sed -n \
+ -e "/^GIT_PREFIX=/d" \
+ -e "/^GIT_TEXTDOMAINDIR=/d" \
+ -e "/^GIT_/s/=.*//p" |
+ sort
EOF
- chmod 755 script &&
+ ./script >expected &&
git config alias.script \!./script &&
- ( mkdir sub && cd sub && git script ) &&
+ ( mkdir sub && cd sub && git script >../actual ) &&
test_cmp expected actual
'
--- /dev/null
+#!/bin/sh
+
+test_description='bounds-checking of access to mmapped on-disk file formats'
+. ./test-lib.sh
+
+clear_base () {
+ test_when_finished 'restore_base' &&
+ rm -f $base
+}
+
+restore_base () {
+ cp base-backup/* .git/objects/pack/
+}
+
+do_pack () {
+ pack_objects=$1; shift
+ sha1=$(
+ for i in $pack_objects
+ do
+ echo $i
+ done | git pack-objects "$@" .git/objects/pack/pack
+ ) &&
+ pack=.git/objects/pack/pack-$sha1.pack &&
+ idx=.git/objects/pack/pack-$sha1.idx &&
+ chmod +w $pack $idx &&
+ test_when_finished 'rm -f "$pack" "$idx"'
+}
+
+munge () {
+ printf "$3" | dd of="$1" bs=1 conv=notrunc seek=$2
+}
+
+# Offset in a v2 .idx to its initial and extended offset tables. For an index
+# with "nr" objects, this is:
+#
+# magic(4) + version(4) + fan-out(4*256) + sha1s(20*nr) + crc(4*nr),
+#
+# for the initial, and another ofs(4*nr) past that for the extended.
+#
+ofs_table () {
+ echo $((4 + 4 + 4*256 + 20*$1 + 4*$1))
+}
+extended_table () {
+ echo $(($(ofs_table "$1") + 4*$1))
+}
+
+test_expect_success 'set up base packfile and variables' '
+ # the hash of this content starts with ff, which
+ # makes some later computations much simpler
+ echo 74 >file &&
+ git add file &&
+ git commit -m base &&
+ git repack -ad &&
+ base=$(echo .git/objects/pack/*) &&
+ chmod +w $base &&
+ mkdir base-backup &&
+ cp $base base-backup/ &&
+ object=$(git rev-parse HEAD:file)
+'
+
+test_expect_success 'pack/index object count mismatch' '
+ do_pack $object &&
+ munge $pack 8 "\377\0\0\0" &&
+ clear_base &&
+
+ # We enumerate the objects from the completely-fine
+ # .idx, but notice later that the .pack is bogus
+ # and fail to show any data.
+ echo "$object missing" >expect &&
+ git cat-file --batch-all-objects --batch-check >actual &&
+ test_cmp expect actual &&
+
+ # ...and here fail to load the object (without segfaulting),
+ # but fallback to a good copy if available.
+ test_must_fail git cat-file blob $object &&
+ restore_base &&
+ git cat-file blob $object >actual &&
+ test_cmp file actual &&
+
+ # ...and make sure that index-pack --verify, which has its
+ # own reading routines, does not segfault.
+ test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'matched bogus object count' '
+ do_pack $object &&
+ munge $pack 8 "\377\0\0\0" &&
+ munge $idx $((255 * 4)) "\377\0\0\0" &&
+ clear_base &&
+
+ # Unlike above, we should notice early that the .idx is totally
+ # bogus, and not even enumerate its contents.
+ >expect &&
+ git cat-file --batch-all-objects --batch-check >actual &&
+ test_cmp expect actual &&
+
+ # But as before, we can do the same object-access checks.
+ test_must_fail git cat-file blob $object &&
+ restore_base &&
+ git cat-file blob $object >actual &&
+ test_cmp file actual &&
+
+ test_must_fail git index-pack --verify $pack
+'
+
+# Note that we cannot check the fallback case for these
+# further .idx tests, as we notice the problem in functions
+# whose interface doesn't allow an error return (like use_pack()),
+# and thus we just die().
+#
+# There's also no point in doing enumeration tests, as
+# we are munging offsets here, which are about looking up
+# specific objects.
+
+test_expect_success 'bogus object offset (v1)' '
+ do_pack $object --index-version=1 &&
+ munge $idx $((4 * 256)) "\377\0\0\0" &&
+ clear_base &&
+ test_must_fail git cat-file blob $object &&
+ test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'bogus object offset (v2, no msb)' '
+ do_pack $object --index-version=2 &&
+ munge $idx $(ofs_table 1) "\0\377\0\0" &&
+ clear_base &&
+ test_must_fail git cat-file blob $object &&
+ test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'bogus offset into v2 extended table' '
+ do_pack $object --index-version=2 &&
+ munge $idx $(ofs_table 1) "\377\0\0\0" &&
+ clear_base &&
+ test_must_fail git cat-file blob $object &&
+ test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'bogus offset inside v2 extended table' '
+ # We need two objects here, so we can plausibly require
+ # an extended table (if the first object were larger than 2^31).
+ do_pack "$object $(git rev-parse HEAD)" --index-version=2 &&
+
+ # We have to make extra room for the table, so we cannot
+ # just munge in place as usual.
+ {
+ dd if=$idx bs=1 count=$(($(ofs_table 2) + 4)) &&
+ printf "\200\0\0\0" &&
+ printf "\377\0\0\0\0\0\0\0" &&
+ dd if=$idx bs=1 skip=$(extended_table 2)
+ } >tmp &&
+ mv tmp "$idx" &&
+ clear_base &&
+ test_must_fail git cat-file blob $object &&
+ test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'bogus OFS_DELTA in packfile' '
+ # Generate a pack with a delta in it.
+ base=$(test-genrandom foo 3000 | git hash-object --stdin -w) &&
+ delta=$(test-genrandom foo 2000 | git hash-object --stdin -w) &&
+ do_pack "$base $delta" --delta-base-offset &&
+ rm -f .git/objects/??/* &&
+
+ # Double check that we have the delta we expect.
+ echo $base >expect &&
+ echo $delta | git cat-file --batch-check="%(deltabase)" >actual &&
+ test_cmp expect actual &&
+
+ # Now corrupt it. We assume the varint size for the delta is small
+ # enough to fit in the first byte (which it should be, since it
+ # is a pure deletion from the base), and that original ofs_delta
+ # takes 2 bytes (which it should, as it should be ~3000).
+ ofs=$(git show-index <$idx | grep $delta | cut -d" " -f1) &&
+ munge $pack $(($ofs + 1)) "\177\377" &&
+ test_must_fail git cat-file blob $delta >/dev/null
+'
+
+test_done
EOF
git clone "file://$D" auto-gc &&
test_commit test2 &&
- cd auto-gc &&
- git config gc.autoPackLimit 1 &&
- GIT_ASK_YESNO="$D/askyesno" git fetch >fetch.out 2>&1 &&
- ! grep "Should I try again" fetch.out
+ (
+ cd auto-gc &&
+ git config gc.autoPackLimit 1 &&
+ GIT_ASK_YESNO="$D/askyesno" git fetch >fetch.out 2>&1 &&
+ ! grep "Should I try again" fetch.out
+ )
'
test_done
use Cwd;
use File::Basename;
+sub adjust_dirsep {
+ my $path = shift;
+ $path =~ s{\\}{/}g;
+ return $path;
+}
+
BEGIN { use_ok('Git') }
# set up
is($r->config_int("test.nonexistent"), undef, "config_int: nonexistent");
ok($r->config_bool("test.booltrue"), "config_bool: true");
ok(!$r->config_bool("test.boolfalse"), "config_bool: false");
-is($r->config_path("test.path") =~ s/\\/\//gr, $r->config("test.pathexpanded"),
+is(adjust_dirsep($r->config_path("test.path")), $r->config("test.pathexpanded"),
"config_path: ~/foo expansion");
is_deeply([$r->config_path("test.pathmulti")], ["foo", "bar"],
"config_path: multiple values");
}
static int task_finished(int result,
- struct child_process *cp,
struct strbuf *err,
void *pp_cb,
void *pp_task_cb)
cp.use_shell = 1;
if (capture_command(&cp, &buf, 1024)) {
- error("running trailer command '%s' failed", cmd.buf);
+ error(_("running trailer command '%s' failed"), cmd.buf);
strbuf_release(&buf);
result = xstrdup("");
} else {