Hash :
ad9a921b
Author :
Date :
2012-11-08T17:05:07
Rework checkout with new strategy options This is a major reworking of checkout strategy options. The checkout code is now sensitive to the contents of the HEAD tree and the new options allow you to update the working tree so that it will match the index content only when it previously matched the contents of the HEAD. This allows you to, for example, to distinguish between removing files that are in the HEAD but not in the index, vs just removing all untracked files. Because of various corner cases that arise, etc., this required some additional capabilities in rmdir and other utility functions. This includes the beginnings of an implementation of code to read a partial tree into the index based on a pathspec, but that is not enabled because of the possibility of creating conflicting index entries.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
#include "clar_libgit2.h"
#include "git2/clone.h"
#include "repository.h"
CL_IN_CATEGORY("network")
#define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository"
#define LIVE_EMPTYREPO_URL "git://github.com/libgit2/TestEmptyRepository"
static git_repository *g_repo;
void test_clone_network__initialize(void)
{
g_repo = NULL;
}
static void cleanup_repository(void *path)
{
if (g_repo)
git_repository_free(g_repo);
cl_fixture_cleanup((const char *)path);
}
void test_clone_network__network_full(void)
{
git_remote *origin;
cl_set_cleanup(&cleanup_repository, "./test2");
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./test2", NULL, NULL, NULL));
cl_assert(!git_repository_is_bare(g_repo));
cl_git_pass(git_remote_load(&origin, g_repo, "origin"));
git_remote_free(origin);
}
void test_clone_network__network_bare(void)
{
git_remote *origin;
cl_set_cleanup(&cleanup_repository, "./test");
cl_git_pass(git_clone_bare(&g_repo, LIVE_REPO_URL, "./test", NULL, NULL));
cl_assert(git_repository_is_bare(g_repo));
cl_git_pass(git_remote_load(&origin, g_repo, "origin"));
git_remote_free(origin);
}
void test_clone_network__cope_with_already_existing_directory(void)
{
cl_set_cleanup(&cleanup_repository, "./foo");
p_mkdir("./foo", GIT_DIR_MODE);
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL, NULL));
git_repository_free(g_repo); g_repo = NULL;
}
void test_clone_network__empty_repository(void)
{
git_reference *head;
cl_set_cleanup(&cleanup_repository, "./empty");
cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./empty", NULL, NULL, NULL));
cl_assert_equal_i(true, git_repository_is_empty(g_repo));
cl_assert_equal_i(true, git_repository_head_orphan(g_repo));
cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE));
cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
cl_assert_equal_s("refs/heads/master", git_reference_target(head));
git_reference_free(head);
}
void test_clone_network__can_prevent_the_checkout_of_a_standard_repo(void)
{
git_buf path = GIT_BUF_INIT;
cl_set_cleanup(&cleanup_repository, "./no-checkout");
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./no-checkout", NULL, NULL, NULL));
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&path)));
git_buf_free(&path);
}
static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload)
{
bool *was_called = (bool*)payload;
GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot);
(*was_called) = true;
}
static void fetch_progress(const git_transfer_progress *stats, void *payload)
{
bool *was_called = (bool*)payload;
GIT_UNUSED(stats);
(*was_called) = true;
}
void test_clone_network__can_checkout_a_cloned_repo(void)
{
git_checkout_opts opts = {0};
git_buf path = GIT_BUF_INIT;
git_reference *head;
bool checkout_progress_cb_was_called = false,
fetch_progress_cb_was_called = false;
opts.checkout_strategy = GIT_CHECKOUT_UPDATE_UNMODIFIED;
opts.progress_cb = &checkout_progress;
opts.progress_payload = &checkout_progress_cb_was_called;
cl_set_cleanup(&cleanup_repository, "./default-checkout");
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./default-checkout",
&fetch_progress, &fetch_progress_cb_was_called, &opts));
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));
cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
cl_assert_equal_s("refs/heads/master", git_reference_target(head));
cl_assert_equal_i(true, checkout_progress_cb_was_called);
cl_assert_equal_i(true, fetch_progress_cb_was_called);
git_reference_free(head);
git_buf_free(&path);
}