Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
bf8dd3f5
Commit
bf8dd3f5
authored
Nov 14, 2014
by
Pierre-Olivier Latour
Committed by
Edward Thomson
May 11, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added git_stash_apply() and git_stash_pop() APIs
parent
9cdd6578
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
651 additions
and
4 deletions
+651
-4
AUTHORS
+1
-0
include/git2/stash.h
+64
-4
src/stash.c
+371
-0
tests/stash/apply.c
+215
-0
No files found.
AUTHORS
View file @
bf8dd3f5
...
...
@@ -49,6 +49,7 @@ Microsoft Corporation
Olivier Ramonat
Peter Drahoš
Pierre Habouzit
Pierre-Olivier Latour
Przemyslaw Pawelczyk
Ramsay Jones
Robert G. Jakabosky
...
...
include/git2/stash.h
View file @
bf8dd3f5
...
...
@@ -70,6 +70,47 @@ GIT_EXTERN(int) git_stash_save(
const
char
*
message
,
unsigned
int
flags
);
typedef
enum
{
GIT_APPLY_DEFAULT
=
0
,
/* Try to reinstate not only the working tree's changes,
* but also the index's ones.
*/
GIT_APPLY_REINSTATE_INDEX
=
(
1
<<
0
),
}
git_apply_flags
;
/**
* Apply a single stashed state from the stash list.
*
* If any untracked or ignored file saved in the stash already exist in the
* workdir, the function will return GIT_EEXISTS and both the workdir and index
* will be left untouched.
*
* If local changes in the workdir would be overwritten when applying
* modifications saved in the stash, the function will return GIT_EMERGECONFLICT
* and the index will be left untouched. The workdir files will be left
* unmodified as well but restored untracked or ignored files that were saved
* in the stash will be left around in the workdir.
*
* If passing the GIT_APPLY_REINSTATE_INDEX flag and there would be conflicts
* when reinstating the index, the function will return GIT_EUNMERGED and both
* the workdir and index will be left untouched.
*
* @param repo The owning repository.
*
* @param index The position within the stash list. 0 points to the
* most recent stashed state.
*
* @param flags Flags to control the applying process. (see GIT_APPLY_* above)
*
* @return 0 on success, GIT_ENOTFOUND if there's no stashed state for the given
* index, or error code. (see details above)
*/
GIT_EXTERN
(
int
)
git_stash_apply
(
git_repository
*
repo
,
size_t
index
,
unsigned
int
flags
);
/**
* This is a callback function you can provide to iterate over all the
* stashed states that will be invoked per entry.
...
...
@@ -79,7 +120,7 @@ GIT_EXTERN(int) git_stash_save(
* @param message The stash message.
* @param stash_id The commit oid of the stashed state.
* @param payload Extra parameter to callback function.
* @return 0 to continue iterating or non-zero to stop
* @return 0 to continue iterating or non-zero to stop
.
*/
typedef
int
(
*
git_stash_cb
)(
size_t
index
,
...
...
@@ -99,7 +140,7 @@ typedef int (*git_stash_cb)(
*
* @param payload Extra parameter to callback function.
*
* @return 0 on success, non-zero callback return value, or error code
* @return 0 on success, non-zero callback return value, or error code
.
*/
GIT_EXTERN
(
int
)
git_stash_foreach
(
git_repository
*
repo
,
...
...
@@ -114,13 +155,32 @@ GIT_EXTERN(int) git_stash_foreach(
* @param index The position within the stash list. 0 points to the
* most recent stashed state.
*
* @return 0 on success, or error code
* @return 0 on success, GIT_ENOTFOUND if there's no stashed state for the given
* index, or error code.
*/
GIT_EXTERN
(
int
)
git_stash_drop
(
git_repository
*
repo
,
size_t
index
);
/**
* Apply a single stashed state from the stash list and remove it from the list
* if successful.
*
* @param repo The owning repository.
*
* @param index The position within the stash list. 0 points to the
* most recent stashed state.
*
* @param flags Flags to control the applying process. (see GIT_APPLY_* above)
*
* @return 0 on success, GIT_ENOTFOUND if there's no stashed state for the given
* index, or error code. (see git_stash_apply() above for details)
*/
GIT_EXTERN
(
int
)
git_stash_pop
(
git_repository
*
repo
,
size_t
index
,
unsigned
int
flags
);
/** @} */
GIT_END_DECL
#endif
src/stash.c
View file @
bf8dd3f5
...
...
@@ -16,6 +16,7 @@
#include "git2/checkout.h"
#include "git2/index.h"
#include "git2/transaction.h"
#include "git2/merge.h"
#include "signature.h"
static
int
create_error
(
int
error
,
const
char
*
msg
)
...
...
@@ -553,6 +554,363 @@ cleanup:
return
error
;
}
static
int
retrieve_stash_commit
(
git_commit
**
commit
,
git_repository
*
repo
,
size_t
index
)
{
git_reference
*
stash
=
NULL
;
git_reflog
*
reflog
=
NULL
;
int
error
;
size_t
max
;
const
git_reflog_entry
*
entry
;
if
((
error
=
git_reference_lookup
(
&
stash
,
repo
,
GIT_REFS_STASH_FILE
))
<
0
)
goto
cleanup
;
if
((
error
=
git_reflog_read
(
&
reflog
,
repo
,
GIT_REFS_STASH_FILE
))
<
0
)
goto
cleanup
;
max
=
git_reflog_entrycount
(
reflog
);
if
(
index
>
max
-
1
)
{
error
=
GIT_ENOTFOUND
;
giterr_set
(
GITERR_STASH
,
"No stashed state at position %"
PRIuZ
,
index
);
goto
cleanup
;
}
entry
=
git_reflog_entry_byindex
(
reflog
,
index
);
if
((
error
=
git_commit_lookup
(
commit
,
repo
,
git_reflog_entry_id_new
(
entry
)))
<
0
)
goto
cleanup
;
cleanup:
git_reference_free
(
stash
);
git_reflog_free
(
reflog
);
return
error
;
}
static
int
retrieve_stash_trees
(
git_tree
**
out_stash_tree
,
git_tree
**
out_base_tree
,
git_tree
**
out_index_tree
,
git_tree
**
out_index_parent_tree
,
git_tree
**
out_untracked_tree
,
git_commit
*
stash_commit
)
{
git_tree
*
stash_tree
=
NULL
;
git_commit
*
base_commit
=
NULL
;
git_tree
*
base_tree
=
NULL
;
git_commit
*
index_commit
=
NULL
;
git_tree
*
index_tree
=
NULL
;
git_commit
*
index_parent_commit
=
NULL
;
git_tree
*
index_parent_tree
=
NULL
;
git_commit
*
untracked_commit
=
NULL
;
git_tree
*
untracked_tree
=
NULL
;
int
error
;
if
((
error
=
git_commit_tree
(
&
stash_tree
,
stash_commit
))
<
0
)
goto
cleanup
;
if
((
error
=
git_commit_parent
(
&
base_commit
,
stash_commit
,
0
))
<
0
)
goto
cleanup
;
if
((
error
=
git_commit_tree
(
&
base_tree
,
base_commit
))
<
0
)
goto
cleanup
;
if
((
error
=
git_commit_parent
(
&
index_commit
,
stash_commit
,
1
))
<
0
)
goto
cleanup
;
if
((
error
=
git_commit_tree
(
&
index_tree
,
index_commit
))
<
0
)
goto
cleanup
;
if
((
error
=
git_commit_parent
(
&
index_parent_commit
,
index_commit
,
0
))
<
0
)
goto
cleanup
;
if
((
error
=
git_commit_tree
(
&
index_parent_tree
,
index_parent_commit
))
<
0
)
goto
cleanup
;
if
(
git_commit_parentcount
(
stash_commit
)
==
3
)
{
if
((
error
=
git_commit_parent
(
&
untracked_commit
,
stash_commit
,
2
))
<
0
)
goto
cleanup
;
if
((
error
=
git_commit_tree
(
&
untracked_tree
,
untracked_commit
))
<
0
)
goto
cleanup
;
}
*
out_stash_tree
=
stash_tree
;
*
out_base_tree
=
base_tree
;
*
out_index_tree
=
index_tree
;
*
out_index_parent_tree
=
index_parent_tree
;
*
out_untracked_tree
=
untracked_tree
;
cleanup:
git_commit_free
(
untracked_commit
);
git_commit_free
(
index_parent_commit
);
git_commit_free
(
index_commit
);
git_commit_free
(
base_commit
);
if
(
error
<
0
)
{
git_tree_free
(
stash_tree
);
git_tree_free
(
base_tree
);
git_tree_free
(
index_tree
);
git_tree_free
(
index_parent_tree
);
git_tree_free
(
untracked_tree
);
}
return
error
;
}
static
int
apply_index
(
git_tree
**
unstashed_tree
,
git_repository
*
repo
,
git_tree
*
start_index_tree
,
git_tree
*
index_parent_tree
,
git_tree
*
index_tree
)
{
git_index
*
unstashed_index
=
NULL
;
git_merge_options
options
=
GIT_MERGE_OPTIONS_INIT
;
int
error
;
git_oid
oid
;
if
((
error
=
git_merge_trees
(
&
unstashed_index
,
repo
,
index_parent_tree
,
start_index_tree
,
index_tree
,
&
options
))
<
0
)
goto
cleanup
;
if
((
error
=
git_index_write_tree_to
(
&
oid
,
unstashed_index
,
repo
))
<
0
)
goto
cleanup
;
if
((
error
=
git_tree_lookup
(
unstashed_tree
,
repo
,
&
oid
))
<
0
)
goto
cleanup
;
cleanup:
git_index_free
(
unstashed_index
);
return
error
;
}
static
int
apply_untracked
(
git_repository
*
repo
,
git_tree
*
untracked_tree
)
{
git_checkout_options
options
=
GIT_CHECKOUT_OPTIONS_INIT
;
size_t
i
,
count
;
unsigned
int
status
;
int
error
;
for
(
i
=
0
,
count
=
git_tree_entrycount
(
untracked_tree
);
i
<
count
;
++
i
)
{
const
git_tree_entry
*
entry
=
git_tree_entry_byindex
(
untracked_tree
,
i
);
const
char
*
path
=
git_tree_entry_name
(
entry
);
error
=
git_status_file
(
&
status
,
repo
,
path
);
if
(
!
error
)
{
giterr_set
(
GITERR_STASH
,
"Untracked or ignored file '%s' already exists"
,
path
);
return
GIT_EEXISTS
;
}
}
/*
The untracked tree only contains the untracked / ignores files so checking
it out would remove all other files in the workdir. Since git_checkout_tree()
does not have a mode to leave removed files alone, we emulate it by checking
out files from the untracked tree one by one.
*/
options
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_DONT_UPDATE_INDEX
;
options
.
paths
.
count
=
1
;
for
(
i
=
0
,
count
=
git_tree_entrycount
(
untracked_tree
);
i
<
count
;
++
i
)
{
const
git_tree_entry
*
entry
=
git_tree_entry_byindex
(
untracked_tree
,
i
);
const
char
*
name
=
git_tree_entry_name
(
entry
);
options
.
paths
.
strings
=
(
char
**
)
&
name
;
if
((
error
=
git_checkout_tree
(
repo
,
(
git_object
*
)
untracked_tree
,
&
options
))
<
0
)
return
error
;
}
return
0
;
}
static
int
checkout_modified_notify_callback
(
git_checkout_notify_t
why
,
const
char
*
path
,
const
git_diff_file
*
baseline
,
const
git_diff_file
*
target
,
const
git_diff_file
*
workdir
,
void
*
payload
)
{
unsigned
int
status
;
int
error
;
GIT_UNUSED
(
why
);
GIT_UNUSED
(
baseline
);
GIT_UNUSED
(
target
);
GIT_UNUSED
(
workdir
);
if
((
error
=
git_status_file
(
&
status
,
payload
,
path
))
<
0
)
return
error
;
if
(
status
&
GIT_STATUS_WT_MODIFIED
)
{
giterr_set
(
GITERR_STASH
,
"Local changes to '%s' would be overwritten"
,
path
);
return
GIT_EMERGECONFLICT
;
}
return
0
;
}
static
int
apply_modified
(
int
*
has_conflicts
,
git_repository
*
repo
,
git_tree
*
base_tree
,
git_tree
*
start_index_tree
,
git_tree
*
stash_tree
,
unsigned
int
flags
)
{
git_index
*
index
=
NULL
;
git_merge_options
merge_options
=
GIT_MERGE_OPTIONS_INIT
;
git_checkout_options
checkout_options
=
GIT_CHECKOUT_OPTIONS_INIT
;
int
error
;
if
((
error
=
git_merge_trees
(
&
index
,
repo
,
base_tree
,
start_index_tree
,
stash_tree
,
&
merge_options
))
<
0
)
goto
cleanup
;
checkout_options
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_ALLOW_CONFLICTS
;
if
((
flags
&
GIT_APPLY_REINSTATE_INDEX
)
&&
!
git_index_has_conflicts
(
index
))
{
/* No need to update the index if it will be overridden later on */
checkout_options
.
checkout_strategy
|=
GIT_CHECKOUT_DONT_UPDATE_INDEX
;
}
checkout_options
.
notify_flags
=
GIT_CHECKOUT_NOTIFY_CONFLICT
;
checkout_options
.
notify_cb
=
checkout_modified_notify_callback
;
checkout_options
.
notify_payload
=
repo
;
checkout_options
.
our_label
=
"Updated upstream"
;
checkout_options
.
their_label
=
"Stashed changes"
;
if
((
error
=
git_checkout_index
(
repo
,
index
,
&
checkout_options
))
<
0
)
goto
cleanup
;
*
has_conflicts
=
git_index_has_conflicts
(
index
);
cleanup:
git_index_free
(
index
);
return
error
;
}
static
int
unstage_modified_files
(
git_repository
*
repo
,
git_index
*
repo_index
,
git_tree
*
unstashed_tree
,
git_tree
*
start_index_tree
)
{
git_diff
*
diff
=
NULL
;
git_diff_options
options
=
GIT_DIFF_OPTIONS_INIT
;
size_t
i
,
count
;
int
error
;
if
(
unstashed_tree
)
{
if
((
error
=
git_index_read_tree
(
repo_index
,
unstashed_tree
))
<
0
)
goto
cleanup
;
}
else
{
options
.
flags
=
GIT_DIFF_FORCE_BINARY
;
if
((
error
=
git_diff_tree_to_index
(
&
diff
,
repo
,
start_index_tree
,
repo_index
,
&
options
))
<
0
)
goto
cleanup
;
/*
This behavior is not 100% similar to "git stash apply" as the latter uses
"git-read-tree --reset {treeish}" which preserves the stat()s from the
index instead of replacing them with the tree ones for identical files.
*/
if
((
error
=
git_index_read_tree
(
repo_index
,
start_index_tree
))
<
0
)
goto
cleanup
;
for
(
i
=
0
,
count
=
git_diff_num_deltas
(
diff
);
i
<
count
;
++
i
)
{
const
git_diff_delta
*
delta
=
git_diff_get_delta
(
diff
,
i
);
if
(
delta
->
status
==
GIT_DELTA_ADDED
)
{
if
((
error
=
git_index_add_bypath
(
repo_index
,
delta
->
new_file
.
path
))
<
0
)
goto
cleanup
;
}
}
}
cleanup:
git_diff_free
(
diff
);
return
error
;
}
int
git_stash_apply
(
git_repository
*
repo
,
size_t
index
,
unsigned
int
flags
)
{
git_commit
*
stash_commit
=
NULL
;
git_tree
*
stash_tree
=
NULL
;
git_tree
*
base_tree
=
NULL
;
git_tree
*
index_tree
=
NULL
;
git_tree
*
index_parent_tree
=
NULL
;
git_tree
*
untracked_tree
=
NULL
;
git_index
*
repo_index
=
NULL
;
git_tree
*
start_index_tree
=
NULL
;
git_tree
*
unstashed_tree
=
NULL
;
int
has_conflicts
;
int
error
;
/* Retrieve commit corresponding to the given stash */
if
((
error
=
retrieve_stash_commit
(
&
stash_commit
,
repo
,
index
))
<
0
)
goto
cleanup
;
/* Retrieve all trees in the stash */
if
((
error
=
retrieve_stash_trees
(
&
stash_tree
,
&
base_tree
,
&
index_tree
,
&
index_parent_tree
,
&
untracked_tree
,
stash_commit
))
<
0
)
goto
cleanup
;
/* Load repo index */
if
((
error
=
git_repository_index
(
&
repo_index
,
repo
))
<
0
)
goto
cleanup
;
/* Create tree from index */
if
((
error
=
build_tree_from_index
(
&
start_index_tree
,
repo_index
))
<
0
)
goto
cleanup
;
/* Restore index if required */
if
((
flags
&
GIT_APPLY_REINSTATE_INDEX
)
&&
git_oid_cmp
(
git_tree_id
(
base_tree
),
git_tree_id
(
index_tree
))
&&
git_oid_cmp
(
git_tree_id
(
start_index_tree
),
git_tree_id
(
index_tree
)))
{
if
((
error
=
apply_index
(
&
unstashed_tree
,
repo
,
start_index_tree
,
index_parent_tree
,
index_tree
))
<
0
)
goto
cleanup
;
}
/* If applicable, restore untracked / ignored files in workdir */
if
(
untracked_tree
)
{
if
((
error
=
apply_untracked
(
repo
,
untracked_tree
))
<
0
)
goto
cleanup
;
}
/* Restore modified files in workdir */
if
((
error
=
apply_modified
(
&
has_conflicts
,
repo
,
base_tree
,
start_index_tree
,
stash_tree
,
flags
))
<
0
)
goto
cleanup
;
/* Unstage modified files from index unless there were merge conflicts */
if
(
!
has_conflicts
&&
(
error
=
unstage_modified_files
(
repo
,
repo_index
,
unstashed_tree
,
start_index_tree
))
<
0
)
goto
cleanup
;
/* Write updated index */
if
((
error
=
git_index_write
(
repo_index
))
<
0
)
goto
cleanup
;
cleanup:
git_tree_free
(
unstashed_tree
);
git_tree_free
(
start_index_tree
);
git_index_free
(
repo_index
);
git_tree_free
(
untracked_tree
);
git_tree_free
(
index_parent_tree
);
git_tree_free
(
index_tree
);
git_tree_free
(
base_tree
);
git_tree_free
(
stash_tree
);
git_commit_free
(
stash_commit
);
return
error
;
}
int
git_stash_foreach
(
git_repository
*
repo
,
git_stash_cb
callback
,
...
...
@@ -651,3 +1009,16 @@ cleanup:
git_reflog_free
(
reflog
);
return
error
;
}
int
git_stash_pop
(
git_repository
*
repo
,
size_t
index
,
unsigned
int
flags
)
{
int
error
;
if
((
error
=
git_stash_apply
(
repo
,
index
,
flags
))
<
0
)
return
error
;
return
git_stash_drop
(
repo
,
index
);
}
tests/stash/apply.c
0 → 100644
View file @
bf8dd3f5
#include "clar_libgit2.h"
#include "fileops.h"
#include "stash_helpers.h"
static
git_signature
*
signature
;
static
git_repository
*
repo
;
static
git_index
*
repo_index
;
void
test_stash_apply__initialize
(
void
)
{
git_oid
oid
;
cl_git_pass
(
git_signature_new
(
&
signature
,
"nulltoken"
,
"emeric.fermas@gmail.com"
,
1323847743
,
60
));
/* Wed Dec 14 08:29:03 2011 +0100 */
cl_git_pass
(
git_repository_init
(
&
repo
,
"stash"
,
0
));
cl_git_pass
(
git_repository_index
(
&
repo_index
,
repo
));
cl_git_mkfile
(
"stash/what"
,
"hello
\n
"
);
cl_git_mkfile
(
"stash/how"
,
"small
\n
"
);
cl_git_mkfile
(
"stash/who"
,
"world
\n
"
);
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
"what"
));
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
"how"
));
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
"who"
));
cl_repo_commit_from_index
(
NULL
,
repo
,
signature
,
0
,
"Initial commit"
);
cl_git_rewritefile
(
"stash/what"
,
"goodbye
\n
"
);
cl_git_rewritefile
(
"stash/who"
,
"funky world
\n
"
);
cl_git_mkfile
(
"stash/when"
,
"tomorrow
\n
"
);
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
"who"
));
/* Pre-stash state */
assert_status
(
repo
,
"what"
,
GIT_STATUS_WT_MODIFIED
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_INDEX_MODIFIED
);
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
cl_git_pass
(
git_stash_save
(
&
oid
,
repo
,
signature
,
NULL
,
GIT_STASH_INCLUDE_UNTRACKED
));
/* Post-stash state */
assert_status
(
repo
,
"what"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"when"
,
GIT_ENOTFOUND
);
}
void
test_stash_apply__cleanup
(
void
)
{
git_signature_free
(
signature
);
signature
=
NULL
;
git_index_free
(
repo_index
);
repo_index
=
NULL
;
git_repository_free
(
repo
);
repo
=
NULL
;
cl_git_pass
(
git_futils_rmdir_r
(
"stash"
,
NULL
,
GIT_RMDIR_REMOVE_FILES
));
cl_fixture_cleanup
(
"sorry-it-is-a-non-bare-only-party"
);
}
void
test_stash_apply__with_default
(
void
)
{
cl_git_pass
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_DEFAULT
));
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
0
);
assert_status
(
repo
,
"what"
,
GIT_STATUS_WT_MODIFIED
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_WT_MODIFIED
);
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
}
void
test_stash_apply__with_reinstate_index
(
void
)
{
cl_git_pass
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_REINSTATE_INDEX
));
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
0
);
assert_status
(
repo
,
"what"
,
GIT_STATUS_WT_MODIFIED
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_INDEX_MODIFIED
);
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
}
void
test_stash_apply__conflict_index_with_default
(
void
)
{
const
git_index_entry
*
ancestor
;
const
git_index_entry
*
our
;
const
git_index_entry
*
their
;
cl_git_rewritefile
(
"stash/who"
,
"nothing
\n
"
);
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
"who"
));
cl_git_pass
(
git_index_write
(
repo_index
));
cl_git_pass
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_DEFAULT
));
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
1
);
assert_status
(
repo
,
"what"
,
GIT_STATUS_INDEX_MODIFIED
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
cl_git_pass
(
git_index_conflict_get
(
&
ancestor
,
&
our
,
&
their
,
repo_index
,
"who"
));
/* unmerged */
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
}
void
test_stash_apply__conflict_index_with_reinstate_index
(
void
)
{
cl_git_rewritefile
(
"stash/who"
,
"nothing
\n
"
);
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
"who"
));
cl_git_pass
(
git_index_write
(
repo_index
));
cl_git_fail_with
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_REINSTATE_INDEX
),
GIT_EUNMERGED
);
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
0
);
assert_status
(
repo
,
"what"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_INDEX_MODIFIED
);
assert_status
(
repo
,
"when"
,
GIT_ENOTFOUND
);
}
void
test_stash_apply__conflict_untracked_with_default
(
void
)
{
cl_git_mkfile
(
"stash/when"
,
"nothing
\n
"
);
cl_git_fail_with
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_DEFAULT
),
GIT_EEXISTS
);
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
0
);
assert_status
(
repo
,
"what"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
}
void
test_stash_apply__conflict_untracked_with_reinstate_index
(
void
)
{
cl_git_mkfile
(
"stash/when"
,
"nothing
\n
"
);
cl_git_fail_with
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_REINSTATE_INDEX
),
GIT_EEXISTS
);
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
0
);
assert_status
(
repo
,
"what"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
}
void
test_stash_apply__conflict_workdir_with_default
(
void
)
{
cl_git_rewritefile
(
"stash/what"
,
"ciao
\n
"
);
cl_git_fail_with
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_DEFAULT
),
GIT_EMERGECONFLICT
);
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
0
);
assert_status
(
repo
,
"what"
,
GIT_STATUS_WT_MODIFIED
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
}
void
test_stash_apply__conflict_workdir_with_reinstate_index
(
void
)
{
cl_git_rewritefile
(
"stash/what"
,
"ciao
\n
"
);
cl_git_fail_with
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_REINSTATE_INDEX
),
GIT_EMERGECONFLICT
);
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
0
);
assert_status
(
repo
,
"what"
,
GIT_STATUS_WT_MODIFIED
);
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
}
void
test_stash_apply__conflict_commit_with_default
(
void
)
{
const
git_index_entry
*
ancestor
;
const
git_index_entry
*
our
;
const
git_index_entry
*
their
;
cl_git_rewritefile
(
"stash/what"
,
"ciao
\n
"
);
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
"what"
));
cl_repo_commit_from_index
(
NULL
,
repo
,
signature
,
0
,
"Other commit"
);
cl_git_pass
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_DEFAULT
));
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
1
);
cl_git_pass
(
git_index_conflict_get
(
&
ancestor
,
&
our
,
&
their
,
repo_index
,
"what"
));
/* unmerged */
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_INDEX_MODIFIED
);
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
}
void
test_stash_apply__conflict_commit_with_reinstate_index
(
void
)
{
const
git_index_entry
*
ancestor
;
const
git_index_entry
*
our
;
const
git_index_entry
*
their
;
cl_git_rewritefile
(
"stash/what"
,
"ciao
\n
"
);
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
"what"
));
cl_repo_commit_from_index
(
NULL
,
repo
,
signature
,
0
,
"Other commit"
);
cl_git_pass
(
git_stash_apply
(
repo
,
0
,
GIT_APPLY_REINSTATE_INDEX
));
cl_assert_equal_i
(
git_index_has_conflicts
(
repo_index
),
1
);
cl_git_pass
(
git_index_conflict_get
(
&
ancestor
,
&
our
,
&
their
,
repo_index
,
"what"
));
/* unmerged */
assert_status
(
repo
,
"how"
,
GIT_STATUS_CURRENT
);
assert_status
(
repo
,
"who"
,
GIT_STATUS_INDEX_MODIFIED
);
assert_status
(
repo
,
"when"
,
GIT_STATUS_WT_NEW
);
}
void
test_stash_apply__pop
(
void
)
{
cl_git_pass
(
git_stash_pop
(
repo
,
0
,
GIT_APPLY_DEFAULT
));
cl_git_fail_with
(
git_stash_pop
(
repo
,
0
,
GIT_APPLY_DEFAULT
),
GIT_ENOTFOUND
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment