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
b8802146
Commit
b8802146
authored
May 01, 2012
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'carlosmn/remaining-errors' into new-error-handling
Conflicts: src/refspec.c
parents
5587a9c9
3aa351ea
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
299 additions
and
311 deletions
+299
-311
include/git2/errors.h
+2
-0
src/commit.c
+4
-2
src/delta-apply.c
+10
-5
src/filter.c
+2
-2
src/object.c
+15
-15
src/refspec.c
+19
-18
src/tag.c
+104
-116
src/tree.c
+131
-147
tests-clar/object/tree/frompath.c
+12
-6
No files found.
include/git2/errors.h
View file @
b8802146
...
...
@@ -133,6 +133,8 @@ typedef enum {
GITERR_INDEX
,
GITERR_OBJECT
,
GITERR_NET
,
GITERR_TAG
,
GITERR_TREE
,
}
git_error_class
;
/**
...
...
src/commit.c
View file @
b8802146
...
...
@@ -310,8 +310,10 @@ int git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n)
assert
(
commit
);
parent_oid
=
git_vector_get
(
&
commit
->
parent_oids
,
n
);
if
(
parent_oid
==
NULL
)
return
git__throw
(
GIT_ENOTFOUND
,
"Parent %u does not exist"
,
n
);
if
(
parent_oid
==
NULL
)
{
giterr_set
(
GITERR_INVALID
,
"Parent %u does not exist"
,
n
);
return
GIT_ENOTFOUND
;
}
return
git_commit_lookup
(
parent
,
commit
->
object
.
repo
,
parent_oid
);
}
...
...
src/delta-apply.c
View file @
b8802146
...
...
@@ -51,11 +51,15 @@ int git__delta_apply(
* if not we would underflow while accessing data from the
* base object, resulting in data corruption or segfault.
*/
if
((
hdr_sz
(
&
base_sz
,
&
delta
,
delta_end
)
<
0
)
||
(
base_sz
!=
base_len
))
return
git__throw
(
GIT_ERROR
,
"Failed to apply delta. Base size does not match given data"
);
if
((
hdr_sz
(
&
base_sz
,
&
delta
,
delta_end
)
<
0
)
||
(
base_sz
!=
base_len
))
{
giterr_set
(
GITERR_INVALID
,
"Failed to apply delta. Base size does not match given data"
);
return
-
1
;
}
if
(
hdr_sz
(
&
res_sz
,
&
delta
,
delta_end
)
<
0
)
return
git__throw
(
GIT_ERROR
,
"Failed to apply delta. Base size does not match given data"
);
if
(
hdr_sz
(
&
res_sz
,
&
delta
,
delta_end
)
<
0
)
{
giterr_set
(
GITERR_INVALID
,
"Failed to apply delta. Base size does not match given data"
);
return
-
1
;
}
if
((
res_dp
=
git__malloc
(
res_sz
+
1
))
==
NULL
)
return
GIT_ENOMEM
;
...
...
@@ -111,5 +115,6 @@ int git__delta_apply(
fail:
git__free
(
out
->
data
);
out
->
data
=
NULL
;
return
git__throw
(
GIT_ERROR
,
"Failed to apply delta"
);
giterr_set
(
GITERR_INVALID
,
"Failed to apply delta"
);
return
-
1
;
}
src/filter.c
View file @
b8802146
...
...
@@ -95,8 +95,8 @@ int git_filters_load(git_vector *filters, git_repository *repo, const char *path
if
(
error
<
GIT_SUCCESS
)
return
error
;
}
else
{
return
git__throw
(
GIT_ENOTIMPLEMENTED
,
"Worktree filters are not implemented yet"
)
;
giterr_set
(
GITERR_INVALID
,
"Worktree filters are not implemented yet"
);
return
GIT_ENOTIMPLEMENTED
;
}
return
(
int
)
filters
->
length
;
...
...
src/object.c
View file @
b8802146
...
...
@@ -68,7 +68,8 @@ static int create_object(git_object **object_out, git_otype type)
break
;
default:
return
git__throw
(
GIT_EINVALIDTYPE
,
"The given type is invalid"
);
giterr_set
(
GITERR_INVALID
,
"The given type is invalid"
);
return
-
1
;
}
object
->
type
=
type
;
...
...
@@ -92,8 +93,7 @@ int git_object_lookup_prefix(
assert
(
repo
&&
object_out
&&
id
);
if
(
len
<
GIT_OID_MINPREFIXLEN
)
return
git__throw
(
GIT_EAMBIGUOUS
,
"Failed to lookup object. Prefix length is lower than %d."
,
GIT_OID_MINPREFIXLEN
);
return
GIT_EAMBIGUOUS
;
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
if
(
error
<
GIT_SUCCESS
)
...
...
@@ -110,13 +110,12 @@ int git_object_lookup_prefix(
if
(
object
!=
NULL
)
{
if
(
type
!=
GIT_OBJ_ANY
&&
type
!=
object
->
type
)
{
git_object_free
(
object
);
return
git__throw
(
GIT_EINVALIDTYPE
,
"Failed to lookup object. "
"The given type does not match the type on the ODB"
);
giterr_set
(
GITERR_INVALID
,
"The given type does not match the type in ODB"
);
return
-
1
;
}
*
object_out
=
object
;
return
GIT_SUCCESS
;
return
0
;
}
/* Object was not found in the cache, let's explore the backends.
...
...
@@ -147,18 +146,19 @@ int git_object_lookup_prefix(
error
=
git_odb_read_prefix
(
&
odb_obj
,
odb
,
&
short_oid
,
len
);
}
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to lookup object"
)
;
if
(
error
<
0
)
return
-
1
;
if
(
type
!=
GIT_OBJ_ANY
&&
type
!=
odb_obj
->
raw
.
type
)
{
git_odb_object_free
(
odb_obj
);
return
git__throw
(
GIT_EINVALIDTYPE
,
"Failed to lookup object. The given type does not match the type on the ODB"
);
giterr_set
(
GITERR_INVALID
,
"The given type does not match the type on the ODB"
);
return
-
1
;
}
type
=
odb_obj
->
raw
.
type
;
if
(
(
error
=
create_object
(
&
object
,
type
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to lookup object"
)
;
if
(
create_object
(
&
object
,
type
)
<
0
)
return
-
1
;
/* Initialize parent object */
git_oid_cpy
(
&
object
->
cached
.
oid
,
&
odb_obj
->
cached
.
oid
);
...
...
@@ -187,13 +187,13 @@ int git_object_lookup_prefix(
git_odb_object_free
(
odb_obj
);
if
(
error
<
GIT_SUCCESS
)
{
if
(
error
<
0
)
{
git_object__free
(
object
);
return
git__rethrow
(
error
,
"Failed to lookup object"
)
;
return
-
1
;
}
*
object_out
=
git_cache_try_store
(
&
repo
->
objects
,
object
);
return
GIT_SUCCESS
;
return
0
;
}
int
git_object_lookup
(
git_object
**
object_out
,
git_repository
*
repo
,
const
git_oid
*
id
,
git_otype
type
)
{
...
...
src/refspec.c
View file @
b8802146
...
...
@@ -25,24 +25,21 @@ int git_refspec_parse(git_refspec *refspec, const char *str)
delim
=
strchr
(
str
,
':'
);
if
(
delim
==
NULL
)
{
refspec
->
src
=
git__strdup
(
str
);
if
(
refspec
->
src
==
NULL
)
return
GIT_ENOMEM
;
return
GIT_SUCCESS
;
GITERR_CHECK_ALLOC
(
refspec
->
src
);
return
0
;
}
refspec
->
src
=
git__strndup
(
str
,
delim
-
str
);
if
(
refspec
->
src
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
refspec
->
src
);
refspec
->
dst
=
git__strdup
(
delim
+
1
);
if
(
refspec
->
dst
==
NULL
)
{
git__free
(
refspec
->
src
);
refspec
->
src
=
NULL
;
return
GIT_ENOMEM
;
return
-
1
;
}
return
GIT_SUCCESS
;
return
0
;
}
const
char
*
git_refspec_src
(
const
git_refspec
*
refspec
)
...
...
@@ -65,8 +62,10 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
size_t
baselen
,
namelen
;
baselen
=
strlen
(
spec
->
dst
);
if
(
outlen
<=
baselen
)
return
git__throw
(
GIT_EINVALIDREFNAME
,
"Reference name too long"
);
if
(
outlen
<=
baselen
)
{
giterr_set
(
GITERR_INVALID
,
"Reference name too long"
);
return
GIT_ESHORTBUFFER
;
}
/*
* No '*' at the end means that it's mapped to one specific local
...
...
@@ -74,7 +73,7 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
*/
if
(
spec
->
dst
[
baselen
-
1
]
!=
'*'
)
{
memcpy
(
out
,
spec
->
dst
,
baselen
+
1
);
/* include '\0' */
return
GIT_SUCCESS
;
return
0
;
}
/* There's a '*' at the end, so remove its length */
...
...
@@ -85,32 +84,34 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
namelen
=
strlen
(
name
);
if
(
outlen
<=
baselen
+
namelen
)
return
git__throw
(
GIT_EINVALIDREFNAME
,
"Reference name too long"
);
if
(
outlen
<=
baselen
+
namelen
)
{
giterr_set
(
GITERR_INVALID
,
"Reference name too long"
);
return
GIT_ESHORTBUFFER
;
}
memcpy
(
out
,
spec
->
dst
,
baselen
);
memcpy
(
out
+
baselen
,
name
,
namelen
+
1
);
return
GIT_SUCCESS
;
return
0
;
}
int
git_refspec_transform_r
(
git_buf
*
out
,
const
git_refspec
*
spec
,
const
char
*
name
)
{
if
(
git_buf_sets
(
out
,
spec
->
dst
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
if
(
git_buf_sets
(
out
,
spec
->
dst
)
<
0
)
return
-
1
;
/*
* No '*' at the end means that it's mapped to one specific local
* branch, so no actual transformation is needed.
*/
if
(
git_buf_len
(
out
)
>
0
&&
out
->
ptr
[
git_buf_len
(
out
)
-
1
]
!=
'*'
)
return
GIT_SUCCESS
;
return
0
;
git_buf_truncate
(
out
,
git_buf_len
(
out
)
-
1
);
/* remove trailing '*' */
git_buf_puts
(
out
,
name
+
strlen
(
spec
->
src
)
-
1
);
if
(
git_buf_oom
(
out
))
return
GIT_ENOMEM
;
return
-
1
;
return
0
;
}
...
...
src/tag.c
View file @
b8802146
...
...
@@ -61,6 +61,12 @@ const char *git_tag_message(git_tag *t)
return
t
->
message
;
}
static
int
tag_error
(
const
char
*
str
)
{
giterr_set
(
GITERR_TAG
,
"Failed to parse tag. %s"
,
str
);
return
-
1
;
}
int
git_tag__parse_buffer
(
git_tag
*
tag
,
const
char
*
buffer
,
size_t
length
)
{
static
const
char
*
tag_types
[]
=
{
...
...
@@ -70,18 +76,17 @@ int git_tag__parse_buffer(git_tag *tag, const char *buffer, size_t length)
unsigned
int
i
;
size_t
text_len
;
char
*
search
;
int
error
;
const
char
*
buffer_end
=
buffer
+
length
;
if
(
(
error
=
git_oid__parse
(
&
tag
->
target
,
&
buffer
,
buffer_end
,
"object "
)
)
<
0
)
return
git__rethrow
(
error
,
"Failed to parse tag.
Object field invalid"
);
if
(
git_oid__parse
(
&
tag
->
target
,
&
buffer
,
buffer_end
,
"object "
)
<
0
)
return
tag_error
(
"
Object field invalid"
);
if
(
buffer
+
5
>=
buffer_end
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tag.
Object too short"
);
return
tag_error
(
"
Object too short"
);
if
(
memcmp
(
buffer
,
"type "
,
5
)
!=
0
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tag.
Type field not found"
);
return
tag_error
(
"
Type field not found"
);
buffer
+=
5
;
tag
->
type
=
GIT_OBJ_BAD
;
...
...
@@ -90,7 +95,7 @@ int git_tag__parse_buffer(git_tag *tag, const char *buffer, size_t length)
size_t
type_length
=
strlen
(
tag_types
[
i
]);
if
(
buffer
+
type_length
>=
buffer_end
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tag.
Object too short"
);
return
tag_error
(
"
Object too short"
);
if
(
memcmp
(
buffer
,
tag_types
[
i
],
type_length
)
==
0
)
{
tag
->
type
=
i
;
...
...
@@ -100,25 +105,24 @@ int git_tag__parse_buffer(git_tag *tag, const char *buffer, size_t length)
}
if
(
tag
->
type
==
GIT_OBJ_BAD
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tag.
Invalid object type"
);
return
tag_error
(
"
Invalid object type"
);
if
(
buffer
+
4
>=
buffer_end
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tag.
Object too short"
);
return
tag_error
(
"
Object too short"
);
if
(
memcmp
(
buffer
,
"tag "
,
4
)
!=
0
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tag.
Tag field not found"
);
return
tag_error
(
"
Tag field not found"
);
buffer
+=
4
;
search
=
memchr
(
buffer
,
'\n'
,
buffer_end
-
buffer
);
if
(
search
==
NULL
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tag.
Object too short"
);
return
tag_error
(
"
Object too short"
);
text_len
=
search
-
buffer
;
tag
->
tag_name
=
git__malloc
(
text_len
+
1
);
if
(
tag
->
tag_name
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
tag
->
tag_name
);
memcpy
(
tag
->
tag_name
,
buffer
,
text_len
);
tag
->
tag_name
[
text_len
]
=
'\0'
;
...
...
@@ -128,27 +132,24 @@ int git_tag__parse_buffer(git_tag *tag, const char *buffer, size_t length)
tag
->
tagger
=
NULL
;
if
(
*
buffer
!=
'\n'
)
{
tag
->
tagger
=
git__malloc
(
sizeof
(
git_signature
));
if
(
tag
->
tagger
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
tag
->
tagger
);
if
((
error
=
git_signature__parse
(
tag
->
tagger
,
&
buffer
,
buffer_end
,
"tagger "
,
'\n'
)
!=
0
))
{
return
git__rethrow
(
error
,
"Failed to parse tag"
);
}
if
(
git_signature__parse
(
tag
->
tagger
,
&
buffer
,
buffer_end
,
"tagger "
,
'\n'
)
<
0
)
return
-
1
;
}
if
(
*
buffer
!=
'\n'
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tag.
No new line before message"
);
return
tag_error
(
"
No new line before message"
);
text_len
=
buffer_end
-
++
buffer
;
tag
->
message
=
git__malloc
(
text_len
+
1
);
if
(
tag
->
message
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
tag
->
message
);
memcpy
(
tag
->
message
,
buffer
,
text_len
);
tag
->
message
[
text_len
]
=
'\0'
;
return
GIT_SUCCESS
;
return
0
;
}
static
int
retrieve_tag_reference
(
...
...
@@ -162,17 +163,28 @@ static int retrieve_tag_reference(
*
tag_reference_out
=
NULL
;
error
=
git_buf_joinpath
(
ref_name_out
,
GIT_REFS_TAGS_DIR
,
tag_name
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to retrieve tag reference"
);
if
(
git_buf_joinpath
(
ref_name_out
,
GIT_REFS_TAGS_DIR
,
tag_name
)
<
0
)
return
-
1
;
error
=
git_reference_lookup
(
&
tag_ref
,
repo
,
ref_name_out
->
ptr
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to retrieve tag reference"
);
return
error
;
/* Be it not foundo or corrupted */
*
tag_reference_out
=
tag_ref
;
return
GIT_SUCCESS
;
return
0
;
}
static
int
retrieve_tag_reference_oid
(
git_oid
*
oid
,
git_buf
*
ref_name_out
,
git_repository
*
repo
,
const
char
*
tag_name
)
{
if
(
git_buf_joinpath
(
ref_name_out
,
GIT_REFS_TAGS_DIR
,
tag_name
)
<
0
)
return
-
1
;
return
git_reference_name_to_oid
(
oid
,
repo
,
ref_name_out
->
ptr
);
}
static
int
write_tag_annotation
(
...
...
@@ -183,7 +195,6 @@ static int write_tag_annotation(
const
git_signature
*
tagger
,
const
char
*
message
)
{
int
error
=
GIT_SUCCESS
;
git_buf
tag
=
GIT_BUF_INIT
;
git_odb
*
odb
;
...
...
@@ -194,24 +205,20 @@ static int write_tag_annotation(
git_buf_putc
(
&
tag
,
'\n'
);
git_buf_puts
(
&
tag
,
message
);
if
(
git_buf_oom
(
&
tag
))
{
git_buf_free
(
&
tag
);
return
git__throw
(
GIT_ENOMEM
,
"Not enough memory to build the tag data"
);
}
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
if
(
error
<
GIT_SUCCESS
)
{
git_buf_free
(
&
tag
);
return
error
;
}
if
(
git_buf_oom
(
&
tag
))
goto
on_error
;
error
=
git_odb_write
(
oid
,
odb
,
tag
.
ptr
,
tag
.
size
,
GIT_OBJ_TAG
);
git_buf_free
(
&
tag
)
;
if
(
git_repository_odb__weakptr
(
&
odb
,
repo
)
<
0
)
goto
on_error
;
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to create tag annotation"
)
;
if
(
git_odb_write
(
oid
,
odb
,
tag
.
ptr
,
tag
.
size
,
GIT_OBJ_TAG
)
<
0
)
goto
on_error
;
return
error
;
git_buf_free
(
&
tag
);
return
0
;
on_error:
git_buf_free
(
&
tag
);
return
-
1
;
}
static
int
git_tag_create__internal
(
...
...
@@ -227,51 +234,38 @@ static int git_tag_create__internal(
git_reference
*
new_ref
=
NULL
;
git_buf
ref_name
=
GIT_BUF_INIT
;
int
error
,
should_update_ref
=
0
;
const
char
*
errmsg
=
"Failed to create tag"
;
int
error
;
assert
(
repo
&&
tag_name
&&
target
);
assert
(
!
create_tag_annotation
||
(
tagger
&&
message
));
if
(
git_object_owner
(
target
)
!=
repo
)
return
git__throw
(
GIT_EINVALIDARGS
,
"The given target does not belong to this repository"
);
if
(
git_object_owner
(
target
)
!=
repo
)
{
giterr_set
(
GITERR_INVALID
,
"The given target does not belong to this repository"
);
return
-
1
;
}
error
=
retrieve_tag_reference
(
&
new_ref
,
&
ref_name
,
repo
,
tag_name
);
error
=
retrieve_tag_reference
_oid
(
oid
,
&
ref_name
,
repo
,
tag_name
);
if
(
error
<
GIT_SUCCESS
&&
error
!=
GIT_ENOTFOUND
)
goto
cleanup
;
return
-
1
;
/** Ensure the tag name doesn't conflict with an already existing
* reference unless overwriting has explictly been requested **/
if
(
new_ref
!=
NULL
)
{
if
(
!
allow_ref_overwrite
)
{
git_oid_cpy
(
oid
,
git_reference_oid
(
new_ref
));
error
=
GIT_EEXISTS
;
errmsg
=
"Tag already exists"
;
goto
cleanup
;
}
else
{
should_update_ref
=
1
;
}
if
(
error
==
0
&&
!
allow_ref_overwrite
)
{
git_buf_free
(
&
ref_name
);
giterr_set
(
GITERR_TAG
,
"Tag already exists"
);
return
GIT_EEXISTS
;
}
if
(
create_tag_annotation
)
{
if
(
(
error
=
write_tag_annotation
(
oid
,
repo
,
tag_name
,
target
,
tagger
,
message
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
write_tag_annotation
(
oid
,
repo
,
tag_name
,
target
,
tagger
,
message
)
<
0
)
return
-
1
;
}
else
git_oid_cpy
(
oid
,
git_object_id
(
target
));
if
(
!
should_update_ref
)
error
=
git_reference_create_oid
(
&
new_ref
,
repo
,
ref_name
.
ptr
,
oid
,
0
);
else
error
=
git_reference_set_oid
(
new_ref
,
oid
);
error
=
git_reference_create_oid
(
&
new_ref
,
repo
,
ref_name
.
ptr
,
oid
,
allow_ref_overwrite
);
cleanup:
git_reference_free
(
new_ref
);
git_buf_free
(
&
ref_name
);
if
(
error
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"%s"
,
errmsg
);
return
error
;
}
...
...
@@ -300,8 +294,7 @@ int git_tag_create_lightweight(
int
git_tag_create_frombuffer
(
git_oid
*
oid
,
git_repository
*
repo
,
const
char
*
buffer
,
int
allow_ref_overwrite
)
{
git_tag
tag
;
int
error
,
should_update_ref
=
0
;
const
char
*
errmsg
=
"Failed to create tag"
;
int
error
;
git_odb
*
odb
;
git_odb_stream
*
stream
;
git_odb_object
*
target_obj
;
...
...
@@ -313,71 +306,66 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
memset
(
&
tag
,
0
,
sizeof
(
tag
));
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
if
(
git_repository_odb__weakptr
(
&
odb
,
repo
)
<
0
)
return
-
1
;
/* validate the buffer */
if
(
(
error
=
git_tag__parse_buffer
(
&
tag
,
buffer
,
strlen
(
buffer
)))
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_tag__parse_buffer
(
&
tag
,
buffer
,
strlen
(
buffer
))
<
0
)
return
-
1
;
/* validate the target */
if
(
(
error
=
git_odb_read
(
&
target_obj
,
odb
,
&
tag
.
target
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_odb_read
(
&
target_obj
,
odb
,
&
tag
.
target
)
<
0
)
goto
on_error
;
if
(
tag
.
type
!=
target_obj
->
raw
.
type
)
{
error
=
GIT_EINVALIDTYPE
;
errmsg
=
"The type for the given target is invalid"
;
goto
cleanup
;
giterr_set
(
GITERR_TAG
,
"The type for the given target is invalid"
);
goto
on_error
;
}
git_odb_object_free
(
target_obj
);
error
=
retrieve_tag_reference
(
&
new_ref
,
&
ref_name
,
repo
,
tag
.
tag_name
);
error
=
retrieve_tag_reference_oid
(
oid
,
&
ref_name
,
repo
,
tag
.
tag_name
);
if
(
error
<
GIT_SUCCESS
&&
error
!=
GIT_ENOTFOUND
)
goto
cleanup
;
goto
on_error
;
/* We don't need these objects after this */
git_signature_free
(
tag
.
tagger
);
git__free
(
tag
.
tag_name
);
git__free
(
tag
.
message
);
git_odb_object_free
(
target_obj
);
/** Ensure the tag name doesn't conflict with an already existing
* reference unless overwriting has explictly been requested **/
if
(
new_ref
!=
NULL
)
{
if
(
!
allow_ref_overwrite
)
{
git_oid_cpy
(
oid
,
git_reference_oid
(
new_ref
));
error
=
GIT_EEXISTS
;
errmsg
=
"Tag already exists"
;
goto
cleanup
;
}
else
{
should_update_ref
=
1
;
}
if
(
error
==
0
&&
!
allow_ref_overwrite
)
{
giterr_set
(
GITERR_TAG
,
"Tag already exists"
);
return
GIT_EEXISTS
;
}
/* write the buffer */
if
(
(
error
=
git_odb_open_wstream
(
&
stream
,
odb
,
strlen
(
buffer
),
GIT_OBJ_TAG
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_odb_open_wstream
(
&
stream
,
odb
,
strlen
(
buffer
),
GIT_OBJ_TAG
)
<
0
)
return
-
1
;
stream
->
write
(
stream
,
buffer
,
strlen
(
buffer
));
error
=
stream
->
finalize_write
(
oid
,
stream
);
stream
->
free
(
stream
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
error
<
0
)
{
git_buf_free
(
&
ref_name
);
return
-
1
;
}
if
(
!
should_update_ref
)
error
=
git_reference_create_oid
(
&
new_ref
,
repo
,
ref_name
.
ptr
,
oid
,
0
);
else
error
=
git_reference_set_oid
(
new_ref
,
oid
);
error
=
git_reference_create_oid
(
&
new_ref
,
repo
,
ref_name
.
ptr
,
oid
,
allow_ref_overwrite
);
cleanup:
git_reference_free
(
new_ref
);
git_signature_free
(
tag
.
tagger
);
git__free
(
tag
.
tag_name
);
git__free
(
tag
.
message
);
git_buf_free
(
&
ref_name
);
if
(
error
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"%s"
,
errmsg
);
return
error
;
on_error:
git_signature_free
(
tag
.
tagger
);
git__free
(
tag
.
tag_name
);
git__free
(
tag
.
message
);
git_odb_object_free
(
target_obj
);
return
-
1
;
}
int
git_tag_delete
(
git_repository
*
repo
,
const
char
*
tag_name
)
...
...
@@ -390,8 +378,8 @@ int git_tag_delete(git_repository *repo, const char *tag_name)
git_buf_free
(
&
ref_name
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to delete tag"
)
;
if
(
error
<
0
)
return
-
1
;
return
git_reference_delete
(
tag_ref
);
}
...
...
@@ -414,13 +402,13 @@ static int tag_list_cb(const char *tag_name, void *payload)
tag_filter_data
*
filter
;
if
(
git__prefixcmp
(
tag_name
,
GIT_REFS_TAGS_DIR
)
!=
0
)
return
GIT_SUCCESS
;
return
0
;
filter
=
(
tag_filter_data
*
)
payload
;
if
(
!*
filter
->
pattern
||
p_fnmatch
(
filter
->
pattern
,
tag_name
+
GIT_REFS_TAGS_DIR_LEN
,
0
)
==
GIT_SUCCESS
)
return
git_vector_insert
(
filter
->
taglist
,
git__strdup
(
tag_name
));
return
GIT_SUCCESS
;
return
0
;
}
int
git_tag_list_match
(
git_strarray
*
tag_names
,
const
char
*
pattern
,
git_repository
*
repo
)
...
...
@@ -438,14 +426,14 @@ int git_tag_list_match(git_strarray *tag_names, const char *pattern, git_reposit
filter
.
pattern
=
pattern
;
error
=
git_reference_foreach
(
repo
,
GIT_REF_OID
|
GIT_REF_PACKED
,
&
tag_list_cb
,
(
void
*
)
&
filter
);
if
(
error
<
GIT_SUCCESS
)
{
if
(
error
<
0
)
{
git_vector_free
(
&
taglist
);
return
git__rethrow
(
error
,
"Failed to list tags"
)
;
return
-
1
;
}
tag_names
->
strings
=
(
char
**
)
taglist
.
contents
;
tag_names
->
count
=
taglist
.
length
;
return
GIT_SUCCESS
;
return
0
;
}
int
git_tag_list
(
git_strarray
*
tag_names
,
git_repository
*
repo
)
...
...
src/tree.c
View file @
b8802146
...
...
@@ -201,41 +201,38 @@ unsigned int git_tree_entrycount(git_tree *tree)
return
tree
->
entries
.
length
;
}
static
int
tree_
parse_buffer
(
git_tree
*
tree
,
const
char
*
buffer
,
const
char
*
buffer_end
)
static
int
tree_
error
(
const
char
*
str
)
{
int
error
=
GIT_SUCCESS
;
giterr_set
(
GITERR_TREE
,
"%s"
,
str
);
return
-
1
;
}
if
(
git_vector_init
(
&
tree
->
entries
,
DEFAULT_TREE_SIZE
,
entry_sort_cmp
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
static
int
tree_parse_buffer
(
git_tree
*
tree
,
const
char
*
buffer
,
const
char
*
buffer_end
)
{
if
(
git_vector_init
(
&
tree
->
entries
,
DEFAULT_TREE_SIZE
,
entry_sort_cmp
)
<
0
)
return
-
1
;
while
(
buffer
<
buffer_end
)
{
git_tree_entry
*
entry
;
int
tmp
;
entry
=
git__calloc
(
1
,
sizeof
(
git_tree_entry
));
if
(
entry
==
NULL
)
{
error
=
GIT_ENOMEM
;
break
;
}
GITERR_CHECK_ALLOC
(
entry
);
if
(
git_vector_insert
(
&
tree
->
entries
,
entry
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
if
(
git_vector_insert
(
&
tree
->
entries
,
entry
)
<
0
)
return
-
1
;
if
(
git__strtol32
(
&
tmp
,
buffer
,
&
buffer
,
8
)
<
GIT_SUCCESS
||
if
(
git__strtol32
(
&
tmp
,
buffer
,
&
buffer
,
8
)
<
0
||
!
buffer
||
!
valid_attributes
(
tmp
))
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tree. Can't parse attributes"
);
return
tree_error
(
"Failed to parse tree. Can't parse attributes"
);
entry
->
attr
=
tmp
;
if
(
*
buffer
++
!=
' '
)
{
error
=
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tree. Object it corrupted"
);
break
;
}
if
(
*
buffer
++
!=
' '
)
return
tree_error
(
"Failed to parse tree. Object is corrupted"
);
if
(
memchr
(
buffer
,
0
,
buffer_end
-
buffer
)
==
NULL
)
{
error
=
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse tree. Object it corrupted"
);
break
;
}
if
(
memchr
(
buffer
,
0
,
buffer_end
-
buffer
)
==
NULL
)
return
tree_error
(
"Failed to parse tree. Object is corrupted"
);
entry
->
filename
=
git__strdup
(
buffer
);
entry
->
filename_len
=
strlen
(
buffer
);
...
...
@@ -249,7 +246,7 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf
buffer
+=
GIT_OID_RAWSZ
;
}
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to parse buffer"
)
;
return
0
;
}
int
git_tree__parse
(
git_tree
*
tree
,
git_odb_object
*
obj
)
...
...
@@ -280,10 +277,9 @@ static int append_entry(git_treebuilder *bld, const char *filename, const git_oi
{
git_tree_entry
*
entry
;
if
((
entry
=
git__malloc
(
sizeof
(
git_tree_entry
)))
==
NULL
)
return
GIT_ENOMEM
;
entry
=
git__calloc
(
1
,
sizeof
(
git_tree_entry
));
GITERR_CHECK_ALLOC
(
entry
)
;
memset
(
entry
,
0x0
,
sizeof
(
git_tree_entry
));
entry
->
filename
=
git__strdup
(
filename
);
entry
->
filename_len
=
strlen
(
entry
->
filename
);
...
...
@@ -291,9 +287,9 @@ static int append_entry(git_treebuilder *bld, const char *filename, const git_oi
entry
->
attr
=
attributes
;
if
(
git_vector_insert
(
&
bld
->
entries
,
entry
)
<
0
)
return
GIT_ENOMEM
;
return
-
1
;
return
GIT_SUCCESS
;
return
0
;
}
static
int
write_tree
(
...
...
@@ -318,7 +314,7 @@ static int write_tree(
error
=
git_treebuilder_create
(
&
bld
,
NULL
);
if
(
bld
==
NULL
)
{
return
GIT_ENOMEM
;
return
-
1
;
}
/*
...
...
@@ -354,16 +350,13 @@ static int write_tree(
char
*
subdir
,
*
last_comp
;
subdir
=
git__strndup
(
entry
->
path
,
next_slash
-
entry
->
path
);
if
(
subdir
==
NULL
)
{
error
=
GIT_ENOMEM
;
goto
cleanup
;
}
GITERR_CHECK_ALLOC
(
subdir
);
/* Write out the subtree */
written
=
write_tree
(
&
sub_oid
,
repo
,
index
,
subdir
,
i
);
if
(
written
<
0
)
{
error
=
git__rethrow
(
written
,
"Failed to write subtree %s"
,
subdir
);
goto
cleanup
;
tree_error
(
"Failed to write subtree"
);
goto
on_error
;
}
else
{
i
=
written
-
1
;
/* -1 because of the loop increment */
}
...
...
@@ -382,51 +375,49 @@ static int write_tree(
}
error
=
append_entry
(
bld
,
last_comp
,
&
sub_oid
,
S_IFDIR
);
git__free
(
subdir
);
if
(
error
<
GIT_SUCCESS
)
{
error
=
git__rethrow
(
error
,
"Failed to insert dir"
);
goto
cleanup
;
if
(
error
<
0
)
{
tree_error
(
"Failed to insert dir"
);
goto
on_error
;
}
}
else
{
error
=
append_entry
(
bld
,
filename
,
&
entry
->
oid
,
entry
->
mode
);
if
(
error
<
GIT_SUCCESS
)
{
error
=
git__rethrow
(
error
,
"Failed to insert file"
);
if
(
error
<
0
)
{
tree_error
(
"Failed to insert file"
);
goto
on_error
;
}
}
}
error
=
git_treebuilder_write
(
oid
,
repo
,
bld
);
if
(
error
<
GIT_SUCCESS
)
error
=
git__rethrow
(
error
,
"Failed to write tree to db"
);
if
(
git_treebuilder_write
(
oid
,
repo
,
bld
)
<
0
)
goto
on_error
;
cleanup:
git_treebuilder_free
(
bld
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
else
return
i
;
on_error:
git_treebuilder_free
(
bld
);
return
-
1
;
}
int
git_tree_create_fromindex
(
git_oid
*
oid
,
git_index
*
index
)
{
int
ret
;
git_repository
*
repo
;
int
error
;
repo
=
(
git_repository
*
)
GIT_REFCOUNT_OWNER
(
index
);
if
(
repo
==
NULL
)
return
git__throw
(
GIT_EBAREINDEX
,
"Failed to create tree. "
return
tree_error
(
"Failed to create tree. "
"The index file is not backed up by an existing repository"
);
if
(
index
->
tree
!=
NULL
&&
index
->
tree
->
entries
>=
0
)
{
git_oid_cpy
(
oid
,
&
index
->
tree
->
oid
);
return
GIT_SUCCESS
;
return
0
;
}
/* The tree cache didn't help us */
error
=
write_tree
(
oid
,
repo
,
index
,
""
,
0
);
return
(
error
<
GIT_SUCCESS
)
?
git__rethrow
(
error
,
"Failed to create tree"
)
:
GIT_SUCCESS
;
ret
=
write_tree
(
oid
,
repo
,
index
,
""
,
0
);
return
ret
<
0
?
ret
:
0
;
}
static
void
sort_entries
(
git_treebuilder
*
bld
)
...
...
@@ -442,30 +433,29 @@ int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
assert
(
builder_p
);
bld
=
git__calloc
(
1
,
sizeof
(
git_treebuilder
));
if
(
bld
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
bld
);
if
(
source
!=
NULL
)
source_entries
=
source
->
entries
.
length
;
if
(
git_vector_init
(
&
bld
->
entries
,
source_entries
,
entry_sort_cmp
)
<
GIT_SUCCESS
)
{
git__free
(
bld
);
return
GIT_ENOMEM
;
}
if
(
git_vector_init
(
&
bld
->
entries
,
source_entries
,
entry_sort_cmp
)
<
0
)
goto
on_error
;
if
(
source
!=
NULL
)
{
for
(
i
=
0
;
i
<
source
->
entries
.
length
;
++
i
)
{
git_tree_entry
*
entry_src
=
source
->
entries
.
contents
[
i
];
if
(
append_entry
(
bld
,
entry_src
->
filename
,
&
entry_src
->
oid
,
entry_src
->
attr
)
<
0
)
{
git_treebuilder_free
(
bld
);
return
GIT_ENOMEM
;
}
if
(
append_entry
(
bld
,
entry_src
->
filename
,
&
entry_src
->
oid
,
entry_src
->
attr
)
<
0
)
goto
on_error
;
}
}
*
builder_p
=
bld
;
return
GIT_SUCCESS
;
return
0
;
on_error:
git_treebuilder_free
(
bld
);
return
-
1
;
}
int
git_treebuilder_insert
(
git_tree_entry
**
entry_out
,
git_treebuilder
*
bld
,
const
char
*
filename
,
const
git_oid
*
id
,
unsigned
int
attributes
)
...
...
@@ -476,10 +466,10 @@ int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, con
assert
(
bld
&&
id
&&
filename
);
if
(
!
valid_attributes
(
attributes
))
return
git__throw
(
GIT_ERROR
,
"Failed to insert entry. Invalid attributes"
);
return
tree_error
(
"Failed to insert entry. Invalid attributes"
);
if
(
!
valid_entry_name
(
filename
))
return
git__throw
(
GIT_ERROR
,
"Failed to insert entry. Invalid name for a tree entry"
);
return
tree_error
(
"Failed to insert entry. Invalid name for a tree entry"
);
pos
=
tree_key_search
(
&
bld
->
entries
,
filename
);
...
...
@@ -488,10 +478,9 @@ int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, con
if
(
entry
->
removed
)
entry
->
removed
=
0
;
}
else
{
if
((
entry
=
git__malloc
(
sizeof
(
git_tree_entry
)))
==
NULL
)
return
GIT_ENOMEM
;
entry
=
git__calloc
(
1
,
sizeof
(
git_tree_entry
));
GITERR_CHECK_ALLOC
(
entry
)
;
memset
(
entry
,
0x0
,
sizeof
(
git_tree_entry
));
entry
->
filename
=
git__strdup
(
filename
);
entry
->
filename_len
=
strlen
(
entry
->
filename
);
}
...
...
@@ -501,13 +490,13 @@ int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, con
if
(
pos
==
GIT_ENOTFOUND
)
{
if
(
git_vector_insert
(
&
bld
->
entries
,
entry
)
<
0
)
return
GIT_ENOMEM
;
return
-
1
;
}
if
(
entry_out
!=
NULL
)
*
entry_out
=
entry
;
return
GIT_SUCCESS
;
return
0
;
}
static
git_tree_entry
*
treebuilder_get
(
git_treebuilder
*
bld
,
const
char
*
filename
)
...
...
@@ -538,16 +527,15 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename)
git_tree_entry
*
remove_ptr
=
treebuilder_get
(
bld
,
filename
);
if
(
remove_ptr
==
NULL
||
remove_ptr
->
removed
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to remove entry. File isn't in the tree"
);
return
tree_error
(
"Failed to remove entry. File isn't in the tree"
);
remove_ptr
->
removed
=
1
;
return
GIT_SUCCESS
;
return
0
;
}
int
git_treebuilder_write
(
git_oid
*
oid
,
git_repository
*
repo
,
git_treebuilder
*
bld
)
{
unsigned
int
i
;
int
error
;
git_buf
tree
=
GIT_BUF_INIT
;
git_odb
*
odb
;
...
...
@@ -569,21 +557,22 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
git_buf_put
(
&
tree
,
(
char
*
)
entry
->
oid
.
id
,
GIT_OID_RAWSZ
);
}
if
(
git_buf_oom
(
&
tree
))
{
git_buf_free
(
&
tree
);
return
git__throw
(
GIT_ENOMEM
,
"Not enough memory to build the tree data"
);
}
if
(
git_buf_oom
(
&
tree
))
goto
on_error
;
if
(
git_repository_odb__weakptr
(
&
odb
,
repo
)
<
0
)
goto
on_error
;
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
if
(
error
<
GIT_SUCCESS
)
{
git_buf_free
(
&
tree
);
return
error
;
}
error
=
git_odb_write
(
oid
,
odb
,
tree
.
ptr
,
tree
.
size
,
GIT_OBJ_TREE
);
if
(
git_odb_write
(
oid
,
odb
,
tree
.
ptr
,
tree
.
size
,
GIT_OBJ_TREE
)
<
0
)
goto
on_error
;
git_buf_free
(
&
tree
);
return
0
;
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to write tree"
);
on_error:
git_buf_free
(
&
tree
);
return
-
1
;
}
void
git_treebuilder_filter
(
git_treebuilder
*
bld
,
int
(
*
filter
)(
const
git_tree_entry
*
,
void
*
),
void
*
payload
)
...
...
@@ -631,9 +620,11 @@ static int tree_frompath(
int
error
=
GIT_SUCCESS
;
git_tree
*
subtree
;
if
(
!*
(
treeentry_path
->
ptr
+
offset
))
return
git__rethrow
(
GIT_EINVALIDPATH
,
if
(
!*
(
treeentry_path
->
ptr
+
offset
))
{
giterr_set
(
GITERR_INVALID
,
"Invalid relative path to a tree entry '%s'."
,
treeentry_path
->
ptr
);
return
-
1
;
}
slash_pos
=
(
char
*
)
strchr
(
treeentry_path
->
ptr
+
offset
,
'/'
);
...
...
@@ -644,9 +635,11 @@ static int tree_frompath(
git_object_id
((
const
git_object
*
)
root
)
);
if
(
slash_pos
==
treeentry_path
->
ptr
+
offset
)
return
git__rethrow
(
GIT_EINVALIDPATH
,
if
(
slash_pos
==
treeentry_path
->
ptr
+
offset
)
{
giterr_set
(
GITERR_INVALID
,
"Invalid relative path to a tree entry '%s'."
,
treeentry_path
->
ptr
);
return
-
1
;
}
*
slash_pos
=
'\0'
;
...
...
@@ -655,14 +648,15 @@ static int tree_frompath(
if
(
slash_pos
!=
NULL
)
*
slash_pos
=
'/'
;
if
(
entry
==
NULL
)
return
git__rethrow
(
GIT_ENOTFOUND
,
if
(
entry
==
NULL
)
{
giterr_set
(
GITERR_TREE
,
"No tree entry can be found from "
"the given tree and relative path '%s'."
,
treeentry_path
->
ptr
);
return
GIT_ENOTFOUND
;
}
error
=
git_tree_lookup
(
&
subtree
,
root
->
object
.
repo
,
&
entry
->
oid
);
if
(
error
<
GIT_SUCCESS
)
if
(
git_tree_lookup
(
&
subtree
,
root
->
object
.
repo
,
&
entry
->
oid
)
<
0
)
return
error
;
error
=
tree_frompath
(
...
...
@@ -686,7 +680,7 @@ int git_tree_get_subtree(
assert
(
subtree
&&
root
&&
subtree_path
);
if
((
error
=
git_buf_sets
(
&
buffer
,
subtree_path
))
==
GIT_SUCCESS
)
if
((
error
=
git_buf_sets
(
&
buffer
,
subtree_path
))
==
0
)
error
=
tree_frompath
(
subtree
,
root
,
&
buffer
,
0
);
git_buf_free
(
&
buffer
);
...
...
@@ -722,18 +716,17 @@ static int tree_walk_post(
git_buf_putc
(
path
,
'/'
);
if
(
git_buf_oom
(
path
))
return
GIT_ENOMEM
;
return
-
1
;
error
=
tree_walk_post
(
subtree
,
callback
,
path
,
payload
);
if
(
error
<
GIT_SUCCESS
)
break
;
if
(
tree_walk_post
(
subtree
,
callback
,
path
,
payload
)
<
0
)
return
-
1
;
git_buf_truncate
(
path
,
path_len
);
git_tree_free
(
subtree
);
}
}
return
error
;
return
0
;
}
int
git_tree_walk
(
git_tree
*
tree
,
git_treewalk_cb
callback
,
int
mode
,
void
*
payload
)
...
...
@@ -747,14 +740,12 @@ int git_tree_walk(git_tree *tree, git_treewalk_cb callback, int mode, void *payl
break
;
case
GIT_TREEWALK_PRE
:
error
=
git__throw
(
GIT_ENOTIMPLEMENTED
,
"Preorder tree walking is still not implemented"
);
break
;
tree_error
(
"Preorder tree walking is still not implemented"
);
return
GIT_ENOTIMPLEMENTED
;
default:
error
=
git__throw
(
GIT_EINVALIDARGS
,
"Invalid walking mode for tree walk"
);
break
;
giterr_set
(
GITERR_INVALID
,
"Invalid walking mode for tree walk"
);
return
-
1
;
}
git_buf_free
(
&
root_path
);
...
...
@@ -793,7 +784,7 @@ static int signal_additions(git_tree *tree, int start, int end, git_tree_diff_cb
{
git_tree_diff_data
diff
;
git_tree_entry
*
entry
;
int
i
,
error
;
int
i
;
if
(
end
<
0
)
end
=
git_tree_entrycount
(
tree
);
...
...
@@ -803,12 +794,11 @@ static int signal_additions(git_tree *tree, int start, int end, git_tree_diff_cb
entry
=
git_vector_get
(
&
tree
->
entries
,
i
);
mark_add
(
&
diff
,
entry
);
error
=
cb
(
&
diff
,
data
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
if
(
cb
(
&
diff
,
data
)
<
0
)
return
-
1
;
}
return
GIT_SUCCESS
;
return
0
;
}
static
int
signal_addition
(
git_tree_entry
*
entry
,
git_tree_diff_cb
cb
,
void
*
data
)
...
...
@@ -826,7 +816,7 @@ static int signal_deletions(git_tree *tree, int start, int end, git_tree_diff_cb
{
git_tree_diff_data
diff
;
git_tree_entry
*
entry
;
int
i
,
error
;
int
i
;
if
(
end
<
0
)
end
=
git_tree_entrycount
(
tree
);
...
...
@@ -836,12 +826,11 @@ static int signal_deletions(git_tree *tree, int start, int end, git_tree_diff_cb
entry
=
git_vector_get
(
&
tree
->
entries
,
i
);
mark_del
(
&
diff
,
entry
);
error
=
cb
(
&
diff
,
data
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
if
(
cb
(
&
diff
,
data
)
<
0
)
return
-
1
;
}
return
GIT_SUCCESS
;
return
0
;
}
static
int
signal_deletion
(
git_tree_entry
*
entry
,
git_tree_diff_cb
cb
,
void
*
data
)
...
...
@@ -873,14 +862,14 @@ int git_tree_diff(git_tree *a, git_tree *b, git_tree_diff_cb cb, void *data)
unsigned
int
i_a
=
0
,
i_b
=
0
;
/* Counters for trees a and b */
git_tree_entry
*
entry_a
=
NULL
,
*
entry_b
=
NULL
;
git_tree_diff_data
diff
;
int
error
=
GIT_SUCCESS
,
cmp
;
int
cmp
;
while
(
1
)
{
entry_a
=
a
==
NULL
?
NULL
:
git_vector_get
(
&
a
->
entries
,
i_a
);
entry_b
=
b
==
NULL
?
NULL
:
git_vector_get
(
&
b
->
entries
,
i_b
);
if
(
!
entry_a
&&
!
entry_b
)
goto
exit
;
return
0
;
memset
(
&
diff
,
0x0
,
sizeof
(
git_tree_diff_data
));
...
...
@@ -911,29 +900,28 @@ int git_tree_diff(git_tree *a, git_tree *b, git_tree_diff_cb cb, void *data)
/* If they're not both dirs or both files, it's add + del */
if
(
S_ISDIR
(
entry_a
->
attr
)
!=
S_ISDIR
(
entry_b
->
attr
))
{
if
(
(
error
=
signal_addition
(
entry_a
,
cb
,
data
)
)
<
0
)
goto
exit
;
if
(
(
error
=
signal_deletion
(
entry_b
,
cb
,
data
)
)
<
0
)
goto
exit
;
if
(
signal_addition
(
entry_a
,
cb
,
data
)
<
0
)
return
-
1
;
if
(
signal_deletion
(
entry_b
,
cb
,
data
)
<
0
)
return
-
1
;
}
/* Otherwise consider it a modification */
if
(
(
error
=
signal_modification
(
entry_a
,
entry_b
,
cb
,
data
)
)
<
0
)
goto
exit
;
if
(
signal_modification
(
entry_a
,
entry_b
,
cb
,
data
)
<
0
)
return
-
1
;
}
else
if
(
cmp
<
0
)
{
i_a
++
;
if
(
(
error
=
signal_deletion
(
entry_a
,
cb
,
data
)
)
<
0
)
goto
exit
;
if
(
signal_deletion
(
entry_a
,
cb
,
data
)
<
0
)
return
-
1
;
}
else
if
(
cmp
>
0
)
{
i_b
++
;
if
(
(
error
=
signal_addition
(
entry_b
,
cb
,
data
)
)
<
0
)
goto
exit
;
if
(
signal_addition
(
entry_b
,
cb
,
data
)
<
0
)
return
-
1
;
}
}
exit:
return
error
;
return
0
;
}
struct
diff_index_cbdata
{
...
...
@@ -978,53 +966,49 @@ static int diff_index_cb(const char *root, git_tree_entry *tentry, void *data)
git_index_entry
*
ientry
=
git_index_get
(
cbdata
->
index
,
cbdata
->
i
);
git_tree_entry
fake_entry
;
git_buf
fn_buf
=
GIT_BUF_INIT
;
int
cmp
,
error
=
GIT_SUCCESS
;
int
cmp
;
if
(
entry_is_tree
(
tentry
))
return
GIT_SUCCESS
;
return
0
;
if
(
!
ientry
)
return
signal_deletion
(
tentry
,
cbdata
->
cb
,
cbdata
->
data
);
git_buf_puts
(
&
fn_buf
,
root
);
git_buf_puts
(
&
fn_buf
,
tentry
->
filename
);
if
(
!
ientry
)
{
error
=
signal_deletion
(
tentry
,
cbdata
->
cb
,
cbdata
->
data
);
git_buf_free
(
&
fn_buf
);
goto
exit
;
}
/* Like with 'git diff-index', the index is the right side*/
cmp
=
strcmp
(
git_buf_cstr
(
&
fn_buf
),
ientry
->
path
);
git_buf_free
(
&
fn_buf
);
if
(
cmp
==
0
)
{
cbdata
->
i
++
;
if
(
!
cmp_tentry_ientry
(
tentry
,
ientry
))
goto
exit
;
return
0
;
/* modification */
make_tentry
(
&
fake_entry
,
ientry
);
if
(
(
error
=
signal_modification
(
tentry
,
&
fake_entry
,
cbdata
->
cb
,
cbdata
->
data
)
)
<
0
)
goto
exit
;
if
(
signal_modification
(
tentry
,
&
fake_entry
,
cbdata
->
cb
,
cbdata
->
data
)
<
0
)
return
-
1
;
}
else
if
(
cmp
<
0
)
{
/* deletion */
memcpy
(
&
fake_entry
,
tentry
,
sizeof
(
git_tree_entry
));
if
(
(
error
=
signal_deletion
(
tentry
,
cbdata
->
cb
,
cbdata
->
data
)
)
<
0
)
goto
exit
;
if
(
signal_deletion
(
tentry
,
cbdata
->
cb
,
cbdata
->
data
)
<
0
)
return
-
1
;
}
else
{
/* addition */
cbdata
->
i
++
;
make_tentry
(
&
fake_entry
,
ientry
);
if
(
(
error
=
signal_addition
(
&
fake_entry
,
cbdata
->
cb
,
cbdata
->
data
)
)
<
0
)
goto
exit
;
if
(
signal_addition
(
&
fake_entry
,
cbdata
->
cb
,
cbdata
->
data
)
<
0
)
return
-
1
;
/*
* The index has an addition. This means that we need to use
* the next entry in the index without advancing the tree
* walker, so call ourselves with the same tree state.
*/
if
(
(
error
=
diff_index_cb
(
root
,
tentry
,
data
)
)
<
0
)
goto
exit
;
if
(
diff_index_cb
(
root
,
tentry
,
data
)
<
0
)
return
-
1
;
;
}
exit:
return
error
;
return
0
;
}
int
git_tree_diff_index_recursive
(
git_tree
*
tree
,
git_index
*
index
,
git_tree_diff_cb
cb
,
void
*
data
)
...
...
tests-clar/object/tree/frompath.c
View file @
b8802146
...
...
@@ -40,6 +40,12 @@ static void assert_tree_from_path(git_tree *root, const char *path, int expected
git_tree_free
(
containing_tree
);
}
static
void
assert_tree_from_path_klass
(
git_tree
*
root
,
const
char
*
path
,
int
expected_result
,
const
char
*
expected_raw_oid
)
{
assert_tree_from_path
(
root
,
path
,
GIT_ERROR
,
expected_raw_oid
);
cl_assert
(
git_error_last
()
->
klass
==
expected_result
);
}
void
test_object_tree_frompath__retrieve_tree_from_path_to_treeentry
(
void
)
{
/* Will return self if given a one path segment... */
...
...
@@ -66,10 +72,10 @@ void test_object_tree_frompath__fail_when_processing_an_unknown_tree_segment(voi
void
test_object_tree_frompath__fail_when_processing_an_invalid_path
(
void
)
{
assert_tree_from_path
(
tree
,
"/"
,
GIT_EINVALIDPATH
,
NULL
);
assert_tree_from_path
(
tree
,
"/ab"
,
GIT_EINVALIDPATH
,
NULL
);
assert_tree_from_path
(
tree
,
"/ab/de"
,
GIT_EINVALIDPATH
,
NULL
);
assert_tree_from_path
(
tree
,
"ab/"
,
GIT_EINVALIDPATH
,
NULL
);
assert_tree_from_path
(
tree
,
"ab//de"
,
GIT_EINVALIDPATH
,
NULL
);
assert_tree_from_path
(
tree
,
"ab/de/"
,
GIT_EINVALIDPATH
,
NULL
);
assert_tree_from_path
_klass
(
tree
,
"/"
,
GITERR_INVALID
,
NULL
);
assert_tree_from_path
_klass
(
tree
,
"/ab"
,
GITERR_INVALID
,
NULL
);
assert_tree_from_path
_klass
(
tree
,
"/ab/de"
,
GITERR_INVALID
,
NULL
);
assert_tree_from_path
_klass
(
tree
,
"ab/"
,
GITERR_INVALID
,
NULL
);
assert_tree_from_path
_klass
(
tree
,
"ab//de"
,
GITERR_INVALID
,
NULL
);
assert_tree_from_path
_klass
(
tree
,
"ab/de/"
,
GITERR_INVALID
,
NULL
);
}
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