Updated to 0.23.1

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJVyJsAAAoJEKPQMr0n6UoaHEIIAILDoUvGOpVEqKyemeQ+lKAz
 hElVNcQzjSmjb4BbXbvGadtSkknqljjwrpKcRkrBam5SfetF0xkEMqhCVUHPHt+G
 OwOCm1EStToL7iCpDfUHwFp5kZPkmWo8bLBv1SWLHVPbgZpqLxfpYH2nBKX8NeQU
 a0OVEz0pGpV+q5NT9tEEtvAx1MvDmLngkbz70e+1Rjzr4ZM/mQoxJ2KenVmkwnkx
 w3YyDVZv7tKGtN1UAbjhpFMdX8JR3lAtZLccs66mpPAnlZle/DZVnBk5QyijVQC6
 +AjkGWAQUIjD4ZkuQ3jlflhKCK+//rx45LFM8KAlhg1PWALFJfWyKm/xZ1I0GpE=
 =Z7Zv
 -----END PGP SIGNATURE-----

Merge tag 'upstream/0.23.1'

Updated to 0.23.1

* tag 'upstream/0.23.1': (29 commits)
  Bump version to v0.23.1
  Stage an unregistered submodule in _add_bypath()
  filebuf: remove lockfile upon rename errors
  filebuf: failing test for leaving the lockfile when failing to rename
  Increase required version of cmake to 2.8
  Handle ssh:// and git:// urls containing a '~' character.
  Remove extra semicolon outside of a function
  Cherry-pick PR #3332: Resolve documentation warnings
  case-insensitive check for WWW-Authenticate header
  iterator: adjust unreadable-dir test to new behaviour
  iterator: skip over errors in diriter init
  Make libgit2 work on Windows Vista again
  Document git_fetch_options struct and fix typo.
  Fix macro redefinition warning
  submodule: normalize slashes in resolve_url
  submodule: add failing test for backslash in url
  Fix #3094 - improve use of portable size_t/ssize_t format specifiers.
  filter: make sure to close the stream even on error
  index: allow add_bypath to update submodules
  blob: fail to create a blob from a dir with EDIRECTORY
  ...
This commit is contained in:
Russell Sim 2015-08-11 08:48:32 +10:00
commit 028efcfb9d
60 changed files with 498 additions and 150 deletions

View File

@ -12,7 +12,7 @@
# > cmake --build . --target install # > cmake --build . --target install
PROJECT(libgit2 C) PROJECT(libgit2 C)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6) CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
CMAKE_POLICY(SET CMP0015 NEW) CMAKE_POLICY(SET CMP0015 NEW)
# Add find modules to the path # Add find modules to the path
@ -412,6 +412,7 @@ ELSE ()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
ENDIF () ENDIF ()
ADD_C_FLAG_IF_SUPPORTED(-Wdocumentation)
ADD_C_FLAG_IF_SUPPORTED(-Wno-missing-field-initializers) ADD_C_FLAG_IF_SUPPORTED(-Wno-missing-field-initializers)
ADD_C_FLAG_IF_SUPPORTED(-Wstrict-aliasing=2) ADD_C_FLAG_IF_SUPPORTED(-Wstrict-aliasing=2)
ADD_C_FLAG_IF_SUPPORTED(-Wstrict-prototypes) ADD_C_FLAG_IF_SUPPORTED(-Wstrict-prototypes)

View File

@ -88,7 +88,7 @@ Under Unix-like systems, like Linux, \*BSD and Mac OS X, libgit2 expects `pthrea
they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API
for threading. for threading.
The `libgit2` library is built using [CMake](<http://www.cmake.org>) (version 2.6 or newer) on all platforms. The `libgit2` library is built using [CMake](<http://www.cmake.org>) (version 2.8 or newer) on all platforms.
On most systems you can build the library using the following commands On most systems you can build the library using the following commands

View File

@ -143,10 +143,10 @@ int fetch(git_repository *repo, int argc, char **argv)
* network. * network.
*/ */
if (stats->local_objects > 0) { 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); stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects);
} else{ } 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); stats->indexed_objects, stats->total_objects, stats->received_bytes);
} }

View File

@ -48,6 +48,7 @@ typedef enum {
GIT_EEOF = -20, /**< Unexpected EOF */ GIT_EEOF = -20, /**< Unexpected EOF */
GIT_EINVALID = -21, /**< Invalid operation or input */ GIT_EINVALID = -21, /**< Invalid operation or input */
GIT_EUNCOMMITTED = -22, /**< Uncommitted changes in index prevented operation */ 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_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */ GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */

View File

@ -511,6 +511,14 @@ typedef enum {
GIT_REMOTE_DOWNLOAD_TAGS_ALL, GIT_REMOTE_DOWNLOAD_TAGS_ALL,
} git_remote_autotag_option_t; } 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 { typedef struct {
int version; int version;
@ -739,7 +747,7 @@ GIT_EXTERN(int) git_remote_prune_refs(const git_remote *remote);
* stored here for further processing by the caller. Always free this * stored here for further processing by the caller. Always free this
* strarray on successful return. * strarray on successful return.
* @param repo the repository in which to rename * @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 * @param new_name the new name the remote should bear
* @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code * @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code
*/ */

View File

@ -745,7 +745,7 @@ GIT_EXTERN(int) git_repository_ident(const char **name, const char **email, cons
* *
* @param repo the repository to configure * @param repo the repository to configure
* @param name the name to use for the reflog entries * @param name the name to use for the reflog entries
* @param name the email to use for the reflog entries * @param email the email to use for the reflog entries
*/ */
GIT_EXTERN(int) git_repository_set_ident(git_repository *repo, const char *name, const char *email); GIT_EXTERN(int) git_repository_set_ident(git_repository *repo, const char *name, const char *email);

View File

@ -76,7 +76,7 @@ struct git_config_backend {
* Initializes a `git_config_backend` with default values. Equivalent to * Initializes a `git_config_backend` with default values. Equivalent to
* creating an instance with GIT_CONFIG_BACKEND_INIT. * creating an instance with GIT_CONFIG_BACKEND_INIT.
* *
* @param opts the `git_config_backend` struct to initialize. * @param backend the `git_config_backend` struct to initialize.
* @param version Version of struct; pass `GIT_CONFIG_BACKEND_VERSION` * @param version Version of struct; pass `GIT_CONFIG_BACKEND_VERSION`
* @return Zero on success; -1 on failure. * @return Zero on success; -1 on failure.
*/ */

View File

@ -38,7 +38,7 @@ GIT_EXTERN(int) git_diff_print_callback__to_buf(
const git_diff_delta *delta, const git_diff_delta *delta,
const git_diff_hunk *hunk, const git_diff_hunk *hunk,
const git_diff_line *line, const git_diff_line *line,
void *payload); /*< payload must be a `git_buf *` */ void *payload); /**< payload must be a `git_buf *` */
/** /**
* Diff print callback that writes to stdio FILE handle. * Diff print callback that writes to stdio FILE handle.
@ -58,7 +58,7 @@ GIT_EXTERN(int) git_diff_print_callback__to_file_handle(
const git_diff_delta *delta, const git_diff_delta *delta,
const git_diff_hunk *hunk, const git_diff_hunk *hunk,
const git_diff_line *line, const git_diff_line *line,
void *payload); /*< payload must be a `FILE *` */ void *payload); /**< payload must be a `FILE *` */
/** /**
@ -66,8 +66,8 @@ GIT_EXTERN(int) git_diff_print_callback__to_file_handle(
*/ */
typedef struct { typedef struct {
unsigned int version; unsigned int version;
size_t stat_calls; /*< Number of stat() calls performed */ size_t stat_calls; /**< Number of stat() calls performed */
size_t oid_calculations; /*< Number of ID calculations */ size_t oid_calculations; /**< Number of ID calculations */
} git_diff_perfdata; } git_diff_perfdata;
#define GIT_DIFF_PERFDATA_VERSION 1 #define GIT_DIFF_PERFDATA_VERSION 1

View File

@ -93,7 +93,7 @@ struct git_odb_backend {
* Initializes a `git_odb_backend` with default values. Equivalent to * Initializes a `git_odb_backend` with default values. Equivalent to
* creating an instance with GIT_ODB_BACKEND_INIT. * creating an instance with GIT_ODB_BACKEND_INIT.
* *
* @param opts the `git_odb_backend` struct to initialize. * @param backend the `git_odb_backend` struct to initialize.
* @param version Version the struct; pass `GIT_ODB_BACKEND_VERSION` * @param version Version the struct; pass `GIT_ODB_BACKEND_VERSION`
* @return Zero on success; -1 on failure. * @return Zero on success; -1 on failure.
*/ */

View File

@ -175,7 +175,7 @@ struct git_refdb_backend {
* Initializes a `git_refdb_backend` with default values. Equivalent to * Initializes a `git_refdb_backend` with default values. Equivalent to
* creating an instance with GIT_REFDB_BACKEND_INIT. * creating an instance with GIT_REFDB_BACKEND_INIT.
* *
* @param opts the `git_refdb_backend` struct to initialize * @param backend the `git_refdb_backend` struct to initialize
* @param version Version of struct; pass `GIT_REFDB_BACKEND_VERSION` * @param version Version of struct; pass `GIT_REFDB_BACKEND_VERSION`
* @return Zero on success; -1 on failure. * @return Zero on success; -1 on failure.
*/ */

View File

@ -7,10 +7,10 @@
#ifndef INCLUDE_git_version_h__ #ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__ #define INCLUDE_git_version_h__
#define LIBGIT2_VERSION "0.23.0" #define LIBGIT2_VERSION "0.23.1"
#define LIBGIT2_VER_MAJOR 0 #define LIBGIT2_VER_MAJOR 0
#define LIBGIT2_VER_MINOR 23 #define LIBGIT2_VER_MINOR 23
#define LIBGIT2_VER_REVISION 0 #define LIBGIT2_VER_REVISION 1
#define LIBGIT2_VER_PATCH 0 #define LIBGIT2_VER_PATCH 0
#define LIBGIT2_SOVERSION 23 #define LIBGIT2_SOVERSION 23

View File

@ -304,21 +304,16 @@ static void blame_chunk(
} }
static int my_emit( static int my_emit(
xdfenv_t *xe, long start_a, long count_a,
xdchange_t *xscr, long start_b, long count_b,
xdemitcb_t *ecb, void *cb_data)
xdemitconf_t const *xecfg)
{ {
xdchange_t *xch = xscr; blame_chunk_cb_data *d = (blame_chunk_cb_data *)cb_data;
GIT_UNUSED(xe);
GIT_UNUSED(xecfg); blame_chunk(d->blame, d->tlno, d->plno, start_b, d->target, d->parent);
while (xch) { d->plno = start_a + count_a;
blame_chunk_cb_data *d = ecb->priv; d->tlno = start_b + count_b;
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;
}
return 0; return 0;
} }
@ -352,7 +347,7 @@ static int diff_hunks(mmfile_t file_a, mmfile_t file_b, void *cb_data)
xdemitconf_t xecfg = {0}; xdemitconf_t xecfg = {0};
xdemitcb_t ecb = {0}; xdemitcb_t ecb = {0};
xecfg.emit_func = (void(*)(void))my_emit; xecfg.hunk_func = my_emit;
ecb.priv = cb_data; ecb.priv = cb_data;
trim_common_tail(&file_a, &file_b, 0); trim_common_tail(&file_a, &file_b, 0);

View File

@ -185,6 +185,12 @@ int git_blob__create_from_paths(
(error = git_repository_odb(&odb, repo)) < 0) (error = git_repository_odb(&odb, repo)) < 0)
goto done; 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) if (out_st)
memcpy(out_st, &st, sizeof(st)); memcpy(out_st, &st, sizeof(st));

View File

@ -50,16 +50,16 @@ void git_cache_dump_stats(git_cache *cache)
if (kh_size(cache->map) == 0) if (kh_size(cache->map) == 0)
return; return;
printf("Cache %p: %d items cached, %d bytes\n", printf("Cache %p: %d items cached, %"PRIdZ" bytes\n",
cache, kh_size(cache->map), (int)cache->used_memory); cache, kh_size(cache->map), cache->used_memory);
kh_foreach_value(cache->map, object, { kh_foreach_value(cache->map, object, {
char oid_str[9]; char oid_str[9];
printf(" %s%c %s (%d)\n", printf(" %s%c %s (%"PRIuZ")\n",
git_object_type2string(object->type), git_object_type2string(object->type),
object->flags == GIT_CACHE_STORE_PARSED ? '*' : ' ', object->flags == GIT_CACHE_STORE_PARSED ? '*' : ' ',
git_oid_tostr(oid_str, sizeof(oid_str), &object->oid), git_oid_tostr(oid_str, sizeof(oid_str), &object->oid),
(int)object->size object->size
); );
}); });
} }

View File

@ -1299,8 +1299,8 @@ static int checkout_get_actions(
if (counts[CHECKOUT_ACTION__CONFLICT] > 0 && if (counts[CHECKOUT_ACTION__CONFLICT] > 0 &&
(data->strategy & GIT_CHECKOUT_ALLOW_CONFLICTS) == 0) (data->strategy & GIT_CHECKOUT_ALLOW_CONFLICTS) == 0)
{ {
giterr_set(GITERR_CHECKOUT, "%d %s checkout", giterr_set(GITERR_CHECKOUT, "%"PRIuZ" %s checkout",
(int)counts[CHECKOUT_ACTION__CONFLICT], counts[CHECKOUT_ACTION__CONFLICT],
counts[CHECKOUT_ACTION__CONFLICT] == 1 ? counts[CHECKOUT_ACTION__CONFLICT] == 1 ?
"conflict prevents" : "conflicts prevent"); "conflict prevents" : "conflicts prevent");
error = GIT_ECONFLICT; error = GIT_ECONFLICT;

View File

@ -19,7 +19,7 @@
#include "vector.h" #include "vector.h"
#include "repository.h" #include "repository.h"
GIT__USE_OIDMAP; GIT__USE_OIDMAP
/* Ported from https://github.com/git/git/blob/89dde7882f71f846ccd0359756d27bebc31108de/builtin/describe.c */ /* Ported from https://github.com/git/git/blob/89dde7882f71f846ccd0359756d27bebc31108de/builtin/describe.c */

View File

@ -101,7 +101,7 @@ void git_filebuf_cleanup(git_filebuf *file)
if (file->fd_is_open && file->fd >= 0) if (file->fd_is_open && file->fd >= 0)
p_close(file->fd); p_close(file->fd);
if (file->fd_is_open && file->path_lock && git_path_exists(file->path_lock)) if (file->created_lock && !file->did_rename && file->path_lock && git_path_exists(file->path_lock))
p_unlink(file->path_lock); p_unlink(file->path_lock);
if (file->compute_digest) { if (file->compute_digest) {
@ -258,6 +258,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags, mode_t mode
goto cleanup; goto cleanup;
} }
file->fd_is_open = true; file->fd_is_open = true;
file->created_lock = true;
/* No original path */ /* No original path */
file->path_original = NULL; file->path_original = NULL;
@ -281,6 +282,8 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags, mode_t mode
/* open the file for locking */ /* open the file for locking */
if ((error = lock_file(file, flags, mode)) < 0) if ((error = lock_file(file, flags, mode)) < 0)
goto cleanup; goto cleanup;
file->created_lock = true;
} }
return 0; return 0;
@ -340,6 +343,8 @@ int git_filebuf_commit(git_filebuf *file)
goto on_error; goto on_error;
} }
file->did_rename = true;
git_filebuf_cleanup(file); git_filebuf_cleanup(file);
return 0; return 0;

View File

@ -44,6 +44,8 @@ struct git_filebuf {
size_t buf_size, buf_pos; size_t buf_size, buf_pos;
git_file fd; git_file fd;
bool fd_is_open; bool fd_is_open;
bool created_lock;
bool did_rename;
bool do_not_buffer; bool do_not_buffer;
int last_error; int last_error;
}; };

View File

@ -947,18 +947,20 @@ int git_filter_list_stream_data(
{ {
git_vector filter_streams = GIT_VECTOR_INIT; git_vector filter_streams = GIT_VECTOR_INIT;
git_writestream *stream_start; git_writestream *stream_start;
int error = 0; int error = 0, close_error;
git_buf_sanitize(data); git_buf_sanitize(data);
if ((error = stream_list_init( if ((error = stream_list_init(&stream_start, &filter_streams, filters, target)) < 0)
&stream_start, &filter_streams, filters, target)) == 0 && goto out;
(error =
stream_start->write(stream_start, data->ptr, data->size)) == 0)
error = stream_start->close(stream_start);
error = stream_start->write(stream_start, data->ptr, data->size);
out:
close_error = stream_start->close(stream_start);
stream_list_free(&filter_streams); 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( int git_filter_list_stream_blob(

View File

@ -1228,6 +1228,45 @@ int git_index_add_frombuffer(
return 0; return 0;
} }
static int add_repo_as_submodule(git_index_entry **out, git_index *index, const char *path)
{
git_repository *sub;
git_buf abspath = GIT_BUF_INIT;
git_repository *repo = INDEX_OWNER(index);
git_reference *head;
git_index_entry *entry;
struct stat st;
int error;
if (index_entry_create(&entry, INDEX_OWNER(index), path) < 0)
return -1;
if ((error = git_buf_joinpath(&abspath, git_repository_workdir(repo), path)) < 0)
return error;
if ((error = p_stat(abspath.ptr, &st)) < 0) {
giterr_set(GITERR_OS, "failed to stat repository dir");
return -1;
}
git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode);
if ((error = git_repository_open(&sub, abspath.ptr)) < 0)
return error;
if ((error = git_repository_head(&head, sub)) < 0)
return error;
git_oid_cpy(&entry->id, git_reference_target(head));
entry->mode = GIT_FILEMODE_COMMIT;
git_reference_free(head);
git_repository_free(sub);
git_buf_free(&abspath);
*out = entry;
return 0;
}
int git_index_add_bypath(git_index *index, const char *path) int git_index_add_bypath(git_index *index, const char *path)
{ {
@ -1236,10 +1275,44 @@ int git_index_add_bypath(git_index *index, const char *path)
assert(index && path); assert(index && path);
if ((ret = index_entry_init(&entry, index, path)) < 0 || if ((ret = index_entry_init(&entry, index, path)) == 0)
(ret = index_insert(index, &entry, 1, false)) < 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; 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);
git__free(err.error_msg.message);
/*
* EEXISTS means that there is a repository at that path, but it's not known
* as a submodule. We add its HEAD as an entry and don't register it.
*/
if (ret == GIT_EEXISTS) {
if ((ret = add_repo_as_submodule(&entry, index, path)) < 0)
return ret;
if ((ret = index_insert(index, &entry, 1, false)) < 0)
return ret;
} else if (ret < 0) {
return ret;
} else {
ret = git_submodule_add_to_index(sm, false);
git_submodule_free(sm);
return ret;
}
}
/* Adding implies conflict was resolved, move conflict entries to REUC */ /* Adding implies conflict was resolved, move conflict entries to REUC */
if ((ret = index_conflict_to_reuc(index, path)) < 0 && ret != GIT_ENOTFOUND) if ((ret = index_conflict_to_reuc(index, path)) < 0 && ret != GIT_ENOTFOUND)
return ret; return ret;

View File

@ -18,7 +18,7 @@
#include "oidmap.h" #include "oidmap.h"
#include "zstream.h" #include "zstream.h"
GIT__USE_OIDMAP; GIT__USE_OIDMAP
extern git_mutex git__mwindow_mutex; extern git_mutex git__mwindow_mutex;

View File

@ -1027,8 +1027,11 @@ static int dirload_with_stat(
strncomp = (flags & GIT_PATH_DIR_IGNORE_CASE) != 0 ? strncomp = (flags & GIT_PATH_DIR_IGNORE_CASE) != 0 ?
git__strncasecmp : git__strncmp; git__strncasecmp : git__strncmp;
if ((error = git_path_diriter_init(&diriter, dirpath, flags)) < 0) /* Any error here is equivalent to the dir not existing, skip over it */
if ((error = git_path_diriter_init(&diriter, dirpath, flags)) < 0) {
error = GIT_ENOTFOUND;
goto done; goto done;
}
while ((error = git_path_diriter_next(&diriter)) == 0) { while ((error = git_path_diriter_next(&diriter)) == 0) {
if ((error = git_path_diriter_fullpath(&path, &path_len, &diriter)) < 0) if ((error = git_path_diriter_fullpath(&path, &path_len, &diriter)) < 0)

View File

@ -619,4 +619,4 @@ typedef const char *kh_cstr_t;
#define KHASH_MAP_INIT_STR(name, khval_t) \ #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) KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
#endif /* __AC_KHASH_H */ #endif /* __AC_KHASH_H */

View File

@ -79,7 +79,7 @@ int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_reposito
unsigned int i; unsigned int i;
if (length < 2) { 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; return -1;
} }
@ -185,7 +185,7 @@ int git_merge_base_octopus(git_oid *out, git_repository *repo, size_t length, co
assert(out && repo && input_array); assert(out && repo && input_array);
if (length < 2) { 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; return -1;
} }
@ -2451,7 +2451,7 @@ int git_merge__check_result(git_repository *repo, git_index *index_new)
goto done; goto done;
if ((conflicts = index_conflicts + wd_conflicts) > 0) { 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" : ""); conflicts, (conflicts != 1) ? "s" : "");
error = GIT_ECONFLICT; error = GIT_ECONFLICT;
} }

View File

@ -324,7 +324,9 @@ int openssl_connect(git_stream *stream)
SSL_set_bio(st->ssl, bio, bio); SSL_set_bio(st->ssl, bio, bio);
/* specify the host in case SNI is needed */ /* specify the host in case SNI is needed */
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
SSL_set_tlsext_host_name(st->ssl, st->host); SSL_set_tlsext_host_name(st->ssl, st->host);
#endif
if ((ret = SSL_connect(st->ssl)) <= 0) if ((ret = SSL_connect(st->ssl)) <= 0)
return ssl_set_error(st->ssl, ret); return ssl_set_error(st->ssl, ret);

View File

@ -41,7 +41,7 @@ struct pack_write_context {
git_transfer_progress *stats; git_transfer_progress *stats;
}; };
GIT__USE_OIDMAP; GIT__USE_OIDMAP
#ifdef GIT_THREADS #ifdef GIT_THREADS

View File

@ -16,8 +16,8 @@
#include <zlib.h> #include <zlib.h>
GIT__USE_OFFMAP; GIT__USE_OFFMAP
GIT__USE_OIDMAP; GIT__USE_OIDMAP
static int packfile_open(struct git_pack_file *p); static int packfile_open(struct git_pack_file *p);
static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n); static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n);

View File

@ -12,6 +12,7 @@
#include "win32/posix.h" #include "win32/posix.h"
#include "win32/buffer.h" #include "win32/buffer.h"
#include "win32/w32_util.h" #include "win32/w32_util.h"
#include "win32/version.h"
#else #else
#include <dirent.h> #include <dirent.h>
#endif #endif
@ -1085,7 +1086,7 @@ int git_path_direach(
#if defined(GIT_WIN32) && !defined(__MINGW32__) #if defined(GIT_WIN32) && !defined(__MINGW32__)
/* Using _FIND_FIRST_EX_LARGE_FETCH may increase performance in Windows 7 /* 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 #ifndef FIND_FIRST_EX_LARGE_FETCH
# define FIND_FIRST_EX_LARGE_FETCH 2 # define FIND_FIRST_EX_LARGE_FETCH 2
@ -1099,6 +1100,10 @@ int git_path_diriter_init(
git_win32_path path_filter; git_win32_path path_filter;
git_buf hack = {0}; 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); assert(diriter && path);
memset(diriter, 0, sizeof(git_path_diriter)); memset(diriter, 0, sizeof(git_path_diriter));
@ -1122,11 +1127,11 @@ int git_path_diriter_init(
diriter->handle = FindFirstFileExW( diriter->handle = FindFirstFileExW(
path_filter, path_filter,
FindExInfoBasic, is_win7_or_later ? FindExInfoBasic : FindExInfoStandard,
&diriter->current, &diriter->current,
FindExSearchNameMatch, FindExSearchNameMatch,
NULL, NULL,
FIND_FIRST_EX_LARGE_FETCH); is_win7_or_later ? FIND_FIRST_EX_LARGE_FETCH : 0);
if (diriter->handle == INVALID_HANDLE_VALUE) { if (diriter->handle == INVALID_HANDLE_VALUE) {
giterr_set(GITERR_OS, "Could not open directory '%s'", path); giterr_set(GITERR_OS, "Could not open directory '%s'", path);

View File

@ -319,7 +319,7 @@ extern int git_path_cmp(
* @param callback Function to invoke on each path. Passed the `payload` * @param callback Function to invoke on each path. Passed the `payload`
* and the buffer containing the current path. The path should not * and the buffer containing the current path. The path should not
* be modified in any way. Return non-zero to stop iteration. * be modified in any way. Return non-zero to stop iteration.
* @param state Passed to fn as the first ath. * @param payload Passed to fn as the first ath.
*/ */
extern int git_path_walk_up( extern int git_path_walk_up(
git_buf *pathbuf, git_buf *pathbuf,

View File

@ -83,7 +83,7 @@ int git_push_add_refspec(git_push *push, const char *refspec);
* Update remote tips after a push * Update remote tips after a push
* *
* @param push The push object * @param push The push object
* @param signature The identity to use when updating reflogs * @param callbacks the callbacks to use for this connection
* *
* @return 0 or an error code * @return 0 or an error code
*/ */
@ -100,6 +100,7 @@ int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks);
* order to find out which updates were accepted or rejected. * order to find out which updates were accepted or rejected.
* *
* @param push The push object * @param push The push object
* @param callbacks the callbacks to use for this connection
* *
* @return 0 or an error code * @return 0 or an error code
*/ */
@ -117,6 +118,7 @@ int git_push_finish(git_push *push, const git_remote_callbacks *callbacks);
* *
* @param push The push object * @param push The push object
* @param cb The callback to call on each object * @param cb The callback to call on each object
* @param data The payload passed to the callback
* *
* @return 0 on success, non-zero callback return value, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */

View File

@ -436,7 +436,7 @@ static int rebase_setupfiles_merge(git_rebase *rebase)
size_t i; size_t i;
int error = 0; 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) (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->onto_name)) < 0)
goto done; goto done;
@ -789,7 +789,7 @@ static int rebase_next_merge(
normalize_checkout_options_for_apply(&checkout_opts, rebase, current_commit); 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 || 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 = 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_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, NULL)) < 0 ||
(error = git_merge__check_result(rebase->repo, index)) < 0 || (error = git_merge__check_result(rebase->repo, index)) < 0 ||

View File

@ -14,7 +14,7 @@
#include "git2/revparse.h" #include "git2/revparse.h"
#include "merge.h" #include "merge.h"
GIT__USE_OIDMAP; GIT__USE_OIDMAP
git_commit_list_node *git_revwalk__commit_lookup( git_commit_list_node *git_revwalk__commit_lookup(
git_revwalk *walk, const git_oid *oid) git_revwalk *walk, const git_oid *oid)

View File

@ -770,7 +770,7 @@ static int ensure_clean_index(git_repository *repo, git_index *index)
goto done; goto done;
if (git_diff_num_deltas(index_diff) > 0) { 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)); git_diff_num_deltas(index_diff));
error = GIT_EUNCOMMITTED; error = GIT_EUNCOMMITTED;
} }

View File

@ -781,11 +781,25 @@ const char *git_submodule_url(git_submodule *submodule)
int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *url) int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *url)
{ {
int error = 0; int error = 0;
git_buf normalized = GIT_BUF_INIT;
assert(out && repo && url); assert(out && repo && url);
git_buf_sanitize(out); 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 (git_path_is_relative(url)) {
if (!(error = get_url_base(out, repo))) if (!(error = get_url_base(out, repo)))
error = git_path_apply_relative(out, url); error = git_path_apply_relative(out, url);
@ -796,6 +810,7 @@ int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *ur
error = -1; error = -1;
} }
git_buf_free(&normalized);
return error; return error;
} }
@ -1647,7 +1662,7 @@ static int submodule_load_from_config(
} else { } else {
khiter_t pos; khiter_t pos;
git_strmap *map = data->map; 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)) { if (git_strmap_valid_index(map, pos)) {
sm = git_strmap_value_at(map, pos); sm = git_strmap_value_at(map, pos);
} else { } else {

View File

@ -8,7 +8,9 @@
#include "thread-utils.h" #include "thread-utils.h"
#ifdef _WIN32 #ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
#endif
# include <windows.h> # include <windows.h>
#elif defined(hpux) || defined(__hpux) || defined(_hpux) #elif defined(hpux) || defined(__hpux) || defined(_hpux)
# include <sys/pstat.h> # include <sys/pstat.h>

View File

@ -50,6 +50,8 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
} }
repo = delim; repo = delim;
if (repo[1] == '~')
++repo;
delim = strchr(url, ':'); delim = strchr(url, ':');
if (delim == NULL) if (delim == NULL)

View File

@ -255,7 +255,7 @@ static int on_header_ready(http_subtransport *t)
GITERR_CHECK_ALLOC(t->content_type); GITERR_CHECK_ALLOC(t->content_type);
} }
} }
else if (!strcmp("WWW-Authenticate", git_buf_cstr(name))) { else if (!strcasecmp("WWW-Authenticate", git_buf_cstr(name))) {
char *dup = git__strdup(git_buf_cstr(value)); char *dup = git__strdup(git_buf_cstr(value));
GITERR_CHECK_ALLOC(dup); GITERR_CHECK_ALLOC(dup);
@ -511,7 +511,7 @@ static int write_chunk(git_stream *io, const char *buffer, size_t len)
git_buf buf = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT;
/* Chunk header */ /* Chunk header */
git_buf_printf(&buf, "%X\r\n", (unsigned)len); git_buf_printf(&buf, "%" PRIxZ "\r\n", len);
if (git_buf_oom(&buf)) if (git_buf_oom(&buf))
return -1; return -1;

View File

@ -523,7 +523,7 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca
if (len > 0xffff) { if (len > 0xffff) {
giterr_set(GITERR_NET, giterr_set(GITERR_NET,
"Tried to produce packet with invalid length %d", len); "Tried to produce packet with invalid length %" PRIuZ, len);
return -1; return -1;
} }

View File

@ -66,6 +66,8 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
if (!git__prefixcmp(url, prefix_ssh)) { if (!git__prefixcmp(url, prefix_ssh)) {
url = url + strlen(prefix_ssh); url = url + strlen(prefix_ssh);
repo = strchr(url, '/'); repo = strchr(url, '/');
if (repo && repo[1] == '~')
++repo;
} else { } else {
repo = strchr(url, ':'); repo = strchr(url, ':');
if (repo) repo++; if (repo) repo++;

View File

@ -32,14 +32,14 @@ extern "C" {
#define XDF_IGNORE_WHITESPACE (1 << 2) #define XDF_IGNORE_WHITESPACE (1 << 2)
#define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3) #define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3)
#define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 4) #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 XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE | XDF_IGNORE_WHITESPACE_AT_EOL)
#define XDL_PATCH_NORMAL '-' #define XDF_PATIENCE_DIFF (1 << 5)
#define XDL_PATCH_REVERSE '+' #define XDF_HISTOGRAM_DIFF (1 << 6)
#define XDL_PATCH_MODEMASK ((1 << 8) - 1) #define XDF_DIFF_ALGORITHM_MASK (XDF_PATIENCE_DIFF | XDF_HISTOGRAM_DIFF)
#define XDL_PATCH_IGNOREBSPACE (1 << 8) #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_FUNCNAMES (1 << 0)
#define XDL_EMIT_COMMON (1 << 1) #define XDL_EMIT_COMMON (1 << 1)
@ -88,13 +88,17 @@ typedef struct s_xdemitcb {
typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv); 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 { typedef struct s_xdemitconf {
long ctxlen; long ctxlen;
long interhunkctxlen; long interhunkctxlen;
unsigned long flags; unsigned long flags;
find_func_t find_func; find_func_t find_func;
void *find_func_priv; void *find_func_priv;
void (*emit_func)(void); xdl_emit_hunk_consume_func_t hunk_func;
} xdemitconf_t; } xdemitconf_t;
typedef struct s_bdiffparam { typedef struct s_bdiffparam {

View File

@ -328,10 +328,10 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdalgoenv_t xenv; xdalgoenv_t xenv;
diffdata_t dd1, dd2; 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); 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); return xdl_do_histogram_diff(mf1, mf2, xpp, xe);
if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) { if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) {
@ -394,6 +394,7 @@ static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1,
xch->i2 = i2; xch->i2 = i2;
xch->chg1 = chg1; xch->chg1 = chg1;
xch->chg2 = chg2; xch->chg2 = chg2;
xch->ignore = 0;
return xch; return xch;
} }
@ -538,13 +539,51 @@ void xdl_free_script(xdchange_t *xscr) {
} }
} }
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, int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdemitconf_t const *xecfg, xdemitcb_t *ecb) { xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
xdchange_t *xscr; xdchange_t *xscr;
xdfenv_t xe; xdfenv_t xe;
emit_func_t ef = xecfg->emit_func ? emit_func_t ef = xecfg->hunk_func ? xdl_call_hunk_func : xdl_emit_diff;
(emit_func_t)xecfg->emit_func : xdl_emit_diff;
if (xdl_do_diff(mf1, mf2, xpp, &xe) < 0) { if (xdl_do_diff(mf1, mf2, xpp, &xe) < 0) {
@ -558,6 +597,9 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
return -1; return -1;
} }
if (xscr) { if (xscr) {
if (xpp->flags & XDF_IGNORE_BLANK_LINES)
xdl_mark_ignorable(xscr, &xe, xpp->flags);
if (ef(&xe, xscr, ecb, xecfg) < 0) { if (ef(&xe, xscr, ecb, xecfg) < 0) {
xdl_free_script(xscr); xdl_free_script(xscr);

View File

@ -41,6 +41,7 @@ typedef struct s_xdchange {
struct s_xdchange *next; struct s_xdchange *next;
long i1, i2; long i1, i2;
long chg1, chg2; long chg1, chg2;
int ignore;
} xdchange_t; } xdchange_t;

View File

@ -56,16 +56,51 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *
/* /*
* Starting at the passed change atom, find the latest change atom to be included * Starting at the passed change atom, find the latest change atom to be included
* inside the differential hunk according to the specified configuration. * 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 *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
xdchange_t *xch, *xchp; {
xdchange_t *xch, *xchp, *lxch;
long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen; 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) /* remove ignorable changes that are too far before other changes */
if (xch->i1 - (xchp->i1 + xchp->chg1) > max_common) 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; 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 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
return xdl_emit_common(xe, xscr, ecb, xecfg); return xdl_emit_common(xe, xscr, ecb, xecfg);
for (xch = xscr; xch; xch = xche->next) { 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); s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0); s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);

View File

@ -27,7 +27,7 @@
typedef int (*emit_func_t)(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, typedef int (*emit_func_t)(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg); 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, int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg); xdemitconf_t const *xecfg);

View File

@ -258,7 +258,7 @@ static int fall_back_to_classic_diff(struct histindex *index,
int line1, int count1, int line2, int count2) int line1, int count1, int line2, int count2)
{ {
xpparam_t xpp; 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, return xdl_fall_back_diff(index->env, &xpp,
line1, count1, line2, count2); line1, count1, line2, count2);

View File

@ -245,11 +245,11 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
dest ? dest + size : NULL); dest ? dest + size : NULL);
/* Postimage from side #1 */ /* Postimage from side #1 */
if (m->mode & 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); dest ? dest + size : NULL);
/* Postimage from side #2 */ /* Postimage from side #2 */
if (m->mode & 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); dest ? dest + size : NULL);
} else } else
continue; continue;

View File

@ -288,7 +288,7 @@ static int fall_back_to_classic_diff(struct hashmap *map,
int line1, int count1, int line2, int count2) int line1, int count1, int line2, int count2)
{ {
xpparam_t xpp; 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, return xdl_fall_back_diff(map->env, &xpp,
line1, count1, line2, count2); line1, count1, line2, count2);

View File

@ -181,7 +181,7 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *)))) if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *))))
goto abort; goto abort;
if (xpp->flags & XDF_HISTOGRAM_DIFF) if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)
hbits = hsize = 0; hbits = hsize = 0;
else { else {
hbits = xdl_hashbits((unsigned int) narec); hbits = xdl_hashbits((unsigned int) narec);
@ -209,8 +209,8 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
crec->ha = hav; crec->ha = hav;
recs[nrec++] = crec; recs[nrec++] = crec;
if (!(xpp->flags & XDF_HISTOGRAM_DIFF) && if ((XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) &&
xdl_classify_record(pass, cf, rhash, hbits, crec) < 0) xdl_classify_record(pass, cf, rhash, hbits, crec) < 0)
goto abort; goto abort;
} }
} }
@ -273,16 +273,15 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
* (nrecs) will be updated correctly anyway by * (nrecs) will be updated correctly anyway by
* xdl_prepare_ctx(). * 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; enl1 = xdl_guess_lines(mf1, sample) + 1;
enl2 = xdl_guess_lines(mf2, sample) + 1; enl2 = xdl_guess_lines(mf2, sample) + 1;
if (!(xpp->flags & XDF_HISTOGRAM_DIFF) && if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF &&
xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0) { xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0)
return -1; return -1;
}
if (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) { if (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) {
@ -296,9 +295,9 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
return -1; return -1;
} }
if (!(xpp->flags & XDF_PATIENCE_DIFF) && if ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) &&
!(xpp->flags & XDF_HISTOGRAM_DIFF) && (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) &&
xdl_optimize_ctxs(&cf, &xe->xdf1, &xe->xdf2) < 0) { xdl_optimize_ctxs(&cf, &xe->xdf1, &xe->xdf2) < 0) {
xdl_free_ctx(&xe->xdf2); xdl_free_ctx(&xe->xdf2);
xdl_free_ctx(&xe->xdf1); xdl_free_ctx(&xe->xdf1);

View File

@ -120,35 +120,6 @@ void *xdl_cha_alloc(chastore_t *cha) {
return data; 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 xdl_guess_lines(mmfile_t *mf, long sample) {
long nl = 0, size, tsize = 0; long nl = 0, size, tsize = 0;
char const *data, *cur, *top; char const *data, *cur, *top;
@ -170,6 +141,19 @@ long xdl_guess_lines(mmfile_t *mf, long sample) {
return nl + 1; 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 xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
{ {
int i1, i2; int i1, i2;

View File

@ -34,6 +34,7 @@ void *xdl_cha_alloc(chastore_t *cha);
void *xdl_cha_first(chastore_t *cha); void *xdl_cha_first(chastore_t *cha);
void *xdl_cha_next(chastore_t *cha); void *xdl_cha_next(chastore_t *cha);
long xdl_guess_lines(mmfile_t *mf, long sample); 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); 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 long xdl_hash_record(char const **data, char const *top, long flags);
unsigned int xdl_hashbits(unsigned int size); unsigned int xdl_hashbits(unsigned int size);

View File

@ -4,7 +4,7 @@ void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...)
{ {
va_list arglist; 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); hunk->final_start_line_number, hunk->lines_in_hunk-1);
va_start(arglist, fmt); va_start(arglist, fmt);

View File

@ -483,8 +483,8 @@ void clar__assert_equal_file(
for (pos = 0; pos < bytes && expected_data[pos] == buf[pos]; ++pos) for (pos = 0; pos < bytes && expected_data[pos] == buf[pos]; ++pos)
/* find differing byte offset */; /* find differing byte offset */;
p_snprintf( p_snprintf(
buf, sizeof(buf), "file content mismatch at byte %d", buf, sizeof(buf), "file content mismatch at byte %"PRIdZ,
(int)(total_bytes + pos)); (ssize_t)(total_bytes + pos));
p_close(fd); p_close(fd);
clar__fail(file, line, path, buf, 1); clar__fail(file, line, path, buf, 1);
} }

View File

@ -124,3 +124,30 @@ void test_core_filebuf__umask(void)
cl_must_pass(p_unlink(test)); cl_must_pass(p_unlink(test));
} }
void test_core_filebuf__rename_error(void)
{
git_filebuf file = GIT_FILEBUF_INIT;
char *dir = "subdir", *test = "subdir/test", *test_lock = "subdir/test.lock";
int fd;
#ifndef GIT_WIN32
cl_skip();
#endif
cl_git_pass(p_mkdir(dir, 0666));
cl_git_mkfile(test, "dummy content");
fd = p_open(test, O_RDONLY);
cl_assert(fd > 0);
cl_git_pass(git_filebuf_open(&file, test, 0, 0666));
cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
cl_assert_equal_i(true, git_path_exists(test_lock));
cl_git_fail(git_filebuf_commit(&file));
p_close(fd);
git_filebuf_cleanup(&file);
cl_assert_equal_i(false, git_path_exists(test_lock));
}

48
tests/index/bypath.c Normal file
View File

@ -0,0 +1,48 @@
#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);
}
void test_index_bypath__add_submodule_unregistered(void)
{
const char *sm_name = "not-submodule";
const char *sm_head = "68e92c611b80ee1ed8f38314ff9577f0d15b2444";
const git_index_entry *entry;
cl_git_pass(git_index_add_bypath(g_idx, sm_name));
cl_assert(entry = git_index_get_bypath(g_idx, sm_name, 0));
cl_assert_equal_s(sm_head, git_oid_tostr_s(&entry->id));
cl_assert_equal_s(sm_name, entry->path);
}

View File

@ -249,3 +249,42 @@ void test_merge_files__automerge_whitespace_change(void)
git_merge_file_result_free(&result); 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);
}

View File

@ -110,7 +110,7 @@ void merge__dump_index_entries(git_vector *index_entries)
size_t i; size_t i;
const git_index_entry *index_entry; 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++) { for (i = 0; i < index_entries->length; i++) {
index_entry = index_entries->contents[i]; index_entry = index_entries->contents[i];

View File

@ -928,7 +928,7 @@ void test_repo_iterator__fs2(void)
git_iterator_free(i); git_iterator_free(i);
} }
void test_repo_iterator__fs_preserves_error(void) void test_repo_iterator__unreadable_dir(void)
{ {
git_iterator *i; git_iterator *i;
const git_index_entry *e; const git_index_entry *e;
@ -951,10 +951,6 @@ void test_repo_iterator__fs_preserves_error(void)
cl_git_pass(git_iterator_advance(&e, i)); /* a */ cl_git_pass(git_iterator_advance(&e, i)); /* a */
cl_git_fail(git_iterator_advance(&e, i)); /* b */ cl_git_fail(git_iterator_advance(&e, i)); /* b */
cl_assert(giterr_last());
cl_assert(giterr_last()->message != NULL);
/* skip 'c/' empty directory */
cl_git_pass(git_iterator_advance(&e, i)); /* d */
cl_assert_equal_i(GIT_ITEROVER, git_iterator_advance(&e, i)); cl_assert_equal_i(GIT_ITEROVER, git_iterator_advance(&e, i));
cl_must_pass(p_chmod("empty_standard_repo/r/b", 0777)); cl_must_pass(p_chmod("empty_standard_repo/r/b", 0777));

View File

@ -334,16 +334,18 @@ void test_revert_workdir__again_after_edit_two(void)
cl_assert(merge_test_index(repo_index, merge_index_entries, 3)); cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
cl_git_pass(git_futils_readbuffer(&diff_buf, "revert/file.txt")); cl_git_pass(git_futils_readbuffer(&diff_buf, "revert/file.txt"));
cl_assert(strcmp(diff_buf.ptr, "a\n" \ cl_assert_equal_s(
"<<<<<<< HEAD\n" \ "a\n" \
"=======\n" \ "<<<<<<< HEAD\n" \
"a\n" \ "=======\n" \
">>>>>>> parent of 97e52d5... Revert me\n" \ "a\n" \
"a\n" \ ">>>>>>> parent of 97e52d5... Revert me\n" \
"a\n" \ "a\n" \
"a\n" \ "a\n" \
"a\n" \ "a\n" \
"ab\n") == 0); "a\n" \
"ab",
diff_buf.ptr);
git_commit_free(revert_commit); git_commit_free(revert_commit);
git_commit_free(head_commit); git_commit_free(head_commit);

View File

@ -4,6 +4,7 @@
#include "submodule_helpers.h" #include "submodule_helpers.h"
#include "config/config_helpers.h" #include "config/config_helpers.h"
#include "fileops.h" #include "fileops.h"
#include "repository.h"
static git_repository *g_repo = NULL; static git_repository *g_repo = NULL;

View File

@ -1,6 +1,7 @@
#include "clar_libgit2.h" #include "clar_libgit2.h"
#include "submodule_helpers.h" #include "submodule_helpers.h"
#include "git2/sys/repository.h" #include "git2/sys/repository.h"
#include "repository.h"
#include "fileops.h" #include "fileops.h"
static git_repository *g_repo = NULL; static git_repository *g_repo = NULL;
@ -103,10 +104,27 @@ static int sm_lookup_cb(git_submodule *sm, const char *name, void *payload)
void test_submodule_lookup__foreach(void) void test_submodule_lookup__foreach(void)
{ {
git_config *cfg;
sm_lookup_data data; sm_lookup_data data;
memset(&data, 0, sizeof(data)); memset(&data, 0, sizeof(data));
cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data)); cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data));
cl_assert_equal_i(8, data.count); 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) void test_submodule_lookup__lookup_even_with_unborn_head(void)
@ -133,6 +151,29 @@ void test_submodule_lookup__lookup_even_with_missing_index(void)
test_submodule_lookup__simple_lookup(); /* baseline should still pass */ 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) static void baseline_tests(void)
{ {
/* small baseline that should work even if we change the index or make /* small baseline that should work even if we change the index or make