mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-03 11:01:01 +00:00
checkout: add notification callback for skipped files
This commit is contained in:
parent
9ac8b113b1
commit
9e592583fc
@ -36,6 +36,21 @@ typedef struct git_checkout_opts {
|
|||||||
int file_mode; /* default is 0644 */
|
int file_mode; /* default is 0644 */
|
||||||
int file_open_flags; /* default is O_CREAT | O_TRUNC | O_WRONLY */
|
int file_open_flags; /* default is O_CREAT | O_TRUNC | O_WRONLY */
|
||||||
|
|
||||||
|
/* Optional callback to notify the consumer of files that
|
||||||
|
* haven't be checked out because a modified version of them
|
||||||
|
* exist in the working directory.
|
||||||
|
*
|
||||||
|
* When provided, this callback will be invoked when the flag
|
||||||
|
* GIT_CHECKOUT_OVERWRITE_MODIFIED isn't part of the checkout strategy.
|
||||||
|
*/
|
||||||
|
int (* skipped_notify_cb)(
|
||||||
|
const char *skipped_file,
|
||||||
|
const git_oid *blob_oid,
|
||||||
|
int file_mode,
|
||||||
|
void *payload);
|
||||||
|
|
||||||
|
void *notify_payload;
|
||||||
|
|
||||||
/* when not NULL, arrays of fnmatch pattern specifying
|
/* when not NULL, arrays of fnmatch pattern specifying
|
||||||
* which paths should be taken into account
|
* which paths should be taken into account
|
||||||
*/
|
*/
|
||||||
|
@ -155,6 +155,7 @@ static int checkout_diff_fn(
|
|||||||
{
|
{
|
||||||
struct checkout_diff_data *data;
|
struct checkout_diff_data *data;
|
||||||
int error = -1;
|
int error = -1;
|
||||||
|
git_checkout_opts *opts;
|
||||||
|
|
||||||
data = (struct checkout_diff_data *)cb_data;
|
data = (struct checkout_diff_data *)cb_data;
|
||||||
|
|
||||||
@ -164,9 +165,11 @@ static int checkout_diff_fn(
|
|||||||
if (git_buf_joinpath(data->path, git_buf_cstr(data->path), delta->new_file.path) < 0)
|
if (git_buf_joinpath(data->path, git_buf_cstr(data->path), delta->new_file.path) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
opts = data->checkout_opts;
|
||||||
|
|
||||||
switch (delta->status) {
|
switch (delta->status) {
|
||||||
case GIT_DELTA_UNTRACKED:
|
case GIT_DELTA_UNTRACKED:
|
||||||
if (!(data->checkout_opts->checkout_strategy & GIT_CHECKOUT_REMOVE_UNTRACKED))
|
if (!(opts->checkout_strategy & GIT_CHECKOUT_REMOVE_UNTRACKED))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!git__suffixcmp(delta->new_file.path, "/"))
|
if (!git__suffixcmp(delta->new_file.path, "/"))
|
||||||
@ -176,8 +179,20 @@ static int checkout_diff_fn(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GIT_DELTA_MODIFIED:
|
case GIT_DELTA_MODIFIED:
|
||||||
if (!(data->checkout_opts->checkout_strategy & GIT_CHECKOUT_OVERWRITE_MODIFIED))
|
if (!(opts->checkout_strategy & GIT_CHECKOUT_OVERWRITE_MODIFIED)) {
|
||||||
|
|
||||||
|
if ((opts->skipped_notify_cb != NULL)
|
||||||
|
&& (opts->skipped_notify_cb(
|
||||||
|
delta->new_file.path,
|
||||||
|
&delta->old_file.oid,
|
||||||
|
delta->old_file.mode,
|
||||||
|
opts->notify_payload))) {
|
||||||
|
giterr_clear();
|
||||||
|
return GIT_EUSER;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (checkout_blob(
|
if (checkout_blob(
|
||||||
data->owner,
|
data->owner,
|
||||||
@ -185,13 +200,13 @@ static int checkout_diff_fn(
|
|||||||
git_buf_cstr(data->path),
|
git_buf_cstr(data->path),
|
||||||
delta->old_file.mode,
|
delta->old_file.mode,
|
||||||
data->can_symlink,
|
data->can_symlink,
|
||||||
data->checkout_opts) < 0)
|
opts) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIT_DELTA_DELETED:
|
case GIT_DELTA_DELETED:
|
||||||
if (!(data->checkout_opts->checkout_strategy & GIT_CHECKOUT_CREATE_MISSING))
|
if (!(opts->checkout_strategy & GIT_CHECKOUT_CREATE_MISSING))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (checkout_blob(
|
if (checkout_blob(
|
||||||
@ -200,7 +215,7 @@ static int checkout_diff_fn(
|
|||||||
git_buf_cstr(data->path),
|
git_buf_cstr(data->path),
|
||||||
delta->old_file.mode,
|
delta->old_file.mode,
|
||||||
data->can_symlink,
|
data->can_symlink,
|
||||||
data->checkout_opts) < 0)
|
opts) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -378,4 +393,3 @@ int git_checkout_head(
|
|||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,3 +287,76 @@ void test_checkout_index__options_open_flags(void)
|
|||||||
|
|
||||||
test_file_contents("./testrepo/new.txt", "hi\nmy new file\n");
|
test_file_contents("./testrepo/new.txt", "hi\nmy new file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct notify_data {
|
||||||
|
const char *file;
|
||||||
|
const char *sha;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int notify_cb(
|
||||||
|
const char *skipped_file,
|
||||||
|
const git_oid *blob_oid,
|
||||||
|
int file_mode,
|
||||||
|
void *payload)
|
||||||
|
{
|
||||||
|
struct notify_data *expectations = (struct notify_data *)payload;
|
||||||
|
|
||||||
|
GIT_UNUSED(file_mode);
|
||||||
|
|
||||||
|
cl_assert_equal_s(expectations->file, skipped_file);
|
||||||
|
cl_assert_equal_i(0, git_oid_streq(blob_oid, expectations->sha));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_checkout_index__can_notify_of_skipped_files(void)
|
||||||
|
{
|
||||||
|
struct notify_data data;
|
||||||
|
|
||||||
|
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $ git ls-tree HEAD
|
||||||
|
* 100644 blob a8233120f6ad708f843d861ce2b7228ec4e3dec6 README
|
||||||
|
* 100644 blob 3697d64be941a53d4ae8f6a271e4e3fa56b022cc branch_file.txt
|
||||||
|
* 100644 blob a71586c1dfe8a71c6cbf6c129f404c5642ff31bd new.txt
|
||||||
|
*/
|
||||||
|
data.file = "new.txt";
|
||||||
|
data.sha = "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd";
|
||||||
|
|
||||||
|
g_opts.checkout_strategy = GIT_CHECKOUT_CREATE_MISSING;
|
||||||
|
g_opts.skipped_notify_cb = notify_cb;
|
||||||
|
g_opts.notify_payload = &data;
|
||||||
|
|
||||||
|
cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dont_notify_cb(
|
||||||
|
const char *skipped_file,
|
||||||
|
const git_oid *blob_oid,
|
||||||
|
int file_mode,
|
||||||
|
void *payload)
|
||||||
|
{
|
||||||
|
GIT_UNUSED(skipped_file);
|
||||||
|
GIT_UNUSED(blob_oid);
|
||||||
|
GIT_UNUSED(file_mode);
|
||||||
|
GIT_UNUSED(payload);
|
||||||
|
|
||||||
|
cl_assert(false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_checkout_index__wont_notify_of_expected_line_ending_changes(void)
|
||||||
|
{
|
||||||
|
cl_git_pass(p_unlink("./testrepo/.gitattributes"));
|
||||||
|
set_core_autocrlf_to(true);
|
||||||
|
|
||||||
|
cl_git_mkfile("./testrepo/new.txt", "my new file\r\n");
|
||||||
|
|
||||||
|
g_opts.checkout_strategy = GIT_CHECKOUT_CREATE_MISSING;
|
||||||
|
g_opts.skipped_notify_cb = dont_notify_cb;
|
||||||
|
g_opts.notify_payload = NULL;
|
||||||
|
|
||||||
|
cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user