Merge pull request #3333 from libgit2/cmn/for-v23
Maintenance updates for v0.23
diff --git a/examples/network/fetch.c b/examples/network/fetch.c
index 67444cb..6be1240 100644
--- a/examples/network/fetch.c
+++ b/examples/network/fetch.c
@@ -143,10 +143,10 @@
* network.
*/
if (stats->local_objects > 0) {
- printf("\rReceived %d/%d objects in %zu bytes (used %d local objects)\n",
+ printf("\rReceived %d/%d objects in %" PRIuZ " bytes (used %d local objects)\n",
stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects);
} else{
- printf("\rReceived %d/%d objects in %zu bytes\n",
+ printf("\rReceived %d/%d objects in %" PRIuZ "bytes\n",
stats->indexed_objects, stats->total_objects, stats->received_bytes);
}
diff --git a/include/git2/errors.h b/include/git2/errors.h
index a81aa05..e189e55 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -48,6 +48,7 @@
GIT_EEOF = -20, /**< Unexpected EOF */
GIT_EINVALID = -21, /**< Invalid operation or input */
GIT_EUNCOMMITTED = -22, /**< Uncommitted changes in index prevented operation */
+ GIT_EDIRECTORY = -23, /**< The operation is not valid for a directory */
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
diff --git a/include/git2/remote.h b/include/git2/remote.h
index e47f008..444fe52 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -511,6 +511,14 @@
GIT_REMOTE_DOWNLOAD_TAGS_ALL,
} git_remote_autotag_option_t;
+/**
+ * Fetch options structure.
+ *
+ * Zero out for defaults. Initialize with `GIT_FETCH_OPTIONS_INIT` macro to
+ * correctly set the `version` field. E.g.
+ *
+ * git_fetch_options opts = GIT_FETCH_OPTIONS_INIT;
+ */
typedef struct {
int version;
@@ -739,7 +747,7 @@
* stored here for further processing by the caller. Always free this
* strarray on successful return.
* @param repo the repository in which to rename
- * @param name the current name of the reamote
+ * @param name the current name of the remote
* @param new_name the new name the remote should bear
* @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code
*/
diff --git a/src/blame_git.c b/src/blame_git.c
index e863efe..f481426 100644
--- a/src/blame_git.c
+++ b/src/blame_git.c
@@ -304,21 +304,16 @@
}
static int my_emit(
- xdfenv_t *xe,
- xdchange_t *xscr,
- xdemitcb_t *ecb,
- xdemitconf_t const *xecfg)
+ long start_a, long count_a,
+ long start_b, long count_b,
+ void *cb_data)
{
- xdchange_t *xch = xscr;
- GIT_UNUSED(xe);
- GIT_UNUSED(xecfg);
- while (xch) {
- blame_chunk_cb_data *d = ecb->priv;
- blame_chunk(d->blame, d->tlno, d->plno, xch->i2, d->target, d->parent);
- d->plno = xch->i1 + xch->chg1;
- d->tlno = xch->i2 + xch->chg2;
- xch = xch->next;
- }
+ blame_chunk_cb_data *d = (blame_chunk_cb_data *)cb_data;
+
+ blame_chunk(d->blame, d->tlno, d->plno, start_b, d->target, d->parent);
+ d->plno = start_a + count_a;
+ d->tlno = start_b + count_b;
+
return 0;
}
@@ -352,7 +347,7 @@
xdemitconf_t xecfg = {0};
xdemitcb_t ecb = {0};
- xecfg.emit_func = (void(*)(void))my_emit;
+ xecfg.hunk_func = my_emit;
ecb.priv = cb_data;
trim_common_tail(&file_a, &file_b, 0);
diff --git a/src/blob.c b/src/blob.c
index 07c4d92..ad0f4ac 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -185,6 +185,12 @@
(error = git_repository_odb(&odb, repo)) < 0)
goto done;
+ if (S_ISDIR(st.st_mode)) {
+ giterr_set(GITERR_ODB, "cannot create blob from '%s'; it is a directory", content_path);
+ error = GIT_EDIRECTORY;
+ goto done;
+ }
+
if (out_st)
memcpy(out_st, &st, sizeof(st));
diff --git a/src/cache.c b/src/cache.c
index 2f3ad15..ca5173c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -50,16 +50,16 @@
if (kh_size(cache->map) == 0)
return;
- printf("Cache %p: %d items cached, %d bytes\n",
- cache, kh_size(cache->map), (int)cache->used_memory);
+ printf("Cache %p: %d items cached, %"PRIdZ" bytes\n",
+ cache, kh_size(cache->map), cache->used_memory);
kh_foreach_value(cache->map, object, {
char oid_str[9];
- printf(" %s%c %s (%d)\n",
+ printf(" %s%c %s (%"PRIuZ")\n",
git_object_type2string(object->type),
object->flags == GIT_CACHE_STORE_PARSED ? '*' : ' ',
git_oid_tostr(oid_str, sizeof(oid_str), &object->oid),
- (int)object->size
+ object->size
);
});
}
diff --git a/src/checkout.c b/src/checkout.c
index a94d509..4b3acbc 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -1299,8 +1299,8 @@
if (counts[CHECKOUT_ACTION__CONFLICT] > 0 &&
(data->strategy & GIT_CHECKOUT_ALLOW_CONFLICTS) == 0)
{
- giterr_set(GITERR_CHECKOUT, "%d %s checkout",
- (int)counts[CHECKOUT_ACTION__CONFLICT],
+ giterr_set(GITERR_CHECKOUT, "%"PRIuZ" %s checkout",
+ counts[CHECKOUT_ACTION__CONFLICT],
counts[CHECKOUT_ACTION__CONFLICT] == 1 ?
"conflict prevents" : "conflicts prevent");
error = GIT_ECONFLICT;
diff --git a/src/filter.c b/src/filter.c
index e25d37c..4006351 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -947,18 +947,20 @@
{
git_vector filter_streams = GIT_VECTOR_INIT;
git_writestream *stream_start;
- int error = 0;
+ int error = 0, close_error;
git_buf_sanitize(data);
- if ((error = stream_list_init(
- &stream_start, &filter_streams, filters, target)) == 0 &&
- (error =
- stream_start->write(stream_start, data->ptr, data->size)) == 0)
- error = stream_start->close(stream_start);
+ if ((error = stream_list_init(&stream_start, &filter_streams, filters, target)) < 0)
+ goto out;
+ error = stream_start->write(stream_start, data->ptr, data->size);
+
+out:
+ close_error = stream_start->close(stream_start);
stream_list_free(&filter_streams);
- return error;
+ /* propagate the stream init or write error */
+ return error < 0 ? error : close_error;
}
int git_filter_list_stream_blob(
diff --git a/src/index.c b/src/index.c
index 5ce5522..501498e 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1236,10 +1236,30 @@
assert(index && path);
- if ((ret = index_entry_init(&entry, index, path)) < 0 ||
- (ret = index_insert(index, &entry, 1, false)) < 0)
+ if ((ret = index_entry_init(&entry, index, path)) == 0)
+ ret = index_insert(index, &entry, 1, false);
+
+ /* If we were given a directory, let's see if it's a submodule */
+ if (ret < 0 && ret != GIT_EDIRECTORY)
return ret;
+ if (ret == GIT_EDIRECTORY) {
+ git_submodule *sm;
+ git_error_state err;
+
+ giterr_capture(&err, ret);
+
+ ret = git_submodule_lookup(&sm, INDEX_OWNER(index), path);
+ if (ret == GIT_ENOTFOUND)
+ return giterr_restore(&err);
+ else
+ git__free(err.error_msg.message);
+
+ ret = git_submodule_add_to_index(sm, false);
+ git_submodule_free(sm);
+ return ret;
+ }
+
/* Adding implies conflict was resolved, move conflict entries to REUC */
if ((ret = index_conflict_to_reuc(index, path)) < 0 && ret != GIT_ENOTFOUND)
return ret;
diff --git a/src/khash.h b/src/khash.h
index 818ac83..71eb583 100644
--- a/src/khash.h
+++ b/src/khash.h
@@ -619,4 +619,4 @@
#define KHASH_MAP_INIT_STR(name, khval_t) \
KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
-#endif /* __AC_KHASH_H */
\ No newline at end of file
+#endif /* __AC_KHASH_H */
diff --git a/src/merge.c b/src/merge.c
index 9d6252e..863ac8f 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -79,7 +79,7 @@
unsigned int i;
if (length < 2) {
- giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %u.", length);
+ giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %" PRIuZ ".", length);
return -1;
}
@@ -185,7 +185,7 @@
assert(out && repo && input_array);
if (length < 2) {
- giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %u.", length);
+ giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %" PRIuZ ".", length);
return -1;
}
@@ -2451,7 +2451,7 @@
goto done;
if ((conflicts = index_conflicts + wd_conflicts) > 0) {
- giterr_set(GITERR_MERGE, "%d uncommitted change%s would be overwritten by merge",
+ giterr_set(GITERR_MERGE, "%" PRIuZ " uncommitted change%s would be overwritten by merge",
conflicts, (conflicts != 1) ? "s" : "");
error = GIT_ECONFLICT;
}
diff --git a/src/openssl_stream.c b/src/openssl_stream.c
index 958252e..4df7c6b 100644
--- a/src/openssl_stream.c
+++ b/src/openssl_stream.c
@@ -324,7 +324,9 @@
SSL_set_bio(st->ssl, bio, bio);
/* specify the host in case SNI is needed */
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
SSL_set_tlsext_host_name(st->ssl, st->host);
+#endif
if ((ret = SSL_connect(st->ssl)) <= 0)
return ssl_set_error(st->ssl, ret);
diff --git a/src/path.c b/src/path.c
index 2558058..3e63f06 100644
--- a/src/path.c
+++ b/src/path.c
@@ -12,6 +12,7 @@
#include "win32/posix.h"
#include "win32/buffer.h"
#include "win32/w32_util.h"
+#include "win32/version.h"
#else
#include <dirent.h>
#endif
@@ -1085,7 +1086,7 @@
#if defined(GIT_WIN32) && !defined(__MINGW32__)
/* Using _FIND_FIRST_EX_LARGE_FETCH may increase performance in Windows 7
- * and better. Prior versions will ignore this.
+ * and better.
*/
#ifndef FIND_FIRST_EX_LARGE_FETCH
# define FIND_FIRST_EX_LARGE_FETCH 2
@@ -1099,6 +1100,10 @@
git_win32_path path_filter;
git_buf hack = {0};
+ static int is_win7_or_later = -1;
+ if (is_win7_or_later < 0)
+ is_win7_or_later = git_has_win32_version(6, 1, 0);
+
assert(diriter && path);
memset(diriter, 0, sizeof(git_path_diriter));
@@ -1122,11 +1127,11 @@
diriter->handle = FindFirstFileExW(
path_filter,
- FindExInfoBasic,
+ is_win7_or_later ? FindExInfoBasic : FindExInfoStandard,
&diriter->current,
FindExSearchNameMatch,
NULL,
- FIND_FIRST_EX_LARGE_FETCH);
+ is_win7_or_later ? FIND_FIRST_EX_LARGE_FETCH : 0);
if (diriter->handle == INVALID_HANDLE_VALUE) {
giterr_set(GITERR_OS, "Could not open directory '%s'", path);
diff --git a/src/rebase.c b/src/rebase.c
index 8da7b4f..17536c0 100644
--- a/src/rebase.c
+++ b/src/rebase.c
@@ -436,7 +436,7 @@
size_t i;
int error = 0;
- if ((error = rebase_setupfile(rebase, END_FILE, -1, "%d\n", git_array_size(rebase->operations))) < 0 ||
+ if ((error = rebase_setupfile(rebase, END_FILE, -1, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 ||
(error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->onto_name)) < 0)
goto done;
@@ -789,7 +789,7 @@
normalize_checkout_options_for_apply(&checkout_opts, rebase, current_commit);
if ((error = git_indexwriter_init_for_operation(&indexwriter, rebase->repo, &checkout_opts.checkout_strategy)) < 0 ||
- (error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%d\n", rebase->current+1)) < 0 ||
+ (error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%" PRIuZ "\n", rebase->current+1)) < 0 ||
(error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0 ||
(error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, NULL)) < 0 ||
(error = git_merge__check_result(rebase->repo, index)) < 0 ||
diff --git a/src/stash.c b/src/stash.c
index acf8944..fcb1112 100644
--- a/src/stash.c
+++ b/src/stash.c
@@ -770,7 +770,7 @@
goto done;
if (git_diff_num_deltas(index_diff) > 0) {
- giterr_set(GITERR_STASH, "%d uncommitted changes exist in the index",
+ giterr_set(GITERR_STASH, "%" PRIuZ " uncommitted changes exist in the index",
git_diff_num_deltas(index_diff));
error = GIT_EUNCOMMITTED;
}
diff --git a/src/submodule.c b/src/submodule.c
index fb3d4bf..3d02874 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -781,11 +781,25 @@
int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *url)
{
int error = 0;
+ git_buf normalized = GIT_BUF_INIT;
assert(out && repo && url);
git_buf_sanitize(out);
+ if (strchr(url, '\\')) {
+ char *p;
+ if ((error = git_buf_puts(&normalized, url)) < 0)
+ return error;
+
+ for (p = normalized.ptr; *p; p++) {
+ if (*p == '\\')
+ *p = '/';
+ }
+
+ url = normalized.ptr;
+ }
+
if (git_path_is_relative(url)) {
if (!(error = get_url_base(out, repo)))
error = git_path_apply_relative(out, url);
@@ -796,6 +810,7 @@
error = -1;
}
+ git_buf_free(&normalized);
return error;
}
@@ -1647,7 +1662,7 @@
} else {
khiter_t pos;
git_strmap *map = data->map;
- pos = git_strmap_lookup_index(map, name.ptr);
+ pos = git_strmap_lookup_index(map, path ? path : name.ptr);
if (git_strmap_valid_index(map, pos)) {
sm = git_strmap_value_at(map, pos);
} else {
diff --git a/src/thread-utils.c b/src/thread-utils.c
index c3baf41..dc9b2f0 100644
--- a/src/thread-utils.c
+++ b/src/thread-utils.c
@@ -8,7 +8,9 @@
#include "thread-utils.h"
#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
+#endif
# include <windows.h>
#elif defined(hpux) || defined(__hpux) || defined(_hpux)
# include <sys/pstat.h>
diff --git a/src/transports/http.c b/src/transports/http.c
index dd44264..1ed292b 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -511,7 +511,7 @@
git_buf buf = GIT_BUF_INIT;
/* Chunk header */
- git_buf_printf(&buf, "%X\r\n", (unsigned)len);
+ git_buf_printf(&buf, "%" PRIxZ "\r\n", len);
if (git_buf_oom(&buf))
return -1;
diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c
index d214c9f..9ccbd80 100644
--- a/src/transports/smart_pkt.c
+++ b/src/transports/smart_pkt.c
@@ -523,7 +523,7 @@
if (len > 0xffff) {
giterr_set(GITERR_NET,
- "Tried to produce packet with invalid length %d", len);
+ "Tried to produce packet with invalid length %" PRIuZ, len);
return -1;
}
diff --git a/src/xdiff/xdiff.h b/src/xdiff/xdiff.h
index cb8b235..e2f1e89 100644
--- a/src/xdiff/xdiff.h
+++ b/src/xdiff/xdiff.h
@@ -32,14 +32,14 @@
#define XDF_IGNORE_WHITESPACE (1 << 2)
#define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3)
#define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 4)
-#define XDF_PATIENCE_DIFF (1 << 5)
-#define XDF_HISTOGRAM_DIFF (1 << 6)
#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE | XDF_IGNORE_WHITESPACE_AT_EOL)
-#define XDL_PATCH_NORMAL '-'
-#define XDL_PATCH_REVERSE '+'
-#define XDL_PATCH_MODEMASK ((1 << 8) - 1)
-#define XDL_PATCH_IGNOREBSPACE (1 << 8)
+#define XDF_PATIENCE_DIFF (1 << 5)
+#define XDF_HISTOGRAM_DIFF (1 << 6)
+#define XDF_DIFF_ALGORITHM_MASK (XDF_PATIENCE_DIFF | XDF_HISTOGRAM_DIFF)
+#define XDF_DIFF_ALG(x) ((x) & XDF_DIFF_ALGORITHM_MASK)
+
+#define XDF_IGNORE_BLANK_LINES (1 << 7)
#define XDL_EMIT_FUNCNAMES (1 << 0)
#define XDL_EMIT_COMMON (1 << 1)
@@ -88,13 +88,17 @@
typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv);
+typedef int (*xdl_emit_hunk_consume_func_t)(long start_a, long count_a,
+ long start_b, long count_b,
+ void *cb_data);
+
typedef struct s_xdemitconf {
long ctxlen;
long interhunkctxlen;
unsigned long flags;
find_func_t find_func;
void *find_func_priv;
- void (*emit_func)(void);
+ xdl_emit_hunk_consume_func_t hunk_func;
} xdemitconf_t;
typedef struct s_bdiffparam {
diff --git a/src/xdiff/xdiffi.c b/src/xdiff/xdiffi.c
index 84aa0fc..0620e5f 100644
--- a/src/xdiff/xdiffi.c
+++ b/src/xdiff/xdiffi.c
@@ -328,10 +328,10 @@
xdalgoenv_t xenv;
diffdata_t dd1, dd2;
- if (xpp->flags & XDF_PATIENCE_DIFF)
+ if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF)
return xdl_do_patience_diff(mf1, mf2, xpp, xe);
- if (xpp->flags & XDF_HISTOGRAM_DIFF)
+ if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)
return xdl_do_histogram_diff(mf1, mf2, xpp, xe);
if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) {
@@ -394,6 +394,7 @@
xch->i2 = i2;
xch->chg1 = chg1;
xch->chg2 = chg2;
+ xch->ignore = 0;
return xch;
}
@@ -538,13 +539,51 @@
}
}
+static int xdl_call_hunk_func(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
+ xdemitconf_t const *xecfg)
+{
+ xdchange_t *xch, *xche;
+
+ (void)xe;
+
+ for (xch = xscr; xch; xch = xche->next) {
+ xche = xdl_get_hunk(&xch, xecfg);
+ if (!xch)
+ break;
+ if (xecfg->hunk_func(xch->i1, xche->i1 + xche->chg1 - xch->i1,
+ xch->i2, xche->i2 + xche->chg2 - xch->i2,
+ ecb->priv) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags)
+{
+ xdchange_t *xch;
+
+ for (xch = xscr; xch; xch = xch->next) {
+ int ignore = 1;
+ xrecord_t **rec;
+ long i;
+
+ rec = &xe->xdf1.recs[xch->i1];
+ for (i = 0; i < xch->chg1 && ignore; i++)
+ ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags);
+
+ rec = &xe->xdf2.recs[xch->i2];
+ for (i = 0; i < xch->chg2 && ignore; i++)
+ ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags);
+
+ xch->ignore = ignore;
+ }
+}
int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
xdchange_t *xscr;
xdfenv_t xe;
- emit_func_t ef = xecfg->emit_func ?
- (emit_func_t)xecfg->emit_func : xdl_emit_diff;
+ emit_func_t ef = xecfg->hunk_func ? xdl_call_hunk_func : xdl_emit_diff;
if (xdl_do_diff(mf1, mf2, xpp, &xe) < 0) {
@@ -558,6 +597,9 @@
return -1;
}
if (xscr) {
+ if (xpp->flags & XDF_IGNORE_BLANK_LINES)
+ xdl_mark_ignorable(xscr, &xe, xpp->flags);
+
if (ef(&xe, xscr, ecb, xecfg) < 0) {
xdl_free_script(xscr);
diff --git a/src/xdiff/xdiffi.h b/src/xdiff/xdiffi.h
index 7a92ea9..8b81206 100644
--- a/src/xdiff/xdiffi.h
+++ b/src/xdiff/xdiffi.h
@@ -41,6 +41,7 @@
struct s_xdchange *next;
long i1, i2;
long chg1, chg2;
+ int ignore;
} xdchange_t;
diff --git a/src/xdiff/xemit.c b/src/xdiff/xemit.c
index e3e63d9..600fd1f 100644
--- a/src/xdiff/xemit.c
+++ b/src/xdiff/xemit.c
@@ -56,16 +56,51 @@
/*
* Starting at the passed change atom, find the latest change atom to be included
* inside the differential hunk according to the specified configuration.
+ * Also advance xscr if the first changes must be discarded.
*/
-xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
- xdchange_t *xch, *xchp;
+xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
+{
+ xdchange_t *xch, *xchp, *lxch;
long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
+ long max_ignorable = xecfg->ctxlen;
+ unsigned long ignored = 0; /* number of ignored blank lines */
- for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next)
- if (xch->i1 - (xchp->i1 + xchp->chg1) > max_common)
+ /* remove ignorable changes that are too far before other changes */
+ for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) {
+ xch = xchp->next;
+
+ if (xch == NULL ||
+ xch->i1 - (xchp->i1 + xchp->chg1) >= max_ignorable)
+ *xscr = xch;
+ }
+
+ if (*xscr == NULL)
+ return NULL;
+
+ lxch = *xscr;
+
+ for (xchp = *xscr, xch = xchp->next; xch; xchp = xch, xch = xch->next) {
+ long distance = xch->i1 - (xchp->i1 + xchp->chg1);
+ if (distance > max_common)
break;
- return xchp;
+ if (distance < max_ignorable && (!xch->ignore || lxch == xchp)) {
+ lxch = xch;
+ ignored = 0;
+ } else if (distance < max_ignorable && xch->ignore) {
+ ignored += xch->chg2;
+ } else if (lxch != xchp &&
+ xch->i1 + ignored - (lxch->i1 + lxch->chg1) > (unsigned long)max_common) {
+ break;
+ } else if (!xch->ignore) {
+ lxch = xch;
+ ignored = 0;
+ } else {
+ ignored += xch->chg2;
+ }
+ }
+
+ return lxch;
}
@@ -144,7 +179,9 @@
return xdl_emit_common(xe, xscr, ecb, xecfg);
for (xch = xscr; xch; xch = xche->next) {
- xche = xdl_get_hunk(xch, xecfg);
+ xche = xdl_get_hunk(&xch, xecfg);
+ if (!xch)
+ break;
s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
diff --git a/src/xdiff/xemit.h b/src/xdiff/xemit.h
index c2e2e83..d297107 100644
--- a/src/xdiff/xemit.h
+++ b/src/xdiff/xemit.h
@@ -27,7 +27,7 @@
typedef int (*emit_func_t)(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg);
-xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg);
+xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg);
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg);
diff --git a/src/xdiff/xhistogram.c b/src/xdiff/xhistogram.c
index c848128..500d811 100644
--- a/src/xdiff/xhistogram.c
+++ b/src/xdiff/xhistogram.c
@@ -258,7 +258,7 @@
int line1, int count1, int line2, int count2)
{
xpparam_t xpp;
- xpp.flags = index->xpp->flags & ~XDF_HISTOGRAM_DIFF;
+ xpp.flags = index->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
return xdl_fall_back_diff(index->env, &xpp,
line1, count1, line2, count2);
diff --git a/src/xdiff/xmerge.c b/src/xdiff/xmerge.c
index 84e4246..b11e598 100644
--- a/src/xdiff/xmerge.c
+++ b/src/xdiff/xmerge.c
@@ -245,11 +245,11 @@
dest ? dest + size : NULL);
/* Postimage from side #1 */
if (m->mode & 1)
- size += xdl_recs_copy(xe1, m->i1, m->chg1, 1,
+ size += xdl_recs_copy(xe1, m->i1, m->chg1, (m->mode & 2),
dest ? dest + size : NULL);
/* Postimage from side #2 */
if (m->mode & 2)
- size += xdl_recs_copy(xe2, m->i2, m->chg2, 1,
+ size += xdl_recs_copy(xe2, m->i2, m->chg2, 0,
dest ? dest + size : NULL);
} else
continue;
diff --git a/src/xdiff/xpatience.c b/src/xdiff/xpatience.c
index fdd7d02..04e1a1a 100644
--- a/src/xdiff/xpatience.c
+++ b/src/xdiff/xpatience.c
@@ -288,7 +288,7 @@
int line1, int count1, int line2, int count2)
{
xpparam_t xpp;
- xpp.flags = map->xpp->flags & ~XDF_PATIENCE_DIFF;
+ xpp.flags = map->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
return xdl_fall_back_diff(map->env, &xpp,
line1, count1, line2, count2);
diff --git a/src/xdiff/xprepare.c b/src/xdiff/xprepare.c
index e419f4f..63a22c6 100644
--- a/src/xdiff/xprepare.c
+++ b/src/xdiff/xprepare.c
@@ -181,7 +181,7 @@
if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *))))
goto abort;
- if (xpp->flags & XDF_HISTOGRAM_DIFF)
+ if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)
hbits = hsize = 0;
else {
hbits = xdl_hashbits((unsigned int) narec);
@@ -209,8 +209,8 @@
crec->ha = hav;
recs[nrec++] = crec;
- if (!(xpp->flags & XDF_HISTOGRAM_DIFF) &&
- xdl_classify_record(pass, cf, rhash, hbits, crec) < 0)
+ if ((XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) &&
+ xdl_classify_record(pass, cf, rhash, hbits, crec) < 0)
goto abort;
}
}
@@ -273,16 +273,15 @@
* (nrecs) will be updated correctly anyway by
* xdl_prepare_ctx().
*/
- sample = xpp->flags & XDF_HISTOGRAM_DIFF ? XDL_GUESS_NLINES2 : XDL_GUESS_NLINES1;
+ sample = (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF
+ ? XDL_GUESS_NLINES2 : XDL_GUESS_NLINES1);
enl1 = xdl_guess_lines(mf1, sample) + 1;
enl2 = xdl_guess_lines(mf2, sample) + 1;
- if (!(xpp->flags & XDF_HISTOGRAM_DIFF) &&
- xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0) {
-
+ if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF &&
+ xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0)
return -1;
- }
if (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) {
@@ -296,9 +295,9 @@
return -1;
}
- if (!(xpp->flags & XDF_PATIENCE_DIFF) &&
- !(xpp->flags & XDF_HISTOGRAM_DIFF) &&
- xdl_optimize_ctxs(&cf, &xe->xdf1, &xe->xdf2) < 0) {
+ if ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) &&
+ (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) &&
+ xdl_optimize_ctxs(&cf, &xe->xdf1, &xe->xdf2) < 0) {
xdl_free_ctx(&xe->xdf2);
xdl_free_ctx(&xe->xdf1);
diff --git a/src/xdiff/xutils.c b/src/xdiff/xutils.c
index bb7bdee..30f2a30 100644
--- a/src/xdiff/xutils.c
+++ b/src/xdiff/xutils.c
@@ -120,35 +120,6 @@
return data;
}
-
-void *xdl_cha_first(chastore_t *cha) {
- chanode_t *sncur;
-
- if (!(cha->sncur = sncur = cha->head))
- return NULL;
-
- cha->scurr = 0;
-
- return (char *) sncur + sizeof(chanode_t) + cha->scurr;
-}
-
-
-void *xdl_cha_next(chastore_t *cha) {
- chanode_t *sncur;
-
- if (!(sncur = cha->sncur))
- return NULL;
- cha->scurr += cha->isize;
- if (cha->scurr == sncur->icurr) {
- if (!(sncur = cha->sncur = sncur->next))
- return NULL;
- cha->scurr = 0;
- }
-
- return (char *) sncur + sizeof(chanode_t) + cha->scurr;
-}
-
-
long xdl_guess_lines(mmfile_t *mf, long sample) {
long nl = 0, size, tsize = 0;
char const *data, *cur, *top;
@@ -170,6 +141,19 @@
return nl + 1;
}
+int xdl_blankline(const char *line, long size, long flags)
+{
+ long i;
+
+ if (!(flags & XDF_WHITESPACE_FLAGS))
+ return (size <= 1);
+
+ for (i = 0; i < size && XDL_ISSPACE(line[i]); i++)
+ ;
+
+ return (i == size);
+}
+
int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
{
int i1, i2;
diff --git a/src/xdiff/xutils.h b/src/xdiff/xutils.h
index 714719a..8f952a8 100644
--- a/src/xdiff/xutils.h
+++ b/src/xdiff/xutils.h
@@ -34,6 +34,7 @@
void *xdl_cha_first(chastore_t *cha);
void *xdl_cha_next(chastore_t *cha);
long xdl_guess_lines(mmfile_t *mf, long sample);
+int xdl_blankline(const char *line, long size, long flags);
int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags);
unsigned long xdl_hash_record(char const **data, char const *top, long flags);
unsigned int xdl_hashbits(unsigned int size);
diff --git a/tests/blame/blame_helpers.c b/tests/blame/blame_helpers.c
index 21cd1a6..b305ba1 100644
--- a/tests/blame/blame_helpers.c
+++ b/tests/blame/blame_helpers.c
@@ -4,7 +4,7 @@
{
va_list arglist;
- printf("Hunk %zd (line %d +%d): ", idx,
+ printf("Hunk %"PRIuZ" (line %d +%d): ", idx,
hunk->final_start_line_number, hunk->lines_in_hunk-1);
va_start(arglist, fmt);
diff --git a/tests/clar_libgit2.c b/tests/clar_libgit2.c
index dabc47a..b14af44 100644
--- a/tests/clar_libgit2.c
+++ b/tests/clar_libgit2.c
@@ -483,8 +483,8 @@
for (pos = 0; pos < bytes && expected_data[pos] == buf[pos]; ++pos)
/* find differing byte offset */;
p_snprintf(
- buf, sizeof(buf), "file content mismatch at byte %d",
- (int)(total_bytes + pos));
+ buf, sizeof(buf), "file content mismatch at byte %"PRIdZ,
+ (ssize_t)(total_bytes + pos));
p_close(fd);
clar__fail(file, line, path, buf, 1);
}
diff --git a/tests/index/bypath.c b/tests/index/bypath.c
new file mode 100644
index 0000000..ddb766a
--- /dev/null
+++ b/tests/index/bypath.c
@@ -0,0 +1,35 @@
+#include "clar_libgit2.h"
+#include "repository.h"
+#include "../submodule/submodule_helpers.h"
+
+static git_repository *g_repo;
+static git_index *g_idx;
+
+void test_index_bypath__initialize(void)
+{
+ g_repo = setup_fixture_submod2();
+ cl_git_pass(git_repository_index__weakptr(&g_idx, g_repo));
+}
+
+void test_index_bypath__cleanup(void)
+{
+ g_repo = NULL;
+ g_idx = NULL;
+}
+
+void test_index_bypath__add_directory(void)
+{
+ cl_git_fail_with(GIT_EDIRECTORY, git_index_add_bypath(g_idx, "just_a_dir"));
+}
+
+void test_index_bypath__add_submodule(void)
+{
+ unsigned int status;
+ const char *sm_name = "sm_changed_head";
+
+ cl_git_pass(git_submodule_status(&status, g_repo, sm_name, 0));
+ cl_assert_equal_i(GIT_SUBMODULE_STATUS_WD_MODIFIED, status & GIT_SUBMODULE_STATUS_WD_MODIFIED);
+ cl_git_pass(git_index_add_bypath(g_idx, sm_name));
+ cl_git_pass(git_submodule_status(&status, g_repo, sm_name, 0));
+ cl_assert_equal_i(0, status & GIT_SUBMODULE_STATUS_WD_MODIFIED);
+}
diff --git a/tests/merge/files.c b/tests/merge/files.c
index 7f461ab..2fd90d0 100644
--- a/tests/merge/files.c
+++ b/tests/merge/files.c
@@ -249,3 +249,42 @@
git_merge_file_result_free(&result);
}
+
+void test_merge_files__doesnt_add_newline(void)
+{
+ git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
+ ours = GIT_MERGE_FILE_INPUT_INIT,
+ theirs = GIT_MERGE_FILE_INPUT_INIT;
+ git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
+ git_merge_file_result result = {0};
+ const char *expected = "Zero\n1\n2\n3\n4\n5 XXX\n6 YYY\n7\n8\n9\nTen";
+
+ ancestor.ptr = "0\n1\n2\n3\n4\n5 XXX\n6YYY\n7\n8\n9\n10";
+ ancestor.size = strlen(ancestor.ptr);
+ ancestor.path = "testfile.txt";
+ ancestor.mode = 0100755;
+
+ ours.ptr = "Zero\n1\n2\n3\n4\n5 XXX\n6 YYY\n7\n8\n9\n10";
+ ours.size = strlen(ours.ptr);
+ ours.path = "testfile.txt";
+ ours.mode = 0100755;
+
+ theirs.ptr = "0\n1\n2\n3\n4\n5 XXX\n6 YYY\n7\n8\n9\nTen";
+ theirs.size = strlen(theirs.ptr);
+ theirs.path = "testfile.txt";
+ theirs.mode = 0100755;
+
+ opts.flags |= GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE;
+ cl_git_pass(git_merge_file(&result, &ancestor, &ours, &theirs, &opts));
+
+ cl_assert_equal_i(1, result.automergeable);
+
+ cl_assert_equal_s("testfile.txt", result.path);
+ cl_assert_equal_i(0100755, result.mode);
+
+ cl_assert_equal_i(strlen(expected), result.len);
+ cl_assert_equal_strn(expected, result.ptr, result.len);
+
+ git_merge_file_result_free(&result);
+}
+
diff --git a/tests/merge/merge_helpers.c b/tests/merge/merge_helpers.c
index 33710f4..f814714 100644
--- a/tests/merge/merge_helpers.c
+++ b/tests/merge/merge_helpers.c
@@ -110,7 +110,7 @@
size_t i;
const git_index_entry *index_entry;
- printf ("\nINDEX [%d]:\n", (int)index_entries->length);
+ printf ("\nINDEX [%"PRIuZ"]:\n", index_entries->length);
for (i = 0; i < index_entries->length; i++) {
index_entry = index_entries->contents[i];
diff --git a/tests/revert/workdir.c b/tests/revert/workdir.c
index 7ccf0f9..9f83bd8 100644
--- a/tests/revert/workdir.c
+++ b/tests/revert/workdir.c
@@ -334,16 +334,18 @@
cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
cl_git_pass(git_futils_readbuffer(&diff_buf, "revert/file.txt"));
- cl_assert(strcmp(diff_buf.ptr, "a\n" \
- "<<<<<<< HEAD\n" \
- "=======\n" \
- "a\n" \
- ">>>>>>> parent of 97e52d5... Revert me\n" \
- "a\n" \
- "a\n" \
- "a\n" \
- "a\n" \
- "ab\n") == 0);
+ cl_assert_equal_s(
+ "a\n" \
+ "<<<<<<< HEAD\n" \
+ "=======\n" \
+ "a\n" \
+ ">>>>>>> parent of 97e52d5... Revert me\n" \
+ "a\n" \
+ "a\n" \
+ "a\n" \
+ "a\n" \
+ "ab",
+ diff_buf.ptr);
git_commit_free(revert_commit);
git_commit_free(head_commit);
diff --git a/tests/submodule/add.c b/tests/submodule/add.c
index 01625d3..c3b3e63 100644
--- a/tests/submodule/add.c
+++ b/tests/submodule/add.c
@@ -4,6 +4,7 @@
#include "submodule_helpers.h"
#include "config/config_helpers.h"
#include "fileops.h"
+#include "repository.h"
static git_repository *g_repo = NULL;
diff --git a/tests/submodule/lookup.c b/tests/submodule/lookup.c
index 4d40e22..ecea694 100644
--- a/tests/submodule/lookup.c
+++ b/tests/submodule/lookup.c
@@ -1,6 +1,7 @@
#include "clar_libgit2.h"
#include "submodule_helpers.h"
#include "git2/sys/repository.h"
+#include "repository.h"
#include "fileops.h"
static git_repository *g_repo = NULL;
@@ -103,10 +104,27 @@
void test_submodule_lookup__foreach(void)
{
+ git_config *cfg;
sm_lookup_data data;
+
memset(&data, 0, sizeof(data));
cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data));
cl_assert_equal_i(8, data.count);
+
+ memset(&data, 0, sizeof(data));
+
+ /* Change the path for a submodule so it doesn't match the name */
+ cl_git_pass(git_config_open_ondisk(&cfg, "submod2/.gitmodules"));
+
+ cl_git_pass(git_config_set_string(cfg, "submodule.smchangedindex.path", "sm_changed_index"));
+ cl_git_pass(git_config_set_string(cfg, "submodule.smchangedindex.url", "../submod2_target"));
+ cl_git_pass(git_config_delete_entry(cfg, "submodule.sm_changed_index.path"));
+ cl_git_pass(git_config_delete_entry(cfg, "submodule.sm_changed_index.url"));
+
+ git_config_free(cfg);
+
+ cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data));
+ cl_assert_equal_i(8, data.count);
}
void test_submodule_lookup__lookup_even_with_unborn_head(void)
@@ -133,6 +151,29 @@
test_submodule_lookup__simple_lookup(); /* baseline should still pass */
}
+void test_submodule_lookup__backslashes(void)
+{
+ git_config *cfg;
+ git_submodule *sm;
+ git_repository *subrepo;
+ git_buf buf = GIT_BUF_INIT;
+ const char *backslashed_path = "..\\submod2_target";
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "submod2/.gitmodules"));
+ cl_git_pass(git_config_set_string(cfg, "submodule.sm_unchanged.url", backslashed_path));
+ git_config_free(cfg);
+
+ cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
+ cl_assert_equal_s(backslashed_path, git_submodule_url(sm));
+ cl_git_pass(git_submodule_open(&subrepo, sm));
+
+ cl_git_pass(git_submodule_resolve_url(&buf, g_repo, backslashed_path));
+
+ git_buf_free(&buf);
+ git_submodule_free(sm);
+ git_repository_free(subrepo);
+}
+
static void baseline_tests(void)
{
/* small baseline that should work even if we change the index or make