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
7321cff0
Unverified
Commit
7321cff0
authored
Nov 15, 2018
by
Edward Thomson
Committed by
GitHub
Nov 15, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4713 from libgit2/ethomson/win_symlinks
Support symlinks on Windows when core.symlinks=true
parents
9189a66a
da500cc6
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
331 additions
and
198 deletions
+331
-198
src/CMakeLists.txt
+1
-1
src/repository.c
+50
-16
src/win32/posix_w32.c
+18
-36
tests/checkout/conflict.c
+56
-48
tests/checkout/icase.c
+17
-28
tests/checkout/index.c
+92
-45
tests/repo/init.c
+65
-24
tests/repo/repo_helpers.c
+30
-0
tests/repo/repo_helpers.h
+2
-0
No files found.
src/CMakeLists.txt
View file @
7321cff0
...
@@ -423,7 +423,7 @@ FILE(GLOB SRC_H
...
@@ -423,7 +423,7 @@ FILE(GLOB SRC_H
# On Windows use specific platform sources
# On Windows use specific platform sources
IF (WIN32 AND NOT CYGWIN)
IF (WIN32 AND NOT CYGWIN)
ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0
501
)
ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0
600
)
IF(MSVC)
IF(MSVC)
SET(WIN_RC "
win32/git2.rc
")
SET(WIN_RC "
win32/git2.rc
")
...
...
src/repository.c
View file @
7321cff0
...
@@ -944,18 +944,20 @@ static int load_config(
...
@@ -944,18 +944,20 @@ static int load_config(
git_buf
config_path
=
GIT_BUF_INIT
;
git_buf
config_path
=
GIT_BUF_INIT
;
git_config
*
cfg
=
NULL
;
git_config
*
cfg
=
NULL
;
assert
(
repo
&&
out
);
assert
(
out
);
if
((
error
=
git_config_new
(
&
cfg
))
<
0
)
if
((
error
=
git_config_new
(
&
cfg
))
<
0
)
return
error
;
return
error
;
if
((
error
=
git_repository_item_path
(
&
config_path
,
repo
,
GIT_REPOSITORY_ITEM_CONFIG
))
==
0
)
if
(
repo
)
{
error
=
git_config_add_file_ondisk
(
cfg
,
config_path
.
ptr
,
GIT_CONFIG_LEVEL_LOCAL
,
repo
,
0
);
if
((
error
=
git_repository_item_path
(
&
config_path
,
repo
,
GIT_REPOSITORY_ITEM_CONFIG
))
==
0
)
error
=
git_config_add_file_ondisk
(
cfg
,
config_path
.
ptr
,
GIT_CONFIG_LEVEL_LOCAL
,
repo
,
0
);
if
(
error
&&
error
!=
GIT_ENOTFOUND
)
if
(
error
&&
error
!=
GIT_ENOTFOUND
)
goto
on_error
;
goto
on_error
;
git_buf_dispose
(
&
config_path
);
git_buf_dispose
(
&
config_path
);
}
if
(
global_config_path
!=
NULL
&&
if
(
global_config_path
!=
NULL
&&
(
error
=
git_config_add_file_ondisk
(
(
error
=
git_config_add_file_ondisk
(
...
@@ -1411,24 +1413,56 @@ static bool is_filesystem_case_insensitive(const char *gitdir_path)
...
@@ -1411,24 +1413,56 @@ static bool is_filesystem_case_insensitive(const char *gitdir_path)
static
bool
are_symlinks_supported
(
const
char
*
wd_path
)
static
bool
are_symlinks_supported
(
const
char
*
wd_path
)
{
{
git_config
*
config
=
NULL
;
git_buf
path
=
GIT_BUF_INIT
;
git_buf
path
=
GIT_BUF_INIT
;
int
fd
;
int
fd
;
struct
stat
st
;
struct
stat
st
;
int
symlinks_supported
=
-
1
;
bool
symlinks
=
false
;
/*
* To emulate Git for Windows, symlinks on Windows must be explicitly
* opted-in. We examine the system configuration for a core.symlinks
* set to true. If found, we then examine the filesystem to see if
* symlinks are _actually_ supported by the current user. If that is
* _not_ set, then we do not test or enable symlink support.
*/
#ifdef GIT_WIN32
git_buf
global_buf
=
GIT_BUF_INIT
;
git_buf
xdg_buf
=
GIT_BUF_INIT
;
git_buf
system_buf
=
GIT_BUF_INIT
;
git_buf
programdata_buf
=
GIT_BUF_INIT
;
git_config_find_global
(
&
global_buf
);
git_config_find_xdg
(
&
xdg_buf
);
git_config_find_system
(
&
system_buf
);
git_config_find_programdata
(
&
programdata_buf
);
if
(
load_config
(
&
config
,
NULL
,
path_unless_empty
(
&
global_buf
),
path_unless_empty
(
&
xdg_buf
),
path_unless_empty
(
&
system_buf
),
path_unless_empty
(
&
programdata_buf
))
<
0
)
goto
done
;
if
(
git_config_get_bool
(
&
symlinks
,
config
,
"core.symlinks"
)
<
0
||
!
symlinks
)
goto
done
;
#endif
if
((
fd
=
git_futils_mktmp
(
&
path
,
wd_path
,
0666
))
<
0
||
if
((
fd
=
git_futils_mktmp
(
&
path
,
wd_path
,
0666
))
<
0
||
p_close
(
fd
)
<
0
||
p_close
(
fd
)
<
0
||
p_unlink
(
path
.
ptr
)
<
0
||
p_unlink
(
path
.
ptr
)
<
0
||
p_symlink
(
"testing"
,
path
.
ptr
)
<
0
||
p_symlink
(
"testing"
,
path
.
ptr
)
<
0
||
p_lstat
(
path
.
ptr
,
&
st
)
<
0
)
p_lstat
(
path
.
ptr
,
&
st
)
<
0
)
symlinks_supported
=
fals
e
;
goto
don
e
;
else
symlinks_supported
=
(
S_ISLNK
(
st
.
st_mode
)
!=
0
);
symlinks
=
(
S_ISLNK
(
st
.
st_mode
)
!=
0
);
(
void
)
p_unlink
(
path
.
ptr
);
(
void
)
p_unlink
(
path
.
ptr
);
git_buf_dispose
(
&
path
);
return
symlinks_supported
;
done:
git_buf_dispose
(
&
path
);
git_config_free
(
config
);
return
symlinks
;
}
}
static
int
create_empty_file
(
const
char
*
path
,
mode_t
mode
)
static
int
create_empty_file
(
const
char
*
path
,
mode_t
mode
)
...
...
src/win32/posix_w32.c
View file @
7321cff0
...
@@ -29,15 +29,16 @@
...
@@ -29,15 +29,16 @@
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
#endif
#endif
#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x02
#endif
/* Allowable mode bits on Win32. Using mode bits that are not supported on
/* Allowable mode bits on Win32. Using mode bits that are not supported on
* Win32 (eg S_IRWXU) is generally ignored, but Wine warns loudly about it
* Win32 (eg S_IRWXU) is generally ignored, but Wine warns loudly about it
* so we simply remove them.
* so we simply remove them.
*/
*/
#define WIN32_MODE_MASK (_S_IREAD | _S_IWRITE)
#define WIN32_MODE_MASK (_S_IREAD | _S_IWRITE)
/* GetFinalPathNameByHandleW signature */
typedef
DWORD
(
WINAPI
*
PFGetFinalPathNameByHandleW
)(
HANDLE
,
LPWSTR
,
DWORD
,
DWORD
);
unsigned
long
git_win32__createfile_sharemode
=
unsigned
long
git_win32__createfile_sharemode
=
FILE_SHARE_READ
|
FILE_SHARE_WRITE
;
FILE_SHARE_READ
|
FILE_SHARE_WRITE
;
int
git_win32__retries
=
10
;
int
git_win32__retries
=
10
;
...
@@ -393,12 +394,20 @@ int p_readlink(const char *path, char *buf, size_t bufsiz)
...
@@ -393,12 +394,20 @@ int p_readlink(const char *path, char *buf, size_t bufsiz)
return
(
int
)
bufsiz
;
return
(
int
)
bufsiz
;
}
}
int
p_symlink
(
const
char
*
old
,
const
char
*
new
)
int
p_symlink
(
const
char
*
target
,
const
char
*
path
)
{
{
/* Real symlinks on NTFS require admin privileges. Until this changes,
git_win32_path
target_w
,
path_w
;
* libgit2 just creates a text file with the link target in the contents.
wchar_t
*
target_p
;
*/
return
git_futils_fake_symlink
(
old
,
new
);
if
(
git_win32_path_from_utf8
(
path_w
,
path
)
<
0
||
git__utf8_to_16
(
target_w
,
MAX_PATH
,
target
)
<
0
)
return
-
1
;
if
(
!
CreateSymbolicLinkW
(
path_w
,
target_w
,
SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
))
return
-
1
;
return
0
;
}
}
struct
open_opts
{
struct
open_opts
{
...
@@ -598,40 +607,13 @@ int p_getcwd(char *buffer_out, size_t size)
...
@@ -598,40 +607,13 @@ int p_getcwd(char *buffer_out, size_t size)
return
0
;
return
0
;
}
}
/*
* Returns the address of the GetFinalPathNameByHandleW function.
* This function is available on Windows Vista and higher.
*/
static
PFGetFinalPathNameByHandleW
get_fpnbyhandle
(
void
)
{
static
PFGetFinalPathNameByHandleW
pFunc
=
NULL
;
PFGetFinalPathNameByHandleW
toReturn
=
pFunc
;
if
(
!
toReturn
)
{
HMODULE
hModule
=
GetModuleHandleW
(
L"kernel32"
);
if
(
hModule
)
toReturn
=
(
PFGetFinalPathNameByHandleW
)
GetProcAddress
(
hModule
,
"GetFinalPathNameByHandleW"
);
pFunc
=
toReturn
;
}
assert
(
toReturn
);
return
toReturn
;
}
static
int
getfinalpath_w
(
static
int
getfinalpath_w
(
git_win32_path
dest
,
git_win32_path
dest
,
const
wchar_t
*
path
)
const
wchar_t
*
path
)
{
{
PFGetFinalPathNameByHandleW
pgfp
=
get_fpnbyhandle
();
HANDLE
hFile
;
HANDLE
hFile
;
DWORD
dwChars
;
DWORD
dwChars
;
if
(
!
pgfp
)
return
-
1
;
/* Use FILE_FLAG_BACKUP_SEMANTICS so we can open a directory. Do not
/* Use FILE_FLAG_BACKUP_SEMANTICS so we can open a directory. Do not
* specify FILE_FLAG_OPEN_REPARSE_POINT; we want to open a handle to the
* specify FILE_FLAG_OPEN_REPARSE_POINT; we want to open a handle to the
* target of the link. */
* target of the link. */
...
@@ -642,7 +624,7 @@ static int getfinalpath_w(
...
@@ -642,7 +624,7 @@ static int getfinalpath_w(
return
-
1
;
return
-
1
;
/* Call GetFinalPathNameByHandle */
/* Call GetFinalPathNameByHandle */
dwChars
=
pgfp
(
hFile
,
dest
,
GIT_WIN_PATH_UTF16
,
FILE_NAME_NORMALIZED
);
dwChars
=
GetFinalPathNameByHandleW
(
hFile
,
dest
,
GIT_WIN_PATH_UTF16
,
FILE_NAME_NORMALIZED
);
CloseHandle
(
hFile
);
CloseHandle
(
hFile
);
if
(
!
dwChars
||
dwChars
>=
GIT_WIN_PATH_UTF16
)
if
(
!
dwChars
||
dwChars
>=
GIT_WIN_PATH_UTF16
)
...
...
tests/checkout/conflict.c
View file @
7321cff0
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
#include "git2/repository.h"
#include "git2/repository.h"
#include "git2/sys/index.h"
#include "git2/sys/index.h"
#include "fileops.h"
#include "fileops.h"
#include "repository.h"
static
git_repository
*
g_repo
;
static
git_repository
*
g_repo
;
static
git_index
*
g_index
;
static
git_index
*
g_index
;
...
@@ -184,28 +185,35 @@ static void ensure_workdir(const char *path, int mode, const char *oid_str)
...
@@ -184,28 +185,35 @@ static void ensure_workdir(const char *path, int mode, const char *oid_str)
ensure_workdir_oid
(
path
,
oid_str
);
ensure_workdir_oid
(
path
,
oid_str
);
}
}
static
void
ensure_workdir_link
(
const
char
*
path
,
const
char
*
target
)
static
void
ensure_workdir_link
(
git_repository
*
repo
,
const
char
*
path
,
const
char
*
target
)
{
{
#ifdef GIT_WIN32
int
symlinks
;
ensure_workdir_contents
(
path
,
target
);
#else
git_buf
fullpath
=
GIT_BUF_INIT
;
char
actual
[
1024
];
struct
stat
st
;
int
len
;
cl_git_pass
(
cl_git_pass
(
git_repository__cvar
(
&
symlinks
,
repo
,
GIT_CVAR_SYMLINKS
));
git_buf_joinpath
(
&
fullpath
,
git_repository_workdir
(
g_repo
),
path
));
cl_git_pass
(
p_lstat
(
git_buf_cstr
(
&
fullpath
),
&
st
));
if
(
!
symlinks
)
{
cl_assert
(
S_ISLNK
(
st
.
st_mode
));
ensure_workdir_contents
(
path
,
target
);
}
else
{
git_buf
fullpath
=
GIT_BUF_INIT
;
char
actual
[
1024
];
struct
stat
st
;
int
len
;
cl_assert
((
len
=
p_readlink
(
git_buf_cstr
(
&
fullpath
),
actual
,
1024
))
>
0
);
cl_git_pass
(
actual
[
len
]
=
'\0'
;
git_buf_joinpath
(
&
fullpath
,
git_repository_workdir
(
g_repo
),
path
));
cl_assert
(
strcmp
(
actual
,
target
)
==
0
);
git_buf_dispose
(
&
fullpath
);
cl_git_pass
(
p_lstat
(
git_buf_cstr
(
&
fullpath
),
&
st
));
#endif
cl_assert
(
S_ISLNK
(
st
.
st_mode
));
cl_assert
((
len
=
p_readlink
(
git_buf_cstr
(
&
fullpath
),
actual
,
1024
))
>
0
);
actual
[
len
]
=
'\0'
;
cl_assert
(
strcmp
(
actual
,
target
)
==
0
);
git_buf_dispose
(
&
fullpath
);
}
}
}
void
test_checkout_conflict__ignored
(
void
)
void
test_checkout_conflict__ignored
(
void
)
...
@@ -415,8 +423,8 @@ void test_checkout_conflict__links(void)
...
@@ -415,8 +423,8 @@ void test_checkout_conflict__links(void)
cl_git_pass
(
git_checkout_index
(
g_repo
,
g_index
,
&
opts
));
cl_git_pass
(
git_checkout_index
(
g_repo
,
g_index
,
&
opts
));
/* Conflicts with links always keep the ours side (even with -Xtheirs) */
/* Conflicts with links always keep the ours side (even with -Xtheirs) */
ensure_workdir_link
(
"link-1"
,
LINK_OURS_TARGET
);
ensure_workdir_link
(
g_repo
,
"link-1"
,
LINK_OURS_TARGET
);
ensure_workdir_link
(
"link-2"
,
LINK_OURS_TARGET
);
ensure_workdir_link
(
g_repo
,
"link-2"
,
LINK_OURS_TARGET
);
}
}
void
test_checkout_conflict__add_add
(
void
)
void
test_checkout_conflict__add_add
(
void
)
...
@@ -684,7 +692,7 @@ void test_checkout_conflict__renames(void)
...
@@ -684,7 +692,7 @@ void test_checkout_conflict__renames(void)
void
test_checkout_conflict__rename_keep_ours
(
void
)
void
test_checkout_conflict__rename_keep_ours
(
void
)
{
{
git_checkout_options
opts
=
GIT_CHECKOUT_OPTIONS_INIT
;
git_checkout_options
opts
=
GIT_CHECKOUT_OPTIONS_INIT
;
struct
checkout_index_entry
checkout_index_entries
[]
=
{
struct
checkout_index_entry
checkout_index_entries
[]
=
{
{
0100644
,
"68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"
,
0
,
"0a-no-change.txt"
},
{
0100644
,
"68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"
,
0
,
"0a-no-change.txt"
},
{
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
,
0
,
"0b-duplicated-in-ours.txt"
},
{
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
,
0
,
"0b-duplicated-in-ours.txt"
},
...
@@ -728,122 +736,122 @@ void test_checkout_conflict__rename_keep_ours(void)
...
@@ -728,122 +736,122 @@ void test_checkout_conflict__rename_keep_ours(void)
{
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
,
2
,
"7-both-renamed.txt"
},
{
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
,
2
,
"7-both-renamed.txt"
},
{
0100644
,
"b69fe837e4cecfd4c9a40cdca7c138468687df07"
,
3
,
"7-both-renamed.txt"
}
{
0100644
,
"b69fe837e4cecfd4c9a40cdca7c138468687df07"
,
3
,
"7-both-renamed.txt"
}
};
};
struct
checkout_name_entry
checkout_name_entries
[]
=
{
struct
checkout_name_entry
checkout_name_entries
[]
=
{
{
{
"3a-renamed-in-ours-deleted-in-theirs.txt"
,
"3a-renamed-in-ours-deleted-in-theirs.txt"
,
"3a-newname-in-ours-deleted-in-theirs.txt"
,
"3a-newname-in-ours-deleted-in-theirs.txt"
,
""
""
},
},
{
{
"3b-renamed-in-theirs-deleted-in-ours.txt"
,
"3b-renamed-in-theirs-deleted-in-ours.txt"
,
""
,
""
,
"3b-newname-in-theirs-deleted-in-ours.txt"
"3b-newname-in-theirs-deleted-in-ours.txt"
},
},
{
{
"4a-renamed-in-ours-added-in-theirs.txt"
,
"4a-renamed-in-ours-added-in-theirs.txt"
,
"4a-newname-in-ours-added-in-theirs.txt"
,
"4a-newname-in-ours-added-in-theirs.txt"
,
""
""
},
},
{
{
"4b-renamed-in-theirs-added-in-ours.txt"
,
"4b-renamed-in-theirs-added-in-ours.txt"
,
""
,
""
,
"4b-newname-in-theirs-added-in-ours.txt"
"4b-newname-in-theirs-added-in-ours.txt"
},
},
{
{
"5a-renamed-in-ours-added-in-theirs.txt"
,
"5a-renamed-in-ours-added-in-theirs.txt"
,
"5a-newname-in-ours-added-in-theirs.txt"
,
"5a-newname-in-ours-added-in-theirs.txt"
,
"5a-renamed-in-ours-added-in-theirs.txt"
"5a-renamed-in-ours-added-in-theirs.txt"
},
},
{
{
"5b-renamed-in-theirs-added-in-ours.txt"
,
"5b-renamed-in-theirs-added-in-ours.txt"
,
"5b-renamed-in-theirs-added-in-ours.txt"
,
"5b-renamed-in-theirs-added-in-ours.txt"
,
"5b-newname-in-theirs-added-in-ours.txt"
"5b-newname-in-theirs-added-in-ours.txt"
},
},
{
{
"6-both-renamed-1-to-2.txt"
,
"6-both-renamed-1-to-2.txt"
,
"6-both-renamed-1-to-2-ours.txt"
,
"6-both-renamed-1-to-2-ours.txt"
,
"6-both-renamed-1-to-2-theirs.txt"
"6-both-renamed-1-to-2-theirs.txt"
},
},
{
{
"7-both-renamed-side-1.txt"
,
"7-both-renamed-side-1.txt"
,
"7-both-renamed.txt"
,
"7-both-renamed.txt"
,
"7-both-renamed-side-1.txt"
"7-both-renamed-side-1.txt"
},
},
{
{
"7-both-renamed-side-2.txt"
,
"7-both-renamed-side-2.txt"
,
"7-both-renamed-side-2.txt"
,
"7-both-renamed-side-2.txt"
,
"7-both-renamed.txt"
"7-both-renamed.txt"
}
}
};
};
opts
.
checkout_strategy
|=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_USE_OURS
;
opts
.
checkout_strategy
|=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_USE_OURS
;
create_index
(
checkout_index_entries
,
41
);
create_index
(
checkout_index_entries
,
41
);
create_index_names
(
checkout_name_entries
,
9
);
create_index_names
(
checkout_name_entries
,
9
);
cl_git_pass
(
git_index_write
(
g_index
));
cl_git_pass
(
git_index_write
(
g_index
));
cl_git_pass
(
git_checkout_index
(
g_repo
,
g_index
,
&
opts
));
cl_git_pass
(
git_checkout_index
(
g_repo
,
g_index
,
&
opts
));
ensure_workdir
(
"0a-no-change.txt"
,
ensure_workdir
(
"0a-no-change.txt"
,
0100644
,
"68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"
);
0100644
,
"68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"
);
ensure_workdir
(
"0b-duplicated-in-ours.txt"
,
ensure_workdir
(
"0b-duplicated-in-ours.txt"
,
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
);
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
);
ensure_workdir
(
"0b-rewritten-in-ours.txt"
,
ensure_workdir
(
"0b-rewritten-in-ours.txt"
,
0100644
,
"e376fbdd06ebf021c92724da9f26f44212734e3e"
);
0100644
,
"e376fbdd06ebf021c92724da9f26f44212734e3e"
);
ensure_workdir
(
"0c-duplicated-in-theirs.txt"
,
ensure_workdir
(
"0c-duplicated-in-theirs.txt"
,
0100644
,
"2f56120107d680129a5d9791b521cb1e73a2ed31"
);
0100644
,
"2f56120107d680129a5d9791b521cb1e73a2ed31"
);
ensure_workdir
(
"0c-rewritten-in-theirs.txt"
,
ensure_workdir
(
"0c-rewritten-in-theirs.txt"
,
0100644
,
"efc9121fdedaf08ba180b53ebfbcf71bd488ed09"
);
0100644
,
"efc9121fdedaf08ba180b53ebfbcf71bd488ed09"
);
ensure_workdir
(
"1a-newname-in-ours-edited-in-theirs.txt"
,
ensure_workdir
(
"1a-newname-in-ours-edited-in-theirs.txt"
,
0100644
,
"0d872f8e871a30208305978ecbf9e66d864f1638"
);
0100644
,
"0d872f8e871a30208305978ecbf9e66d864f1638"
);
ensure_workdir
(
"1a-newname-in-ours.txt"
,
ensure_workdir
(
"1a-newname-in-ours.txt"
,
0100644
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
);
0100644
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
);
ensure_workdir
(
"1b-newname-in-theirs-edited-in-ours.txt"
,
ensure_workdir
(
"1b-newname-in-theirs-edited-in-ours.txt"
,
0100644
,
"ed9523e62e453e50dd9be1606af19399b96e397a"
);
0100644
,
"ed9523e62e453e50dd9be1606af19399b96e397a"
);
ensure_workdir
(
"1b-newname-in-theirs.txt"
,
ensure_workdir
(
"1b-newname-in-theirs.txt"
,
0100644
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
);
0100644
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
);
ensure_workdir
(
"2-newname-in-both.txt"
,
ensure_workdir
(
"2-newname-in-both.txt"
,
0100644
,
"178940b450f238a56c0d75b7955cb57b38191982"
);
0100644
,
"178940b450f238a56c0d75b7955cb57b38191982"
);
ensure_workdir
(
"3a-newname-in-ours-deleted-in-theirs.txt"
,
ensure_workdir
(
"3a-newname-in-ours-deleted-in-theirs.txt"
,
0100644
,
"18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"
);
0100644
,
"18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"
);
ensure_workdir
(
"3b-newname-in-theirs-deleted-in-ours.txt"
,
ensure_workdir
(
"3b-newname-in-theirs-deleted-in-ours.txt"
,
0100644
,
"36219b49367146cb2e6a1555b5a9ebd4d0328495"
);
0100644
,
"36219b49367146cb2e6a1555b5a9ebd4d0328495"
);
ensure_workdir
(
"4a-newname-in-ours-added-in-theirs.txt"
,
ensure_workdir
(
"4a-newname-in-ours-added-in-theirs.txt"
,
0100644
,
"227792b52aaa0b238bea00ec7e509b02623f168c"
);
0100644
,
"227792b52aaa0b238bea00ec7e509b02623f168c"
);
ensure_workdir
(
"4b-newname-in-theirs-added-in-ours.txt"
,
ensure_workdir
(
"4b-newname-in-theirs-added-in-ours.txt"
,
0100644
,
"de872ee3618b894992e9d1e18ba2ebe256a112f9"
);
0100644
,
"de872ee3618b894992e9d1e18ba2ebe256a112f9"
);
ensure_workdir
(
"5a-newname-in-ours-added-in-theirs.txt"
,
ensure_workdir
(
"5a-newname-in-ours-added-in-theirs.txt"
,
0100644
,
"d3719a5ae8e4d92276b5313ce976f6ee5af2b436"
);
0100644
,
"d3719a5ae8e4d92276b5313ce976f6ee5af2b436"
);
ensure_workdir
(
"5b-newname-in-theirs-added-in-ours.txt"
,
ensure_workdir
(
"5b-newname-in-theirs-added-in-ours.txt"
,
0100644
,
"385c8a0f26ddf79e9041e15e17dc352ed2c4cced"
);
0100644
,
"385c8a0f26ddf79e9041e15e17dc352ed2c4cced"
);
ensure_workdir
(
"6-both-renamed-1-to-2-ours.txt"
,
ensure_workdir
(
"6-both-renamed-1-to-2-ours.txt"
,
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
);
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
);
ensure_workdir
(
"7-both-renamed.txt"
,
ensure_workdir
(
"7-both-renamed.txt"
,
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
);
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
);
}
}
...
...
tests/checkout/icase.c
View file @
7321cff0
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
#include "git2/checkout.h"
#include "git2/checkout.h"
#include "refs.h"
#include "refs.h"
#include "path.h"
#include "path.h"
#include "repository.h"
#ifdef GIT_WIN32
#ifdef GIT_WIN32
# include <windows.h>
# include <windows.h>
...
@@ -44,29 +45,6 @@ void test_checkout_icase__cleanup(void)
...
@@ -44,29 +45,6 @@ void test_checkout_icase__cleanup(void)
static
char
*
get_filename
(
const
char
*
in
)
static
char
*
get_filename
(
const
char
*
in
)
{
{
#ifdef GIT_WIN32
HANDLE
fh
;
HMODULE
kerneldll
;
char
*
filename
;
typedef
DWORD
(
__stdcall
*
getfinalpathname
)(
HANDLE
,
LPSTR
,
DWORD
,
DWORD
);
getfinalpathname
getfinalpathfn
;
cl_assert
(
filename
=
malloc
(
MAX_PATH
));
cl_assert
(
kerneldll
=
LoadLibrary
(
"kernel32.dll"
));
cl_assert
(
getfinalpathfn
=
(
getfinalpathname
)
GetProcAddress
(
kerneldll
,
"GetFinalPathNameByHandleA"
));
cl_assert
(
fh
=
CreateFileA
(
in
,
FILE_READ_ATTRIBUTES
|
STANDARD_RIGHTS_READ
,
FILE_SHARE_READ
,
NULL
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
,
NULL
));
cl_win32_pass
(
getfinalpathfn
(
fh
,
filename
,
MAX_PATH
,
VOLUME_NAME_DOS
));
CloseHandle
(
fh
);
git_path_mkposix
(
filename
);
return
filename
;
#else
char
*
search_dirname
,
*
search_filename
,
*
filename
=
NULL
;
char
*
search_dirname
,
*
search_filename
,
*
filename
=
NULL
;
git_buf
out
=
GIT_BUF_INIT
;
git_buf
out
=
GIT_BUF_INIT
;
DIR
*
dir
;
DIR
*
dir
;
...
@@ -92,7 +70,6 @@ static char *get_filename(const char *in)
...
@@ -92,7 +70,6 @@ static char *get_filename(const char *in)
git_buf_dispose
(
&
out
);
git_buf_dispose
(
&
out
);
return
filename
;
return
filename
;
#endif
}
}
static
void
assert_name_is
(
const
char
*
expected
)
static
void
assert_name_is
(
const
char
*
expected
)
...
@@ -115,6 +92,18 @@ static void assert_name_is(const char *expected)
...
@@ -115,6 +92,18 @@ static void assert_name_is(const char *expected)
free
(
actual
);
free
(
actual
);
}
}
static
int
symlink_or_fake
(
git_repository
*
repo
,
const
char
*
a
,
const
char
*
b
)
{
int
symlinks
;
cl_git_pass
(
git_repository__cvar
(
&
symlinks
,
repo
,
GIT_CVAR_SYMLINKS
));
if
(
symlinks
)
return
p_symlink
(
a
,
b
);
else
return
git_futils_fake_symlink
(
a
,
b
);
}
void
test_checkout_icase__refuses_to_overwrite_files_for_files
(
void
)
void
test_checkout_icase__refuses_to_overwrite_files_for_files
(
void
)
{
{
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_RECREATE_MISSING
;
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_RECREATE_MISSING
;
...
@@ -141,7 +130,7 @@ void test_checkout_icase__refuses_to_overwrite_links_for_files(void)
...
@@ -141,7 +130,7 @@ void test_checkout_icase__refuses_to_overwrite_links_for_files(void)
{
{
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_RECREATE_MISSING
;
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_RECREATE_MISSING
;
cl_must_pass
(
p_symlink
(
"../tmp"
,
"testrepo/BRANCH_FILE.txt"
));
cl_must_pass
(
symlink_or_fake
(
repo
,
"../tmp"
,
"testrepo/BRANCH_FILE.txt"
));
cl_git_fail
(
git_checkout_tree
(
repo
,
obj
,
&
checkout_opts
));
cl_git_fail
(
git_checkout_tree
(
repo
,
obj
,
&
checkout_opts
));
...
@@ -153,7 +142,7 @@ void test_checkout_icase__overwrites_links_for_files_when_forced(void)
...
@@ -153,7 +142,7 @@ void test_checkout_icase__overwrites_links_for_files_when_forced(void)
{
{
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_FORCE
;
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_FORCE
;
cl_must_pass
(
p_symlink
(
"../tmp"
,
"testrepo/NEW.txt"
));
cl_must_pass
(
symlink_or_fake
(
repo
,
"../tmp"
,
"testrepo/NEW.txt"
));
cl_git_pass
(
git_checkout_tree
(
repo
,
obj
,
&
checkout_opts
));
cl_git_pass
(
git_checkout_tree
(
repo
,
obj
,
&
checkout_opts
));
...
@@ -229,7 +218,7 @@ void test_checkout_icase__refuses_to_overwrite_links_for_folders(void)
...
@@ -229,7 +218,7 @@ void test_checkout_icase__refuses_to_overwrite_links_for_folders(void)
{
{
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_RECREATE_MISSING
;
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_RECREATE_MISSING
;
cl_must_pass
(
p_symlink
(
".."
,
"testrepo/A"
));
cl_must_pass
(
symlink_or_fake
(
repo
,
".."
,
"testrepo/A"
));
cl_git_fail
(
git_checkout_tree
(
repo
,
obj
,
&
checkout_opts
));
cl_git_fail
(
git_checkout_tree
(
repo
,
obj
,
&
checkout_opts
));
...
@@ -241,7 +230,7 @@ void test_checkout_icase__overwrites_links_for_folders_when_forced(void)
...
@@ -241,7 +230,7 @@ void test_checkout_icase__overwrites_links_for_folders_when_forced(void)
{
{
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_FORCE
;
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_FORCE
;
cl_must_pass
(
p_symlink
(
".."
,
"testrepo/A"
));
cl_must_pass
(
symlink_or_fake
(
repo
,
".."
,
"testrepo/A"
));
cl_git_pass
(
git_checkout_tree
(
repo
,
obj
,
&
checkout_opts
));
cl_git_pass
(
git_checkout_tree
(
repo
,
obj
,
&
checkout_opts
));
...
...
tests/checkout/index.c
View file @
7321cff0
...
@@ -5,8 +5,10 @@
...
@@ -5,8 +5,10 @@
#include "fileops.h"
#include "fileops.h"
#include "repository.h"
#include "repository.h"
#include "remote.h"
#include "remote.h"
#include "repo/repo_helpers.h"
static
git_repository
*
g_repo
;
static
git_repository
*
g_repo
;
static
git_buf
g_global_path
=
GIT_BUF_INIT
;
void
test_checkout_index__initialize
(
void
)
void
test_checkout_index__initialize
(
void
)
{
{
...
@@ -22,21 +24,29 @@ void test_checkout_index__initialize(void)
...
@@ -22,21 +24,29 @@ void test_checkout_index__initialize(void)
cl_git_rewritefile
(
cl_git_rewritefile
(
"./testrepo/.gitattributes"
,
"./testrepo/.gitattributes"
,
"* text eol=lf
\n
"
);
"* text eol=lf
\n
"
);
git_libgit2_opts
(
GIT_OPT_GET_SEARCH_PATH
,
GIT_CONFIG_LEVEL_GLOBAL
,
&
g_global_path
);
}
}
void
test_checkout_index__cleanup
(
void
)
void
test_checkout_index__cleanup
(
void
)
{
{
git_libgit2_opts
(
GIT_OPT_SET_SEARCH_PATH
,
GIT_CONFIG_LEVEL_GLOBAL
,
g_global_path
.
ptr
);
git_buf_dispose
(
&
g_global_path
);
cl_git_sandbox_cleanup
();
cl_git_sandbox_cleanup
();
/* try to remove alternative dir */
/* try to remove directories created by tests */
if
(
git_path_isdir
(
"alternative"
))
cl_fixture_cleanup
(
"alternative"
);
git_futils_rmdir_r
(
"alternative"
,
NULL
,
GIT_RMDIR_REMOVE_FILES
);
cl_fixture_cleanup
(
"symlink"
);
cl_fixture_cleanup
(
"symlink.git"
);
cl_fixture_cleanup
(
"tmp_global_path"
);
}
}
void
test_checkout_index__cannot_checkout_a_bare_repository
(
void
)
void
test_checkout_index__cannot_checkout_a_bare_repository
(
void
)
{
{
test_checkout_index__cleanup
();
cl_git_sandbox_cleanup
();
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
));
...
@@ -136,23 +146,20 @@ void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void)
...
@@ -136,23 +146,20 @@ void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void)
#endif
#endif
}
}
void
test_checkout_index__honor_coresymlinks_default
(
void
)
static
void
populate_symlink_workdir
(
void
)
{
{
git_repository
*
repo
;
git_repository
*
repo
;
git_remote
*
origin
;
git_remote
*
origin
;
git_object
*
target
;
git_object
*
target
;
char
cwd
[
GIT_PATH_MAX
];
const
char
*
url
=
git_repository_path
(
g_repo
);
const
char
*
url
=
git_repository_path
(
g_repo
);
cl_assert
(
getcwd
(
cwd
,
sizeof
(
cwd
))
!=
NULL
);
cl_assert_equal_i
(
0
,
p_mkdir
(
"readonly"
,
0555
));
/* Read-only directory */
cl_assert_equal_i
(
0
,
chdir
(
"readonly"
));
cl_git_pass
(
git_repository_init
(
&
repo
,
"../symlink.git"
,
true
));
cl_git_pass
(
git_repository_init
(
&
repo
,
"../symlink.git"
,
true
));
cl_assert_equal_i
(
0
,
chdir
(
cwd
));
cl_assert_equal_i
(
0
,
p_mkdir
(
"symlink"
,
0777
));
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"symlink"
,
1
));
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"symlink"
,
1
));
/* Delete the `origin` repo (if it exists) so we can recreate it. */
git_remote_delete
(
repo
,
GIT_REMOTE_ORIGIN
);
cl_git_pass
(
git_remote_create
(
&
origin
,
repo
,
GIT_REMOTE_ORIGIN
,
url
));
cl_git_pass
(
git_remote_create
(
&
origin
,
repo
,
GIT_REMOTE_ORIGIN
,
url
));
cl_git_pass
(
git_remote_fetch
(
origin
,
NULL
,
NULL
,
NULL
));
cl_git_pass
(
git_remote_fetch
(
origin
,
NULL
,
NULL
,
NULL
));
git_remote_free
(
origin
);
git_remote_free
(
origin
);
...
@@ -161,28 +168,79 @@ void test_checkout_index__honor_coresymlinks_default(void)
...
@@ -161,28 +168,79 @@ void test_checkout_index__honor_coresymlinks_default(void)
cl_git_pass
(
git_reset
(
repo
,
target
,
GIT_RESET_HARD
,
NULL
));
cl_git_pass
(
git_reset
(
repo
,
target
,
GIT_RESET_HARD
,
NULL
));
git_object_free
(
target
);
git_object_free
(
target
);
git_repository_free
(
repo
);
git_repository_free
(
repo
);
}
void
test_checkout_index__honor_coresymlinks_default_true
(
void
)
{
char
link_data
[
GIT_PATH_MAX
];
int
link_size
=
GIT_PATH_MAX
;
cl_must_pass
(
p_mkdir
(
"symlink"
,
0777
));
if
(
!
filesystem_supports_symlinks
(
"symlink/test"
))
cl_skip
();
#ifdef GIT_WIN32
#ifdef GIT_WIN32
/*
* Windows explicitly requires the global configuration to have
* core.symlinks=true in addition to actual filesystem support.
*/
create_tmp_global_config
(
"tmp_global_path"
,
"core.symlinks"
,
"true"
);
#endif
populate_symlink_workdir
();
link_size
=
p_readlink
(
"./symlink/link_to_new.txt"
,
link_data
,
link_size
);
cl_assert
(
link_size
>=
0
);
link_data
[
link_size
]
=
'\0'
;
cl_assert_equal_i
(
link_size
,
strlen
(
"new.txt"
));
cl_assert_equal_s
(
link_data
,
"new.txt"
);
check_file_contents
(
"./symlink/link_to_new.txt"
,
"my new file
\n
"
);
}
void
test_checkout_index__honor_coresymlinks_default_false
(
void
)
{
cl_must_pass
(
p_mkdir
(
"symlink"
,
0777
));
#ifndef GIT_WIN32
/*
* This test is largely for Windows platforms to ensure that
* we respect an unset core.symlinks even when the platform
* supports symlinks. Bail entirely on POSIX platforms that
* do support symlinks.
*/
if
(
filesystem_supports_symlinks
(
"symlink/test"
))
cl_skip
();
#endif
populate_symlink_workdir
();
check_file_contents
(
"./symlink/link_to_new.txt"
,
"new.txt"
);
check_file_contents
(
"./symlink/link_to_new.txt"
,
"new.txt"
);
#else
}
{
char
link_data
[
1024
];
void
test_checkout_index__coresymlinks_set_to_true_fails_when_unsupported
(
void
)
size_t
link_size
=
1024
;
{
git_checkout_options
opts
=
GIT_CHECKOUT_OPTIONS_INIT
;
link_size
=
p_readlink
(
"./symlink/link_to_new.txt"
,
link_data
,
link_size
);
link_data
[
link_size
]
=
'\0'
;
if
(
filesystem_supports_symlinks
(
"testrepo/test"
))
{
cl_assert_equal_i
(
link_size
,
strlen
(
"new.txt"
));
cl_skip
();
cl_assert_equal_s
(
link_data
,
"new.txt"
);
check_file_contents
(
"./symlink/link_to_new.txt"
,
"my new file
\n
"
);
}
}
#endif
cl_fixture_cleanup
(
"symlink"
);
cl_repo_set_bool
(
g_repo
,
"core.symlinks"
,
true
);
opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_RECREATE_MISSING
;
cl_git_fail
(
git_checkout_index
(
g_repo
,
NULL
,
&
opts
));
}
}
void
test_checkout_index__honor_coresymlinks_setting_set_to_true
(
void
)
void
test_checkout_index__honor_coresymlinks_setting_set_to_true
(
void
)
{
{
git_checkout_options
opts
=
GIT_CHECKOUT_OPTIONS_INIT
;
git_checkout_options
opts
=
GIT_CHECKOUT_OPTIONS_INIT
;
char
link_data
[
GIT_PATH_MAX
];
size_t
link_size
=
GIT_PATH_MAX
;
if
(
!
filesystem_supports_symlinks
(
"testrepo/test"
))
{
cl_skip
();
}
cl_repo_set_bool
(
g_repo
,
"core.symlinks"
,
true
);
cl_repo_set_bool
(
g_repo
,
"core.symlinks"
,
true
);
...
@@ -190,20 +248,11 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
...
@@ -190,20 +248,11 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
cl_git_pass
(
git_checkout_index
(
g_repo
,
NULL
,
&
opts
));
cl_git_pass
(
git_checkout_index
(
g_repo
,
NULL
,
&
opts
));
#ifdef GIT_WIN32
link_size
=
p_readlink
(
"./testrepo/link_to_new.txt"
,
link_data
,
link_size
);
check_file_contents
(
"./testrepo/link_to_new.txt"
,
"new.txt"
);
link_data
[
link_size
]
=
'\0'
;
#else
cl_assert_equal_i
(
link_size
,
strlen
(
"new.txt"
));
{
cl_assert_equal_s
(
link_data
,
"new.txt"
);
char
link_data
[
1024
];
check_file_contents
(
"./testrepo/link_to_new.txt"
,
"my new file
\n
"
);
size_t
link_size
=
1024
;
link_size
=
p_readlink
(
"./testrepo/link_to_new.txt"
,
link_data
,
link_size
);
link_data
[
link_size
]
=
'\0'
;
cl_assert_equal_i
(
link_size
,
strlen
(
"new.txt"
));
cl_assert_equal_s
(
link_data
,
"new.txt"
);
check_file_contents
(
"./testrepo/link_to_new.txt"
,
"my new file
\n
"
);
}
#endif
}
}
void
test_checkout_index__honor_coresymlinks_setting_set_to_false
(
void
)
void
test_checkout_index__honor_coresymlinks_setting_set_to_false
(
void
)
...
@@ -474,7 +523,7 @@ void test_checkout_index__can_overcome_name_clashes(void)
...
@@ -474,7 +523,7 @@ void test_checkout_index__can_overcome_name_clashes(void)
cl_assert
(
git_path_isfile
(
"./testrepo/path0/file0"
));
cl_assert
(
git_path_isfile
(
"./testrepo/path0/file0"
));
opts
.
checkout_strategy
=
opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_SAFE
|
GIT_CHECKOUT_RECREATE_MISSING
|
GIT_CHECKOUT_RECREATE_MISSING
|
GIT_CHECKOUT_ALLOW_CONFLICTS
;
GIT_CHECKOUT_ALLOW_CONFLICTS
;
cl_git_pass
(
git_checkout_index
(
g_repo
,
index
,
&
opts
));
cl_git_pass
(
git_checkout_index
(
g_repo
,
index
,
&
opts
));
...
@@ -547,9 +596,9 @@ void test_checkout_index__can_update_prefixed_files(void)
...
@@ -547,9 +596,9 @@ void test_checkout_index__can_update_prefixed_files(void)
void
test_checkout_index__can_checkout_a_newly_initialized_repository
(
void
)
void
test_checkout_index__can_checkout_a_newly_initialized_repository
(
void
)
{
{
test_checkout_index__cleanup
();
cl_git_sandbox_cleanup
();
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
cl_git_remove_placeholders
(
git_repository_path
(
g_repo
),
"dummy-marker.txt"
);
cl_git_remove_placeholders
(
git_repository_path
(
g_repo
),
"dummy-marker.txt"
);
cl_git_pass
(
git_checkout_index
(
g_repo
,
NULL
,
NULL
));
cl_git_pass
(
git_checkout_index
(
g_repo
,
NULL
,
NULL
));
...
@@ -559,8 +608,7 @@ void test_checkout_index__issue_1397(void)
...
@@ -559,8 +608,7 @@ void test_checkout_index__issue_1397(void)
{
{
git_checkout_options
opts
=
GIT_CHECKOUT_OPTIONS_INIT
;
git_checkout_options
opts
=
GIT_CHECKOUT_OPTIONS_INIT
;
test_checkout_index__cleanup
();
cl_git_sandbox_cleanup
();
g_repo
=
cl_git_sandbox_init
(
"issue_1397"
);
g_repo
=
cl_git_sandbox_init
(
"issue_1397"
);
cl_repo_set_bool
(
g_repo
,
"core.autocrlf"
,
true
);
cl_repo_set_bool
(
g_repo
,
"core.autocrlf"
,
true
);
...
@@ -613,8 +661,7 @@ void test_checkout_index__target_directory_from_bare(void)
...
@@ -613,8 +661,7 @@ void test_checkout_index__target_directory_from_bare(void)
checkout_counts
cts
;
checkout_counts
cts
;
memset
(
&
cts
,
0
,
sizeof
(
cts
));
memset
(
&
cts
,
0
,
sizeof
(
cts
));
test_checkout_index__cleanup
();
cl_git_sandbox_cleanup
();
g_repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
g_repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
cl_assert
(
git_repository_is_bare
(
g_repo
));
cl_assert
(
git_repository_is_bare
(
g_repo
));
...
...
tests/repo/init.c
View file @
7321cff0
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
#include "config.h"
#include "config.h"
#include "path.h"
#include "path.h"
#include "config/config_helpers.h"
#include "config/config_helpers.h"
#include "repo/repo_helpers.h"
enum
repo_mode
{
enum
repo_mode
{
STANDARD_REPOSITORY
=
0
,
STANDARD_REPOSITORY
=
0
,
...
@@ -12,7 +13,6 @@ enum repo_mode {
...
@@ -12,7 +13,6 @@ enum repo_mode {
static
git_repository
*
_repo
=
NULL
;
static
git_repository
*
_repo
=
NULL
;
static
git_buf
_global_path
=
GIT_BUF_INIT
;
static
git_buf
_global_path
=
GIT_BUF_INIT
;
static
git_buf
_tmp_path
=
GIT_BUF_INIT
;
static
mode_t
g_umask
=
0
;
static
mode_t
g_umask
=
0
;
void
test_repo_init__initialize
(
void
)
void
test_repo_init__initialize
(
void
)
...
@@ -35,9 +35,7 @@ void test_repo_init__cleanup(void)
...
@@ -35,9 +35,7 @@ void test_repo_init__cleanup(void)
_global_path
.
ptr
);
_global_path
.
ptr
);
git_buf_dispose
(
&
_global_path
);
git_buf_dispose
(
&
_global_path
);
if
(
_tmp_path
.
size
>
0
&&
git_path_isdir
(
_tmp_path
.
ptr
))
cl_fixture_cleanup
(
"tmp_global_path"
);
git_futils_rmdir_r
(
_tmp_path
.
ptr
,
NULL
,
GIT_RMDIR_REMOVE_FILES
);
git_buf_dispose
(
&
_tmp_path
);
}
}
static
void
cleanup_repository
(
void
*
path
)
static
void
cleanup_repository
(
void
*
path
)
...
@@ -247,6 +245,68 @@ void test_repo_init__detect_ignorecase(void)
...
@@ -247,6 +245,68 @@ void test_repo_init__detect_ignorecase(void)
"core.ignorecase"
,
found_without_match
?
true
:
GIT_ENOTFOUND
);
"core.ignorecase"
,
found_without_match
?
true
:
GIT_ENOTFOUND
);
}
}
/*
* Windows: if the filesystem supports symlinks (because we're running
* as administrator, or because the user has opted into it for normal
* users) then we can also opt-in explicitly by settings `core.symlinks`
* in the global config. Symlinks remain off by default.
*/
void
test_repo_init__symlinks_win32_enabled_by_global_config
(
void
)
{
#ifndef GIT_WIN32
cl_skip
();
#else
git_config
*
config
,
*
repo_config
;
int
val
;
if
(
!
filesystem_supports_symlinks
(
"link"
))
cl_skip
();
create_tmp_global_config
(
"tmp_global_config"
,
"core.symlinks"
,
"true"
);
/*
* Create a new repository (can't use `assert_config_on_init` since we
* want to examine configuration levels with more granularity.)
*/
cl_git_pass
(
git_repository_init
(
&
_repo
,
"config_entry/test.non.bare.git"
,
false
));
/* Ensure that core.symlinks remains set (via the global config). */
cl_git_pass
(
git_repository_config
(
&
config
,
_repo
));
cl_git_pass
(
git_config_get_bool
(
&
val
,
config
,
"core.symlinks"
));
cl_assert_equal_i
(
1
,
val
);
/*
* Ensure that the repository config does not set core.symlinks.
* It should remain inherited.
*/
cl_git_pass
(
git_config_open_level
(
&
repo_config
,
config
,
GIT_CONFIG_LEVEL_LOCAL
));
cl_git_fail_with
(
GIT_ENOTFOUND
,
git_config_get_bool
(
&
val
,
repo_config
,
"core.symlinks"
));
git_config_free
(
repo_config
);
git_config_free
(
config
);
#endif
}
void
test_repo_init__symlinks_win32_off_by_default
(
void
)
{
#ifndef GIT_WIN32
cl_skip
();
#else
assert_config_entry_on_init
(
"core.symlinks"
,
false
);
#endif
}
void
test_repo_init__symlinks_posix_detected
(
void
)
{
#ifdef GIT_WIN32
cl_skip
();
#else
assert_config_entry_on_init
(
"core.symlinks"
,
filesystem_supports_symlinks
(
"link"
)
?
GIT_ENOTFOUND
:
false
);
#endif
}
void
test_repo_init__detect_precompose_unicode_required
(
void
)
void
test_repo_init__detect_precompose_unicode_required
(
void
)
{
{
#ifdef GIT_USE_ICONV
#ifdef GIT_USE_ICONV
...
@@ -563,26 +623,7 @@ static const char *template_sandbox(const char *name)
...
@@ -563,26 +623,7 @@ static const char *template_sandbox(const char *name)
static
void
configure_templatedir
(
const
char
*
template_path
)
static
void
configure_templatedir
(
const
char
*
template_path
)
{
{
git_buf
config_path
=
GIT_BUF_INIT
;
create_tmp_global_config
(
"tmp_global_path"
,
"init.templatedir"
,
template_path
);
git_buf
config_data
=
GIT_BUF_INIT
;
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_GET_SEARCH_PATH
,
GIT_CONFIG_LEVEL_GLOBAL
,
&
_tmp_path
));
cl_git_pass
(
git_buf_puts
(
&
_tmp_path
,
".tmp"
));
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_SEARCH_PATH
,
GIT_CONFIG_LEVEL_GLOBAL
,
_tmp_path
.
ptr
));
cl_must_pass
(
p_mkdir
(
_tmp_path
.
ptr
,
0777
));
cl_git_pass
(
git_buf_joinpath
(
&
config_path
,
_tmp_path
.
ptr
,
".gitconfig"
));
cl_git_pass
(
git_buf_printf
(
&
config_data
,
"[init]
\n\t
templatedir =
\"
%s
\"\n
"
,
template_path
));
cl_git_mkfile
(
config_path
.
ptr
,
config_data
.
ptr
);
git_buf_dispose
(
&
config_path
);
git_buf_dispose
(
&
config_data
);
}
}
static
void
validate_templates
(
git_repository
*
repo
,
const
char
*
template_path
)
static
void
validate_templates
(
git_repository
*
repo
,
const
char
*
template_path
)
...
...
tests/repo/repo_helpers.c
View file @
7321cff0
...
@@ -20,3 +20,33 @@ void delete_head(git_repository* repo)
...
@@ -20,3 +20,33 @@ void delete_head(git_repository* repo)
git_buf_dispose
(
&
head_path
);
git_buf_dispose
(
&
head_path
);
}
}
int
filesystem_supports_symlinks
(
const
char
*
path
)
{
struct
stat
st
;
bool
support
=
0
;
if
(
p_symlink
(
"target"
,
path
)
==
0
)
{
if
(
p_lstat
(
path
,
&
st
)
==
0
&&
S_ISLNK
(
st
.
st_mode
))
support
=
1
;
p_unlink
(
path
);
}
return
support
;
}
void
create_tmp_global_config
(
const
char
*
dirname
,
const
char
*
key
,
const
char
*
val
)
{
git_buf
path
=
GIT_BUF_INIT
;
git_config
*
config
;
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_SEARCH_PATH
,
GIT_CONFIG_LEVEL_GLOBAL
,
dirname
));
cl_must_pass
(
p_mkdir
(
dirname
,
0777
));
cl_git_pass
(
git_buf_joinpath
(
&
path
,
dirname
,
".gitconfig"
));
cl_git_pass
(
git_config_open_ondisk
(
&
config
,
path
.
ptr
));
cl_git_pass
(
git_config_set_string
(
config
,
key
,
val
));
git_config_free
(
config
);
git_buf_dispose
(
&
path
);
}
tests/repo/repo_helpers.h
View file @
7321cff0
...
@@ -4,3 +4,5 @@
...
@@ -4,3 +4,5 @@
extern
void
make_head_unborn
(
git_repository
*
repo
,
const
char
*
target
);
extern
void
make_head_unborn
(
git_repository
*
repo
,
const
char
*
target
);
extern
void
delete_head
(
git_repository
*
repo
);
extern
void
delete_head
(
git_repository
*
repo
);
extern
int
filesystem_supports_symlinks
(
const
char
*
path
);
extern
void
create_tmp_global_config
(
const
char
*
path
,
const
char
*
key
,
const
char
*
val
);
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