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
fcb2164f
Commit
fcb2164f
authored
Apr 13, 2012
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #623 from arrbee/refactor-open
Update git_repository_open
parents
6a625435
7784bcbb
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
562 additions
and
329 deletions
+562
-329
include/git2/repository.h
+14
-0
src/attr.c
+11
-9
src/config.c
+9
-18
src/diff.c
+1
-2
src/errors.c
+5
-1
src/path.c
+10
-13
src/repository.c
+255
-270
tests-clar/clar_helpers.c
+16
-5
tests-clar/clar_libgit2.h
+2
-0
tests-clar/repo/open.c
+239
-11
No files found.
include/git2/repository.h
View file @
fcb2164f
...
@@ -70,6 +70,20 @@ GIT_EXTERN(int) git_repository_discover(
...
@@ -70,6 +70,20 @@ GIT_EXTERN(int) git_repository_discover(
int
across_fs
,
int
across_fs
,
const
char
*
ceiling_dirs
);
const
char
*
ceiling_dirs
);
enum
{
GIT_REPOSITORY_OPEN_NO_SEARCH
=
(
1
<<
0
),
GIT_REPOSITORY_OPEN_CROSS_FS
=
(
1
<<
1
),
};
/**
* Find and open a repository with extended controls.
*/
GIT_EXTERN
(
int
)
git_repository_open_ext
(
git_repository
**
repo
,
const
char
*
start_path
,
uint32_t
flags
,
const
char
*
ceiling_dirs
);
/**
/**
* Free a previously allocated repository
* Free a previously allocated repository
*
*
...
...
src/attr.c
View file @
fcb2164f
...
@@ -347,6 +347,7 @@ static int collect_attr_files(
...
@@ -347,6 +347,7 @@ static int collect_attr_files(
int
git_attr_cache__init
(
git_repository
*
repo
)
int
git_attr_cache__init
(
git_repository
*
repo
)
{
{
int
ret
;
git_attr_cache
*
cache
=
git_repository_attr_cache
(
repo
);
git_attr_cache
*
cache
=
git_repository_attr_cache
(
repo
);
git_config
*
cfg
;
git_config
*
cfg
;
...
@@ -354,17 +355,18 @@ int git_attr_cache__init(git_repository *repo)
...
@@ -354,17 +355,18 @@ int git_attr_cache__init(git_repository *repo)
return
0
;
return
0
;
/* cache config settings for attributes and ignores */
/* cache config settings for attributes and ignores */
if
(
git_repository_config
(
&
cfg
,
repo
)
<
0
)
if
(
git_repository_config
__weakptr
(
&
cfg
,
repo
)
<
0
)
return
-
1
;
return
-
1
;
if
(
git_config_get_string
(
cfg
,
GIT_ATTR_CONFIG
,
&
cache
->
cfg_attr_file
))
{
giterr_clear
();
ret
=
git_config_get_string
(
cfg
,
GIT_ATTR_CONFIG
,
&
cache
->
cfg_attr_file
);
cache
->
cfg_attr_file
=
NULL
;
if
(
ret
<
0
&&
ret
!=
GIT_ENOTFOUND
)
}
return
ret
;
if
(
git_config_get_string
(
cfg
,
GIT_IGNORE_CONFIG
,
&
cache
->
cfg_excl_file
))
{
ret
=
git_config_get_string
(
cfg
,
GIT_IGNORE_CONFIG
,
&
cache
->
cfg_excl_file
);
if
(
ret
<
0
&&
ret
!=
GIT_ENOTFOUND
)
return
ret
;
giterr_clear
();
giterr_clear
();
cache
->
cfg_excl_file
=
NULL
;
}
git_config_free
(
cfg
);
/* allocate hashtable for attribute and ignore file contents */
/* allocate hashtable for attribute and ignore file contents */
if
(
cache
->
files
==
NULL
)
{
if
(
cache
->
files
==
NULL
)
{
...
...
src/config.c
View file @
fcb2164f
...
@@ -327,11 +327,11 @@ int git_config_lookup_map_value(
...
@@ -327,11 +327,11 @@ int git_config_lookup_map_value(
int
git_config_get_mapped
(
git_config
*
cfg
,
const
char
*
name
,
git_cvar_map
*
maps
,
size_t
map_n
,
int
*
out
)
int
git_config_get_mapped
(
git_config
*
cfg
,
const
char
*
name
,
git_cvar_map
*
maps
,
size_t
map_n
,
int
*
out
)
{
{
const
char
*
value
;
const
char
*
value
;
int
error
;
int
ret
;
error
=
git_config_get_string
(
cfg
,
name
,
&
value
);
ret
=
git_config_get_string
(
cfg
,
name
,
&
value
);
if
(
error
<
0
)
if
(
ret
<
0
)
return
error
;
return
ret
;
if
(
!
git_config_lookup_map_value
(
maps
,
map_n
,
value
,
out
))
if
(
!
git_config_lookup_map_value
(
maps
,
map_n
,
value
,
out
))
return
0
;
return
0
;
...
@@ -399,25 +399,16 @@ int git_config_get_bool(git_config *cfg, const char *name, int *out)
...
@@ -399,25 +399,16 @@ int git_config_get_bool(git_config *cfg, const char *name, int *out)
int
git_config_get_string
(
git_config
*
cfg
,
const
char
*
name
,
const
char
**
out
)
int
git_config_get_string
(
git_config
*
cfg
,
const
char
*
name
,
const
char
**
out
)
{
{
file_internal
*
internal
;
file_internal
*
internal
;
git_config_file
*
file
;
int
ret
=
GIT_ENOTFOUND
;
unsigned
int
i
;
unsigned
int
i
;
assert
(
cfg
->
files
.
length
);
assert
(
cfg
->
files
.
length
);
for
(
i
=
0
;
i
<
cfg
->
files
.
length
;
++
i
)
{
*
out
=
NULL
;
internal
=
git_vector_get
(
&
cfg
->
files
,
i
);
file
=
internal
->
file
;
ret
=
file
->
get
(
file
,
name
,
out
);
if
(
ret
==
0
)
return
0
;
/* File backend doesn't set error message on variable
* not found */
if
(
ret
==
GIT_ENOTFOUND
)
continue
;
git_vector_foreach
(
&
cfg
->
files
,
i
,
internal
)
{
git_config_file
*
file
=
internal
->
file
;
int
ret
=
file
->
get
(
file
,
name
,
out
);
if
(
ret
!=
GIT_ENOTFOUND
)
return
ret
;
return
ret
;
}
}
...
...
src/diff.c
View file @
fcb2164f
...
@@ -253,7 +253,7 @@ static git_diff_list *git_diff_list_alloc(
...
@@ -253,7 +253,7 @@ static git_diff_list *git_diff_list_alloc(
diff
->
repo
=
repo
;
diff
->
repo
=
repo
;
/* load config values that affect diff behavior */
/* load config values that affect diff behavior */
if
(
git_repository_config
(
&
cfg
,
repo
)
<
0
)
if
(
git_repository_config
__weakptr
(
&
cfg
,
repo
)
<
0
)
goto
fail
;
goto
fail
;
if
(
config_bool
(
cfg
,
"core.symlinks"
,
1
))
if
(
config_bool
(
cfg
,
"core.symlinks"
,
1
))
diff
->
diffcaps
=
diff
->
diffcaps
|
GIT_DIFFCAPS_HAS_SYMLINKS
;
diff
->
diffcaps
=
diff
->
diffcaps
|
GIT_DIFFCAPS_HAS_SYMLINKS
;
...
@@ -264,7 +264,6 @@ static git_diff_list *git_diff_list_alloc(
...
@@ -264,7 +264,6 @@ static git_diff_list *git_diff_list_alloc(
if
(
config_bool
(
cfg
,
"core.trustctime"
,
1
))
if
(
config_bool
(
cfg
,
"core.trustctime"
,
1
))
diff
->
diffcaps
=
diff
->
diffcaps
|
GIT_DIFFCAPS_TRUST_CTIME
;
diff
->
diffcaps
=
diff
->
diffcaps
|
GIT_DIFFCAPS_TRUST_CTIME
;
/* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */
/* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */
git_config_free
(
cfg
);
if
(
opts
==
NULL
)
if
(
opts
==
NULL
)
return
diff
;
return
diff
;
...
...
src/errors.c
View file @
fcb2164f
...
@@ -92,8 +92,12 @@ const char *git_lasterror(void)
...
@@ -92,8 +92,12 @@ const char *git_lasterror(void)
{
{
char
*
last_error
=
GIT_GLOBAL
->
error
.
last
;
char
*
last_error
=
GIT_GLOBAL
->
error
.
last
;
if
(
!
last_error
[
0
])
if
(
!
last_error
[
0
])
{
const
git_error
*
err
=
git_error_last
();
if
(
err
!=
NULL
)
return
err
->
message
;
return
NULL
;
return
NULL
;
}
return
last_error
;
return
last_error
;
}
}
...
...
src/path.c
View file @
fcb2164f
...
@@ -172,20 +172,22 @@ int git_path_root(const char *path)
...
@@ -172,20 +172,22 @@ int git_path_root(const char *path)
if
(
isalpha
(
path
[
0
])
&&
(
path
[
1
]
==
':'
))
if
(
isalpha
(
path
[
0
])
&&
(
path
[
1
]
==
':'
))
offset
+=
2
;
offset
+=
2
;
/* Are we dealing with a network path? */
/* Are we dealing with a windows network path? */
else
if
(
path
[
0
]
==
'/'
&&
path
[
1
]
==
'/'
)
{
else
if
((
path
[
0
]
==
'/'
&&
path
[
1
]
==
'/'
)
||
(
path
[
0
]
==
'\\'
&&
path
[
1
]
==
'\\'
))
{
offset
+=
2
;
offset
+=
2
;
/* Skip the computer name segment */
/* Skip the computer name segment */
while
(
*
(
path
+
offset
)
&&
*
(
path
+
offset
)
!=
'/
'
)
while
(
path
[
offset
]
&&
path
[
offset
]
!=
'/'
&&
path
[
offset
]
!=
'\\
'
)
offset
++
;
offset
++
;
}
}
#endif
#endif
if
(
*
(
path
+
offset
)
==
'/
'
)
if
(
path
[
offset
]
==
'/'
||
path
[
offset
]
==
'\\
'
)
return
offset
;
return
offset
;
return
-
1
;
/* Not a real error
. Rather a signal than the
path is not rooted */
return
-
1
;
/* Not a real error
- signals that
path is not rooted */
}
}
int
git_path_prettify
(
git_buf
*
path_out
,
const
char
*
path
,
const
char
*
base
)
int
git_path_prettify
(
git_buf
*
path_out
,
const
char
*
path
,
const
char
*
base
)
...
@@ -193,26 +195,21 @@ int git_path_prettify(git_buf *path_out, const char *path, const char *base)
...
@@ -193,26 +195,21 @@ int git_path_prettify(git_buf *path_out, const char *path, const char *base)
char
buf
[
GIT_PATH_MAX
];
char
buf
[
GIT_PATH_MAX
];
assert
(
path
&&
path_out
);
assert
(
path
&&
path_out
);
git_buf_clear
(
path_out
);
/* construct path if needed */
/* construct path if needed */
if
(
base
!=
NULL
&&
git_path_root
(
path
)
<
0
)
{
if
(
base
!=
NULL
&&
git_path_root
(
path
)
<
0
)
{
if
(
git_buf_joinpath
(
path_out
,
base
,
path
)
<
0
)
if
(
git_buf_joinpath
(
path_out
,
base
,
path
)
<
0
)
return
-
1
;
return
-
1
;
path
=
path_out
->
ptr
;
path
=
path_out
->
ptr
;
}
}
if
(
p_realpath
(
path
,
buf
)
==
NULL
)
{
if
(
p_realpath
(
path
,
buf
)
==
NULL
)
{
giterr_set
(
GITERR_OS
,
"Failed to resolve path '%s'
: %s"
,
giterr_set
(
GITERR_OS
,
"Failed to resolve path '%s'
"
,
path
);
path
,
strerror
(
errno
)
);
git_buf_clear
(
path_out
);
return
(
errno
==
ENOENT
)
?
GIT_ENOTFOUND
:
-
1
;
return
(
errno
==
ENOENT
)
?
GIT_ENOTFOUND
:
-
1
;
}
}
if
(
git_buf_sets
(
path_out
,
buf
)
<
0
)
return
git_buf_sets
(
path_out
,
buf
);
return
-
1
;
return
0
;
}
}
int
git_path_prettify_dir
(
git_buf
*
path_out
,
const
char
*
path
,
const
char
*
base
)
int
git_path_prettify_dir
(
git_buf
*
path_out
,
const
char
*
path
,
const
char
*
base
)
...
...
src/repository.c
View file @
fcb2164f
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
* a Linking Exception. For full terms see the included COPYING file.
*/
*/
#include <stdarg.h>
#include <stdarg.h>
#include <ctype.h>
#include "git2/object.h"
#include "git2/object.h"
...
@@ -20,7 +21,7 @@
...
@@ -20,7 +21,7 @@
#define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
#define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
#define GIT_FILE_CONTENT_PREFIX "gitdir:
"
#define GIT_FILE_CONTENT_PREFIX "gitdir:"
#define GIT_BRANCH_MASTER "master"
#define GIT_BRANCH_MASTER "master"
...
@@ -132,69 +133,287 @@ static int load_config_data(git_repository *repo)
...
@@ -132,69 +133,287 @@ static int load_config_data(git_repository *repo)
return
0
;
return
0
;
}
}
static
int
load_workdir
(
git_repository
*
repo
)
static
int
load_workdir
(
git_repository
*
repo
,
git_buf
*
parent_path
)
{
{
git_buf
workdir_buf
=
GIT_BUF_INIT
;
int
error
;
git_config
*
config
;
const
char
*
worktree
;
git_buf
worktree_buf
=
GIT_BUF_INIT
;
if
(
repo
->
is_bare
)
if
(
repo
->
is_bare
)
return
0
;
return
0
;
git_path_dirname_r
(
&
workdir_buf
,
repo
->
path_repository
);
if
(
git_repository_config__weakptr
(
&
config
,
repo
)
<
0
)
git_path_to_dir
(
&
workdir_buf
);
if
(
git_buf_oom
(
&
workdir_buf
))
return
-
1
;
return
-
1
;
repo
->
workdir
=
git_buf_detach
(
&
workdir_buf
);
error
=
git_config_get_string
(
config
,
"core.worktree"
,
&
worktree
);
git_buf_free
(
&
workdir_buf
);
if
(
!
error
&&
worktree
!=
NULL
)
repo
->
workdir
=
git__strdup
(
worktree
);
else
if
(
error
!=
GIT_ENOTFOUND
)
return
error
;
else
{
giterr_clear
();
if
(
parent_path
&&
git_path_isdir
(
parent_path
->
ptr
))
repo
->
workdir
=
git_buf_detach
(
parent_path
);
else
{
git_path_dirname_r
(
&
worktree_buf
,
repo
->
path_repository
);
git_path_to_dir
(
&
worktree_buf
);
repo
->
workdir
=
git_buf_detach
(
&
worktree_buf
);
}
}
GITERR_CHECK_ALLOC
(
repo
->
workdir
);
return
0
;
return
0
;
}
}
int
git_repository_open
(
git_repository
**
repo_out
,
const
char
*
path
)
/*
* This function returns furthest offset into path where a ceiling dir
* is found, so we can stop processing the path at that point.
*
* Note: converting this to use git_bufs instead of GIT_PATH_MAX buffers on
* the stack could remove directories name limits, but at the cost of doing
* repeated malloc/frees inside the loop below, so let's not do it now.
*/
static
int
find_ceiling_dir_offset
(
const
char
*
path
,
const
char
*
ceiling_directories
)
{
{
git_buf
path_buf
=
GIT_BUF_INIT
;
char
buf
[
GIT_PATH_MAX
+
1
];
git_repository
*
repo
=
NULL
;
char
buf2
[
GIT_PATH_MAX
+
1
];
int
res
;
const
char
*
ceil
,
*
sep
;
int
len
,
max_len
=
-
1
;
int
min_len
;
res
=
git_path_prettify_dir
(
&
path_buf
,
path
,
NULL
);
assert
(
path
);
if
(
res
<
0
)
return
res
;
min_len
=
git_path_root
(
path
)
+
1
;
if
(
ceiling_directories
==
NULL
||
min_len
==
0
)
return
min_len
;
for
(
sep
=
ceil
=
ceiling_directories
;
*
sep
;
ceil
=
sep
+
1
)
{
for
(
sep
=
ceil
;
*
sep
&&
*
sep
!=
GIT_PATH_LIST_SEPARATOR
;
sep
++
);
len
=
sep
-
ceil
;
/**
if
(
len
==
0
||
len
>=
(
int
)
sizeof
(
buf
)
||
git_path_root
(
ceil
)
==
-
1
)
* Check if the path we've been given is actually the path
continue
;
* of the working dir, by testing if it contains a `.git`
* folder inside of it.
strncpy
(
buf
,
ceil
,
len
);
buf
[
len
]
=
'\0'
;
if
(
p_realpath
(
buf
,
buf2
)
==
NULL
)
continue
;
len
=
strlen
(
buf2
);
if
(
len
>
0
&&
buf2
[
len
-
1
]
==
'/'
)
buf
[
--
len
]
=
'\0'
;
if
(
!
strncmp
(
path
,
buf2
,
len
)
&&
path
[
len
]
==
'/'
&&
len
>
max_len
)
{
max_len
=
len
;
}
}
return
max_len
<=
min_len
?
min_len
:
max_len
;
}
/*
* Read the contents of `file_path` and set `path_out` to the repo dir that
* it points to. Before calling, set `path_out` to the base directory that
* should be used if the contents of `file_path` are a relative path.
*/
*/
if
(
git_path_contains_dir
(
&
path_buf
,
GIT_DIR
)
==
true
)
static
int
read_gitfile
(
git_buf
*
path_out
,
const
char
*
file_path
)
git_buf_joinpath
(
&
path_buf
,
path_buf
.
ptr
,
GIT_DIR
);
{
int
error
=
0
;
git_buf
file
=
GIT_BUF_INIT
;
size_t
prefix_len
=
strlen
(
GIT_FILE_CONTENT_PREFIX
);
assert
(
path_out
&&
file_path
);
if
(
valid_repository_path
(
&
path_buf
)
==
false
)
{
if
(
git_futils_readbuffer
(
&
file
,
file_path
)
<
0
)
return
-
1
;
git_buf_rtrim
(
&
file
);
if
(
file
.
size
<=
prefix_len
||
memcmp
(
file
.
ptr
,
GIT_FILE_CONTENT_PREFIX
,
prefix_len
)
!=
0
)
{
giterr_set
(
GITERR_REPOSITORY
,
"The `.git` file at '%s' is malformed"
,
file_path
);
error
=
-
1
;
}
else
if
((
error
=
git_path_dirname_r
(
path_out
,
file_path
))
>=
0
)
{
const
char
*
gitlink
=
((
const
char
*
)
file
.
ptr
)
+
prefix_len
;
while
(
*
gitlink
&&
isspace
(
*
gitlink
))
gitlink
++
;
error
=
git_path_prettify_dir
(
path_out
,
gitlink
,
path_out
->
ptr
);
}
git_buf_free
(
&
file
);
return
error
;
}
static
int
find_repo
(
git_buf
*
repo_path
,
git_buf
*
parent_path
,
const
char
*
start_path
,
uint32_t
flags
,
const
char
*
ceiling_dirs
)
{
int
error
;
git_buf
path
=
GIT_BUF_INIT
;
struct
stat
st
;
dev_t
initial_device
=
0
;
bool
try_with_dot_git
=
false
;
int
ceiling_offset
;
git_buf_free
(
repo_path
);
if
((
error
=
git_path_prettify_dir
(
&
path
,
start_path
,
NULL
))
<
0
)
return
error
;
ceiling_offset
=
find_ceiling_dir_offset
(
path
.
ptr
,
ceiling_dirs
);
if
((
error
=
git_buf_joinpath
(
&
path
,
path
.
ptr
,
DOT_GIT
))
<
0
)
return
error
;
while
(
!
error
&&
!
repo_path
->
size
)
{
if
(
p_stat
(
path
.
ptr
,
&
st
)
==
0
)
{
/* check that we have not crossed device boundaries */
if
(
initial_device
==
0
)
initial_device
=
st
.
st_dev
;
else
if
(
st
.
st_dev
!=
initial_device
&&
(
flags
&
GIT_REPOSITORY_OPEN_CROSS_FS
)
==
0
)
break
;
if
(
S_ISDIR
(
st
.
st_mode
))
{
if
(
valid_repository_path
(
&
path
))
{
git_path_to_dir
(
&
path
);
git_buf_set
(
repo_path
,
path
.
ptr
,
path
.
size
);
break
;
}
}
else
if
(
S_ISREG
(
st
.
st_mode
))
{
git_buf
repo_link
=
GIT_BUF_INIT
;
if
(
!
(
error
=
read_gitfile
(
&
repo_link
,
path
.
ptr
)))
{
if
(
valid_repository_path
(
&
repo_link
))
git_buf_swap
(
repo_path
,
&
repo_link
);
break
;
}
git_buf_free
(
&
repo_link
);
}
}
/* move up one directory level */
if
(
git_path_dirname_r
(
&
path
,
path
.
ptr
)
<
0
)
{
error
=
-
1
;
break
;
}
if
(
try_with_dot_git
)
{
/* if we tried original dir with and without .git AND either hit
* directory ceiling or NO_SEARCH was requested, then be done.
*/
if
(
path
.
ptr
[
ceiling_offset
]
==
'\0'
||
(
flags
&
GIT_REPOSITORY_OPEN_NO_SEARCH
)
!=
0
)
break
;
/* otherwise look first for .git item */
error
=
git_buf_joinpath
(
&
path
,
path
.
ptr
,
DOT_GIT
);
}
try_with_dot_git
=
!
try_with_dot_git
;
}
if
(
!
error
&&
parent_path
!=
NULL
)
{
if
(
!
repo_path
->
size
)
git_buf_clear
(
parent_path
);
else
{
git_path_dirname_r
(
parent_path
,
path
.
ptr
);
git_path_to_dir
(
parent_path
);
}
if
(
git_buf_oom
(
parent_path
))
return
-
1
;
}
git_buf_free
(
&
path
);
if
(
!
repo_path
->
size
&&
!
error
)
{
giterr_set
(
GITERR_REPOSITORY
,
giterr_set
(
GITERR_REPOSITORY
,
"The given path (%s) is not a valid Git repository"
,
git_buf_cstr
(
&
path_buf
));
"Could not find repository from '%s'"
,
start_path
);
git_buf_free
(
&
path_buf
);
error
=
GIT_ENOTFOUND
;
return
GIT_ENOTFOUND
;
}
}
return
error
;
}
int
git_repository_open_ext
(
git_repository
**
repo_ptr
,
const
char
*
start_path
,
uint32_t
flags
,
const
char
*
ceiling_dirs
)
{
int
error
;
git_buf
path
=
GIT_BUF_INIT
,
parent
=
GIT_BUF_INIT
;
git_repository
*
repo
;
*
repo_ptr
=
NULL
;
if
((
error
=
find_repo
(
&
path
,
&
parent
,
start_path
,
flags
,
ceiling_dirs
))
<
0
)
return
error
;
repo
=
repository_alloc
();
repo
=
repository_alloc
();
GITERR_CHECK_ALLOC
(
repo
);
GITERR_CHECK_ALLOC
(
repo
);
repo
->
path_repository
=
git_buf_detach
(
&
path
_buf
);
repo
->
path_repository
=
git_buf_detach
(
&
path
);
GITERR_CHECK_ALLOC
(
repo
->
path_repository
);
GITERR_CHECK_ALLOC
(
repo
->
path_repository
);
if
(
load_config_data
(
repo
)
<
0
)
if
((
error
=
load_config_data
(
repo
))
<
0
||
goto
cleanup
;
(
error
=
load_workdir
(
repo
,
&
parent
))
<
0
)
{
if
(
load_workdir
(
repo
)
<
0
)
git_repository_free
(
repo
);
goto
cleanup
;
return
error
;
}
*
repo_
out
=
repo
;
*
repo_
ptr
=
repo
;
return
0
;
return
0
;
}
cleanup:
int
git_repository_open
(
git_repository
**
repo_out
,
const
char
*
path
)
git_repository_free
(
repo
);
{
git_buf_free
(
&
path_buf
);
return
git_repository_open_ext
(
repo_out
,
path
,
GIT_REPOSITORY_OPEN_NO_SEARCH
,
NULL
);
}
int
git_repository_discover
(
char
*
repository_path
,
size_t
size
,
const
char
*
start_path
,
int
across_fs
,
const
char
*
ceiling_dirs
)
{
git_buf
path
=
GIT_BUF_INIT
;
uint32_t
flags
=
across_fs
?
GIT_REPOSITORY_OPEN_CROSS_FS
:
0
;
assert
(
start_path
&&
repository_path
&&
size
>
0
);
*
repository_path
=
'\0'
;
if
(
find_repo
(
&
path
,
NULL
,
start_path
,
flags
,
ceiling_dirs
)
<
0
)
return
-
1
;
if
(
size
<
(
size_t
)(
path
.
size
+
1
))
{
giterr_set
(
GITERR_REPOSITORY
,
"The given buffer is too long to store the discovered path"
);
git_buf_free
(
&
path
);
return
-
1
;
return
-
1
;
}
/* success: we discovered a repository */
git_buf_copy_cstr
(
repository_path
,
size
,
&
path
);
git_buf_free
(
&
path
);
return
0
;
}
}
static
int
load_config
(
static
int
load_config
(
...
@@ -375,240 +594,6 @@ void git_repository_set_index(git_repository *repo, git_index *index)
...
@@ -375,240 +594,6 @@ void git_repository_set_index(git_repository *repo, git_index *index)
GIT_REFCOUNT_OWN
(
repo
->
_index
,
repo
);
GIT_REFCOUNT_OWN
(
repo
->
_index
,
repo
);
}
}
static
int
retrieve_device
(
dev_t
*
device_out
,
const
char
*
path
)
{
int
error
;
struct
stat
path_info
;
assert
(
device_out
);
if
((
error
=
git_path_lstat
(
path
,
&
path_info
))
==
0
)
*
device_out
=
path_info
.
st_dev
;
return
error
;
}
/*
* This function returns furthest offset into path where a ceiling dir
* is found, so we can stop processing the path at that point.
*
* Note: converting this to use git_bufs instead of GIT_PATH_MAX buffers on
* the stack could remove directories name limits, but at the cost of doing
* repeated malloc/frees inside the loop below, so let's not do it now.
*/
static
int
retrieve_ceiling_directories_offset
(
const
char
*
path
,
const
char
*
ceiling_directories
)
{
char
buf
[
GIT_PATH_MAX
+
1
];
char
buf2
[
GIT_PATH_MAX
+
1
];
const
char
*
ceil
,
*
sep
;
int
len
,
max_len
=
-
1
;
int
min_len
;
assert
(
path
);
min_len
=
git_path_root
(
path
)
+
1
;
if
(
ceiling_directories
==
NULL
||
min_len
==
0
)
return
min_len
;
for
(
sep
=
ceil
=
ceiling_directories
;
*
sep
;
ceil
=
sep
+
1
)
{
for
(
sep
=
ceil
;
*
sep
&&
*
sep
!=
GIT_PATH_LIST_SEPARATOR
;
sep
++
);
len
=
sep
-
ceil
;
if
(
len
==
0
||
len
>=
(
int
)
sizeof
(
buf
)
||
git_path_root
(
ceil
)
==
-
1
)
continue
;
strncpy
(
buf
,
ceil
,
len
);
buf
[
len
]
=
'\0'
;
if
(
p_realpath
(
buf
,
buf2
)
==
NULL
)
continue
;
len
=
strlen
(
buf2
);
if
(
len
>
0
&&
buf2
[
len
-
1
]
==
'/'
)
buf
[
--
len
]
=
'\0'
;
if
(
!
strncmp
(
path
,
buf2
,
len
)
&&
path
[
len
]
==
'/'
&&
len
>
max_len
)
{
max_len
=
len
;
}
}
return
max_len
<=
min_len
?
min_len
:
max_len
;
}
/*
* Read the contents of `file_path` and set `path_out` to the repo dir that
* it points to. Before calling, set `path_out` to the base directory that
* should be used if the contents of `file_path` are a relative path.
*/
static
int
read_gitfile
(
git_buf
*
path_out
,
const
char
*
file_path
,
const
char
*
base_path
)
{
git_buf
file
=
GIT_BUF_INIT
;
assert
(
path_out
&&
file_path
);
if
(
git_futils_readbuffer
(
&
file
,
file_path
)
<
0
)
return
-
1
;
git_buf_rtrim
(
&
file
);
if
(
git__prefixcmp
((
char
*
)
file
.
ptr
,
GIT_FILE_CONTENT_PREFIX
)
!=
0
||
strlen
(
GIT_FILE_CONTENT_PREFIX
)
==
file
.
size
)
{
git_buf_free
(
&
file
);
giterr_set
(
GITERR_REPOSITORY
,
"The `.git` file at '%s' is corrupted"
,
file_path
);
return
-
1
;
}
if
(
git_path_prettify_dir
(
path_out
,
((
char
*
)
file
.
ptr
)
+
strlen
(
GIT_FILE_CONTENT_PREFIX
),
base_path
)
<
0
)
{
git_buf_free
(
&
file
);
giterr_set
(
GITERR_REPOSITORY
,
"The `.git` file at '%s' points to an invalid path."
,
file_path
);
return
-
1
;
}
git_buf_free
(
&
file
);
return
0
;
}
int
git_repository_discover
(
char
*
repository_path
,
size_t
size
,
const
char
*
start_path
,
int
across_fs
,
const
char
*
ceiling_dirs
)
{
int
res
,
ceiling_offset
;
git_buf
bare_path
=
GIT_BUF_INIT
;
git_buf
normal_path
=
GIT_BUF_INIT
;
git_buf
*
found_path
=
NULL
;
dev_t
current_device
=
0
;
assert
(
start_path
&&
repository_path
);
*
repository_path
=
'\0'
;
res
=
git_path_prettify_dir
(
&
bare_path
,
start_path
,
NULL
);
if
(
res
<
0
)
return
res
;
if
(
!
across_fs
)
{
if
(
retrieve_device
(
&
current_device
,
bare_path
.
ptr
)
<
0
)
goto
on_error
;
}
ceiling_offset
=
retrieve_ceiling_directories_offset
(
bare_path
.
ptr
,
ceiling_dirs
);
while
(
1
)
{
if
(
git_buf_joinpath
(
&
normal_path
,
bare_path
.
ptr
,
DOT_GIT
)
<
0
)
goto
on_error
;
/**
* If the `.git` file is regular instead of
* a directory, it should contain the path of the actual git repository
*/
if
(
git_path_isfile
(
normal_path
.
ptr
)
==
true
)
{
git_buf
gitfile_path
=
GIT_BUF_INIT
;
if
(
read_gitfile
(
&
gitfile_path
,
normal_path
.
ptr
,
bare_path
.
ptr
)
<
0
)
{
git_buf_free
(
&
gitfile_path
);
goto
on_error
;
}
if
(
valid_repository_path
(
&
gitfile_path
)
==
false
)
{
git_buf_free
(
&
gitfile_path
);
giterr_set
(
GITERR_REPOSITORY
,
"The `.git` file found at '%s' points to an invalid git folder"
,
normal_path
.
ptr
);
goto
on_error
;
}
git_buf_swap
(
&
normal_path
,
&
gitfile_path
);
found_path
=
&
normal_path
;
git_buf_free
(
&
gitfile_path
);
break
;
}
/**
* If the `.git` file is a folder, we check inside of it
*/
if
(
git_path_isdir
(
normal_path
.
ptr
)
==
true
)
{
if
(
valid_repository_path
(
&
normal_path
)
==
true
)
{
found_path
=
&
normal_path
;
break
;
}
}
/**
* Otherwise, the repository may be bare, let's check
* the root anyway
*/
if
(
valid_repository_path
(
&
bare_path
)
==
true
)
{
found_path
=
&
bare_path
;
break
;
}
/**
* If we didn't find it, walk up the tree
*/
if
(
git_path_dirname_r
(
&
normal_path
,
bare_path
.
ptr
)
<
0
)
goto
on_error
;
git_buf_swap
(
&
bare_path
,
&
normal_path
);
if
(
!
across_fs
)
{
dev_t
new_device
;
if
(
retrieve_device
(
&
new_device
,
bare_path
.
ptr
)
<
0
)
goto
on_error
;
if
(
current_device
!=
new_device
)
goto
on_not_found
;
current_device
=
new_device
;
}
/* nothing has been found, lets try the parent directory
* but stop if we hit one of the ceiling directories
*/
if
(
bare_path
.
ptr
[
ceiling_offset
]
==
'\0'
)
goto
on_not_found
;
}
assert
(
found_path
);
if
(
git_path_to_dir
(
found_path
)
<
0
)
goto
on_error
;
if
(
size
<
(
size_t
)(
found_path
->
size
+
1
))
{
giterr_set
(
GITERR_REPOSITORY
,
"The given buffer is too long to store the discovered path"
);
goto
on_error
;
}
/* success: we discovered a repository */
git_buf_copy_cstr
(
repository_path
,
size
,
found_path
);
git_buf_free
(
&
bare_path
);
git_buf_free
(
&
normal_path
);
return
0
;
on_error:
/* unrecoverable error */
git_buf_free
(
&
bare_path
);
git_buf_free
(
&
normal_path
);
return
-
1
;
on_not_found:
/* failed to discover the repository */
git_buf_free
(
&
bare_path
);
git_buf_free
(
&
normal_path
);
return
GIT_ENOTFOUND
;
}
static
int
check_repositoryformatversion
(
git_repository
*
repo
)
static
int
check_repositoryformatversion
(
git_repository
*
repo
)
{
{
git_config
*
config
;
git_config
*
config
;
...
...
tests-clar/clar_helpers.c
View file @
fcb2164f
...
@@ -28,9 +28,9 @@ void cl_git_mkfile(const char *filename, const char *content)
...
@@ -28,9 +28,9 @@ void cl_git_mkfile(const char *filename, const char *content)
cl_must_pass
(
p_close
(
fd
));
cl_must_pass
(
p_close
(
fd
));
}
}
void
cl_git_
append2file
(
const
char
*
filename
,
const
char
*
new_content
)
void
cl_git_
write2file
(
const
char
*
filename
,
const
char
*
new_content
,
int
flags
)
{
{
int
fd
=
p_open
(
filename
,
O_WRONLY
|
O_APPEND
|
O_CREAT
);
int
fd
=
p_open
(
filename
,
flags
);
cl_assert
(
fd
!=
0
);
cl_assert
(
fd
!=
0
);
if
(
!
new_content
)
if
(
!
new_content
)
new_content
=
"
\n
"
;
new_content
=
"
\n
"
;
...
@@ -39,6 +39,16 @@ void cl_git_append2file(const char *filename, const char *new_content)
...
@@ -39,6 +39,16 @@ void cl_git_append2file(const char *filename, const char *new_content)
cl_must_pass
(
p_chmod
(
filename
,
0644
));
cl_must_pass
(
p_chmod
(
filename
,
0644
));
}
}
void
cl_git_append2file
(
const
char
*
filename
,
const
char
*
new_content
)
{
cl_git_write2file
(
filename
,
new_content
,
O_WRONLY
|
O_APPEND
|
O_CREAT
);
}
void
cl_git_rewritefile
(
const
char
*
filename
,
const
char
*
new_content
)
{
cl_git_write2file
(
filename
,
new_content
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
);
}
static
const
char
*
_cl_sandbox
=
NULL
;
static
const
char
*
_cl_sandbox
=
NULL
;
static
git_repository
*
_cl_repo
=
NULL
;
static
git_repository
*
_cl_repo
=
NULL
;
...
@@ -52,10 +62,11 @@ git_repository *cl_git_sandbox_init(const char *sandbox)
...
@@ -52,10 +62,11 @@ git_repository *cl_git_sandbox_init(const char *sandbox)
p_chdir
(
sandbox
);
p_chdir
(
sandbox
);
/*
Rename `sandbox/.gitted` to `sandbox/.git` which must be done since
/*
If this is not a bare repo, then rename `sandbox/.gitted` to
*
we cannot store a folder named `.git` inside the fixtures folder of
*
`sandbox/.git` which must be done since we cannot store a folder
* our libgit2 repo.
*
named `.git` inside the fixtures folder of
our libgit2 repo.
*/
*/
if
(
p_access
(
".gitted"
,
F_OK
)
==
0
)
cl_git_pass
(
p_rename
(
".gitted"
,
".git"
));
cl_git_pass
(
p_rename
(
".gitted"
,
".git"
));
/* If we have `gitattributes`, rename to `.gitattributes`. This may
/* If we have `gitattributes`, rename to `.gitattributes`. This may
...
...
tests-clar/clar_libgit2.h
View file @
fcb2164f
...
@@ -57,6 +57,8 @@ GIT_INLINE(void) cl_assert_strequal_internal(
...
@@ -57,6 +57,8 @@ GIT_INLINE(void) cl_assert_strequal_internal(
/* Write the contents of a buffer to disk */
/* Write the contents of a buffer to disk */
void
cl_git_mkfile
(
const
char
*
filename
,
const
char
*
content
);
void
cl_git_mkfile
(
const
char
*
filename
,
const
char
*
content
);
void
cl_git_append2file
(
const
char
*
filename
,
const
char
*
new_content
);
void
cl_git_append2file
(
const
char
*
filename
,
const
char
*
new_content
);
void
cl_git_rewritefile
(
const
char
*
filename
,
const
char
*
new_content
);
void
cl_git_write2file
(
const
char
*
filename
,
const
char
*
new_content
,
int
mode
);
/* Git sandbox setup helpers */
/* Git sandbox setup helpers */
...
...
tests-clar/repo/open.c
View file @
fcb2164f
#include "clar_libgit2.h"
#include "clar_libgit2.h"
#include "posix.h"
#include "fileops.h"
static
git_repository
*
repo
;
void
test_repo_open__cleanup
(
void
)
void
test_repo_open__cleanup
(
void
)
{
{
git_repository_free
(
repo
);
cl_git_sandbox_cleanup
();
if
(
git_path_isdir
(
"alternate"
))
git_futils_rmdir_r
(
"alternate"
,
1
);
}
}
void
test_repo_open__bare_empty_repo
(
void
)
void
test_repo_open__bare_empty_repo
(
void
)
{
{
cl_git_pass
(
git_repository_open
(
&
repo
,
cl_fixture
(
"empty_bare.git"
))
);
git_repository
*
repo
=
cl_git_sandbox_init
(
"empty_bare.git"
);
cl_assert
(
git_repository_path
(
repo
)
!=
NULL
);
cl_assert
(
git_repository_path
(
repo
)
!=
NULL
);
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo
),
"/"
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo
),
"/"
)
==
0
);
cl_assert
(
git_repository_workdir
(
repo
)
==
NULL
);
cl_assert
(
git_repository_workdir
(
repo
)
==
NULL
);
}
}
void
test_repo_open__standard_empty_repo_through_gitdir
(
void
)
void
test_repo_open__standard_empty_repo_through_gitdir
(
void
)
{
{
git_repository
*
repo
;
cl_git_pass
(
git_repository_open
(
&
repo
,
cl_fixture
(
"empty_standard_repo/.gitted"
)));
cl_git_pass
(
git_repository_open
(
&
repo
,
cl_fixture
(
"empty_standard_repo/.gitted"
)));
cl_assert
(
git_repository_path
(
repo
)
!=
NULL
);
cl_assert
(
git_repository_path
(
repo
)
!=
NULL
);
...
@@ -27,20 +29,246 @@ void test_repo_open__standard_empty_repo_through_gitdir(void)
...
@@ -27,20 +29,246 @@ void test_repo_open__standard_empty_repo_through_gitdir(void)
cl_assert
(
git_repository_workdir
(
repo
)
!=
NULL
);
cl_assert
(
git_repository_workdir
(
repo
)
!=
NULL
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo
),
"/"
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo
),
"/"
)
==
0
);
git_repository_free
(
repo
);
}
}
void
test_repo_open__standard_empty_repo_through_workdir
(
void
)
void
test_repo_open__standard_empty_repo_through_workdir
(
void
)
{
{
cl_fixture_sandbox
(
"empty_standard_repo"
);
git_repository
*
repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
cl_git_pass
(
p_rename
(
"empty_standard_repo/.gitted"
,
"empty_standard_repo/.git"
));
cl_git_pass
(
git_repository_open
(
&
repo
,
"empty_standard_repo"
));
cl_assert
(
git_repository_path
(
repo
)
!=
NULL
);
cl_assert
(
git_repository_path
(
repo
)
!=
NULL
);
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo
),
"/"
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo
),
"/"
)
==
0
);
cl_assert
(
git_repository_workdir
(
repo
)
!=
NULL
);
cl_assert
(
git_repository_workdir
(
repo
)
!=
NULL
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo
),
"/"
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo
),
"/"
)
==
0
);
}
void
test_repo_open__open_with_discover
(
void
)
{
static
const
char
*
variants
[]
=
{
"attr"
,
"attr/"
,
"attr/.git"
,
"attr/.git/"
,
"attr/sub"
,
"attr/sub/"
,
"attr/sub/sub"
,
"attr/sub/sub/"
,
NULL
};
git_repository
*
repo
;
const
char
**
scan
;
cl_fixture_sandbox
(
"attr"
);
cl_git_pass
(
p_rename
(
"attr/.gitted"
,
"attr/.git"
));
for
(
scan
=
variants
;
*
scan
!=
NULL
;
scan
++
)
{
cl_git_pass
(
git_repository_open_ext
(
&
repo
,
*
scan
,
0
,
NULL
));
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo
),
"attr/.git/"
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo
),
"attr/"
)
==
0
);
git_repository_free
(
repo
);
}
cl_fixture_cleanup
(
"attr"
);
}
void
test_repo_open__gitlinked
(
void
)
{
/* need to have both repo dir and workdir set up correctly */
git_repository
*
repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
git_repository
*
repo2
;
cl_must_pass
(
p_mkdir
(
"alternate"
,
0777
));
cl_git_mkfile
(
"alternate/.git"
,
"gitdir: ../empty_standard_repo/.git"
);
cl_git_pass
(
git_repository_open
(
&
repo2
,
"alternate"
));
cl_assert
(
git_repository_path
(
repo2
)
!=
NULL
);
cl_assert_
(
git__suffixcmp
(
git_repository_path
(
repo2
),
"empty_standard_repo/.git/"
)
==
0
,
git_repository_path
(
repo2
));
cl_assert_equal_s
(
git_repository_path
(
repo
),
git_repository_path
(
repo2
));
cl_assert
(
git_repository_workdir
(
repo2
)
!=
NULL
);
cl_assert_
(
git__suffixcmp
(
git_repository_workdir
(
repo2
),
"alternate/"
)
==
0
,
git_repository_workdir
(
repo2
));
git_repository_free
(
repo2
);
}
void
test_repo_open__from_git_new_workdir
(
void
)
{
/* The git-new-workdir script that ships with git sets up a bunch of
* symlinks to create a second workdir that shares the object db with
* another checkout. Libgit2 can open a repo that has been configured
* this way.
*/
cl_git_sandbox_init
(
"empty_standard_repo"
);
#ifndef GIT_WIN32
git_repository
*
repo2
;
git_buf
link_tgt
=
GIT_BUF_INIT
,
link
=
GIT_BUF_INIT
,
body
=
GIT_BUF_INIT
;
const
char
**
scan
;
int
link_fd
;
static
const
char
*
links
[]
=
{
"config"
,
"refs"
,
"logs/refs"
,
"objects"
,
"info"
,
"hooks"
,
"packed-refs"
,
"remotes"
,
"rr-cache"
,
"svn"
,
NULL
};
static
const
char
*
copies
[]
=
{
"HEAD"
,
NULL
};
cl_git_pass
(
p_mkdir
(
"alternate"
,
0777
));
cl_git_pass
(
p_mkdir
(
"alternate/.git"
,
0777
));
for
(
scan
=
links
;
*
scan
!=
NULL
;
scan
++
)
{
git_buf_joinpath
(
&
link_tgt
,
"empty_standard_repo/.git"
,
*
scan
);
if
(
git_path_exists
(
link_tgt
.
ptr
))
{
git_buf_joinpath
(
&
link_tgt
,
"../../empty_standard_repo/.git"
,
*
scan
);
git_buf_joinpath
(
&
link
,
"alternate/.git"
,
*
scan
);
if
(
strchr
(
*
scan
,
'/'
))
git_futils_mkpath2file
(
link
.
ptr
,
0777
);
cl_assert_
(
symlink
(
link_tgt
.
ptr
,
link
.
ptr
)
==
0
,
strerror
(
errno
));
}
}
for
(
scan
=
copies
;
*
scan
!=
NULL
;
scan
++
)
{
git_buf_joinpath
(
&
link_tgt
,
"empty_standard_repo/.git"
,
*
scan
);
if
(
git_path_exists
(
link_tgt
.
ptr
))
{
git_buf_joinpath
(
&
link
,
"alternate/.git"
,
*
scan
);
cl_git_pass
(
git_futils_readbuffer
(
&
body
,
link_tgt
.
ptr
));
cl_assert
((
link_fd
=
git_futils_creat_withpath
(
link
.
ptr
,
0777
,
0666
))
>=
0
);
cl_must_pass
(
p_write
(
link_fd
,
body
.
ptr
,
body
.
size
));
p_close
(
link_fd
);
}
}
git_buf_free
(
&
link_tgt
);
git_buf_free
(
&
link
);
git_buf_free
(
&
body
);
cl_git_pass
(
git_repository_open
(
&
repo2
,
"alternate"
));
cl_assert
(
git_repository_path
(
repo2
)
!=
NULL
);
cl_assert_
(
git__suffixcmp
(
git_repository_path
(
repo2
),
"alternate/.git/"
)
==
0
,
git_repository_path
(
repo2
));
cl_assert
(
git_repository_workdir
(
repo2
)
!=
NULL
);
cl_assert_
(
git__suffixcmp
(
git_repository_workdir
(
repo2
),
"alternate/"
)
==
0
,
git_repository_workdir
(
repo2
));
git_repository_free
(
repo2
);
#endif
}
void
test_repo_open__failures
(
void
)
{
git_repository
*
base
,
*
repo
;
git_buf
ceiling
=
GIT_BUF_INIT
;
base
=
cl_git_sandbox_init
(
"attr"
);
cl_git_pass
(
git_buf_sets
(
&
ceiling
,
git_repository_workdir
(
base
)));
/* fail with no searching */
cl_git_fail
(
git_repository_open
(
&
repo
,
"attr/sub"
));
cl_git_fail
(
git_repository_open_ext
(
&
repo
,
"attr/sub"
,
GIT_REPOSITORY_OPEN_NO_SEARCH
,
NULL
));
/* fail with ceiling too low */
cl_git_pass
(
git_buf_joinpath
(
&
ceiling
,
ceiling
.
ptr
,
"sub"
));
cl_git_fail
(
git_repository_open_ext
(
&
repo
,
"attr/sub"
,
0
,
ceiling
.
ptr
));
/* fail with no repo */
cl_git_pass
(
p_mkdir
(
"alternate"
,
0777
));
cl_git_pass
(
p_mkdir
(
"alternate/.git"
,
0777
));
cl_git_fail
(
git_repository_open_ext
(
&
repo
,
"alternate"
,
0
,
NULL
));
cl_git_fail
(
git_repository_open_ext
(
&
repo
,
"alternate/.git"
,
0
,
NULL
));
git_buf_free
(
&
ceiling
);
}
void
test_repo_open__bad_gitlinks
(
void
)
{
git_repository
*
repo
;
static
const
char
*
bad_links
[]
=
{
"garbage
\n
"
,
"gitdir"
,
"gitdir:
\n
"
,
"gitdir: foobar"
,
"gitdir: ../invalid"
,
"gitdir: ../invalid2"
,
"gitdir: ../attr/.git with extra stuff"
,
NULL
};
const
char
**
scan
;
cl_git_sandbox_init
(
"attr"
);
cl_git_pass
(
p_mkdir
(
"alternate"
,
0777
));
cl_git_pass
(
p_mkdir
(
"invalid"
,
0777
));
cl_git_pass
(
git_futils_mkdir_r
(
"invalid2/.git"
,
NULL
,
0777
));
for
(
scan
=
bad_links
;
*
scan
!=
NULL
;
scan
++
)
{
cl_git_rewritefile
(
"alternate/.git"
,
*
scan
);
cl_git_fail
(
git_repository_open_ext
(
&
repo
,
"alternate"
,
0
,
NULL
));
}
git_futils_rmdir_r
(
"invalid"
,
1
);
git_futils_rmdir_r
(
"invalid2"
,
1
);
}
static
void
unposix_path
(
git_buf
*
path
)
{
char
*
src
,
*
tgt
;
src
=
tgt
=
path
->
ptr
;
/* convert "/d/..." to "d:\..." */
if
(
src
[
0
]
==
'/'
&&
isalpha
(
src
[
1
])
&&
src
[
2
]
==
'/'
)
{
*
tgt
++
=
src
[
1
];
*
tgt
++
=
':'
;
*
tgt
++
=
'\\'
;
src
+=
3
;
}
while
(
*
src
)
{
*
tgt
++
=
(
*
src
==
'/'
)
?
'\\'
:
*
src
;
src
++
;
}
*
tgt
=
'\0'
;
}
void
test_repo_open__win32_path
(
void
)
{
#ifdef GIT_WIN32
git_repository
*
repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
),
*
repo2
;
git_buf
winpath
=
GIT_BUF_INIT
;
char
*
src
,
*
tgt
;
static
const
char
*
repo_path
=
"empty_standard_repo/.git/"
;
static
const
char
*
repo_wd
=
"empty_standard_repo/"
;
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo
),
repo_path
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo
),
repo_wd
)
==
0
);
cl_git_pass
(
git_buf_sets
(
&
winpath
,
git_repository_path
(
repo
)));
unposix_path
(
&
winpath
);
cl_git_pass
(
git_repository_open
(
&
repo2
,
winpath
.
ptr
));
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo2
),
repo_path
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo2
),
repo_wd
)
==
0
);
git_repository_free
(
repo2
);
cl_git_pass
(
git_buf_sets
(
&
winpath
,
git_repository_path
(
repo
)));
git_buf_truncate
(
&
winpath
,
winpath
.
size
-
1
);
/* remove trailing '/' */
unposix_path
(
&
winpath
);
cl_git_pass
(
git_repository_open
(
&
repo2
,
winpath
.
ptr
));
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo2
),
repo_path
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo2
),
repo_wd
)
==
0
);
git_repository_free
(
repo2
);
cl_git_pass
(
git_buf_sets
(
&
winpath
,
git_repository_workdir
(
repo
)));
unposix_path
(
&
winpath
);
cl_git_pass
(
git_repository_open
(
&
repo2
,
winpath
.
ptr
));
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo2
),
repo_path
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo2
),
repo_wd
)
==
0
);
git_repository_free
(
repo2
);
cl_git_pass
(
git_buf_sets
(
&
winpath
,
git_repository_workdir
(
repo
)));
git_buf_truncate
(
&
winpath
,
winpath
.
size
-
1
);
/* remove trailing '/' */
unposix_path
(
&
winpath
);
cl_git_pass
(
git_repository_open
(
&
repo2
,
winpath
.
ptr
));
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo2
),
repo_path
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo2
),
repo_wd
)
==
0
);
git_repository_free
(
repo2
);
cl_fixture_cleanup
(
"empty_standard_repo"
);
git_buf_free
(
&
winpath
);
#endif
}
}
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