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
5d669f0a
Commit
5d669f0a
authored
Jun 21, 2013
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1665 from arrbee/checkout-target-directory
Add target directory to checkout options
parents
00197c34
d4f98ba4
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
211 additions
and
19 deletions
+211
-19
include/git2/checkout.h
+2
-0
src/checkout.c
+45
-13
src/iterator.c
+8
-4
src/iterator.h
+13
-2
tests-clar/checkout/index.c
+99
-0
tests-clar/checkout/tree.c
+44
-0
No files found.
include/git2/checkout.h
View file @
5d669f0a
...
...
@@ -236,6 +236,8 @@ typedef struct git_checkout_opts {
git_strarray
paths
;
git_tree
*
baseline
;
/** expected content of workdir, defaults to HEAD */
const
char
*
target_directory
;
/** alternative checkout path to workdir */
}
git_checkout_opts
;
#define GIT_CHECKOUT_OPTS_VERSION 1
...
...
src/checkout.c
View file @
5d669f0a
...
...
@@ -858,7 +858,7 @@ static int checkout_submodule(
return
0
;
if
((
error
=
git_futils_mkdir
(
file
->
path
,
git_repository_workdir
(
data
->
repo
)
,
file
->
path
,
data
->
opts
.
target_directory
,
data
->
opts
.
dir_mode
,
GIT_MKDIR_PATH
))
<
0
)
return
error
;
...
...
@@ -1030,7 +1030,7 @@ static int checkout_deferred_remove(git_repository *repo, const char *path)
{
#if 0
int error = git_futils_rmdir_r(
path,
git_repository_workdir(repo)
, GIT_RMDIR_EMPTY_PARENTS);
path,
data->opts.target_directory
, GIT_RMDIR_EMPTY_PARENTS);
if (error == GIT_ENOTFOUND) {
error = 0;
...
...
@@ -1163,7 +1163,8 @@ static int checkout_data_init(
return
-
1
;
}
if
((
error
=
git_repository__ensure_not_bare
(
repo
,
"checkout"
))
<
0
)
if
((
!
proposed
||
!
proposed
->
target_directory
)
&&
(
error
=
git_repository__ensure_not_bare
(
repo
,
"checkout"
))
<
0
)
return
error
;
data
->
repo
=
repo
;
...
...
@@ -1176,6 +1177,13 @@ static int checkout_data_init(
else
memmove
(
&
data
->
opts
,
proposed
,
sizeof
(
git_checkout_opts
));
if
(
!
data
->
opts
.
target_directory
)
data
->
opts
.
target_directory
=
git_repository_workdir
(
repo
);
else
if
(
!
git_path_isdir
(
data
->
opts
.
target_directory
)
&&
(
error
=
git_futils_mkdir
(
data
->
opts
.
target_directory
,
NULL
,
GIT_DIR_MODE
,
GIT_MKDIR_VERIFY_DIR
))
<
0
)
goto
cleanup
;
/* refresh config and index content unless NO_REFRESH is given */
if
((
data
->
opts
.
checkout_strategy
&
GIT_CHECKOUT_NO_REFRESH
)
==
0
)
{
git_config
*
cfg
;
...
...
@@ -1238,7 +1246,8 @@ static int checkout_data_init(
if
((
error
=
git_vector_init
(
&
data
->
removes
,
0
,
git__strcmp_cb
))
<
0
||
(
error
=
git_pool_init
(
&
data
->
pool
,
1
,
0
))
<
0
||
(
error
=
git_buf_puts
(
&
data
->
path
,
git_repository_workdir
(
repo
)))
<
0
)
(
error
=
git_buf_puts
(
&
data
->
path
,
data
->
opts
.
target_directory
))
<
0
||
(
error
=
git_path_to_dir
(
&
data
->
path
))
<
0
)
goto
cleanup
;
data
->
workdir_len
=
git_buf_len
(
&
data
->
path
);
...
...
@@ -1286,11 +1295,13 @@ int git_checkout_iterator(
GIT_ITERATOR_IGNORE_CASE
:
GIT_ITERATOR_DONT_IGNORE_CASE
;
if
((
error
=
git_iterator_reset
(
target
,
data
.
pfx
,
data
.
pfx
))
<
0
||
(
error
=
git_iterator_for_workdir
(
&
workdir
,
data
.
repo
,
iterflags
|
GIT_ITERATOR_DONT_AUTOEXPAND
,
(
error
=
git_iterator_for_workdir_ext
(
&
workdir
,
data
.
repo
,
data
.
opts
.
target_directory
,
iterflags
|
GIT_ITERATOR_DONT_AUTOEXPAND
,
data
.
pfx
,
data
.
pfx
))
<
0
||
(
error
=
git_iterator_for_tree
(
&
baseline
,
data
.
opts
.
baseline
,
iterflags
,
data
.
pfx
,
data
.
pfx
))
<
0
)
&
baseline
,
data
.
opts
.
baseline
,
iterflags
,
data
.
pfx
,
data
.
pfx
))
<
0
)
goto
cleanup
;
/* Should not have case insensitivity mismatch */
...
...
@@ -1358,8 +1369,19 @@ int git_checkout_index(
int
error
;
git_iterator
*
index_i
;
if
((
error
=
git_repository__ensure_not_bare
(
repo
,
"checkout index"
))
<
0
)
return
error
;
if
(
!
index
&&
!
repo
)
{
giterr_set
(
GITERR_CHECKOUT
,
"Must provide either repository or index to checkout"
);
return
-
1
;
}
if
(
index
&&
repo
&&
git_index_owner
(
index
)
!=
repo
)
{
giterr_set
(
GITERR_CHECKOUT
,
"Index to checkout does not match repository"
);
return
-
1
;
}
if
(
!
repo
)
repo
=
git_index_owner
(
index
);
if
(
!
index
&&
(
error
=
git_repository_index__weakptr
(
&
index
,
repo
))
<
0
)
return
error
;
...
...
@@ -1383,8 +1405,19 @@ int git_checkout_tree(
git_tree
*
tree
=
NULL
;
git_iterator
*
tree_i
=
NULL
;
if
((
error
=
git_repository__ensure_not_bare
(
repo
,
"checkout tree"
))
<
0
)
return
error
;
if
(
!
treeish
&&
!
repo
)
{
giterr_set
(
GITERR_CHECKOUT
,
"Must provide either repository or tree to checkout"
);
return
-
1
;
}
if
(
treeish
&&
repo
&&
git_object_owner
(
treeish
)
!=
repo
)
{
giterr_set
(
GITERR_CHECKOUT
,
"Object to checkout does not match repository"
);
return
-
1
;
}
if
(
!
repo
)
repo
=
git_object_owner
(
treeish
);
if
(
git_object_peel
((
git_object
**
)
&
tree
,
treeish
,
GIT_OBJ_TREE
)
<
0
)
{
giterr_set
(
...
...
@@ -1409,8 +1442,7 @@ int git_checkout_head(
git_tree
*
head
=
NULL
;
git_iterator
*
head_i
=
NULL
;
if
((
error
=
git_repository__ensure_not_bare
(
repo
,
"checkout head"
))
<
0
)
return
error
;
assert
(
repo
);
if
(
!
(
error
=
checkout_lookup_head_tree
(
&
head
,
repo
))
&&
!
(
error
=
git_iterator_for_tree
(
&
head_i
,
head
,
0
,
NULL
,
NULL
)))
...
...
src/iterator.c
View file @
5d669f0a
...
...
@@ -1321,9 +1321,10 @@ static void workdir_iterator__free(git_iterator *self)
git_ignore__free
(
&
wi
->
ignores
);
}
int
git_iterator_for_workdir
(
int
git_iterator_for_workdir
_ext
(
git_iterator
**
out
,
git_repository
*
repo
,
const
char
*
repo_workdir
,
git_iterator_flag_t
flags
,
const
char
*
start
,
const
char
*
end
)
...
...
@@ -1331,8 +1332,11 @@ int git_iterator_for_workdir(
int
error
;
workdir_iterator
*
wi
;
if
(
git_repository__ensure_not_bare
(
repo
,
"scan working directory"
)
<
0
)
return
GIT_EBAREREPO
;
if
(
!
repo_workdir
)
{
if
(
git_repository__ensure_not_bare
(
repo
,
"scan working directory"
)
<
0
)
return
GIT_EBAREREPO
;
repo_workdir
=
git_repository_workdir
(
repo
);
}
/* initialize as an fs iterator then do overrides */
wi
=
git__calloc
(
1
,
sizeof
(
workdir_iterator
));
...
...
@@ -1352,7 +1356,7 @@ int git_iterator_for_workdir(
return
error
;
}
return
fs_iterator__initialize
(
out
,
&
wi
->
fi
,
git_repository_workdir
(
repo
)
);
return
fs_iterator__initialize
(
out
,
&
wi
->
fi
,
repo_workdir
);
}
...
...
src/iterator.h
View file @
5d669f0a
...
...
@@ -79,15 +79,26 @@ extern int git_iterator_for_index(
const
char
*
start
,
const
char
*
end
);
extern
int
git_iterator_for_workdir_ext
(
git_iterator
**
out
,
git_repository
*
repo
,
const
char
*
repo_workdir
,
git_iterator_flag_t
flags
,
const
char
*
start
,
const
char
*
end
);
/* workdir iterators will match the ignore_case value from the index of the
* repository, unless you override with a non-zero flag value
*/
extern
int
git_iterator_for_workdir
(
GIT_INLINE
(
int
)
git_iterator_for_workdir
(
git_iterator
**
out
,
git_repository
*
repo
,
git_iterator_flag_t
flags
,
const
char
*
start
,
const
char
*
end
);
const
char
*
end
)
{
return
git_iterator_for_workdir_ext
(
out
,
repo
,
NULL
,
flags
,
start
,
end
);
}
/* for filesystem iterators, you have to explicitly pass in the ignore_case
* behavior that you desire
...
...
tests-clar/checkout/index.c
View file @
5d669f0a
...
...
@@ -506,3 +506,102 @@ void test_checkout_index__issue_1397(void)
check_file_contents
(
"./issue_1397/crlf_file.txt"
,
"first line
\r\n
second line
\r\n
both with crlf"
);
}
void
test_checkout_index__target_directory
(
void
)
{
git_checkout_opts
opts
=
GIT_CHECKOUT_OPTS_INIT
;
checkout_counts
cts
;
memset
(
&
cts
,
0
,
sizeof
(
cts
));
opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE_CREATE
;
opts
.
target_directory
=
"alternative"
;
cl_assert
(
!
git_path_isdir
(
"alternative"
));
opts
.
notify_flags
=
GIT_CHECKOUT_NOTIFY_ALL
;
opts
.
notify_cb
=
checkout_count_callback
;
opts
.
notify_payload
=
&
cts
;
/* create some files that *would* conflict if we were using the wd */
cl_git_mkfile
(
"testrepo/README"
,
"I'm in the way!
\n
"
);
cl_git_mkfile
(
"testrepo/new.txt"
,
"my new file
\n
"
);
cl_git_pass
(
git_checkout_index
(
g_repo
,
NULL
,
&
opts
));
cl_assert_equal_i
(
0
,
cts
.
n_untracked
);
cl_assert_equal_i
(
0
,
cts
.
n_ignored
);
cl_assert_equal_i
(
4
,
cts
.
n_updates
);
check_file_contents
(
"./alternative/README"
,
"hey there
\n
"
);
check_file_contents
(
"./alternative/branch_file.txt"
,
"hi
\n
bye!
\n
"
);
check_file_contents
(
"./alternative/new.txt"
,
"my new file
\n
"
);
cl_git_pass
(
git_futils_rmdir_r
(
"alternative"
,
NULL
,
GIT_RMDIR_REMOVE_FILES
));
}
void
test_checkout_index__target_directory_from_bare
(
void
)
{
git_checkout_opts
opts
=
GIT_CHECKOUT_OPTS_INIT
;
git_index
*
index
;
git_object
*
head
=
NULL
;
checkout_counts
cts
;
memset
(
&
cts
,
0
,
sizeof
(
cts
));
test_checkout_index__cleanup
();
g_repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
cl_assert
(
git_repository_is_bare
(
g_repo
));
cl_git_pass
(
git_repository_index
(
&
index
,
g_repo
));
cl_git_pass
(
git_revparse_single
(
&
head
,
g_repo
,
"HEAD^{tree}"
));
cl_git_pass
(
git_index_read_tree
(
index
,
(
const
git_tree
*
)
head
));
cl_git_pass
(
git_index_write
(
index
));
git_index_free
(
index
);
opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE_CREATE
;
opts
.
notify_flags
=
GIT_CHECKOUT_NOTIFY_ALL
;
opts
.
notify_cb
=
checkout_count_callback
;
opts
.
notify_payload
=
&
cts
;
/* fail to checkout a bare repo */
cl_git_fail
(
git_checkout_index
(
g_repo
,
NULL
,
&
opts
));
opts
.
target_directory
=
"alternative"
;
cl_assert
(
!
git_path_isdir
(
"alternative"
));
cl_git_pass
(
git_checkout_index
(
g_repo
,
NULL
,
&
opts
));
cl_assert_equal_i
(
0
,
cts
.
n_untracked
);
cl_assert_equal_i
(
0
,
cts
.
n_ignored
);
cl_assert_equal_i
(
3
,
cts
.
n_updates
);
check_file_contents
(
"./alternative/README"
,
"hey there
\n
"
);
check_file_contents
(
"./alternative/branch_file.txt"
,
"hi
\n
bye!
\n
"
);
check_file_contents
(
"./alternative/new.txt"
,
"my new file
\n
"
);
cl_git_pass
(
git_futils_rmdir_r
(
"alternative"
,
NULL
,
GIT_RMDIR_REMOVE_FILES
));
}
void
test_checkout_index__can_get_repo_from_index
(
void
)
{
git_index
*
index
;
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/branch_file.txt"
));
cl_assert_equal_i
(
false
,
git_path_isfile
(
"./testrepo/new.txt"
));
opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE_CREATE
;
cl_git_pass
(
git_repository_index
(
&
index
,
g_repo
));
cl_git_pass
(
git_checkout_index
(
NULL
,
index
,
&
opts
));
check_file_contents
(
"./testrepo/README"
,
"hey there
\n
"
);
check_file_contents
(
"./testrepo/branch_file.txt"
,
"hi
\n
bye!
\n
"
);
check_file_contents
(
"./testrepo/new.txt"
,
"my new file
\n
"
);
git_index_free
(
index
);
}
tests-clar/checkout/tree.c
View file @
5d669f0a
...
...
@@ -596,6 +596,8 @@ void test_checkout_tree__fails_when_dir_in_use(void)
cl_git_pass
(
p_chdir
(
"../.."
));
cl_assert
(
git_path_is_empty_dir
(
"testrepo/a"
));
git_object_free
(
obj
);
#endif
}
...
...
@@ -628,5 +630,47 @@ void test_checkout_tree__can_continue_when_dir_in_use(void)
cl_git_pass
(
p_chdir
(
"../.."
));
cl_assert
(
git_path_is_empty_dir
(
"testrepo/a"
));
git_object_free
(
obj
);
#endif
}
void
test_checkout_tree__target_directory_from_bare
(
void
)
{
git_checkout_opts
opts
=
GIT_CHECKOUT_OPTS_INIT
;
git_oid
oid
;
checkout_counts
cts
;
memset
(
&
cts
,
0
,
sizeof
(
cts
));
test_checkout_tree__cleanup
();
/* cleanup default checkout */
g_repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
cl_assert
(
git_repository_is_bare
(
g_repo
));
opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE_CREATE
;
opts
.
notify_flags
=
GIT_CHECKOUT_NOTIFY_ALL
;
opts
.
notify_cb
=
checkout_count_callback
;
opts
.
notify_payload
=
&
cts
;
cl_git_pass
(
git_reference_name_to_id
(
&
oid
,
g_repo
,
"HEAD"
));
cl_git_pass
(
git_object_lookup
(
&
g_object
,
g_repo
,
&
oid
,
GIT_OBJ_ANY
));
cl_git_fail
(
git_checkout_tree
(
g_repo
,
g_object
,
&
opts
));
opts
.
target_directory
=
"alternative"
;
cl_assert
(
!
git_path_isdir
(
"alternative"
));
cl_git_pass
(
git_checkout_tree
(
g_repo
,
g_object
,
&
opts
));
cl_assert_equal_i
(
0
,
cts
.
n_untracked
);
cl_assert_equal_i
(
0
,
cts
.
n_ignored
);
cl_assert_equal_i
(
3
,
cts
.
n_updates
);
check_file_contents
(
"./alternative/README"
,
"hey there
\n
"
);
check_file_contents
(
"./alternative/branch_file.txt"
,
"hi
\n
bye!
\n
"
);
check_file_contents
(
"./alternative/new.txt"
,
"my new file
\n
"
);
cl_git_pass
(
git_futils_rmdir_r
(
"alternative"
,
NULL
,
GIT_RMDIR_REMOVE_FILES
));
}
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