summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deps/regex/regcomp.c13
-rw-r--r--deps/regex/regex_internal.h13
-rw-r--r--deps/regex/regexec.c10
-rw-r--r--include/git2/errors.h1
-rw-r--r--include/git2/remote.h12
-rw-r--r--src/buf_text.c5
-rw-r--r--src/buf_text.h8
-rw-r--r--src/checkout.c24
-rw-r--r--src/diff_output.c45
-rw-r--r--src/diff_output.h1
-rw-r--r--src/indexer.c2
-rw-r--r--src/offmap.h65
-rw-r--r--src/pack.c182
-rw-r--r--src/pack.h23
-rw-r--r--src/refspec.c3
-rw-r--r--src/remote.c13
-rw-r--r--src/transports/winhttp.c14
-rw-r--r--tests-clar/checkout/binaryunicode.c68
-rw-r--r--tests-clar/checkout/tree.c126
-rw-r--r--tests-clar/clar/fs.h4
-rw-r--r--tests-clar/clone/nonetwork.c2
-rw-r--r--tests-clar/core/buffer.c23
-rw-r--r--tests-clar/diff/patch.c110
-rw-r--r--tests-clar/diff/workdir.c1
-rw-r--r--tests-clar/network/cred.c2
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/HEAD1
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/config6
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/description1
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/indexbin0 -> 104 bytes
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/info/exclude6
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/info/refs3
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/objects/info/packs2
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.idxbin0 -> 1380 bytes
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.packbin0 -> 20879 bytes
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/refs/heads/branch11
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/refs/heads/branch21
-rw-r--r--tests-clar/resources/binaryunicode/.gitted/refs/heads/master1
-rw-r--r--tests-clar/resources/binaryunicode/file.txt1
-rw-r--r--tests-clar/revwalk/mergebase.c36
39 files changed, 694 insertions, 135 deletions
diff --git a/deps/regex/regcomp.c b/deps/regex/regcomp.c
index 7373fbc22..43bffbc21 100644
--- a/deps/regex/regcomp.c
+++ b/deps/regex/regcomp.c
@@ -542,7 +542,7 @@ weak_alias (__regcomp, regcomp)
from either regcomp or regexec. We don't use PREG here. */
size_t
-regerror(int errcode, const regex_t *__restrict preg,
+regerror(int errcode, UNUSED const regex_t *__restrict preg,
char *__restrict errbuf, size_t errbuf_size)
{
const char *msg;
@@ -1140,7 +1140,7 @@ analyze (regex_t *preg)
dfa->subexp_map[i] = i;
preorder (dfa->str_tree, optimize_subexps, dfa);
for (i = 0; i < preg->re_nsub; i++)
- if (dfa->subexp_map[i] != i)
+ if (dfa->subexp_map[i] != (int)i)
break;
if (i == preg->re_nsub)
{
@@ -1358,7 +1358,7 @@ calc_first (void *extra, bin_tree_t *node)
/* Pass 2: compute NEXT on the tree. Preorder visit. */
static reg_errcode_t
-calc_next (void *extra, bin_tree_t *node)
+calc_next (UNUSED void *extra, bin_tree_t *node)
{
switch (node->token.type)
{
@@ -1609,7 +1609,8 @@ calc_inveclosure (re_dfa_t *dfa)
static reg_errcode_t
calc_eclosure (re_dfa_t *dfa)
{
- int node_idx, incomplete;
+ size_t node_idx;
+ int incomplete;
#ifdef DEBUG
assert (dfa->nodes_len > 0);
#endif
@@ -3308,7 +3309,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
static reg_errcode_t
parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
- re_token_t *token, int token_len, re_dfa_t *dfa,
+ re_token_t *token, int token_len, UNUSED re_dfa_t *dfa,
reg_syntax_t syntax, int accept_hyphen)
{
#ifdef RE_ENABLE_I18N
@@ -3803,7 +3804,7 @@ free_token (re_token_t *node)
and its children. */
static reg_errcode_t
-free_tree (void *extra, bin_tree_t *node)
+free_tree (UNUSED void *extra, bin_tree_t *node)
{
free_token (&node->token);
return REG_NOERROR;
diff --git a/deps/regex/regex_internal.h b/deps/regex/regex_internal.h
index 9eca671dc..53ccebecd 100644
--- a/deps/regex/regex_internal.h
+++ b/deps/regex/regex_internal.h
@@ -27,6 +27,14 @@
#include <stdlib.h>
#include <string.h>
+#ifndef UNUSED
+# ifdef __GNUC__
+# define UNUSED __attribute__((unused))
+# else
+# define UNUSED
+# endif
+#endif
+
#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
# include <langinfo.h>
#endif
@@ -171,8 +179,9 @@ extern const size_t __re_error_msgid_idx[] attribute_hidden;
typedef unsigned long int bitset_word_t;
/* All bits set in a bitset_word_t. */
#define BITSET_WORD_MAX ULONG_MAX
-/* Number of bits in a bitset_word_t. */
-#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT)
+/* Number of bits in a bitset_word_t. Cast to int as most code use it
+ * like that for counting */
+#define BITSET_WORD_BITS ((int)(sizeof (bitset_word_t) * CHAR_BIT))
/* Number of bitset_word_t in a bit_set. */
#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS)
typedef bitset_word_t bitset_t[BITSET_WORDS];
diff --git a/deps/regex/regexec.c b/deps/regex/regexec.c
index 5eb6f1fea..0a1602e5a 100644
--- a/deps/regex/regexec.c
+++ b/deps/regex/regexec.c
@@ -689,7 +689,7 @@ re_search_internal (const regex_t *preg,
if (nmatch > 1 || dfa->has_mb_node)
{
/* Avoid overflow. */
- if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= mctx.input.bufs_len, 0))
+ if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= (size_t)mctx.input.bufs_len, 0))
{
err = REG_ESPACE;
goto free_return;
@@ -920,7 +920,7 @@ re_search_internal (const regex_t *preg,
if (dfa->subexp_map)
for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)
- if (dfa->subexp_map[reg_idx] != reg_idx)
+ if (dfa->subexp_map[reg_idx] != (int)reg_idx)
{
pmatch[reg_idx + 1].rm_so
= pmatch[dfa->subexp_map[reg_idx] + 1].rm_so;
@@ -953,7 +953,7 @@ prune_impossible_nodes (re_match_context_t *mctx)
halt_node = mctx->last_node;
/* Avoid overflow. */
- if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0))
+ if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= (size_t)match_last, 0))
return REG_ESPACE;
sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
@@ -3375,7 +3375,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
/* Avoid arithmetic overflow in size calculation. */
if (BE ((((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX)
/ (3 * sizeof (re_dfastate_t *)))
- < ndests),
+ < (size_t)ndests),
0))
goto out_free;
@@ -4099,7 +4099,7 @@ extend_buffers (re_match_context_t *mctx)
re_string_t *pstr = &mctx->input;
/* Avoid overflow. */
- if (BE (INT_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0))
+ if (BE (INT_MAX / 2 / sizeof (re_dfastate_t *) <= (size_t)pstr->bufs_len, 0))
return REG_ESPACE;
/* Double the lengthes of the buffers. */
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 9e0a1a9e6..917f0699c 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -31,6 +31,7 @@ enum {
GIT_EUNMERGED = -10,
GIT_ENONFASTFORWARD = -11,
GIT_EINVALIDSPEC = -12,
+ GIT_EMERGECONFLICT = -13,
GIT_PASSTHROUGH = -30,
GIT_ITEROVER = -31,
diff --git a/include/git2/remote.h b/include/git2/remote.h
index a0f5d5246..b92a0cd04 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -60,7 +60,7 @@ GIT_EXTERN(int) git_remote_create(
* See `git_tag_create()` for rules about valid names.
*
* @param out pointer to the new remote object
- * @param repo the associated repository. May be NULL for a "dangling" remote.
+ * @param repo the associated repository
* @param fetch the fetch refspec to use for this remote. May be NULL for defaults.
* @param url the remote repository's URL
* @return 0 or an error code
@@ -72,16 +72,6 @@ GIT_EXTERN(int) git_remote_create_inmemory(
const char *url);
/**
- * Sets the owning repository for the remote. This is only allowed on
- * dangling remotes.
- *
- * @param remote the remote to configure
- * @param repo the repository that will own the remote
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_remote_set_repository(git_remote *remote, git_repository *repo);
-
-/**
* Get the information for a particular remote
*
* The name will be checked for validity.
diff --git a/src/buf_text.c b/src/buf_text.c
index a7122dc0c..3a8f442b4 100644
--- a/src/buf_text.c
+++ b/src/buf_text.c
@@ -109,6 +109,11 @@ bool git_buf_text_is_binary(const git_buf *buf)
return ((printable >> 7) < nonprintable);
}
+bool git_buf_text_contains_nul(const git_buf *buf)
+{
+ return (memchr(buf->ptr, '\0', buf->size) != NULL);
+}
+
int git_buf_text_detect_bom(git_bom_t *bom, const git_buf *buf, size_t offset)
{
const char *ptr;
diff --git a/src/buf_text.h b/src/buf_text.h
index ae5e6ca30..458ee33c9 100644
--- a/src/buf_text.h
+++ b/src/buf_text.h
@@ -71,6 +71,14 @@ extern int git_buf_text_common_prefix(git_buf *buf, const git_strarray *strs);
extern bool git_buf_text_is_binary(const git_buf *buf);
/**
+ * Check quickly if buffer contains a NUL byte
+ *
+ * @param buf Buffer to check
+ * @return true if buffer contains a NUL byte
+ */
+extern bool git_buf_text_contains_nul(const git_buf *buf);
+
+/**
* Check if a buffer begins with a UTF BOM
*
* @param bom Set to the type of BOM detected or GIT_BOM_NONE
diff --git a/src/checkout.c b/src/checkout.c
index 4d6f99463..b58ef9f44 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -616,7 +616,7 @@ static int checkout_get_actions(
{
giterr_set(GITERR_CHECKOUT, "%d conflicts prevent checkout",
(int)counts[CHECKOUT_ACTION__CONFLICT]);
- error = -1;
+ error = GIT_EMERGECONFLICT;
goto fail;
}
@@ -687,19 +687,23 @@ static int blob_content_to_file(
git_buf unfiltered = GIT_BUF_INIT, filtered = GIT_BUF_INIT;
git_vector filters = GIT_VECTOR_INIT;
- if (opts->disable_filters ||
+ /* Create a fake git_buf from the blob raw data... */
+ filtered.ptr = blob->odb_object->raw.data;
+ filtered.size = blob->odb_object->raw.len;
+ /* ... and make sure it doesn't get unexpectedly freed */
+ dont_free_filtered = true;
+
+ if (!opts->disable_filters &&
+ !git_buf_text_is_binary(&filtered) &&
(nb_filters = git_filters_load(
&filters,
git_object_owner((git_object *)blob),
path,
- GIT_FILTER_TO_WORKTREE)) == 0) {
-
- /* Create a fake git_buf from the blob raw data... */
- filtered.ptr = blob->odb_object->raw.data;
- filtered.size = blob->odb_object->raw.len;
-
- /* ... and make sure it doesn't get unexpectedly freed */
- dont_free_filtered = true;
+ GIT_FILTER_TO_WORKTREE)) > 0)
+ {
+ /* reset 'filtered' so it can be a filter target */
+ git_buf_init(&filtered, 0);
+ dont_free_filtered = false;
}
if (nb_filters < 0)
diff --git a/src/diff_output.c b/src/diff_output.c
index f98665dfb..933d44ee5 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -142,7 +142,12 @@ static int diff_delta_is_binary_by_content(
GIT_UNUSED(ctxt);
if ((file->flags & KNOWN_BINARY_FLAGS) == 0) {
- if (git_buf_text_is_binary(&search))
+ /* TODO: provide encoding / binary detection callbacks that can
+ * be UTF-8 aware, etc. For now, instead of trying to be smart,
+ * let's just use the simple NUL-byte detection that core git uses.
+ */
+ /* previously was: if (git_buf_text_is_binary(&search)) */
+ if (git_buf_text_contains_nul(&search))
file->flags |= GIT_DIFF_FILE_BINARY;
else
file->flags |= GIT_DIFF_FILE_NOT_BINARY;
@@ -821,6 +826,9 @@ static int diff_patch_hunk_cb(
hunk->line_start = patch->lines_size;
hunk->line_count = 0;
+ patch->oldno = range->old_start;
+ patch->newno = range->new_start;
+
return 0;
}
@@ -879,24 +887,23 @@ static int diff_patch_line_cb(
++line->lines;
}
- if (!last) {
- line->oldno = hunk->range.old_start;
- line->newno = hunk->range.new_start;
- } else {
- switch (last->origin) {
- case GIT_DIFF_LINE_ADDITION:
- line->oldno = last->oldno;
- line->newno = last->newno + last->lines;
- break;
- case GIT_DIFF_LINE_DELETION:
- line->oldno = last->oldno + last->lines;
- line->newno = last->newno;
- break;
- default:
- line->oldno = last->oldno + last->lines;
- line->newno = last->newno + last->lines;
- break;
- }
+ switch (line_origin) {
+ case GIT_DIFF_LINE_ADDITION:
+ line->oldno = -1;
+ line->newno = patch->newno;
+ patch->newno += line->lines;
+ break;
+ case GIT_DIFF_LINE_DELETION:
+ line->oldno = patch->oldno;
+ line->newno = -1;
+ patch->oldno += line->lines;
+ break;
+ default:
+ line->oldno = patch->oldno;
+ line->newno = patch->newno;
+ patch->oldno += line->lines;
+ patch->newno += line->lines;
+ break;
}
hunk->line_count++;
diff --git a/src/diff_output.h b/src/diff_output.h
index 7785bf54b..ae1a491ec 100644
--- a/src/diff_output.h
+++ b/src/diff_output.h
@@ -72,6 +72,7 @@ struct git_diff_patch {
size_t hunks_asize, hunks_size;
diff_patch_line *lines;
size_t lines_asize, lines_size;
+ size_t oldno, newno;
};
/* context for performing diff on a single delta */
diff --git a/src/indexer.c b/src/indexer.c
index 599228f3e..c1d599062 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -273,7 +273,7 @@ static int crc_object(uint32_t *crc_out, git_mwindow_file *mwf, git_off_t start,
if (ptr == NULL)
return -1;
- len = min(left, (size_t)size);
+ len = min(left, (unsigned int)size);
crc = crc32(crc, ptr, len);
size -= len;
start += len;
diff --git a/src/offmap.h b/src/offmap.h
new file mode 100644
index 000000000..cd46fd687
--- /dev/null
+++ b/src/offmap.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 the libgit2 contributors
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_offmap_h__
+#define INCLUDE_offmap_h__
+
+#include "common.h"
+#include "git2/types.h"
+
+#define kmalloc git__malloc
+#define kcalloc git__calloc
+#define krealloc git__realloc
+#define kfree git__free
+#include "khash.h"
+
+__KHASH_TYPE(off, git_off_t, void *);
+typedef khash_t(off) git_offmap;
+
+#define GIT__USE_OFFMAP \
+ __KHASH_IMPL(off, static kh_inline, git_off_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal);
+
+#define git_offmap_alloc() kh_init(off)
+#define git_offmap_free(h) kh_destroy(off, h), h = NULL
+#define git_offmap_clear(h) kh_clear(off, h)
+
+#define git_offmap_num_entries(h) kh_size(h)
+
+#define git_offmap_lookup_index(h, k) kh_get(off, h, k)
+#define git_offmap_valid_index(h, idx) (idx != kh_end(h))
+
+#define git_offmap_exists(h, k) (kh_get(off, h, k) != kh_end(h))
+
+#define git_offmap_value_at(h, idx) kh_val(h, idx)
+#define git_offmap_set_value_at(h, idx, v) kh_val(h, idx) = v
+#define git_offmap_delete_at(h, idx) kh_del(off, h, idx)
+
+#define git_offmap_insert(h, key, val, rval) do { \
+ khiter_t __pos = kh_put(off, h, key, &rval); \
+ if (rval >= 0) { \
+ if (rval == 0) kh_key(h, __pos) = key; \
+ kh_val(h, __pos) = val; \
+ } } while (0)
+
+#define git_offmap_insert2(h, key, val, oldv, rval) do { \
+ khiter_t __pos = kh_put(off, h, key, &rval); \
+ if (rval >= 0) { \
+ if (rval == 0) { \
+ oldv = kh_val(h, __pos); \
+ kh_key(h, __pos) = key; \
+ } else { oldv = NULL; } \
+ kh_val(h, __pos) = val; \
+ } } while (0)
+
+#define git_offmap_delete(h, key) do { \
+ khiter_t __pos = git_offmap_lookup_index(h, key); \
+ if (git_offmap_valid_index(h, __pos)) \
+ git_offmap_delete_at(h, __pos); } while (0)
+
+#define git_offmap_foreach kh_foreach
+#define git_offmap_foreach_value kh_foreach_value
+
+#endif
diff --git a/src/pack.c b/src/pack.c
index d4f8d72e7..dcf9dd178 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -46,6 +46,133 @@ static int packfile_error(const char *message)
return -1;
}
+/********************
+ * Delta base cache
+ ********************/
+
+static git_pack_cache_entry *new_cache_object(git_rawobj *source)
+{
+ git_pack_cache_entry *e = git__calloc(1, sizeof(git_pack_cache_entry));
+ if (!e)
+ return NULL;
+
+ memcpy(&e->raw, source, sizeof(git_rawobj));
+
+ return e;
+}
+
+static void free_cache_object(void *o)
+{
+ git_pack_cache_entry *e = (git_pack_cache_entry *)o;
+
+ if (e != NULL) {
+ assert(e->refcount.val == 0);
+ git__free(e->raw.data);
+ git__free(e);
+ }
+}
+
+static void cache_free(git_pack_cache *cache)
+{
+ khiter_t k;
+
+ if (cache->entries) {
+ for (k = kh_begin(cache->entries); k != kh_end(cache->entries); k++) {
+ if (kh_exist(cache->entries, k))
+ free_cache_object(kh_value(cache->entries, k));
+ }
+
+ git_offmap_free(cache->entries);
+ }
+}
+
+static int cache_init(git_pack_cache *cache)
+{
+ memset(cache, 0, sizeof(git_pack_cache));
+ cache->entries = git_offmap_alloc();
+ GITERR_CHECK_ALLOC(cache->entries);
+ cache->memory_limit = GIT_PACK_CACHE_MEMORY_LIMIT;
+ git_mutex_init(&cache->lock);
+
+ return 0;
+}
+
+static git_pack_cache_entry *cache_get(git_pack_cache *cache, size_t offset)
+{
+ khiter_t k;
+ git_pack_cache_entry *entry = NULL;
+
+ git_mutex_lock(&cache->lock);
+ k = kh_get(off, cache->entries, offset);
+ if (k != kh_end(cache->entries)) { /* found it */
+ entry = kh_value(cache->entries, k);
+ git_atomic_inc(&entry->refcount);
+ entry->last_usage = cache->use_ctr++;
+ }
+ git_mutex_unlock(&cache->lock);
+
+ return entry;
+}
+
+/* Run with the cache lock held */
+static void free_lowest_entry(git_pack_cache *cache)
+{
+ git_pack_cache_entry *lowest = NULL, *entry;
+ khiter_t k, lowest_k;
+
+ for (k = kh_begin(cache->entries); k != kh_end(cache->entries); k++) {
+ if (!kh_exist(cache->entries, k))
+ continue;
+
+ entry = kh_value(cache->entries, k);
+ if (lowest == NULL || entry->last_usage < lowest->last_usage) {
+ lowest_k = k;
+ lowest = entry;
+ }
+ }
+
+ if (!lowest) /* there's nothing to free */
+ return;
+
+ cache->memory_used -= lowest->raw.len;
+ kh_del(off, cache->entries, lowest_k);
+ free_cache_object(lowest);
+}
+
+static int cache_add(git_pack_cache *cache, git_rawobj *base, git_off_t offset)
+{
+ git_pack_cache_entry *entry;
+ int error, exists = 0;
+ khiter_t k;
+
+ if (base->len > GIT_PACK_CACHE_SIZE_LIMIT)
+ return -1;
+
+ entry = new_cache_object(base);
+ if (entry) {
+ git_mutex_lock(&cache->lock);
+ /* Add it to the cache if nobody else has */
+ exists = kh_get(off, cache->entries, offset) != kh_end(cache->entries);
+ if (!exists) {
+ while (cache->memory_used + base->len > cache->memory_limit)
+ free_lowest_entry(cache);
+
+ k = kh_put(off, cache->entries, offset, &error);
+ assert(error != 0);
+ kh_value(cache->entries, k) = entry;
+ cache->memory_used += entry->raw.len;
+ }
+ git_mutex_unlock(&cache->lock);
+ /* Somebody beat us to adding it into the cache */
+ if (exists) {
+ git__free(entry);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
/***********************************************************
*
* PACK INDEX METHODS
@@ -336,9 +463,10 @@ static int packfile_unpack_delta(
git_otype delta_type,
git_off_t obj_offset)
{
- git_off_t base_offset;
+ git_off_t base_offset, base_key;
git_rawobj base, delta;
- int error;
+ git_pack_cache_entry *cached = NULL;
+ int error, found_base = 0;
base_offset = get_delta_base(p, w_curs, curpos, delta_type, obj_offset);
git_mwindow_close(w_curs);
@@ -347,32 +475,49 @@ static int packfile_unpack_delta(
if (base_offset < 0) /* must actually be an error code */
return (int)base_offset;
- error = git_packfile_unpack(&base, p, &base_offset);
+ if (!p->bases.entries && (cache_init(&p->bases) < 0))
+ return -1;
- /*
- * TODO: git.git tries to load the base from other packfiles
- * or loose objects.
- *
- * We'll need to do this in order to support thin packs.
- */
- if (error < 0)
- return error;
+ base_key = base_offset; /* git_packfile_unpack modifies base_offset */
+ if ((cached = cache_get(&p->bases, base_offset)) != NULL) {
+ memcpy(&base, &cached->raw, sizeof(git_rawobj));
+ found_base = 1;
+ }
+
+ if (!cached) { /* have to inflate it */
+ error = git_packfile_unpack(&base, p, &base_offset);
+
+ /*
+ * TODO: git.git tries to load the base from other packfiles
+ * or loose objects.
+ *
+ * We'll need to do this in order to support thin packs.
+ */
+ if (error < 0)
+ return error;
+ }
error = packfile_unpack_compressed(&delta, p, w_curs, curpos, delta_size, delta_type);
git_mwindow_close(w_curs);
+
if (error < 0) {
- git__free(base.data);
+ if (!found_base)
+ git__free(base.data);
return error;
}
obj->type = base.type;
error = git__delta_apply(obj, base.data, base.len, delta.data, delta.len);
+ if (error < 0)
+ goto on_error;
- git__free(base.data);
- git__free(delta.data);
+ if (found_base)
+ git_atomic_dec(&cached->refcount);
+ else if (cache_add(&p->bases, &base, base_key) < 0)
+ git__free(base.data);
- /* TODO: we might want to cache this. eventually */
- //add_delta_base_cache(p, base_offset, base, base_size, *type);
+on_error:
+ git__free(delta.data);
return error; /* error set by git__delta_apply */
}
@@ -476,7 +621,7 @@ ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t
return GIT_EBUFS;
obj->zstream.next_out = buffer;
- obj->zstream.avail_out = len;
+ obj->zstream.avail_out = (unsigned int)len;
obj->zstream.next_in = in;
st = inflate(&obj->zstream, Z_SYNC_FLUSH);
@@ -653,7 +798,8 @@ void packfile_free(struct git_pack_file *p)
{
assert(p);
- /* clear_delta_base_cache(); */
+ cache_free(&p->bases);
+
git_mwindow_free_all(&p->mwf);
git_mwindow_file_deregister(&p->mwf);
diff --git a/src/pack.h b/src/pack.h
index bbfcca591..db57e57d2 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -53,6 +53,27 @@ struct git_pack_idx_header {
uint32_t idx_version;
};
+typedef struct git_pack_cache_entry {
+ size_t last_usage; /* enough? */
+ git_atomic refcount;
+ git_rawobj raw;
+} git_pack_cache_entry;
+
+#include "offmap.h"
+
+GIT__USE_OFFMAP;
+
+#define GIT_PACK_CACHE_MEMORY_LIMIT 16 * 1024 * 1024
+#define GIT_PACK_CACHE_SIZE_LIMIT 1024 * 1024 /* don't bother caching anything over 1MB */
+
+typedef struct {
+ size_t memory_used;
+ size_t memory_limit;
+ size_t use_ctr;
+ git_mutex lock;
+ git_offmap *entries;
+} git_pack_cache;
+
struct git_pack_file {
git_mwindow_file mwf;
git_map index_map;
@@ -68,6 +89,8 @@ struct git_pack_file {
git_vector cache;
git_oid **oids;
+ git_pack_cache bases; /* delta base cache */
+
/* something like ".git/objects/pack/xxxxx.pack" */
char pack_name[GIT_FLEX_ARRAY]; /* more */
};
diff --git a/src/refspec.c b/src/refspec.c
index 5567301f3..bd69f58ae 100644
--- a/src/refspec.c
+++ b/src/refspec.c
@@ -127,6 +127,9 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
void git_refspec__free(git_refspec *refspec)
{
+ if (refspec == NULL)
+ return;
+
git__free(refspec->src);
git__free(refspec->dst);
}
diff --git a/src/remote.c b/src/remote.c
index dbfad13fb..d7e1c5f70 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -195,19 +195,6 @@ int git_remote_create_inmemory(git_remote **out, git_repository *repo, const cha
return 0;
}
-int git_remote_set_repository(git_remote *remote, git_repository *repo)
-{
- assert(repo);
-
- if (remote->repo) {
- giterr_set(GITERR_INVALID, "Remotes can't change repositiories.");
- return GIT_ERROR;
- }
-
- remote->repo = repo;
- return 0;
-}
-
int git_remote_load(git_remote **out, git_repository *repo, const char *name)
{
git_remote *remote;
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index 1a471b7de..808f6afaa 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -298,7 +298,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len)
return -1;
if (!WinHttpWriteData(request,
- git_buf_cstr(&buf), git_buf_len(&buf),
+ git_buf_cstr(&buf), (DWORD)git_buf_len(&buf),
&bytes_written)) {
git_buf_free(&buf);
giterr_set(GITERR_OS, "Failed to write chunk header");
@@ -309,7 +309,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len)
/* Chunk body */
if (!WinHttpWriteData(request,
- buffer, len,
+ buffer, (DWORD)len,
&bytes_written)) {
giterr_set(GITERR_OS, "Failed to write chunk");
return -1;
@@ -494,7 +494,7 @@ replay:
if (!WinHttpReadData(s->request,
(LPVOID)buffer,
- buf_size,
+ (DWORD)buf_size,
&dw_bytes_read))
{
giterr_set(GITERR_OS, "Failed to read data");
@@ -580,7 +580,7 @@ static int put_uuid_string(LPWSTR buffer, DWORD buffer_len_cch)
static int get_temp_file(LPWSTR buffer, DWORD buffer_len_cch)
{
- int len;
+ size_t len;
if (!GetTempPathW(buffer_len_cch, buffer)) {
giterr_set(GITERR_OS, "Failed to get temp path");
@@ -639,7 +639,7 @@ static int winhttp_stream_write_buffered(
}
}
- if (!WriteFile(s->post_body, buffer, len, &bytes_written, NULL)) {
+ if (!WriteFile(s->post_body, buffer, (DWORD)len, &bytes_written, NULL)) {
giterr_set(GITERR_OS, "Failed to write to temporary file");
return -1;
}
@@ -697,7 +697,7 @@ static int winhttp_stream_write_chunked(
}
else {
/* Append as much to the buffer as we can */
- int count = min(CACHED_POST_BODY_BUF_SIZE - s->chunk_buffer_len, len);
+ int count = min(CACHED_POST_BODY_BUF_SIZE - s->chunk_buffer_len, (int)len);
if (!s->chunk_buffer)
s->chunk_buffer = git__malloc(CACHED_POST_BODY_BUF_SIZE);
@@ -717,7 +717,7 @@ static int winhttp_stream_write_chunked(
/* Is there any remaining data from the source? */
if (len > 0) {
memcpy(s->chunk_buffer, buffer, len);
- s->chunk_buffer_len = len;
+ s->chunk_buffer_len = (unsigned int)len;
}
}
}
diff --git a/tests-clar/checkout/binaryunicode.c b/tests-clar/checkout/binaryunicode.c
new file mode 100644
index 000000000..5a781740f
--- /dev/null
+++ b/tests-clar/checkout/binaryunicode.c
@@ -0,0 +1,68 @@
+#include "clar_libgit2.h"
+#include "refs.h"
+#include "repo/repo_helpers.h"
+#include "path.h"
+#include "fileops.h"
+
+static git_repository *g_repo;
+
+void test_checkout_binaryunicode__initialize(void)
+{
+ g_repo = cl_git_sandbox_init("binaryunicode");
+}
+
+void test_checkout_binaryunicode__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+static void execute_test(void)
+{
+ git_oid oid, check;
+ git_commit *commit;
+ git_tree *tree;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
+ cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/branch1"));
+ cl_git_pass(git_commit_lookup(&commit, g_repo, &oid));
+ cl_git_pass(git_commit_tree(&tree, commit));
+
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+
+ cl_git_pass(git_checkout_tree(g_repo, (git_object *)tree, &opts));
+
+ git_tree_free(tree);
+ git_commit_free(commit);
+
+ /* Verify that the lenna.jpg file was checked out correctly */
+ cl_git_pass(git_oid_fromstr(&check, "8ab005d890fe53f65eda14b23672f60d9f4ec5a1"));
+ cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/lenna.jpg", GIT_OBJ_BLOB));
+ cl_assert(git_oid_equal(&oid, &check));
+
+ /* Verify that the text file was checked out correctly */
+ cl_git_pass(git_oid_fromstr(&check, "965b223880dd4249e2c66a0cc0b4cffe1dc40f5a"));
+ cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/utf16_withbom_noeol_crlf.txt", GIT_OBJ_BLOB));
+ cl_assert(git_oid_equal(&oid, &check));
+}
+
+void test_checkout_binaryunicode__noautocrlf(void)
+{
+ git_config *config;
+
+ cl_git_pass(git_repository_config(&config, g_repo));
+ cl_git_pass(git_config_set_bool(config, "core.autocrlf", false));
+ git_config_free(config);
+
+ execute_test();
+}
+
+void test_checkout_binaryunicode__autocrlf(void)
+{
+ git_config *config;
+
+ cl_git_pass(git_repository_config(&config, g_repo));
+ cl_git_pass(git_config_set_bool(config, "core.autocrlf", true));
+ git_config_free(config);
+
+ execute_test();
+}
diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c
index 013c79b57..80e26a15a 100644
--- a/tests-clar/checkout/tree.c
+++ b/tests-clar/checkout/tree.c
@@ -122,26 +122,26 @@ void test_checkout_tree__calls_progress_callback(void)
void test_checkout_tree__doesnt_write_unrequested_files_to_worktree(void)
{
- git_oid master_oid;
- git_oid chomped_oid;
- git_commit* p_master_commit;
- git_commit* p_chomped_commit;
- git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
-
- git_oid_fromstr(&master_oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
- git_oid_fromstr(&chomped_oid, "e90810b8df3e80c413d903f631643c716887138d");
- cl_git_pass(git_commit_lookup(&p_master_commit, g_repo, &master_oid));
- cl_git_pass(git_commit_lookup(&p_chomped_commit, g_repo, &chomped_oid));
-
- /* GIT_CHECKOUT_NONE should not add any file to the working tree from the
- * index as it is supposed to be a dry run.
- */
- opts.checkout_strategy = GIT_CHECKOUT_NONE;
- git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts);
- cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt"));
-
- git_commit_free(p_master_commit);
- git_commit_free(p_chomped_commit);
+ git_oid master_oid;
+ git_oid chomped_oid;
+ git_commit* p_master_commit;
+ git_commit* p_chomped_commit;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
+ git_oid_fromstr(&master_oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
+ git_oid_fromstr(&chomped_oid, "e90810b8df3e80c413d903f631643c716887138d");
+ cl_git_pass(git_commit_lookup(&p_master_commit, g_repo, &master_oid));
+ cl_git_pass(git_commit_lookup(&p_chomped_commit, g_repo, &chomped_oid));
+
+ /* GIT_CHECKOUT_NONE should not add any file to the working tree from the
+ * index as it is supposed to be a dry run.
+ */
+ opts.checkout_strategy = GIT_CHECKOUT_NONE;
+ git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts);
+ cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt"));
+
+ git_commit_free(p_master_commit);
+ git_commit_free(p_chomped_commit);
}
void test_checkout_tree__can_switch_branches(void)
@@ -356,3 +356,89 @@ void test_checkout_tree__can_disable_pattern_match(void)
cl_assert(git_path_isfile("testrepo/branch_file.txt"));
}
+
+void assert_conflict(
+ const char *entry_path,
+ const char *new_content,
+ const char *parent_sha,
+ const char *commit_sha)
+{
+ git_index *index;
+ git_object *hack_tree;
+ git_reference *branch, *head;
+ git_buf file_path = GIT_BUF_INIT;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ /* Create a branch pointing at the parent */
+ cl_git_pass(git_revparse_single(&g_object, g_repo, parent_sha));
+ cl_git_pass(git_branch_create(&branch, g_repo,
+ "potential_conflict", (git_commit *)g_object, 0));
+
+ /* Make HEAD point to this branch */
+ cl_git_pass(git_reference_symbolic_create(
+ &head, g_repo, "HEAD", git_reference_name(branch), 1));
+
+ /* Checkout the parent */
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+ cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
+
+ /* Hack-ishy workaound to ensure *all* the index entries
+ * match the content of the tree
+ */
+ cl_git_pass(git_object_peel(&hack_tree, g_object, GIT_OBJ_TREE));
+ cl_git_pass(git_index_read_tree(index, (git_tree *)hack_tree));
+ git_object_free(hack_tree);
+ git_object_free(g_object);
+ g_object = NULL;
+
+ /* Create a conflicting file */
+ cl_git_pass(git_buf_joinpath(&file_path, "./testrepo", entry_path));
+ cl_git_mkfile(git_buf_cstr(&file_path), new_content);
+ git_buf_free(&file_path);
+
+ /* Trying to checkout the original commit */
+ cl_git_pass(git_revparse_single(&g_object, g_repo, commit_sha));
+
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+ cl_assert_equal_i(
+ GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts));
+
+ /* Stage the conflicting change */
+ cl_git_pass(git_index_add_from_workdir(index, entry_path));
+ cl_git_pass(git_index_write(index));
+
+ cl_assert_equal_i(
+ GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts));
+}
+
+void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT(void)
+{
+ /*
+ * 099faba adds a symlink named 'link_to_new.txt'
+ * a65fedf is the parent of 099faba
+ */
+
+ assert_conflict("link_to_new.txt", "old.txt", "a65fedf", "099faba");
+}
+
+void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT_2(void)
+{
+ /*
+ * cf80f8d adds a directory named 'a/'
+ * a4a7dce is the parent of cf80f8d
+ */
+
+ assert_conflict("a", "hello\n", "a4a7dce", "cf80f8d");
+}
+
+void test_checkout_tree__checking_out_a_conflicting_content_change_returns_EMERGECONFLICT(void)
+{
+ /*
+ * c47800c adds a symlink named 'branch_file.txt'
+ * 5b5b025 is the parent of 763d71a
+ */
+
+ assert_conflict("branch_file.txt", "hello\n", "5b5b025", "c47800c");
+}
diff --git a/tests-clar/clar/fs.h b/tests-clar/clar/fs.h
index 1cdc1ce2f..b7a1ff9d2 100644
--- a/tests-clar/clar/fs.h
+++ b/tests-clar/clar/fs.h
@@ -46,7 +46,7 @@ fs_rmdir_helper(WCHAR *_wsource)
WCHAR buffer[MAX_PATH];
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
- int buffer_prefix_len;
+ size_t buffer_prefix_len;
/* Set up the buffer and capture the length */
wcscpy_s(buffer, MAX_PATH, _wsource);
@@ -153,7 +153,7 @@ fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest)
WCHAR buf_source[MAX_PATH], buf_dest[MAX_PATH];
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
- int buf_source_prefix_len, buf_dest_prefix_len;
+ size_t buf_source_prefix_len, buf_dest_prefix_len;
wcscpy_s(buf_source, MAX_PATH, _wsource);
wcscat_s(buf_source, MAX_PATH, L"\\");
diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c
index 50b0bc2d9..953f79659 100644
--- a/tests-clar/clone/nonetwork.c
+++ b/tests-clar/clone/nonetwork.c
@@ -140,7 +140,7 @@ void test_clone_nonetwork__custom_autotag(void)
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
cl_git_pass(git_tag_list(&tags, g_repo));
- cl_assert_equal_i(0, tags.count);
+ cl_assert_equal_sz(0, tags.count);
git_strarray_free(&tags);
}
diff --git a/tests-clar/core/buffer.c b/tests-clar/core/buffer.c
index 40fc4c571..5d9b7850c 100644
--- a/tests-clar/core/buffer.c
+++ b/tests-clar/core/buffer.c
@@ -704,3 +704,26 @@ void test_core_buffer__base64(void)
git_buf_free(&buf);
}
+
+void test_core_buffer__classify_with_utf8(void)
+{
+ char *data0 = "Simple text\n";
+ size_t data0len = 12;
+ char *data1 = "Is that UTF-8 data I see…\nYep!\n";
+ size_t data1len = 31;
+ char *data2 = "Internal NUL!!!\000\n\nI see you!\n";
+ size_t data2len = 29;
+ git_buf b;
+
+ b.ptr = data0; b.size = b.asize = data0len;
+ cl_assert(!git_buf_text_is_binary(&b));
+ cl_assert(!git_buf_text_contains_nul(&b));
+
+ b.ptr = data1; b.size = b.asize = data1len;
+ cl_assert(git_buf_text_is_binary(&b));
+ cl_assert(!git_buf_text_contains_nul(&b));
+
+ b.ptr = data2; b.size = b.asize = data2len;
+ cl_assert(git_buf_text_is_binary(&b));
+ cl_assert(git_buf_text_contains_nul(&b));
+}
diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c
index 6a3c5bc39..4e85ab883 100644
--- a/tests-clar/diff/patch.c
+++ b/tests-clar/diff/patch.c
@@ -1,11 +1,12 @@
#include "clar_libgit2.h"
#include "diff_helpers.h"
+#include "repository.h"
+#include "buf_text.h"
static git_repository *g_repo = NULL;
void test_diff_patch__initialize(void)
{
- g_repo = cl_git_sandbox_init("status");
}
void test_diff_patch__cleanup(void)
@@ -85,6 +86,8 @@ void test_diff_patch__can_properly_display_the_removal_of_a_file(void)
git_tree *one, *another;
git_diff_list *diff;
+ g_repo = cl_git_sandbox_init("status");
+
one = resolve_commit_oid_to_tree(g_repo, one_sha);
another = resolve_commit_oid_to_tree(g_repo, another_sha);
@@ -108,6 +111,8 @@ void test_diff_patch__to_string(void)
char *text;
const char *expected = "diff --git a/subdir.txt b/subdir.txt\ndeleted file mode 100644\nindex e8ee89e..0000000\n--- a/subdir.txt\n+++ /dev/null\n@@ -1,2 +0,0 @@\n-Is it a bird?\n-Is it a plane?\n";
+ g_repo = cl_git_sandbox_init("status");
+
one = resolve_commit_oid_to_tree(g_repo, one_sha);
another = resolve_commit_oid_to_tree(g_repo, another_sha);
@@ -127,3 +132,106 @@ void test_diff_patch__to_string(void)
git_tree_free(another);
git_tree_free(one);
}
+
+void test_diff_patch__hunks_have_correct_line_numbers(void)
+{
+ git_tree *head;
+ git_diff_list *diff;
+ git_diff_patch *patch;
+ const git_diff_delta *delta;
+ const git_diff_range *range;
+ const char *hdr, *text;
+ size_t hdrlen, hunklen, textlen;
+ char origin;
+ int oldno, newno;
+ const char *new_content = "The Song of Seven Cities\n========================\n\nI WAS Lord of Cities very sumptuously builded.\nSeven roaring Cities paid me tribute from afar.\nIvory their outposts were—the guardrooms of them gilded,\nAnd garrisoned with Amazons invincible in war.\n\nThis is some new text;\nNot as good as the old text;\nBut here it is.\n\nSo they warred and trafficked only yesterday, my Cities.\nTo-day there is no mark or mound of where my Cities stood.\nFor the River rose at midnight and it washed away my Cities.\nThey are evened with Atlantis and the towns before the Flood.\n\nRain on rain-gorged channels raised the water-levels round them,\nFreshet backed on freshet swelled and swept their world from sight,\nTill the emboldened floods linked arms and, flashing forward, drowned them—\nDrowned my Seven Cities and their peoples in one night!\n\nLow among the alders lie their derelict foundations,\nThe beams wherein they trusted and the plinths whereon they built—\nMy rulers and their treasure and their unborn populations,\nDead, destroyed, aborted, and defiled with mud and silt!\n\nAnother replacement;\nBreaking up the poem;\nGenerating some hunks.\n\nTo the sound of trumpets shall their seed restore my Cities\nWealthy and well-weaponed, that once more may I behold\nAll the world go softly when it walks before my Cities,\nAnd the horses and the chariots fleeing from them as of old!\n\n -- Rudyard Kipling\n";
+
+ g_repo = cl_git_sandbox_init("renames");
+
+ cl_git_rewritefile("renames/songofseven.txt", new_content);
+
+ cl_git_pass(git_repository_head_tree(&head, g_repo));
+
+ cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, head, NULL));
+
+ cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
+
+ cl_git_pass(git_diff_get_patch(&patch, &delta, diff, 0));
+
+ cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status);
+ cl_assert_equal_i(2, (int)git_diff_patch_num_hunks(patch));
+
+ /* check hunk 0 */
+
+ cl_git_pass(
+ git_diff_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 0));
+
+ cl_assert_equal_i(18, (int)hunklen);
+
+ cl_assert_equal_i(6, (int)range->old_start);
+ cl_assert_equal_i(15, (int)range->old_lines);
+ cl_assert_equal_i(6, (int)range->new_start);
+ cl_assert_equal_i(9, (int)range->new_lines);
+
+ cl_assert_equal_i(18, (int)git_diff_patch_num_lines_in_hunk(patch, 0));
+
+ cl_git_pass(git_diff_patch_get_line_in_hunk(
+ &origin, &text, &textlen, &oldno, &newno, patch, 0, 0));
+ cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin);
+ cl_assert(strncmp("Ivory their outposts were—the guardrooms of them gilded,\n", text, textlen) == 0);
+ cl_assert_equal_i(6, oldno);
+ cl_assert_equal_i(6, newno);
+
+ cl_git_pass(git_diff_patch_get_line_in_hunk(
+ &origin, &text, &textlen, &oldno, &newno, patch, 0, 3));
+ cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin);
+ cl_assert(strncmp("All the world went softly when it walked before my Cities—\n", text, textlen) == 0);
+ cl_assert_equal_i(9, oldno);
+ cl_assert_equal_i(-1, newno);
+
+ cl_git_pass(git_diff_patch_get_line_in_hunk(
+ &origin, &text, &textlen, &oldno, &newno, patch, 0, 12));
+ cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin);
+ cl_assert(strncmp("This is some new text;\n", text, textlen) == 0);
+ cl_assert_equal_i(-1, oldno);
+ cl_assert_equal_i(9, newno);
+
+ /* check hunk 1 */
+
+ cl_git_pass(
+ git_diff_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 1));
+
+ cl_assert_equal_i(18, (int)hunklen);
+
+ cl_assert_equal_i(31, (int)range->old_start);
+ cl_assert_equal_i(15, (int)range->old_lines);
+ cl_assert_equal_i(25, (int)range->new_start);
+ cl_assert_equal_i(9, (int)range->new_lines);
+
+ cl_assert_equal_i(18, (int)git_diff_patch_num_lines_in_hunk(patch, 1));
+
+ cl_git_pass(git_diff_patch_get_line_in_hunk(
+ &origin, &text, &textlen, &oldno, &newno, patch, 1, 0));
+ cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin);
+ cl_assert(strncmp("My rulers and their treasure and their unborn populations,\n", text, textlen) == 0);
+ cl_assert_equal_i(31, oldno);
+ cl_assert_equal_i(25, newno);
+
+ cl_git_pass(git_diff_patch_get_line_in_hunk(
+ &origin, &text, &textlen, &oldno, &newno, patch, 1, 3));
+ cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin);
+ cl_assert(strncmp("The Daughters of the Palace whom they cherished in my Cities,\n", text, textlen) == 0);
+ cl_assert_equal_i(34, oldno);
+ cl_assert_equal_i(-1, newno);
+
+ cl_git_pass(git_diff_patch_get_line_in_hunk(
+ &origin, &text, &textlen, &oldno, &newno, patch, 1, 12));
+ cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin);
+ cl_assert(strncmp("Another replacement;\n", text, textlen) == 0);
+ cl_assert_equal_i(-1, oldno);
+ cl_assert_equal_i(28, newno);
+
+ git_diff_patch_free(patch);
+ git_diff_list_free(diff);
+ git_tree_free(head);
+}
diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c
index 5c89b95e7..21da63954 100644
--- a/tests-clar/diff/workdir.c
+++ b/tests-clar/diff/workdir.c
@@ -897,6 +897,7 @@ void test_diff_workdir__can_diff_empty_file(void)
/* baseline - make sure there are no outstanding diffs */
cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
+ git_tree_free(tree);
cl_assert_equal_i(2, (int)git_diff_num_deltas(diff));
git_diff_list_free(diff);
diff --git a/tests-clar/network/cred.c b/tests-clar/network/cred.c
index 0fdcf3aa0..b7f45c23b 100644
--- a/tests-clar/network/cred.c
+++ b/tests-clar/network/cred.c
@@ -23,5 +23,5 @@ void test_network_cred__stock_userpass_validates_that_method_is_allowed(void)
cl_git_fail(git_cred_userpass(&cred, NULL, 0, &payload));
cl_git_pass(git_cred_userpass(&cred, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload));
- git__free(cred);
+ cred->free(cred);
}
diff --git a/tests-clar/resources/binaryunicode/.gitted/HEAD b/tests-clar/resources/binaryunicode/.gitted/HEAD
new file mode 100644
index 000000000..cb089cd89
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests-clar/resources/binaryunicode/.gitted/config b/tests-clar/resources/binaryunicode/.gitted/config
new file mode 100644
index 000000000..f9845fe7e
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/config
@@ -0,0 +1,6 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ autocrlf = true
+ logallrefupdates = true
diff --git a/tests-clar/resources/binaryunicode/.gitted/description b/tests-clar/resources/binaryunicode/.gitted/description
new file mode 100644
index 000000000..498b267a8
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/tests-clar/resources/binaryunicode/.gitted/index b/tests-clar/resources/binaryunicode/.gitted/index
new file mode 100644
index 000000000..a216d2219
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/index
Binary files differ
diff --git a/tests-clar/resources/binaryunicode/.gitted/info/exclude b/tests-clar/resources/binaryunicode/.gitted/info/exclude
new file mode 100644
index 000000000..a5196d1be
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests-clar/resources/binaryunicode/.gitted/info/refs b/tests-clar/resources/binaryunicode/.gitted/info/refs
new file mode 100644
index 000000000..128eea7c9
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/info/refs
@@ -0,0 +1,3 @@
+39e046d1416a208265b754124d0d197b4c9c0c47 refs/heads/branch1
+9e7d8bcd4d24dd57e3f1179aaf7afe648ff50e80 refs/heads/branch2
+d2a291469f4c11f387600d189313b927ddfe891c refs/heads/master
diff --git a/tests-clar/resources/binaryunicode/.gitted/objects/info/packs b/tests-clar/resources/binaryunicode/.gitted/objects/info/packs
new file mode 100644
index 000000000..c2de8f5cb
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/objects/info/packs
@@ -0,0 +1,2 @@
+P pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.pack
+
diff --git a/tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.idx b/tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.idx
new file mode 100644
index 000000000..8a05b2beb
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.idx
Binary files differ
diff --git a/tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.pack b/tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.pack
new file mode 100644
index 000000000..6b5ddc414
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.pack
Binary files differ
diff --git a/tests-clar/resources/binaryunicode/.gitted/refs/heads/branch1 b/tests-clar/resources/binaryunicode/.gitted/refs/heads/branch1
new file mode 100644
index 000000000..0595fbd31
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/refs/heads/branch1
@@ -0,0 +1 @@
+39e046d1416a208265b754124d0d197b4c9c0c47
diff --git a/tests-clar/resources/binaryunicode/.gitted/refs/heads/branch2 b/tests-clar/resources/binaryunicode/.gitted/refs/heads/branch2
new file mode 100644
index 000000000..d86856687
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/refs/heads/branch2
@@ -0,0 +1 @@
+9e7d8bcd4d24dd57e3f1179aaf7afe648ff50e80
diff --git a/tests-clar/resources/binaryunicode/.gitted/refs/heads/master b/tests-clar/resources/binaryunicode/.gitted/refs/heads/master
new file mode 100644
index 000000000..552d166da
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/.gitted/refs/heads/master
@@ -0,0 +1 @@
+d2a291469f4c11f387600d189313b927ddfe891c
diff --git a/tests-clar/resources/binaryunicode/file.txt b/tests-clar/resources/binaryunicode/file.txt
new file mode 100644
index 000000000..2255035d4
--- /dev/null
+++ b/tests-clar/resources/binaryunicode/file.txt
@@ -0,0 +1 @@
+Master branch.
diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c
index 293a585f0..e2617ab0e 100644
--- a/tests-clar/revwalk/mergebase.c
+++ b/tests-clar/revwalk/mergebase.c
@@ -33,12 +33,12 @@ void test_revwalk_mergebase__single1(void)
cl_assert(git_oid_cmp(&result, &expected) == 0);
cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two));
- cl_assert_equal_i(ahead, 2);
- cl_assert_equal_i(behind, 1);
+ cl_assert_equal_sz(ahead, 2);
+ cl_assert_equal_sz(behind, 1);
cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one));
- cl_assert_equal_i(ahead, 1);
- cl_assert_equal_i(behind, 2);
+ cl_assert_equal_sz(ahead, 1);
+ cl_assert_equal_sz(behind, 2);
}
void test_revwalk_mergebase__single2(void)
@@ -54,12 +54,12 @@ void test_revwalk_mergebase__single2(void)
cl_assert(git_oid_cmp(&result, &expected) == 0);
cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &one, &two));
- cl_assert_equal_i(ahead, 4);
- cl_assert_equal_i(behind, 1);
+ cl_assert_equal_sz(ahead, 4);
+ cl_assert_equal_sz(behind, 1);
cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &two, &one));
- cl_assert_equal_i(ahead, 1);
- cl_assert_equal_i(behind, 4);
+ cl_assert_equal_sz(ahead, 1);
+ cl_assert_equal_sz(behind, 4);
}
void test_revwalk_mergebase__merged_branch(void)
@@ -78,12 +78,12 @@ void test_revwalk_mergebase__merged_branch(void)
cl_assert(git_oid_cmp(&result, &expected) == 0);
cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two));
- cl_assert_equal_i(ahead, 0);
- cl_assert_equal_i(behind, 3);
+ cl_assert_equal_sz(ahead, 0);
+ cl_assert_equal_sz(behind, 3);
cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one));
- cl_assert_equal_i(ahead, 3);
- cl_assert_equal_i(behind, 0);
+ cl_assert_equal_sz(ahead, 3);
+ cl_assert_equal_sz(behind, 0);
}
void test_revwalk_mergebase__two_way_merge(void)
@@ -95,13 +95,13 @@ void test_revwalk_mergebase__two_way_merge(void)
cl_git_pass(git_oid_fromstr(&two, "a953a018c5b10b20c86e69fef55ebc8ad4c5a417"));
cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &one, &two));
- cl_assert_equal_i(ahead, 2);
- cl_assert_equal_i(behind, 8);
+ cl_assert_equal_sz(ahead, 2);
+ cl_assert_equal_sz(behind, 8);
cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &two, &one));
- cl_assert_equal_i(ahead, 8);
- cl_assert_equal_i(behind, 2);
+ cl_assert_equal_sz(ahead, 8);
+ cl_assert_equal_sz(behind, 2);
}
void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void)
@@ -119,8 +119,8 @@ void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void)
cl_assert_equal_i(GIT_ENOTFOUND, error);
cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two));
- cl_assert_equal_i(2, ahead);
- cl_assert_equal_i(4, behind);
+ cl_assert_equal_sz(2, ahead);
+ cl_assert_equal_sz(4, behind);
}
void test_revwalk_mergebase__no_off_by_one_missing(void)