Commit a1f4d65a by Carlos Martín Nieto

Merge pull request #2655 from ethomson/v0.21.2

More backports to 0.21
parents 5757c020 cc71348d
......@@ -46,10 +46,11 @@ after_success:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install valgrind; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline; fi
# Only watch the development branch
# Watch development and stable branches
branches:
only:
- development
- /^maint\/.*$/
# Notify development list when needed
notifications:
......
......@@ -1736,10 +1736,12 @@ static int checkout_write_merge(
checkout_conflictdata *conflict)
{
git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT,
path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT;
path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT,
in_data = GIT_BUF_INIT, out_data = GIT_BUF_INIT;
git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_result result = {0};
git_filebuf output = GIT_FILEBUF_INIT;
git_filter_list *fl = NULL;
int error = 0;
if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)
......@@ -1785,13 +1787,29 @@ static int checkout_write_merge(
(error = checkout_safe_for_update_only(git_buf_cstr(&path_workdir), result.mode)) <= 0)
goto done;
if (!data->opts.disable_filters) {
in_data.ptr = (char *)result.ptr;
in_data.size = result.len;
if ((error = git_filter_list_load(&fl, data->repo, NULL, git_buf_cstr(&path_workdir),
GIT_FILTER_TO_WORKTREE, GIT_FILTER_OPT_DEFAULT)) < 0 ||
(error = git_filter_list_apply_to_data(&out_data, fl, &in_data)) < 0)
goto done;
} else {
out_data.ptr = (char *)result.ptr;
out_data.size = result.len;
}
if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 ||
(error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 ||
(error = git_filebuf_write(&output, result.ptr, result.len)) < 0 ||
(error = git_filebuf_open(&output, git_buf_cstr(&path_workdir), GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 ||
(error = git_filebuf_write(&output, out_data.ptr, out_data.size)) < 0 ||
(error = git_filebuf_commit(&output)) < 0)
goto done;
done:
git_filter_list_free(fl);
git_buf_free(&out_data);
git_buf_free(&our_label);
git_buf_free(&their_label);
......
......@@ -767,12 +767,17 @@ static int config_readonly_open(git_config_backend *cfg, git_config_level_t leve
{
diskfile_readonly_backend *b = (diskfile_readonly_backend *) cfg;
diskfile_backend *src = b->snapshot_from;
diskfile_header *src_header = &src->header;
refcounted_strmap *src_map;
int error;
if (!src_header->readonly && (error = config_refresh(&src_header->parent)) < 0)
return error;
/* We're just copying data, don't care about the level */
GIT_UNUSED(level);
src_map = refcounted_strmap_take(&src->header);
src_map = refcounted_strmap_take(src_header);
b->header.values = src_map;
return 0;
......
......@@ -61,8 +61,12 @@ void openssl_locking_function(int mode, int n, const char *file, int line)
git_mutex_unlock(&openssl_locks[n]);
}
}
#endif
static void shutdown_ssl(void)
{
git__free(openssl_locks);
}
#endif
static void init_ssl(void)
{
......@@ -110,6 +114,8 @@ static void init_ssl(void)
CRYPTO_set_locking_callback(openssl_locking_function);
}
git__on_shutdown(shutdown_ssl);
# endif
#endif
}
......
......@@ -494,23 +494,33 @@ bool git_path_is_empty_dir(const char *path)
WIN32_FIND_DATAW findData;
HANDLE hFind = FindFirstFileW(filter_w, &findData);
/* FindFirstFile will fail if there are no children to the given
* path, which can happen if the given path is a file (and obviously
* has no children) or if the given path is an empty mount point.
* (Most directories have at least directory entries '.' and '..',
* but ridiculously another volume mounted in another drive letter's
* path space do not, and thus have nothing to enumerate.) If
* FindFirstFile fails, check if this is a directory-like thing
* (a mount point).
*/
if (hFind == INVALID_HANDLE_VALUE)
return git_path_isdir(path);
/* If the find handle was created successfully, then it's a directory */
if (hFind != INVALID_HANDLE_VALUE) {
empty = true;
do {
/* Allow the enumeration to return . and .. and still be considered
* empty. In the special case of drive roots (i.e. C:\) where . and
* .. do not occur, we can still consider the path to be an empty
* directory if there's nothing there. */
if (!git_path_is_dot_or_dotdotW(findData.cFileName)) {
empty = false;
break;
}
} while (FindNextFileW(hFind, &findData));
FindClose(hFind);
}
empty = true;
do {
/* Allow the enumeration to return . and .. and still be considered
* empty. In the special case of drive roots (i.e. C:\) where . and
* .. do not occur, we can still consider the path to be an empty
* directory if there's nothing there. */
if (!git_path_is_dot_or_dotdotW(findData.cFileName)) {
empty = false;
break;
}
} while (FindNextFileW(hFind, &findData));
FindClose(hFind);
}
return empty;
......
......@@ -1551,8 +1551,10 @@ int git_repository_head_unborn(git_repository *repo)
error = git_repository_head(&ref, repo);
git_reference_free(ref);
if (error == GIT_EUNBORNBRANCH)
if (error == GIT_EUNBORNBRANCH) {
giterr_clear();
return 1;
}
if (error < 0)
return -1;
......
......@@ -406,8 +406,9 @@ int git_tag_delete(git_repository *repo, const char *tag_name)
if (error < 0)
return error;
if ((error = git_reference_delete(tag_ref)) == 0)
git_reference_free(tag_ref);
error = git_reference_delete(tag_ref);
git_reference_free(tag_ref);
return error;
}
......
......@@ -110,6 +110,11 @@ GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
return (time_t)winTime;
}
static bool path_is_volume(wchar_t *target, size_t target_len)
{
return (target_len && wcsncmp(target, L"\\??\\Volume{", 11) == 0);
}
/* On success, returns the length, in characters, of the path stored in dest.
* On failure, returns a negative value. */
static int readlink_w(
......@@ -156,7 +161,13 @@ static int readlink_w(
goto on_error;
}
if (target_len) {
if (path_is_volume(target, target_len)) {
/* This path is a reparse point that represents another volume mounted
* at this location, it is not a symbolic link our input was canonical.
*/
errno = EINVAL;
error = -1;
} else if (target_len) {
/* The path may need to have a prefix removed. */
target_len = git_win32__canonicalize_path(target, target_len);
......
......@@ -618,3 +618,72 @@ void test_checkout_index__can_get_repo_from_index(void)
git_index_free(index);
}
static void add_conflict(void)
{
git_index *index;
git_index_entry entry;
memset(&entry, 0, sizeof(git_index_entry));
cl_git_pass(git_repository_index(&index, g_repo));
entry.mode = 0100644;
entry.path = "conflicting.txt";
git_oid_fromstr(&entry.id, "d427e0b2e138501a3d15cc376077a3631e15bd46");
entry.flags = (1 << GIT_IDXENTRY_STAGESHIFT);
cl_git_pass(git_index_add(index, &entry));
git_oid_fromstr(&entry.id, "4e886e602529caa9ab11d71f86634bd1b6e0de10");
entry.flags = (2 << GIT_IDXENTRY_STAGESHIFT);
cl_git_pass(git_index_add(index, &entry));
git_oid_fromstr(&entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
entry.flags = (3 << GIT_IDXENTRY_STAGESHIFT);
cl_git_pass(git_index_add(index, &entry));
cl_git_pass(git_index_write(index));
git_index_free(index);
}
void test_checkout_index__writes_conflict_file(void)
{
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
git_buf conflicting_buf = GIT_BUF_INIT;
add_conflict();
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
cl_git_pass(git_futils_readbuffer(&conflicting_buf, "testrepo/conflicting.txt"));
cl_assert(strcmp(conflicting_buf.ptr,
"<<<<<<< ours\n"
"this file is changed in master and branch\n"
"=======\n"
"this file is changed in branch and master\n"
">>>>>>> theirs\n") == 0);
git_buf_free(&conflicting_buf);
}
void test_checkout_index__conflicts_honor_coreautocrlf(void)
{
#ifdef GIT_WIN32
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
git_buf conflicting_buf = GIT_BUF_INIT;
cl_git_pass(p_unlink("./testrepo/.gitattributes"));
cl_repo_set_bool(g_repo, "core.autocrlf", true);
add_conflict();
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
cl_git_pass(git_futils_readbuffer(&conflicting_buf, "testrepo/conflicting.txt"));
cl_assert(strcmp(conflicting_buf.ptr,
"<<<<<<< ours\r\n"
"this file is changed in master and branch\r\n"
"=======\r\n"
"this file is changed in branch and master\r\n"
">>>>>>> theirs\r\n") == 0);
git_buf_free(&conflicting_buf);
#endif
}
......@@ -3,7 +3,7 @@
void test_config_snapshot__create_snapshot(void)
{
int32_t tmp;
git_config *cfg, *snapshot;
git_config *cfg, *snapshot, *new_snapshot;
const char *filename = "config-ext-change";
cl_git_mkfile(filename, "[old]\nvalue = 5\n");
......@@ -23,7 +23,21 @@ void test_config_snapshot__create_snapshot(void)
cl_git_pass(git_config_get_int32(&tmp, snapshot, "old.value"));
cl_assert_equal_i(5, tmp);
/* Change the value on the file itself (simulate external process) */
cl_git_mkfile(filename, "[old]\nvalue = 999\n");
cl_git_pass(git_config_snapshot(&new_snapshot, cfg));
/* New snapshot should see new value */
cl_git_pass(git_config_get_int32(&tmp, new_snapshot, "old.value"));
cl_assert_equal_i(999, tmp);
/* Old snapshot should still have the old value */
cl_git_pass(git_config_get_int32(&tmp, snapshot, "old.value"));
cl_assert_equal_i(5, tmp);
git_config_free(new_snapshot);
git_config_free(snapshot);
git_config_free(cfg);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment