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
06f42b62
Commit
06f42b62
authored
May 26, 2016
by
Edward Thomson
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'checkout_submodules'
parents
fdf14637
c864b4ab
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
105 additions
and
10 deletions
+105
-10
docs/checkout-internals.md
+28
-1
src/checkout.c
+2
-1
src/merge.c
+1
-0
tests/checkout/typechange.c
+74
-8
No files found.
docs/checkout-internals.md
View file @
06f42b62
...
@@ -66,6 +66,8 @@ Key
...
@@ -66,6 +66,8 @@ Key
-
Bi - ignored blob (WD only)
-
Bi - ignored blob (WD only)
-
T1,T2,T3 - trees with different SHAs,
-
T1,T2,T3 - trees with different SHAs,
-
Ti - ignored tree (WD only)
-
Ti - ignored tree (WD only)
-
S1,S2 - submodules with different SHAs
-
Sd - dirty submodule (WD only)
-
x - nothing
-
x - nothing
Diff with 2 non-workdir iterators
Diff with 2 non-workdir iterators
...
@@ -162,6 +164,27 @@ Checkout From 3 Iterators (2 not workdir, 1 workdir)
...
@@ -162,6 +164,27 @@ Checkout From 3 Iterators (2 not workdir, 1 workdir)
| 35+ | T1 | T2 | x | update locally deleted tree (SAFE+MISSING) |
| 35+ | T1 | T2 | x | update locally deleted tree (SAFE+MISSING) |
| 36
*
| T1 | T2 | B1/Bi | update to tree with typechanged tree->blob conflict (F-1) |
| 36
*
| T1 | T2 | B1/Bi | update to tree with typechanged tree->blob conflict (F-1) |
| 37 | T1 | T2 | T1/T2/T3 | update to existing tree (MAYBE SAFE) |
| 37 | T1 | T2 | T1/T2/T3 | update to existing tree (MAYBE SAFE) |
| 38+ | x | S1 | x | add submodule (SAFE) |
| 39 | x | S1 | S1/Sd | independently added submodule (SUBMODULE) |
| 40
*
| x | S1 | B1 | add submodule with blob confilct (FORCEABLE) |
| 41
*
| x | S1 | T1 | add submodule with tree conflict (FORCEABLE) |
| 42 | S1 | x | S1/Sd | deleted submodule (SUBMODULE) |
| 43 | S1 | x | x | independently deleted submodule (SUBMODULE) |
| 44 | S1 | x | B1 | independently deleted submodule with added blob (SAFE+MISSING) |
| 45 | S1 | x | T1 | independently deleted submodule with added tree (SAFE+MISSING) |
| 46 | S1 | S1 | x | locally deleted submodule (SUBMODULE) |
| 47+ | S1 | S2 | x | update locally deleted submodule (SAFE) |
| 48 | S1 | S1 | S2 | locally updated submodule commit (SUBMODULE) |
| 49 | S1 | S2 | S1 | updated submodule commit (SUBMODULE) |
| 50+ | S1 | B1 | x | add blob with locally deleted submodule (SAFE+MISSING) |
| 51
*
| S1 | B1 | S1 | typechange submodule->blob (SAFE) |
| 52
*
| S1 | B1 | Sd | typechange dirty submodule->blob (SAFE!?!?) |
| 53+ | S1 | T1 | x | add tree with locally deleted submodule (SAFE+MISSING) |
| 54
*
| S1 | T1 | S1/Sd | typechange submodule->tree (MAYBE SAFE) |
| 55+ | B1 | S1 | x | add submodule with locally deleted blob (SAFE+MISSING) |
| 56
*
| B1 | S1 | B1 | typechange blob->submodule (SAFE) |
| 57+ | T1 | S1 | x | add submodule with locally deleted tree (SAFE+MISSING) |
| 58
*
| T1 | S1 | T1 | typechange tree->submodule (SAFE) |
The number is followed by ' ' if no change is needed or '+' if the case
The number is followed by ' ' if no change is needed or '+' if the case
...
@@ -176,6 +199,8 @@ There are four tiers of safe cases:
...
@@ -176,6 +199,8 @@ There are four tiers of safe cases:
content, which is unknown at this point
content, which is unknown at this point
*
FORCEABLE == conflict unless FORCE is given
*
FORCEABLE == conflict unless FORCE is given
*
DIRTY == no conflict but change is not applied unless FORCE
*
DIRTY == no conflict but change is not applied unless FORCE
*
SUBMODULE == no conflict and no change is applied unless a deleted
submodule dir is empty
Some slightly unusual circumstances:
Some slightly unusual circumstances:
...
@@ -198,7 +223,9 @@ Some slightly unusual circumstances:
...
@@ -198,7 +223,9 @@ Some slightly unusual circumstances:
cases, if baseline == target, we don't touch the workdir (it is
cases, if baseline == target, we don't touch the workdir (it is
either already right or is "dirty"). However, since this case also
either already right or is "dirty"). However, since this case also
implies that a ?/B1/x case will exist as well, it can be skipped.
implies that a ?/B1/x case will exist as well, it can be skipped.
*
41 - It's not clear how core git distinguishes this case from 39 (mode?).
*
52 - Core git makes destructive changes without any warning when the
submodule is dirty and the type changes to a blob.
Cases 3, 17, 24, 26, and 29 are all considered conflicts even though
Cases 3, 17, 24, 26, and 29 are all considered conflicts even though
none of them will require making any updates to the working directory.
none of them will require making any updates to the working directory.
src/checkout.c
View file @
06f42b62
...
@@ -482,7 +482,8 @@ static int checkout_action_with_wd(
...
@@ -482,7 +482,8 @@ static int checkout_action_with_wd(
*
action
=
CHECKOUT_ACTION_IF
(
SAFE
,
REMOVE
,
NONE
);
*
action
=
CHECKOUT_ACTION_IF
(
SAFE
,
REMOVE
,
NONE
);
break
;
break
;
case
GIT_DELTA_MODIFIED
:
/* case 16, 17, 18 (or 36 but not really) */
case
GIT_DELTA_MODIFIED
:
/* case 16, 17, 18 (or 36 but not really) */
if
(
checkout_is_workdir_modified
(
data
,
&
delta
->
old_file
,
&
delta
->
new_file
,
wd
))
if
(
wd
->
mode
!=
GIT_FILEMODE_COMMIT
&&
checkout_is_workdir_modified
(
data
,
&
delta
->
old_file
,
&
delta
->
new_file
,
wd
))
*
action
=
CHECKOUT_ACTION_IF
(
FORCE
,
UPDATE_BLOB
,
CONFLICT
);
*
action
=
CHECKOUT_ACTION_IF
(
FORCE
,
UPDATE_BLOB
,
CONFLICT
);
else
else
*
action
=
CHECKOUT_ACTION_IF
(
SAFE
,
UPDATE_BLOB
,
NONE
);
*
action
=
CHECKOUT_ACTION_IF
(
SAFE
,
UPDATE_BLOB
,
NONE
);
...
...
src/merge.c
View file @
06f42b62
...
@@ -2827,6 +2827,7 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
...
@@ -2827,6 +2827,7 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
opts
.
flags
|=
GIT_DIFF_DISABLE_PATHSPEC_MATCH
;
opts
.
flags
|=
GIT_DIFF_DISABLE_PATHSPEC_MATCH
;
opts
.
pathspec
.
count
=
merged_paths
->
length
;
opts
.
pathspec
.
count
=
merged_paths
->
length
;
opts
.
pathspec
.
strings
=
(
char
**
)
merged_paths
->
contents
;
opts
.
pathspec
.
strings
=
(
char
**
)
merged_paths
->
contents
;
opts
.
ignore_submodules
=
GIT_SUBMODULE_IGNORE_ALL
;
if
((
error
=
git_diff_index_to_workdir
(
&
wd_diff_list
,
repo
,
NULL
,
&
opts
))
<
0
)
if
((
error
=
git_diff_index_to_workdir
(
&
wd_diff_list
,
repo
,
NULL
,
&
opts
))
<
0
)
goto
done
;
goto
done
;
...
...
tests/checkout/typechange.c
View file @
06f42b62
...
@@ -6,6 +6,36 @@
...
@@ -6,6 +6,36 @@
static
git_repository
*
g_repo
=
NULL
;
static
git_repository
*
g_repo
=
NULL
;
/*
From the test repo used for this test:
--------------------------------------
This is a test repo for libgit2 where tree entries have type changes
The key types that could be found in tree entries are:
1 - GIT_FILEMODE_NEW = 0000000
2 - GIT_FILEMODE_TREE = 0040000
3 - GIT_FILEMODE_BLOB = 0100644
4 - GIT_FILEMODE_BLOB_EXECUTABLE = 0100755
5 - GIT_FILEMODE_LINK = 0120000
6 - GIT_FILEMODE_COMMIT = 0160000
I will try to have every type of transition somewhere in the history
of this repo.
Commits
-------
Initial commit - a(1) b(1) c(1) d(1) e(1)
Create content - a(1->2) b(1->3) c(1->4) d(1->5) e(1->6)
Changes #1 - a(2->3) b(3->4) c(4->5) d(5->6) e(6->2)
Changes #2 - a(3->5) b(4->6) c(5->2) d(6->3) e(2->4)
Changes #3 - a(5->3) b(6->4) c(2->5) d(3->6) e(4->2)
Changes #4 - a(3->2) b(4->3) c(5->4) d(6->5) e(2->6)
Changes #5 - a(2->1) b(3->1) c(4->1) d(5->1) e(6->1)
*/
static
const
char
*
g_typechange_oids
[]
=
{
static
const
char
*
g_typechange_oids
[]
=
{
"79b9f23e85f55ea36a472a902e875bc1121a94cb"
,
"79b9f23e85f55ea36a472a902e875bc1121a94cb"
,
"9bdb75b73836a99e3dbeea640a81de81031fdc29"
,
"9bdb75b73836a99e3dbeea640a81de81031fdc29"
,
...
@@ -21,6 +51,14 @@ static bool g_typechange_empty[] = {
...
@@ -21,6 +51,14 @@ static bool g_typechange_empty[] = {
true
,
false
,
false
,
false
,
false
,
false
,
true
,
true
true
,
false
,
false
,
false
,
false
,
false
,
true
,
true
};
};
static
const
int
g_typechange_expected_conflicts
[]
=
{
1
,
2
,
3
,
3
,
2
,
3
,
2
};
static
const
int
g_typechange_expected_untracked
[]
=
{
6
,
4
,
3
,
2
,
3
,
2
,
5
};
void
test_checkout_typechange__initialize
(
void
)
void
test_checkout_typechange__initialize
(
void
)
{
{
g_repo
=
cl_git_sandbox_init
(
"typechanges"
);
g_repo
=
cl_git_sandbox_init
(
"typechanges"
);
...
@@ -112,12 +150,7 @@ void test_checkout_typechange__checkout_typechanges_safe(void)
...
@@ -112,12 +150,7 @@ void test_checkout_typechange__checkout_typechanges_safe(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
]));
opts
.
checkout_strategy
=
GIT_CHECKOUT_FORCE
;
opts
.
checkout_strategy
=
!
i
?
GIT_CHECKOUT_FORCE
:
GIT_CHECKOUT_SAFE
;
/* There are bugs in some submodule->tree changes that prevent
* SAFE from passing here, even though the following should work:
*/
/* !i ? GIT_CHECKOUT_FORCE : GIT_CHECKOUT_SAFE; */
cl_git_pass
(
git_checkout_tree
(
g_repo
,
obj
,
&
opts
));
cl_git_pass
(
git_checkout_tree
(
g_repo
,
obj
,
&
opts
));
...
@@ -190,6 +223,35 @@ static void force_create_file(const char *file)
...
@@ -190,6 +223,35 @@ static void force_create_file(const char *file)
cl_git_rewritefile
(
file
,
"yowza!!"
);
cl_git_rewritefile
(
file
,
"yowza!!"
);
}
}
static
int
make_submodule_dirty
(
git_submodule
*
sm
,
const
char
*
name
,
void
*
payload
)
{
git_buf
submodulepath
=
GIT_BUF_INIT
;
git_buf
dirtypath
=
GIT_BUF_INIT
;
git_repository
*
submodule_repo
;
/* remove submodule directory in preparation for init and repo_init */
cl_git_pass
(
git_buf_joinpath
(
&
submodulepath
,
git_repository_workdir
(
g_repo
),
git_submodule_path
(
sm
)
));
git_futils_rmdir_r
(
git_buf_cstr
(
&
submodulepath
),
NULL
,
GIT_RMDIR_REMOVE_FILES
);
/* initialize submodule and its repository */
cl_git_pass
(
git_submodule_init
(
sm
,
1
));
cl_git_pass
(
git_submodule_repo_init
(
&
submodule_repo
,
sm
,
0
));
/* create a file in the submodule workdir to make it dirty */
cl_git_pass
(
git_buf_joinpath
(
&
dirtypath
,
git_repository_workdir
(
submodule_repo
),
"dirty"
));
force_create_file
(
git_buf_cstr
(
&
dirtypath
));
git_buf_free
(
&
dirtypath
);
git_buf_free
(
&
submodulepath
);
return
0
;
}
void
test_checkout_typechange__checkout_with_conflicts
(
void
)
void
test_checkout_typechange__checkout_with_conflicts
(
void
)
{
{
int
i
;
int
i
;
...
@@ -211,13 +273,17 @@ void test_checkout_typechange__checkout_with_conflicts(void)
...
@@ -211,13 +273,17 @@ void test_checkout_typechange__checkout_with_conflicts(void)
git_futils_rmdir_r
(
"typechanges/d"
,
NULL
,
GIT_RMDIR_REMOVE_FILES
);
git_futils_rmdir_r
(
"typechanges/d"
,
NULL
,
GIT_RMDIR_REMOVE_FILES
);
p_mkdir
(
"typechanges/d"
,
0777
);
/* intentionally empty dir */
p_mkdir
(
"typechanges/d"
,
0777
);
/* intentionally empty dir */
force_create_file
(
"typechanges/untracked"
);
force_create_file
(
"typechanges/untracked"
);
cl_git_pass
(
git_submodule_foreach
(
g_repo
,
make_submodule_dirty
,
NULL
));
opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
;
opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
;
memset
(
&
cts
,
0
,
sizeof
(
cts
));
memset
(
&
cts
,
0
,
sizeof
(
cts
));
cl_git_fail
(
git_checkout_tree
(
g_repo
,
obj
,
&
opts
));
cl_git_fail
(
git_checkout_tree
(
g_repo
,
obj
,
&
opts
));
cl_assert
(
cts
.
conflicts
>
0
);
cl_assert_equal_i
(
cts
.
conflicts
,
g_typechange_expected_conflicts
[
i
]);
cl_assert
(
cts
.
untracked
>
0
);
cl_assert_equal_i
(
cts
.
untracked
,
g_typechange_expected_untracked
[
i
]);
cl_assert_equal_i
(
cts
.
dirty
,
0
);
cl_assert_equal_i
(
cts
.
updates
,
0
);
cl_assert_equal_i
(
cts
.
ignored
,
0
);
opts
.
checkout_strategy
=
opts
.
checkout_strategy
=
GIT_CHECKOUT_FORCE
|
GIT_CHECKOUT_REMOVE_UNTRACKED
;
GIT_CHECKOUT_FORCE
|
GIT_CHECKOUT_REMOVE_UNTRACKED
;
...
...
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