mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 17:05:49 +00:00
More checkout improvements
This flips checkout back to be driven off the changes between the baseline and the target trees. This reinstates the complex code for tracking the contents of the working directory, but overall, I think the resulting logic is easier to follow.
This commit is contained in:
parent
cf20803170
commit
7e5c8a5b41
@ -9,8 +9,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "indexer.h"
|
#include "diff.h"
|
||||||
#include "strarray.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file git2/checkout.h
|
* @file git2/checkout.h
|
||||||
@ -25,27 +24,28 @@ GIT_BEGIN_DECL
|
|||||||
* Checkout behavior flags
|
* Checkout behavior flags
|
||||||
*
|
*
|
||||||
* In libgit2, the function of checkout is to update the working directory
|
* In libgit2, the function of checkout is to update the working directory
|
||||||
* to match a target tree given an expected baseline tree. It does not move
|
* to match a target tree. It does not move the HEAD commit - you do that
|
||||||
* the HEAD commit - you do that separately. Typically the expected tree is
|
* separately. To safely perform the update, checkout relies on a baseline
|
||||||
* the (to-be-moved) HEAD commit.
|
* tree (generally the current HEAD) as a reference for the unmodified
|
||||||
|
* content expected in the working directory.
|
||||||
*
|
*
|
||||||
* Checkout examines the differences between the target and expected trees
|
* Checkout examines the differences between the target tree, the baseline
|
||||||
* plus the current working directory and groups files into five categories:
|
* tree and the working directory, and groups files into five categories:
|
||||||
*
|
*
|
||||||
* 1. UNMODIFIED - Files that match in all places.
|
* 1. UNMODIFIED - Files that match in all places.
|
||||||
* 2. SAFE - Files where the working directory and the expect content match
|
* 2. SAFE - Files where the working directory and the baseline content
|
||||||
* that can be safely updated to the target.
|
* match that can be safely updated to the target.
|
||||||
* 3. DIRTY/MISSING - Files where the working directory differs from the
|
* 3. DIRTY/MISSING - Files where the working directory differs from the
|
||||||
* expected content but there is no conflicting change with the target
|
* baseline but there is no conflicting change with the target. One
|
||||||
* tree. An example is a file that doesn't exist in the working
|
* example is a file that doesn't exist in the working directory - no
|
||||||
* directory - no data would be lost as a result of writing this file.
|
* data would be lost as a result of writing this file. Which action
|
||||||
* The action to take with these files depends on the options you elect.
|
* will be taken with these files depends on the options you use.
|
||||||
* 4. CONFLICTS - Files where changes in the working directory conflicts
|
* 4. CONFLICTS - Files where changes in the working directory conflict
|
||||||
* with changes to be applied by the target. If conflicts are found,
|
* with changes to be applied by the target. If conflicts are found,
|
||||||
* they prevent any other modifications from being made (although there
|
* they prevent any other modifications from being made (although there
|
||||||
* are options to override that and force the update, of course).
|
* are options to override that and force the update, of course).
|
||||||
* 5. UNTRACKED/IGNORED - Files in the working directory that are untracked
|
* 5. UNTRACKED/IGNORED - Files in the working directory that are untracked
|
||||||
* or ignored.
|
* or ignored (i.e. only in the working directory, not the other places).
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* You control the actions checkout takes with one of four base strategies:
|
* You control the actions checkout takes with one of four base strategies:
|
||||||
@ -54,11 +54,11 @@ GIT_BEGIN_DECL
|
|||||||
* run that you can use to find conflicts, etc. if you wish.
|
* run that you can use to find conflicts, etc. if you wish.
|
||||||
*
|
*
|
||||||
* - `GIT_CHECKOUT_SAFE` is like `git checkout` and only applies changes
|
* - `GIT_CHECKOUT_SAFE` is like `git checkout` and only applies changes
|
||||||
* between the expected and target trees to files in category 2.
|
* between the baseline and target trees to files in category 2.
|
||||||
*
|
*
|
||||||
* - `GIT_CHECKOUT_SAFE_CREATE` also creates files that are missing from the
|
* - `GIT_CHECKOUT_SAFE_CREATE` also creates files that are missing from the
|
||||||
* working directory (category 3), even if there is no change between the
|
* working directory (category 3), even if there is no change between the
|
||||||
* expected and target trees for those files. See notes below on
|
* baseline and target trees for those files. See notes below on
|
||||||
* emulating `git checkout-index` for some of the subtleties of this.
|
* emulating `git checkout-index` for some of the subtleties of this.
|
||||||
*
|
*
|
||||||
* - `GIT_CHECKOUT_FORCE` is like `git checkout -f` and will update the
|
* - `GIT_CHECKOUT_FORCE` is like `git checkout -f` and will update the
|
||||||
@ -97,7 +97,7 @@ GIT_BEGIN_DECL
|
|||||||
* To emulate `git checkout`, use `GIT_CHECKOUT_SAFE` with a checkout
|
* To emulate `git checkout`, use `GIT_CHECKOUT_SAFE` with a checkout
|
||||||
* notification callback (see below) that displays information about dirty
|
* notification callback (see below) that displays information about dirty
|
||||||
* files (i.e. files that don't need an update but that no longer match the
|
* files (i.e. files that don't need an update but that no longer match the
|
||||||
* expected content). The default behavior will cancel on conflicts.
|
* baseline content). The default behavior will cancel on conflicts.
|
||||||
*
|
*
|
||||||
* To emulate `git checkout-index`, use `GIT_CHECKOUT_SAFE_CREATE` with a
|
* To emulate `git checkout-index`, use `GIT_CHECKOUT_SAFE_CREATE` with a
|
||||||
* notification callback that cancels the operation if a dirty-but-existing
|
* notification callback that cancels the operation if a dirty-but-existing
|
||||||
@ -140,6 +140,9 @@ typedef enum {
|
|||||||
/** Only update existing files, don't create new ones */
|
/** Only update existing files, don't create new ones */
|
||||||
GIT_CHECKOUT_UPDATE_ONLY = (1u << 7),
|
GIT_CHECKOUT_UPDATE_ONLY = (1u << 7),
|
||||||
|
|
||||||
|
/** Don't refresh index/config/etc before doing checkout */
|
||||||
|
GIT_CHECKOUT_NO_REFRESH = (1u << 8),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
|
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
|
||||||
*/
|
*/
|
||||||
@ -166,14 +169,14 @@ typedef enum {
|
|||||||
* receive a callback depend on the `notify_flags` value which is a
|
* receive a callback depend on the `notify_flags` value which is a
|
||||||
* combination of these flags.
|
* combination of these flags.
|
||||||
*
|
*
|
||||||
* - GIT_CHECKOUT_NOTIFY_CONFLICTS means that conflicting files that would
|
* - GIT_CHECKOUT_NOTIFY_CONFLICT means that conflicting files that would
|
||||||
* prevent the checkout from occurring will receive callbacks. If you
|
* prevent the checkout from occurring will receive callbacks. If you
|
||||||
* used GIT_CHECKOUT_ALLOW_CONFLICTS, the callbacks are still done, but
|
* used GIT_CHECKOUT_ALLOW_CONFLICTS, the callbacks are still done, but
|
||||||
* the checkout will not be blocked. The callback `status_flags` will
|
* the checkout will not be blocked. The callback `status_flags` will
|
||||||
* have both index and work tree change bits set (see `git_status_t`).
|
* have both index and work tree change bits set (see `git_status_t`).
|
||||||
*
|
*
|
||||||
* - GIT_CHECKOUT_NOTIFY_DIRTY means to notify about "dirty" files, i.e.
|
* - GIT_CHECKOUT_NOTIFY_DIRTY means to notify about "dirty" files, i.e.
|
||||||
* those that do not need to be updated but no longer match the expected
|
* those that do not need to be updated but no longer match the baseline
|
||||||
* content. Core git displays these files when checkout runs, but does
|
* content. Core git displays these files when checkout runs, but does
|
||||||
* not stop the checkout. For these, `status_flags` will have only work
|
* not stop the checkout. For these, `status_flags` will have only work
|
||||||
* tree bits set (i.e. GIT_STATUS_WT_MODIFIED, etc).
|
* tree bits set (i.e. GIT_STATUS_WT_MODIFIED, etc).
|
||||||
@ -202,11 +205,12 @@ typedef enum {
|
|||||||
* Dirty files will only have work tree flags set.
|
* Dirty files will only have work tree flags set.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GIT_CHECKOUT_NOTIFY_CONFLICTS = (1u << 0),
|
GIT_CHECKOUT_NOTIFY_NONE = 0,
|
||||||
GIT_CHECKOUT_NOTIFY_DIRTY = (1u << 1),
|
GIT_CHECKOUT_NOTIFY_CONFLICT = (1u << 0),
|
||||||
GIT_CHECKOUT_NOTIFY_UPDATED = (1u << 2),
|
GIT_CHECKOUT_NOTIFY_DIRTY = (1u << 1),
|
||||||
|
GIT_CHECKOUT_NOTIFY_UPDATED = (1u << 2),
|
||||||
GIT_CHECKOUT_NOTIFY_UNTRACKED = (1u << 3),
|
GIT_CHECKOUT_NOTIFY_UNTRACKED = (1u << 3),
|
||||||
GIT_CHECKOUT_NOTIFY_IGNORED = (1u << 4),
|
GIT_CHECKOUT_NOTIFY_IGNORED = (1u << 4),
|
||||||
} git_checkout_notify_t;
|
} git_checkout_notify_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -231,11 +235,11 @@ typedef struct git_checkout_opts {
|
|||||||
|
|
||||||
unsigned int notify_flags; /** see `git_checkout_notify_t` above */
|
unsigned int notify_flags; /** see `git_checkout_notify_t` above */
|
||||||
int (*notify_cb)(
|
int (*notify_cb)(
|
||||||
|
git_checkout_notify_t why,
|
||||||
const char *path,
|
const char *path,
|
||||||
unsigned int status_flags, /** combo of git_status_t values */
|
const git_diff_file *baseline,
|
||||||
const git_oid *index_oid,
|
const git_diff_file *target,
|
||||||
unsigned int checkout_mode,
|
const git_diff_file *workdir,
|
||||||
unsigned int workdir_mode,
|
|
||||||
void *payload);
|
void *payload);
|
||||||
void *notify_payload;
|
void *notify_payload;
|
||||||
|
|
||||||
|
1053
src/checkout.c
1053
src/checkout.c
File diff suppressed because it is too large
Load Diff
@ -10,22 +10,15 @@
|
|||||||
#include "git2/checkout.h"
|
#include "git2/checkout.h"
|
||||||
#include "iterator.h"
|
#include "iterator.h"
|
||||||
|
|
||||||
#define GIT_CHECKOUT__FREE_BASELINE (1u << 24)
|
#define GIT_CHECKOUT__NOTIFY_CONFLICT_TREE (1u << 12)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a working directory which is expected to match the contents
|
* Update the working directory to match the target iterator. The
|
||||||
* of iterator "expected", this will make the directory match the
|
* expected baseline value can be passed in via the checkout options
|
||||||
* contents of "desired" according to the rules in the checkout "opts".
|
* or else will default to the HEAD commit.
|
||||||
*
|
|
||||||
* Because the iterators for the desired and expected values were already
|
|
||||||
* created when this is invoked, if the checkout opts `paths` is in play,
|
|
||||||
* then presumably the pathspec_pfx was already computed, so it should be
|
|
||||||
* passed in to prevent reallocation.
|
|
||||||
*/
|
*/
|
||||||
extern int git_checkout__from_iterators(
|
extern int git_checkout_iterator(
|
||||||
git_iterator *desired,
|
git_iterator *target,
|
||||||
git_iterator *expected,
|
git_checkout_opts *opts);
|
||||||
git_checkout_opts *opts,
|
|
||||||
const char *pathspec_pfx);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
43
src/diff.c
43
src/diff.c
@ -164,6 +164,11 @@ static git_diff_delta *diff_delta__last_for_item(
|
|||||||
if (git_oid_cmp(&delta->new_file.oid, &item->oid) == 0)
|
if (git_oid_cmp(&delta->new_file.oid, &item->oid) == 0)
|
||||||
return delta;
|
return delta;
|
||||||
break;
|
break;
|
||||||
|
case GIT_DELTA_UNTRACKED:
|
||||||
|
if (diff->strcomp(delta->new_file.path, item->path) == 0 &&
|
||||||
|
git_oid_cmp(&delta->new_file.oid, &item->oid) == 0)
|
||||||
|
return delta;
|
||||||
|
break;
|
||||||
case GIT_DELTA_MODIFIED:
|
case GIT_DELTA_MODIFIED:
|
||||||
if (git_oid_cmp(&delta->old_file.oid, &item->oid) == 0 ||
|
if (git_oid_cmp(&delta->old_file.oid, &item->oid) == 0 ||
|
||||||
git_oid_cmp(&delta->new_file.oid, &item->oid) == 0)
|
git_oid_cmp(&delta->new_file.oid, &item->oid) == 0)
|
||||||
@ -531,14 +536,14 @@ static bool entry_is_prefixed(
|
|||||||
{
|
{
|
||||||
size_t pathlen;
|
size_t pathlen;
|
||||||
|
|
||||||
if (!prefix_item || diff->pfxcomp(prefix_item->path, item->path))
|
if (!item || diff->pfxcomp(item->path, prefix_item->path) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pathlen = strlen(item->path);
|
pathlen = strlen(prefix_item->path);
|
||||||
|
|
||||||
return (item->path[pathlen - 1] == '/' ||
|
return (prefix_item->path[pathlen - 1] == '/' ||
|
||||||
prefix_item->path[pathlen] == '\0' ||
|
item->path[pathlen] == '\0' ||
|
||||||
prefix_item->path[pathlen] == '/');
|
item->path[pathlen] == '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
static int diff_list_init_from_iterators(
|
static int diff_list_init_from_iterators(
|
||||||
@ -616,7 +621,7 @@ int git_diff__from_iterators(
|
|||||||
* instead of just generating a DELETE record
|
* instead of just generating a DELETE record
|
||||||
*/
|
*/
|
||||||
if ((diff->opts.flags & GIT_DIFF_INCLUDE_TYPECHANGE_TREES) != 0 &&
|
if ((diff->opts.flags & GIT_DIFF_INCLUDE_TYPECHANGE_TREES) != 0 &&
|
||||||
entry_is_prefixed(diff, oitem, nitem))
|
entry_is_prefixed(diff, nitem, oitem))
|
||||||
{
|
{
|
||||||
/* this entry has become a tree! convert to TYPECHANGE */
|
/* this entry has become a tree! convert to TYPECHANGE */
|
||||||
git_diff_delta *last = diff_delta__last_for_item(diff, oitem);
|
git_diff_delta *last = diff_delta__last_for_item(diff, oitem);
|
||||||
@ -624,6 +629,17 @@ int git_diff__from_iterators(
|
|||||||
last->status = GIT_DELTA_TYPECHANGE;
|
last->status = GIT_DELTA_TYPECHANGE;
|
||||||
last->new_file.mode = GIT_FILEMODE_TREE;
|
last->new_file.mode = GIT_FILEMODE_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If new_iter is a workdir iterator, then this situation
|
||||||
|
* will certainly be followed by a series of untracked items.
|
||||||
|
* Unless RECURSE_UNTRACKED_DIRS is set, skip over them...
|
||||||
|
*/
|
||||||
|
if (S_ISDIR(nitem->mode) &&
|
||||||
|
!(diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS))
|
||||||
|
{
|
||||||
|
if (git_iterator_advance(new_iter, &nitem) < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (git_iterator_advance(old_iter, &oitem) < 0)
|
if (git_iterator_advance(old_iter, &oitem) < 0)
|
||||||
@ -635,6 +651,7 @@ int git_diff__from_iterators(
|
|||||||
*/
|
*/
|
||||||
else if (cmp > 0) {
|
else if (cmp > 0) {
|
||||||
git_delta_t delta_type = GIT_DELTA_UNTRACKED;
|
git_delta_t delta_type = GIT_DELTA_UNTRACKED;
|
||||||
|
bool contains_oitem = entry_is_prefixed(diff, oitem, nitem);
|
||||||
|
|
||||||
/* check if contained in ignored parent directory */
|
/* check if contained in ignored parent directory */
|
||||||
if (git_buf_len(&ignore_prefix) &&
|
if (git_buf_len(&ignore_prefix) &&
|
||||||
@ -646,14 +663,12 @@ int git_diff__from_iterators(
|
|||||||
* it or if the user requested the contents of untracked
|
* it or if the user requested the contents of untracked
|
||||||
* directories and it is not under an ignored directory.
|
* directories and it is not under an ignored directory.
|
||||||
*/
|
*/
|
||||||
bool contains_tracked =
|
|
||||||
entry_is_prefixed(diff, nitem, oitem);
|
|
||||||
bool recurse_untracked =
|
bool recurse_untracked =
|
||||||
(delta_type == GIT_DELTA_UNTRACKED &&
|
(delta_type == GIT_DELTA_UNTRACKED &&
|
||||||
(diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS) != 0);
|
(diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS) != 0);
|
||||||
|
|
||||||
/* do not advance into directories that contain a .git file */
|
/* do not advance into directories that contain a .git file */
|
||||||
if (!contains_tracked && recurse_untracked) {
|
if (!contains_oitem && recurse_untracked) {
|
||||||
git_buf *full = NULL;
|
git_buf *full = NULL;
|
||||||
if (git_iterator_current_workdir_path(new_iter, &full) < 0)
|
if (git_iterator_current_workdir_path(new_iter, &full) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -661,7 +676,7 @@ int git_diff__from_iterators(
|
|||||||
recurse_untracked = false;
|
recurse_untracked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contains_tracked || recurse_untracked) {
|
if (contains_oitem || recurse_untracked) {
|
||||||
/* if this directory is ignored, remember it as the
|
/* if this directory is ignored, remember it as the
|
||||||
* "ignore_prefix" for processing contained items
|
* "ignore_prefix" for processing contained items
|
||||||
*/
|
*/
|
||||||
@ -707,14 +722,14 @@ int git_diff__from_iterators(
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* if we are generating TYPECHANGE records then check for that
|
/* if we are generating TYPECHANGE records then check for that
|
||||||
* instead of just generating an ADD/UNTRACKED record
|
* instead of just generating an ADDED/UNTRACKED record
|
||||||
*/
|
*/
|
||||||
if (delta_type != GIT_DELTA_IGNORED &&
|
if (delta_type != GIT_DELTA_IGNORED &&
|
||||||
(diff->opts.flags & GIT_DIFF_INCLUDE_TYPECHANGE_TREES) != 0 &&
|
(diff->opts.flags & GIT_DIFF_INCLUDE_TYPECHANGE_TREES) != 0 &&
|
||||||
entry_is_prefixed(diff, nitem, oitem))
|
contains_oitem)
|
||||||
{
|
{
|
||||||
/* this entry was a tree! convert to TYPECHANGE */
|
/* this entry was prefixed with a tree - make TYPECHANGE */
|
||||||
git_diff_delta *last = diff_delta__last_for_item(diff, oitem);
|
git_diff_delta *last = diff_delta__last_for_item(diff, nitem);
|
||||||
if (last) {
|
if (last) {
|
||||||
last->status = GIT_DELTA_TYPECHANGE;
|
last->status = GIT_DELTA_TYPECHANGE;
|
||||||
last->old_file.mode = GIT_FILEMODE_TREE;
|
last->old_file.mode = GIT_FILEMODE_TREE;
|
||||||
|
@ -352,6 +352,7 @@ int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *base;
|
const char *base;
|
||||||
|
size_t baselen;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
int error;
|
int error;
|
||||||
} futils__rmdir_data;
|
} futils__rmdir_data;
|
||||||
@ -443,9 +444,13 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
|
|||||||
|
|
||||||
static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
|
static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
|
||||||
{
|
{
|
||||||
int error = p_rmdir(path->ptr);
|
futils__rmdir_data *data = opaque;
|
||||||
|
int error;
|
||||||
|
|
||||||
GIT_UNUSED(opaque);
|
if (git_buf_len(path) <= data->baselen)
|
||||||
|
return GIT_ITEROVER;
|
||||||
|
|
||||||
|
error = p_rmdir(git_buf_cstr(path));
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
int en = errno;
|
int en = errno;
|
||||||
@ -457,7 +462,7 @@ static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
|
|||||||
giterr_clear();
|
giterr_clear();
|
||||||
error = GIT_ITEROVER;
|
error = GIT_ITEROVER;
|
||||||
} else {
|
} else {
|
||||||
futils__error_cannot_rmdir(path->ptr, NULL);
|
futils__error_cannot_rmdir(git_buf_cstr(path), NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,9 +480,10 @@ int git_futils_rmdir_r(
|
|||||||
if (git_path_join_unrooted(&fullpath, path, base, NULL) < 0)
|
if (git_path_join_unrooted(&fullpath, path, base, NULL) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
data.base = base ? base : "";
|
data.base = base ? base : "";
|
||||||
data.flags = flags;
|
data.baselen = base ? strlen(base) : 0;
|
||||||
data.error = 0;
|
data.flags = flags;
|
||||||
|
data.error = 0;
|
||||||
|
|
||||||
error = futils__rmdir_recurs_foreach(&data, &fullpath);
|
error = futils__rmdir_recurs_foreach(&data, &fullpath);
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "repository.h"
|
#include "repository.h"
|
||||||
|
|
||||||
static git_repository *g_repo;
|
static git_repository *g_repo;
|
||||||
static git_checkout_opts g_opts;
|
|
||||||
|
|
||||||
static void reset_index_to_treeish(git_object *treeish)
|
static void reset_index_to_treeish(git_object *treeish)
|
||||||
{
|
{
|
||||||
@ -25,8 +24,6 @@ void test_checkout_index__initialize(void)
|
|||||||
{
|
{
|
||||||
git_tree *tree;
|
git_tree *tree;
|
||||||
|
|
||||||
GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION);
|
|
||||||
|
|
||||||
g_repo = cl_git_sandbox_init("testrepo");
|
g_repo = cl_git_sandbox_init("testrepo");
|
||||||
|
|
||||||
cl_git_pass(git_repository_head_tree(&tree, g_repo));
|
cl_git_pass(git_repository_head_tree(&tree, g_repo));
|
||||||
@ -65,7 +62,6 @@ void test_checkout_index__cannot_checkout_a_bare_repository(void)
|
|||||||
{
|
{
|
||||||
test_checkout_index__cleanup();
|
test_checkout_index__cleanup();
|
||||||
|
|
||||||
GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION);
|
|
||||||
g_repo = cl_git_sandbox_init("testrepo.git");
|
g_repo = cl_git_sandbox_init("testrepo.git");
|
||||||
|
|
||||||
cl_git_fail(git_checkout_index(g_repo, NULL, NULL));
|
cl_git_fail(git_checkout_index(g_repo, NULL, NULL));
|
||||||
@ -73,13 +69,15 @@ void test_checkout_index__cannot_checkout_a_bare_repository(void)
|
|||||||
|
|
||||||
void test_checkout_index__can_create_missing_files(void)
|
void test_checkout_index__can_create_missing_files(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
|
||||||
cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
|
cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
|
||||||
cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
|
cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
|
||||||
cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
|
cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
test_file_contents("./testrepo/README", "hey there\n");
|
test_file_contents("./testrepo/README", "hey there\n");
|
||||||
test_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
|
test_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
|
||||||
@ -88,34 +86,37 @@ void test_checkout_index__can_create_missing_files(void)
|
|||||||
|
|
||||||
void test_checkout_index__can_remove_untracked_files(void)
|
void test_checkout_index__can_remove_untracked_files(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
|
||||||
git_futils_mkdir("./testrepo/dir/subdir/subsubdir", NULL, 0755, GIT_MKDIR_PATH);
|
git_futils_mkdir("./testrepo/dir/subdir/subsubdir", NULL, 0755, GIT_MKDIR_PATH);
|
||||||
cl_git_mkfile("./testrepo/dir/one", "one\n");
|
cl_git_mkfile("./testrepo/dir/one", "one\n");
|
||||||
cl_git_mkfile("./testrepo/dir/subdir/two", "two\n");
|
cl_git_mkfile("./testrepo/dir/subdir/two", "two\n");
|
||||||
|
|
||||||
cl_assert_equal_i(true, git_path_isdir("./testrepo/dir/subdir/subsubdir"));
|
cl_assert_equal_i(true, git_path_isdir("./testrepo/dir/subdir/subsubdir"));
|
||||||
|
|
||||||
g_opts.checkout_strategy =
|
opts.checkout_strategy =
|
||||||
GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_REMOVE_UNTRACKED;
|
GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_REMOVE_UNTRACKED;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
cl_assert_equal_i(false, git_path_isdir("./testrepo/dir"));
|
cl_assert_equal_i(false, git_path_isdir("./testrepo/dir"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_checkout_index__honor_the_specified_pathspecs(void)
|
void test_checkout_index__honor_the_specified_pathspecs(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
char *entries[] = { "*.txt" };
|
char *entries[] = { "*.txt" };
|
||||||
|
|
||||||
g_opts.paths.strings = entries;
|
opts.paths.strings = entries;
|
||||||
g_opts.paths.count = 1;
|
opts.paths.count = 1;
|
||||||
|
|
||||||
cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
|
cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
|
||||||
cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
|
cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
|
||||||
cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
|
cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
|
cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
|
||||||
test_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
|
test_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
|
||||||
@ -139,6 +140,7 @@ static void set_core_autocrlf_to(bool value)
|
|||||||
|
|
||||||
void test_checkout_index__honor_the_gitattributes_directives(void)
|
void test_checkout_index__honor_the_gitattributes_directives(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
const char *attributes =
|
const char *attributes =
|
||||||
"branch_file.txt text eol=crlf\n"
|
"branch_file.txt text eol=crlf\n"
|
||||||
"new.txt text eol=lf\n";
|
"new.txt text eol=lf\n";
|
||||||
@ -146,9 +148,9 @@ void test_checkout_index__honor_the_gitattributes_directives(void)
|
|||||||
cl_git_mkfile("./testrepo/.gitattributes", attributes);
|
cl_git_mkfile("./testrepo/.gitattributes", attributes);
|
||||||
set_core_autocrlf_to(false);
|
set_core_autocrlf_to(false);
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
test_file_contents("./testrepo/README", "hey there\n");
|
test_file_contents("./testrepo/README", "hey there\n");
|
||||||
test_file_contents("./testrepo/new.txt", "my new file\n");
|
test_file_contents("./testrepo/new.txt", "my new file\n");
|
||||||
@ -158,14 +160,15 @@ void test_checkout_index__honor_the_gitattributes_directives(void)
|
|||||||
void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void)
|
void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void)
|
||||||
{
|
{
|
||||||
#ifdef GIT_WIN32
|
#ifdef GIT_WIN32
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
const char *expected_readme_text = "hey there\r\n";
|
const char *expected_readme_text = "hey there\r\n";
|
||||||
|
|
||||||
cl_git_pass(p_unlink("./testrepo/.gitattributes"));
|
cl_git_pass(p_unlink("./testrepo/.gitattributes"));
|
||||||
set_core_autocrlf_to(true);
|
set_core_autocrlf_to(true);
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
test_file_contents("./testrepo/README", expected_readme_text);
|
test_file_contents("./testrepo/README", expected_readme_text);
|
||||||
#endif
|
#endif
|
||||||
@ -178,11 +181,13 @@ static void set_repo_symlink_handling_cap_to(bool value)
|
|||||||
|
|
||||||
void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
|
void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
|
||||||
set_repo_symlink_handling_cap_to(true);
|
set_repo_symlink_handling_cap_to(true);
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
#ifdef GIT_WIN32
|
#ifdef GIT_WIN32
|
||||||
test_file_contents("./testrepo/link_to_new.txt", "new.txt");
|
test_file_contents("./testrepo/link_to_new.txt", "new.txt");
|
||||||
@ -202,55 +207,63 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
|
|||||||
|
|
||||||
void test_checkout_index__honor_coresymlinks_setting_set_to_false(void)
|
void test_checkout_index__honor_coresymlinks_setting_set_to_false(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
|
||||||
set_repo_symlink_handling_cap_to(false);
|
set_repo_symlink_handling_cap_to(false);
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
test_file_contents("./testrepo/link_to_new.txt", "new.txt");
|
test_file_contents("./testrepo/link_to_new.txt", "new.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_checkout_index__donot_overwrite_modified_file_by_default(void)
|
void test_checkout_index__donot_overwrite_modified_file_by_default(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
|
||||||
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
|
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
|
||||||
|
|
||||||
/* set this up to not return an error code on conflicts, but it
|
/* set this up to not return an error code on conflicts, but it
|
||||||
* still will not have permission to overwrite anything...
|
* still will not have permission to overwrite anything...
|
||||||
*/
|
*/
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
test_file_contents("./testrepo/new.txt", "This isn't what's stored!");
|
test_file_contents("./testrepo/new.txt", "This isn't what's stored!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_checkout_index__can_overwrite_modified_file(void)
|
void test_checkout_index__can_overwrite_modified_file(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
|
||||||
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
|
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
test_file_contents("./testrepo/new.txt", "my new file\n");
|
test_file_contents("./testrepo/new.txt", "my new file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_checkout_index__options_disable_filters(void)
|
void test_checkout_index__options_disable_filters(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
|
||||||
cl_git_mkfile("./testrepo/.gitattributes", "*.txt text eol=crlf\n");
|
cl_git_mkfile("./testrepo/.gitattributes", "*.txt text eol=crlf\n");
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
g_opts.disable_filters = false;
|
opts.disable_filters = false;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
test_file_contents("./testrepo/new.txt", "my new file\r\n");
|
test_file_contents("./testrepo/new.txt", "my new file\r\n");
|
||||||
|
|
||||||
p_unlink("./testrepo/new.txt");
|
p_unlink("./testrepo/new.txt");
|
||||||
|
|
||||||
g_opts.disable_filters = true;
|
opts.disable_filters = true;
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
test_file_contents("./testrepo/new.txt", "my new file\n");
|
test_file_contents("./testrepo/new.txt", "my new file\n");
|
||||||
}
|
}
|
||||||
@ -258,6 +271,7 @@ void test_checkout_index__options_disable_filters(void)
|
|||||||
void test_checkout_index__options_dir_modes(void)
|
void test_checkout_index__options_dir_modes(void)
|
||||||
{
|
{
|
||||||
#ifndef GIT_WIN32
|
#ifndef GIT_WIN32
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
git_oid oid;
|
git_oid oid;
|
||||||
git_commit *commit;
|
git_commit *commit;
|
||||||
@ -267,10 +281,10 @@ void test_checkout_index__options_dir_modes(void)
|
|||||||
|
|
||||||
reset_index_to_treeish((git_object *)commit);
|
reset_index_to_treeish((git_object *)commit);
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
g_opts.dir_mode = 0701;
|
opts.dir_mode = 0701;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
cl_git_pass(p_stat("./testrepo/a", &st));
|
cl_git_pass(p_stat("./testrepo/a", &st));
|
||||||
cl_assert_equal_i(st.st_mode & 0777, 0701);
|
cl_assert_equal_i(st.st_mode & 0777, 0701);
|
||||||
@ -286,12 +300,13 @@ void test_checkout_index__options_dir_modes(void)
|
|||||||
void test_checkout_index__options_override_file_modes(void)
|
void test_checkout_index__options_override_file_modes(void)
|
||||||
{
|
{
|
||||||
#ifndef GIT_WIN32
|
#ifndef GIT_WIN32
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
g_opts.file_mode = 0700;
|
opts.file_mode = 0700;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
cl_git_pass(p_stat("./testrepo/new.txt", &st));
|
cl_git_pass(p_stat("./testrepo/new.txt", &st));
|
||||||
cl_assert_equal_i(st.st_mode & 0777, 0700);
|
cl_assert_equal_i(st.st_mode & 0777, 0700);
|
||||||
@ -300,13 +315,15 @@ void test_checkout_index__options_override_file_modes(void)
|
|||||||
|
|
||||||
void test_checkout_index__options_open_flags(void)
|
void test_checkout_index__options_open_flags(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
|
||||||
cl_git_mkfile("./testrepo/new.txt", "hi\n");
|
cl_git_mkfile("./testrepo/new.txt", "hi\n");
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
g_opts.file_open_flags = O_CREAT | O_RDWR | O_APPEND;
|
opts.file_open_flags = O_CREAT | O_RDWR | O_APPEND;
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
test_file_contents("./testrepo/new.txt", "hi\nmy new file\n");
|
test_file_contents("./testrepo/new.txt", "hi\nmy new file\n");
|
||||||
}
|
}
|
||||||
@ -316,28 +333,29 @@ struct notify_data {
|
|||||||
const char *sha;
|
const char *sha;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int notify_cb(
|
static int test_checkout_notify_cb(
|
||||||
const char *file,
|
git_checkout_notify_t why,
|
||||||
unsigned int status,
|
const char *path,
|
||||||
const git_oid *blob_oid,
|
const git_diff_file *baseline,
|
||||||
unsigned int checkout_mode,
|
const git_diff_file *target,
|
||||||
unsigned int workdir_mode,
|
const git_diff_file *workdir,
|
||||||
void *payload)
|
void *payload)
|
||||||
{
|
{
|
||||||
struct notify_data *expectations = (struct notify_data *)payload;
|
struct notify_data *expectations = (struct notify_data *)payload;
|
||||||
|
|
||||||
GIT_UNUSED(checkout_mode);
|
GIT_UNUSED(workdir);
|
||||||
GIT_UNUSED(workdir_mode);
|
|
||||||
GIT_UNUSED(status);
|
|
||||||
|
|
||||||
cl_assert_equal_s(expectations->file, file);
|
cl_assert_equal_i(GIT_CHECKOUT_NOTIFY_CONFLICT, why);
|
||||||
cl_assert_equal_i(0, git_oid_streq(blob_oid, expectations->sha));
|
cl_assert_equal_s(expectations->file, path);
|
||||||
|
cl_assert_equal_i(0, git_oid_streq(&baseline->oid, expectations->sha));
|
||||||
|
cl_assert_equal_i(0, git_oid_streq(&target->oid, expectations->sha));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_checkout_index__can_notify_of_skipped_files(void)
|
void test_checkout_index__can_notify_of_skipped_files(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
struct notify_data data;
|
struct notify_data data;
|
||||||
|
|
||||||
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
|
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
|
||||||
@ -351,28 +369,28 @@ void test_checkout_index__can_notify_of_skipped_files(void)
|
|||||||
data.file = "new.txt";
|
data.file = "new.txt";
|
||||||
data.sha = "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd";
|
data.sha = "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd";
|
||||||
|
|
||||||
g_opts.checkout_strategy =
|
opts.checkout_strategy =
|
||||||
GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS;
|
GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS;
|
||||||
g_opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICTS;
|
opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT;
|
||||||
g_opts.notify_cb = notify_cb;
|
opts.notify_cb = test_checkout_notify_cb;
|
||||||
g_opts.notify_payload = &data;
|
opts.notify_payload = &data;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dont_notify_cb(
|
static int dont_notify_cb(
|
||||||
const char *file,
|
git_checkout_notify_t why,
|
||||||
unsigned int status,
|
const char *path,
|
||||||
const git_oid *blob_oid,
|
const git_diff_file *baseline,
|
||||||
unsigned int checkout_mode,
|
const git_diff_file *target,
|
||||||
unsigned int workdir_mode,
|
const git_diff_file *workdir,
|
||||||
void *payload)
|
void *payload)
|
||||||
{
|
{
|
||||||
GIT_UNUSED(file);
|
GIT_UNUSED(why);
|
||||||
GIT_UNUSED(status);
|
GIT_UNUSED(path);
|
||||||
GIT_UNUSED(blob_oid);
|
GIT_UNUSED(baseline);
|
||||||
GIT_UNUSED(checkout_mode);
|
GIT_UNUSED(target);
|
||||||
GIT_UNUSED(workdir_mode);
|
GIT_UNUSED(workdir);
|
||||||
GIT_UNUSED(payload);
|
GIT_UNUSED(payload);
|
||||||
|
|
||||||
cl_assert(false);
|
cl_assert(false);
|
||||||
@ -382,18 +400,20 @@ static int dont_notify_cb(
|
|||||||
|
|
||||||
void test_checkout_index__wont_notify_of_expected_line_ending_changes(void)
|
void test_checkout_index__wont_notify_of_expected_line_ending_changes(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
|
||||||
cl_git_pass(p_unlink("./testrepo/.gitattributes"));
|
cl_git_pass(p_unlink("./testrepo/.gitattributes"));
|
||||||
set_core_autocrlf_to(true);
|
set_core_autocrlf_to(true);
|
||||||
|
|
||||||
cl_git_mkfile("./testrepo/new.txt", "my new file\r\n");
|
cl_git_mkfile("./testrepo/new.txt", "my new file\r\n");
|
||||||
|
|
||||||
g_opts.checkout_strategy =
|
opts.checkout_strategy =
|
||||||
GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS;
|
GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS;
|
||||||
g_opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICTS;
|
opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT;
|
||||||
g_opts.notify_cb = dont_notify_cb;
|
opts.notify_cb = dont_notify_cb;
|
||||||
g_opts.notify_payload = NULL;
|
opts.notify_payload = NULL;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkout_progress_counter(
|
static void checkout_progress_counter(
|
||||||
@ -405,18 +425,20 @@ static void checkout_progress_counter(
|
|||||||
|
|
||||||
void test_checkout_index__calls_progress_callback(void)
|
void test_checkout_index__calls_progress_callback(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
int calls = 0;
|
int calls = 0;
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
g_opts.progress_cb = checkout_progress_counter;
|
opts.progress_cb = checkout_progress_counter;
|
||||||
g_opts.progress_payload = &calls;
|
opts.progress_payload = &calls;
|
||||||
|
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
|
||||||
cl_assert(calls > 0);
|
cl_assert(calls > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_checkout_index__can_overcome_name_clashes(void)
|
void test_checkout_index__can_overcome_name_clashes(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
git_index *index;
|
git_index *index;
|
||||||
|
|
||||||
cl_git_pass(git_repository_index(&index, g_repo));
|
cl_git_pass(git_repository_index(&index, g_repo));
|
||||||
@ -440,15 +462,15 @@ void test_checkout_index__can_overcome_name_clashes(void)
|
|||||||
cl_assert(git_path_isfile("./testrepo/path1"));
|
cl_assert(git_path_isfile("./testrepo/path1"));
|
||||||
cl_assert(git_path_isfile("./testrepo/path0/file0"));
|
cl_assert(git_path_isfile("./testrepo/path0/file0"));
|
||||||
|
|
||||||
g_opts.checkout_strategy =
|
opts.checkout_strategy =
|
||||||
GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS;
|
GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS;
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, index, &opts));
|
||||||
|
|
||||||
cl_assert(git_path_isfile("./testrepo/path1"));
|
cl_assert(git_path_isfile("./testrepo/path1"));
|
||||||
cl_assert(git_path_isfile("./testrepo/path0/file0"));
|
cl_assert(git_path_isfile("./testrepo/path0/file0"));
|
||||||
|
|
||||||
g_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||||
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_pass(git_checkout_index(g_repo, index, &opts));
|
||||||
|
|
||||||
cl_assert(git_path_isfile("./testrepo/path0"));
|
cl_assert(git_path_isfile("./testrepo/path0"));
|
||||||
cl_assert(git_path_isfile("./testrepo/path1/file1"));
|
cl_assert(git_path_isfile("./testrepo/path1/file1"));
|
||||||
@ -458,17 +480,18 @@ void test_checkout_index__can_overcome_name_clashes(void)
|
|||||||
|
|
||||||
void test_checkout_index__validates_struct_version(void)
|
void test_checkout_index__validates_struct_version(void)
|
||||||
{
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
const git_error *err;
|
const git_error *err;
|
||||||
|
|
||||||
g_opts.version = 1024;
|
opts.version = 1024;
|
||||||
cl_git_fail(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_fail(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
err = giterr_last();
|
err = giterr_last();
|
||||||
cl_assert_equal_i(err->klass, GITERR_INVALID);
|
cl_assert_equal_i(err->klass, GITERR_INVALID);
|
||||||
|
|
||||||
g_opts.version = 0;
|
opts.version = 0;
|
||||||
giterr_clear();
|
giterr_clear();
|
||||||
cl_git_fail(git_checkout_index(g_repo, NULL, &g_opts));
|
cl_git_fail(git_checkout_index(g_repo, NULL, &opts));
|
||||||
|
|
||||||
err = giterr_last();
|
err = giterr_last();
|
||||||
cl_assert_equal_i(err->klass, GITERR_INVALID);
|
cl_assert_equal_i(err->klass, GITERR_INVALID);
|
||||||
|
@ -126,9 +126,10 @@ void test_checkout_tree__doesnt_write_unrequested_files_to_worktree(void)
|
|||||||
cl_git_pass(git_commit_lookup(&p_master_commit, g_repo, &master_oid));
|
cl_git_pass(git_commit_lookup(&p_master_commit, g_repo, &master_oid));
|
||||||
cl_git_pass(git_commit_lookup(&p_chomped_commit, g_repo, &chomped_oid));
|
cl_git_pass(git_commit_lookup(&p_chomped_commit, g_repo, &chomped_oid));
|
||||||
|
|
||||||
/* A GIT_CHECKOUT_DEFAULT checkout is not allowed to add any file to the
|
/* GIT_CHECKOUT_NONE should not add any file to the working tree from the
|
||||||
* working tree from the index as it is supposed to be a dry run. */
|
* index as it is supposed to be a dry run.
|
||||||
opts.checkout_strategy = GIT_CHECKOUT_DEFAULT;
|
*/
|
||||||
|
opts.checkout_strategy = GIT_CHECKOUT_NONE;
|
||||||
git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts);
|
git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts);
|
||||||
cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt"));
|
cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt"));
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,8 @@ void test_checkout_typechange__checkout_typechanges(void)
|
|||||||
|
|
||||||
for (i = 0; g_typechange_oids[i] != NULL; ++i) {
|
for (i = 0; g_typechange_oids[i] != NULL; ++i) {
|
||||||
cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i]));
|
cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i]));
|
||||||
/* fprintf(stderr, "checking out '%s'\n", g_typechange_oids[i]); */
|
|
||||||
|
/* fprintf(stderr, "---- checking out '%s' ----\n", g_typechange_oids[i]); */
|
||||||
|
|
||||||
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
|
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user