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
e24fbba9
Commit
e24fbba9
authored
Mar 14, 2012
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #595 from arrbee/new-errors-odb
Update odb code to new error handling
parents
dda708e7
deafee7b
Hide whitespace changes
Inline
Side-by-side
Showing
41 changed files
with
1066 additions
and
976 deletions
+1066
-976
include/git2/errors.h
+18
-1
src/attr.c
+17
-22
src/attr_file.c
+11
-11
src/attr_file.h
+3
-3
src/blob.c
+47
-63
src/buffer.c
+2
-2
src/buffer.h
+2
-2
src/errors.c
+43
-4
src/filebuf.c
+6
-2
src/filebuf.h
+1
-0
src/fileops.c
+61
-32
src/fileops.h
+3
-12
src/hashtable.c
+39
-30
src/hashtable.h
+1
-1
src/ignore.c
+2
-2
src/index.c
+1
-2
src/indexer.c
+13
-10
src/iterator.c
+1
-1
src/map.h
+5
-0
src/mwindow.c
+7
-10
src/mwindow.h
+3
-3
src/object.c
+1
-1
src/odb.c
+58
-59
src/odb.h
+10
-0
src/odb_loose.c
+132
-191
src/odb_pack.c
+70
-88
src/pack.c
+135
-145
src/pack.h
+6
-6
src/path.c
+73
-73
src/path.h
+5
-0
src/posix.c
+2
-2
src/refs.c
+2
-2
src/repository.c
+4
-6
src/unix/map.c
+7
-23
src/win32/dir.c
+55
-33
src/win32/map.c
+18
-34
src/win32/posix_w32.c
+104
-89
src/win32/pthread.c
+8
-5
src/win32/utf-conv.c
+15
-5
tests-clar/attr/attr_expect.h
+1
-1
tests-clar/core/errors.c
+74
-0
No files found.
include/git2/errors.h
View file @
e24fbba9
...
...
@@ -103,7 +103,7 @@ typedef enum {
GIT_EOBJCORRUPTED
=
-
28
,
/** The given short oid is ambiguous */
GIT_EAMBIGUOUS
OIDPREFIX
=
-
29
,
GIT_EAMBIGUOUS
=
-
29
,
/** Skip and passthrough the given ODB backend */
GIT_EPASSTHROUGH
=
-
30
,
...
...
@@ -128,11 +128,13 @@ typedef enum {
GITERR_REPOSITORY
,
GITERR_CONFIG
,
GITERR_REGEX
,
GITERR_ODB
}
git_error_class
;
/**
* Return a detailed error string with the latest error
* that occurred in the library.
* @deprecated This will be replaced in the new error handling
* @return a string explaining the error
*/
GIT_EXTERN
(
const
char
*
)
git_lasterror
(
void
);
...
...
@@ -144,6 +146,7 @@ GIT_EXTERN(const char *) git_lasterror(void);
* NOTE: This method will be eventually deprecated in favor
* of the new `git_lasterror`.
*
* @deprecated This will be replaced in the new error handling
* @param num The error code to explain
* @return a string explaining the error code
*/
...
...
@@ -151,9 +154,23 @@ GIT_EXTERN(const char *) git_strerror(int num);
/**
* Clear the latest library error
* @deprecated This will be replaced in the new error handling
*/
GIT_EXTERN
(
void
)
git_clearerror
(
void
);
/**
* Return the last `git_error` object that was generated for the
* current thread or NULL if no error has occurred.
*
* @return A git_error object.
*/
GIT_EXTERN
(
const
git_error
*
)
git_error_last
(
void
);
/**
* Clear the last library error that occurred for this thread.
*/
GIT_EXTERN
(
void
)
git_error_clear
(
void
);
/** @} */
GIT_END_DECL
#endif
src/attr.c
View file @
e24fbba9
...
...
@@ -317,13 +317,12 @@ static int collect_attr_files(
const
char
*
workdir
=
git_repository_workdir
(
repo
);
attr_walk_up_info
info
;
if
((
error
=
git_attr_cache__init
(
repo
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
((
error
=
git_vector_init
(
files
,
4
,
NULL
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_attr_cache__init
(
repo
)
<
0
||
git_vector_init
(
files
,
4
,
NULL
)
<
0
)
return
-
1
;
if
((
error
=
git_path_find_dir
(
&
dir
,
path
,
workdir
))
<
GIT_SUCCESS
)
error
=
git_path_find_dir
(
&
dir
,
path
,
workdir
);
if
(
error
<
0
)
goto
cleanup
;
/* in precendence order highest to lowest:
...
...
@@ -334,13 +333,13 @@ static int collect_attr_files(
*/
error
=
push_attrs
(
repo
,
files
,
repo
->
path_repository
,
GIT_ATTR_FILE_INREPO
);
if
(
error
<
GIT_SUCCESS
)
if
(
error
<
0
)
goto
cleanup
;
info
.
repo
=
repo
;
info
.
files
=
files
;
error
=
git_path_walk_up
(
&
dir
,
workdir
,
push_one_attr
,
&
info
);
if
(
error
<
GIT_SUCCESS
)
if
(
error
<
0
)
goto
cleanup
;
if
((
error
=
git_repository_config
(
&
cfg
,
repo
))
==
GIT_SUCCESS
)
{
...
...
@@ -352,19 +351,17 @@ static int collect_attr_files(
git_config_free
(
cfg
);
}
if
(
error
==
GIT_SUCCESS
)
{
if
(
!
error
)
{
error
=
git_futils_find_system_file
(
&
dir
,
GIT_ATTR_FILE_SYSTEM
);
if
(
error
==
GIT_SUCCESS
)
if
(
!
error
)
error
=
push_attrs
(
repo
,
files
,
NULL
,
dir
.
ptr
);
else
if
(
error
==
GIT_ENOTFOUND
)
error
=
GIT_SUCCESS
;
error
=
0
;
}
cleanup:
if
(
error
<
GIT_SUCCESS
)
{
git__rethrow
(
error
,
"Could not get attributes for '%s'"
,
path
);
if
(
error
<
0
)
git_vector_free
(
files
);
}
git_buf_free
(
&
dir
);
return
error
;
...
...
@@ -373,32 +370,29 @@ static int collect_attr_files(
int
git_attr_cache__init
(
git_repository
*
repo
)
{
int
error
=
GIT_SUCCESS
;
git_attr_cache
*
cache
=
&
repo
->
attrcache
;
if
(
cache
->
initialized
)
return
GIT_SUCCESS
;
return
0
;
if
(
cache
->
files
==
NULL
)
{
cache
->
files
=
git_hashtable_alloc
(
8
,
git_hash__strhash_cb
,
git_hash__strcmp_cb
);
if
(
!
cache
->
files
)
return
git__throw
(
GIT_ENOMEM
,
"Could not initialize attribute cache"
)
;
return
-
1
;
}
if
(
cache
->
macros
==
NULL
)
{
cache
->
macros
=
git_hashtable_alloc
(
8
,
git_hash__strhash_cb
,
git_hash__strcmp_cb
);
if
(
!
cache
->
macros
)
return
git__throw
(
GIT_ENOMEM
,
"Could not initialize attribute cache"
)
;
return
-
1
;
}
cache
->
initialized
=
1
;
/* insert default macros */
error
=
git_attr_add_macro
(
repo
,
"binary"
,
"-diff -crlf"
);
return
error
;
return
git_attr_add_macro
(
repo
,
"binary"
,
"-diff -crlf"
);
}
void
git_attr_cache_flush
(
...
...
@@ -432,8 +426,9 @@ void git_attr_cache_flush(
int
git_attr_cache__insert_macro
(
git_repository
*
repo
,
git_attr_rule
*
macro
)
{
/* TODO: generate warning log if (macro->assigns.length == 0) */
if
(
macro
->
assigns
.
length
==
0
)
return
git__throw
(
GIT_EMISSINGOBJDATA
,
"git attribute macro with no values"
)
;
return
0
;
return
git_hashtable_insert
(
repo
->
attrcache
.
macros
,
macro
->
match
.
pattern
,
macro
);
...
...
src/attr_file.c
View file @
e24fbba9
...
...
@@ -180,37 +180,37 @@ int git_attr_file__lookup_one(
}
}
return
GIT_SUCCESS
;
return
0
;
}
int
git_attr_fnmatch__match
(
bool
git_attr_fnmatch__match
(
git_attr_fnmatch
*
match
,
const
git_attr_path
*
path
)
{
int
matched
=
FNM_NOMATCH
;
int
fnm
;
if
(
match
->
flags
&
GIT_ATTR_FNMATCH_DIRECTORY
&&
!
path
->
is_dir
)
return
matched
;
return
false
;
if
(
match
->
flags
&
GIT_ATTR_FNMATCH_FULLPATH
)
matched
=
p_fnmatch
(
match
->
pattern
,
path
->
path
,
FNM_PATHNAME
);
fnm
=
p_fnmatch
(
match
->
pattern
,
path
->
path
,
FNM_PATHNAME
);
else
if
(
path
->
is_dir
)
matched
=
p_fnmatch
(
match
->
pattern
,
path
->
basename
,
FNM_LEADING_DIR
);
fnm
=
p_fnmatch
(
match
->
pattern
,
path
->
basename
,
FNM_LEADING_DIR
);
else
matched
=
p_fnmatch
(
match
->
pattern
,
path
->
basename
,
0
);
fnm
=
p_fnmatch
(
match
->
pattern
,
path
->
basename
,
0
);
return
matched
;
return
(
fnm
==
FNM_NOMATCH
)
?
false
:
true
;
}
int
git_attr_rule__match
(
bool
git_attr_rule__match
(
git_attr_rule
*
rule
,
const
git_attr_path
*
path
)
{
int
matched
=
git_attr_fnmatch__match
(
&
rule
->
match
,
path
);
bool
matched
=
git_attr_fnmatch__match
(
&
rule
->
match
,
path
);
if
(
rule
->
match
.
flags
&
GIT_ATTR_FNMATCH_NEGATIVE
)
matched
=
(
matched
==
GIT_SUCCESS
)
?
FNM_NOMATCH
:
GIT_SUCCESS
;
matched
=
!
matched
;
return
matched
;
}
...
...
src/attr_file.h
View file @
e24fbba9
...
...
@@ -82,7 +82,7 @@ extern int git_attr_file__lookup_one(
/* loop over rules in file from bottom to top */
#define git_attr_file__foreach_matching_rule(file, path, iter, rule) \
git_vector_rforeach(&(file)->rules, (iter), (rule)) \
if (git_attr_rule__match((rule), (path))
== GIT_SUCCESS
)
if (git_attr_rule__match((rule), (path)))
extern
unsigned
long
git_attr_file__name_hash
(
const
char
*
name
);
...
...
@@ -96,13 +96,13 @@ extern int git_attr_fnmatch__parse(
const
char
*
source
,
const
char
**
base
);
extern
int
git_attr_fnmatch__match
(
extern
bool
git_attr_fnmatch__match
(
git_attr_fnmatch
*
rule
,
const
git_attr_path
*
path
);
extern
void
git_attr_rule__free
(
git_attr_rule
*
rule
);
extern
int
git_attr_rule__match
(
extern
bool
git_attr_rule__match
(
git_attr_rule
*
rule
,
const
git_attr_path
*
path
);
...
...
src/blob.c
View file @
e24fbba9
...
...
@@ -42,7 +42,7 @@ int git_blob__parse(git_blob *blob, git_odb_object *odb_obj)
assert
(
blob
);
git_cached_obj_incref
((
git_cached_obj
*
)
odb_obj
);
blob
->
odb_object
=
odb_obj
;
return
GIT_SUCCESS
;
return
0
;
}
int
git_blob_create_frombuffer
(
git_oid
*
oid
,
git_repository
*
repo
,
const
void
*
buffer
,
size_t
len
)
...
...
@@ -51,58 +51,50 @@ int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *b
git_odb
*
odb
;
git_odb_stream
*
stream
;
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
if
(
error
<
GIT_SUCCESS
)
if
((
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
))
<
0
||
(
error
=
git_odb_open_wstream
(
&
stream
,
odb
,
len
,
GIT_OBJ_BLOB
))
<
0
)
return
error
;
if
((
error
=
git_odb_open_wstream
(
&
stream
,
odb
,
len
,
GIT_OBJ_BLOB
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to create blob"
);
if
((
error
=
stream
->
write
(
stream
,
buffer
,
len
))
==
0
)
error
=
stream
->
finalize_write
(
oid
,
stream
);
if
((
error
=
stream
->
write
(
stream
,
buffer
,
len
))
<
GIT_SUCCESS
)
{
stream
->
free
(
stream
);
return
error
;
}
error
=
stream
->
finalize_write
(
oid
,
stream
);
stream
->
free
(
stream
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to create blob"
);
return
GIT_SUCCESS
;
return
error
;
}
static
int
write_file_stream
(
git_oid
*
oid
,
git_odb
*
odb
,
const
char
*
path
,
git_off_t
file_size
)
static
int
write_file_stream
(
git_oid
*
oid
,
git_odb
*
odb
,
const
char
*
path
,
git_off_t
file_size
)
{
int
fd
,
error
;
char
buffer
[
4096
];
git_odb_stream
*
stream
=
NULL
;
if
((
error
=
git_odb_open_wstream
(
&
stream
,
odb
,
file_size
,
GIT_OBJ_BLOB
))
<
GIT_SUCCESS
)
if
((
error
=
git_odb_open_wstream
(
&
stream
,
odb
,
(
size_t
)
file_size
,
GIT_OBJ_BLOB
))
<
0
)
return
error
;
if
((
fd
=
p_open
(
path
,
O_RDONLY
))
<
0
)
{
error
=
git__throw
(
GIT_ENOTFOUND
,
"Failed to create blob. Could not open '%s'"
,
path
);
goto
cleanup
;
if
((
fd
=
git_futils_open_ro
(
path
))
<
0
)
{
stream
->
free
(
stream
);
return
-
1
;
}
while
(
file_size
>
0
)
{
while
(
!
error
&&
file_size
>
0
)
{
ssize_t
read_len
=
p_read
(
fd
,
buffer
,
sizeof
(
buffer
));
if
(
read_len
<
0
)
{
error
=
git__throw
(
GIT_EOSERR
,
"Failed to create blob. Can't read full file"
);
p_close
(
fd
);
goto
cleanup
;
giterr_set
(
GITERR_OS
,
"Failed to create blob. Can't read whole file"
);
error
=
-
1
;
}
stream
->
write
(
stream
,
buffer
,
read_len
);
file_size
-=
read_len
;
else
if
(
!
(
error
=
stream
->
write
(
stream
,
buffer
,
read_len
)))
file_size
-=
read_len
;
}
p_close
(
fd
);
error
=
stream
->
finalize_write
(
oid
,
stream
);
cleanup:
if
(
!
error
)
error
=
stream
->
finalize_write
(
oid
,
stream
);
stream
->
free
(
stream
);
return
error
;
}
...
...
@@ -117,8 +109,7 @@ static int write_file_filtered(
git_buf
source
=
GIT_BUF_INIT
;
git_buf
dest
=
GIT_BUF_INIT
;
error
=
git_futils_readbuffer
(
&
source
,
full_path
);
if
(
error
<
GIT_SUCCESS
)
if
((
error
=
git_futils_readbuffer
(
&
source
,
full_path
))
<
0
)
return
error
;
error
=
git_filters_apply
(
&
dest
,
&
source
,
filters
);
...
...
@@ -127,30 +118,29 @@ static int write_file_filtered(
* and we don't want to ODB write to choke */
git_buf_free
(
&
source
);
if
(
error
==
GIT_SUCCESS
)
{
/* Write the file to disk if it was properly filtered */
/* Write the file to disk if it was properly filtered */
if
(
!
error
)
error
=
git_odb_write
(
oid
,
odb
,
dest
.
ptr
,
dest
.
size
,
GIT_OBJ_BLOB
);
}
git_buf_free
(
&
dest
);
return
GIT_SUCCESS
;
return
error
;
}
static
int
write_symlink
(
git_oid
*
oid
,
git_odb
*
odb
,
const
char
*
path
,
size_t
link_size
)
static
int
write_symlink
(
git_oid
*
oid
,
git_odb
*
odb
,
const
char
*
path
,
size_t
link_size
)
{
char
*
link_data
;
ssize_t
read_len
;
int
error
;
link_data
=
git__malloc
(
link_size
);
if
(
!
link_data
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
link_data
);
read_len
=
p_readlink
(
path
,
link_data
,
link_size
);
if
(
read_len
!=
(
ssize_t
)
link_size
)
{
giterr_set
(
GITERR_OS
,
"Failed to create blob. Can't read symlink '%s'"
,
path
);
free
(
link_data
);
return
git__throw
(
GIT_EOSERR
,
"Failed to create blob. Can't read symlink"
)
;
return
-
1
;
}
error
=
git_odb_write
(
oid
,
odb
,
(
void
*
)
link_data
,
link_size
,
GIT_OBJ_BLOB
);
...
...
@@ -168,25 +158,18 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
git_odb
*
odb
=
NULL
;
workdir
=
git_repository_workdir
(
repo
);
if
(
workdir
==
NULL
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to create blob. (No working directory found)"
);
assert
(
workdir
);
/* error to call this on bare repo */
error
=
git_buf_joinpath
(
&
full_path
,
workdir
,
path
);
if
(
error
<
GIT_SUCCESS
)
if
((
error
=
git_buf_joinpath
(
&
full_path
,
workdir
,
path
))
<
0
||
(
error
=
git_path_lstat
(
full_path
.
ptr
,
&
st
))
<
0
||
(
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
))
<
0
)
{
git_buf_free
(
&
full_path
);
return
error
;
error
=
p_lstat
(
full_path
.
ptr
,
&
st
);
if
(
error
<
0
)
{
error
=
git__throw
(
GIT_EOSERR
,
"Failed to stat blob. %s"
,
strerror
(
errno
));
goto
cleanup
;
}
size
=
st
.
st_size
;
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
S_ISLNK
(
st
.
st_mode
))
{
error
=
write_symlink
(
oid
,
odb
,
full_path
.
ptr
,
(
size_t
)
size
);
}
else
{
...
...
@@ -194,12 +177,12 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
int
filter_count
;
/* Load the filters for writing this file to the ODB */
filter_count
=
git_filters_load
(
&
write_filters
,
repo
,
path
,
GIT_FILTER_TO_ODB
);
filter_count
=
git_filters_load
(
&
write_filters
,
repo
,
path
,
GIT_FILTER_TO_ODB
);
if
(
filter_count
<
0
)
{
/* Negative value means there was a critical error */
error
=
filter_count
;
goto
cleanup
;
}
else
if
(
filter_count
==
0
)
{
/* No filters need to be applied to the document: we can stream
* directly from disk */
...
...
@@ -212,19 +195,20 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
git_filters_free
(
&
write_filters
);
/*
* TODO: eventually support streaming filtered files, for files which are bigger
* than a given threshold. This is not a priority because applying a filter in
* streaming mode changes the final size of the blob, and without knowing its
* final size, the blob cannot be written in stream mode to the ODB.
* TODO: eventually support streaming filtered files, for files
* which are bigger than a given threshold. This is not a priority
* because applying a filter in streaming mode changes the final
* size of the blob, and without knowing its final size, the blob
* cannot be written in stream mode to the ODB.
*
* The plan is to do streaming writes to a tempfile on disk and then opening
* streaming that file to the ODB, using `write_file_stream`.
* The plan is to do streaming writes to a tempfile on disk and then
* opening streaming that file to the ODB, using
* `write_file_stream`.
*
* CAREFULLY DESIGNED APIS YO
*/
}
cleanup:
git_buf_free
(
&
full_path
);
return
error
;
}
...
...
src/buffer.c
View file @
e24fbba9
...
...
@@ -215,8 +215,8 @@ void git_buf_truncate(git_buf *buf, size_t len)
void
git_buf_rtruncate_at_char
(
git_buf
*
buf
,
char
separator
)
{
in
t
idx
=
git_buf_rfind_next
(
buf
,
separator
);
git_buf_truncate
(
buf
,
idx
<
0
?
0
:
idx
);
ssize_
t
idx
=
git_buf_rfind_next
(
buf
,
separator
);
git_buf_truncate
(
buf
,
idx
<
0
?
0
:
(
size_t
)
idx
);
}
void
git_buf_swap
(
git_buf
*
buf_a
,
git_buf
*
buf_b
)
...
...
src/buffer.h
View file @
e24fbba9
...
...
@@ -102,9 +102,9 @@ void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf);
#define git_buf_PUTS(buf, str) git_buf_put(buf, str, sizeof(str) - 1)
GIT_INLINE
(
in
t
)
git_buf_rfind_next
(
git_buf
*
buf
,
char
ch
)
GIT_INLINE
(
ssize_
t
)
git_buf_rfind_next
(
git_buf
*
buf
,
char
ch
)
{
int
idx
=
buf
->
size
-
1
;
ssize_t
idx
=
(
ssize_t
)
buf
->
size
-
1
;
while
(
idx
>=
0
&&
buf
->
ptr
[
idx
]
==
ch
)
idx
--
;
while
(
idx
>=
0
&&
buf
->
ptr
[
idx
]
!=
ch
)
idx
--
;
return
idx
;
...
...
src/errors.c
View file @
e24fbba9
...
...
@@ -40,7 +40,7 @@ static struct {
{
GIT_EEXISTS
,
"A reference with this name already exists"
},
{
GIT_EOVERFLOW
,
"The given integer literal is too large to be parsed"
},
{
GIT_ENOTNUM
,
"The given literal is not a valid number"
},
{
GIT_EAMBIGUOUS
OIDPREFIX
,
"The given oid prefix is ambiguous"
},
{
GIT_EAMBIGUOUS
,
"The given oid prefix is ambiguous"
},
};
const
char
*
git_strerror
(
int
num
)
...
...
@@ -123,15 +123,43 @@ void giterr_set(int error_class, const char *string, ...)
char
error_str
[
1024
];
va_list
arglist
;
/* Grab errno before calling vsnprintf() so it won't be overwritten */
const
char
*
os_error_msg
=
(
error_class
==
GITERR_OS
&&
errno
!=
0
)
?
strerror
(
errno
)
:
NULL
;
#ifdef GIT_WIN32
DWORD
dwLastError
=
GetLastError
();
#endif
va_start
(
arglist
,
string
);
p_vsnprintf
(
error_str
,
sizeof
(
error_str
),
string
,
arglist
);
va_end
(
arglist
);
/* automatically suffix strerror(errno) for GITERR_OS errors */
if
(
error_class
==
GITERR_OS
)
{
strncat
(
error_str
,
": "
,
sizeof
(
error_str
));
strncat
(
error_str
,
strerror
(
errno
),
sizeof
(
error_str
));
errno
=
0
;
if
(
os_error_msg
!=
NULL
)
{
strncat
(
error_str
,
": "
,
sizeof
(
error_str
));
strncat
(
error_str
,
os_error_msg
,
sizeof
(
error_str
));
errno
=
0
;
/* reset so same error won't be reported twice */
}
#ifdef GIT_WIN32
else
if
(
dwLastError
!=
0
)
{
LPVOID
lpMsgBuf
=
NULL
;
FormatMessage
(
FORMAT_MESSAGE_ALLOCATE_BUFFER
|
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
NULL
,
dwLastError
,
0
,
(
LPTSTR
)
&
lpMsgBuf
,
0
,
NULL
);
if
(
lpMsgBuf
)
{
strncat
(
error_str
,
": "
,
sizeof
(
error_str
));
strncat
(
error_str
,
(
const
char
*
)
lpMsgBuf
,
sizeof
(
error_str
));
LocalFree
(
lpMsgBuf
);
}
SetLastError
(
0
);
}
#endif
}
giterr_set_str
(
error_class
,
error_str
);
...
...
@@ -165,3 +193,14 @@ void giterr_clear(void)
{
GIT_GLOBAL
->
last_error
=
NULL
;
}
const
git_error
*
git_error_last
(
void
)
{
return
GIT_GLOBAL
->
last_error
;
}
void
git_error_clear
(
void
)
{
giterr_clear
();
}
src/filebuf.c
View file @
e24fbba9
...
...
@@ -67,6 +67,8 @@ static int lock_file(git_filebuf *file, int flags)
if
(
file
->
fd
<
0
)
return
-
1
;
file
->
fd_is_open
=
true
;
if
((
flags
&
GIT_FILEBUF_APPEND
)
&&
git_path_exists
(
file
->
path_original
)
==
true
)
{
git_file
source
;
char
buffer
[
2048
];
...
...
@@ -94,10 +96,10 @@ static int lock_file(git_filebuf *file, int flags)
void
git_filebuf_cleanup
(
git_filebuf
*
file
)
{
if
(
file
->
fd
>=
0
)
if
(
file
->
fd
_is_open
&&
file
->
fd
>=
0
)
p_close
(
file
->
fd
);
if
(
file
->
fd
>=
0
&&
file
->
path_lock
&&
git_path_exists
(
file
->
path_lock
)
==
true
)
if
(
file
->
fd
_is_open
&&
file
->
path_lock
&&
git_path_exists
(
file
->
path_lock
)
)
p_unlink
(
file
->
path_lock
);
if
(
file
->
digest
)
...
...
@@ -239,6 +241,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)
git_buf_free
(
&
tmp_path
);
goto
cleanup
;
}
file
->
fd_is_open
=
true
;
/* No original path */
file
->
path_original
=
NULL
;
...
...
@@ -308,6 +311,7 @@ int git_filebuf_commit(git_filebuf *file, mode_t mode)
p_close
(
file
->
fd
);
file
->
fd
=
-
1
;
file
->
fd_is_open
=
false
;
if
(
p_chmod
(
file
->
path_lock
,
mode
))
{
giterr_set
(
GITERR_OS
,
"Failed to set attributes for file at '%s'"
,
file
->
path_lock
);
...
...
src/filebuf.h
View file @
e24fbba9
...
...
@@ -40,6 +40,7 @@ struct git_filebuf {
size_t
buf_size
,
buf_pos
;
git_file
fd
;
bool
fd_is_open
;
int
last_error
;
};
...
...
src/fileops.c
View file @
e24fbba9
...
...
@@ -79,11 +79,25 @@ int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, con
return
git_futils_creat_locked
(
path
,
mode
);
}
int
git_futils_open_ro
(
const
char
*
path
)
{
int
fd
=
p_open
(
path
,
O_RDONLY
);
if
(
fd
<
0
)
{
if
(
errno
==
ENOENT
)
fd
=
GIT_ENOTFOUND
;
giterr_set
(
GITERR_OS
,
"Failed to open '%s'"
,
path
);
}
return
fd
;
}
git_off_t
git_futils_filesize
(
git_file
fd
)
{
struct
stat
sb
;
if
(
p_fstat
(
fd
,
&
sb
))
return
GIT_ERROR
;
if
(
p_fstat
(
fd
,
&
sb
))
{
giterr_set
(
GITERR_OS
,
"Failed to stat file descriptor"
);
return
-
1
;
}
return
sb
.
st_size
;
}
...
...
@@ -117,7 +131,7 @@ int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime,
return
fd
;
if
(
p_fstat
(
fd
,
&
st
)
<
0
||
S_ISDIR
(
st
.
st_mode
)
||
!
git__is_sizet
(
st
.
st_size
+
1
))
{
close
(
fd
);
p_
close
(
fd
);
giterr_set
(
GITERR_OS
,
"Invalid regular file stat for '%s'"
,
path
);
return
-
1
;
}
...
...
@@ -127,7 +141,7 @@ int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime,
* has been modified.
*/
if
(
mtime
!=
NULL
&&
*
mtime
>=
st
.
st_mtime
)
{
close
(
fd
);
p_
close
(
fd
);
return
0
;
}
...
...
@@ -139,8 +153,8 @@ int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime,
git_buf_clear
(
buf
);
if
(
git_buf_grow
(
buf
,
len
+
1
)
<
0
)
{
close
(
fd
);
return
GIT_ENOMEM
;
p_
close
(
fd
);
return
-
1
;
}
buf
->
ptr
[
len
]
=
'\0'
;
...
...
@@ -149,7 +163,7 @@ int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime,
ssize_t
read_size
=
p_read
(
fd
,
buf
->
ptr
,
len
);
if
(
read_size
<
0
)
{
close
(
fd
);
p_
close
(
fd
);
giterr_set
(
GITERR_OS
,
"Failed to read descriptor for '%s'"
,
path
);
return
-
1
;
}
...
...
@@ -176,10 +190,15 @@ int git_futils_readbuffer(git_buf *buf, const char *path)
int
git_futils_mv_withpath
(
const
char
*
from
,
const
char
*
to
,
const
mode_t
dirmode
)
{
if
(
git_futils_mkpath2file
(
to
,
dirmode
)
<
GIT_SUCCESS
)
return
GIT_EOSERR
;
/* The callee already takes care of setting the correct error message. */
if
(
git_futils_mkpath2file
(
to
,
dirmode
)
<
0
)
return
-
1
;
if
(
p_rename
(
from
,
to
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Failed to rename '%s' to '%s'"
,
from
,
to
);
return
-
1
;
}
return
p_rename
(
from
,
to
);
/* The callee already takes care of setting the correct error message. */
return
0
;
}
int
git_futils_mmap_ro
(
git_map
*
out
,
git_file
fd
,
git_off_t
begin
,
size_t
len
)
...
...
@@ -192,8 +211,10 @@ int git_futils_mmap_ro_file(git_map *out, const char *path)
git_file
fd
=
p_open
(
path
,
O_RDONLY
/* | O_NOATIME */
);
git_off_t
len
=
git_futils_filesize
(
fd
);
int
result
;
if
(
!
git__is_sizet
(
len
))
return
git__throw
(
GIT_ERROR
,
"File `%s` too large to mmap"
,
path
);
if
(
!
git__is_sizet
(
len
))
{
giterr_set
(
GITERR_OS
,
"File `%s` too large to mmap"
,
path
);
return
-
1
;
}
result
=
git_futils_mmap_ro
(
out
,
fd
,
0
,
(
size_t
)
len
);
p_close
(
fd
);
return
result
;
...
...
@@ -260,20 +281,31 @@ int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)
static
int
_rmdir_recurs_foreach
(
void
*
opaque
,
git_buf
*
path
)
{
int
error
=
GIT_SUCCESS
;
int
force
=
*
(
int
*
)
opaque
;
if
(
git_path_isdir
(
path
->
ptr
)
==
true
)
{
error
=
git_path_direach
(
path
,
_rmdir_recurs_foreach
,
opaque
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to remove directory `%s`"
,
path
->
ptr
);
return
p_rmdir
(
path
->
ptr
);
if
(
git_path_direach
(
path
,
_rmdir_recurs_foreach
,
opaque
)
<
0
)
return
-
1
;
if
(
p_rmdir
(
path
->
ptr
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Could not remove directory '%s'"
,
path
->
ptr
);
return
-
1
;
}
}
else
if
(
force
)
{
return
p_unlink
(
path
->
ptr
);
return
0
;
}
return
git__rethrow
(
error
,
"Failed to remove directory. `%s` is not empty"
,
path
->
ptr
);
if
(
force
)
{
if
(
p_unlink
(
path
->
ptr
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Could not remove directory. File '%s' cannot be removed"
,
path
->
ptr
);
return
-
1
;
}
return
0
;
}
giterr_set
(
GITERR_OS
,
"Could not remove directory. File '%s' still present"
,
path
->
ptr
);
return
-
1
;
}
int
git_futils_rmdir_r
(
const
char
*
path
,
int
force
)
...
...
@@ -282,7 +314,7 @@ int git_futils_rmdir_r(const char *path, int force)
git_buf
p
=
GIT_BUF_INIT
;
error
=
git_buf_sets
(
&
p
,
path
);
if
(
error
==
GIT_SUCCESS
)
if
(
!
error
)
error
=
_rmdir_recurs_foreach
(
&
force
,
&
p
);
git_buf_free
(
&
p
);
return
error
;
...
...
@@ -328,9 +360,8 @@ static const win32_path *win32_system_root(void)
const
wchar_t
*
root_tmpl
=
L"%PROGRAMFILES%
\\
Git
\\
etc
\\
"
;
s_root
.
len
=
ExpandEnvironmentStringsW
(
root_tmpl
,
NULL
,
0
);
if
(
s_root
.
len
<=
0
)
{
git
__throw
(
GIT_EOSERR
,
"Failed to expand environment strings"
);
git
err_set
(
GITERR_OS
,
"Failed to expand environment strings"
);
return
NULL
;
}
...
...
@@ -339,7 +370,7 @@ static const win32_path *win32_system_root(void)
return
NULL
;
if
(
ExpandEnvironmentStringsW
(
root_tmpl
,
s_root
.
path
,
s_root
.
len
)
!=
s_root
.
len
)
{
git
__throw
(
GIT_EOSERR
,
"Failed to expand environment strings"
);
git
err_set
(
GITERR_OS
,
"Failed to expand environment strings"
);
git__free
(
s_root
.
path
);
s_root
.
path
=
NULL
;
return
NULL
;
...
...
@@ -351,7 +382,7 @@ static const win32_path *win32_system_root(void)
static
int
win32_find_system_file
(
git_buf
*
path
,
const
char
*
filename
)
{
int
error
=
GIT_SUCCESS
;
int
error
=
0
;
const
win32_path
*
root
=
win32_system_root
();
size_t
len
;
wchar_t
*
file_utf16
=
NULL
,
*
scan
;
...
...
@@ -362,8 +393,7 @@ static int win32_find_system_file(git_buf *path, const char *filename)
/* allocate space for wchar_t path to file */
file_utf16
=
git__calloc
(
root
->
len
+
len
+
2
,
sizeof
(
wchar_t
));
if
(
!
file_utf16
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
file_utf16
);
/* append root + '\\' + filename as wchar_t */
memcpy
(
file_utf16
,
root
->
path
,
root
->
len
*
sizeof
(
wchar_t
));
...
...
@@ -373,7 +403,7 @@ static int win32_find_system_file(git_buf *path, const char *filename)
if
(
gitwin_append_utf16
(
file_utf16
+
root
->
len
-
1
,
filename
,
len
+
1
)
!=
(
int
)
len
+
1
)
{
error
=
git__throw
(
GIT_EOSERR
,
"Failed to build file path"
)
;
error
=
-
1
;
goto
cleanup
;
}
...
...
@@ -389,9 +419,8 @@ static int win32_find_system_file(git_buf *path, const char *filename)
/* convert to utf8 */
if
((
file_utf8
=
gitwin_from_utf16
(
file_utf16
))
==
NULL
)
error
=
GIT_ENOMEM
;
if
(
file_utf8
)
{
error
=
-
1
;
else
{
git_path_mkposix
(
file_utf8
);
git_buf_attach
(
path
,
file_utf8
,
0
);
}
...
...
@@ -409,7 +438,7 @@ int git_futils_find_system_file(git_buf *path, const char *filename)
return
-
1
;
if
(
git_path_exists
(
path
->
ptr
)
==
true
)
return
GIT_SUCCESS
;
return
0
;
git_buf_clear
(
path
);
...
...
src/fileops.h
View file @
e24fbba9
...
...
@@ -77,18 +77,9 @@ extern int git_futils_mktmp(git_buf *path_out, const char *filename);
extern
int
git_futils_mv_withpath
(
const
char
*
from
,
const
char
*
to
,
const
mode_t
dirmode
);
/**
* Open a file readonly and set error if needed
*/
GIT_INLINE
(
int
)
git_futils_open_ro
(
const
char
*
path
)
{
int
fd
=
p_open
(
path
,
O_RDONLY
);
if
(
fd
<
0
)
{
if
(
errno
==
ENOENT
)
fd
=
GIT_ENOTFOUND
;
giterr_set
(
GITERR_OS
,
"Failed to open '%s'"
,
path
);
}
return
fd
;
}
* Open a file readonly and set error if needed.
*/
extern
int
git_futils_open_ro
(
const
char
*
path
);
/**
* Get the filesize in bytes of a file
...
...
src/hashtable.c
View file @
e24fbba9
...
...
@@ -31,9 +31,7 @@ static int resize_to(git_hashtable *self, size_t new_size)
self
->
size_mask
=
new_size
-
1
;
self
->
key_count
=
0
;
self
->
nodes
=
git__calloc
(
1
,
sizeof
(
git_hashtable_node
)
*
self
->
size
);
if
(
self
->
nodes
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
self
->
nodes
);
if
(
insert_nodes
(
self
,
old_nodes
,
old_size
)
==
0
)
self
->
is_resizing
=
0
;
...
...
@@ -44,22 +42,22 @@ static int resize_to(git_hashtable *self, size_t new_size)
}
while
(
self
->
is_resizing
);
git__free
(
old_nodes
);
return
GIT_SUCCESS
;
return
0
;
}
static
int
set_size
(
git_hashtable
*
self
,
size_t
new_size
)
{
self
->
nodes
=
git__realloc
(
self
->
nodes
,
new_size
*
sizeof
(
git_hashtable_node
));
if
(
self
->
nodes
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
self
->
nodes
);
if
(
new_size
>
self
->
size
)
{
memset
(
&
self
->
nodes
[
self
->
size
],
0x0
,
(
new_size
-
self
->
size
)
*
sizeof
(
git_hashtable_node
));
memset
(
&
self
->
nodes
[
self
->
size
],
0x0
,
(
new_size
-
self
->
size
)
*
sizeof
(
git_hashtable_node
));
}
self
->
size
=
new_size
;
self
->
size_mask
=
new_size
-
1
;
return
GIT_SUCCESS
;
return
0
;
}
static
git_hashtable_node
*
node_with_hash
(
git_hashtable
*
self
,
const
void
*
key
,
int
hash_id
)
...
...
@@ -84,43 +82,47 @@ static int node_insert(git_hashtable *self, git_hashtable_node *new_node)
git_hashtable_node
*
node
;
node
=
node_with_hash
(
self
,
new_node
->
key
,
hash_id
);
node_swap_with
(
new_node
,
node
);
if
(
new_node
->
key
==
0x0
){
if
(
new_node
->
key
==
0x0
){
self
->
key_count
++
;
return
GIT_SUCCESS
;
return
0
;
}
}
}
if
(
self
->
is_resizing
)
return
git__throw
(
GIT_EBUSY
,
"Failed to insert node. Hashtable is currently resizing"
);
/* Failed to insert node. Hashtable is currently resizing */
assert
(
!
self
->
is_resizing
);
if
(
resize_to
(
self
,
self
->
size
*
2
)
<
0
)
return
-
1
;
resize_to
(
self
,
self
->
size
*
2
);
git_hashtable_insert
(
self
,
new_node
->
key
,
new_node
->
value
);
return
GIT_SUCCESS
;
return
git_hashtable_insert
(
self
,
new_node
->
key
,
new_node
->
value
);
}
static
int
insert_nodes
(
git_hashtable
*
self
,
git_hashtable_node
*
old_nodes
,
size_t
old_size
)
static
int
insert_nodes
(
git_hashtable
*
self
,
git_hashtable_node
*
old_nodes
,
size_t
old_size
)
{
size_t
i
;
for
(
i
=
0
;
i
<
old_size
;
++
i
)
{
git_hashtable_node
*
node
=
git_hashtable_node_at
(
old_nodes
,
i
);
if
(
node
->
key
&&
git_hashtable_insert
(
self
,
node
->
key
,
node
->
value
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
if
(
node
->
key
&&
git_hashtable_insert
(
self
,
node
->
key
,
node
->
value
)
<
0
)
return
-
1
;
}
return
GIT_SUCCESS
;
return
0
;
}
git_hashtable
*
git_hashtable_alloc
(
size_t
min_size
,
git_hash_ptr
hash
,
git_hash_keyeq_ptr
key_eq
)
git_hashtable
*
git_hashtable_alloc
(
size_t
min_size
,
git_hash_ptr
hash
,
git_hash_keyeq_ptr
key_eq
)
{
git_hashtable
*
table
;
assert
(
hash
&&
key_eq
);
if
((
table
=
git__malloc
(
sizeof
(
git_hash
table
)))
==
NULL
)
if
((
table
=
git__malloc
(
sizeof
(
*
table
)))
==
NULL
)
return
NULL
;
memset
(
table
,
0x0
,
sizeof
(
git_hashtable
));
...
...
@@ -161,7 +163,8 @@ void git_hashtable_free(git_hashtable *self)
}
int
git_hashtable_insert2
(
git_hashtable
*
self
,
const
void
*
key
,
void
*
value
,
void
**
old_value
)
int
git_hashtable_insert2
(
git_hashtable
*
self
,
const
void
*
key
,
void
*
value
,
void
**
old_value
)
{
int
hash_id
;
git_hashtable_node
*
node
;
...
...
@@ -177,14 +180,14 @@ int git_hashtable_insert2(git_hashtable *self, const void *key, void *value, voi
node
->
key
=
key
;
node
->
value
=
value
;
self
->
key_count
++
;
return
GIT_SUCCESS
;
return
0
;
}
if
(
key
==
node
->
key
||
self
->
key_equal
(
key
,
node
->
key
)
==
0
)
{
*
old_value
=
node
->
value
;
node
->
key
=
key
;
node
->
value
=
value
;
return
GIT_SUCCESS
;
return
0
;
}
}
...
...
@@ -213,7 +216,8 @@ void *git_hashtable_lookup(git_hashtable *self, const void *key)
return
NULL
;
}
int
git_hashtable_remove2
(
git_hashtable
*
self
,
const
void
*
key
,
void
**
old_value
)
int
git_hashtable_remove2
(
git_hashtable
*
self
,
const
void
*
key
,
void
**
old_value
)
{
int
hash_id
;
git_hashtable_node
*
node
;
...
...
@@ -236,8 +240,8 @@ int git_hashtable_remove2(git_hashtable *self, const void *key, void **old_value
int
git_hashtable_merge
(
git_hashtable
*
self
,
git_hashtable
*
other
)
{
if
(
resize_to
(
self
,
(
self
->
size
+
other
->
size
)
*
2
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
if
(
resize_to
(
self
,
(
self
->
size
+
other
->
size
)
*
2
)
<
0
)
return
-
1
;
return
insert_nodes
(
self
,
other
->
nodes
,
other
->
key_count
);
}
...
...
@@ -254,5 +258,10 @@ uint32_t git_hash__strhash_cb(const void *key, int hash_id)
0x7daaab3c
};
return
git__hash
(
key
,
strlen
((
const
char
*
)
key
),
hash_seeds
[
hash_id
]);
size_t
key_len
=
strlen
((
const
char
*
)
key
);
/* won't take hash of strings longer than 2^31 right now */
assert
(
key_len
==
(
size_t
)((
int
)
key_len
));
return
git__hash
(
key
,
(
int
)
key_len
,
hash_seeds
[
hash_id
]);
}
src/hashtable.h
View file @
e24fbba9
...
...
@@ -66,7 +66,7 @@ GIT_INLINE(int) git_hashtable_insert(git_hashtable *h, const void *key, void *va
#define git_hashtable_node_at(nodes, pos) ((git_hashtable_node *)(&nodes[pos]))
#define GIT_HASHTABLE__FOREACH(self,block) { \
unsigned in
t _c; \
size_
t _c; \
git_hashtable_node *_n = (self)->nodes; \
for (_c = (self)->size; _c > 0; _c--, _n++) { \
if (!_n->key) continue; block } }
...
...
src/ignore.c
View file @
e24fbba9
...
...
@@ -168,9 +168,9 @@ static int ignore_lookup_in_rules(
git_attr_fnmatch
*
match
;
git_vector_rforeach
(
rules
,
j
,
match
)
{
if
(
git_attr_fnmatch__match
(
match
,
path
)
==
GIT_SUCCESS
)
{
if
(
git_attr_fnmatch__match
(
match
,
path
))
{
*
ignored
=
((
match
->
flags
&
GIT_ATTR_FNMATCH_NEGATIVE
)
==
0
);
return
GIT_SUCCESS
;
return
0
;
}
}
...
...
src/index.c
View file @
e24fbba9
...
...
@@ -319,8 +319,7 @@ static int index_entry_init(git_index_entry **entry_out, git_index *index, const
if
(
error
<
GIT_SUCCESS
)
return
error
;
if
(
p_lstat
(
full_path
.
ptr
,
&
st
)
<
0
)
{
error
=
git__throw
(
GIT_ENOTFOUND
,
"Failed to initialize entry. '%s' cannot be opened. %s"
,
full_path
.
ptr
,
strerror
(
errno
));
if
((
error
=
git_path_lstat
(
full_path
.
ptr
,
&
st
))
<
0
)
{
git_buf_free
(
&
full_path
);
return
error
;
}
...
...
src/indexer.c
View file @
e24fbba9
...
...
@@ -133,12 +133,15 @@ int git_indexer_new(git_indexer **out, const char *packname)
idx
->
nr_objects
=
ntohl
(
idx
->
hdr
.
hdr_entries
);
error
=
git_vector_init
(
&
idx
->
pack
->
cache
,
idx
->
nr_objects
,
cache_cmp
);
/* for now, limit to 2^32 objects */
assert
(
idx
->
nr_objects
==
(
size_t
)((
unsigned
int
)
idx
->
nr_objects
));
error
=
git_vector_init
(
&
idx
->
pack
->
cache
,
(
unsigned
int
)
idx
->
nr_objects
,
cache_cmp
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
idx
->
pack
->
has_cache
=
1
;
error
=
git_vector_init
(
&
idx
->
objects
,
idx
->
nr_objects
,
objects_cmp
);
error
=
git_vector_init
(
&
idx
->
objects
,
(
unsigned
int
)
idx
->
nr_objects
,
objects_cmp
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
...
...
@@ -307,7 +310,7 @@ cleanup:
int
git_indexer_run
(
git_indexer
*
idx
,
git_indexer_stats
*
stats
)
{
git_mwindow_file
*
mwf
;
off_t
off
=
sizeof
(
struct
git_pack_header
);
git_
off_t
off
=
sizeof
(
struct
git_pack_header
);
int
error
;
struct
entry
*
entry
;
unsigned
int
left
,
processed
;
...
...
@@ -319,7 +322,7 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to register mwindow file"
);
stats
->
total
=
idx
->
nr_objects
;
stats
->
total
=
(
unsigned
int
)
idx
->
nr_objects
;
stats
->
processed
=
processed
=
0
;
while
(
processed
<
idx
->
nr_objects
)
{
...
...
@@ -328,18 +331,18 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
struct
git_pack_entry
*
pentry
;
git_mwindow
*
w
=
NULL
;
int
i
;
off_t
entry_start
=
off
;
git_
off_t
entry_start
=
off
;
void
*
packed
;
size_t
entry_size
;
entry
=
git__
malloc
(
sizeof
(
struct
entry
));
memset
(
entry
,
0x0
,
sizeof
(
struct
entry
)
);
entry
=
git__
calloc
(
1
,
sizeof
(
*
entry
));
GITERR_CHECK_ALLOC
(
entry
);
if
(
off
>
UINT31_MAX
)
{
entry
->
offset
=
UINT32_MAX
;
entry
->
offset_long
=
off
;
}
else
{
entry
->
offset
=
off
;
entry
->
offset
=
(
uint32_t
)
off
;
}
error
=
git_packfile_unpack
(
&
obj
,
idx
->
pack
,
&
off
);
...
...
@@ -369,13 +372,13 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
git_oid_cpy
(
&
entry
->
oid
,
&
oid
);
entry
->
crc
=
crc32
(
0L
,
Z_NULL
,
0
);
entry_size
=
off
-
entry_start
;
entry_size
=
(
size_t
)(
off
-
entry_start
)
;
packed
=
git_mwindow_open
(
mwf
,
&
w
,
entry_start
,
entry_size
,
&
left
);
if
(
packed
==
NULL
)
{
error
=
git__rethrow
(
error
,
"Failed to open window to read packed data"
);
goto
cleanup
;
}
entry
->
crc
=
htonl
(
crc32
(
entry
->
crc
,
packed
,
entry_size
));
entry
->
crc
=
htonl
(
crc32
(
entry
->
crc
,
packed
,
(
uInt
)
entry_size
));
git_mwindow_close
(
&
w
);
/* Add the object to the list */
...
...
src/iterator.c
View file @
e24fbba9
...
...
@@ -309,7 +309,7 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi)
/* only push new ignores if this is not top level directory */
if
(
wi
->
stack
->
next
!=
NULL
)
{
in
t
slash_pos
=
git_buf_rfind_next
(
&
wi
->
path
,
'/'
);
ssize_
t
slash_pos
=
git_buf_rfind_next
(
&
wi
->
path
,
'/'
);
(
void
)
git_ignore__push_dir
(
&
wi
->
ignores
,
&
wi
->
path
.
ptr
[
slash_pos
+
1
]);
}
...
...
src/map.h
View file @
e24fbba9
...
...
@@ -31,6 +31,11 @@ typedef struct { /* memory mapped buffer */
#endif
}
git_map
;
#define GIT_MMAP_VALIDATE(out, len, prot, flags) do { \
assert(out != NULL && len > 0); \
assert((prot & GIT_PROT_WRITE) || (prot & GIT_PROT_READ)); \
assert((flags & GIT_MAP_FIXED) == 0); } while (0)
extern
int
p_mmap
(
git_map
*
out
,
size_t
len
,
int
prot
,
int
flags
,
int
fd
,
git_off_t
offset
);
extern
int
p_munmap
(
git_map
*
map
);
...
...
src/mwindow.c
View file @
e24fbba9
...
...
@@ -178,8 +178,10 @@ static git_mwindow *new_window(
* window.
*/
if
(
git_futils_mmap_ro
(
&
w
->
window_map
,
fd
,
w
->
offset
,
(
size_t
)
len
)
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_futils_mmap_ro
(
&
w
->
window_map
,
fd
,
w
->
offset
,
(
size_t
)
len
)
<
0
)
{
git__free
(
w
);
return
NULL
;
}
ctl
->
mmap_calls
++
;
ctl
->
open_windows
++
;
...
...
@@ -191,10 +193,6 @@ static git_mwindow *new_window(
ctl
->
peak_open_windows
=
ctl
->
open_windows
;
return
w
;
cleanup:
git__free
(
w
);
return
NULL
;
}
/*
...
...
@@ -205,7 +203,7 @@ unsigned char *git_mwindow_open(
git_mwindow_file
*
mwf
,
git_mwindow
**
cursor
,
git_off_t
offset
,
in
t
extra
,
size_
t
extra
,
unsigned
int
*
left
)
{
git_mwindow_ctl
*
ctl
=
&
GIT_GLOBAL
->
mem_ctl
;
...
...
@@ -253,11 +251,10 @@ unsigned char *git_mwindow_open(
int
git_mwindow_file_register
(
git_mwindow_file
*
mwf
)
{
git_mwindow_ctl
*
ctl
=
&
GIT_GLOBAL
->
mem_ctl
;
int
error
;
if
(
ctl
->
windowfiles
.
length
==
0
&&
(
error
=
git_vector_init
(
&
ctl
->
windowfiles
,
8
,
NULL
))
<
GIT_SUCCESS
)
return
error
;
git_vector_init
(
&
ctl
->
windowfiles
,
8
,
NULL
)
<
0
)
return
-
1
;
return
git_vector_insert
(
&
ctl
->
windowfiles
,
mwf
);
}
...
...
src/mwindow.h
View file @
e24fbba9
...
...
@@ -15,8 +15,8 @@ typedef struct git_mwindow {
struct
git_mwindow
*
next
;
git_map
window_map
;
git_off_t
offset
;
unsigned
in
t
last_used
;
unsigned
in
t
inuse_cnt
;
size_
t
last_used
;
size_
t
inuse_cnt
;
}
git_mwindow
;
typedef
struct
git_mwindow_file
{
...
...
@@ -37,7 +37,7 @@ typedef struct git_mwindow_ctl {
int
git_mwindow_contains
(
git_mwindow
*
win
,
git_off_t
offset
);
void
git_mwindow_free_all
(
git_mwindow_file
*
mwf
);
unsigned
char
*
git_mwindow_open
(
git_mwindow_file
*
mwf
,
git_mwindow
**
cursor
,
git_off_t
offset
,
in
t
extra
,
unsigned
int
*
left
);
unsigned
char
*
git_mwindow_open
(
git_mwindow_file
*
mwf
,
git_mwindow
**
cursor
,
git_off_t
offset
,
size_
t
extra
,
unsigned
int
*
left
);
void
git_mwindow_scan_lru
(
git_mwindow_file
*
mwf
,
git_mwindow
**
lru_w
,
git_mwindow
**
lru_l
);
int
git_mwindow_file_register
(
git_mwindow_file
*
mwf
);
void
git_mwindow_close
(
git_mwindow
**
w_cursor
);
...
...
src/object.c
View file @
e24fbba9
...
...
@@ -92,7 +92,7 @@ int git_object_lookup_prefix(
assert
(
repo
&&
object_out
&&
id
);
if
(
len
<
GIT_OID_MINPREFIXLEN
)
return
git__throw
(
GIT_EAMBIGUOUS
OIDPREFIX
,
return
git__throw
(
GIT_EAMBIGUOUS
,
"Failed to lookup object. Prefix length is lower than %d."
,
GIT_OID_MINPREFIXLEN
);
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
...
...
src/odb.c
View file @
e24fbba9
...
...
@@ -145,10 +145,8 @@ int git_odb__hashlink(git_oid *out, const char *path)
git_off_t
size
;
int
result
;
if
(
p_lstat
(
path
,
&
st
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Failed to stat object '%s'"
,
path
);
if
(
git_path_lstat
(
path
,
&
st
)
<
0
)
return
-
1
;
}
size
=
st
.
st_size
;
...
...
@@ -188,7 +186,7 @@ int git_odb_hashfile(git_oid *out, const char *path, git_otype type)
git_off_t
size
;
int
result
,
fd
=
git_futils_open_ro
(
path
);
if
(
fd
<
0
)
return
-
1
;
return
fd
;
if
((
size
=
git_futils_filesize
(
fd
))
<
0
||
!
git__is_sizet
(
size
))
{
giterr_set
(
GITERR_OS
,
"File size overflow for 32-bit systems"
);
...
...
@@ -507,23 +505,20 @@ int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git
error
=
b
->
read_header
(
len_p
,
type_p
,
b
,
id
);
}
if
(
error
==
GIT_EPASSTHROUGH
)
if
(
!
error
||
error
==
GIT_EPASSTHROUGH
)
return
0
;
/*
* no backend could read only the header.
* try reading the whole object and freeing the contents
*/
if
(
error
<
0
)
{
if
((
error
=
git_odb_read
(
&
object
,
db
,
id
))
<
GIT_SUCCESS
)
return
error
;
/* error already set - pass through */
*
len_p
=
object
->
raw
.
len
;
*
type_p
=
object
->
raw
.
type
;
git_odb_object_free
(
object
);
}
if
((
error
=
git_odb_read
(
&
object
,
db
,
id
))
<
0
)
return
error
;
/* error already set - pass along */
return
GIT_SUCCESS
;
*
len_p
=
object
->
raw
.
len
;
*
type_p
=
object
->
raw
.
type
;
git_odb_object_free
(
object
);
return
0
;
}
int
git_odb_read
(
git_odb_object
**
out
,
git_odb
*
db
,
const
git_oid
*
id
)
...
...
@@ -536,7 +531,7 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
*
out
=
git_cache_get
(
&
db
->
cache
,
id
);
if
(
*
out
!=
NULL
)
return
GIT_SUCCESS
;
return
0
;
for
(
i
=
0
;
i
<
db
->
backends
.
length
&&
error
<
0
;
++
i
)
{
backend_internal
*
internal
=
git_vector_get
(
&
db
->
backends
,
i
);
...
...
@@ -546,15 +541,15 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
error
=
b
->
read
(
&
raw
.
data
,
&
raw
.
len
,
&
raw
.
type
,
b
,
id
);
}
if
(
error
==
GIT_EPASSTHROUGH
||
error
==
GIT_SUCCESS
)
{
*
out
=
git_cache_try_store
(
&
db
->
cache
,
new_odb_object
(
id
,
&
raw
));
return
GIT_SUCCESS
;
}
if
(
error
&&
error
!=
GIT_EPASSTHROUGH
)
return
error
;
return
git__rethrow
(
error
,
"Failed to read object"
);
*
out
=
git_cache_try_store
(
&
db
->
cache
,
new_odb_object
(
id
,
&
raw
));
return
0
;
}
int
git_odb_read_prefix
(
git_odb_object
**
out
,
git_odb
*
db
,
const
git_oid
*
short_id
,
unsigned
int
len
)
int
git_odb_read_prefix
(
git_odb_object
**
out
,
git_odb
*
db
,
const
git_oid
*
short_id
,
unsigned
int
len
)
{
unsigned
int
i
;
int
error
=
GIT_ENOTFOUND
;
...
...
@@ -565,7 +560,7 @@ int git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_
assert
(
out
&&
db
);
if
(
len
<
GIT_OID_MINPREFIXLEN
)
return
git_
_throw
(
GIT_EAMBIGUOUSOIDPREFIX
,
"Failed to lookup object. Prefix length is lower than %d."
,
GIT_OID_MINPREFIXLEN
);
return
git_
odb__error_ambiguous
(
"prefix length too short"
);
if
(
len
>
GIT_OID_HEXSZ
)
len
=
GIT_OID_HEXSZ
;
...
...
@@ -573,7 +568,7 @@ int git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_
if
(
len
==
GIT_OID_HEXSZ
)
{
*
out
=
git_cache_get
(
&
db
->
cache
,
short_id
);
if
(
*
out
!=
NULL
)
return
GIT_SUCCESS
;
return
0
;
}
for
(
i
=
0
;
i
<
db
->
backends
.
length
&&
found
<
2
;
++
i
)
{
...
...
@@ -582,33 +577,24 @@ int git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_
if
(
b
->
read
!=
NULL
)
{
error
=
b
->
read_prefix
(
&
full_oid
,
&
raw
.
data
,
&
raw
.
len
,
&
raw
.
type
,
b
,
short_id
,
len
);
switch
(
error
)
{
case
GIT_SUCCESS
:
if
(
!
error
)
found
++
;
break
;
case
GIT_ENOTFOUND
:
case
GIT_EPASSTHROUGH
:
break
;
case
GIT_EAMBIGUOUSOIDPREFIX
:
return
git__rethrow
(
error
,
"Failed to read object. Ambiguous sha1 prefix"
);
default:
return
git__rethrow
(
error
,
"Failed to read object"
);
}
else
if
(
error
!=
GIT_ENOTFOUND
&&
error
!=
GIT_EPASSTHROUGH
)
return
error
;
}
}
if
(
found
==
1
)
{
*
out
=
git_cache_try_store
(
&
db
->
cache
,
new_odb_object
(
&
full_oid
,
&
raw
));
}
else
if
(
found
>
1
)
{
return
git__throw
(
GIT_EAMBIGUOUSOIDPREFIX
,
"Failed to read object. Ambiguous sha1 prefix"
);
}
else
{
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to read object. Object not found"
);
}
if
(
found
==
0
)
return
git_odb__error_notfound
(
"no match for prefix"
);
if
(
found
>
1
)
return
git_odb__error_ambiguous
(
"multiple matches for prefix"
);
return
GIT_SUCCESS
;
*
out
=
git_cache_try_store
(
&
db
->
cache
,
new_odb_object
(
&
full_oid
,
&
raw
));
return
0
;
}
int
git_odb_write
(
git_oid
*
oid
,
git_odb
*
db
,
const
void
*
data
,
size_t
len
,
git_otype
type
)
int
git_odb_write
(
git_oid
*
oid
,
git_odb
*
db
,
const
void
*
data
,
size_t
len
,
git_otype
type
)
{
unsigned
int
i
;
int
error
=
GIT_ERROR
;
...
...
@@ -628,24 +614,25 @@ int git_odb_write(git_oid *oid, git_odb *db, const void *data, size_t len, git_o
error
=
b
->
write
(
oid
,
b
,
data
,
len
,
type
);
}
if
(
error
==
GIT_EPASSTHROUGH
||
error
==
GIT_SUCCESS
)
return
GIT_SUCCESS
;
if
(
!
error
||
error
==
GIT_EPASSTHROUGH
)
return
0
;
/* if no backends were able to write the object directly, we try a streaming
* write to the backends; just write the whole object into the stream in one
* push */
if
((
error
=
git_odb_open_wstream
(
&
stream
,
db
,
len
,
type
))
==
GIT_SUCCESS
)
{
stream
->
write
(
stream
,
data
,
len
);
error
=
stream
->
finalize_write
(
oid
,
stream
);
stream
->
free
(
stream
);
return
GIT_SUCCESS
;
}
if
((
error
=
git_odb_open_wstream
(
&
stream
,
db
,
len
,
type
))
!=
0
)
return
error
;
return
git__rethrow
(
error
,
"Failed to write object"
);
stream
->
write
(
stream
,
data
,
len
);
error
=
stream
->
finalize_write
(
oid
,
stream
);
stream
->
free
(
stream
);
return
error
;
}
int
git_odb_open_wstream
(
git_odb_stream
**
stream
,
git_odb
*
db
,
size_t
size
,
git_otype
type
)
int
git_odb_open_wstream
(
git_odb_stream
**
stream
,
git_odb
*
db
,
size_t
size
,
git_otype
type
)
{
unsigned
int
i
;
int
error
=
GIT_ERROR
;
...
...
@@ -666,10 +653,10 @@ int git_odb_open_wstream(git_odb_stream **stream, git_odb *db, size_t size, git_
error
=
init_fake_wstream
(
stream
,
b
,
size
,
type
);
}
if
(
error
==
GIT_EPASSTHROUGH
||
error
==
GIT_SUCCESS
)
return
GIT_SUCCESS
;
if
(
error
==
GIT_EPASSTHROUGH
)
error
=
0
;
return
git__rethrow
(
error
,
"Failed to open write stream"
)
;
return
error
;
}
int
git_odb_open_rstream
(
git_odb_stream
**
stream
,
git_odb
*
db
,
const
git_oid
*
oid
)
...
...
@@ -687,9 +674,21 @@ int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oi
error
=
b
->
readstream
(
stream
,
b
,
oid
);
}
if
(
error
==
GIT_EPASSTHROUGH
||
error
==
GIT_SUCCESS
)
return
GIT_SUCCESS
;
if
(
error
==
GIT_EPASSTHROUGH
)
error
=
0
;
return
git__rethrow
(
error
,
"Failed to open read stream"
);
return
error
;
}
int
git_odb__error_notfound
(
const
char
*
message
)
{
giterr_set
(
GITERR_ODB
,
"Object not found - %s"
,
message
);
return
GIT_ENOTFOUND
;
}
int
git_odb__error_ambiguous
(
const
char
*
message
)
{
giterr_set
(
GITERR_ODB
,
"Ambiguous SHA1 prefix - %s"
,
message
);
return
GIT_EAMBIGUOUS
;
}
src/odb.h
View file @
e24fbba9
...
...
@@ -67,4 +67,14 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type);
*/
int
git_odb__hashlink
(
git_oid
*
out
,
const
char
*
path
);
/*
* Generate a GIT_ENOTFOUND error for the ODB.
*/
int
git_odb__error_notfound
(
const
char
*
message
);
/*
* Generate a GIT_EAMBIGUOUS error for the ODB.
*/
int
git_odb__error_ambiguous
(
const
char
*
message
);
#endif
src/odb_loose.c
View file @
e24fbba9
...
...
@@ -61,8 +61,8 @@ static int object_file_name(git_buf *name, const char *dir, const git_oid *id)
git_buf_sets
(
name
,
dir
);
/* expand length for 40 hex sha1 chars + 2 * '/' + '\0' */
if
(
git_buf_grow
(
name
,
name
->
size
+
GIT_OID_HEXSZ
+
3
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
if
(
git_buf_grow
(
name
,
name
->
size
+
GIT_OID_HEXSZ
+
3
)
<
0
)
return
-
1
;
git_path_to_dir
(
name
);
...
...
@@ -71,7 +71,7 @@ static int object_file_name(git_buf *name, const char *dir, const git_oid *id)
name
->
size
+=
GIT_OID_HEXSZ
+
1
;
name
->
ptr
[
name
->
size
]
=
'\0'
;
return
GIT_SUCCESS
;
return
0
;
}
...
...
@@ -199,10 +199,12 @@ static int finish_inflate(z_stream *s)
inflateEnd
(
s
);
if
((
status
!=
Z_STREAM_END
)
||
(
s
->
avail_in
!=
0
))
return
git__throw
(
GIT_ERROR
,
"Failed to finish inflation. Stream aborted prematurely"
);
if
((
status
!=
Z_STREAM_END
)
||
(
s
->
avail_in
!=
0
))
{
giterr_set
(
GITERR_ZLIB
,
"Failed to finish ZLib inflation. Stream aborted prematurely"
);
return
-
1
;
}
return
GIT_SUCCESS
;
return
0
;
}
static
int
is_zlib_compressed_data
(
unsigned
char
*
data
)
...
...
@@ -226,21 +228,24 @@ static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
zs
.
next_in
=
in
;
zs
.
avail_in
=
(
uInt
)
inlen
;
if
(
inflateInit
(
&
zs
)
<
Z_OK
)
return
git__throw
(
GIT_ERROR
,
"Failed to inflate buffer"
);
if
(
inflateInit
(
&
zs
)
<
Z_OK
)
{
giterr_set
(
GITERR_ZLIB
,
"Failed to inflate buffer"
);
return
-
1
;
}
while
(
status
==
Z_OK
)
status
=
inflate
(
&
zs
,
Z_FINISH
);
inflateEnd
(
&
zs
);
if
((
status
!=
Z_STREAM_END
)
/*|| (zs.avail_in != 0) */
)
return
git__throw
(
GIT_ERROR
,
"Failed to inflate buffer. Stream aborted prematurely"
);
if
(
zs
.
total_out
!=
outlen
)
return
git__throw
(
GIT_ERROR
,
"Failed to inflate buffer. Stream aborted prematurely"
);
if
(
status
!=
Z_STREAM_END
/* || zs.avail_in != 0 */
||
zs
.
total_out
!=
outlen
)
{
giterr_set
(
GITERR_ZLIB
,
"Failed to inflate buffer. Stream aborted prematurely"
);
return
-
1
;
}
return
GIT_SUCCESS
;
return
0
;
}
static
void
*
inflate_tail
(
z_stream
*
s
,
void
*
hb
,
size_t
used
,
obj_hdr
*
hdr
)
...
...
@@ -297,24 +302,23 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj)
* read the object header, which is an (uncompressed)
* binary encoding of the object type and size.
*/
if
((
used
=
get_binary_object_header
(
&
hdr
,
obj
))
==
0
)
return
git__throw
(
GIT_ERROR
,
"Failed to inflate loose object. Object has no header"
);
if
(
!
git_object_typeisloose
(
hdr
.
type
))
return
git__throw
(
GIT_ERROR
,
"Failed to inflate loose object. Wrong object type"
);
if
((
used
=
get_binary_object_header
(
&
hdr
,
obj
))
==
0
||
!
git_object_typeisloose
(
hdr
.
type
))
{
giterr_set
(
GITERR_ODB
,
"Failed to inflate loose object."
);
return
-
1
;
}
/*
* allocate a buffer and inflate the data into it
*/
buf
=
git__malloc
(
hdr
.
size
+
1
);
if
(
!
buf
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
buf
);
in
=
((
unsigned
char
*
)
obj
->
ptr
)
+
used
;
len
=
obj
->
size
-
used
;
if
(
inflate_buffer
(
in
,
len
,
buf
,
hdr
.
size
))
{
if
(
inflate_buffer
(
in
,
len
,
buf
,
hdr
.
size
)
<
0
)
{
git__free
(
buf
);
return
git__throw
(
GIT_ERROR
,
"Failed to inflate loose object. Could not inflate buffer"
)
;
return
-
1
;
}
buf
[
hdr
.
size
]
=
'\0'
;
...
...
@@ -322,7 +326,7 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj)
out
->
len
=
hdr
.
size
;
out
->
type
=
hdr
.
type
;
return
GIT_SUCCESS
;
return
0
;
}
static
int
inflate_disk_obj
(
git_rawobj
*
out
,
git_buf
*
obj
)
...
...
@@ -342,28 +346,27 @@ static int inflate_disk_obj(git_rawobj *out, git_buf *obj)
* inflate the initial part of the io buffer in order
* to parse the object header (type and size).
*/
if
(
start_inflate
(
&
zs
,
obj
,
head
,
sizeof
(
head
))
<
Z_OK
)
return
git__throw
(
GIT_ERROR
,
"Failed to inflate disk object. Could not inflate buffer"
);
if
((
used
=
get_object_header
(
&
hdr
,
head
))
==
0
)
return
git__throw
(
GIT_ERROR
,
"Failed to inflate disk object. Object has no header"
);
if
(
!
git_object_typeisloose
(
hdr
.
type
))
return
git__throw
(
GIT_ERROR
,
"Failed to inflate disk object. Wrong object type"
);
if
(
start_inflate
(
&
zs
,
obj
,
head
,
sizeof
(
head
))
<
Z_OK
||
(
used
=
get_object_header
(
&
hdr
,
head
))
==
0
||
!
git_object_typeisloose
(
hdr
.
type
))
{
giterr_set
(
GITERR_ODB
,
"Failed to inflate disk object."
);
return
-
1
;
}
/*
* allocate a buffer and inflate the object data into it
* (including the initial sequence in the head buffer).
*/
if
((
buf
=
inflate_tail
(
&
zs
,
head
,
used
,
&
hdr
))
==
NULL
)
return
GIT_ENOMEM
;
return
-
1
;
buf
[
hdr
.
size
]
=
'\0'
;
out
->
data
=
buf
;
out
->
len
=
hdr
.
size
;
out
->
type
=
hdr
.
type
;
return
GIT_SUCCESS
;
return
0
;
}
...
...
@@ -388,24 +391,23 @@ static int read_loose(git_rawobj *out, git_buf *loc)
assert
(
out
&&
loc
);
if
(
git_buf_oom
(
loc
))
return
GIT_ENOMEM
;
return
-
1
;
out
->
data
=
NULL
;
out
->
len
=
0
;
out
->
type
=
GIT_OBJ_BAD
;
if
(
git_futils_readbuffer
(
&
obj
,
loc
->
ptr
)
<
0
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to read loose object. File not found"
);
if
(
!
(
error
=
git_futils_readbuffer
(
&
obj
,
loc
->
ptr
))
)
error
=
inflate_disk_obj
(
out
,
&
obj
);
error
=
inflate_disk_obj
(
out
,
&
obj
);
git_buf_free
(
&
obj
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to read loose object"
)
;
return
error
;
}
static
int
read_header_loose
(
git_rawobj
*
out
,
git_buf
*
loc
)
{
int
error
=
GIT_SUCCESS
,
z_return
=
Z_ERRNO
,
read_bytes
;
int
error
=
0
,
z_return
=
Z_ERRNO
,
read_bytes
;
git_file
fd
;
z_stream
zs
;
obj_hdr
header_obj
;
...
...
@@ -414,48 +416,40 @@ static int read_header_loose(git_rawobj *out, git_buf *loc)
assert
(
out
&&
loc
);
if
(
git_buf_oom
(
loc
))
return
GIT_ENOMEM
;
return
-
1
;
out
->
data
=
NULL
;
if
((
fd
=
p_open
(
loc
->
ptr
,
O_RDONLY
))
<
0
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to read loose object header. File not found"
)
;
if
((
fd
=
git_futils_open_ro
(
loc
->
ptr
))
<
0
)
return
fd
;
init_stream
(
&
zs
,
inflated_buffer
,
sizeof
(
inflated_buffer
));
if
(
inflateInit
(
&
zs
)
<
Z_OK
)
{
error
=
GIT_EZLIB
;
goto
cleanup
;
}
z_return
=
inflateInit
(
&
zs
);
do
{
if
((
read_bytes
=
read
(
fd
,
raw_buffer
,
sizeof
(
raw_buffer
)))
>
0
)
{
while
(
z_return
==
Z_OK
)
{
if
((
read_bytes
=
p_
read
(
fd
,
raw_buffer
,
sizeof
(
raw_buffer
)))
>
0
)
{
set_stream_input
(
&
zs
,
raw_buffer
,
read_bytes
);
z_return
=
inflate
(
&
zs
,
0
);
}
else
{
}
else
z_return
=
Z_STREAM_END
;
break
;
}
}
while
(
z_return
==
Z_OK
);
}
if
((
z_return
!=
Z_STREAM_END
&&
z_return
!=
Z_BUF_ERROR
)
||
get_object_header
(
&
header_obj
,
inflated_buffer
)
==
0
||
git_object_typeisloose
(
header_obj
.
type
)
==
0
)
{
error
=
GIT_EOBJCORRUPTED
;
goto
cleanup
;
||
git_object_typeisloose
(
header_obj
.
type
)
==
0
)
{
giterr_set
(
GITERR_ZLIB
,
"Failed to read loose object header"
);
error
=
-
1
;
}
else
{
out
->
len
=
header_obj
.
size
;
out
->
type
=
header_obj
.
type
;
}
out
->
len
=
header_obj
.
size
;
out
->
type
=
header_obj
.
type
;
cleanup:
finish_inflate
(
&
zs
);
p_close
(
fd
);
if
(
error
<
GIT_SUCCESS
)
return
git__throw
(
error
,
"Failed to read loose object header. Header is corrupted"
);
return
GIT_SUCCESS
;
return
error
;
}
static
int
locate_object
(
...
...
@@ -465,8 +459,8 @@ static int locate_object(
{
int
error
=
object_file_name
(
object_location
,
backend
->
objects_dir
,
oid
);
if
(
error
==
GIT_SUCCESS
)
error
=
git_path_exists
(
git_buf_cstr
(
object_location
))
?
GIT_SUCCESS
:
GIT_ENOTFOUND
;
if
(
!
error
&&
!
git_path_exists
(
object_location
->
ptr
)
)
return
GIT_ENOTFOUND
;
return
error
;
}
...
...
@@ -477,7 +471,7 @@ static int fn_locate_object_short_oid(void *state, git_buf *pathbuf) {
if
(
pathbuf
->
size
-
sstate
->
dir_len
!=
GIT_OID_HEXSZ
-
2
)
{
/* Entry cannot be an object. Continue to next entry */
return
GIT_SUCCESS
;
return
0
;
}
if
(
git_path_isdir
(
pathbuf
->
ptr
)
==
false
)
{
...
...
@@ -495,10 +489,11 @@ static int fn_locate_object_short_oid(void *state, git_buf *pathbuf) {
sstate
->
found
++
;
}
}
if
(
sstate
->
found
>
1
)
return
git_
_throw
(
GIT_EAMBIGUOUSOIDPREFIX
,
"Ambiguous sha1 prefix with
in loose objects"
);
return
git_
odb__error_ambiguous
(
"multiple matches
in loose objects"
);
return
GIT_SUCCESS
;
return
0
;
}
/* Locate an object matching a given short oid */
...
...
@@ -515,8 +510,8 @@ static int locate_object_short_oid(
int
error
;
/* prealloc memory for OBJ_DIR/xx/ */
if
(
(
error
=
git_buf_grow
(
object_location
,
dir_len
+
5
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to locate object from short oid"
)
;
if
(
git_buf_grow
(
object_location
,
dir_len
+
5
)
<
0
)
return
-
1
;
git_buf_sets
(
object_location
,
objects_dir
);
git_path_to_dir
(
object_location
);
...
...
@@ -528,46 +523,43 @@ static int locate_object_short_oid(
git_oid_fmt
((
char
*
)
state
.
short_oid
,
short_oid
);
/* Explore OBJ_DIR/xx/ where xx is the beginning of hex formatted short oid */
error
=
git_buf_printf
(
object_location
,
"%.2s/"
,
state
.
short_oid
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to locate object from short oid"
);
if
(
git_buf_printf
(
object_location
,
"%.2s/"
,
state
.
short_oid
)
<
0
)
return
-
1
;
/* Check that directory exists */
if
(
git_path_isdir
(
object_location
->
ptr
)
==
false
)
return
git_
_throw
(
GIT_ENOTFOUND
,
"Failed to locate object from short oid. Object not foun
d"
);
return
git_
odb__error_notfound
(
"failed to locate from short oi
d"
);
state
.
dir_len
=
object_location
->
size
;
state
.
short_oid_len
=
len
;
state
.
found
=
0
;
/* Explore directory to find a unique object matching short_oid */
error
=
git_path_direach
(
object_location
,
fn_locate_object_short_oid
,
&
state
);
error
=
git_path_direach
(
object_location
,
fn_locate_object_short_oid
,
&
state
);
if
(
error
)
return
git__rethrow
(
error
,
"Failed to locate object from short oid"
)
;
return
error
;
if
(
!
state
.
found
)
{
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to locate object from short oid. Object not found"
);
}
if
(
!
state
.
found
)
return
git_odb__error_notfound
(
"failed to locate from short oid"
);
/* Convert obtained hex formatted oid to raw */
error
=
git_oid_fromstr
(
res_oid
,
(
char
*
)
state
.
res_oid
);
if
(
error
)
{
return
git__rethrow
(
error
,
"Failed to locate object from short oid"
);
}
if
(
error
)
return
error
;
/* Update the location according to the oid obtained */
git_buf_truncate
(
object_location
,
dir_len
);
error
=
git_buf_grow
(
object_location
,
dir_len
+
GIT_OID_HEXSZ
+
2
);
if
(
error
)
return
git__rethrow
(
error
,
"Failed to locate object from short oid"
);
if
(
git_buf_grow
(
object_location
,
dir_len
+
GIT_OID_HEXSZ
+
2
)
<
0
)
return
-
1
;
git_oid_pathfmt
(
object_location
->
ptr
+
dir_len
,
res_oid
);
object_location
->
size
+=
GIT_OID_HEXSZ
+
1
;
object_location
->
ptr
[
object_location
->
size
]
=
'\0'
;
return
GIT_SUCCESS
;
return
0
;
}
...
...
@@ -598,8 +590,8 @@ static int loose_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_
raw
.
type
=
GIT_OBJ_BAD
;
if
(
locate_object
(
&
object_path
,
(
loose_backend
*
)
backend
,
oid
)
<
0
)
error
=
git_
_throw
(
GIT_ENOTFOUND
,
"Failed to read loose backend header. Object not fou
nd"
);
else
if
((
error
=
read_header_loose
(
&
raw
,
&
object_path
))
==
GIT_SUCCESS
)
{
error
=
git_
odb__error_notfound
(
"in loose backe
nd"
);
else
if
((
error
=
read_header_loose
(
&
raw
,
&
object_path
))
==
0
)
{
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
}
...
...
@@ -613,20 +605,17 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p
{
git_buf
object_path
=
GIT_BUF_INIT
;
git_rawobj
raw
;
int
error
=
GIT_SUCCESS
;
int
error
=
0
;
assert
(
backend
&&
oid
);
if
(
locate_object
(
&
object_path
,
(
loose_backend
*
)
backend
,
oid
)
<
0
)
error
=
git_
_throw
(
GIT_ENOTFOUND
,
"Failed to read loose backend. Object not fou
nd"
);
else
if
((
error
=
read_loose
(
&
raw
,
&
object_path
))
==
GIT_SUCCESS
)
{
error
=
git_
odb__error_notfound
(
"in loose backe
nd"
);
else
if
((
error
=
read_loose
(
&
raw
,
&
object_path
))
==
0
)
{
*
buffer_p
=
raw
.
data
;
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
}
else
{
git__rethrow
(
error
,
"Failed to read loose backend"
);
}
git_buf_free
(
&
object_path
);
...
...
@@ -642,16 +631,15 @@ static int loose_backend__read_prefix(
const
git_oid
*
short_oid
,
unsigned
int
len
)
{
int
error
=
GIT_SUCCESS
;
int
error
=
0
;
if
(
len
<
GIT_OID_MINPREFIXLEN
)
return
git__throw
(
GIT_EAMBIGUOUSOIDPREFIX
,
"Failed to read loose "
"backend. Prefix length is lower than %d."
,
GIT_OID_MINPREFIXLEN
);
error
=
git_odb__error_ambiguous
(
"prefix length too short"
);
if
(
len
>=
GIT_OID_HEXSZ
)
{
else
if
(
len
>=
GIT_OID_HEXSZ
)
{
/* We can fall back to regular read method */
error
=
loose_backend__read
(
buffer_p
,
len_p
,
type_p
,
backend
,
short_oid
);
if
(
error
==
GIT_SUCCESS
)
if
(
!
error
)
git_oid_cpy
(
out_oid
,
short_oid
);
}
else
{
git_buf
object_path
=
GIT_BUF_INIT
;
...
...
@@ -660,11 +648,9 @@ static int loose_backend__read_prefix(
assert
(
backend
&&
short_oid
);
if
((
error
=
locate_object_short_oid
(
&
object_path
,
out_oid
,
(
loose_backend
*
)
backend
,
short_oid
,
len
))
<
0
)
git__rethrow
(
error
,
"Failed to read loose backend"
);
else
if
((
error
=
read_loose
(
&
raw
,
&
object_path
))
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"Failed to read loose backend"
);
else
{
(
loose_backend
*
)
backend
,
short_oid
,
len
))
==
0
&&
(
error
=
read_loose
(
&
raw
,
&
object_path
))
==
0
)
{
*
buffer_p
=
raw
.
data
;
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
...
...
@@ -687,47 +673,33 @@ static int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
git_buf_free
(
&
object_path
);
return
(
error
==
GIT_SUCCESS
)
;
return
!
error
;
}
static
int
loose_backend__stream_fwrite
(
git_oid
*
oid
,
git_odb_stream
*
_stream
)
{
loose_writestream
*
stream
=
(
loose_writestream
*
)
_stream
;
loose_backend
*
backend
=
(
loose_backend
*
)
_stream
->
backend
;
int
error
;
git_buf
final_path
=
GIT_BUF_INIT
;
int
error
=
0
;
if
((
error
=
git_filebuf_hash
(
oid
,
&
stream
->
fbuf
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
((
error
=
object_file_name
(
&
final_path
,
backend
->
objects_dir
,
oid
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_buf_oom
(
&
final_path
))
return
GIT_ENOMEM
;
if
((
error
=
git_futils_mkpath2file
(
final_path
.
ptr
,
GIT_OBJECT_DIR_MODE
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_filebuf_hash
(
oid
,
&
stream
->
fbuf
)
<
0
||
object_file_name
(
&
final_path
,
backend
->
objects_dir
,
oid
)
<
0
||
git_futils_mkpath2file
(
final_path
.
ptr
,
GIT_OBJECT_DIR_MODE
)
<
0
)
error
=
-
1
;
/*
* Don't try to add an existing object to the repository. This
* is what git does and allows us to sidestep the fact that
* we're not allowed to overwrite a read-only file on Windows.
*/
if
(
git_path_exists
(
final_path
.
ptr
)
==
true
)
{
else
if
(
git_path_exists
(
final_path
.
ptr
)
==
true
)
git_filebuf_cleanup
(
&
stream
->
fbuf
);
goto
cleanup
;
}
error
=
git_filebuf_commit_at
(
&
stream
->
fbuf
,
final_path
.
ptr
,
GIT_OBJECT_FILE_MODE
);
else
error
=
git_filebuf_commit_at
(
&
stream
->
fbuf
,
final_path
.
ptr
,
GIT_OBJECT_FILE_MODE
);
cleanup:
git_buf_free
(
&
final_path
);
if
(
error
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"Failed to write loose backend"
);
return
error
;
}
...
...
@@ -751,22 +723,18 @@ static int format_object_header(char *hdr, size_t n, size_t obj_len, git_otype o
int
len
=
snprintf
(
hdr
,
n
,
"%s %"
PRIuZ
,
type_str
,
obj_len
);
assert
(
len
>
0
);
/* otherwise snprintf() is broken */
assert
(((
size_t
)
len
)
<
n
);
/* otherwise the caller is broken! */
assert
(((
size_t
)
len
)
<
n
);
/* otherwise the caller is broken! */
if
(
len
<
0
||
((
size_t
)
len
)
>=
n
)
return
git__throw
(
GIT_ERROR
,
"Failed to format object header. Length is out of bounds"
);
return
len
+
1
;
}
static
int
loose_backend__stream
(
git_odb_stream
**
stream_out
,
git_odb_backend
*
_backend
,
size_t
length
,
git_otype
type
)
{
loose_backend
*
backend
;
loose_writestream
*
stream
;
loose_writestream
*
stream
=
NULL
;
char
hdr
[
64
];
git_buf
tmp_path
=
GIT_BUF_INIT
;
int
hdrlen
;
int
error
;
assert
(
_backend
);
...
...
@@ -774,12 +742,9 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_
*
stream_out
=
NULL
;
hdrlen
=
format_object_header
(
hdr
,
sizeof
(
hdr
),
length
,
type
);
if
(
hdrlen
<
GIT_SUCCESS
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to create loose backend stream. Object is corrupted"
);
stream
=
git__calloc
(
1
,
sizeof
(
loose_writestream
));
if
(
stream
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
stream
);
stream
->
stream
.
backend
=
_backend
;
stream
->
stream
.
read
=
NULL
;
/* read only */
...
...
@@ -788,31 +753,21 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_
stream
->
stream
.
free
=
&
loose_backend__stream_free
;
stream
->
stream
.
mode
=
GIT_STREAM_WRONLY
;
error
=
git_buf_joinpath
(
&
tmp_path
,
backend
->
objects_dir
,
"tmp_object"
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_filebuf_open
(
&
stream
->
fbuf
,
tmp_path
.
ptr
,
GIT_FILEBUF_HASH_CONTENTS
|
GIT_FILEBUF_TEMPORARY
|
(
backend
->
object_zlib_level
<<
GIT_FILEBUF_DEFLATE_SHIFT
));
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
stream
->
stream
.
write
((
git_odb_stream
*
)
stream
,
hdr
,
hdrlen
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_buf_joinpath
(
&
tmp_path
,
backend
->
objects_dir
,
"tmp_object"
)
<
0
||
git_filebuf_open
(
&
stream
->
fbuf
,
tmp_path
.
ptr
,
GIT_FILEBUF_HASH_CONTENTS
|
GIT_FILEBUF_TEMPORARY
|
(
backend
->
object_zlib_level
<<
GIT_FILEBUF_DEFLATE_SHIFT
))
<
0
||
stream
->
stream
.
write
((
git_odb_stream
*
)
stream
,
hdr
,
hdrlen
)
<
0
)
{
git_filebuf_cleanup
(
&
stream
->
fbuf
);
git__free
(
stream
);
stream
=
NULL
;
}
git_buf_free
(
&
tmp_path
);
*
stream_out
=
(
git_odb_stream
*
)
stream
;
return
GIT_SUCCESS
;
cleanup:
git_buf_free
(
&
tmp_path
);
git_filebuf_cleanup
(
&
stream
->
fbuf
);
git__free
(
stream
);
return
git__rethrow
(
error
,
"Failed to create loose backend stream"
);
return
!
stream
?
-
1
:
0
;
}
static
int
loose_backend__write
(
git_oid
*
oid
,
git_odb_backend
*
_backend
,
const
void
*
data
,
size_t
len
,
git_otype
type
)
...
...
@@ -826,36 +781,26 @@ static int loose_backend__write(git_oid *oid, git_odb_backend *_backend, const v
backend
=
(
loose_backend
*
)
_backend
;
/* prepare the header for the file */
{
header_len
=
format_object_header
(
header
,
sizeof
(
header
),
len
,
type
);
if
(
header_len
<
GIT_SUCCESS
)
return
GIT_EOBJCORRUPTED
;
}
error
=
git_buf_joinpath
(
&
final_path
,
backend
->
objects_dir
,
"tmp_object"
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
header_len
=
format_object_header
(
header
,
sizeof
(
header
),
len
,
type
);
error
=
git_filebuf_open
(
&
fbuf
,
final_path
.
ptr
,
GIT_FILEBUF_HASH_CONTENTS
|
GIT_FILEBUF_TEMPORARY
|
(
backend
->
object_zlib_level
<<
GIT_FILEBUF_DEFLATE_SHIFT
));
if
(
error
<
GIT_SUCCESS
)
if
(
git_buf_joinpath
(
&
final_path
,
backend
->
objects_dir
,
"tmp_object"
)
<
0
||
git_filebuf_open
(
&
fbuf
,
final_path
.
ptr
,
GIT_FILEBUF_HASH_CONTENTS
|
GIT_FILEBUF_TEMPORARY
|
(
backend
->
object_zlib_level
<<
GIT_FILEBUF_DEFLATE_SHIFT
))
<
0
)
{
error
=
-
1
;
goto
cleanup
;
}
git_filebuf_write
(
&
fbuf
,
header
,
header_len
);
git_filebuf_write
(
&
fbuf
,
data
,
len
);
git_filebuf_hash
(
oid
,
&
fbuf
);
error
=
object_file_name
(
&
final_path
,
backend
->
objects_dir
,
oid
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_futils_mkpath2file
(
final_path
.
ptr
,
GIT_OBJECT_DIR_MODE
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_filebuf_commit_at
(
&
fbuf
,
final_path
.
ptr
,
GIT_OBJECT_FILE_MODE
);
if
(
object_file_name
(
&
final_path
,
backend
->
objects_dir
,
oid
)
<
0
||
git_futils_mkpath2file
(
final_path
.
ptr
,
GIT_OBJECT_DIR_MODE
)
<
0
||
git_filebuf_commit_at
(
&
fbuf
,
final_path
.
ptr
,
GIT_OBJECT_FILE_MODE
)
<
0
)
error
=
-
1
;
cleanup:
if
(
error
<
GIT_SUCCESS
)
...
...
@@ -883,14 +828,10 @@ int git_odb_backend_loose(
loose_backend
*
backend
;
backend
=
git__calloc
(
1
,
sizeof
(
loose_backend
));
if
(
backend
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
backend
);
backend
->
objects_dir
=
git__strdup
(
objects_dir
);
if
(
backend
->
objects_dir
==
NULL
)
{
git__free
(
backend
);
return
GIT_ENOMEM
;
}
GITERR_CHECK_ALLOC
(
backend
->
objects_dir
);
if
(
compression_level
<
0
)
compression_level
=
Z_BEST_SPEED
;
...
...
@@ -907,5 +848,5 @@ int git_odb_backend_loose(
backend
->
parent
.
free
=
&
loose_backend__free
;
*
backend_out
=
(
git_odb_backend
*
)
backend
;
return
GIT_SUCCESS
;
return
0
;
}
src/odb_pack.c
View file @
e24fbba9
...
...
@@ -137,19 +137,19 @@ static int packfile_load__cb(void *_data, git_buf *path);
static
int
packfile_refresh_all
(
struct
pack_backend
*
backend
);
static
int
pack_entry_find
(
struct
git_pack_entry
*
e
,
struct
pack_backend
*
backend
,
const
git_oid
*
oid
);
struct
pack_backend
*
backend
,
const
git_oid
*
oid
);
/* Can find the offset of an object given
* a prefix of an identifier.
* Throws GIT_EAMBIGUOUSOIDPREFIX if short oid
* is ambiguous.
* Sets GIT_EAMBIGUOUS if short oid is ambiguous.
* This method assumes that len is between
* GIT_OID_MINPREFIXLEN and GIT_OID_HEXSZ.
*/
static
int
pack_entry_find_prefix
(
struct
git_pack_entry
*
e
,
struct
pack_backend
*
backend
,
const
git_oid
*
short_oid
,
unsigned
int
len
);
static
int
pack_entry_find_prefix
(
struct
git_pack_entry
*
e
,
struct
pack_backend
*
backend
,
const
git_oid
*
short_oid
,
unsigned
int
len
);
...
...
@@ -215,27 +215,22 @@ static int packfile_load__cb(void *_data, git_buf *path)
size_t
i
;
if
(
git__suffixcmp
(
path
->
ptr
,
".idx"
)
!=
0
)
return
GIT_SUCCESS
;
/* not an index */
return
0
;
/* not an index */
for
(
i
=
0
;
i
<
backend
->
packs
.
length
;
++
i
)
{
struct
git_pack_file
*
p
=
git_vector_get
(
&
backend
->
packs
,
i
);
if
(
memcmp
(
p
->
pack_name
,
path
->
ptr
,
path
->
size
-
strlen
(
".idx"
))
==
0
)
return
GIT_SUCCESS
;
return
0
;
}
error
=
git_packfile_check
(
&
pack
,
path
->
ptr
);
if
(
error
==
GIT_ENOTFOUND
)
{
if
(
error
==
GIT_ENOTFOUND
)
/* ignore missing .pack file as git does */
return
GIT_SUCCESS
;
}
else
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to load packfile"
);
if
(
git_vector_insert
(
&
backend
->
packs
,
pack
)
<
GIT_SUCCESS
)
{
git__free
(
pack
);
return
GIT_ENOMEM
;
}
else
if
(
error
<
0
)
return
error
;
return
GIT_SUCCESS
;
return
git_vector_insert
(
&
backend
->
packs
,
pack
)
;
}
static
int
packfile_refresh_all
(
struct
pack_backend
*
backend
)
...
...
@@ -244,10 +239,10 @@ static int packfile_refresh_all(struct pack_backend *backend)
struct
stat
st
;
if
(
backend
->
pack_folder
==
NULL
)
return
GIT_SUCCESS
;
return
0
;
if
(
p_stat
(
backend
->
pack_folder
,
&
st
)
<
0
||
!
S_ISDIR
(
st
.
st_mode
))
return
git_
_throw
(
GIT_ENOTFOUND
,
"Failed to refresh packfiles. Backend not found
"
);
return
git_
odb__error_notfound
(
"failed to refresh packfiles
"
);
if
(
st
.
st_mtime
!=
backend
->
pack_folder_mtime
)
{
git_buf
path
=
GIT_BUF_INIT
;
...
...
@@ -257,14 +252,15 @@ static int packfile_refresh_all(struct pack_backend *backend)
error
=
git_path_direach
(
&
path
,
packfile_load__cb
,
(
void
*
)
backend
);
git_buf_free
(
&
path
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to refresh packfiles"
);
if
(
error
<
0
)
return
error
;
git_vector_sort
(
&
backend
->
packs
);
backend
->
pack_folder_mtime
=
st
.
st_mtime
;
}
return
GIT_SUCCESS
;
return
0
;
}
static
int
pack_entry_find
(
struct
git_pack_entry
*
e
,
struct
pack_backend
*
backend
,
const
git_oid
*
oid
)
...
...
@@ -272,12 +268,12 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen
int
error
;
size_t
i
;
if
((
error
=
packfile_refresh_all
(
backend
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to find pack entry"
)
;
if
((
error
=
packfile_refresh_all
(
backend
))
<
0
)
return
error
;
if
(
backend
->
last_found
&&
git_pack_entry_find
(
e
,
backend
->
last_found
,
oid
,
GIT_OID_HEXSZ
)
==
GIT_SUCCESS
)
return
GIT_SUCCESS
;
git_pack_entry_find
(
e
,
backend
->
last_found
,
oid
,
GIT_OID_HEXSZ
)
==
0
)
return
0
;
for
(
i
=
0
;
i
<
backend
->
packs
.
length
;
++
i
)
{
struct
git_pack_file
*
p
;
...
...
@@ -286,13 +282,13 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen
if
(
p
==
backend
->
last_found
)
continue
;
if
(
git_pack_entry_find
(
e
,
p
,
oid
,
GIT_OID_HEXSZ
)
==
GIT_SUCCESS
)
{
if
(
git_pack_entry_find
(
e
,
p
,
oid
,
GIT_OID_HEXSZ
)
==
0
)
{
backend
->
last_found
=
p
;
return
GIT_SUCCESS
;
return
0
;
}
}
return
git_
_throw
(
GIT_ENOTFOUND
,
"F
ailed to find pack entry"
);
return
git_
odb__error_notfound
(
"f
ailed to find pack entry"
);
}
static
int
pack_entry_find_prefix
(
...
...
@@ -305,16 +301,15 @@ static int pack_entry_find_prefix(
size_t
i
;
unsigned
found
=
0
;
if
((
error
=
packfile_refresh_all
(
backend
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to find pack entry"
)
;
if
((
error
=
packfile_refresh_all
(
backend
))
<
0
)
return
error
;
if
(
backend
->
last_found
)
{
error
=
git_pack_entry_find
(
e
,
backend
->
last_found
,
short_oid
,
len
);
if
(
error
==
GIT_EAMBIGUOUS
OIDPREFIX
)
{
return
git__rethrow
(
error
,
"Failed to find pack entry. Ambiguous sha1 prefix"
)
;
}
else
if
(
error
==
GIT_SUCCESS
)
{
if
(
error
==
GIT_EAMBIGUOUS
)
return
error
;
if
(
!
error
)
found
=
1
;
}
}
for
(
i
=
0
;
i
<
backend
->
packs
.
length
;
++
i
)
{
...
...
@@ -325,24 +320,21 @@ static int pack_entry_find_prefix(
continue
;
error
=
git_pack_entry_find
(
e
,
p
,
short_oid
,
len
);
if
(
error
==
GIT_EAMBIGUOUSOIDPREFIX
)
{
return
git__rethrow
(
error
,
"Failed to find pack entry. Ambiguous sha1 prefix"
);
}
else
if
(
error
==
GIT_SUCCESS
)
{
found
++
;
if
(
found
>
1
)
if
(
error
==
GIT_EAMBIGUOUS
)
return
error
;
if
(
!
error
)
{
if
(
++
found
>
1
)
break
;
backend
->
last_found
=
p
;
}
}
if
(
!
found
)
{
return
git__rethrow
(
GIT_ENOTFOUND
,
"Failed to find pack entry"
);
}
else
if
(
found
>
1
)
{
return
git__rethrow
(
GIT_EAMBIGUOUSOIDPREFIX
,
"Failed to find pack entry. Ambiguous sha1 prefix"
);
}
else
{
return
GIT_SUCCESS
;
}
if
(
!
found
)
return
git_odb__error_notfound
(
"failed to find pack entry"
);
else
if
(
found
>
1
)
return
git_odb__error_ambiguous
(
"found multiple pack entries"
);
else
return
0
;
}
...
...
@@ -374,17 +366,15 @@ static int pack_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p,
git_rawobj
raw
;
int
error
;
if
((
error
=
pack_entry_find
(
&
e
,
(
struct
pack_backend
*
)
backend
,
oid
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to read pack backend"
);
if
((
error
=
git_packfile_unpack
(
&
raw
,
e
.
p
,
&
e
.
offset
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to read pack backend"
);
if
((
error
=
pack_entry_find
(
&
e
,
(
struct
pack_backend
*
)
backend
,
oid
))
<
0
||
(
error
=
git_packfile_unpack
(
&
raw
,
e
.
p
,
&
e
.
offset
))
<
0
)
return
error
;
*
buffer_p
=
raw
.
data
;
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
return
GIT_SUCCESS
;
return
0
;
}
static
int
pack_backend__read_prefix
(
...
...
@@ -396,40 +386,38 @@ static int pack_backend__read_prefix(
const
git_oid
*
short_oid
,
unsigned
int
len
)
{
int
error
=
0
;
if
(
len
<
GIT_OID_MINPREFIXLEN
)
return
git__throw
(
GIT_EAMBIGUOUSOIDPREFIX
,
"Failed to read pack backend. Prefix length is lower than %d."
,
GIT_OID_MINPREFIXLEN
);
error
=
git_odb__error_ambiguous
(
"prefix length too short"
);
if
(
len
>=
GIT_OID_HEXSZ
)
{
else
if
(
len
>=
GIT_OID_HEXSZ
)
{
/* We can fall back to regular read method */
int
error
=
pack_backend__read
(
buffer_p
,
len_p
,
type_p
,
backend
,
short_oid
);
if
(
error
==
GIT_SUCCESS
)
error
=
pack_backend__read
(
buffer_p
,
len_p
,
type_p
,
backend
,
short_oid
);
if
(
!
error
)
git_oid_cpy
(
out_oid
,
short_oid
);
return
error
;
}
else
{
struct
git_pack_entry
e
;
git_rawobj
raw
;
int
error
;
if
((
error
=
pack_entry_find_prefix
(
&
e
,
(
struct
pack_backend
*
)
backend
,
short_oid
,
len
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to read pack backend"
);
if
((
error
=
git_packfile_unpack
(
&
raw
,
e
.
p
,
&
e
.
offset
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to read pack backend"
);
*
buffer_p
=
raw
.
data
;
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
git_oid_cpy
(
out_oid
,
&
e
.
sha1
);
if
((
error
=
pack_entry_find_prefix
(
&
e
,
(
struct
pack_backend
*
)
backend
,
short_oid
,
len
))
==
0
&&
(
error
=
git_packfile_unpack
(
&
raw
,
e
.
p
,
&
e
.
offset
))
==
0
)
{
*
buffer_p
=
raw
.
data
;
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
git_oid_cpy
(
out_oid
,
&
e
.
sha1
);
}
}
return
GIT_SUCCESS
;
return
error
;
}
static
int
pack_backend__exists
(
git_odb_backend
*
backend
,
const
git_oid
*
oid
)
{
struct
git_pack_entry
e
;
return
pack_entry_find
(
&
e
,
(
struct
pack_backend
*
)
backend
,
oid
)
==
GIT_SUCCESS
;
return
pack_entry_find
(
&
e
,
(
struct
pack_backend
*
)
backend
,
oid
)
==
0
;
}
static
void
pack_backend__free
(
git_odb_backend
*
_backend
)
...
...
@@ -455,19 +443,16 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
{
struct
pack_backend
*
backend
=
NULL
;
git_buf
path
=
GIT_BUF_INIT
;
int
error
=
GIT_SUCCESS
;
backend
=
git__calloc
(
1
,
sizeof
(
struct
pack_backend
));
if
(
backend
==
NULL
)
return
GIT_ENOMEM
;
error
=
git_vector_init
(
&
backend
->
packs
,
8
,
packfile_sort__cb
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
GITERR_CHECK_ALLOC
(
backend
);
error
=
git_buf_joinpath
(
&
path
,
objects_dir
,
"pack"
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_vector_init
(
&
backend
->
packs
,
8
,
packfile_sort__cb
)
<
0
||
git_buf_joinpath
(
&
path
,
objects_dir
,
"pack"
)
<
0
)
{
git__free
(
backend
);
return
-
1
;
}
if
(
git_path_isdir
(
git_buf_cstr
(
&
path
))
==
true
)
{
backend
->
pack_folder
=
git_buf_detach
(
&
path
);
...
...
@@ -482,10 +467,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
*
backend_out
=
(
git_odb_backend
*
)
backend
;
cleanup
:
if
(
error
<
GIT_SUCCESS
)
git__free
(
backend
);
git_buf_free
(
&
path
);
return
error
;
return
0
;
}
src/pack.c
View file @
e24fbba9
...
...
@@ -17,12 +17,12 @@
#include <zlib.h>
static
int
packfile_open
(
struct
git_pack_file
*
p
);
static
off_t
nth_packed_object_offset
(
const
struct
git_pack_file
*
p
,
uint32_t
n
);
static
git_
off_t
nth_packed_object_offset
(
const
struct
git_pack_file
*
p
,
uint32_t
n
);
int
packfile_unpack_compressed
(
git_rawobj
*
obj
,
struct
git_pack_file
*
p
,
git_mwindow
**
w_curs
,
off_t
*
curpos
,
git_
off_t
*
curpos
,
size_t
size
,
git_otype
type
);
...
...
@@ -34,12 +34,18 @@ int packfile_unpack_compressed(
* GIT_OID_MINPREFIXLEN and GIT_OID_HEXSZ.
*/
static
int
pack_entry_find_offset
(
off_t
*
offset_out
,
git_
off_t
*
offset_out
,
git_oid
*
found_oid
,
struct
git_pack_file
*
p
,
const
git_oid
*
short_oid
,
unsigned
int
len
);
static
int
packfile_error
(
const
char
*
message
)
{
giterr_set
(
GITERR_ODB
,
"Invalid pack file - %s"
,
message
);
return
-
1
;
}
/***********************************************************
*
* PACK INDEX METHODS
...
...
@@ -58,40 +64,31 @@ static int pack_index_check(const char *path, struct git_pack_file *p)
{
struct
git_pack_idx_header
*
hdr
;
uint32_t
version
,
nr
,
i
,
*
index
;
void
*
idx_map
;
size_t
idx_size
;
struct
stat
st
;
/* TODO: properly open the file without access time */
git_file
fd
=
p_open
(
path
,
O_RDONLY
/*| O_NOATIME */
);
int
error
;
/* TODO: properly open the file without access time using O_NOATIME */
git_file
fd
=
git_futils_open_ro
(
path
);
if
(
fd
<
0
)
return
git__throw
(
GIT_EOSERR
,
"Failed to check index. File missing or corrupted"
)
;
return
fd
;
if
(
p_fstat
(
fd
,
&
st
)
<
GIT_SUCCESS
)
{
if
(
p_fstat
(
fd
,
&
st
)
<
0
||
!
S_ISREG
(
st
.
st_mode
)
||
!
git__is_sizet
(
st
.
st_size
)
||
(
idx_size
=
(
size_t
)
st
.
st_size
)
<
4
*
256
+
20
+
20
)
{
p_close
(
fd
);
return
git__throw
(
GIT_EOSERR
,
"Failed to check index. File appears to be corrupted"
);
}
if
(
!
git__is_sizet
(
st
.
st_size
))
return
GIT_ENOMEM
;
idx_size
=
(
size_t
)
st
.
st_size
;
if
(
idx_size
<
4
*
256
+
20
+
20
)
{
p_close
(
fd
);
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to check index. Object is corrupted"
);
giterr_set
(
GITERR_OS
,
"Failed to check pack index."
);
return
-
1
;
}
error
=
git_futils_mmap_ro
(
&
p
->
index_map
,
fd
,
0
,
idx_size
);
p_close
(
fd
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to check index"
)
;
if
(
error
<
0
)
return
error
;
hdr
=
idx_map
=
p
->
index_map
.
data
;
...
...
@@ -100,7 +97,7 @@ static int pack_index_check(const char *path, struct git_pack_file *p)
if
(
version
<
2
||
version
>
2
)
{
git_futils_mmap_free
(
&
p
->
index_map
);
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to check index. U
nsupported index version"
);
return
packfile_error
(
"u
nsupported index version"
);
}
}
else
...
...
@@ -116,7 +113,7 @@ static int pack_index_check(const char *path, struct git_pack_file *p)
uint32_t
n
=
ntohl
(
index
[
i
]);
if
(
n
<
nr
)
{
git_futils_mmap_free
(
&
p
->
index_map
);
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to check index. I
ndex is non-monotonic"
);
return
packfile_error
(
"i
ndex is non-monotonic"
);
}
nr
=
n
;
}
...
...
@@ -131,7 +128,7 @@ static int pack_index_check(const char *path, struct git_pack_file *p)
*/
if
(
idx_size
!=
4
*
256
+
nr
*
24
+
20
+
20
)
{
git_futils_mmap_free
(
&
p
->
index_map
);
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to check index. Object
is corrupted"
);
return
packfile_error
(
"index
is corrupted"
);
}
}
else
if
(
version
==
2
)
{
/*
...
...
@@ -155,13 +152,13 @@ static int pack_index_check(const char *path, struct git_pack_file *p)
if
(
idx_size
<
min_size
||
idx_size
>
max_size
)
{
git_futils_mmap_free
(
&
p
->
index_map
);
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to check index. W
rong index size"
);
return
packfile_error
(
"w
rong index size"
);
}
}
p
->
index_version
=
version
;
p
->
num_objects
=
nr
;
return
GIT_SUCCESS
;
return
0
;
}
static
int
pack_index_open
(
struct
git_pack_file
*
p
)
...
...
@@ -170,24 +167,26 @@ static int pack_index_open(struct git_pack_file *p)
int
error
;
if
(
p
->
index_map
.
data
)
return
GIT_SUCCESS
;
return
0
;
idx_name
=
git__strdup
(
p
->
pack_name
);
GITERR_CHECK_ALLOC
(
idx_name
);
strcpy
(
idx_name
+
strlen
(
idx_name
)
-
strlen
(
".pack"
),
".idx"
);
error
=
pack_index_check
(
idx_name
,
p
);
git__free
(
idx_name
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to open index"
)
;
return
error
;
}
static
unsigned
char
*
pack_window_open
(
struct
git_pack_file
*
p
,
git_mwindow
**
w_cursor
,
off_t
offset
,
git_
off_t
offset
,
unsigned
int
*
left
)
{
if
(
p
->
mwf
.
fd
==
-
1
&&
packfile_open
(
p
)
<
GIT_SUCCESS
)
if
(
p
->
mwf
.
fd
==
-
1
&&
packfile_open
(
p
)
<
0
)
return
NULL
;
/* Since packfiles end in a hash of their content and it's
...
...
@@ -233,7 +232,7 @@ int git_packfile_unpack_header(
git_otype
*
type_p
,
git_mwindow_file
*
mwf
,
git_mwindow
**
w_curs
,
off_t
*
curpos
)
git_
off_t
*
curpos
)
{
unsigned
char
*
base
;
unsigned
int
left
;
...
...
@@ -248,35 +247,34 @@ int git_packfile_unpack_header(
// base = pack_window_open(p, w_curs, *curpos, &left);
base
=
git_mwindow_open
(
mwf
,
w_curs
,
*
curpos
,
20
,
&
left
);
if
(
base
==
NULL
)
return
GIT_ENOMEM
;
return
-
1
;
used
=
packfile_unpack_header1
(
size_p
,
type_p
,
base
,
left
);
if
(
used
==
0
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"H
eader length is zero"
);
return
packfile_error
(
"h
eader length is zero"
);
*
curpos
+=
used
;
return
GIT_SUCCESS
;
return
0
;
}
static
int
packfile_unpack_delta
(
git_rawobj
*
obj
,
struct
git_pack_file
*
p
,
git_mwindow
**
w_curs
,
off_t
*
curpos
,
git_
off_t
*
curpos
,
size_t
delta_size
,
git_otype
delta_type
,
off_t
obj_offset
)
git_
off_t
obj_offset
)
{
off_t
base_offset
;
git_
off_t
base_offset
;
git_rawobj
base
,
delta
;
int
error
;
base_offset
=
get_delta_base
(
p
,
w_curs
,
curpos
,
delta_type
,
obj_offset
);
if
(
base_offset
==
0
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"D
elta offset is zero"
);
if
(
base_offset
<
0
)
return
git__rethrow
(
base_offset
,
"Failed to get delta base"
)
;
return
packfile_error
(
"d
elta offset is zero"
);
if
(
base_offset
<
0
)
/* must actually be an error code */
return
(
int
)
base_offset
;
git_mwindow_close
(
w_curs
);
error
=
git_packfile_unpack
(
&
base
,
p
,
&
base_offset
);
...
...
@@ -287,35 +285,34 @@ static int packfile_unpack_delta(
*
* We'll need to do this in order to support thin packs.
*/
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Corrupted delta"
)
;
if
(
error
<
0
)
return
error
;
error
=
packfile_unpack_compressed
(
&
delta
,
p
,
w_curs
,
curpos
,
delta_size
,
delta_type
);
if
(
error
<
GIT_SUCCESS
)
{
if
(
error
<
0
)
{
git__free
(
base
.
data
);
return
git__rethrow
(
error
,
"Corrupted delta"
)
;
return
error
;
}
obj
->
type
=
base
.
type
;
error
=
git__delta_apply
(
obj
,
base
.
data
,
base
.
len
,
delta
.
data
,
delta
.
len
);
error
=
git__delta_apply
(
obj
,
base
.
data
,
base
.
len
,
delta
.
data
,
delta
.
len
);
git__free
(
base
.
data
);
git__free
(
delta
.
data
);
/* TODO: we might want to cache this shit. eventually */
//add_delta_base_cache(p, base_offset, base, base_size, *type);
return
error
;
/* error set by git__delta_apply */
}
int
git_packfile_unpack
(
git_rawobj
*
obj
,
struct
git_pack_file
*
p
,
off_t
*
obj_offset
)
git_rawobj
*
obj
,
struct
git_pack_file
*
p
,
git_
off_t
*
obj_offset
)
{
git_mwindow
*
w_curs
=
NULL
;
off_t
curpos
=
*
obj_offset
;
git_
off_t
curpos
=
*
obj_offset
;
int
error
;
size_t
size
=
0
;
...
...
@@ -330,8 +327,8 @@ int git_packfile_unpack(
obj
->
type
=
GIT_OBJ_BAD
;
error
=
git_packfile_unpack_header
(
&
size
,
&
type
,
&
p
->
mwf
,
&
w_curs
,
&
curpos
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to unpack packfile"
)
;
if
(
error
<
0
)
return
error
;
switch
(
type
)
{
case
GIT_OBJ_OFS_DELTA
:
...
...
@@ -351,33 +348,30 @@ int git_packfile_unpack(
break
;
default:
error
=
GIT_EOBJCORRUPTED
;
error
=
packfile_error
(
"invalid packfile type in header"
);
;
break
;
}
git_mwindow_close
(
&
w_curs
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to unpack object"
);
*
obj_offset
=
curpos
;
return
GIT_SUCCESS
;
return
error
;
}
int
packfile_unpack_compressed
(
git_rawobj
*
obj
,
struct
git_pack_file
*
p
,
git_mwindow
**
w_curs
,
off_t
*
curpos
,
size_t
size
,
git_otype
type
)
git_rawobj
*
obj
,
struct
git_pack_file
*
p
,
git_mwindow
**
w_curs
,
git_
off_t
*
curpos
,
size_t
size
,
git_otype
type
)
{
int
st
;
z_stream
stream
;
unsigned
char
*
buffer
,
*
in
;
buffer
=
git__
malloc
(
size
+
1
);
memset
(
buffer
,
0x0
,
size
+
1
);
buffer
=
git__
calloc
(
1
,
size
+
1
);
GITERR_CHECK_ALLOC
(
buffer
);
memset
(
&
stream
,
0
,
sizeof
(
stream
));
stream
.
next_out
=
buffer
;
...
...
@@ -386,7 +380,8 @@ int packfile_unpack_compressed(
st
=
inflateInit
(
&
stream
);
if
(
st
!=
Z_OK
)
{
git__free
(
buffer
);
return
git__throw
(
GIT_EZLIB
,
"Error in zlib"
);
giterr_set
(
GITERR_ZLIB
,
"Failed to inflate packfile"
);
return
-
1
;
}
do
{
...
...
@@ -404,28 +399,29 @@ int packfile_unpack_compressed(
if
((
st
!=
Z_STREAM_END
)
||
stream
.
total_out
!=
size
)
{
git__free
(
buffer
);
return
git__throw
(
GIT_EZLIB
,
"Error in zlib"
);
giterr_set
(
GITERR_ZLIB
,
"Failed to inflate packfile"
);
return
-
1
;
}
obj
->
type
=
type
;
obj
->
len
=
size
;
obj
->
data
=
buffer
;
return
GIT_SUCCESS
;
return
0
;
}
/*
* curpos is where the data starts, delta_obj_offset is the where the
* header starts
*/
off_t
get_delta_base
(
struct
git_pack_file
*
p
,
git_mwindow
**
w_curs
,
off_t
*
curpos
,
git_otype
type
,
off_t
delta_obj_offset
)
git_
off_t
get_delta_base
(
struct
git_pack_file
*
p
,
git_mwindow
**
w_curs
,
git_
off_t
*
curpos
,
git_otype
type
,
git_
off_t
delta_obj_offset
)
{
unsigned
char
*
base_info
=
pack_window_open
(
p
,
w_curs
,
*
curpos
,
NULL
);
off_t
base_offset
;
git_
off_t
base_offset
;
git_oid
unused
;
/* pack_window_open() assured us we have [base_info, base_info + 20)
...
...
@@ -463,8 +459,8 @@ off_t get_delta_base(
}
}
/* The base entry _must_ be in the same pack */
if
(
pack_entry_find_offset
(
&
base_offset
,
&
unused
,
p
,
(
git_oid
*
)
base_info
,
GIT_OID_HEXSZ
)
<
GIT_SUCCESS
)
return
git__rethrow
(
GIT_EPACKCORRUPTED
,
"B
ase entry delta is not in the same pack"
);
if
(
pack_entry_find_offset
(
&
base_offset
,
&
unused
,
p
,
(
git_oid
*
)
base_info
,
GIT_OID_HEXSZ
)
<
0
)
return
packfile_error
(
"b
ase entry delta is not in the same pack"
);
*
curpos
+=
20
;
}
else
return
0
;
...
...
@@ -480,9 +476,9 @@ off_t get_delta_base(
static
struct
git_pack_file
*
packfile_alloc
(
int
extra
)
{
struct
git_pack_file
*
p
=
git__
malloc
(
sizeof
(
*
p
)
+
extra
);
memset
(
p
,
0
,
sizeof
(
*
p
));
p
->
mwf
.
fd
=
-
1
;
struct
git_pack_file
*
p
=
git__
calloc
(
1
,
sizeof
(
*
p
)
+
extra
);
if
(
p
!=
NULL
)
p
->
mwf
.
fd
=
-
1
;
return
p
;
}
...
...
@@ -510,24 +506,25 @@ static int packfile_open(struct git_pack_file *p)
git_oid
sha1
;
unsigned
char
*
idx_sha1
;
assert
(
p
->
index_map
.
data
);
if
(
!
p
->
index_map
.
data
&&
pack_index_open
(
p
)
<
GIT_SUCCESS
)
return
git_
_throw
(
GIT_ENOTFOUND
,
"Failed to open packfile. File not found
"
);
return
git_
odb__error_notfound
(
"failed to open packfile
"
);
/* TODO: open with noatime */
p
->
mwf
.
fd
=
p_open
(
p
->
pack_name
,
O_RDONLY
);
if
(
p
->
mwf
.
fd
<
0
||
p_fstat
(
p
->
mwf
.
fd
,
&
st
)
<
GIT_SUCCESS
)
return
git__throw
(
GIT_EOSERR
,
"Failed to open packfile. File appears to be corrupted"
)
;
p
->
mwf
.
fd
=
git_futils_open_ro
(
p
->
pack_name
);
if
(
p
->
mwf
.
fd
<
0
)
return
p
->
mwf
.
fd
;
if
(
git_mwindow_file_register
(
&
p
->
mwf
)
<
GIT_SUCCESS
)
{
p_close
(
p
->
mwf
.
fd
);
return
git__throw
(
GIT_ERROR
,
"Failed to register packfile windows"
);
}
if
(
p_fstat
(
p
->
mwf
.
fd
,
&
st
)
<
0
||
git_mwindow_file_register
(
&
p
->
mwf
)
<
0
)
goto
cleanup
;
/* If we created the struct before we had the pack we lack size. */
if
(
!
p
->
mwf
.
size
)
{
if
(
!
S_ISREG
(
st
.
st_mode
))
goto
cleanup
;
p
->
mwf
.
size
=
(
off_t
)
st
.
st_size
;
p
->
mwf
.
size
=
(
git_
off_t
)
st
.
st_size
;
}
else
if
(
p
->
mwf
.
size
!=
st
.
st_size
)
goto
cleanup
;
...
...
@@ -537,44 +534,35 @@ static int packfile_open(struct git_pack_file *p)
*/
fd_flag = fcntl(p->mwf.fd, F_GETFD, 0);
if (fd_flag < 0)
return error("cannot determine file descriptor flags")
;
goto cleanup
;
fd_flag |= FD_CLOEXEC;
if (fcntl(p->pack_fd, F_SETFD, fd_flag) == -1)
return GIT_EOSERR
;
goto cleanup
;
#endif
/* Verify we recognize this pack file format. */
if
(
p_read
(
p
->
mwf
.
fd
,
&
hdr
,
sizeof
(
hdr
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
hdr
.
hdr_signature
!=
htonl
(
PACK_SIGNATURE
))
goto
cleanup
;
if
(
!
pack_version_ok
(
hdr
.
hdr_version
))
if
(
p_read
(
p
->
mwf
.
fd
,
&
hdr
,
sizeof
(
hdr
))
<
0
||
hdr
.
hdr_signature
!=
htonl
(
PACK_SIGNATURE
)
||
!
pack_version_ok
(
hdr
.
hdr_version
))
goto
cleanup
;
/* Verify the pack matches its index. */
if
(
p
->
num_objects
!=
ntohl
(
hdr
.
hdr_entries
))
goto
cleanup
;
if
(
p_lseek
(
p
->
mwf
.
fd
,
p
->
mwf
.
size
-
GIT_OID_RAWSZ
,
SEEK_SET
)
==
-
1
)
goto
cleanup
;
if
(
p_read
(
p
->
mwf
.
fd
,
sha1
.
id
,
GIT_OID_RAWSZ
)
<
GIT_SUCCESS
)
if
(
p
->
num_objects
!=
ntohl
(
hdr
.
hdr_entries
)
||
p_lseek
(
p
->
mwf
.
fd
,
p
->
mwf
.
size
-
GIT_OID_RAWSZ
,
SEEK_SET
)
==
-
1
||
p_read
(
p
->
mwf
.
fd
,
sha1
.
id
,
GIT_OID_RAWSZ
)
<
0
)
goto
cleanup
;
idx_sha1
=
((
unsigned
char
*
)
p
->
index_map
.
data
)
+
p
->
index_map
.
len
-
40
;
if
(
git_oid_cmp
(
&
sha1
,
(
git_oid
*
)
idx_sha1
)
!=
0
)
goto
cleanup
;
return
GIT_SUCCESS
;
if
(
git_oid_cmp
(
&
sha1
,
(
git_oid
*
)
idx_sha1
)
==
0
)
return
0
;
cleanup:
giterr_set
(
GITERR_OS
,
"Invalid packfile '%s'"
,
p
->
pack_name
);
p_close
(
p
->
mwf
.
fd
);
p
->
mwf
.
fd
=
-
1
;
return
git__throw
(
GIT_EPACKCORRUPTED
,
"Failed to open packfile. Pack is corrupted"
)
;
return
-
1
;
}
int
git_packfile_check
(
struct
git_pack_file
**
pack_out
,
const
char
*
path
)
...
...
@@ -586,6 +574,7 @@ int git_packfile_check(struct git_pack_file **pack_out, const char *path)
*
pack_out
=
NULL
;
path_len
=
strlen
(
path
);
p
=
packfile_alloc
(
path_len
+
2
);
GITERR_CHECK_ALLOC
(
p
);
/*
* Make sure a corresponding .pack file exists and that
...
...
@@ -594,7 +583,7 @@ int git_packfile_check(struct git_pack_file **pack_out, const char *path)
path_len
-=
strlen
(
".idx"
);
if
(
path_len
<
1
)
{
git__free
(
p
);
return
git_
_throw
(
GIT_ENOTFOUND
,
"Failed to check packfile. Wrong path name
"
);
return
git_
odb__error_notfound
(
"invalid packfile path
"
);
}
memcpy
(
p
->
pack_name
,
path
,
path_len
);
...
...
@@ -604,9 +593,9 @@ int git_packfile_check(struct git_pack_file **pack_out, const char *path)
p
->
pack_keep
=
1
;
strcpy
(
p
->
pack_name
+
path_len
,
".pack"
);
if
(
p_stat
(
p
->
pack_name
,
&
st
)
<
GIT_SUCCESS
||
!
S_ISREG
(
st
.
st_mode
))
{
if
(
p_stat
(
p
->
pack_name
,
&
st
)
<
0
||
!
S_ISREG
(
st
.
st_mode
))
{
git__free
(
p
);
return
git_
_throw
(
GIT_ENOTFOUND
,
"Failed to check packfile. F
ile not found"
);
return
git_
odb__error_notfound
(
"packf
ile not found"
);
}
/* ok, it looks sane as far as we can check without
...
...
@@ -618,11 +607,12 @@ int git_packfile_check(struct git_pack_file **pack_out, const char *path)
/* see if we can parse the sha1 oid in the packfile name */
if
(
path_len
<
40
||
git_oid_fromstr
(
&
p
->
sha1
,
path
+
path_len
-
GIT_OID_HEXSZ
)
<
GIT_SUCCESS
)
git_oid_fromstr
(
&
p
->
sha1
,
path
+
path_len
-
GIT_OID_HEXSZ
)
<
0
)
memset
(
&
p
->
sha1
,
0x0
,
GIT_OID_RAWSZ
);
*
pack_out
=
p
;
return
GIT_SUCCESS
;
return
0
;
}
/***********************************************************
...
...
@@ -631,7 +621,7 @@ int git_packfile_check(struct git_pack_file **pack_out, const char *path)
*
***********************************************************/
static
off_t
nth_packed_object_offset
(
const
struct
git_pack_file
*
p
,
uint32_t
n
)
static
git_
off_t
nth_packed_object_offset
(
const
struct
git_pack_file
*
p
,
uint32_t
n
)
{
const
unsigned
char
*
index
=
p
->
index_map
.
data
;
index
+=
4
*
256
;
...
...
@@ -650,11 +640,11 @@ static off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n)
}
static
int
pack_entry_find_offset
(
off_t
*
offset_out
,
git_oid
*
found_oid
,
struct
git_pack_file
*
p
,
const
git_oid
*
short_oid
,
unsigned
int
len
)
git_
off_t
*
offset_out
,
git_oid
*
found_oid
,
struct
git_pack_file
*
p
,
const
git_oid
*
short_oid
,
unsigned
int
len
)
{
const
uint32_t
*
level1_ofs
=
p
->
index_map
.
data
;
const
unsigned
char
*
index
=
p
->
index_map
.
data
;
...
...
@@ -667,8 +657,8 @@ static int pack_entry_find_offset(
if
(
index
==
NULL
)
{
int
error
;
if
((
error
=
pack_index_open
(
p
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to find offset for pack entry"
)
;
if
((
error
=
pack_index_open
(
p
))
<
0
)
return
error
;
assert
(
p
->
index_map
.
data
);
...
...
@@ -726,22 +716,22 @@ static int pack_entry_find_offset(
}
}
if
(
!
found
)
{
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to find offset for pack entry. Entry not found"
);
}
else
if
(
found
>
1
)
{
return
git__throw
(
GIT_EAMBIGUOUSOIDPREFIX
,
"Failed to find offset for pack entry. Ambiguous sha1 prefix within pack"
);
}
else
{
*
offset_out
=
nth_packed_object_offset
(
p
,
pos
);
git_oid_fromraw
(
found_oid
,
current
);
if
(
!
found
)
return
git_odb__error_notfound
(
"failed to find offset for pack entry"
);
if
(
found
>
1
)
return
git_odb__error_ambiguous
(
"found multiple offsets for pack entry"
);
*
offset_out
=
nth_packed_object_offset
(
p
,
pos
);
git_oid_fromraw
(
found_oid
,
current
);
#ifdef INDEX_DEBUG_LOOKUP
{
unsigned
char
hex_sha1
[
GIT_OID_HEXSZ
+
1
];
git_oid_fmt
(
hex_sha1
,
found_oid
);
hex_sha1
[
GIT_OID_HEXSZ
]
=
'\0'
;
printf
(
"found lo=%d %s
\n
"
,
lo
,
hex_sha1
);
#endif
return
GIT_SUCCESS
;
}
#endif
return
0
;
}
int
git_pack_entry_find
(
...
...
@@ -750,7 +740,7 @@ int git_pack_entry_find(
const
git_oid
*
short_oid
,
unsigned
int
len
)
{
off_t
offset
;
git_
off_t
offset
;
git_oid
found_oid
;
int
error
;
...
...
@@ -760,22 +750,22 @@ int git_pack_entry_find(
unsigned
i
;
for
(
i
=
0
;
i
<
p
->
num_bad_objects
;
i
++
)
if
(
git_oid_cmp
(
short_oid
,
&
p
->
bad_object_sha1
[
i
])
==
0
)
return
git__throw
(
GIT_ERROR
,
"Failed to find pack entry. Bad object found
"
);
return
packfile_error
(
"bad object found in packfile
"
);
}
error
=
pack_entry_find_offset
(
&
offset
,
&
found_oid
,
p
,
short_oid
,
len
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to find pack entry. Couldn't find offset"
)
;
if
(
error
<
0
)
return
error
;
/* we found a unique entry in the index;
* make sure the packfile backing the index
* still exists on disk */
if
(
p
->
mwf
.
fd
==
-
1
&&
packfile_open
(
p
)
<
GIT_SUCCESS
)
return
git__throw
(
GIT_EOSERR
,
"Failed to find pack entry. Packfile doesn't exist on disk"
)
;
if
(
p
->
mwf
.
fd
==
-
1
&&
(
error
=
packfile_open
(
p
))
<
0
)
return
error
;
e
->
offset
=
offset
;
e
->
p
=
p
;
git_oid_cpy
(
&
e
->
sha1
,
&
found_oid
);
return
GIT_SUCCESS
;
return
0
;
}
src/pack.h
View file @
e24fbba9
...
...
@@ -70,7 +70,7 @@ struct git_pack_file {
};
struct
git_pack_entry
{
off_t
offset
;
git_
off_t
offset
;
git_oid
sha1
;
struct
git_pack_file
*
p
;
};
...
...
@@ -80,13 +80,13 @@ int git_packfile_unpack_header(
git_otype
*
type_p
,
git_mwindow_file
*
mwf
,
git_mwindow
**
w_curs
,
off_t
*
curpos
);
git_
off_t
*
curpos
);
int
git_packfile_unpack
(
git_rawobj
*
obj
,
struct
git_pack_file
*
p
,
off_t
*
obj_offset
);
int
git_packfile_unpack
(
git_rawobj
*
obj
,
struct
git_pack_file
*
p
,
git_
off_t
*
obj_offset
);
off_t
get_delta_base
(
struct
git_pack_file
*
p
,
git_mwindow
**
w_curs
,
off_t
*
curpos
,
git_otype
type
,
off_t
delta_obj_offset
);
git_
off_t
get_delta_base
(
struct
git_pack_file
*
p
,
git_mwindow
**
w_curs
,
git_
off_t
*
curpos
,
git_otype
type
,
git_
off_t
delta_obj_offset
);
void
packfile_free
(
struct
git_pack_file
*
p
);
int
git_packfile_check
(
struct
git_pack_file
**
pack_out
,
const
char
*
path
);
...
...
src/path.c
View file @
e24fbba9
...
...
@@ -49,16 +49,14 @@ int git_path_basename_r(git_buf *buffer, const char *path)
while
(
startp
>
path
&&
*
(
startp
-
1
)
!=
'/'
)
startp
--
;
len
=
endp
-
startp
+
1
;
/* Cast is safe because max path < max int */
len
=
(
int
)(
endp
-
startp
+
1
);
Exit:
result
=
len
;
if
(
buffer
!=
NULL
)
{
if
(
git_buf_set
(
buffer
,
startp
,
len
)
<
GIT_SUCCESS
)
return
git__rethrow
(
GIT_ENOMEM
,
"Could not get basename of '%s'"
,
path
);
}
if
(
buffer
!=
NULL
&&
git_buf_set
(
buffer
,
startp
,
len
)
<
0
)
return
-
1
;
return
result
;
}
...
...
@@ -99,7 +97,8 @@ int git_path_dirname_r(git_buf *buffer, const char *path)
endp
--
;
}
while
(
endp
>
path
&&
*
endp
==
'/'
);
len
=
endp
-
path
+
1
;
/* Cast is safe because max path < max int */
len
=
(
int
)(
endp
-
path
+
1
);
#ifdef GIT_WIN32
/* Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return
...
...
@@ -114,11 +113,8 @@ int git_path_dirname_r(git_buf *buffer, const char *path)
Exit:
result
=
len
;
if
(
buffer
!=
NULL
)
{
if
(
git_buf_set
(
buffer
,
path
,
len
)
<
GIT_SUCCESS
)
return
git__rethrow
(
GIT_ENOMEM
,
"Could not get dirname of '%s'"
,
path
);
}
if
(
buffer
!=
NULL
&&
git_buf_set
(
buffer
,
path
,
len
)
<
0
)
return
-
1
;
return
result
;
}
...
...
@@ -152,7 +148,7 @@ char *git_path_basename(const char *path)
const
char
*
git_path_topdir
(
const
char
*
path
)
{
size_t
len
;
in
t
i
;
ssize_
t
i
;
assert
(
path
);
len
=
strlen
(
path
);
...
...
@@ -160,7 +156,7 @@ const char *git_path_topdir(const char *path)
if
(
!
len
||
path
[
len
-
1
]
!=
'/'
)
return
NULL
;
for
(
i
=
len
-
2
;
i
>=
0
;
--
i
)
for
(
i
=
(
ssize_t
)
len
-
2
;
i
>=
0
;
--
i
)
if
(
path
[
i
]
==
'/'
)
break
;
...
...
@@ -199,7 +195,8 @@ int git_path_prettify(git_buf *path_out, const char *path, const char *base)
}
if
(
p_realpath
(
path
,
buf
)
==
NULL
)
{
giterr_set
(
GITERR_OS
,
"Failed to resolve path '%s': %s"
,
path
,
strerror
(
errno
));
giterr_set
(
GITERR_OS
,
"Failed to resolve path '%s': %s"
,
path
,
strerror
(
errno
));
return
(
errno
==
ENOENT
)
?
GIT_ENOTFOUND
:
-
1
;
}
...
...
@@ -211,10 +208,8 @@ int git_path_prettify(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
)
{
if
(
git_path_prettify
(
path_out
,
path
,
base
)
<
0
)
return
-
1
;
return
git_path_to_dir
(
path_out
);
int
error
=
git_path_prettify
(
path_out
,
path
,
base
);
return
(
error
<
0
)
?
error
:
git_path_to_dir
(
path_out
);
}
int
git_path_to_dir
(
git_buf
*
path
)
...
...
@@ -224,10 +219,7 @@ int git_path_to_dir(git_buf *path)
path
->
ptr
[
path
->
size
-
1
]
!=
'/'
)
git_buf_putc
(
path
,
'/'
);
if
(
git_buf_oom
(
path
))
return
-
1
;
return
0
;
return
git_buf_oom
(
path
)
?
-
1
:
0
;
}
void
git_path_string_to_dir
(
char
*
path
,
size_t
size
)
...
...
@@ -242,10 +234,10 @@ void git_path_string_to_dir(char* path, size_t size)
int
git__percent_decode
(
git_buf
*
decoded_out
,
const
char
*
input
)
{
int
len
,
hi
,
lo
,
i
,
error
=
GIT_SUCCESS
;
int
len
,
hi
,
lo
,
i
;
assert
(
decoded_out
&&
input
);
len
=
strlen
(
input
);
len
=
(
int
)
strlen
(
input
);
git_buf_clear
(
decoded_out
);
for
(
i
=
0
;
i
<
len
;
i
++
)
...
...
@@ -268,39 +260,40 @@ int git__percent_decode(git_buf *decoded_out, const char *input)
i
+=
2
;
append:
error
=
git_buf_putc
(
decoded_out
,
c
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to percent decode '%s'."
,
input
);
if
(
git_buf_putc
(
decoded_out
,
c
)
<
0
)
return
-
1
;
}
return
error
;
return
0
;
}
static
int
error_invalid_local_file_uri
(
const
char
*
uri
)
{
giterr_set
(
GITERR_CONFIG
,
"'%s' is not a valid local file URI"
,
uri
);
return
-
1
;
}
int
git_path_fromurl
(
git_buf
*
local_path_out
,
const
char
*
file_url
)
{
int
error
=
GIT_SUCCESS
,
offset
=
0
,
len
;
int
offset
=
0
,
len
;
assert
(
local_path_out
&&
file_url
);
if
(
git__prefixcmp
(
file_url
,
"file://"
)
!=
0
)
return
git__throw
(
GIT_EINVALIDPATH
,
"Parsing of '%s' failed. A file Uri is expected (ie. with 'file://' scheme)."
,
file_url
);
return
error_invalid_local_file_uri
(
file_url
);
offset
+=
7
;
len
=
strlen
(
file_url
);
len
=
(
int
)
strlen
(
file_url
);
if
(
offset
<
len
&&
file_url
[
offset
]
==
'/'
)
offset
++
;
else
if
(
offset
<
len
&&
git__prefixcmp
(
file_url
+
offset
,
"localhost/"
)
==
0
)
offset
+=
10
;
else
return
git__throw
(
GIT_EINVALIDPATH
,
"Parsing of '%s' failed. A local file Uri is expected."
,
file_url
);
return
error_invalid_local_file_uri
(
file_url
);
if
(
offset
>=
len
||
file_url
[
offset
]
==
'/'
)
return
git__throw
(
GIT_EINVALIDPATH
,
"Parsing of '%s' failed. Invalid file Uri format."
,
file_url
);
return
error_invalid_local_file_uri
(
file_url
);
#ifndef _MSC_VER
offset
--
;
/* A *nix absolute path starts with a forward slash */
...
...
@@ -308,11 +301,7 @@ int git_path_fromurl(git_buf *local_path_out, const char *file_url)
git_buf_clear
(
local_path_out
);
error
=
git__percent_decode
(
local_path_out
,
file_url
+
offset
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Parsing of '%s' failed."
,
file_url
);
return
error
;
return
git__percent_decode
(
local_path_out
,
file_url
+
offset
);
}
int
git_path_walk_up
(
...
...
@@ -321,7 +310,7 @@ int git_path_walk_up(
int
(
*
cb
)(
void
*
data
,
git_buf
*
),
void
*
data
)
{
int
error
=
GIT_SUCCESS
;
int
error
=
0
;
git_buf
iter
;
ssize_t
stop
=
0
,
scan
;
char
oldc
=
'\0'
;
...
...
@@ -341,7 +330,7 @@ int git_path_walk_up(
iter
.
asize
=
path
->
asize
;
while
(
scan
>=
stop
)
{
if
((
error
=
cb
(
data
,
&
iter
))
<
GIT_SUCCESS
)
if
((
error
=
cb
(
data
,
&
iter
))
<
0
)
break
;
iter
.
ptr
[
scan
]
=
oldc
;
scan
=
git_buf_rfind_next
(
&
iter
,
'/'
);
...
...
@@ -394,6 +383,18 @@ bool git_path_isfile(const char *path)
return
S_ISREG
(
st
.
st_mode
)
!=
0
;
}
int
git_path_lstat
(
const
char
*
path
,
struct
stat
*
st
)
{
int
err
=
0
;
if
(
p_lstat
(
path
,
st
)
<
0
)
{
err
=
(
errno
==
ENOENT
)
?
GIT_ENOTFOUND
:
-
1
;
giterr_set
(
GITERR_OS
,
"Failed to stat file '%s'"
,
path
);
}
return
err
;
}
static
bool
_check_dir_contents
(
git_buf
*
dir
,
const
char
*
sub
,
...
...
@@ -434,25 +435,24 @@ bool git_path_contains_file(git_buf *base, const char *file)
int
git_path_find_dir
(
git_buf
*
dir
,
const
char
*
path
,
const
char
*
base
)
{
int
error
=
GIT_SUCCESS
;
int
error
;
if
(
base
!=
NULL
&&
git_path_root
(
path
)
<
0
)
error
=
git_buf_joinpath
(
dir
,
base
,
path
);
else
error
=
git_buf_sets
(
dir
,
path
);
if
(
error
==
GIT_SUCCESS
)
{
if
(
!
error
)
{
char
buf
[
GIT_PATH_MAX
];
if
(
p_realpath
(
dir
->
ptr
,
buf
)
!=
NULL
)
error
=
git_buf_sets
(
dir
,
buf
);
}
/* call dirname if this is not a directory */
if
(
error
==
GIT_SUCCESS
&&
git_path_isdir
(
dir
->
ptr
)
==
false
)
if
(
git_path_dirname_r
(
dir
,
dir
->
ptr
)
<
GIT_SUCCESS
)
error
=
GIT_ENOMEM
;
if
(
!
error
&&
git_path_isdir
(
dir
->
ptr
)
==
false
)
error
=
git_path_dirname_r
(
dir
,
dir
->
ptr
);
if
(
error
==
GIT_SUCCESS
)
if
(
!
error
)
error
=
git_path_to_dir
(
dir
);
return
error
;
...
...
@@ -497,9 +497,9 @@ int git_path_direach(
return
-
1
;
wd_len
=
path
->
size
;
dir
=
opendir
(
path
->
ptr
);
if
(
!
dir
)
{
giterr_set
(
GITERR_OS
,
"Failed to
'opendir' %s
"
,
path
->
ptr
);
if
(
(
dir
=
opendir
(
path
->
ptr
))
==
NULL
)
{
giterr_set
(
GITERR_OS
,
"Failed to
open directory '%s'
"
,
path
->
ptr
);
return
-
1
;
}
...
...
@@ -541,9 +541,10 @@ int git_path_dirload(
path_len
=
strlen
(
path
);
assert
(
path_len
>
0
&&
path_len
>=
prefix_len
);
if
((
dir
=
opendir
(
path
))
==
NULL
)
return
git__throw
(
GIT_EOSERR
,
"Failed to process `%s` tree structure."
" An error occured while opening the directory"
,
path
);
if
((
dir
=
opendir
(
path
))
==
NULL
)
{
giterr_set
(
GITERR_OS
,
"Failed to open directory '%s'"
,
path
);
return
-
1
;
}
path
+=
prefix_len
;
path_len
-=
prefix_len
;
...
...
@@ -560,8 +561,7 @@ int git_path_dirload(
entry_path
=
git__malloc
(
path_len
+
need_slash
+
entry_len
+
1
+
alloc_extra
);
if
(
entry_path
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
entry_path
);
if
(
path_len
)
memcpy
(
entry_path
,
path
,
path_len
);
...
...
@@ -570,19 +570,16 @@ int git_path_dirload(
memcpy
(
&
entry_path
[
path_len
+
need_slash
],
de
->
d_name
,
entry_len
);
entry_path
[
path_len
+
need_slash
+
entry_len
]
=
'\0'
;
if
((
error
=
git_vector_insert
(
contents
,
entry_path
))
<
GIT_SUCCESS
)
{
git__free
(
entry_path
);
return
error
;
}
if
(
git_vector_insert
(
contents
,
entry_path
)
<
0
)
return
-
1
;
}
closedir
(
dir
);
if
(
error
!=
GIT_SUCCESS
)
return
git__throw
(
GIT_EOSERR
,
"Failed to process directory entry in `%s`"
,
path
);
if
(
error
!=
0
)
giterr_set
(
GITERR_OS
,
"Failed to process directory entry in '%s'"
,
path
);
return
GIT_SUCCESS
;
return
error
;
}
int
git_path_with_stat_cmp
(
const
void
*
a
,
const
void
*
b
)
...
...
@@ -601,11 +598,12 @@ int git_path_dirload_with_stat(
git_path_with_stat
*
ps
;
git_buf
full
=
GIT_BUF_INIT
;
if
(
(
error
=
git_buf_set
(
&
full
,
path
,
prefix_len
))
!=
GIT_SUCCESS
)
return
error
;
if
(
git_buf_set
(
&
full
,
path
,
prefix_len
)
<
0
)
return
-
1
;
if
((
error
=
git_path_dirload
(
path
,
prefix_len
,
sizeof
(
git_path_with_stat
)
+
1
,
contents
))
!=
GIT_SUCCESS
)
{
error
=
git_path_dirload
(
path
,
prefix_len
,
sizeof
(
git_path_with_stat
)
+
1
,
contents
);
if
(
error
<
0
)
{
git_buf_free
(
&
full
);
return
error
;
}
...
...
@@ -616,8 +614,10 @@ int git_path_dirload_with_stat(
memmove
(
ps
->
path
,
ps
,
path_len
+
1
);
ps
->
path_len
=
path_len
;
git_buf_joinpath
(
&
full
,
full
.
ptr
,
ps
->
path
);
p_lstat
(
full
.
ptr
,
&
ps
->
st
);
if
((
error
=
git_buf_joinpath
(
&
full
,
full
.
ptr
,
ps
->
path
))
<
0
||
(
error
=
git_path_lstat
(
full
.
ptr
,
&
ps
->
st
))
<
0
)
break
;
git_buf_truncate
(
&
full
,
prefix_len
);
if
(
S_ISDIR
(
ps
->
st
.
st_mode
))
{
...
...
src/path.h
View file @
e24fbba9
...
...
@@ -130,6 +130,11 @@ extern bool git_path_isdir(const char *path);
extern
bool
git_path_isfile
(
const
char
*
path
);
/**
* Stat a file and/or link and set error if needed.
*/
extern
int
git_path_lstat
(
const
char
*
path
,
struct
stat
*
st
);
/**
* Check if the parent directory contains the item.
*
* @param dir Directory to check.
...
...
src/posix.c
View file @
e24fbba9
...
...
@@ -34,9 +34,9 @@ int p_getcwd(char *buffer_out, size_t size)
return
-
1
;
git_path_mkposix
(
buffer_out
);
git_path_string_to_dir
(
buffer_out
,
size
);
//Ensure the path ends with a trailing slash
git_path_string_to_dir
(
buffer_out
,
size
);
/* append trailing slash */
return
GIT_SUCCESS
;
return
0
;
}
int
p_rename
(
const
char
*
from
,
const
char
*
to
)
...
...
src/refs.c
View file @
e24fbba9
...
...
@@ -842,7 +842,7 @@ static int reference_path_available(
if
(
!
data
.
available
)
{
giterr_set
(
GITERR_REFERENCE
,
"The path to reference '%s' collides with an existing one"
);
"The path to reference '%s' collides with an existing one"
,
ref
);
return
-
1
;
}
...
...
@@ -902,7 +902,7 @@ static int reference_can_write(
* the rename; the existing one would be overwritten */
if
(
exists
)
{
giterr_set
(
GITERR_REFERENCE
,
"A reference with that name (%s) already exists"
);
"A reference with that name (%s) already exists"
,
refname
);
return
GIT_EEXISTS
;
}
}
...
...
src/repository.c
View file @
e24fbba9
...
...
@@ -377,17 +377,15 @@ void git_repository_set_index(git_repository *repo, git_index *index)
static
int
retrieve_device
(
dev_t
*
device_out
,
const
char
*
path
)
{
int
error
;
struct
stat
path_info
;
assert
(
device_out
);
if
(
p_lstat
(
path
,
&
path_info
))
{
giterr_set
(
GITERR_OS
,
"Failed to retrieve file information: %s"
,
strerror
(
errno
));
return
-
1
;
}
if
((
error
=
git_path_lstat
(
path
,
&
path_info
))
==
0
)
*
device_out
=
path_info
.
st_dev
;
*
device_out
=
path_info
.
st_dev
;
return
0
;
return
error
;
}
/*
...
...
src/unix/map.c
View file @
e24fbba9
...
...
@@ -17,12 +17,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
int
mprot
=
0
;
int
mflag
=
0
;
assert
((
out
!=
NULL
)
&&
(
len
>
0
));
if
((
out
==
NULL
)
||
(
len
==
0
))
{
errno
=
EINVAL
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. No map or zero length"
);
}
GIT_MMAP_VALIDATE
(
out
,
len
,
prot
,
flags
);
out
->
data
=
NULL
;
out
->
len
=
0
;
...
...
@@ -31,39 +26,28 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
mprot
=
PROT_WRITE
;
else
if
(
prot
&
GIT_PROT_READ
)
mprot
=
PROT_READ
;
else
{
errno
=
EINVAL
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. Invalid protection parameters"
);
}
if
((
flags
&
GIT_MAP_TYPE
)
==
GIT_MAP_SHARED
)
mflag
=
MAP_SHARED
;
else
if
((
flags
&
GIT_MAP_TYPE
)
==
GIT_MAP_PRIVATE
)
mflag
=
MAP_PRIVATE
;
if
(
flags
&
GIT_MAP_FIXED
)
{
errno
=
EINVAL
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. FIXED not set"
);
out
->
data
=
mmap
(
NULL
,
len
,
mprot
,
mflag
,
fd
,
offset
);
if
(
!
out
->
data
||
out
->
data
==
MAP_FAILED
)
{
giterr_set
(
GITERR_OS
,
"Failed to mmap. Could not write data"
);
return
-
1
;
}
out
->
data
=
mmap
(
NULL
,
len
,
mprot
,
mflag
,
fd
,
offset
);
if
(
!
out
->
data
||
out
->
data
==
MAP_FAILED
)
return
git__throw
(
GIT_EOSERR
,
"Failed to mmap. Could not write data"
);
out
->
len
=
len
;
return
GIT_SUCCESS
;
return
0
;
}
int
p_munmap
(
git_map
*
map
)
{
assert
(
map
!=
NULL
);
if
(
!
map
)
return
git__throw
(
GIT_ERROR
,
"Failed to munmap. Map does not exist"
);
munmap
(
map
->
data
,
map
->
len
);
return
GIT_SUCCESS
;
return
0
;
}
#endif
...
...
src/win32/dir.c
View file @
e24fbba9
...
...
@@ -27,8 +27,8 @@ static int init_filter(char *filter, size_t n, const char *dir)
git__DIR
*
git__opendir
(
const
char
*
dir
)
{
char
filter
[
4096
];
wchar_t
*
filter_w
;
git__DIR
*
new
;
wchar_t
*
filter_w
=
NULL
;
git__DIR
*
new
=
NULL
;
if
(
!
dir
||
!
init_filter
(
filter
,
sizeof
(
filter
),
dir
))
return
NULL
;
...
...
@@ -37,25 +37,29 @@ git__DIR *git__opendir(const char *dir)
if
(
!
new
)
return
NULL
;
new
->
dir
=
git__malloc
(
strlen
(
dir
)
+
1
);
if
(
!
new
->
dir
)
{
git__free
(
new
);
return
NULL
;
}
strcpy
(
new
->
dir
,
dir
);
new
->
dir
=
git__strdup
(
dir
);
if
(
!
new
->
dir
)
goto
fail
;
filter_w
=
gitwin_to_utf16
(
filter
);
if
(
!
filter_w
)
goto
fail
;
new
->
h
=
FindFirstFileW
(
filter_w
,
&
new
->
f
);
git__free
(
filter_w
);
if
(
new
->
h
==
INVALID_HANDLE_VALUE
)
{
git__free
(
new
->
dir
);
git__free
(
new
);
return
NULL
;
giterr_set
(
GITERR_OS
,
"Could not open directory '%s'"
,
dir
);
goto
fail
;
}
new
->
first
=
1
;
new
->
first
=
1
;
return
new
;
fail:
git__free
(
new
->
dir
);
git__free
(
new
);
return
NULL
;
}
int
git__readdir_ext
(
...
...
@@ -67,22 +71,32 @@ int git__readdir_ext(
if
(
!
d
||
!
entry
||
!
result
||
d
->
h
==
INVALID_HANDLE_VALUE
)
return
-
1
;
*
result
=
NULL
;
if
(
d
->
first
)
d
->
first
=
0
;
else
if
(
!
FindNextFileW
(
d
->
h
,
&
d
->
f
))
{
*
result
=
NULL
;
return
0
;
if
(
GetLastError
()
==
ERROR_NO_MORE_FILES
)
return
0
;
giterr_set
(
GITERR_OS
,
"Could not read from directory '%s'"
,
d
->
dir
);
return
-
1
;
}
if
(
wcslen
(
d
->
f
.
cFileName
)
>=
sizeof
(
entry
->
d_name
))
return
-
1
;
entry
->
d_ino
=
0
;
WideCharToMultiByte
(
if
(
WideCharToMultiByte
(
gitwin_get_codepage
(),
0
,
d
->
f
.
cFileName
,
-
1
,
entry
->
d_name
,
GIT_PATH_MAX
,
NULL
,
NULL
);
entry
->
d_name
,
GIT_PATH_MAX
,
NULL
,
NULL
)
==
0
)
{
giterr_set
(
GITERR_OS
,
"Could not convert filename to UTF-8"
);
return
-
1
;
}
*
result
=
entry
;
if
(
is_dir
!=
NULL
)
*
is_dir
=
((
d
->
f
.
dwFileAttributes
&
FILE_ATTRIBUTE_DIRECTORY
)
!=
0
);
...
...
@@ -102,32 +116,40 @@ void git__rewinddir(git__DIR *d)
char
filter
[
4096
];
wchar_t
*
filter_w
;
if
(
d
)
{
if
(
d
->
h
!=
INVALID_HANDLE_VALUE
)
FindClose
(
d
->
h
);
if
(
!
d
)
return
;
if
(
d
->
h
!=
INVALID_HANDLE_VALUE
)
{
FindClose
(
d
->
h
);
d
->
h
=
INVALID_HANDLE_VALUE
;
d
->
first
=
0
;
}
if
(
init_filter
(
filter
,
sizeof
(
filter
),
d
->
dir
))
{
filter_w
=
gitwin_to_utf16
(
filter
);
d
->
h
=
FindFirstFileW
(
filter_w
,
&
d
->
f
);
git__free
(
filter_w
);
if
(
!
init_filter
(
filter
,
sizeof
(
filter
),
d
->
dir
)
||
(
filter_w
=
gitwin_to_utf16
(
filter
))
==
NULL
)
return
;
if
(
d
->
h
!=
INVALID_HANDLE_VALUE
)
d
->
first
=
1
;
}
}
d
->
h
=
FindFirstFileW
(
filter_w
,
&
d
->
f
);
git__free
(
filter_w
);
if
(
d
->
h
==
INVALID_HANDLE_VALUE
)
giterr_set
(
GITERR_OS
,
"Could not open directory '%s'"
,
d
->
dir
);
else
d
->
first
=
1
;
}
int
git__closedir
(
git__DIR
*
d
)
{
if
(
d
)
{
if
(
d
->
h
!=
INVALID_HANDLE_VALUE
)
FindClose
(
d
->
h
);
if
(
d
->
dir
)
git__free
(
d
->
dir
);
git__free
(
d
)
;
if
(
!
d
)
return
0
;
if
(
d
->
h
!=
INVALID_HANDLE_VALUE
)
{
FindClose
(
d
->
h
);
d
->
h
=
INVALID_HANDLE_VALUE
;
}
git__free
(
d
->
dir
);
d
->
dir
=
NULL
;
git__free
(
d
);
return
0
;
}
src/win32/map.c
View file @
e24fbba9
...
...
@@ -33,12 +33,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
git_off_t
page_start
;
git_off_t
page_offset
;
assert
((
out
!=
NULL
)
&&
(
len
>
0
));
if
((
out
==
NULL
)
||
(
len
==
0
))
{
errno
=
EINVAL
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. No map or zero length"
);
}
GIT_MMAP_VALIDATE
(
out
,
len
,
prot
,
flags
);
out
->
data
=
NULL
;
out
->
len
=
0
;
...
...
@@ -46,86 +41,75 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
if
(
fh
==
INVALID_HANDLE_VALUE
)
{
errno
=
EBADF
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. Invalid handle value"
);
giterr_set
(
GITERR_OS
,
"Failed to mmap. Invalid handle value"
);
return
-
1
;
}
if
(
prot
&
GIT_PROT_WRITE
)
fmap_prot
|=
PAGE_READWRITE
;
else
if
(
prot
&
GIT_PROT_READ
)
fmap_prot
|=
PAGE_READONLY
;
else
{
errno
=
EINVAL
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. Invalid protection parameters"
);
}
if
(
prot
&
GIT_PROT_WRITE
)
view_prot
|=
FILE_MAP_WRITE
;
if
(
prot
&
GIT_PROT_READ
)
view_prot
|=
FILE_MAP_READ
;
if
(
flags
&
GIT_MAP_FIXED
)
{
errno
=
EINVAL
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. FIXED not set"
);
}
page_start
=
(
offset
/
page_size
)
*
page_size
;
page_offset
=
offset
-
page_start
;
if
(
page_offset
!=
0
)
{
/* offset must be multiple of page size */
errno
=
EINVAL
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. Offset must be multiple of page size"
);
giterr_set
(
GITERR_OS
,
"Failed to mmap. Offset must be multiple of page size"
);
return
-
1
;
}
out
->
fmh
=
CreateFileMapping
(
fh
,
NULL
,
fmap_prot
,
0
,
0
,
NULL
);
if
(
!
out
->
fmh
||
out
->
fmh
==
INVALID_HANDLE_VALUE
)
{
/* errno = ? */
giterr_set
(
GITERR_OS
,
"Failed to mmap. Invalid handle value"
);
out
->
fmh
=
NULL
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. Invalid handle value"
)
;
return
-
1
;
}
assert
(
sizeof
(
git_off_t
)
==
8
);
off_low
=
(
DWORD
)(
page_start
);
off_hi
=
(
DWORD
)(
page_start
>>
32
);
out
->
data
=
MapViewOfFile
(
out
->
fmh
,
view_prot
,
off_hi
,
off_low
,
len
);
if
(
!
out
->
data
)
{
/* errno = ? */
giterr_set
(
GITERR_OS
,
"Failed to mmap. No data written"
);
CloseHandle
(
out
->
fmh
);
out
->
fmh
=
NULL
;
return
git__throw
(
GIT_ERROR
,
"Failed to mmap. No data written"
)
;
return
-
1
;
}
out
->
len
=
len
;
return
GIT_SUCCESS
;
return
0
;
}
int
p_munmap
(
git_map
*
map
)
{
assert
(
map
!=
NULL
)
;
int
error
=
0
;
if
(
!
map
)
return
git__throw
(
GIT_ERROR
,
"Failed to munmap. Map does not exist"
);
assert
(
map
!=
NULL
);
if
(
map
->
data
)
{
if
(
!
UnmapViewOfFile
(
map
->
data
))
{
/* errno = ? */
CloseHandle
(
map
->
fmh
);
map
->
data
=
NULL
;
map
->
fmh
=
NULL
;
return
git__throw
(
GIT_ERROR
,
"Failed to munmap. Could not unmap view of file"
);
giterr_set
(
GITERR_OS
,
"Failed to munmap. Could not unmap view of file"
);
error
=
-
1
;
}
map
->
data
=
NULL
;
}
if
(
map
->
fmh
)
{
if
(
!
CloseHandle
(
map
->
fmh
))
{
/* errno = ? */
map
->
fmh
=
NULL
;
return
git__throw
(
GIT_ERROR
,
"Failed to munmap. Could not close handle"
);
giterr_set
(
GITERR_OS
,
"Failed to munmap. Could not close handle"
);
error
=
-
1
;
}
map
->
fmh
=
NULL
;
}
return
GIT_SUCCESS
;
return
error
;
}
src/win32/posix_w32.c
View file @
e24fbba9
/
<
0
)
/
*
* Copyright (C) 2009-2012 the libgit2 contributors
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
...
...
@@ -17,10 +17,11 @@ int p_unlink(const char *path)
int
ret
=
0
;
wchar_t
*
buf
;
buf
=
gitwin_to_utf16
(
path
);
_wchmod
(
buf
,
0666
);
ret
=
_wunlink
(
buf
);
git__free
(
buf
);
if
((
buf
=
gitwin_to_utf16
(
path
))
!=
NULL
)
{
_wchmod
(
buf
,
0666
);
ret
=
_wunlink
(
buf
);
git__free
(
buf
);
}
return
ret
;
}
...
...
@@ -60,6 +61,8 @@ static int do_lstat(const char *file_name, struct stat *buf)
{
WIN32_FILE_ATTRIBUTE_DATA
fdata
;
wchar_t
*
fbuf
=
gitwin_to_utf16
(
file_name
);
if
(
!
fbuf
)
return
-
1
;
if
(
GetFileAttributesExW
(
fbuf
,
GetFileExInfoStandard
,
&
fdata
))
{
int
fMode
=
S_IREAD
;
...
...
@@ -87,54 +90,43 @@ static int do_lstat(const char *file_name, struct stat *buf)
buf
->
st_ctime
=
filetime_to_time_t
(
&
(
fdata
.
ftCreationTime
));
git__free
(
fbuf
);
return
GIT_SUCCESS
;
return
0
;
}
git__free
(
fbuf
);
switch
(
GetLastError
())
{
case
ERROR_ACCESS_DENIED
:
case
ERROR_SHARING_VIOLATION
:
case
ERROR_LOCK_VIOLATION
:
case
ERROR_SHARING_BUFFER_EXCEEDED
:
return
GIT_EOSERR
;
case
ERROR_BUFFER_OVERFLOW
:
case
ERROR_NOT_ENOUGH_MEMORY
:
return
GIT_ENOMEM
;
default
:
return
GIT_EINVALIDPATH
;
}
return
-
1
;
}
int
p_lstat
(
const
char
*
file_name
,
struct
stat
*
buf
)
{
int
namelen
,
error
;
char
alt_name
[
GIT_PATH_MAX
];
int
error
;
size_t
namelen
;
char
*
alt_name
;
if
(
(
error
=
do_lstat
(
file_name
,
buf
))
==
GIT_SUCCESS
)
return
GIT_SUCCESS
;
if
(
do_lstat
(
file_name
,
buf
)
==
0
)
return
0
;
/* if file_name ended in a '/', Windows returned ENOENT;
* try again without trailing slashes
*/
if
(
error
!=
GIT_EINVALIDPATH
)
return
git__throw
(
GIT_EOSERR
,
"Failed to lstat file"
);
namelen
=
strlen
(
file_name
);
if
(
namelen
&&
file_name
[
namelen
-
1
]
!=
'/'
)
return
git__throw
(
GIT_EOSERR
,
"Failed to lstat file"
)
;
return
-
1
;
while
(
namelen
&&
file_name
[
namelen
-
1
]
==
'/'
)
--
namelen
;
if
(
!
namelen
||
namelen
>=
GIT_PATH_MAX
)
return
git__throw
(
GIT_ENOMEM
,
"Failed to lstat file"
);
if
(
!
namelen
)
return
-
1
;
alt_name
=
git__strndup
(
file_name
,
namelen
);
if
(
!
alt_name
)
return
-
1
;
error
=
do_lstat
(
alt_name
,
buf
);
memcpy
(
alt_name
,
file_name
,
namelen
);
alt_name
[
namelen
]
=
0
;
return
do_lstat
(
alt_name
,
buf
);
git__free
(
alt_name
);
return
error
;
}
int
p_readlink
(
const
char
*
link
,
char
*
target
,
size_t
target_len
)
...
...
@@ -145,6 +137,9 @@ int p_readlink(const char *link, char *target, size_t target_len)
DWORD
dwRet
;
wchar_t
*
link_w
;
wchar_t
*
target_w
;
int
error
=
0
;
assert
(
link
&&
target
&&
target_len
>
0
);
/*
* Try to load the pointer to pGetFinalPath dynamically, because
...
...
@@ -156,12 +151,15 @@ int p_readlink(const char *link, char *target, size_t target_len)
if
(
library
!=
NULL
)
pGetFinalPath
=
(
fpath_func
)
GetProcAddress
(
library
,
"GetFinalPathNameByHandleW"
);
if
(
pGetFinalPath
==
NULL
)
return
git__throw
(
GIT_EOSERR
,
if
(
pGetFinalPath
==
NULL
)
{
giterr_set
(
GITERR_OS
,
"'GetFinalPathNameByHandleW' is not available in this platform"
);
return
-
1
;
}
}
link_w
=
gitwin_to_utf16
(
link
);
GITERR_CHECK_ALLOC
(
link_w
);
hFile
=
CreateFileW
(
link_w
,
// file to open
GENERIC_READ
,
// open for reading
...
...
@@ -173,50 +171,49 @@ int p_readlink(const char *link, char *target, size_t target_len)
git__free
(
link_w
);
if
(
hFile
==
INVALID_HANDLE_VALUE
)
return
GIT_EOSERR
;
if
(
target_len
<=
0
)
{
return
GIT_EINVALIDARGS
;
if
(
hFile
==
INVALID_HANDLE_VALUE
)
{
giterr_set
(
GITERR_OS
,
"Cannot open '%s' for reading"
,
link
);
return
-
1
;
}
target_w
=
(
wchar_t
*
)
git__malloc
(
target_len
*
sizeof
(
wchar_t
));
GITERR_CHECK_ALLOC
(
target_w
);
dwRet
=
pGetFinalPath
(
hFile
,
target_w
,
target_len
,
0x0
);
if
(
dwRet
>=
target_len
)
{
git__free
(
target_w
);
CloseHandle
(
hFile
);
return
GIT_ENOMEM
;
}
if
(
!
WideCharToMultiByte
(
CP_UTF8
,
0
,
target_w
,
-
1
,
target
,
target_len
*
sizeof
(
char
),
NULL
,
NULL
))
{
git__free
(
target_w
);
return
GIT_EOSERR
;
}
if
(
dwRet
==
0
||
dwRet
>=
target_len
||
!
WideCharToMultiByte
(
CP_UTF8
,
0
,
target_w
,
-
1
,
target
,
target_len
*
sizeof
(
char
),
NULL
,
NULL
))
error
=
-
1
;
git__free
(
target_w
);
CloseHandle
(
hFile
);
if
(
dwRet
>
4
)
{
/* Skip first 4 characters if they are "\\?\" */
if
(
target
[
0
]
==
'\\'
&&
target
[
1
]
==
'\\'
&&
target
[
2
]
==
'?'
&&
target
[
3
]
==
'\\'
)
{
char
tmp
[
GIT_PATH_MAX
];
unsigned
int
offset
=
4
;
dwRet
-=
4
;
/* \??\UNC\ */
if
(
dwRet
>
7
&&
target
[
4
]
==
'U'
&&
target
[
5
]
==
'N'
&&
target
[
6
]
==
'C'
)
{
offset
+=
2
;
dwRet
-=
2
;
target
[
offset
]
=
'\\'
;
}
memcpy
(
tmp
,
target
+
offset
,
dwRet
);
memcpy
(
target
,
tmp
,
dwRet
);
if
(
error
)
return
error
;
/* Skip first 4 characters if they are "\\?\" */
if
(
dwRet
>
4
&&
target
[
0
]
==
'\\'
&&
target
[
1
]
==
'\\'
&&
target
[
2
]
==
'?'
&&
target
[
3
]
==
'\\'
)
{
unsigned
int
offset
=
4
;
dwRet
-=
4
;
/* \??\UNC\ */
if
(
dwRet
>
7
&&
target
[
4
]
==
'U'
&&
target
[
5
]
==
'N'
&&
target
[
6
]
==
'C'
)
{
offset
+=
2
;
dwRet
-=
2
;
target
[
offset
]
=
'\\'
;
}
memmove
(
target
,
target
+
offset
,
dwRet
);
}
target
[
dwRet
]
=
'\0'
;
return
dwRet
;
}
...
...
@@ -224,8 +221,9 @@ int p_open(const char *path, int flags)
{
int
fd
;
wchar_t
*
buf
=
gitwin_to_utf16
(
path
);
if
(
!
buf
)
return
-
1
;
fd
=
_wopen
(
buf
,
flags
|
_O_BINARY
);
git__free
(
buf
);
return
fd
;
}
...
...
@@ -234,8 +232,9 @@ int p_creat(const char *path, mode_t mode)
{
int
fd
;
wchar_t
*
buf
=
gitwin_to_utf16
(
path
);
if
(
!
buf
)
return
-
1
;
fd
=
_wopen
(
buf
,
_O_WRONLY
|
_O_CREAT
|
_O_TRUNC
|
_O_BINARY
,
mode
);
git__free
(
buf
);
return
fd
;
}
...
...
@@ -243,15 +242,15 @@ int p_creat(const char *path, mode_t mode)
int
p_getcwd
(
char
*
buffer_out
,
size_t
size
)
{
wchar_t
*
buf
=
(
wchar_t
*
)
git__malloc
(
sizeof
(
wchar_t
)
*
(
int
)
size
);
int
ret
;
_wgetcwd
(
buf
,
(
int
)
size
);
if
(
!
WideCharToMultiByte
(
CP_UTF8
,
0
,
buf
,
-
1
,
buffer_out
,
size
,
NULL
,
NULL
))
{
git__free
(
buf
);
return
GIT_EOSERR
;
}
ret
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
buf
,
-
1
,
buffer_out
,
size
,
NULL
,
NULL
);
git__free
(
buf
);
return
GIT_SUCCESS
;
return
!
ret
?
-
1
:
0
;
}
int
p_stat
(
const
char
*
path
,
struct
stat
*
buf
)
...
...
@@ -262,8 +261,10 @@ int p_stat(const char* path, struct stat* buf)
int
p_chdir
(
const
char
*
path
)
{
wchar_t
*
buf
=
gitwin_to_utf16
(
path
);
int
ret
=
_wchdir
(
buf
);
int
ret
;
if
(
!
buf
)
return
-
1
;
ret
=
_wchdir
(
buf
);
git__free
(
buf
);
return
ret
;
}
...
...
@@ -271,8 +272,10 @@ int p_chdir(const char* path)
int
p_chmod
(
const
char
*
path
,
mode_t
mode
)
{
wchar_t
*
buf
=
gitwin_to_utf16
(
path
);
int
ret
=
_wchmod
(
buf
,
mode
);
int
ret
;
if
(
!
buf
)
return
-
1
;
ret
=
_wchmod
(
buf
,
mode
);
git__free
(
buf
);
return
ret
;
}
...
...
@@ -280,8 +283,10 @@ int p_chmod(const char* path, mode_t mode)
int
p_rmdir
(
const
char
*
path
)
{
wchar_t
*
buf
=
gitwin_to_utf16
(
path
);
int
ret
=
_wrmdir
(
buf
);
int
ret
;
if
(
!
buf
)
return
-
1
;
ret
=
_wrmdir
(
buf
);
git__free
(
buf
);
return
ret
;
}
...
...
@@ -290,11 +295,13 @@ int p_hide_directory__w32(const char *path)
{
int
res
;
wchar_t
*
buf
=
gitwin_to_utf16
(
path
);
if
(
!
buf
)
return
-
1
;
res
=
SetFileAttributesW
(
buf
,
FILE_ATTRIBUTE_HIDDEN
);
git__free
(
buf
);
return
(
res
!=
0
)
?
GIT_SUCCESS
:
GIT_ERROR
;
/* MSDN states a "non zero" value indicates a success */
return
(
res
!=
0
)
?
0
:
-
1
;
/* MSDN states a "non zero" value indicates a success */
}
char
*
p_realpath
(
const
char
*
orig_path
,
char
*
buffer
)
...
...
@@ -303,6 +310,9 @@ char *p_realpath(const char *orig_path, char *buffer)
wchar_t
*
orig_path_w
=
gitwin_to_utf16
(
orig_path
);
wchar_t
*
buffer_w
=
(
wchar_t
*
)
git__malloc
(
GIT_PATH_MAX
*
sizeof
(
wchar_t
));
if
(
!
orig_path_w
||
!
buffer_w
)
return
NULL
;
ret
=
GetFullPathNameW
(
orig_path_w
,
GIT_PATH_MAX
,
buffer_w
,
NULL
);
git__free
(
orig_path_w
);
...
...
@@ -339,7 +349,7 @@ int p_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
int
len
;
if
(
count
==
0
||
(
len
=
_vsnprintf
(
buffer
,
count
,
format
,
argptr
))
<
0
)
return
p
_vscprintf
(
format
,
argptr
);
return
_vscprintf
(
format
,
argptr
);
return
len
;
#else
/* MinGW */
...
...
@@ -365,10 +375,10 @@ int p_mkstemp(char *tmp_path)
{
#if defined(_MSC_VER)
if
(
_mktemp_s
(
tmp_path
,
strlen
(
tmp_path
)
+
1
)
!=
0
)
return
GIT_EOSERR
;
return
-
1
;
#else
if
(
_mktemp
(
tmp_path
)
==
NULL
)
return
GIT_EOSERR
;
return
-
1
;
#endif
return
p_creat
(
tmp_path
,
0744
);
...
...
@@ -377,15 +387,17 @@ int p_mkstemp(char *tmp_path)
int
p_setenv
(
const
char
*
name
,
const
char
*
value
,
int
overwrite
)
{
if
(
overwrite
!=
1
)
return
EINVAL
;
return
-
1
;
return
(
SetEnvironmentVariableA
(
name
,
value
)
==
0
?
GIT_EOSERR
:
GIT_SUCCESS
);
return
(
SetEnvironmentVariableA
(
name
,
value
)
==
0
?
-
1
:
0
);
}
int
p_access
(
const
char
*
path
,
mode_t
mode
)
{
wchar_t
*
buf
=
gitwin_to_utf16
(
path
);
int
ret
;
if
(
!
buf
)
return
-
1
;
ret
=
_waccess
(
buf
,
mode
);
git__free
(
buf
);
...
...
@@ -393,13 +405,16 @@ int p_access(const char* path, mode_t mode)
return
ret
;
}
extern
int
p_rename
(
const
char
*
from
,
const
char
*
to
)
int
p_rename
(
const
char
*
from
,
const
char
*
to
)
{
wchar_t
*
wfrom
=
gitwin_to_utf16
(
from
);
wchar_t
*
wto
=
gitwin_to_utf16
(
to
);
int
ret
;
ret
=
MoveFileExW
(
wfrom
,
wto
,
MOVEFILE_REPLACE_EXISTING
|
MOVEFILE_COPY_ALLOWED
)
?
GIT_SUCCESS
:
GIT_EOSERR
;
if
(
!
wfrom
||
!
wto
)
return
-
1
;
ret
=
MoveFileExW
(
wfrom
,
wto
,
MOVEFILE_REPLACE_EXISTING
|
MOVEFILE_COPY_ALLOWED
)
?
0
:
-
1
;
git__free
(
wfrom
);
git__free
(
wto
);
...
...
src/win32/pthread.c
View file @
e24fbba9
...
...
@@ -7,13 +7,16 @@
#include "pthread.h"
int
pthread_create
(
pthread_t
*
GIT_RESTRICT
thread
,
const
pthread_attr_t
*
GIT_RESTRICT
attr
,
void
*
(
*
start_routine
)(
void
*
),
void
*
GIT_RESTRICT
arg
)
int
pthread_create
(
pthread_t
*
GIT_RESTRICT
thread
,
const
pthread_attr_t
*
GIT_RESTRICT
attr
,
void
*
(
*
start_routine
)(
void
*
),
void
*
GIT_RESTRICT
arg
)
{
GIT_UNUSED
(
attr
);
*
thread
=
(
pthread_t
)
CreateThread
(
NULL
,
0
,
(
LPTHREAD_START_ROUTINE
)
start_routine
,
arg
,
0
,
NULL
);
return
*
thread
?
GIT_SUCCESS
:
git__throw
(
GIT_EOSERR
,
"Failed to create pthread"
);
*
thread
=
(
pthread_t
)
CreateThread
(
NULL
,
0
,
(
LPTHREAD_START_ROUTINE
)
start_routine
,
arg
,
0
,
NULL
);
return
*
thread
?
0
:
-
1
;
}
int
pthread_join
(
pthread_t
thread
,
void
**
value_ptr
)
...
...
src/win32/utf-conv.c
View file @
e24fbba9
...
...
@@ -33,14 +33,14 @@ wchar_t* gitwin_to_utf16(const char* str)
wchar_t
*
ret
;
int
cb
;
if
(
!
str
)
{
if
(
!
str
)
return
NULL
;
}
cb
=
strlen
(
str
)
*
sizeof
(
wchar_t
);
if
(
cb
==
0
)
{
ret
=
(
wchar_t
*
)
git__malloc
(
sizeof
(
wchar_t
));
ret
[
0
]
=
0
;
if
(
ret
)
ret
[
0
]
=
0
;
return
ret
;
}
...
...
@@ -48,8 +48,11 @@ wchar_t* gitwin_to_utf16(const char* str)
cb
+=
sizeof
(
wchar_t
);
ret
=
(
wchar_t
*
)
git__malloc
(
cb
);
if
(
!
ret
)
return
NULL
;
if
(
MultiByteToWideChar
(
_active_codepage
,
0
,
str
,
-
1
,
ret
,
cb
)
==
0
)
{
giterr_set
(
GITERR_OS
,
"Could not convert string to UTF-16"
);
git__free
(
ret
);
ret
=
NULL
;
}
...
...
@@ -59,7 +62,10 @@ wchar_t* gitwin_to_utf16(const char* str)
int
gitwin_append_utf16
(
wchar_t
*
buffer
,
const
char
*
str
,
size_t
len
)
{
return
MultiByteToWideChar
(
_active_codepage
,
0
,
str
,
-
1
,
buffer
,
len
);
int
result
=
MultiByteToWideChar
(
_active_codepage
,
0
,
str
,
-
1
,
buffer
,
len
);
if
(
result
==
0
)
giterr_set
(
GITERR_OS
,
"Could not convert string to UTF-16"
);
return
result
;
}
char
*
gitwin_from_utf16
(
const
wchar_t
*
str
)
...
...
@@ -74,7 +80,8 @@ char* gitwin_from_utf16(const wchar_t* str)
cb
=
wcslen
(
str
)
*
sizeof
(
char
);
if
(
cb
==
0
)
{
ret
=
(
char
*
)
git__malloc
(
sizeof
(
char
));
ret
[
0
]
=
0
;
if
(
ret
)
ret
[
0
]
=
0
;
return
ret
;
}
...
...
@@ -82,8 +89,11 @@ char* gitwin_from_utf16(const wchar_t* str)
cb
+=
sizeof
(
char
);
ret
=
(
char
*
)
git__malloc
(
cb
);
if
(
!
ret
)
return
NULL
;
if
(
WideCharToMultiByte
(
_active_codepage
,
0
,
str
,
-
1
,
ret
,
cb
,
NULL
,
NULL
)
==
0
)
{
giterr_set
(
GITERR_OS
,
"Could not convert string to UTF-8"
);
git__free
(
ret
);
ret
=
NULL
;
}
...
...
tests-clar/attr/attr_expect.h
View file @
e24fbba9
...
...
@@ -15,7 +15,7 @@ struct attr_expected {
const
char
*
expected_str
;
};
static
inline
void
attr_check_expected
(
GIT_INLINE
(
void
)
attr_check_expected
(
enum
attr_expect_t
expected
,
const
char
*
expected_str
,
const
char
*
value
)
...
...
tests-clar/core/errors.c
0 → 100644
View file @
e24fbba9
#include "clar_libgit2.h"
#include "common.h"
#include "util.h"
#include "posix.h"
#ifdef git__throw
void
test_core_errors__old_school
(
void
)
{
git_clearerror
();
cl_assert
(
git_lasterror
()
==
NULL
);
cl_assert
(
git_strerror
(
GIT_ENOTFOUND
)
!=
NULL
);
git__throw
(
GIT_ENOTFOUND
,
"My Message"
);
cl_assert
(
git_lasterror
()
!=
NULL
);
cl_assert
(
git__prefixcmp
(
git_lasterror
(),
"My Message"
)
==
0
);
git_clearerror
();
}
#endif
#ifdef GITERR_CHECK_ALLOC
void
test_core_errors__new_school
(
void
)
{
char
*
str_in_error
;
git_error_clear
();
cl_assert
(
git_error_last
()
==
NULL
);
giterr_set_oom
();
/* internal fn */
cl_assert
(
git_error_last
()
!=
NULL
);
cl_assert
(
git_error_last
()
->
klass
==
GITERR_NOMEMORY
);
str_in_error
=
strstr
(
git_error_last
()
->
message
,
"memory"
);
cl_assert
(
str_in_error
!=
NULL
);
git_error_clear
();
giterr_set
(
GITERR_REPOSITORY
,
"This is a test"
);
/* internal fn */
cl_assert
(
git_error_last
()
!=
NULL
);
str_in_error
=
strstr
(
git_error_last
()
->
message
,
"This is a test"
);
cl_assert
(
str_in_error
!=
NULL
);
git_error_clear
();
{
struct
stat
st
;
assert
(
p_lstat
(
"this_file_does_not_exist"
,
&
st
)
<
0
);
}
giterr_set
(
GITERR_OS
,
"stat failed"
);
/* internal fn */
cl_assert
(
git_error_last
()
!=
NULL
);
str_in_error
=
strstr
(
git_error_last
()
->
message
,
"stat failed"
);
cl_assert
(
str_in_error
!=
NULL
);
cl_assert
(
git__prefixcmp
(
str_in_error
,
"stat failed: "
)
==
0
);
cl_assert
(
strlen
(
str_in_error
)
>
strlen
(
"stat failed: "
));
#ifdef GIT_WIN32
git_error_clear
();
/* The MSDN docs use this to generate a sample error */
cl_assert
(
GetProcessId
(
NULL
)
==
0
);
giterr_set
(
GITERR_OS
,
"GetProcessId failed"
);
/* internal fn */
cl_assert
(
git_error_last
()
!=
NULL
);
str_in_error
=
strstr
(
git_error_last
()
->
message
,
"GetProcessId failed"
);
cl_assert
(
str_in_error
!=
NULL
);
cl_assert
(
git__prefixcmp
(
str_in_error
,
"GetProcessId failed: "
)
==
0
);
cl_assert
(
strlen
(
str_in_error
)
>
strlen
(
"GetProcessId failed: "
));
#endif
git_error_clear
();
}
#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