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
e8bc8558
Unverified
Commit
e8bc8558
authored
Jan 02, 2018
by
Brian Lopez
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master' into charliesome/trailer-info
parents
72fbf05c
7610638e
Show whitespace changes
Inline
Side-by-side
Showing
44 changed files
with
1387 additions
and
416 deletions
+1387
-416
CMakeLists.txt
+6
-2
git.git-authors
+1
-0
include/git2/notes.h
+89
-0
src/CMakeLists.txt
+1
-1
src/checkout.c
+3
-0
src/diff_file.c
+3
-1
src/fetchhead.c
+1
-1
src/fileops.c
+10
-0
src/fileops.h
+5
-0
src/hash/hash_common_crypto.h
+15
-2
src/hash/hash_win32.c
+22
-4
src/indexer.c
+11
-1
src/iterator.c
+36
-1
src/iterator.h
+2
-0
src/notes.c
+164
-48
src/object.c
+11
-2
src/object.h
+2
-0
src/odb_loose.c
+94
-95
src/pack-objects.c
+5
-1
src/pack.c
+10
-7
src/patch_parse.c
+42
-8
src/push.c
+2
-169
src/refdb_fs.c
+1
-0
src/remote.c
+17
-0
src/streams/openssl.c
+17
-12
src/streams/stransport.c
+3
-1
src/transports/local.c
+18
-5
src/transports/winhttp.c
+13
-4
src/util.c
+28
-16
src/util.h
+1
-0
src/zstream.c
+15
-9
tests/core/string.c
+42
-0
tests/diff/blob.c
+39
-0
tests/fetchhead/nonetwork.c
+80
-8
tests/merge/workdir/submodules.c
+36
-0
tests/notes/notes.c
+274
-0
tests/odb/largefiles.c
+114
-0
tests/pack/indexer.c
+68
-0
tests/patch/parse.c
+6
-0
tests/patch/patch_common.h
+10
-0
tests/refs/iterator.c
+66
-18
tests/resources/merge-resolve/.gitted/objects/50/c5dc8cdfe40c688eb0a0e23be54dd57cae2e78
+3
-0
tests/resources/merge-resolve/.gitted/objects/7a/a825857f87aea74ddf13d954568aa30dfcdeb4
+0
-0
tests/resources/merge-resolve/.gitted/refs/heads/delete-submodule
+1
-0
No files found.
CMakeLists.txt
View file @
e8bc8558
...
...
@@ -43,7 +43,6 @@ OPTION( ENABLE_TRACE "Enables tracing support" OFF )
OPTION
(
LIBGIT2_FILENAME
"Name of the produced binary"
OFF
)
OPTION
(
USE_SHA1DC
"Use SHA-1 with collision detection"
OFF
)
OPTION
(
USE_ICONV
"Link with and use iconv library"
OFF
)
OPTION
(
USE_SSH
"Link with libssh to enable SSH support"
ON
)
OPTION
(
USE_HTTPS
"Enable HTTPS support. Can be set to a specific backend"
ON
)
OPTION
(
USE_GSSAPI
"Link with libgssapi for SPNEGO auth"
OFF
)
...
...
@@ -52,10 +51,15 @@ OPTION( CURL "Use curl for HTTP if available" ON)
OPTION
(
USE_EXT_HTTP_PARSER
"Use system HTTP_Parser if available"
ON
)
OPTION
(
DEBUG_POOL
"Enable debug pool allocator"
OFF
)
OPTION
(
ENABLE_WERROR
"Enable compilation with -Werror"
OFF
)
OPTION
(
USE_BUNDLED_ZLIB
"Use the bundled version of zlib"
OFF
)
IF
(
UNIX AND NOT APPLE
)
OPTION
(
ENABLE_REPRODUCIBLE_BUILDS
"Enable reproducible builds"
OFF
)
ENDIF
()
OPTION
(
USE_BUNDLED_ZLIB
"Use the bundled version of zlib"
OFF
)
IF
(
APPLE
)
OPTION
(
USE_ICONV
"Link with and use iconv library"
ON
)
ENDIF
()
IF
(
MSVC
)
# This option is only available when building with MSVC. By default, libgit2
...
...
git.git-authors
View file @
e8bc8558
...
...
@@ -53,6 +53,7 @@ ok Jeff King <peff@peff.net>
ok Johannes Schindelin <Johannes.Schindelin@gmx.de>
ok Johannes Sixt <j6t@kdbg.org>
ask Jonathan Nieder <jrnieder@gmail.com>
ok Jonathan Tan <jonathantanmy@google.com>
ok Junio C Hamano <gitster@pobox.com>
ok Kristian Høgsberg <krh@redhat.com>
ok Linus Torvalds <torvalds@linux-foundation.org>
...
...
include/git2/notes.h
View file @
e8bc8558
...
...
@@ -52,6 +52,20 @@ GIT_EXTERN(int) git_note_iterator_new(
const
char
*
notes_ref
);
/**
* Creates a new iterator for notes from a commit
*
* The iterator must be freed manually by the user.
*
* @param out pointer to the iterator
* @param notes_commit a pointer to the notes commit object
*
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_note_commit_iterator_new
(
git_note_iterator
**
out
,
git_commit
*
notes_commit
);
/**
* Frees an git_note_iterator
*
* @param it pointer to the iterator
...
...
@@ -94,6 +108,25 @@ GIT_EXTERN(int) git_note_read(
const
char
*
notes_ref
,
const
git_oid
*
oid
);
/**
* Read the note for an object from a note commit
*
* The note must be freed manually by the user.
*
* @param out pointer to the read note; NULL in case of error
* @param repo repository where to look up the note
* @param notes_commit a pointer to the notes commit object
* @param oid OID of the git object to read the note from
*
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_note_commit_read
(
git_note
**
out
,
git_repository
*
repo
,
git_commit
*
notes_commit
,
const
git_oid
*
oid
);
/**
* Get the note author
*
...
...
@@ -153,6 +186,36 @@ GIT_EXTERN(int) git_note_create(
const
char
*
note
,
int
force
);
/**
* Add a note for an object from a commit
*
* This function will create a notes commit for a given object,
* the commit is a dangling commit, no reference is created.
*
* @param notes_commit_out pointer to store the commit (optional);
* NULL in case of error
* @param notes_blob_out a point to the id of a note blob (optional)
* @param repo repository where the note will live
* @param parent Pointer to parent note
* or NULL if this shall start a new notes tree
* @param author signature of the notes commit author
* @param committer signature of the notes commit committer
* @param oid OID of the git object to decorate
* @param note Content of the note to add for object oid
* @param allow_note_overwrite Overwrite existing note
*
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_note_commit_create
(
git_oid
*
notes_commit_out
,
git_oid
*
notes_blob_out
,
git_repository
*
repo
,
git_commit
*
parent
,
const
git_signature
*
author
,
const
git_signature
*
committer
,
const
git_oid
*
oid
,
const
char
*
note
,
int
allow_note_overwrite
);
/**
* Remove the note for an object
...
...
@@ -174,6 +237,32 @@ GIT_EXTERN(int) git_note_remove(
const
git_oid
*
oid
);
/**
* Remove the note for an object
*
* @param notes_commit_out pointer to store the new notes commit (optional);
* NULL in case of error.
* When removing a note a new tree containing all notes
* sans the note to be removed is created and a new commit
* pointing to that tree is also created.
* In the case where the resulting tree is an empty tree
* a new commit pointing to this empty tree will be returned.
* @param repo repository where the note lives
* @param notes_commit a pointer to the notes commit object
* @param author signature of the notes commit author
* @param committer signature of the notes commit committer
* @param oid OID of the git object to remove the note from
*
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_note_commit_remove
(
git_oid
*
notes_commit_out
,
git_repository
*
repo
,
git_commit
*
notes_commit
,
const
git_signature
*
author
,
const
git_signature
*
committer
,
const
git_oid
*
oid
);
/**
* Free a git_note object
*
* @param note git_note object
...
...
src/CMakeLists.txt
View file @
e8bc8558
...
...
@@ -310,7 +310,7 @@ ENDIF()
ADD_FEATURE_INFO(SPNEGO GIT_GSSAPI "
SPNEGO authentication support
")
# Optional external dependency: iconv
IF (USE_ICONV
OR CMAKE_SYSTEM_NAME MATCHES "
Darwin
"
)
IF (USE_ICONV)
FIND_PACKAGE(Iconv)
ENDIF()
IF (ICONV_FOUND)
...
...
src/checkout.c
View file @
e8bc8558
...
...
@@ -2022,8 +2022,11 @@ static int checkout_write_entry(
(
error
=
checkout_safe_for_update_only
(
data
,
fullpath
->
ptr
,
side
->
mode
))
<=
0
)
return
error
;
if
(
!
S_ISGITLINK
(
side
->
mode
))
return
checkout_write_content
(
data
,
&
side
->
id
,
fullpath
->
ptr
,
hint_path
,
side
->
mode
,
&
st
);
return
0
;
}
static
int
checkout_write_entries
(
...
...
src/diff_file.c
View file @
e8bc8558
...
...
@@ -139,7 +139,6 @@ int git_diff_file_content__init_from_src(
memset
(
fc
,
0
,
sizeof
(
*
fc
));
fc
->
repo
=
repo
;
fc
->
file
=
as_file
;
fc
->
blob
=
src
->
blob
;
if
(
!
src
->
blob
&&
!
src
->
buf
)
{
fc
->
flags
|=
GIT_DIFF_FLAG__NO_DATA
;
...
...
@@ -149,12 +148,15 @@ int git_diff_file_content__init_from_src(
fc
->
file
->
mode
=
GIT_FILEMODE_BLOB
;
if
(
src
->
blob
)
{
git_blob_dup
((
git_blob
**
)
&
fc
->
blob
,
(
git_blob
*
)
src
->
blob
);
fc
->
file
->
size
=
git_blob_rawsize
(
src
->
blob
);
git_oid_cpy
(
&
fc
->
file
->
id
,
git_blob_id
(
src
->
blob
));
fc
->
file
->
id_abbrev
=
GIT_OID_HEXSZ
;
fc
->
map
.
len
=
(
size_t
)
fc
->
file
->
size
;
fc
->
map
.
data
=
(
char
*
)
git_blob_rawcontent
(
src
->
blob
);
fc
->
flags
|=
GIT_DIFF_FLAG__FREE_BLOB
;
}
else
{
fc
->
file
->
size
=
src
->
buflen
;
git_odb_hash
(
&
fc
->
file
->
id
,
src
->
buf
,
src
->
buflen
,
GIT_OBJ_BLOB
);
...
...
src/fetchhead.c
View file @
e8bc8558
...
...
@@ -118,7 +118,7 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs)
if
(
git_buf_joinpath
(
&
path
,
repo
->
gitdir
,
GIT_FETCH_HEAD_FILE
)
<
0
)
return
-
1
;
if
(
git_filebuf_open
(
&
file
,
path
.
ptr
,
GIT_FILEBUF_
FORCE
,
GIT_REFS_FILE_MODE
)
<
0
)
{
if
(
git_filebuf_open
(
&
file
,
path
.
ptr
,
GIT_FILEBUF_
APPEND
,
GIT_REFS_FILE_MODE
)
<
0
)
{
git_buf_free
(
&
path
);
return
-
1
;
}
...
...
src/fileops.c
View file @
e8bc8558
...
...
@@ -102,6 +102,16 @@ int git_futils_open_ro(const char *path)
return
fd
;
}
int
git_futils_truncate
(
const
char
*
path
,
int
mode
)
{
int
fd
=
p_open
(
path
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
|
O_CLOEXEC
,
mode
);
if
(
fd
<
0
)
return
git_path_set_error
(
errno
,
path
,
"open"
);
close
(
fd
);
return
0
;
}
git_off_t
git_futils_filesize
(
git_file
fd
)
{
struct
stat
sb
;
...
...
src/fileops.h
View file @
e8bc8558
...
...
@@ -248,6 +248,11 @@ extern int git_futils_cp_r(
extern
int
git_futils_open_ro
(
const
char
*
path
);
/**
* Truncate a file, creating it if it doesn't exist.
*/
extern
int
git_futils_truncate
(
const
char
*
path
,
int
mode
);
/**
* Get the filesize in bytes of a file
*/
extern
git_off_t
git_futils_filesize
(
git_file
fd
);
...
...
src/hash/hash_common_crypto.h
View file @
e8bc8558
...
...
@@ -16,6 +16,8 @@ struct git_hash_ctx {
CC_SHA1_CTX
c
;
};
#define CC_LONG_MAX ((CC_LONG)-1)
#define git_hash_global_init() 0
#define git_hash_ctx_init(ctx) git_hash_init(ctx)
#define git_hash_ctx_cleanup(ctx)
...
...
@@ -27,10 +29,21 @@ GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx)
return
0
;
}
GIT_INLINE
(
int
)
git_hash_update
(
git_hash_ctx
*
ctx
,
const
void
*
data
,
size_t
len
)
GIT_INLINE
(
int
)
git_hash_update
(
git_hash_ctx
*
ctx
,
const
void
*
_
data
,
size_t
len
)
{
const
unsigned
char
*
data
=
_data
;
assert
(
ctx
);
CC_SHA1_Update
(
&
ctx
->
c
,
data
,
len
);
while
(
len
>
0
)
{
CC_LONG
chunk
=
(
len
>
CC_LONG_MAX
)
?
CC_LONG_MAX
:
(
CC_LONG
)
len
;
CC_SHA1_Update
(
&
ctx
->
c
,
data
,
chunk
);
data
+=
chunk
;
len
-=
chunk
;
}
return
0
;
}
...
...
src/hash/hash_win32.c
View file @
e8bc8558
...
...
@@ -136,13 +136,22 @@ GIT_INLINE(int) hash_cryptoapi_init(git_hash_ctx *ctx)
return
0
;
}
GIT_INLINE
(
int
)
hash_cryptoapi_update
(
git_hash_ctx
*
ctx
,
const
void
*
data
,
size_t
len
)
GIT_INLINE
(
int
)
hash_cryptoapi_update
(
git_hash_ctx
*
ctx
,
const
void
*
_
data
,
size_t
len
)
{
const
BYTE
*
data
=
(
BYTE
*
)
_data
;
assert
(
ctx
->
ctx
.
cryptoapi
.
valid
);
if
(
!
CryptHashData
(
ctx
->
ctx
.
cryptoapi
.
hash_handle
,
(
const
BYTE
*
)
data
,
(
DWORD
)
len
,
0
))
while
(
len
>
0
)
{
DWORD
chunk
=
(
len
>
MAXDWORD
)
?
MAXDWORD
:
(
DWORD
)
len
;
if
(
!
CryptHashData
(
ctx
->
ctx
.
cryptoapi
.
hash_handle
,
data
,
chunk
,
0
))
return
-
1
;
data
+=
chunk
;
len
-=
chunk
;
}
return
0
;
}
...
...
@@ -202,11 +211,20 @@ GIT_INLINE(int) hash_cng_init(git_hash_ctx *ctx)
return
0
;
}
GIT_INLINE
(
int
)
hash_cng_update
(
git_hash_ctx
*
ctx
,
const
void
*
data
,
size_t
len
)
GIT_INLINE
(
int
)
hash_cng_update
(
git_hash_ctx
*
ctx
,
const
void
*
_
data
,
size_t
len
)
{
if
(
ctx
->
prov
->
prov
.
cng
.
hash_data
(
ctx
->
ctx
.
cng
.
hash_handle
,
(
PBYTE
)
data
,
(
ULONG
)
len
,
0
)
<
0
)
PBYTE
data
=
(
PBYTE
)
_data
;
while
(
len
>
0
)
{
ULONG
chunk
=
(
len
>
ULONG_MAX
)
?
ULONG_MAX
:
(
ULONG
)
len
;
if
(
ctx
->
prov
->
prov
.
cng
.
hash_data
(
ctx
->
ctx
.
cng
.
hash_handle
,
data
,
chunk
,
0
)
<
0
)
return
-
1
;
data
+=
chunk
;
len
-=
chunk
;
}
return
0
;
}
...
...
src/indexer.c
View file @
e8bc8558
...
...
@@ -844,6 +844,7 @@ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats)
static
int
resolve_deltas
(
git_indexer
*
idx
,
git_transfer_progress
*
stats
)
{
unsigned
int
i
;
int
error
;
struct
delta_info
*
delta
;
int
progressed
=
0
,
non_null
=
0
,
progress_cb_result
;
...
...
@@ -858,8 +859,13 @@ static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats)
non_null
=
1
;
idx
->
off
=
delta
->
delta_off
;
if
(
git_packfile_unpack
(
&
obj
,
idx
->
pack
,
&
idx
->
off
)
<
0
)
if
((
error
=
git_packfile_unpack
(
&
obj
,
idx
->
pack
,
&
idx
->
off
))
<
0
)
{
if
(
error
==
GIT_PASSTHROUGH
)
{
/* We have not seen the base object, we'll try again later. */
continue
;
}
return
-
1
;
}
if
(
hash_and_save
(
idx
,
&
obj
,
delta
->
delta_off
)
<
0
)
continue
;
...
...
@@ -951,6 +957,10 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
giterr_set
(
GITERR_INDEXER
,
"unexpected data at the end of the pack"
);
return
-
1
;
}
if
(
idx
->
off
+
20
>
idx
->
pack
->
mwf
.
size
)
{
giterr_set
(
GITERR_INDEXER
,
"missing trailer at the end of the pack"
);
return
-
1
;
}
packfile_trailer
=
git_mwindow_open
(
&
idx
->
pack
->
mwf
,
&
w
,
idx
->
pack
->
mwf
.
size
-
GIT_OID_RAWSZ
,
GIT_OID_RAWSZ
,
&
left
);
if
(
packfile_trailer
==
NULL
)
{
...
...
src/iterator.c
View file @
e8bc8558
...
...
@@ -23,6 +23,7 @@
#define iterator__has_been_accessed(I) iterator__flag(I,FIRST_ACCESS)
#define iterator__honor_ignores(I) iterator__flag(I,HONOR_IGNORES)
#define iterator__ignore_dot_git(I) iterator__flag(I,IGNORE_DOT_GIT)
#define iterator__descend_symlinks(I) iterator__flag(I,DESCEND_SYMLINKS)
static
void
iterator_set_ignore_case
(
git_iterator
*
iter
,
bool
ignore_case
)
...
...
@@ -1491,10 +1492,41 @@ static int filesystem_iterator_current(
return
0
;
}
static
int
filesystem_iterator_is_dir
(
bool
*
is_dir
,
const
filesystem_iterator
*
iter
,
const
filesystem_iterator_entry
*
entry
)
{
struct
stat
st
;
git_buf
fullpath
=
GIT_BUF_INIT
;
int
error
=
0
;
if
(
S_ISDIR
(
entry
->
st
.
st_mode
))
{
*
is_dir
=
1
;
goto
done
;
}
if
(
!
iterator__descend_symlinks
(
iter
)
||
!
S_ISLNK
(
entry
->
st
.
st_mode
))
{
*
is_dir
=
0
;
goto
done
;
}
if
((
error
=
git_buf_joinpath
(
&
fullpath
,
iter
->
root
,
entry
->
path
))
<
0
||
(
error
=
p_stat
(
fullpath
.
ptr
,
&
st
))
<
0
)
goto
done
;
*
is_dir
=
S_ISDIR
(
st
.
st_mode
);
done
:
git_buf_free
(
&
fullpath
);
return
error
;
}
static
int
filesystem_iterator_advance
(
const
git_index_entry
**
out
,
git_iterator
*
i
)
{
filesystem_iterator
*
iter
=
(
filesystem_iterator
*
)
i
;
bool
is_dir
;
int
error
=
0
;
iter
->
base
.
flags
|=
GIT_ITERATOR_FIRST_ACCESS
;
...
...
@@ -1519,7 +1551,10 @@ static int filesystem_iterator_advance(
entry
=
frame
->
entries
.
contents
[
frame
->
next_idx
];
frame
->
next_idx
++
;
if
(
S_ISDIR
(
entry
->
st
.
st_mode
))
{
if
((
error
=
filesystem_iterator_is_dir
(
&
is_dir
,
iter
,
entry
))
<
0
)
break
;
if
(
is_dir
)
{
if
(
iterator__do_autoexpand
(
iter
))
{
error
=
filesystem_iterator_frame_push
(
iter
,
entry
);
...
...
src/iterator.h
View file @
e8bc8558
...
...
@@ -39,6 +39,8 @@ typedef enum {
GIT_ITERATOR_DONT_PRECOMPOSE_UNICODE
=
(
1u
<<
5
),
/** include conflicts */
GIT_ITERATOR_INCLUDE_CONFLICTS
=
(
1u
<<
6
),
/** descend into symlinked directories */
GIT_ITERATOR_DESCEND_SYMLINKS
=
(
1u
<<
7
),
}
git_iterator_flag_t
;
typedef
enum
{
...
...
src/notes.c
View file @
e8bc8558
...
...
@@ -268,7 +268,9 @@ static int insert_note_in_tree_enotfound_cb(git_tree **out,
GIT_FILEMODE_BLOB
);
}
static
int
note_write
(
git_oid
*
out
,
static
int
note_write
(
git_oid
*
notes_commit_out
,
git_oid
*
notes_blob_out
,
git_repository
*
repo
,
const
git_signature
*
author
,
const
git_signature
*
committer
,
...
...
@@ -294,13 +296,17 @@ static int note_write(git_oid *out,
insert_note_in_tree_enotfound_cb
))
<
0
)
goto
cleanup
;
if
(
out
)
git_oid_cpy
(
out
,
&
oid
);
if
(
notes_blob_out
)
git_oid_cpy
(
notes_blob_out
,
&
oid
);
error
=
git_commit_create
(
&
oid
,
repo
,
notes_ref
,
author
,
committer
,
NULL
,
GIT_NOTES_DEFAULT_MSG_ADD
,
tree
,
*
parents
==
NULL
?
0
:
1
,
(
const
git_commit
**
)
parents
);
if
(
notes_commit_out
)
git_oid_cpy
(
notes_commit_out
,
&
oid
);
cleanup:
git_tree_free
(
tree
);
return
error
;
...
...
@@ -363,7 +369,9 @@ cleanup:
return
error
;
}
static
int
note_remove
(
git_repository
*
repo
,
static
int
note_remove
(
git_oid
*
notes_commit_out
,
git_repository
*
repo
,
const
git_signature
*
author
,
const
git_signature
*
committer
,
const
char
*
notes_ref
,
git_tree
*
tree
,
const
char
*
target
,
git_commit
**
parents
)
...
...
@@ -383,6 +391,12 @@ static int note_remove(git_repository *repo,
*
parents
==
NULL
?
0
:
1
,
(
const
git_commit
**
)
parents
);
if
(
error
<
0
)
goto
cleanup
;
if
(
notes_commit_out
)
git_oid_cpy
(
notes_commit_out
,
&
oid
);
cleanup:
git_tree_free
(
tree_after_removal
);
return
error
;
...
...
@@ -410,8 +424,7 @@ static int normalize_namespace(char **out, git_repository *repo, const char *not
return
note_get_default_ref
(
out
,
repo
);
}
static
int
retrieve_note_tree_and_commit
(
git_tree
**
tree_out
,
static
int
retrieve_note_commit
(
git_commit
**
commit_out
,
char
**
notes_ref_out
,
git_repository
*
repo
,
...
...
@@ -429,34 +442,82 @@ static int retrieve_note_tree_and_commit(
if
(
git_commit_lookup
(
commit_out
,
repo
,
&
oid
)
<
0
)
return
error
;
if
((
error
=
git_commit_tree
(
tree_out
,
*
commit_out
))
<
0
)
return
error
;
return
0
;
}
int
git_note_commit_read
(
git_note
**
out
,
git_repository
*
repo
,
git_commit
*
notes_commit
,
const
git_oid
*
oid
)
{
int
error
;
git_tree
*
tree
=
NULL
;
char
target
[
GIT_OID_HEXSZ
+
1
];
git_oid_tostr
(
target
,
sizeof
(
target
),
oid
);
if
((
error
=
git_commit_tree
(
&
tree
,
notes_commit
))
<
0
)
goto
cleanup
;
error
=
note_lookup
(
out
,
repo
,
notes_commit
,
tree
,
target
);
cleanup:
git_tree_free
(
tree
);
return
error
;
}
int
git_note_read
(
git_note
**
out
,
git_repository
*
repo
,
const
char
*
notes_ref_in
,
const
git_oid
*
oid
)
{
int
error
;
char
*
target
=
NULL
,
*
notes_ref
=
NULL
;
git_tree
*
tree
=
NULL
;
char
*
notes_ref
=
NULL
;
git_commit
*
commit
=
NULL
;
target
=
git_oid_allocfmt
(
oid
);
GITERR_CHECK_ALLOC
(
target
);
error
=
retrieve_note_commit
(
&
commit
,
&
notes_ref
,
repo
,
notes_ref_in
);
if
(
error
<
0
)
goto
cleanup
;
if
(
!
(
error
=
retrieve_note_tree_and_commit
(
&
tree
,
&
commit
,
&
notes_ref
,
repo
,
notes_ref_in
)))
error
=
note_lookup
(
out
,
repo
,
commit
,
tree
,
target
);
error
=
git_note_commit_read
(
out
,
repo
,
commit
,
oid
);
cleanup:
git__free
(
notes_ref
);
git__free
(
target
);
git_tree_free
(
tree
);
git_commit_free
(
commit
);
return
error
;
}
int
git_note_commit_create
(
git_oid
*
notes_commit_out
,
git_oid
*
notes_blob_out
,
git_repository
*
repo
,
git_commit
*
parent
,
const
git_signature
*
author
,
const
git_signature
*
committer
,
const
git_oid
*
oid
,
const
char
*
note
,
int
allow_note_overwrite
)
{
int
error
;
git_tree
*
tree
=
NULL
;
char
target
[
GIT_OID_HEXSZ
+
1
];
git_oid_tostr
(
target
,
sizeof
(
target
),
oid
);
if
(
parent
!=
NULL
&&
(
error
=
git_commit_tree
(
&
tree
,
parent
))
<
0
)
goto
cleanup
;
error
=
note_write
(
notes_commit_out
,
notes_blob_out
,
repo
,
author
,
committer
,
NULL
,
note
,
tree
,
target
,
&
parent
,
allow_note_overwrite
);
if
(
error
<
0
)
goto
cleanup
;
cleanup:
git_tree_free
(
tree
);
return
error
;
}
int
git_note_create
(
git_oid
*
out
,
git_repository
*
repo
,
...
...
@@ -468,25 +529,59 @@ int git_note_create(
int
allow_note_overwrite
)
{
int
error
;
char
*
target
=
NULL
,
*
notes_ref
=
NULL
;
git_commit
*
commit
=
NULL
;
git_tree
*
tree
=
NULL
;
target
=
git_oid_allocfmt
(
oid
);
GITERR_CHECK_ALLOC
(
target
);
char
*
notes_ref
=
NULL
;
git_commit
*
existing_notes_commit
=
NULL
;
git_reference
*
ref
=
NULL
;
git_oid
notes_blob_oid
,
notes_commit_oid
;
error
=
retrieve_note_tree_and_commit
(
&
tree
,
&
commit
,
&
notes_ref
,
repo
,
notes_ref_in
);
error
=
retrieve_note_commit
(
&
existing_notes_commit
,
&
notes_ref
,
repo
,
notes_ref_in
);
if
(
error
<
0
&&
error
!=
GIT_ENOTFOUND
)
goto
cleanup
;
error
=
note_write
(
out
,
repo
,
author
,
committer
,
notes_ref
,
note
,
tree
,
target
,
&
commit
,
allow_note_overwrite
);
error
=
git_note_commit_create
(
&
notes_commit_oid
,
&
notes_blob_oid
,
repo
,
existing_notes_commit
,
author
,
committer
,
oid
,
note
,
allow_note_overwrite
);
if
(
error
<
0
)
goto
cleanup
;
error
=
git_reference_create
(
&
ref
,
repo
,
notes_ref
,
&
notes_commit_oid
,
1
,
NULL
);
if
(
out
!=
NULL
)
git_oid_cpy
(
out
,
&
notes_blob_oid
);
cleanup:
git__free
(
notes_ref
);
git__free
(
target
);
git_commit_free
(
commit
);
git_commit_free
(
existing_notes_commit
);
git_reference_free
(
ref
);
return
error
;
}
int
git_note_commit_remove
(
git_oid
*
notes_commit_out
,
git_repository
*
repo
,
git_commit
*
notes_commit
,
const
git_signature
*
author
,
const
git_signature
*
committer
,
const
git_oid
*
oid
)
{
int
error
;
git_tree
*
tree
=
NULL
;
char
target
[
GIT_OID_HEXSZ
+
1
];
git_oid_tostr
(
target
,
sizeof
(
target
),
oid
);
if
((
error
=
git_commit_tree
(
&
tree
,
notes_commit
))
<
0
)
goto
cleanup
;
error
=
note_remove
(
notes_commit_out
,
repo
,
author
,
committer
,
NULL
,
tree
,
target
,
&
notes_commit
);
cleanup:
git_tree_free
(
tree
);
return
error
;
}
...
...
@@ -496,22 +591,29 @@ int git_note_remove(git_repository *repo, const char *notes_ref_in,
const
git_oid
*
oid
)
{
int
error
;
char
*
target
=
NULL
,
*
notes_ref
;
git_commit
*
commit
=
NULL
;
git_tree
*
tree
=
NULL
;
char
*
notes_ref_target
=
NULL
;
git_commit
*
existing_notes_commit
=
NULL
;
git_oid
new_notes_commit
;
git_reference
*
notes_ref
=
NULL
;
error
=
retrieve_note_commit
(
&
existing_notes_commit
,
&
notes_ref_target
,
repo
,
notes_ref_in
);
if
(
error
<
0
)
goto
cleanup
;
target
=
git_oid_allocfmt
(
oid
);
GITERR_CHECK_ALLOC
(
target
);
error
=
git_note_commit_remove
(
&
new_notes_commit
,
repo
,
existing_notes_commit
,
author
,
committer
,
oid
);
if
(
error
<
0
)
goto
cleanup
;
if
(
!
(
error
=
retrieve_note_tree_and_commit
(
&
tree
,
&
commit
,
&
notes_ref
,
repo
,
notes_ref_in
)))
error
=
note_remove
(
repo
,
author
,
committer
,
notes_ref
,
tree
,
target
,
&
commit
);
error
=
git_reference_create
(
&
notes_ref
,
repo
,
notes_ref_target
,
&
new_notes_commit
,
1
,
NULL
);
git__free
(
notes_ref
);
git__free
(
target
);
git_
commit_free
(
commit
);
git_
tree_free
(
tree
);
cleanup:
git__free
(
notes_ref_
target
);
git_
reference_free
(
notes_ref
);
git_
commit_free
(
existing_notes_commit
);
return
error
;
}
...
...
@@ -639,7 +741,6 @@ int git_note_foreach(
return
error
;
}
void
git_note_iterator_free
(
git_note_iterator
*
it
)
{
if
(
it
==
NULL
)
...
...
@@ -648,6 +749,24 @@ void git_note_iterator_free(git_note_iterator *it)
git_iterator_free
(
it
);
}
int
git_note_commit_iterator_new
(
git_note_iterator
**
it
,
git_commit
*
notes_commit
)
{
int
error
;
git_tree
*
tree
;
if
((
error
=
git_commit_tree
(
&
tree
,
notes_commit
))
<
0
)
goto
cleanup
;
if
((
error
=
git_iterator_for_tree
(
it
,
tree
,
NULL
))
<
0
)
git_iterator_free
(
*
it
);
cleanup:
git_tree_free
(
tree
);
return
error
;
}
int
git_note_iterator_new
(
git_note_iterator
**
it
,
...
...
@@ -656,19 +775,16 @@ int git_note_iterator_new(
{
int
error
;
git_commit
*
commit
=
NULL
;
git_tree
*
tree
=
NULL
;
char
*
notes_ref
;
error
=
retrieve_note_
tree_and_commit
(
&
tree
,
&
commit
,
&
notes_ref
,
repo
,
notes_ref_in
);
error
=
retrieve_note_
commit
(
&
commit
,
&
notes_ref
,
repo
,
notes_ref_in
);
if
(
error
<
0
)
goto
cleanup
;
if
((
error
=
git_iterator_for_tree
(
it
,
tree
,
NULL
))
<
0
)
git_iterator_free
(
*
it
);
error
=
git_note_commit_iterator_new
(
it
,
commit
);
cleanup:
git__free
(
notes_ref
);
git_tree_free
(
tree
);
git_commit_free
(
commit
);
return
error
;
...
...
src/object.c
View file @
e8bc8558
...
...
@@ -236,13 +236,22 @@ const char *git_object_type2string(git_otype type)
git_otype
git_object_string2type
(
const
char
*
str
)
{
if
(
!
str
)
return
GIT_OBJ_BAD
;
return
git_object_stringn2type
(
str
,
strlen
(
str
));
}
git_otype
git_object_stringn2type
(
const
char
*
str
,
size_t
len
)
{
size_t
i
;
if
(
!
str
||
!*
str
)
if
(
!
str
||
!
len
||
!
*
str
)
return
GIT_OBJ_BAD
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
git_objects_table
);
i
++
)
if
(
!
strcmp
(
str
,
git_objects_table
[
i
].
str
))
if
(
*
git_objects_table
[
i
].
str
&&
!
git__prefixncmp
(
str
,
len
,
git_objects_table
[
i
].
str
))
return
(
git_otype
)
i
;
return
GIT_OBJ_BAD
;
...
...
src/object.h
View file @
e8bc8558
...
...
@@ -30,6 +30,8 @@ int git_object__from_odb_object(
int
git_object__resolve_to_type
(
git_object
**
obj
,
git_otype
type
);
git_otype
git_object_stringn2type
(
const
char
*
str
,
size_t
len
);
int
git_oid__parse
(
git_oid
*
oid
,
const
char
**
buffer_out
,
const
char
*
buffer_end
,
const
char
*
header
);
void
git_oid__writebuf
(
git_buf
*
buf
,
const
char
*
header
,
const
git_oid
*
oid
);
...
...
src/odb_loose.c
View file @
e8bc8558
...
...
@@ -16,6 +16,7 @@
#include "delta.h"
#include "filebuf.h"
#include "object.h"
#include "zstream.h"
#include "git2/odb_backend.h"
#include "git2/types.h"
...
...
@@ -119,53 +120,58 @@ static size_t get_binary_object_header(obj_hdr *hdr, git_buf *obj)
return
used
;
}
static
size_t
get_object_header
(
obj_hdr
*
hdr
,
unsigned
char
*
data
)
static
int
parse_header
(
obj_hdr
*
out
,
size_t
*
out_len
,
const
unsigned
char
*
_data
,
size_t
data_len
)
{
char
c
,
typename
[
10
];
size_t
size
,
used
=
0
;
const
char
*
data
=
(
char
*
)
_data
;
size_t
i
,
typename_len
,
size_idx
,
size_len
;
int64_t
size
;
/*
* type name string followed by space.
*/
while
((
c
=
data
[
used
])
!=
' '
)
{
typename
[
used
++
]
=
c
;
if
(
used
>=
sizeof
(
typename
))
return
0
;
*
out_len
=
0
;
/* find the object type name */
for
(
i
=
0
,
typename_len
=
0
;
i
<
data_len
;
i
++
,
typename_len
++
)
{
if
(
data
[
i
]
==
' '
)
break
;
}
typename
[
used
]
=
0
;
if
(
used
==
0
)
return
0
;
hdr
->
type
=
git_object_string2type
(
typename
);
used
++
;
/* consume the space */
/*
* length follows immediately in decimal (without
* leading zeros).
*/
size
=
data
[
used
++
]
-
'0'
;
if
(
size
>
9
)
return
0
;
if
(
size
)
{
while
((
c
=
data
[
used
])
!=
'\0'
)
{
size_t
d
=
c
-
'0'
;
if
(
d
>
9
)
if
(
typename_len
==
data_len
)
goto
on_error
;
out
->
type
=
git_object_stringn2type
(
data
,
typename_len
);
size_idx
=
typename_len
+
1
;
for
(
i
=
size_idx
,
size_len
=
0
;
i
<
data_len
;
i
++
,
size_len
++
)
{
if
(
data
[
i
]
==
'\0'
)
break
;
used
++
;
size
=
size
*
10
+
d
;
}
if
(
i
==
data_len
)
goto
on_error
;
if
(
git__strntol64
(
&
size
,
&
data
[
size_idx
],
size_len
,
NULL
,
10
)
<
0
||
size
<
0
)
goto
on_error
;
if
((
uint64_t
)
size
>
SIZE_MAX
)
{
giterr_set
(
GITERR_OBJECT
,
"object is larger than available memory"
);
return
-
1
;
}
hdr
->
size
=
size
;
/*
* the length must be followed by a zero byte
*/
if
(
data
[
used
++
]
!=
'\0'
)
return
0
;
out
->
size
=
size
;
return
used
;
}
if
(
GIT_ADD_SIZET_OVERFLOW
(
out_len
,
i
,
1
))
goto
on_error
;
return
0
;
on_error:
giterr_set
(
GITERR_OBJECT
,
"failed to parse loose object: invalid header"
);
return
-
1
;
}
/***********************************************************
*
...
...
@@ -269,45 +275,6 @@ static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
return
0
;
}
static
void
*
inflate_tail
(
z_stream
*
s
,
void
*
hb
,
size_t
used
,
obj_hdr
*
hdr
)
{
unsigned
char
*
buf
,
*
head
=
hb
;
size_t
tail
,
alloc_size
;
/*
* allocate a buffer to hold the inflated data and copy the
* initial sequence of inflated data from the tail of the
* head buffer, if any.
*/
if
(
GIT_ADD_SIZET_OVERFLOW
(
&
alloc_size
,
hdr
->
size
,
1
)
||
(
buf
=
git__malloc
(
alloc_size
))
==
NULL
)
{
inflateEnd
(
s
);
return
NULL
;
}
tail
=
s
->
total_out
-
used
;
if
(
used
>
0
&&
tail
>
0
)
{
if
(
tail
>
hdr
->
size
)
tail
=
hdr
->
size
;
memcpy
(
buf
,
head
+
used
,
tail
);
}
used
=
tail
;
/*
* inflate the remainder of the object data, if any
*/
if
(
hdr
->
size
<
used
)
inflateEnd
(
s
);
else
{
set_stream_output
(
s
,
buf
+
used
,
hdr
->
size
-
used
);
if
(
finish_inflate
(
s
))
{
git__free
(
buf
);
return
NULL
;
}
}
return
buf
;
}
/*
* At one point, there was a loose object format that was intended to
* mimic the format used in pack-files. This was to allow easy copying
...
...
@@ -354,43 +321,74 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj)
static
int
inflate_disk_obj
(
git_rawobj
*
out
,
git_buf
*
obj
)
{
unsigned
char
head
[
64
],
*
buf
;
z_stream
zs
;
git_zstream
zstream
=
GIT_ZSTREAM_INIT
;
unsigned
char
head
[
64
],
*
body
=
NULL
;
size_t
decompressed
,
head_len
,
body_len
,
alloc_size
;
obj_hdr
hdr
;
size_t
used
;
int
error
;
/*
* check for a pack-like loose object
*/
/* check for a pack-like loose object */
if
(
!
is_zlib_compressed_data
((
unsigned
char
*
)
obj
->
ptr
))
return
inflate_packlike_loose_disk_obj
(
out
,
obj
);
if
((
error
=
git_zstream_init
(
&
zstream
,
GIT_ZSTREAM_INFLATE
))
<
0
||
(
error
=
git_zstream_set_input
(
&
zstream
,
git_buf_cstr
(
obj
),
git_buf_len
(
obj
)))
<
0
)
goto
done
;
decompressed
=
sizeof
(
head
);
/*
* inflate the initial part of the io buffer in order
* to parse the object header (type and size)
.
* inflate the initial part of the compressed buffer in order to parse the
* header; read the largest header possible, then push back the remainder
.
*/
if
(
start_inflate
(
&
zs
,
obj
,
head
,
sizeof
(
head
))
<
Z_OK
||
(
used
=
get_object_header
(
&
hdr
,
head
))
==
0
||
!
git_object_typeisloose
(
hdr
.
type
))
{
abort_inflate
(
&
zs
);
if
(
(
error
=
git_zstream_get_output
(
head
,
&
decompressed
,
&
zstream
))
<
0
||
(
error
=
parse_header
(
&
hdr
,
&
head_len
,
head
,
decompressed
))
<
0
)
goto
done
;
if
(
!
git_object_typeisloose
(
hdr
.
type
))
{
giterr_set
(
GITERR_ODB
,
"failed to inflate disk object"
);
return
-
1
;
error
=
-
1
;
goto
done
;
}
/*
* 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
-
1
;
buf
[
hdr
.
size
]
=
'\0'
;
if
(
GIT_ADD_SIZET_OVERFLOW
(
&
alloc_size
,
hdr
.
size
,
1
)
||
(
body
=
git__malloc
(
alloc_size
))
==
NULL
)
{
error
=
-
1
;
goto
done
;
}
out
->
data
=
buf
;
assert
(
decompressed
>=
head_len
);
body_len
=
decompressed
-
head_len
;
if
(
body_len
)
memcpy
(
body
,
head
+
head_len
,
body_len
);
decompressed
=
hdr
.
size
-
body_len
;
if
((
error
=
git_zstream_get_output
(
body
+
body_len
,
&
decompressed
,
&
zstream
))
<
0
)
goto
done
;
if
(
!
git_zstream_done
(
&
zstream
))
{
giterr_set
(
GITERR_ZLIB
,
"failed to finish zlib inflation: stream aborted prematurely"
);
error
=
-
1
;
goto
done
;
}
body
[
hdr
.
size
]
=
'\0'
;
out
->
data
=
body
;
out
->
len
=
hdr
.
size
;
out
->
type
=
hdr
.
type
;
return
0
;
done:
if
(
error
<
0
)
git__free
(
body
);
git_zstream_free
(
&
zstream
);
return
error
;
}
...
...
@@ -435,6 +433,7 @@ static int read_header_loose(git_rawobj *out, git_buf *loc)
git_file
fd
;
z_stream
zs
;
obj_hdr
header_obj
;
size_t
header_len
;
unsigned
char
raw_buffer
[
16
],
inflated_buffer
[
64
];
assert
(
out
&&
loc
);
...
...
@@ -460,7 +459,7 @@ static int read_header_loose(git_rawobj *out, git_buf *loc)
}
if
((
z_return
!=
Z_STREAM_END
&&
z_return
!=
Z_BUF_ERROR
)
||
get_object_header
(
&
header_obj
,
inflated_buffer
)
==
0
||
parse_header
(
&
header_obj
,
&
header_len
,
inflated_buffer
,
sizeof
(
inflated_buffer
))
<
0
||
git_object_typeisloose
(
header_obj
.
type
)
==
0
)
{
giterr_set
(
GITERR_ZLIB
,
"failed to read loose object header"
);
...
...
src/pack-objects.c
View file @
e8bc8558
...
...
@@ -1642,7 +1642,7 @@ int insert_tree(git_packbuilder *pb, git_tree *tree)
if
((
error
=
retrieve_object
(
&
obj
,
pb
,
git_tree_id
(
tree
)))
<
0
)
return
error
;
if
(
obj
->
seen
)
if
(
obj
->
seen
||
obj
->
uninteresting
)
return
0
;
obj
->
seen
=
1
;
...
...
@@ -1666,6 +1666,10 @@ int insert_tree(git_packbuilder *pb, git_tree *tree)
break
;
case
GIT_OBJ_BLOB
:
if
((
error
=
retrieve_object
(
&
obj
,
pb
,
git_tree_id
(
tree
)))
<
0
)
return
error
;
if
(
obj
->
uninteresting
)
continue
;
name
=
git_tree_entry_name
(
entry
);
if
((
error
=
git_packbuilder_insert
(
pb
,
entry_id
,
name
))
<
0
)
return
error
;
...
...
src/pack.c
View file @
e8bc8558
...
...
@@ -716,8 +716,11 @@ int git_packfile_unpack(
error
=
packfile_unpack_compressed
(
&
delta
,
p
,
&
w_curs
,
&
curpos
,
elem
->
size
,
elem
->
type
);
git_mwindow_close
(
&
w_curs
);
if
(
error
<
0
)
if
(
error
<
0
)
{
/* We have transferred ownership of the data to the cache. */
obj
->
data
=
NULL
;
break
;
}
/* the current object becomes the new base, on which we apply the delta */
base
=
*
obj
;
...
...
@@ -934,19 +937,19 @@ git_off_t get_delta_base(
if
(
type
==
GIT_OBJ_OFS_DELTA
)
{
unsigned
used
=
0
;
unsigned
char
c
=
base_info
[
used
++
];
base_offset
=
c
&
127
;
size_t
unsigned_
base_offset
=
c
&
127
;
while
(
c
&
128
)
{
if
(
left
<=
used
)
return
GIT_EBUFS
;
base_offset
+=
1
;
if
(
!
base_offset
||
MSB
(
base_offset
,
7
))
unsigned_
base_offset
+=
1
;
if
(
!
unsigned_base_offset
||
MSB
(
unsigned_
base_offset
,
7
))
return
0
;
/* overflow */
c
=
base_info
[
used
++
];
base_offset
=
(
base_offset
<<
7
)
+
(
c
&
127
);
unsigned_base_offset
=
(
unsigned_
base_offset
<<
7
)
+
(
c
&
127
);
}
base_offset
=
delta_obj_offset
-
base_offset
;
if
(
base_offset
<=
0
||
base_offset
>=
delta_obj_offset
)
if
(
unsigned_base_offset
==
0
||
(
size_t
)
delta_obj_offset
<=
unsigned_base_offset
)
return
0
;
/* out of bound */
base_offset
=
delta_obj_offset
-
unsigned_base_offset
;
*
curpos
+=
used
;
}
else
if
(
type
==
GIT_OBJ_REF_DELTA
)
{
/* If we have the cooperative cache, search in it first */
...
...
src/patch_parse.c
View file @
e8bc8558
...
...
@@ -53,11 +53,9 @@ static int header_path_len(git_patch_parse_ctx *ctx)
return
len
;
}
static
int
parse_header_path_buf
(
git_buf
*
path
,
git_patch_parse_ctx
*
ctx
)
static
int
parse_header_path_buf
(
git_buf
*
path
,
git_patch_parse_ctx
*
ctx
,
size_t
path_len
)
{
int
path_len
,
error
=
0
;
path_len
=
header_path_len
(
ctx
);
int
error
;
if
((
error
=
git_buf_put
(
path
,
ctx
->
parse_ctx
.
line
,
path_len
))
<
0
)
goto
done
;
...
...
@@ -81,7 +79,7 @@ done:
static
int
parse_header_path
(
char
**
out
,
git_patch_parse_ctx
*
ctx
)
{
git_buf
path
=
GIT_BUF_INIT
;
int
error
=
parse_header_path_buf
(
&
path
,
ctx
);
int
error
=
parse_header_path_buf
(
&
path
,
ctx
,
header_path_len
(
ctx
)
);
*
out
=
git_buf_detach
(
&
path
);
...
...
@@ -91,13 +89,33 @@ static int parse_header_path(char **out, git_patch_parse_ctx *ctx)
static
int
parse_header_git_oldpath
(
git_patch_parsed
*
patch
,
git_patch_parse_ctx
*
ctx
)
{
return
parse_header_path
(
&
patch
->
old_path
,
ctx
);
git_buf
old_path
=
GIT_BUF_INIT
;
int
error
;
if
((
error
=
parse_header_path_buf
(
&
old_path
,
ctx
,
ctx
->
parse_ctx
.
line_len
-
1
))
<
0
)
goto
out
;
patch
->
old_path
=
git_buf_detach
(
&
old_path
);
out:
git_buf_free
(
&
old_path
);
return
error
;
}
static
int
parse_header_git_newpath
(
git_patch_parsed
*
patch
,
git_patch_parse_ctx
*
ctx
)
{
return
parse_header_path
(
&
patch
->
new_path
,
ctx
);
git_buf
new_path
=
GIT_BUF_INIT
;
int
error
;
if
((
error
=
parse_header_path_buf
(
&
new_path
,
ctx
,
ctx
->
parse_ctx
.
line_len
-
1
))
<
0
)
goto
out
;
patch
->
new_path
=
git_buf_detach
(
&
new_path
);
out:
git_buf_free
(
&
new_path
);
return
error
;
}
static
int
parse_header_mode
(
uint16_t
*
mode
,
git_patch_parse_ctx
*
ctx
)
...
...
@@ -213,7 +231,7 @@ static int parse_header_rename(
{
git_buf
path
=
GIT_BUF_INIT
;
if
(
parse_header_path_buf
(
&
path
,
ctx
)
<
0
)
if
(
parse_header_path_buf
(
&
path
,
ctx
,
header_path_len
(
ctx
)
)
<
0
)
return
-
1
;
/* Note: the `rename from` and `rename to` lines include the literal
...
...
@@ -303,6 +321,22 @@ static int parse_header_start(git_patch_parsed *patch, git_patch_parse_ctx *ctx)
return
git_parse_err
(
"corrupt new path in git diff header at line %"
PRIuZ
,
ctx
->
parse_ctx
.
line_num
);
/*
* We cannot expect to be able to always parse paths correctly at this
* point. Due to the possibility of unquoted names, whitespaces in
* filenames and custom prefixes we have to allow that, though, and just
* proceeed here. We then hope for the "---" and "+++" lines to fix that
* for us.
*/
if
(
!
git_parse_ctx_contains
(
&
ctx
->
parse_ctx
,
"
\n
"
,
1
))
{
git_parse_advance_chars
(
&
ctx
->
parse_ctx
,
ctx
->
parse_ctx
.
line_len
-
1
);
git__free
(
patch
->
header_old_path
);
patch
->
header_old_path
=
NULL
;
git__free
(
patch
->
header_new_path
);
patch
->
header_new_path
=
NULL
;
}
return
0
;
}
...
...
src/push.c
View file @
e8bc8558
...
...
@@ -263,12 +263,11 @@ static int enqueue_tag(git_object **out, git_push *push, git_oid *id)
return
error
;
}
static
int
revwalk
(
git_vector
*
commits
,
git_push
*
push
)
static
int
queue_objects
(
git_push
*
push
)
{
git_remote_head
*
head
;
push_spec
*
spec
;
git_revwalk
*
rw
;
git_oid
oid
;
unsigned
int
i
;
int
error
=
-
1
;
...
...
@@ -353,176 +352,10 @@ static int revwalk(git_vector *commits, git_push *push)
git_revwalk_hide
(
rw
,
&
head
->
oid
);
}
while
((
error
=
git_revwalk_next
(
&
oid
,
rw
))
==
0
)
{
git_oid
*
o
=
git__malloc
(
GIT_OID_RAWSZ
);
if
(
!
o
)
{
error
=
-
1
;
goto
on_error
;
}
git_oid_cpy
(
o
,
&
oid
);
if
((
error
=
git_vector_insert
(
commits
,
o
))
<
0
)
goto
on_error
;
}
error
=
git_packbuilder_insert_walk
(
push
->
pb
,
rw
);
on_error:
git_revwalk_free
(
rw
);
return
error
==
GIT_ITEROVER
?
0
:
error
;
}
static
int
enqueue_object
(
const
git_tree_entry
*
entry
,
git_packbuilder
*
pb
)
{
switch
(
git_tree_entry_type
(
entry
))
{
case
GIT_OBJ_COMMIT
:
return
0
;
case
GIT_OBJ_TREE
:
return
git_packbuilder_insert_tree
(
pb
,
entry
->
oid
);
default:
return
git_packbuilder_insert
(
pb
,
entry
->
oid
,
entry
->
filename
);
}
}
static
int
queue_differences
(
git_tree
*
base
,
git_tree
*
delta
,
git_packbuilder
*
pb
)
{
git_tree
*
b_child
=
NULL
,
*
d_child
=
NULL
;
size_t
b_length
=
git_tree_entrycount
(
base
);
size_t
d_length
=
git_tree_entrycount
(
delta
);
size_t
i
=
0
,
j
=
0
;
int
error
;
while
(
i
<
b_length
&&
j
<
d_length
)
{
const
git_tree_entry
*
b_entry
=
git_tree_entry_byindex
(
base
,
i
);
const
git_tree_entry
*
d_entry
=
git_tree_entry_byindex
(
delta
,
j
);
int
cmp
=
0
;
if
(
!
git_oid__cmp
(
b_entry
->
oid
,
d_entry
->
oid
))
goto
loop
;
cmp
=
strcmp
(
b_entry
->
filename
,
d_entry
->
filename
);
/* If the entries are both trees and they have the same name but are
* different, then we'll recurse after adding the right-hand entry */
if
(
!
cmp
&&
git_tree_entry__is_tree
(
b_entry
)
&&
git_tree_entry__is_tree
(
d_entry
))
{
/* Add the right-hand entry */
if
((
error
=
git_packbuilder_insert
(
pb
,
d_entry
->
oid
,
d_entry
->
filename
))
<
0
)
goto
on_error
;
/* Acquire the subtrees and recurse */
if
((
error
=
git_tree_lookup
(
&
b_child
,
git_tree_owner
(
base
),
b_entry
->
oid
))
<
0
||
(
error
=
git_tree_lookup
(
&
d_child
,
git_tree_owner
(
delta
),
d_entry
->
oid
))
<
0
||
(
error
=
queue_differences
(
b_child
,
d_child
,
pb
))
<
0
)
goto
on_error
;
git_tree_free
(
b_child
);
b_child
=
NULL
;
git_tree_free
(
d_child
);
d_child
=
NULL
;
}
/* If the object is new or different in the right-hand tree,
* then enumerate it */
else
if
(
cmp
>=
0
&&
(
error
=
enqueue_object
(
d_entry
,
pb
))
<
0
)
goto
on_error
;
loop:
if
(
cmp
<=
0
)
i
++
;
if
(
cmp
>=
0
)
j
++
;
}
/* Drain the right-hand tree of entries */
for
(;
j
<
d_length
;
j
++
)
if
((
error
=
enqueue_object
(
git_tree_entry_byindex
(
delta
,
j
),
pb
))
<
0
)
goto
on_error
;
error
=
0
;
on_error:
if
(
b_child
)
git_tree_free
(
b_child
);
if
(
d_child
)
git_tree_free
(
d_child
);
return
error
;
}
static
int
queue_objects
(
git_push
*
push
)
{
git_vector
commits
=
GIT_VECTOR_INIT
;
git_oid
*
oid
;
size_t
i
;
unsigned
j
;
int
error
;
if
((
error
=
revwalk
(
&
commits
,
push
))
<
0
)
goto
on_error
;
git_vector_foreach
(
&
commits
,
i
,
oid
)
{
git_commit
*
parent
=
NULL
,
*
commit
;
git_tree
*
tree
=
NULL
,
*
ptree
=
NULL
;
size_t
parentcount
;
if
((
error
=
git_commit_lookup
(
&
commit
,
push
->
repo
,
oid
))
<
0
)
goto
on_error
;
/* Insert the commit */
if
((
error
=
git_packbuilder_insert
(
push
->
pb
,
oid
,
NULL
))
<
0
)
goto
loop_error
;
parentcount
=
git_commit_parentcount
(
commit
);
if
(
!
parentcount
)
{
if
((
error
=
git_packbuilder_insert_tree
(
push
->
pb
,
git_commit_tree_id
(
commit
)))
<
0
)
goto
loop_error
;
}
else
{
if
((
error
=
git_tree_lookup
(
&
tree
,
push
->
repo
,
git_commit_tree_id
(
commit
)))
<
0
||
(
error
=
git_packbuilder_insert
(
push
->
pb
,
git_commit_tree_id
(
commit
),
NULL
))
<
0
)
goto
loop_error
;
/* For each parent, add the items which are different */
for
(
j
=
0
;
j
<
parentcount
;
j
++
)
{
if
((
error
=
git_commit_parent
(
&
parent
,
commit
,
j
))
<
0
||
(
error
=
git_commit_tree
(
&
ptree
,
parent
))
<
0
||
(
error
=
queue_differences
(
ptree
,
tree
,
push
->
pb
))
<
0
)
goto
loop_error
;
git_tree_free
(
ptree
);
ptree
=
NULL
;
git_commit_free
(
parent
);
parent
=
NULL
;
}
}
error
=
0
;
loop_error:
if
(
tree
)
git_tree_free
(
tree
);
if
(
ptree
)
git_tree_free
(
ptree
);
if
(
parent
)
git_commit_free
(
parent
);
git_commit_free
(
commit
);
if
(
error
<
0
)
goto
on_error
;
}
error
=
0
;
on_error:
git_vector_free_deep
(
&
commits
);
return
error
;
}
...
...
src/refdb_fs.c
View file @
e8bc8558
...
...
@@ -2035,6 +2035,7 @@ int git_refdb_backend_fs(
if
((
!
git_repository__cvar
(
&
t
,
backend
->
repo
,
GIT_CVAR_FSYNCOBJECTFILES
)
&&
t
)
||
git_repository__fsync_gitdir
)
backend
->
fsync
=
1
;
backend
->
iterator_flags
|=
GIT_ITERATOR_DESCEND_SYMLINKS
;
backend
->
parent
.
exists
=
&
refdb_fs_backend__exists
;
backend
->
parent
.
lookup
=
&
refdb_fs_backend__lookup
;
...
...
src/remote.c
View file @
e8bc8558
...
...
@@ -1541,6 +1541,20 @@ cleanup:
return
error
;
}
static
int
truncate_fetch_head
(
const
char
*
gitdir
)
{
git_buf
path
=
GIT_BUF_INIT
;
int
error
;
if
((
error
=
git_buf_joinpath
(
&
path
,
gitdir
,
GIT_FETCH_HEAD_FILE
))
<
0
)
return
error
;
error
=
git_futils_truncate
(
path
.
ptr
,
GIT_REFS_FILE_MODE
);
git_buf_free
(
&
path
);
return
error
;
}
int
git_remote_update_tips
(
git_remote
*
remote
,
const
git_remote_callbacks
*
callbacks
,
...
...
@@ -1571,6 +1585,9 @@ int git_remote_update_tips(
else
tagopt
=
download_tags
;
if
((
error
=
truncate_fetch_head
(
git_repository_path
(
remote
->
repo
)))
<
0
)
goto
out
;
if
(
tagopt
==
GIT_REMOTE_DOWNLOAD_TAGS_ALL
)
{
if
((
error
=
update_tips_for_spec
(
remote
,
callbacks
,
update_fetchhead
,
tagopt
,
&
tagspec
,
&
refs
,
reflog_message
))
<
0
)
goto
out
;
...
...
src/streams/openssl.c
View file @
e8bc8558
...
...
@@ -332,7 +332,7 @@ static int check_host_name(const char *name, const char *host)
static
int
verify_server_cert
(
SSL
*
ssl
,
const
char
*
host
)
{
X509
*
cert
;
X509
*
cert
=
NULL
;
X509_NAME
*
peer_name
;
ASN1_STRING
*
str
;
unsigned
char
*
peer_cn
=
NULL
;
...
...
@@ -341,7 +341,7 @@ static int verify_server_cert(SSL *ssl, const char *host)
struct
in6_addr
addr6
;
struct
in_addr
addr4
;
void
*
addr
;
int
i
=
-
1
,
j
;
int
i
=
-
1
,
j
,
error
=
0
;
if
(
SSL_get_verify_result
(
ssl
)
!=
X509_V_OK
)
{
giterr_set
(
GITERR_SSL
,
"the SSL certificate is invalid"
);
...
...
@@ -362,8 +362,9 @@ static int verify_server_cert(SSL *ssl, const char *host)
cert
=
SSL_get_peer_certificate
(
ssl
);
if
(
!
cert
)
{
error
=
-
1
;
giterr_set
(
GITERR_SSL
,
"the server did not provide a certificate"
);
return
-
1
;
goto
cleanup
;
}
/* Check the alternative names */
...
...
@@ -401,8 +402,9 @@ static int verify_server_cert(SSL *ssl, const char *host)
if
(
matched
==
0
)
goto
cert_fail_name
;
if
(
matched
==
1
)
return
0
;
if
(
matched
==
1
)
{
goto
cleanup
;
}
/* If no alternative names are available, check the common name */
peer_name
=
X509_get_subject_name
(
cert
);
...
...
@@ -444,18 +446,21 @@ static int verify_server_cert(SSL *ssl, const char *host)
if
(
check_host_name
((
char
*
)
peer_cn
,
host
)
<
0
)
goto
cert_fail_name
;
OPENSSL_free
(
peer_cn
)
;
goto
cleanup
;
return
0
;
cert_fail_name:
error
=
GIT_ECERTIFICATE
;
giterr_set
(
GITERR_SSL
,
"hostname does not match certificate"
);
goto
cleanup
;
on_error:
OPENSSL_free
(
peer_cn
);
return
ssl_set_error
(
ssl
,
0
)
;
error
=
ssl_set_error
(
ssl
,
0
);
goto
cleanup
;
cert_fail_name:
cleanup:
X509_free
(
cert
);
OPENSSL_free
(
peer_cn
);
giterr_set
(
GITERR_SSL
,
"hostname does not match certificate"
);
return
GIT_ECERTIFICATE
;
return
error
;
}
typedef
struct
{
...
...
src/streams/stransport.c
View file @
e8bc8558
...
...
@@ -83,8 +83,10 @@ static int stransport_connect(git_stream *stream)
}
if
(
sec_res
==
kSecTrustResultDeny
||
sec_res
==
kSecTrustResultRecoverableTrustFailure
||
sec_res
==
kSecTrustResultFatalTrustFailure
)
sec_res
==
kSecTrustResultFatalTrustFailure
)
{
giterr_set
(
GITERR_SSL
,
"untrusted connection error"
);
return
GIT_ECERTIFICATE
;
}
return
0
;
...
...
src/transports/local.c
View file @
e8bc8558
...
...
@@ -507,6 +507,21 @@ static int local_counting(int stage, unsigned int current, unsigned int total, v
return
error
;
}
static
int
foreach_reference_cb
(
git_reference
*
reference
,
void
*
payload
)
{
git_revwalk
*
walk
=
(
git_revwalk
*
)
payload
;
int
error
=
git_revwalk_hide
(
walk
,
git_reference_target
(
reference
));
/* The reference is in the local repository, so the target may not
* exist on the remote. It also may not be a commit. */
if
(
error
==
GIT_ENOTFOUND
||
error
==
GITERR_INVALID
)
{
giterr_clear
();
error
=
0
;
}
return
error
;
}
static
int
local_download_pack
(
git_transport
*
transport
,
git_repository
*
repo
,
...
...
@@ -546,11 +561,6 @@ static int local_download_pack(
if
(
git_object_type
(
obj
)
==
GIT_OBJ_COMMIT
)
{
/* Revwalker includes only wanted commits */
error
=
git_revwalk_push
(
walk
,
&
rhead
->
oid
);
if
(
!
error
&&
!
git_oid_iszero
(
&
rhead
->
loid
))
{
error
=
git_revwalk_hide
(
walk
,
&
rhead
->
loid
);
if
(
error
==
GIT_ENOTFOUND
)
error
=
0
;
}
}
else
{
/* Tag or some other wanted object. Add it on its own */
error
=
git_packbuilder_insert_recur
(
pack
,
&
rhead
->
oid
,
rhead
->
name
);
...
...
@@ -560,6 +570,9 @@ static int local_download_pack(
goto
cleanup
;
}
if
((
error
=
git_reference_foreach
(
repo
,
foreach_reference_cb
,
walk
)))
goto
cleanup
;
if
((
error
=
git_packbuilder_insert_walk
(
pack
,
walk
)))
goto
cleanup
;
...
...
src/transports/winhttp.c
View file @
e8bc8558
...
...
@@ -172,9 +172,15 @@ static int apply_default_credentials(HINTERNET request, int mechanisms)
* is "medium" which applies to the intranet and sounds like it would correspond
* to Internet Explorer security zones, but in fact does not. */
DWORD
data
=
WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW
;
DWORD
native_scheme
=
0
;
if
((
mechanisms
&
GIT_WINHTTP_AUTH_NTLM
)
==
0
&&
(
mechanisms
&
GIT_WINHTTP_AUTH_NEGOTIATE
)
==
0
)
{
if
((
mechanisms
&
GIT_WINHTTP_AUTH_NTLM
)
!=
0
)
native_scheme
|=
WINHTTP_AUTH_SCHEME_NTLM
;
if
((
mechanisms
&
GIT_WINHTTP_AUTH_NEGOTIATE
)
!=
0
)
native_scheme
|=
WINHTTP_AUTH_SCHEME_NEGOTIATE
;
if
(
!
native_scheme
)
{
giterr_set
(
GITERR_NET
,
"invalid authentication scheme"
);
return
-
1
;
}
...
...
@@ -182,6 +188,9 @@ static int apply_default_credentials(HINTERNET request, int mechanisms)
if
(
!
WinHttpSetOption
(
request
,
WINHTTP_OPTION_AUTOLOGON_POLICY
,
&
data
,
sizeof
(
DWORD
)))
return
-
1
;
if
(
!
WinHttpSetCredentials
(
request
,
WINHTTP_AUTH_TARGET_SERVER
,
native_scheme
,
NULL
,
NULL
,
NULL
))
return
-
1
;
return
0
;
}
...
...
@@ -606,12 +615,12 @@ static int parse_unauthorized_response(
if
(
WINHTTP_AUTH_SCHEME_NTLM
&
supported
)
{
*
allowed_types
|=
GIT_CREDTYPE_USERPASS_PLAINTEXT
;
*
allowed_types
|=
GIT_CREDTYPE_DEFAULT
;
*
allowed_mechanisms
=
GIT_WINHTTP_AUTH_NEGOTIATE
;
*
allowed_mechanisms
|=
GIT_WINHTTP_AUTH_NTLM
;
}
if
(
WINHTTP_AUTH_SCHEME_NEGOTIATE
&
supported
)
{
*
allowed_types
|=
GIT_CREDTYPE_DEFAULT
;
*
allowed_mechanisms
=
GIT_WINHTTP_AUTH_NEGOTIATE
;
*
allowed_mechanisms
|
=
GIT_WINHTTP_AUTH_NEGOTIATE
;
}
if
(
WINHTTP_AUTH_SCHEME_BASIC
&
supported
)
{
...
...
src/util.c
View file @
e8bc8558
...
...
@@ -252,35 +252,47 @@ void git__strtolower(char *str)
git__strntolower
(
str
,
strlen
(
str
));
}
int
git__prefixcmp
(
const
char
*
str
,
const
char
*
prefix
)
GIT_INLINE
(
int
)
prefixcmp
(
const
char
*
str
,
size_t
str_n
,
const
char
*
prefix
,
bool
icase
)
{
for
(;;)
{
unsigned
char
p
=
*
(
prefix
++
),
s
;
int
s
,
p
;
while
(
str_n
--
)
{
s
=
(
unsigned
char
)
*
str
++
;
p
=
(
unsigned
char
)
*
prefix
++
;
if
(
icase
)
{
s
=
git__tolower
(
s
);
p
=
git__tolower
(
p
);
}
if
(
!
p
)
return
0
;
if
((
s
=
*
(
str
++
))
!=
p
)
if
(
s
!=
p
)
return
s
-
p
;
}
return
(
0
-
*
prefix
);
}
int
git__prefixcmp
_icase
(
const
char
*
str
,
const
char
*
prefix
)
int
git__prefixcmp
(
const
char
*
str
,
const
char
*
prefix
)
{
return
strncasecmp
(
str
,
prefix
,
strlen
(
prefix
)
);
return
prefixcmp
(
str
,
SIZE_MAX
,
prefix
,
false
);
}
int
git__prefixncmp
_icase
(
const
char
*
str
,
size_t
str_n
,
const
char
*
prefix
)
int
git__prefixncmp
(
const
char
*
str
,
size_t
str_n
,
const
char
*
prefix
)
{
int
s
,
p
;
while
(
str_n
--
)
{
s
=
(
unsigned
char
)
git__tolower
(
*
str
++
);
p
=
(
unsigned
char
)
git__tolower
(
*
prefix
++
);
return
prefixcmp
(
str
,
str_n
,
prefix
,
false
);
}
if
(
s
!=
p
)
return
s
-
p
;
}
int
git__prefixcmp_icase
(
const
char
*
str
,
const
char
*
prefix
)
{
return
prefixcmp
(
str
,
SIZE_MAX
,
prefix
,
true
);
}
return
(
0
-
*
prefix
);
int
git__prefixncmp_icase
(
const
char
*
str
,
size_t
str_n
,
const
char
*
prefix
)
{
return
prefixcmp
(
str
,
str_n
,
prefix
,
true
);
}
int
git__suffixcmp
(
const
char
*
str
,
const
char
*
suffix
)
...
...
src/util.h
View file @
e8bc8558
...
...
@@ -180,6 +180,7 @@ GIT_INLINE(void) git__free(void *ptr)
extern
int
git__prefixcmp
(
const
char
*
str
,
const
char
*
prefix
);
extern
int
git__prefixcmp_icase
(
const
char
*
str
,
const
char
*
prefix
);
extern
int
git__prefixncmp
(
const
char
*
str
,
size_t
str_n
,
const
char
*
prefix
);
extern
int
git__prefixncmp_icase
(
const
char
*
str
,
size_t
str_n
,
const
char
*
prefix
);
extern
int
git__suffixcmp
(
const
char
*
str
,
const
char
*
suffix
);
...
...
src/zstream.c
View file @
e8bc8558
...
...
@@ -14,17 +14,22 @@
#define ZSTREAM_BUFFER_SIZE (1024 * 1024)
#define ZSTREAM_BUFFER_MIN_EXTRA 8
static
int
zstream_seterr
(
git_zstream
*
zs
)
GIT_INLINE
(
int
)
zstream_seterr
(
git_zstream
*
zs
)
{
if
(
zs
->
zerr
==
Z_OK
||
zs
->
zerr
==
Z_STREAM_END
)
switch
(
zs
->
zerr
)
{
case
Z_OK
:
case
Z_STREAM_END
:
case
Z_BUF_ERROR
:
/* not fatal; we retry with a larger buffer */
return
0
;
if
(
zs
->
zerr
==
Z_MEM_ERROR
)
case
Z_MEM_ERROR
:
giterr_set_oom
();
else
if
(
zs
->
z
.
msg
)
break
;
default
:
if
(
zs
->
z
.
msg
)
giterr_set_str
(
GITERR_ZLIB
,
zs
->
z
.
msg
);
else
giterr_set
(
GITERR_ZLIB
,
"unknown compression error"
);
}
return
-
1
;
}
...
...
@@ -98,8 +103,9 @@ int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream)
/* set up in data */
zstream
->
z
.
next_in
=
(
Bytef
*
)
zstream
->
in
;
zstream
->
z
.
avail_in
=
(
uInt
)
zstream
->
in_len
;
if
((
size_t
)
zstream
->
z
.
avail_in
!=
zstream
->
in_len
)
{
zstream
->
z
.
avail_in
=
INT_MAX
;
zstream
->
z
.
avail_in
=
U
INT_MAX
;
zflush
=
Z_NO_FLUSH
;
}
else
{
zflush
=
Z_FINISH
;
...
...
@@ -110,7 +116,7 @@ int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream)
zstream
->
z
.
next_out
=
out
;
zstream
->
z
.
avail_out
=
(
uInt
)
out_remain
;
if
((
size_t
)
zstream
->
z
.
avail_out
!=
out_remain
)
zstream
->
z
.
avail_out
=
INT_MAX
;
zstream
->
z
.
avail_out
=
U
INT_MAX
;
out_queued
=
(
size_t
)
zstream
->
z
.
avail_out
;
/* compress next chunk */
...
...
@@ -119,8 +125,8 @@ int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream)
else
zstream
->
zerr
=
deflate
(
&
zstream
->
z
,
zflush
);
if
(
zstream
->
zerr
==
Z_STREAM_ERROR
)
return
zstream_seterr
(
zstream
)
;
if
(
zstream
_seterr
(
zstream
)
)
return
-
1
;
out_used
=
(
out_queued
-
zstream
->
z
.
avail_out
);
out_remain
-=
out_used
;
...
...
tests/core/string.c
View file @
e8bc8558
...
...
@@ -40,6 +40,48 @@ void test_core_string__2(void)
cl_assert
(
git__strcasesort_cmp
(
"fooBar"
,
"foobar"
)
<
0
);
}
/* compare prefixes with len */
void
test_core_string__prefixncmp
(
void
)
{
cl_assert
(
git__prefixncmp
(
""
,
0
,
""
)
==
0
);
cl_assert
(
git__prefixncmp
(
"a"
,
1
,
""
)
==
0
);
cl_assert
(
git__prefixncmp
(
""
,
0
,
"a"
)
<
0
);
cl_assert
(
git__prefixncmp
(
"a"
,
1
,
"b"
)
<
0
);
cl_assert
(
git__prefixncmp
(
"b"
,
1
,
"a"
)
>
0
);
cl_assert
(
git__prefixncmp
(
"ab"
,
2
,
"a"
)
==
0
);
cl_assert
(
git__prefixncmp
(
"ab"
,
1
,
"a"
)
==
0
);
cl_assert
(
git__prefixncmp
(
"ab"
,
2
,
"ac"
)
<
0
);
cl_assert
(
git__prefixncmp
(
"a"
,
1
,
"ac"
)
<
0
);
cl_assert
(
git__prefixncmp
(
"ab"
,
1
,
"ac"
)
<
0
);
cl_assert
(
git__prefixncmp
(
"ab"
,
2
,
"aa"
)
>
0
);
cl_assert
(
git__prefixncmp
(
"ab"
,
1
,
"aa"
)
<
0
);
}
/* compare prefixes with len */
void
test_core_string__prefixncmp_icase
(
void
)
{
cl_assert
(
git__prefixncmp_icase
(
""
,
0
,
""
)
==
0
);
cl_assert
(
git__prefixncmp_icase
(
"a"
,
1
,
""
)
==
0
);
cl_assert
(
git__prefixncmp_icase
(
""
,
0
,
"a"
)
<
0
);
cl_assert
(
git__prefixncmp_icase
(
"a"
,
1
,
"b"
)
<
0
);
cl_assert
(
git__prefixncmp_icase
(
"A"
,
1
,
"b"
)
<
0
);
cl_assert
(
git__prefixncmp_icase
(
"a"
,
1
,
"B"
)
<
0
);
cl_assert
(
git__prefixncmp_icase
(
"b"
,
1
,
"a"
)
>
0
);
cl_assert
(
git__prefixncmp_icase
(
"B"
,
1
,
"a"
)
>
0
);
cl_assert
(
git__prefixncmp_icase
(
"b"
,
1
,
"A"
)
>
0
);
cl_assert
(
git__prefixncmp_icase
(
"ab"
,
2
,
"a"
)
==
0
);
cl_assert
(
git__prefixncmp_icase
(
"Ab"
,
2
,
"a"
)
==
0
);
cl_assert
(
git__prefixncmp_icase
(
"ab"
,
2
,
"A"
)
==
0
);
cl_assert
(
git__prefixncmp_icase
(
"ab"
,
1
,
"a"
)
==
0
);
cl_assert
(
git__prefixncmp_icase
(
"ab"
,
2
,
"ac"
)
<
0
);
cl_assert
(
git__prefixncmp_icase
(
"Ab"
,
2
,
"ac"
)
<
0
);
cl_assert
(
git__prefixncmp_icase
(
"ab"
,
2
,
"Ac"
)
<
0
);
cl_assert
(
git__prefixncmp_icase
(
"a"
,
1
,
"ac"
)
<
0
);
cl_assert
(
git__prefixncmp_icase
(
"ab"
,
1
,
"ac"
)
<
0
);
cl_assert
(
git__prefixncmp_icase
(
"ab"
,
2
,
"aa"
)
>
0
);
cl_assert
(
git__prefixncmp_icase
(
"ab"
,
1
,
"aa"
)
<
0
);
}
void
test_core_string__strcmp
(
void
)
{
cl_assert
(
git__strcmp
(
""
,
""
)
==
0
);
...
...
tests/diff/blob.c
View file @
e8bc8558
#include "clar_libgit2.h"
#include "diff_helpers.h"
#define BLOB_DIFF \
"diff --git a/file b/file\n" \
"index 45141a7..4d713dc 100644\n" \
"--- a/file\n" \
"+++ b/file\n" \
"@@ -1 +1,6 @@\n" \
" Hello from the root\n" \
"+\n" \
"+Some additional lines\n" \
"+\n" \
"+Down here below\n" \
"+\n"
static
git_repository
*
g_repo
=
NULL
;
static
diff_expects
expected
;
static
git_diff_options
opts
;
...
...
@@ -65,6 +78,32 @@ static void assert_one_modified(
cl_assert_equal_i
(
dels
,
exp
->
line_dels
);
}
void
test_diff_blob__patch_with_freed_blobs
(
void
)
{
git_oid
a_oid
,
b_oid
;
git_blob
*
a
,
*
b
;
git_patch
*
p
;
git_buf
buf
=
GIT_BUF_INIT
;
/* tests/resources/attr/root_test1 */
cl_git_pass
(
git_oid_fromstrn
(
&
a_oid
,
"45141a79"
,
8
));
cl_git_pass
(
git_blob_lookup_prefix
(
&
a
,
g_repo
,
&
a_oid
,
4
));
/* tests/resources/attr/root_test2 */
cl_git_pass
(
git_oid_fromstrn
(
&
b_oid
,
"4d713dc4"
,
8
));
cl_git_pass
(
git_blob_lookup_prefix
(
&
b
,
g_repo
,
&
b_oid
,
4
));
cl_git_pass
(
git_patch_from_blobs
(
&
p
,
a
,
NULL
,
b
,
NULL
,
NULL
));
git_blob_free
(
a
);
git_blob_free
(
b
);
cl_git_pass
(
git_patch_to_buf
(
&
buf
,
p
));
cl_assert_equal_s
(
buf
.
ptr
,
BLOB_DIFF
);
git_patch_free
(
p
);
git_buf_free
(
&
buf
);
}
void
test_diff_blob__can_compare_text_blobs
(
void
)
{
git_blob
*
a
,
*
b
,
*
c
;
...
...
tests/fetchhead/nonetwork.c
View file @
e8bc8558
...
...
@@ -353,20 +353,25 @@ void test_fetchhead_nonetwork__quote_in_branch_name(void)
}
static
bool
found_master
;
static
bool
find_master_called
;
static
bool
found_haacked
;
static
bool
find_master_haacked_called
;
int
find_master
(
const
char
*
ref_name
,
const
char
*
remote_url
,
const
git_oid
*
oid
,
unsigned
int
is_merge
,
void
*
payload
)
int
find_master
_haacked
(
const
char
*
ref_name
,
const
char
*
remote_url
,
const
git_oid
*
oid
,
unsigned
int
is_merge
,
void
*
payload
)
{
GIT_UNUSED
(
remote_url
);
GIT_UNUSED
(
oid
);
GIT_UNUSED
(
payload
);
find_master_called
=
true
;
find_master_
haacked_
called
=
true
;
if
(
!
strcmp
(
"refs/heads/master"
,
ref_name
))
{
cl_assert
(
is_merge
);
found_master
=
true
;
}
if
(
!
strcmp
(
"refs/heads/haacked"
,
ref_name
))
{
cl_assert
(
is_merge
);
found_haacked
=
true
;
}
return
0
;
}
...
...
@@ -375,10 +380,12 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void)
{
git_remote
*
remote
;
git_buf
path
=
GIT_BUF_INIT
;
char
*
refspec
=
"refs/heads/master"
;
char
*
refspec1
=
"refs/heads/master"
;
char
*
refspec2
=
"refs/heads/haacked"
;
char
*
refspecs
[]
=
{
refspec1
,
refspec2
};
git_strarray
specs
=
{
&
refspec
,
1
,
refspecs
,
2
,
};
cl_set_cleanup
(
&
cleanup_repository
,
"./test1"
);
...
...
@@ -391,9 +398,74 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void)
cl_git_pass
(
git_remote_fetch
(
remote
,
&
specs
,
NULL
,
NULL
));
cl_assert
(
git_path_exists
(
path
.
ptr
));
cl_git_pass
(
git_repository_fetchhead_foreach
(
g_repo
,
find_master
,
NULL
));
cl_assert
(
find_master_called
);
cl_git_pass
(
git_repository_fetchhead_foreach
(
g_repo
,
find_master
_haacked
,
NULL
));
cl_assert
(
find_master_
haacked_
called
);
cl_assert
(
found_master
);
cl_assert
(
found_haacked
);
git_remote_free
(
remote
);
git_buf_free
(
&
path
);
}
static
bool
count_refs_called
;
struct
prefix_count
{
const
char
*
prefix
;
int
count
;
int
expected
;
};
int
count_refs
(
const
char
*
ref_name
,
const
char
*
remote_url
,
const
git_oid
*
oid
,
unsigned
int
is_merge
,
void
*
payload
)
{
int
i
;
struct
prefix_count
*
prefix_counts
=
(
struct
prefix_count
*
)
payload
;
GIT_UNUSED
(
remote_url
);
GIT_UNUSED
(
oid
);
GIT_UNUSED
(
is_merge
);
count_refs_called
=
true
;
for
(
i
=
0
;
prefix_counts
[
i
].
prefix
;
i
++
)
{
if
(
!
git__prefixcmp
(
ref_name
,
prefix_counts
[
i
].
prefix
))
prefix_counts
[
i
].
count
++
;
}
return
0
;
}
void
test_fetchhead_nonetwork__create_with_multiple_refspecs
(
void
)
{
git_remote
*
remote
;
git_buf
path
=
GIT_BUF_INIT
;
cl_set_cleanup
(
&
cleanup_repository
,
"./test1"
);
cl_git_pass
(
git_repository_init
(
&
g_repo
,
"./test1"
,
0
));
cl_git_pass
(
git_remote_create
(
&
remote
,
g_repo
,
"origin"
,
cl_fixture
(
"testrepo.git"
)));
git_remote_free
(
remote
);
cl_git_pass
(
git_remote_add_fetch
(
g_repo
,
"origin"
,
"+refs/notes/*:refs/origin/notes/*"
));
/* Pick up the new refspec */
cl_git_pass
(
git_remote_lookup
(
&
remote
,
g_repo
,
"origin"
));
cl_git_pass
(
git_buf_joinpath
(
&
path
,
git_repository_path
(
g_repo
),
"FETCH_HEAD"
));
cl_assert
(
!
git_path_exists
(
path
.
ptr
));
cl_git_pass
(
git_remote_fetch
(
remote
,
NULL
,
NULL
,
NULL
));
cl_assert
(
git_path_exists
(
path
.
ptr
));
{
int
i
;
struct
prefix_count
prefix_counts
[]
=
{
{
"refs/notes/"
,
0
,
1
},
{
"refs/heads/"
,
0
,
12
},
{
"refs/tags/"
,
0
,
7
},
{
NULL
,
0
,
0
},
};
cl_git_pass
(
git_repository_fetchhead_foreach
(
g_repo
,
count_refs
,
&
prefix_counts
));
cl_assert
(
count_refs_called
);
for
(
i
=
0
;
prefix_counts
[
i
].
prefix
;
i
++
)
cl_assert_equal_i
(
prefix_counts
[
i
].
expected
,
prefix_counts
[
i
].
count
);
}
git_remote_free
(
remote
);
git_buf_free
(
&
path
);
...
...
tests/merge/workdir/submodules.c
View file @
e8bc8558
...
...
@@ -12,6 +12,7 @@ static git_repository *repo;
#define SUBMODULE_MAIN_BRANCH "submodules"
#define SUBMODULE_OTHER_BRANCH "submodules-branch"
#define SUBMODULE_OTHER2_BRANCH "submodules-branch2"
#define SUBMODULE_DELETE_BRANCH "delete-submodule"
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
...
...
@@ -93,3 +94,38 @@ void test_merge_workdir_submodules__take_changed(void)
git_reference_free
(
their_ref
);
git_reference_free
(
our_ref
);
}
void
test_merge_workdir_submodules__update_delete_conflict
(
void
)
{
git_reference
*
our_ref
,
*
their_ref
;
git_commit
*
our_commit
;
git_annotated_commit
*
their_head
;
git_index
*
index
;
struct
merge_index_entry
merge_index_entries
[]
=
{
{
0100644
,
"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"
,
0
,
".gitmodules"
},
{
0100644
,
"5887a5e516c53bd58efb0f02ec6aa031b6fe9ad7"
,
0
,
"file1.txt"
},
{
0100644
,
"4218670ab81cc219a9f94befb5c5dad90ec52648"
,
0
,
"file2.txt"
},
{
0160000
,
"d3d806a4bef96889117fd7ebac0e3cb5ec152932"
,
1
,
"submodule"
},
{
0160000
,
"297aa6cd028b3336c7802c7a6f49143da4e1602d"
,
3
,
"submodule"
},
};
cl_git_pass
(
git_reference_lookup
(
&
our_ref
,
repo
,
"refs/heads/"
SUBMODULE_DELETE_BRANCH
));
cl_git_pass
(
git_commit_lookup
(
&
our_commit
,
repo
,
git_reference_target
(
our_ref
)));
cl_git_pass
(
git_reset
(
repo
,
(
git_object
*
)
our_commit
,
GIT_RESET_HARD
,
NULL
));
cl_git_pass
(
git_reference_lookup
(
&
their_ref
,
repo
,
"refs/heads/"
SUBMODULE_MAIN_BRANCH
));
cl_git_pass
(
git_annotated_commit_from_ref
(
&
their_head
,
repo
,
their_ref
));
cl_git_pass
(
git_merge
(
repo
,
(
const
git_annotated_commit
**
)
&
their_head
,
1
,
NULL
,
NULL
));
cl_git_pass
(
git_repository_index
(
&
index
,
repo
));
cl_assert
(
merge_test_index
(
index
,
merge_index_entries
,
5
));
git_index_free
(
index
);
git_annotated_commit_free
(
their_head
);
git_commit_free
(
our_commit
);
git_reference_free
(
their_ref
);
git_reference_free
(
our_ref
);
}
tests/notes/notes.c
View file @
e8bc8558
...
...
@@ -73,6 +73,128 @@ static int note_list_cb(
return
0
;
}
struct
note_create_payload
{
const
char
*
note_oid
;
const
char
*
object_oid
;
unsigned
seen
;
};
static
int
note_list_create_cb
(
const
git_oid
*
blob_oid
,
const
git_oid
*
annotated_obj_id
,
void
*
payload
)
{
git_oid
expected_note_oid
,
expected_target_oid
;
struct
note_create_payload
*
notes
=
payload
;
size_t
i
;
for
(
i
=
0
;
notes
[
i
].
note_oid
!=
NULL
;
i
++
)
{
cl_git_pass
(
git_oid_fromstr
(
&
expected_note_oid
,
notes
[
i
].
note_oid
));
if
(
git_oid_cmp
(
&
expected_note_oid
,
blob_oid
)
!=
0
)
continue
;
cl_git_pass
(
git_oid_fromstr
(
&
expected_target_oid
,
notes
[
i
].
object_oid
));
if
(
git_oid_cmp
(
&
expected_target_oid
,
annotated_obj_id
)
!=
0
)
continue
;
notes
[
i
].
seen
=
1
;
return
0
;
}
cl_fail
(
"Did not see expected note"
);
return
0
;
}
void
assert_notes_seen
(
struct
note_create_payload
payload
[],
size_t
n
)
{
size_t
seen
=
0
,
i
;
for
(
i
=
0
;
payload
[
i
].
note_oid
!=
NULL
;
i
++
)
{
if
(
payload
[
i
].
seen
)
seen
++
;
}
cl_assert_equal_i
(
seen
,
n
);
}
void
test_notes_notes__can_create_a_note
(
void
)
{
git_oid
note_oid
;
static
struct
note_create_payload
can_create_a_note
[]
=
{
{
"1c9b1bc36730582a42d56eeee0dc58673d7ae869"
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
,
0
},
{
NULL
,
NULL
,
0
}
};
create_note
(
&
note_oid
,
"refs/notes/i-can-see-dead-notes"
,
can_create_a_note
[
0
].
object_oid
,
"I decorate 4a20
\n
"
);
cl_git_pass
(
git_note_foreach
(
_repo
,
"refs/notes/i-can-see-dead-notes"
,
note_list_create_cb
,
&
can_create_a_note
));
assert_notes_seen
(
can_create_a_note
,
1
);
}
void
test_notes_notes__can_create_a_note_from_commit
(
void
)
{
git_oid
oid
;
git_oid
notes_commit_out
;
git_reference
*
ref
;
static
struct
note_create_payload
can_create_a_note_from_commit
[]
=
{
{
"1c9b1bc36730582a42d56eeee0dc58673d7ae869"
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
,
0
},
{
NULL
,
NULL
,
0
}
};
cl_git_pass
(
git_oid_fromstr
(
&
oid
,
can_create_a_note_from_commit
[
0
].
object_oid
));
cl_git_pass
(
git_note_commit_create
(
&
notes_commit_out
,
NULL
,
_repo
,
NULL
,
_sig
,
_sig
,
&
oid
,
"I decorate 4a20
\n
"
,
1
));
/* create_from_commit will not update any ref,
* so we must manually create the ref, that points to the commit */
cl_git_pass
(
git_reference_create
(
&
ref
,
_repo
,
"refs/notes/i-can-see-dead-notes"
,
&
notes_commit_out
,
0
,
NULL
));
cl_git_pass
(
git_note_foreach
(
_repo
,
"refs/notes/i-can-see-dead-notes"
,
note_list_create_cb
,
&
can_create_a_note_from_commit
));
assert_notes_seen
(
can_create_a_note_from_commit
,
1
);
git_reference_free
(
ref
);
}
/* Test that we can create a note from a commit, given an existing commit */
void
test_notes_notes__can_create_a_note_from_commit_given_an_existing_commit
(
void
)
{
git_oid
oid
;
git_oid
notes_commit_out
;
git_commit
*
existing_notes_commit
=
NULL
;
git_reference
*
ref
;
static
struct
note_create_payload
can_create_a_note_from_commit_given_an_existing_commit
[]
=
{
{
"1c9b1bc36730582a42d56eeee0dc58673d7ae869"
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
,
0
},
{
"1aaf94147c21f981e0a20bf57b89137c5a6aae52"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
,
0
},
{
NULL
,
NULL
,
0
}
};
cl_git_pass
(
git_oid_fromstr
(
&
oid
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
));
cl_git_pass
(
git_note_commit_create
(
&
notes_commit_out
,
NULL
,
_repo
,
NULL
,
_sig
,
_sig
,
&
oid
,
"I decorate 4a20
\n
"
,
0
));
cl_git_pass
(
git_oid_fromstr
(
&
oid
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
));
git_commit_lookup
(
&
existing_notes_commit
,
_repo
,
&
notes_commit_out
);
cl_assert
(
existing_notes_commit
);
cl_git_pass
(
git_note_commit_create
(
&
notes_commit_out
,
NULL
,
_repo
,
existing_notes_commit
,
_sig
,
_sig
,
&
oid
,
"I decorate 9fd7
\n
"
,
0
));
/* create_from_commit will not update any ref,
* so we must manually create the ref, that points to the commit */
cl_git_pass
(
git_reference_create
(
&
ref
,
_repo
,
"refs/notes/i-can-see-dead-notes"
,
&
notes_commit_out
,
0
,
NULL
));
cl_git_pass
(
git_note_foreach
(
_repo
,
"refs/notes/i-can-see-dead-notes"
,
note_list_create_cb
,
&
can_create_a_note_from_commit_given_an_existing_commit
));
assert_notes_seen
(
can_create_a_note_from_commit_given_an_existing_commit
,
2
);
git_commit_free
(
existing_notes_commit
);
git_reference_free
(
ref
);
}
/*
* $ git notes --ref i-can-see-dead-notes add -m "I decorate a65f" a65fedf39aefe402d3bb6e24df4d4f5fe4547750
* $ git notes --ref i-can-see-dead-notes add -m "I decorate c478" c47800c7266a2be04c571c04d5a6614691ea99bd
...
...
@@ -253,6 +375,71 @@ static char *messages[] = {
#define MESSAGES_COUNT (sizeof(messages)/sizeof(messages[0])) - 1
/* Test that we can read a note */
void
test_notes_notes__can_read_a_note
(
void
)
{
git_oid
note_oid
,
target_oid
;
git_note
*
note
;
create_note
(
&
note_oid
,
"refs/notes/i-can-see-dead-notes"
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
,
"I decorate 4a20
\n
"
);
cl_git_pass
(
git_oid_fromstr
(
&
target_oid
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
));
cl_git_pass
(
git_note_read
(
&
note
,
_repo
,
"refs/notes/i-can-see-dead-notes"
,
&
target_oid
));
cl_assert_equal_s
(
git_note_message
(
note
),
"I decorate 4a20
\n
"
);
git_note_free
(
note
);
}
/* Test that we can read a note with from commit api */
void
test_notes_notes__can_read_a_note_from_a_commit
(
void
)
{
git_oid
oid
,
notes_commit_oid
;
git_commit
*
notes_commit
;
git_note
*
note
;
cl_git_pass
(
git_oid_fromstr
(
&
oid
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
));
cl_git_pass
(
git_note_commit_create
(
&
notes_commit_oid
,
NULL
,
_repo
,
NULL
,
_sig
,
_sig
,
&
oid
,
"I decorate 4a20
\n
"
,
1
));
git_commit_lookup
(
&
notes_commit
,
_repo
,
&
notes_commit_oid
);
cl_assert
(
notes_commit
);
cl_git_pass
(
git_note_commit_read
(
&
note
,
_repo
,
notes_commit
,
&
oid
));
cl_assert_equal_s
(
git_note_message
(
note
),
"I decorate 4a20
\n
"
);
git_commit_free
(
notes_commit
);
git_note_free
(
note
);
}
/* Test that we can read a commit with no note fails */
void
test_notes_notes__attempt_to_read_a_note_from_a_commit_with_no_note_fails
(
void
)
{
git_oid
oid
,
notes_commit_oid
;
git_commit
*
notes_commit
;
git_note
*
note
;
cl_git_pass
(
git_oid_fromstr
(
&
oid
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
));
cl_git_pass
(
git_note_commit_create
(
&
notes_commit_oid
,
NULL
,
_repo
,
NULL
,
_sig
,
_sig
,
&
oid
,
"I decorate 4a20
\n
"
,
1
));
git_commit_lookup
(
&
notes_commit
,
_repo
,
&
notes_commit_oid
);
cl_git_pass
(
git_note_commit_remove
(
&
notes_commit_oid
,
_repo
,
notes_commit
,
_sig
,
_sig
,
&
oid
));
git_commit_free
(
notes_commit
);
git_commit_lookup
(
&
notes_commit
,
_repo
,
&
notes_commit_oid
);
cl_assert
(
notes_commit
);
cl_git_fail_with
(
GIT_ENOTFOUND
,
git_note_commit_read
(
&
note
,
_repo
,
notes_commit
,
&
oid
));
git_commit_free
(
notes_commit
);
}
/*
* $ git ls-tree refs/notes/fanout
* 040000 tree 4b22b35d44b5a4f589edf3dc89196399771796ea 84
...
...
@@ -298,6 +485,50 @@ void test_notes_notes__can_read_a_note_in_an_existing_fanout(void)
git_note_free
(
note
);
}
/* Can remove a note */
void
test_notes_notes__can_remove_a_note
(
void
)
{
git_oid
note_oid
,
target_oid
;
git_note
*
note
;
create_note
(
&
note_oid
,
"refs/notes/i-can-see-dead-notes"
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
,
"I decorate 4a20
\n
"
);
cl_git_pass
(
git_oid_fromstr
(
&
target_oid
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
));
cl_git_pass
(
git_note_remove
(
_repo
,
"refs/notes/i-can-see-dead-notes"
,
_sig
,
_sig
,
&
target_oid
));
cl_git_fail
(
git_note_read
(
&
note
,
_repo
,
"refs/notes/i-can-see-dead-notes"
,
&
target_oid
));
}
/* Can remove a note from a commit */
void
test_notes_notes__can_remove_a_note_from_commit
(
void
)
{
git_oid
oid
,
notes_commit_oid
;
git_note
*
note
=
NULL
;
git_commit
*
existing_notes_commit
;
git_reference
*
ref
;
cl_git_pass
(
git_oid_fromstr
(
&
oid
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
));
cl_git_pass
(
git_note_commit_create
(
&
notes_commit_oid
,
NULL
,
_repo
,
NULL
,
_sig
,
_sig
,
&
oid
,
"I decorate 4a20
\n
"
,
0
));
git_commit_lookup
(
&
existing_notes_commit
,
_repo
,
&
notes_commit_oid
);
cl_assert
(
existing_notes_commit
);
cl_git_pass
(
git_note_commit_remove
(
&
notes_commit_oid
,
_repo
,
existing_notes_commit
,
_sig
,
_sig
,
&
oid
));
/* remove_from_commit will not update any ref,
* so we must manually create the ref, that points to the commit */
cl_git_pass
(
git_reference_create
(
&
ref
,
_repo
,
"refs/notes/i-can-see-dead-notes"
,
&
notes_commit_oid
,
0
,
NULL
));
cl_git_fail
(
git_note_read
(
&
note
,
_repo
,
"refs/notes/i-can-see-dead-notes"
,
&
oid
));
git_commit_free
(
existing_notes_commit
);
git_reference_free
(
ref
);
git_note_free
(
note
);
}
void
test_notes_notes__can_remove_a_note_in_an_existing_fanout
(
void
)
{
git_oid
target_oid
;
...
...
@@ -388,3 +619,46 @@ void test_notes_notes__empty_iterate(void)
cl_git_fail
(
git_note_iterator_new
(
&
iter
,
_repo
,
"refs/notes/commits"
));
}
void
test_notes_notes__iterate_from_commit
(
void
)
{
git_note_iterator
*
iter
;
git_note
*
note
;
git_oid
note_id
,
annotated_id
;
git_oid
oids
[
2
];
git_oid
notes_commit_oids
[
2
];
git_commit
*
notes_commits
[
2
];
const
char
*
note_message
[]
=
{
"I decorate a65f
\n
"
,
"I decorate c478
\n
"
};
int
i
,
err
;
cl_git_pass
(
git_oid_fromstr
(
&
(
oids
[
0
]),
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
));
cl_git_pass
(
git_oid_fromstr
(
&
(
oids
[
1
]),
"c47800c7266a2be04c571c04d5a6614691ea99bd"
));
cl_git_pass
(
git_note_commit_create
(
&
notes_commit_oids
[
0
],
NULL
,
_repo
,
NULL
,
_sig
,
_sig
,
&
(
oids
[
0
]),
note_message
[
0
],
0
));
git_commit_lookup
(
&
notes_commits
[
0
],
_repo
,
&
notes_commit_oids
[
0
]);
cl_assert
(
notes_commits
[
0
]);
cl_git_pass
(
git_note_commit_create
(
&
notes_commit_oids
[
1
],
NULL
,
_repo
,
notes_commits
[
0
],
_sig
,
_sig
,
&
(
oids
[
1
]),
note_message
[
1
],
0
));
git_commit_lookup
(
&
notes_commits
[
1
],
_repo
,
&
notes_commit_oids
[
1
]);
cl_assert
(
notes_commits
[
1
]);
cl_git_pass
(
git_note_commit_iterator_new
(
&
iter
,
notes_commits
[
1
]));
for
(
i
=
0
;
(
err
=
git_note_next
(
&
note_id
,
&
annotated_id
,
iter
))
>=
0
;
++
i
)
{
cl_git_pass
(
git_note_commit_read
(
&
note
,
_repo
,
notes_commits
[
1
],
&
annotated_id
));
cl_assert_equal_s
(
git_note_message
(
note
),
note_message
[
i
]);
git_note_free
(
note
);
}
cl_assert_equal_i
(
GIT_ITEROVER
,
err
);
cl_assert_equal_i
(
2
,
i
);
git_note_iterator_free
(
iter
);
git_commit_free
(
notes_commits
[
0
]);
git_commit_free
(
notes_commits
[
1
]);
}
tests/odb/largefiles.c
0 → 100644
View file @
e8bc8558
#include "clar_libgit2.h"
#include "git2/odb_backend.h"
static
git_repository
*
repo
;
static
git_odb
*
odb
;
void
test_odb_largefiles__initialize
(
void
)
{
repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
cl_git_pass
(
git_repository_odb
(
&
odb
,
repo
));
}
void
test_odb_largefiles__cleanup
(
void
)
{
git_odb_free
(
odb
);
cl_git_sandbox_cleanup
();
}
static
void
writefile
(
git_oid
*
oid
)
{
static
git_odb_stream
*
stream
;
git_buf
buf
=
GIT_BUF_INIT
;
size_t
i
;
for
(
i
=
0
;
i
<
3041
;
i
++
)
cl_git_pass
(
git_buf_puts
(
&
buf
,
"Hello, world.
\n
"
));
cl_git_pass
(
git_odb_open_wstream
(
&
stream
,
odb
,
5368709122
,
GIT_OBJ_BLOB
));
for
(
i
=
0
;
i
<
126103
;
i
++
)
cl_git_pass
(
git_odb_stream_write
(
stream
,
buf
.
ptr
,
buf
.
size
));
cl_git_pass
(
git_odb_stream_finalize_write
(
oid
,
stream
));
git_odb_stream_free
(
stream
);
git_buf_free
(
&
buf
);
}
void
test_odb_largefiles__write_from_memory
(
void
)
{
git_oid
expected
,
oid
;
git_buf
buf
=
GIT_BUF_INIT
;
size_t
i
;
#ifndef GIT_ARCH_64
cl_skip
();
#endif
if
(
!
cl_is_env_set
(
"GITTEST_INVASIVE_FS_SIZE"
)
||
!
cl_is_env_set
(
"GITTEST_INVASIVE_MEMORY"
)
||
!
cl_is_env_set
(
"GITTEST_SLOW"
))
cl_skip
();
for
(
i
=
0
;
i
<
(
3041
*
126103
);
i
++
)
cl_git_pass
(
git_buf_puts
(
&
buf
,
"Hello, world.
\n
"
));
git_oid_fromstr
(
&
expected
,
"3fb56989cca483b21ba7cb0a6edb229d10e1c26c"
);
cl_git_pass
(
git_odb_write
(
&
oid
,
odb
,
buf
.
ptr
,
buf
.
size
,
GIT_OBJ_BLOB
));
cl_assert_equal_oid
(
&
expected
,
&
oid
);
}
void
test_odb_largefiles__streamwrite
(
void
)
{
git_oid
expected
,
oid
;
if
(
!
cl_is_env_set
(
"GITTEST_INVASIVE_FS_SIZE"
)
||
!
cl_is_env_set
(
"GITTEST_SLOW"
))
cl_skip
();
git_oid_fromstr
(
&
expected
,
"3fb56989cca483b21ba7cb0a6edb229d10e1c26c"
);
writefile
(
&
oid
);
cl_assert_equal_oid
(
&
expected
,
&
oid
);
}
void
test_odb_largefiles__read_into_memory
(
void
)
{
git_oid
oid
;
git_odb_object
*
obj
;
#ifndef GIT_ARCH_64
cl_skip
();
#endif
if
(
!
cl_is_env_set
(
"GITTEST_INVASIVE_FS_SIZE"
)
||
!
cl_is_env_set
(
"GITTEST_INVASIVE_MEMORY"
)
||
!
cl_is_env_set
(
"GITTEST_SLOW"
))
cl_skip
();
writefile
(
&
oid
);
cl_git_pass
(
git_odb_read
(
&
obj
,
odb
,
&
oid
));
git_odb_object_free
(
obj
);
}
void
test_odb_largefiles__read_into_memory_rejected_on_32bit
(
void
)
{
git_oid
oid
;
git_odb_object
*
obj
=
NULL
;
#ifdef GIT_ARCH_64
cl_skip
();
#endif
if
(
!
cl_is_env_set
(
"GITTEST_INVASIVE_FS_SIZE"
)
||
!
cl_is_env_set
(
"GITTEST_INVASIVE_MEMORY"
)
||
!
cl_is_env_set
(
"GITTEST_SLOW"
))
cl_skip
();
writefile
(
&
oid
);
cl_git_fail
(
git_odb_read
(
&
obj
,
odb
,
&
oid
));
git_odb_object_free
(
obj
);
}
tests/pack/indexer.c
View file @
e8bc8558
...
...
@@ -41,6 +41,29 @@ static const unsigned char thin_pack[] = {
static
const
unsigned
int
thin_pack_len
=
78
;
/*
* Packfile with one object. It references an object which is not in the
* packfile and has a corrupt length (states the deltified stream is 1 byte
* long, where it is actually 6).
*/
static
const
unsigned
char
corrupt_thin_pack
[]
=
{
0x50
,
0x41
,
0x43
,
0x4b
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x01
,
0x71
,
0xe6
,
0x8f
,
0xe8
,
0x12
,
0x9b
,
0x54
,
0x6b
,
0x10
,
0x1a
,
0xee
,
0x95
,
0x10
,
0xc5
,
0x32
,
0x8e
,
0x7f
,
0x21
,
0xca
,
0x1d
,
0x18
,
0x78
,
0x9c
,
0x63
,
0x62
,
0x66
,
0x4e
,
0xcb
,
0xcf
,
0x07
,
0x00
,
0x02
,
0xac
,
0x01
,
0x4d
,
0x07
,
0x67
,
0x03
,
0xc5
,
0x40
,
0x99
,
0x49
,
0xb1
,
0x3b
,
0x7d
,
0xae
,
0x9b
,
0x0e
,
0xdd
,
0xde
,
0xc6
,
0x76
,
0x43
,
0x24
,
0x64
};
static
const
unsigned
int
corrupt_thin_pack_len
=
67
;
/*
* Packfile with a missing trailer.
*/
static
const
unsigned
char
missing_trailer_pack
[]
=
{
0x50
,
0x41
,
0x43
,
0x4b
,
0x00
,
0x00
,
0x00
,
0x03
,
0x00
,
0x50
,
0xf4
,
0x3b
,
};
static
const
unsigned
int
missing_trailer_pack_len
=
12
;
/*
* Packfile that causes the packfile stream to open in a way in which it leaks
* the stream reader.
*/
...
...
@@ -71,6 +94,22 @@ void test_pack_indexer__out_of_order(void)
git_indexer_free
(
idx
);
}
void
test_pack_indexer__missing_trailer
(
void
)
{
git_indexer
*
idx
=
0
;
git_transfer_progress
stats
=
{
0
};
cl_git_pass
(
git_indexer_new
(
&
idx
,
"."
,
0
,
NULL
,
NULL
,
NULL
));
cl_git_pass
(
git_indexer_append
(
idx
,
missing_trailer_pack
,
missing_trailer_pack_len
,
&
stats
));
cl_git_fail
(
git_indexer_commit
(
idx
,
&
stats
));
cl_assert
(
giterr_last
()
!=
NULL
);
cl_assert_equal_i
(
giterr_last
()
->
klass
,
GITERR_INDEXER
);
git_indexer_free
(
idx
);
}
void
test_pack_indexer__leaky
(
void
)
{
git_indexer
*
idx
=
0
;
...
...
@@ -153,6 +192,35 @@ void test_pack_indexer__fix_thin(void)
}
}
void
test_pack_indexer__corrupt_length
(
void
)
{
git_indexer
*
idx
=
NULL
;
git_transfer_progress
stats
=
{
0
};
git_repository
*
repo
;
git_odb
*
odb
;
git_oid
id
,
should_id
;
cl_git_pass
(
git_repository_init
(
&
repo
,
"thin.git"
,
true
));
cl_git_pass
(
git_repository_odb
(
&
odb
,
repo
));
/* Store the missing base into your ODB so the indexer can fix the pack */
cl_git_pass
(
git_odb_write
(
&
id
,
odb
,
base_obj
,
base_obj_len
,
GIT_OBJ_BLOB
));
git_oid_fromstr
(
&
should_id
,
"e68fe8129b546b101aee9510c5328e7f21ca1d18"
);
cl_assert_equal_oid
(
&
should_id
,
&
id
);
cl_git_pass
(
git_indexer_new
(
&
idx
,
"."
,
0
,
odb
,
NULL
,
NULL
));
cl_git_pass
(
git_indexer_append
(
idx
,
corrupt_thin_pack
,
corrupt_thin_pack_len
,
&
stats
));
cl_git_fail
(
git_indexer_commit
(
idx
,
&
stats
));
cl_assert
(
giterr_last
()
!=
NULL
);
cl_assert_equal_i
(
giterr_last
()
->
klass
,
GITERR_ZLIB
);
git_indexer_free
(
idx
);
git_odb_free
(
odb
);
git_repository_free
(
repo
);
}
static
int
find_tmp_file_recurs
(
void
*
opaque
,
git_buf
*
path
)
{
int
error
=
0
;
...
...
tests/patch/parse.c
View file @
e8bc8558
...
...
@@ -102,3 +102,9 @@ void test_patch_parse__invalid_patches_fails(void)
strlen
(
PATCH_CORRUPT_MISSING_HUNK_HEADER
),
NULL
));
}
void
test_patch_parse__files_with_whitespaces_succeeds
(
void
)
{
git_patch
*
patch
;
cl_git_pass
(
git_patch_from_buffer
(
&
patch
,
PATCH_NAME_WHITESPACE
,
strlen
(
PATCH_NAME_WHITESPACE
),
NULL
));
git_patch_free
(
patch
);
}
tests/patch/patch_common.h
View file @
e8bc8558
...
...
@@ -575,6 +575,16 @@
"+added line with no nl\n" \
"\\ No newline at end of file\n"
#define PATCH_NAME_WHITESPACE \
"diff --git a/file with spaces.txt b/file with spaces.txt\n" \
"index 9432026..83759c0 100644\n" \
"--- a/file with spaces.txt\n" \
"+++ b/file with spaces.txt\n" \
"@@ -0,3 +0,2 @@\n" \
" and this\n" \
"-is additional context\n" \
" below it!\n" \
#define PATCH_CORRUPT_GIT_HEADER \
"diff --git a/file.txt\n" \
"index 9432026..0f39b9a 100644\n" \
...
...
tests/refs/iterator.c
View file @
e8bc8558
...
...
@@ -6,12 +6,12 @@ static git_repository *repo;
void
test_refs_iterator__initialize
(
void
)
{
cl_git_pass
(
git_repository_open
(
&
repo
,
cl_fixture
(
"testrepo.git"
))
);
repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
}
void
test_refs_iterator__cleanup
(
void
)
{
git_repository_free
(
repo
);
cl_git_sandbox_cleanup
(
);
}
static
const
char
*
refnames
[]
=
{
...
...
@@ -36,6 +36,36 @@ static const char *refnames[] = {
"refs/tags/taggerless"
,
"refs/tags/test"
,
"refs/tags/wrapped_tag"
,
NULL
};
static
const
char
*
refnames_with_symlink
[]
=
{
"refs/heads/br2"
,
"refs/heads/cannot-fetch"
,
"refs/heads/chomped"
,
"refs/heads/haacked"
,
"refs/heads/link/a"
,
"refs/heads/link/b"
,
"refs/heads/link/c"
,
"refs/heads/link/d"
,
"refs/heads/master"
,
"refs/heads/not-good"
,
"refs/heads/packed"
,
"refs/heads/packed-test"
,
"refs/heads/subtrees"
,
"refs/heads/test"
,
"refs/heads/track-local"
,
"refs/heads/trailing"
,
"refs/notes/fanout"
,
"refs/remotes/test/master"
,
"refs/tags/annotated_tag_to_blob"
,
"refs/tags/e90810b"
,
"refs/tags/hard_tag"
,
"refs/tags/point_to_blob"
,
"refs/tags/taggerless"
,
"refs/tags/test"
,
"refs/tags/wrapped_tag"
,
NULL
};
static
int
refcmp_cb
(
const
void
*
a
,
const
void
*
b
)
...
...
@@ -46,21 +76,21 @@ static int refcmp_cb(const void *a, const void *b)
return
strcmp
(
refa
->
name
,
refb
->
name
);
}
static
void
assert_all_refnames_match
(
git_vector
*
output
)
static
void
assert_all_refnames_match
(
const
char
**
expected
,
git_vector
*
names
)
{
size_t
i
;
git_reference
*
ref
;
cl_assert_equal_sz
(
output
->
length
,
ARRAY_SIZE
(
refnames
));
git_vector_sort
(
output
);
git_vector_sort
(
names
);
git_vector_foreach
(
output
,
i
,
ref
)
{
cl_assert_equal_s
(
ref
->
name
,
refnames
[
i
]);
git_vector_foreach
(
names
,
i
,
ref
)
{
cl_assert
(
expected
[
i
]
!=
NULL
);
cl_assert_equal_s
(
expected
[
i
],
ref
->
name
);
git_reference_free
(
ref
);
}
cl_assert
(
expected
[
i
]
==
NULL
);
git_vector_free
(
output
);
git_vector_free
(
names
);
}
void
test_refs_iterator__list
(
void
)
...
...
@@ -82,7 +112,7 @@ void test_refs_iterator__list(void)
git_reference_iterator_free
(
iter
);
assert_all_refnames_match
(
&
output
);
assert_all_refnames_match
(
refnames
,
&
output
);
}
void
test_refs_iterator__empty
(
void
)
...
...
@@ -115,7 +145,29 @@ void test_refs_iterator__foreach(void)
git_vector
output
;
cl_git_pass
(
git_vector_init
(
&
output
,
32
,
&
refcmp_cb
));
cl_git_pass
(
git_reference_foreach
(
repo
,
refs_foreach_cb
,
&
output
));
assert_all_refnames_match
(
&
output
);
assert_all_refnames_match
(
refnames
,
&
output
);
}
void
test_refs_iterator__foreach_through_symlink
(
void
)
{
git_vector
output
;
#ifdef GIT_WIN32
cl_skip
();
#endif
cl_git_pass
(
git_vector_init
(
&
output
,
32
,
&
refcmp_cb
));
cl_git_pass
(
p_mkdir
(
"refs"
,
0777
));
cl_git_mkfile
(
"refs/a"
,
"1234567890123456789012345678901234567890"
);
cl_git_mkfile
(
"refs/b"
,
"1234567890123456789012345678901234567890"
);
cl_git_mkfile
(
"refs/c"
,
"1234567890123456789012345678901234567890"
);
cl_git_mkfile
(
"refs/d"
,
"1234567890123456789012345678901234567890"
);
cl_git_pass
(
p_symlink
(
"../../../refs"
,
"testrepo.git/refs/heads/link"
));
cl_git_pass
(
git_reference_foreach
(
repo
,
refs_foreach_cb
,
&
output
));
assert_all_refnames_match
(
refnames_with_symlink
,
&
output
);
}
static
int
refs_foreach_cancel_cb
(
git_reference
*
reference
,
void
*
payload
)
...
...
@@ -156,12 +208,11 @@ void test_refs_iterator__foreach_name(void)
cl_git_pass
(
git_reference_foreach_name
(
repo
,
refs_foreach_name_cb
,
&
output
));
cl_assert_equal_sz
(
output
.
length
,
ARRAY_SIZE
(
refnames
));
git_vector_sort
(
&
output
);
git_vector_foreach
(
&
output
,
i
,
name
)
{
cl_assert
_equal_s
(
name
,
refnames
[
i
]
);
git__free
(
name
);
cl_assert
(
refnames
[
i
]
!=
NULL
);
cl_assert_equal_s
(
refnames
[
i
],
name
);
}
git_vector_free
(
&
output
);
...
...
@@ -194,7 +245,7 @@ void test_refs_iterator__concurrent_delete(void)
const
char
*
name
;
int
error
;
git_repository_free
(
repo
);
cl_git_sandbox_cleanup
(
);
repo
=
cl_git_sandbox_init
(
"testrepo"
);
cl_git_pass
(
git_reference_iterator_new
(
&
iter
,
repo
));
...
...
@@ -215,7 +266,4 @@ void test_refs_iterator__concurrent_delete(void)
cl_assert_equal_i
(
GIT_ITEROVER
,
error
);
cl_assert_equal_i
(
full_count
,
concurrent_count
);
cl_git_sandbox_cleanup
();
repo
=
NULL
;
}
tests/resources/merge-resolve/.gitted/objects/50/c5dc8cdfe40c688eb0a0e23be54dd57cae2e78
0 → 100644
View file @
e8bc8558
File added
tests/resources/merge-resolve/.gitted/objects/7a/a825857f87aea74ddf13d954568aa30dfcdeb4
0 → 100644
View file @
e8bc8558
File added
tests/resources/merge-resolve/.gitted/refs/heads/delete-submodule
0 → 100644
View file @
e8bc8558
50c5dc8cdfe40c688eb0a0e23be54dd57cae2e78
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