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
55c197cd
Commit
55c197cd
authored
Apr 11, 2011
by
Carlos Martín Nieto
Browse files
Options
Browse Files
Download
Plain Diff
Merge upstream/development
parents
b075b991
fdd0cc9e
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
733 additions
and
66 deletions
+733
-66
include/git2/commit.h
+20
-0
include/git2/common.h
+6
-0
include/git2/index.h
+40
-0
include/git2/repository.h
+30
-0
include/git2/signature.h
+17
-6
src/backends/hiredis.c
+200
-0
src/commit.c
+6
-0
src/errors.c
+3
-1
src/filebuf.c
+1
-1
src/index.c
+13
-2
src/refs.c
+24
-13
src/repository.c
+26
-0
src/revwalk.c
+3
-2
src/signature.c
+49
-9
src/tag.c
+20
-9
src/tree.c
+3
-2
src/util.c
+79
-0
src/util.h
+2
-0
tests/resources/testrepo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1
+0
-0
tests/resources/testrepo.git/refs/tags/point_to_blob
+1
-0
tests/t00-core.c
+2
-2
tests/t08-tag.c
+2
-16
tests/t09-tree.c
+26
-0
tests/t10-refs.c
+7
-2
tests/t12-repo.c
+18
-0
tests/t14-hiredis.c
+123
-0
tests/t15-config.c
+0
-0
tests/test_main.c
+2
-0
wscript
+10
-1
No files found.
include/git2/commit.h
View file @
55c197cd
...
@@ -136,6 +136,16 @@ GIT_EXTERN(const git_signature *) git_commit_author(git_commit *commit);
...
@@ -136,6 +136,16 @@ GIT_EXTERN(const git_signature *) git_commit_author(git_commit *commit);
GIT_EXTERN
(
int
)
git_commit_tree
(
git_tree
**
tree_out
,
git_commit
*
commit
);
GIT_EXTERN
(
int
)
git_commit_tree
(
git_tree
**
tree_out
,
git_commit
*
commit
);
/**
/**
* Get the id of the tree pointed to by a commit. This differs from
* `git_commit_tree` in that no attempts are made to fetch an object
* from the ODB.
*
* @param commit a previously loaded commit.
* @return the id of tree pointed to by commit.
*/
GIT_EXTERN
(
const
git_oid
*
)
git_commit_tree_oid
(
git_commit
*
commit
);
/**
* Get the number of parents of this commit
* Get the number of parents of this commit
*
*
* @param commit a previously loaded commit.
* @param commit a previously loaded commit.
...
@@ -153,6 +163,16 @@ GIT_EXTERN(unsigned int) git_commit_parentcount(git_commit *commit);
...
@@ -153,6 +163,16 @@ GIT_EXTERN(unsigned int) git_commit_parentcount(git_commit *commit);
*/
*/
GIT_EXTERN
(
int
)
git_commit_parent
(
git_commit
**
parent
,
git_commit
*
commit
,
unsigned
int
n
);
GIT_EXTERN
(
int
)
git_commit_parent
(
git_commit
**
parent
,
git_commit
*
commit
,
unsigned
int
n
);
/**
* Get the oid of a specified parent for a commit. This is different from
* `git_commit_parent`, which will attempt to load the parent commit from
* the ODB.
*
* @param commit a previously loaded commit.
* @param n the position of the parent (from 0 to `parentcount`)
* @return the id of the parent, NULL on error.
*/
GIT_EXTERN
(
const
git_oid
*
)
git_commit_parent_oid
(
git_commit
*
commit
,
unsigned
int
n
);
/**
/**
* Create a new commit in the repository
* Create a new commit in the repository
...
...
include/git2/common.h
View file @
55c197cd
...
@@ -164,6 +164,12 @@
...
@@ -164,6 +164,12 @@
/** A reference with this name already exists */
/** A reference with this name already exists */
#define GIT_EEXISTS (GIT_ERROR - 23)
#define GIT_EEXISTS (GIT_ERROR - 23)
/** The given integer literal is too large to be parsed */
#define GIT_EOVERFLOW (GIT_ERROR - 24)
/** The given literal is not a valid number */
#define GIT_ENOTNUM (GIT_ERROR - 25)
GIT_BEGIN_DECL
GIT_BEGIN_DECL
typedef
struct
{
typedef
struct
{
...
...
include/git2/index.h
View file @
55c197cd
...
@@ -44,6 +44,46 @@ GIT_BEGIN_DECL
...
@@ -44,6 +44,46 @@ GIT_BEGIN_DECL
#define GIT_IDXENTRY_VALID (0x8000)
#define GIT_IDXENTRY_VALID (0x8000)
#define GIT_IDXENTRY_STAGESHIFT 12
#define GIT_IDXENTRY_STAGESHIFT 12
/*
* Flags are divided into two parts: in-memory flags and
* on-disk ones. Flags in GIT_IDXENTRY_EXTENDED_FLAGS
* will get saved on-disk.
*
* In-memory only flags:
*/
#define GIT_IDXENTRY_UPDATE (1 << 16)
#define GIT_IDXENTRY_REMOVE (1 << 17)
#define GIT_IDXENTRY_UPTODATE (1 << 18)
#define GIT_IDXENTRY_ADDED (1 << 19)
#define GIT_IDXENTRY_HASHED (1 << 20)
#define GIT_IDXENTRY_UNHASHED (1 << 21)
#define GIT_IDXENTRY_WT_REMOVE (1 << 22)
/* remove in work directory */
#define GIT_IDXENTRY_CONFLICTED (1 << 23)
#define GIT_IDXENTRY_UNPACKED (1 << 24)
#define GIT_IDXENTRY_NEW_SKIP_WORKTREE (1 << 25)
/*
* Extended on-disk flags:
*/
#define GIT_IDXENTRY_INTENT_TO_ADD (1 << 29)
#define GIT_IDXENTRY_SKIP_WORKTREE (1 << 30)
/* GIT_IDXENTRY_EXTENDED2 is for future extension */
#define GIT_IDXENTRY_EXTENDED2 (1 << 31)
#define GIT_IDXENTRY_EXTENDED_FLAGS (GIT_IDXENTRY_INTENT_TO_ADD | GIT_IDXENTRY_SKIP_WORKTREE)
/*
* Safeguard to avoid saving wrong flags:
* - GIT_IDXENTRY_EXTENDED2 won't get saved until its semantic is known
* - Bits in 0x0000FFFF have been saved in flags already
* - Bits in 0x003F0000 are currently in-memory flags
*/
#if GIT_IDXENTRY_EXTENDED_FLAGS & 0x803FFFFF
#error "GIT_IDXENTRY_EXTENDED_FLAGS out of range"
#endif
/** Time used in a git index entry */
/** Time used in a git index entry */
typedef
struct
{
typedef
struct
{
git_time_t
seconds
;
git_time_t
seconds
;
...
...
include/git2/repository.h
View file @
55c197cd
...
@@ -182,6 +182,36 @@ GIT_EXTERN(void) git_repository_free(git_repository *repo);
...
@@ -182,6 +182,36 @@ GIT_EXTERN(void) git_repository_free(git_repository *repo);
*/
*/
GIT_EXTERN
(
int
)
git_repository_init
(
git_repository
**
repo_out
,
const
char
*
path
,
unsigned
is_bare
);
GIT_EXTERN
(
int
)
git_repository_init
(
git_repository
**
repo_out
,
const
char
*
path
,
unsigned
is_bare
);
/**
* Check if a repository is empty
*
* An empty repository has just been initialized and contains
* no commits.
*
* @param repo Repo to test
* @return 1 if the repository is empty, 0 if it isn't, error code
* if the repository is corrupted
*/
GIT_EXTERN
(
int
)
git_repository_is_empty
(
git_repository
*
repo
);
/**
* Get the normalized path to the git repository.
*
* @param repo a repository object
* @return absolute path to the git directory
*/
GIT_EXTERN
(
const
char
*
)
git_repository_path
(
git_repository
*
repo
);
/**
* Get the normalized path to the working directory of the repository.
*
* If the repository is bare, there is no working directory and NULL we be returned.
*
* @param repo a repository object
* @return NULL if the repository is bare; absolute path to the working directory otherwise.
*/
GIT_EXTERN
(
const
char
*
)
git_repository_workdir
(
git_repository
*
repo
);
/** @} */
/** @} */
GIT_END_DECL
GIT_END_DECL
#endif
#endif
include/git2/signature.h
View file @
55c197cd
...
@@ -41,19 +41,30 @@ GIT_BEGIN_DECL
...
@@ -41,19 +41,30 @@ GIT_BEGIN_DECL
* Create a new action signature. The signature must be freed
* Create a new action signature. The signature must be freed
* manually or using git_signature_free
* manually or using git_signature_free
*
*
* @name name of the person
* @
param
name name of the person
* @
e
mail email of the person
* @
param
mail email of the person
* @time time when the action happened
* @
param
time time when the action happened
* @offset timezone offset in minutes for the time
* @
param
offset timezone offset in minutes for the time
* @return the new sig, NULL on out of memory
* @return the new sig, NULL on out of memory
*/
*/
GIT_EXTERN
(
git_signature
*
)
git_signature_new
(
const
char
*
name
,
const
char
*
email
,
git_time_t
time
,
int
offset
);
GIT_EXTERN
(
git_signature
*
)
git_signature_new
(
const
char
*
name
,
const
char
*
email
,
git_time_t
time
,
int
offset
);
/**
/**
* Create a new action signature with a timestamp of 'now'. The
* signature must be freed manually or using git_signature_free
*
* @param name name of the person
* @param email email of the person
* @return the new sig, NULL on out of memory
*/
GIT_EXTERN
(
git_signature
*
)
git_signature_now
(
const
char
*
name
,
const
char
*
email
);
/**
* Create a copy of an existing signature.
* Create a copy of an existing signature.
*
*
* All internal strings are also duplicated.
* All internal strings are also duplicated.
* @sig signature to duplicated
* @
param
sig signature to duplicated
* @return a copy of sig, NULL on out of memory
* @return a copy of sig, NULL on out of memory
*/
*/
GIT_EXTERN
(
git_signature
*
)
git_signature_dup
(
const
git_signature
*
sig
);
GIT_EXTERN
(
git_signature
*
)
git_signature_dup
(
const
git_signature
*
sig
);
...
@@ -61,7 +72,7 @@ GIT_EXTERN(git_signature *) git_signature_dup(const git_signature *sig);
...
@@ -61,7 +72,7 @@ GIT_EXTERN(git_signature *) git_signature_dup(const git_signature *sig);
/**
/**
* Free an existing signature
* Free an existing signature
*
*
* @sig signature to free
* @
param
sig signature to free
*/
*/
GIT_EXTERN
(
void
)
git_signature_free
(
git_signature
*
sig
);
GIT_EXTERN
(
void
)
git_signature_free
(
git_signature
*
sig
);
...
...
src/backends/hiredis.c
0 → 100644
View file @
55c197cd
/*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2,
* as published by the Free Software Foundation.
*
* In addition to the permissions in the GNU General Public License,
* the authors give you unlimited permission to link the compiled
* version of this file into combinations with other programs,
* and to distribute those combinations without any restriction
* coming from the use of this file. (The General Public License
* restrictions do apply in other respects; for example, they cover
* modification of the file, and distribution when not linked into
* a combined executable.)
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "common.h"
#include "git2/object.h"
#include "hash.h"
#include "odb.h"
#include "git2/odb_backend.h"
#ifdef GIT2_HIREDIS_BACKEND
#include <hiredis/hiredis.h>
typedef
struct
{
git_odb_backend
parent
;
redisContext
*
db
;
}
hiredis_backend
;
int
hiredis_backend__read_header
(
size_t
*
len_p
,
git_otype
*
type_p
,
git_odb_backend
*
_backend
,
const
git_oid
*
oid
)
{
hiredis_backend
*
backend
;
int
error
;
redisReply
*
reply
;
assert
(
len_p
&&
type_p
&&
_backend
&&
oid
);
backend
=
(
hiredis_backend
*
)
_backend
;
error
=
GIT_ERROR
;
reply
=
redisCommand
(
backend
->
db
,
"HMGET %b %s %s"
,
oid
->
id
,
GIT_OID_RAWSZ
,
"type"
,
"size"
);
if
(
reply
->
type
==
REDIS_REPLY_ARRAY
)
{
if
(
reply
->
element
[
0
]
->
type
!=
REDIS_REPLY_NIL
&&
reply
->
element
[
0
]
->
type
!=
REDIS_REPLY_NIL
)
{
*
type_p
=
(
git_otype
)
atoi
(
reply
->
element
[
0
]
->
str
);
*
len_p
=
(
size_t
)
atoi
(
reply
->
element
[
1
]
->
str
);
error
=
GIT_SUCCESS
;
}
else
{
error
=
GIT_ENOTFOUND
;
}
}
else
{
error
=
GIT_ERROR
;
}
freeReplyObject
(
reply
);
return
error
;
}
int
hiredis_backend__read
(
void
**
data_p
,
size_t
*
len_p
,
git_otype
*
type_p
,
git_odb_backend
*
_backend
,
const
git_oid
*
oid
)
{
hiredis_backend
*
backend
;
int
error
;
redisReply
*
reply
;
assert
(
data_p
&&
len_p
&&
type_p
&&
_backend
&&
oid
);
backend
=
(
hiredis_backend
*
)
_backend
;
error
=
GIT_ERROR
;
reply
=
redisCommand
(
backend
->
db
,
"HMGET %b %s %s %s"
,
oid
->
id
,
GIT_OID_RAWSZ
,
"type"
,
"size"
,
"data"
);
if
(
reply
->
type
==
REDIS_REPLY_ARRAY
)
{
if
(
reply
->
element
[
0
]
->
type
!=
REDIS_REPLY_NIL
&&
reply
->
element
[
1
]
->
type
!=
REDIS_REPLY_NIL
&&
reply
->
element
[
2
]
->
type
!=
REDIS_REPLY_NIL
)
{
*
type_p
=
(
git_otype
)
atoi
(
reply
->
element
[
0
]
->
str
);
*
len_p
=
(
size_t
)
atoi
(
reply
->
element
[
1
]
->
str
);
*
data_p
=
git__malloc
(
*
len_p
);
if
(
*
data_p
==
NULL
)
{
error
=
GIT_ENOMEM
;
}
else
{
memcpy
(
*
data_p
,
reply
->
element
[
2
]
->
str
,
*
len_p
);
error
=
GIT_SUCCESS
;
}
}
else
{
error
=
GIT_ENOTFOUND
;
}
}
else
{
error
=
GIT_ERROR
;
}
freeReplyObject
(
reply
);
return
error
;
}
int
hiredis_backend__exists
(
git_odb_backend
*
_backend
,
const
git_oid
*
oid
)
{
hiredis_backend
*
backend
;
int
found
;
redisReply
*
reply
;
assert
(
_backend
&&
oid
);
backend
=
(
hiredis_backend
*
)
_backend
;
found
=
0
;
reply
=
redisCommand
(
backend
->
db
,
"exists %b"
,
oid
->
id
,
GIT_OID_RAWSZ
);
if
(
reply
->
type
!=
REDIS_REPLY_NIL
&&
reply
->
type
!=
REDIS_REPLY_ERROR
)
found
=
1
;
freeReplyObject
(
reply
);
return
found
;
}
int
hiredis_backend__write
(
git_oid
*
id
,
git_odb_backend
*
_backend
,
const
void
*
data
,
size_t
len
,
git_otype
type
)
{
hiredis_backend
*
backend
;
int
error
;
redisReply
*
reply
;
assert
(
id
&&
_backend
&&
data
);
backend
=
(
hiredis_backend
*
)
_backend
;
error
=
GIT_ERROR
;
if
((
error
=
git_odb_hash
(
id
,
data
,
len
,
type
))
<
0
)
return
error
;
reply
=
redisCommand
(
backend
->
db
,
"HMSET %b "
"type %d "
"size %d "
"data %b "
,
id
->
id
,
GIT_OID_RAWSZ
,
(
int
)
type
,
len
,
data
,
len
);
error
=
reply
->
type
==
REDIS_REPLY_ERROR
?
GIT_ERROR
:
GIT_SUCCESS
;
freeReplyObject
(
reply
);
return
error
;
}
void
hiredis_backend__free
(
git_odb_backend
*
_backend
)
{
hiredis_backend
*
backend
;
assert
(
_backend
);
backend
=
(
hiredis_backend
*
)
_backend
;
redisFree
(
backend
->
db
);
free
(
backend
);
}
int
git_odb_backend_hiredis
(
git_odb_backend
**
backend_out
,
const
char
*
host
,
int
port
)
{
hiredis_backend
*
backend
;
backend
=
git__calloc
(
1
,
sizeof
(
hiredis_backend
));
if
(
backend
==
NULL
)
return
GIT_ENOMEM
;
backend
->
db
=
redisConnect
(
host
,
port
);
if
(
backend
->
db
->
err
)
goto
cleanup
;
backend
->
parent
.
read
=
&
hiredis_backend__read
;
backend
->
parent
.
read_header
=
&
hiredis_backend__read_header
;
backend
->
parent
.
write
=
&
hiredis_backend__write
;
backend
->
parent
.
exists
=
&
hiredis_backend__exists
;
backend
->
parent
.
free
=
&
hiredis_backend__free
;
*
backend_out
=
(
git_odb_backend
*
)
backend
;
return
GIT_SUCCESS
;
cleanup:
free
(
backend
);
return
GIT_ERROR
;
}
#else
int
git_odb_backend_hiredis
(
git_odb_backend
**
GIT_UNUSED
(
backend_out
),
const
char
*
GIT_UNUSED
(
host
),
int
GIT_UNUSED
(
port
))
{
GIT_UNUSED_ARG
(
backend_out
);
GIT_UNUSED_ARG
(
host
);
GIT_UNUSED_ARG
(
port
);
return
GIT_ENOTIMPLEMENTED
;
}
#endif
/* HAVE_HIREDIS */
src/commit.c
View file @
55c197cd
...
@@ -318,6 +318,7 @@ GIT_COMMIT_GETTER(const char *, message_short, commit->message_short)
...
@@ -318,6 +318,7 @@ GIT_COMMIT_GETTER(const char *, message_short, commit->message_short)
GIT_COMMIT_GETTER
(
git_time_t
,
time
,
commit
->
committer
->
when
.
time
)
GIT_COMMIT_GETTER
(
git_time_t
,
time
,
commit
->
committer
->
when
.
time
)
GIT_COMMIT_GETTER
(
int
,
time_offset
,
commit
->
committer
->
when
.
offset
)
GIT_COMMIT_GETTER
(
int
,
time_offset
,
commit
->
committer
->
when
.
offset
)
GIT_COMMIT_GETTER
(
unsigned
int
,
parentcount
,
commit
->
parent_oids
.
length
)
GIT_COMMIT_GETTER
(
unsigned
int
,
parentcount
,
commit
->
parent_oids
.
length
)
GIT_COMMIT_GETTER
(
const
git_oid
*
,
tree_oid
,
&
commit
->
tree_oid
);
int
git_commit_tree
(
git_tree
**
tree_out
,
git_commit
*
commit
)
int
git_commit_tree
(
git_tree
**
tree_out
,
git_commit
*
commit
)
...
@@ -338,4 +339,9 @@ int git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n)
...
@@ -338,4 +339,9 @@ int git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n)
return
git_commit_lookup
(
parent
,
commit
->
object
.
repo
,
parent_oid
);
return
git_commit_lookup
(
parent
,
commit
->
object
.
repo
,
parent_oid
);
}
}
const
git_oid
*
git_commit_parent_oid
(
git_commit
*
commit
,
unsigned
int
n
)
{
assert
(
commit
);
return
git_vector_get
(
&
commit
->
parent_oids
,
n
);
}
src/errors.c
View file @
55c197cd
...
@@ -29,7 +29,9 @@ static struct {
...
@@ -29,7 +29,9 @@ static struct {
{
GIT_EREVWALKOVER
,
"The revision walker is empty; there are no more commits left to iterate"
},
{
GIT_EREVWALKOVER
,
"The revision walker is empty; there are no more commits left to iterate"
},
{
GIT_EINVALIDREFSTATE
,
"The state of the reference is not valid"
},
{
GIT_EINVALIDREFSTATE
,
"The state of the reference is not valid"
},
{
GIT_ENOTIMPLEMENTED
,
"This feature has not been implemented yet"
},
{
GIT_ENOTIMPLEMENTED
,
"This feature has not been implemented yet"
},
{
GIT_EEXISTS
,
"A reference with this name already exists"
}
{
GIT_EEXISTS
,
"A reference with this name already exists"
},
{
GIT_EOVERFLOW
,
"The given integer literal is too large to be parsed"
},
{
GIT_ENOTNUM
,
"The given literal is not a valid number"
},
};
};
const
char
*
git_strerror
(
int
num
)
const
char
*
git_strerror
(
int
num
)
...
...
src/filebuf.c
View file @
55c197cd
...
@@ -178,7 +178,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)
...
@@ -178,7 +178,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)
if
(
flags
&
GIT_FILEBUF_DEFLATE_CONTENTS
)
{
if
(
flags
&
GIT_FILEBUF_DEFLATE_CONTENTS
)
{
/* Initialize the ZLib stream */
/* Initialize the ZLib stream */
if
(
deflateInit
(
&
file
->
zs
,
Z_
DEFAULT_COMPRESSION
)
!=
Z_OK
)
{
if
(
deflateInit
(
&
file
->
zs
,
Z_
BEST_SPEED
)
!=
Z_OK
)
{
error
=
GIT_EZLIB
;
error
=
GIT_EZLIB
;
goto
cleanup
;
goto
cleanup
;
}
}
...
...
src/index.c
View file @
55c197cd
...
@@ -411,6 +411,7 @@ static git_index_tree *read_tree_internal(
...
@@ -411,6 +411,7 @@ static git_index_tree *read_tree_internal(
{
{
git_index_tree
*
tree
;
git_index_tree
*
tree
;
const
char
*
name_start
,
*
buffer
;
const
char
*
name_start
,
*
buffer
;
long
count
;
if
((
tree
=
git__malloc
(
sizeof
(
git_index_tree
)))
==
NULL
)
if
((
tree
=
git__malloc
(
sizeof
(
git_index_tree
)))
==
NULL
)
return
NULL
;
return
NULL
;
...
@@ -429,12 +430,22 @@ static git_index_tree *read_tree_internal(
...
@@ -429,12 +430,22 @@ static git_index_tree *read_tree_internal(
goto
error_cleanup
;
goto
error_cleanup
;
/* Blank-terminated ASCII decimal number of entries in this tree */
/* Blank-terminated ASCII decimal number of entries in this tree */
tree
->
entries
=
strtol
(
buffer
,
(
char
**
)
&
buffer
,
10
);
if
(
git__strtol32
(
&
count
,
buffer
,
&
buffer
,
10
)
<
GIT_SUCCESS
||
count
<
0
)
goto
error_cleanup
;
tree
->
entries
=
(
size_t
)
count
;
if
(
*
buffer
!=
' '
||
++
buffer
>=
buffer_end
)
if
(
*
buffer
!=
' '
||
++
buffer
>=
buffer_end
)
goto
error_cleanup
;
goto
error_cleanup
;
/* Number of children of the tree, newline-terminated */
/* Number of children of the tree, newline-terminated */
tree
->
children_count
=
strtol
(
buffer
,
(
char
**
)
&
buffer
,
10
);
if
(
git__strtol32
(
&
count
,
buffer
,
&
buffer
,
10
)
<
GIT_SUCCESS
||
count
<
0
)
goto
error_cleanup
;
tree
->
children_count
=
(
size_t
)
count
;
if
(
*
buffer
!=
'\n'
||
++
buffer
>=
buffer_end
)
if
(
*
buffer
!=
'\n'
||
++
buffer
>=
buffer_end
)
goto
error_cleanup
;
goto
error_cleanup
;
...
...
src/refs.c
View file @
55c197cd
...
@@ -746,7 +746,7 @@ static int packed_write_ref(reference_oid *ref, git_filebuf *file)
...
@@ -746,7 +746,7 @@ static int packed_write_ref(reference_oid *ref, git_filebuf *file)
*/
*/
static
int
packed_find_peel
(
reference_oid
*
ref
)
static
int
packed_find_peel
(
reference_oid
*
ref
)
{
{
git_
tag
*
tag
;
git_
object
*
object
;
int
error
;
int
error
;
if
(
ref
->
ref
.
type
&
GIT_REF_HAS_PEEL
)
if
(
ref
->
ref
.
type
&
GIT_REF_HAS_PEEL
)
...
@@ -760,25 +760,32 @@ static int packed_find_peel(reference_oid *ref)
...
@@ -760,25 +760,32 @@ static int packed_find_peel(reference_oid *ref)
return
GIT_SUCCESS
;
return
GIT_SUCCESS
;
/*
/*
* Find the tag in the repository. The tag must exist,
* Find the tagged object in the repository
* otherwise this reference is broken and we shouldn't
* pack it.
*/
*/
error
=
git_
tag_lookup
(
&
tag
,
ref
->
ref
.
owner
,
&
ref
->
oid
);
error
=
git_
object_lookup
(
&
object
,
ref
->
ref
.
owner
,
&
ref
->
oid
,
GIT_OBJ_ANY
);
if
(
error
<
GIT_SUCCESS
)
if
(
error
<
GIT_SUCCESS
)
return
GIT_EOBJCORRUPTED
;
return
GIT_EOBJCORRUPTED
;
/*
/*
* Find the object pointed at by this tag
* If the tagged object is a Tag object, we need to resolve it;
* if the ref is actually a 'weak' ref, we don't need to resolve
* anything.
*/
*/
git_oid_cpy
(
&
ref
->
peel_target
,
git_tag_target_oid
(
tag
));
if
(
git_object_type
(
object
)
==
GIT_OBJ_TAG
)
{
ref
->
ref
.
type
|=
GIT_REF_HAS_PEEL
;
git_tag
*
tag
=
(
git_tag
*
)
object
;
/*
/*
* The reference has now cached the resolved OID, and is
* Find the object pointed at by this tag
* marked at such. When written to the packfile, it'll be
*/
* accompanied by this resolved oid
git_oid_cpy
(
&
ref
->
peel_target
,
git_tag_target_oid
(
tag
));
*/
ref
->
ref
.
type
|=
GIT_REF_HAS_PEEL
;
/*
* The reference has now cached the resolved OID, and is
* marked at such. When written to the packfile, it'll be
* accompanied by this resolved oid
*/
}
return
GIT_SUCCESS
;
return
GIT_SUCCESS
;
}
}
...
@@ -1419,6 +1426,10 @@ int git_reference_delete(git_reference *ref)
...
@@ -1419,6 +1426,10 @@ int git_reference_delete(git_reference *ref)
assert
(
ref
);
assert
(
ref
);
if
(
ref
->
type
&
GIT_REF_PACKED
)
{
if
(
ref
->
type
&
GIT_REF_PACKED
)
{
/* load the existing packfile */
if
((
error
=
packed_load
(
ref
->
owner
))
<
GIT_SUCCESS
)
return
error
;
git_hashtable_remove
(
ref
->
owner
->
references
.
packfile
,
ref
->
name
);
git_hashtable_remove
(
ref
->
owner
->
references
.
packfile
,
ref
->
name
);
error
=
packed_write
(
ref
->
owner
);
error
=
packed_write
(
ref
->
owner
);
}
else
{
}
else
{
...
...
src/repository.c
View file @
55c197cd
...
@@ -473,3 +473,29 @@ cleanup:
...
@@ -473,3 +473,29 @@ cleanup:
return
error
;
return
error
;
}
}
int
git_repository_is_empty
(
git_repository
*
repo
)
{
git_reference
*
head
,
*
branch
;
int
error
;
error
=
git_reference_lookup
(
&
head
,
repo
,
"HEAD"
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
if
(
git_reference_type
(
head
)
!=
GIT_REF_SYMBOLIC
)
return
GIT_EOBJCORRUPTED
;
return
git_reference_resolve
(
&
branch
,
head
)
==
GIT_SUCCESS
?
0
:
1
;
}
const
char
*
git_repository_path
(
git_repository
*
repo
)
{
assert
(
repo
);
return
repo
->
path_repository
;
}
const
char
*
git_repository_workdir
(
git_repository
*
repo
)
{
assert
(
repo
);
return
repo
->
path_workdir
;
}
src/revwalk.c
View file @
55c197cd
...
@@ -191,6 +191,7 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
...
@@ -191,6 +191,7 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
unsigned
char
*
parents_start
;
unsigned
char
*
parents_start
;
int
i
,
parents
=
0
;
int
i
,
parents
=
0
;
long
commit_time
;
buffer
+=
STRLEN
(
"tree "
)
+
GIT_OID_HEXSZ
+
1
;
buffer
+=
STRLEN
(
"tree "
)
+
GIT_OID_HEXSZ
+
1
;
...
@@ -227,10 +228,10 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
...
@@ -227,10 +228,10 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
if
(
buffer
==
NULL
)
if
(
buffer
==
NULL
)
return
GIT_EOBJCORRUPTED
;
return
GIT_EOBJCORRUPTED
;
commit
->
time
=
strtol
((
char
*
)
buffer
+
2
,
NULL
,
10
);
if
(
git__strtol32
(
&
commit_time
,
(
char
*
)
buffer
+
2
,
NULL
,
10
)
<
GIT_SUCCESS
)
if
(
commit
->
time
==
0
)
return
GIT_EOBJCORRUPTED
;
return
GIT_EOBJCORRUPTED
;
commit
->
time
=
(
time_t
)
commit_time
;
commit
->
parsed
=
1
;
commit
->
parsed
=
1
;
return
GIT_SUCCESS
;
return
GIT_SUCCESS
;
}
}
...
...
src/signature.c
View file @
55c197cd
...
@@ -65,14 +65,47 @@ git_signature *git_signature_dup(const git_signature *sig)
...
@@ -65,14 +65,47 @@ git_signature *git_signature_dup(const git_signature *sig)
return
git_signature_new
(
sig
->
name
,
sig
->
email
,
sig
->
when
.
time
,
sig
->
when
.
offset
);
return
git_signature_new
(
sig
->
name
,
sig
->
email
,
sig
->
when
.
time
,
sig
->
when
.
offset
);
}
}
git_signature
*
git_signature_now
(
const
char
*
name
,
const
char
*
email
)
{
time_t
now
;
time_t
offset
;
struct
tm
*
utc_tm
,
*
local_tm
;
#ifndef GIT_WIN32
struct
tm
_utc
,
_local
;
#endif
time
(
&
now
);
/**
* On Win32, `gmtime_r` doesn't exist but
* `gmtime` is threadsafe, so we can use that
*/
#ifdef GIT_WIN32
utc_tm
=
gmtime
(
&
now
);
local_tm
=
localtime
(
&
now
);
#else
utc_tm
=
gmtime_r
(
&
now
,
&
_utc
);
local_tm
=
localtime_r
(
&
now
,
&
_local
);
#endif
offset
=
mktime
(
local_tm
)
-
mktime
(
utc_tm
);
offset
/=
60
;
/* mktime takes care of setting tm_isdst correctly */
if
(
local_tm
->
tm_isdst
)
offset
+=
60
;
return
git_signature_new
(
name
,
email
,
now
,
(
int
)
offset
);
}
static
int
parse_timezone_offset
(
const
char
*
buffer
,
int
*
offset_out
)
static
int
parse_timezone_offset
(
const
char
*
buffer
,
long
*
offset_out
)
{
{
int
offset
,
dec_offset
;
long
offset
,
dec_offset
;
int
mins
,
hours
;
int
mins
,
hours
;
const
char
*
offset_start
;
const
char
*
offset_start
;
c
har
*
offset_end
;
c
onst
char
*
offset_end
;
offset_start
=
buffer
+
1
;
offset_start
=
buffer
+
1
;
...
@@ -84,7 +117,8 @@ static int parse_timezone_offset(const char *buffer, int *offset_out)
...
@@ -84,7 +117,8 @@ static int parse_timezone_offset(const char *buffer, int *offset_out)
if
(
offset_start
[
0
]
!=
'-'
&&
offset_start
[
0
]
!=
'+'
)
if
(
offset_start
[
0
]
!=
'-'
&&
offset_start
[
0
]
!=
'+'
)
return
GIT_EOBJCORRUPTED
;
return
GIT_EOBJCORRUPTED
;
dec_offset
=
strtol
(
offset_start
+
1
,
&
offset_end
,
10
);
if
(
git__strtol32
(
&
dec_offset
,
offset_start
+
1
,
&
offset_end
,
10
)
<
GIT_SUCCESS
)
return
GIT_EOBJCORRUPTED
;
if
(
offset_end
-
offset_start
!=
5
)
if
(
offset_end
-
offset_start
!=
5
)
return
GIT_EOBJCORRUPTED
;
return
GIT_EOBJCORRUPTED
;
...
@@ -117,7 +151,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
...
@@ -117,7 +151,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
int
name_length
,
email_length
;
int
name_length
,
email_length
;
const
char
*
buffer
=
*
buffer_out
;
const
char
*
buffer
=
*
buffer_out
;
const
char
*
line_end
,
*
name_end
,
*
email_end
;
const
char
*
line_end
,
*
name_end
,
*
email_end
;
int
offset
=
0
;
long
offset
=
0
,
time
;
memset
(
sig
,
0x0
,
sizeof
(
git_signature
));
memset
(
sig
,
0x0
,
sizeof
(
git_signature
));
...
@@ -139,6 +173,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
...
@@ -139,6 +173,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
name_length
=
name_end
-
buffer
-
1
;
name_length
=
name_end
-
buffer
-
1
;
sig
->
name
=
git__malloc
(
name_length
+
1
);
sig
->
name
=
git__malloc
(
name_length
+
1
);
if
(
sig
->
name
==
NULL
)
return
GIT_ENOMEM
;
memcpy
(
sig
->
name
,
buffer
,
name_length
);
memcpy
(
sig
->
name
,
buffer
,
name_length
);
sig
->
name
[
name_length
]
=
0
;
sig
->
name
[
name_length
]
=
0
;
buffer
=
name_end
+
1
;
buffer
=
name_end
+
1
;
...
@@ -152,6 +189,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
...
@@ -152,6 +189,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
email_length
=
email_end
-
buffer
;
email_length
=
email_end
-
buffer
;
sig
->
email
=
git__malloc
(
email_length
+
1
);
sig
->
email
=
git__malloc
(
email_length
+
1
);
if
(
sig
->
name
==
NULL
)
return
GIT_ENOMEM
;
memcpy
(
sig
->
email
,
buffer
,
email_length
);
memcpy
(
sig
->
email
,
buffer
,
email_length
);
sig
->
email
[
email_length
]
=
0
;
sig
->
email
[
email_length
]
=
0
;
buffer
=
email_end
+
1
;
buffer
=
email_end
+
1
;
...
@@ -159,11 +199,11 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
...
@@ -159,11 +199,11 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
if
(
buffer
>=
line_end
)
if
(
buffer
>=
line_end
)
return
GIT_EOBJCORRUPTED
;
return
GIT_EOBJCORRUPTED
;
sig
->
when
.
time
=
strtol
(
buffer
,
(
char
**
)
&
buffer
,
10
);
if
(
git__strtol32
(
&
time
,
buffer
,
&
buffer
,
10
)
<
GIT_SUCCESS
)
if
(
sig
->
when
.
time
==
0
)
return
GIT_EOBJCORRUPTED
;
return
GIT_EOBJCORRUPTED
;
sig
->
when
.
time
=
(
time_t
)
time
;
if
(
parse_timezone_offset
(
buffer
,
&
offset
)
<
GIT_SUCCESS
)
if
(
parse_timezone_offset
(
buffer
,
&
offset
)
<
GIT_SUCCESS
)
return
GIT_EOBJCORRUPTED
;
return
GIT_EOBJCORRUPTED
;
...
...
src/tag.c
View file @
55c197cd
...
@@ -131,12 +131,17 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
...
@@ -131,12 +131,17 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
text_len
=
search
-
buffer
;
text_len
=
search
-
buffer
;
tag
->
tag_name
=
git__malloc
(
text_len
+
1
);
tag
->
tag_name
=
git__malloc
(
text_len
+
1
);
if
(
tag
->
tag_name
==
NULL
)
return
GIT_ENOMEM
;
memcpy
(
tag
->
tag_name
,
buffer
,
text_len
);
memcpy
(
tag
->
tag_name
,
buffer
,
text_len
);
tag
->
tag_name
[
text_len
]
=
'\0'
;
tag
->
tag_name
[
text_len
]
=
'\0'
;
buffer
=
search
+
1
;
buffer
=
search
+
1
;
tag
->
tagger
=
git__malloc
(
sizeof
(
git_signature
));
tag
->
tagger
=
git__malloc
(
sizeof
(
git_signature
));
if
(
tag
->
tagger
==
NULL
)
return
GIT_ENOMEM
;
if
((
error
=
git_signature__parse
(
tag
->
tagger
,
&
buffer
,
buffer_end
,
"tagger "
))
!=
0
)
{
if
((
error
=
git_signature__parse
(
tag
->
tagger
,
&
buffer
,
buffer_end
,
"tagger "
))
!=
0
)
{
free
(
tag
->
tag_name
);
free
(
tag
->
tag_name
);
...
@@ -147,6 +152,9 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
...
@@ -147,6 +152,9 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
text_len
=
buffer_end
-
++
buffer
;
text_len
=
buffer_end
-
++
buffer
;
tag
->
message
=
git__malloc
(
text_len
+
1
);
tag
->
message
=
git__malloc
(
text_len
+
1
);
if
(
tag
->
message
==
NULL
)
return
GIT_ENOMEM
;
memcpy
(
tag
->
message
,
buffer
,
text_len
);
memcpy
(
tag
->
message
,
buffer
,
text_len
);
tag
->
message
[
text_len
]
=
'\0'
;
tag
->
message
[
text_len
]
=
'\0'
;
...
@@ -209,6 +217,17 @@ static int tag_create(
...
@@ -209,6 +217,17 @@ static int tag_create(
return
error
;
return
error
;
}
}
if
(
!
git_odb_exists
(
repo
->
db
,
target
))
return
GIT_ENOTFOUND
;
/* Try to find out what the type is */
if
(
target_type
==
GIT_OBJ_ANY
)
{
size_t
_unused
;
error
=
git_odb_read_header
(
&
_unused
,
&
target_type
,
repo
->
db
,
target
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
}
type_str
=
git_object_type2string
(
target_type
);
type_str
=
git_object_type2string
(
target_type
);
tagger_str_len
=
git_signature__write
(
&
tagger_str
,
"tagger"
,
tagger
);
tagger_str_len
=
git_signature__write
(
&
tagger_str
,
"tagger"
,
tagger
);
...
@@ -260,7 +279,6 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
...
@@ -260,7 +279,6 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
{
{
git_tag
tag
;
git_tag
tag
;
int
error
;
int
error
;
git_object
*
obj
;
assert
(
oid
&&
buffer
);
assert
(
oid
&&
buffer
);
...
@@ -269,15 +287,8 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
...
@@ -269,15 +287,8 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
if
((
error
=
parse_tag_buffer
(
&
tag
,
buffer
,
buffer
+
strlen
(
buffer
)))
<
GIT_SUCCESS
)
if
((
error
=
parse_tag_buffer
(
&
tag
,
buffer
,
buffer
+
strlen
(
buffer
)))
<
GIT_SUCCESS
)
return
error
;
return
error
;
error
=
git_object_lookup
(
&
obj
,
repo
,
&
tag
.
target
,
tag
.
type
);
error
=
git_tag_create
(
oid
,
repo
,
tag
.
tag_name
,
&
tag
.
target
,
tag
.
type
,
tag
.
tagger
,
tag
.
message
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_tag_create_o
(
oid
,
repo
,
tag
.
tag_name
,
obj
,
tag
.
tagger
,
tag
.
message
);
git_object_close
(
obj
);
cleanup:
git_signature_free
(
tag
.
tagger
);
git_signature_free
(
tag
.
tagger
);
free
(
tag
.
tag_name
);
free
(
tag
.
tag_name
);
free
(
tag
.
message
);
free
(
tag
.
message
);
...
...
src/tree.c
View file @
55c197cd
...
@@ -150,7 +150,8 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf
...
@@ -150,7 +150,8 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf
if
(
git_vector_insert
(
&
tree
->
entries
,
entry
)
<
GIT_SUCCESS
)
if
(
git_vector_insert
(
&
tree
->
entries
,
entry
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
return
GIT_ENOMEM
;
entry
->
attr
=
strtol
(
buffer
,
(
char
**
)
&
buffer
,
8
);
if
(
git__strtol32
((
long
*
)
&
entry
->
attr
,
buffer
,
&
buffer
,
8
)
<
GIT_SUCCESS
)
return
GIT_EOBJCORRUPTED
;
if
(
*
buffer
++
!=
' '
)
{
if
(
*
buffer
++
!=
' '
)
{
error
=
GIT_EOBJCORRUPTED
;
error
=
GIT_EOBJCORRUPTED
;
...
@@ -364,7 +365,7 @@ int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, con
...
@@ -364,7 +365,7 @@ int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, con
git_oid_cpy
(
&
entry
->
oid
,
id
);
git_oid_cpy
(
&
entry
->
oid
,
id
);
entry
->
attr
=
attributes
;
entry
->
attr
=
attributes
;
if
(
pos
!
=
GIT_ENOTFOUND
)
{
if
(
pos
=
=
GIT_ENOTFOUND
)
{
if
(
git_vector_insert
(
&
bld
->
entries
,
entry
)
<
0
)
if
(
git_vector_insert
(
&
bld
->
entries
,
entry
)
<
0
)
return
GIT_ENOMEM
;
return
GIT_ENOMEM
;
}
}
...
...
src/util.c
View file @
55c197cd
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
#include "common.h"
#include "common.h"
#include <stdarg.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdio.h>
#include <ctype.h>
void
git_strarray_free
(
git_strarray
*
array
)
void
git_strarray_free
(
git_strarray
*
array
)
{
{
...
@@ -12,6 +13,84 @@ void git_strarray_free(git_strarray *array)
...
@@ -12,6 +13,84 @@ void git_strarray_free(git_strarray *array)
free
(
array
->
strings
);
free
(
array
->
strings
);
}
}
int
git__strtol32
(
long
*
result
,
const
char
*
nptr
,
const
char
**
endptr
,
int
base
)
{
const
char
*
p
;
long
n
,
nn
;
int
c
,
ovfl
,
v
,
neg
,
ndig
;
p
=
nptr
;
neg
=
0
;
n
=
0
;
ndig
=
0
;
ovfl
=
0
;
/*
* White space
*/
while
(
isspace
(
*
p
))
p
++
;
/*
* Sign
*/
if
(
*
p
==
'-'
||
*
p
==
'+'
)
if
(
*
p
++
==
'-'
)
neg
=
1
;
/*
* Base
*/
if
(
base
==
0
)
{
if
(
*
p
!=
'0'
)
base
=
10
;
else
{
base
=
8
;
if
(
p
[
1
]
==
'x'
||
p
[
1
]
==
'X'
)
{
p
+=
2
;
base
=
16
;
}
}
}
else
if
(
base
==
16
&&
*
p
==
'0'
)
{
if
(
p
[
1
]
==
'x'
||
p
[
1
]
==
'X'
)
p
+=
2
;
}
else
if
(
base
<
0
||
36
<
base
)
goto
Return
;
/*
* Non-empty sequence of digits
*/
for
(;;
p
++
,
ndig
++
)
{
c
=
*
p
;
v
=
base
;
if
(
'0'
<=
c
&&
c
<=
'9'
)
v
=
c
-
'0'
;
else
if
(
'a'
<=
c
&&
c
<=
'z'
)
v
=
c
-
'a'
+
10
;
else
if
(
'A'
<=
c
&&
c
<=
'Z'
)
v
=
c
-
'A'
+
10
;
if
(
v
>=
base
)
break
;
nn
=
n
*
base
+
v
;
if
(
nn
<
n
)
ovfl
=
1
;
n
=
nn
;
}
Return:
if
(
ndig
==
0
)
return
GIT_ENOTNUM
;
if
(
endptr
)
*
endptr
=
p
;
if
(
ovfl
)
return
GIT_EOVERFLOW
;
*
result
=
neg
?
-
n
:
n
;
return
GIT_SUCCESS
;
}
int
git__fmt
(
char
*
buf
,
size_t
buf_sz
,
const
char
*
fmt
,
...)
int
git__fmt
(
char
*
buf
,
size_t
buf_sz
,
const
char
*
fmt
,
...)
{
{
va_list
va
;
va_list
va
;
...
...
src/util.h
View file @
55c197cd
...
@@ -22,6 +22,8 @@ extern int git__fmt(char *, size_t, const char *, ...)
...
@@ -22,6 +22,8 @@ extern int git__fmt(char *, size_t, const char *, ...)
extern
int
git__prefixcmp
(
const
char
*
str
,
const
char
*
prefix
);
extern
int
git__prefixcmp
(
const
char
*
str
,
const
char
*
prefix
);
extern
int
git__suffixcmp
(
const
char
*
str
,
const
char
*
suffix
);
extern
int
git__suffixcmp
(
const
char
*
str
,
const
char
*
suffix
);
extern
int
git__strtol32
(
long
*
n
,
const
char
*
buff
,
const
char
**
end_buf
,
int
base
);
/*
/*
* The dirname() function shall take a pointer to a character string
* The dirname() function shall take a pointer to a character string
* that contains a pathname, and return a pointer to a string that is a
* that contains a pathname, and return a pointer to a string that is a
...
...
tests/resources/testrepo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1
View file @
55c197cd
No preview for this file type
tests/resources/testrepo.git/refs/tags/point_to_blob
0 → 100644
View file @
55c197cd
1385f264afb75a56a5bec74243be9b367ba4ca08
tests/t00-core.c
View file @
55c197cd
...
@@ -233,7 +233,7 @@ BEGIN_TEST(path3, "prettify and validate a path to a file")
...
@@ -233,7 +233,7 @@ BEGIN_TEST(path3, "prettify and validate a path to a file")
must_fail
(
ensure_file_path_normalized
(
"d1/s1///s2/..//../s3/"
,
NULL
,
0
));
must_fail
(
ensure_file_path_normalized
(
"d1/s1///s2/..//../s3/"
,
NULL
,
0
));
must_pass
(
ensure_file_path_normalized
(
"d1/s1//../s2/../../d2"
,
"d2"
,
CWD_AS_PREFIX
|
PATH_AS_SUFFIX
));
must_pass
(
ensure_file_path_normalized
(
"d1/s1//../s2/../../d2"
,
"d2"
,
CWD_AS_PREFIX
|
PATH_AS_SUFFIX
));
must_fail
(
ensure_file_path_normalized
(
"dir/sub/../"
,
NULL
,
0
));
must_fail
(
ensure_file_path_normalized
(
"dir/sub/../"
,
NULL
,
0
));
must_pass
(
ensure_file_path_normalized
(
"../
../a/..
/../b/c/d/../../e"
,
"b/e"
,
PATH_AS_SUFFIX
));
must_pass
(
ensure_file_path_normalized
(
"../
a
/../b/c/d/../../e"
,
"b/e"
,
PATH_AS_SUFFIX
));
must_fail
(
ensure_file_path_normalized
(
"...."
,
NULL
,
0
));
must_fail
(
ensure_file_path_normalized
(
"...."
,
NULL
,
0
));
must_fail
(
ensure_file_path_normalized
(
"..."
,
NULL
,
0
));
must_fail
(
ensure_file_path_normalized
(
"..."
,
NULL
,
0
));
must_fail
(
ensure_file_path_normalized
(
"./..."
,
NULL
,
0
));
must_fail
(
ensure_file_path_normalized
(
"./..."
,
NULL
,
0
));
...
@@ -309,7 +309,7 @@ BEGIN_TEST(path4, "validate and prettify a path to a folder")
...
@@ -309,7 +309,7 @@ BEGIN_TEST(path4, "validate and prettify a path to a folder")
must_pass
(
ensure_dir_path_normalized
(
"d1/s1///s2/..//../s3/"
,
"d1/s3/"
,
CWD_AS_PREFIX
|
PATH_AS_SUFFIX
));
must_pass
(
ensure_dir_path_normalized
(
"d1/s1///s2/..//../s3/"
,
"d1/s3/"
,
CWD_AS_PREFIX
|
PATH_AS_SUFFIX
));
must_pass
(
ensure_dir_path_normalized
(
"d1/s1//../s2/../../d2"
,
"d2/"
,
CWD_AS_PREFIX
|
PATH_AS_SUFFIX
));
must_pass
(
ensure_dir_path_normalized
(
"d1/s1//../s2/../../d2"
,
"d2/"
,
CWD_AS_PREFIX
|
PATH_AS_SUFFIX
));
must_pass
(
ensure_dir_path_normalized
(
"dir/sub/../"
,
"dir/"
,
CWD_AS_PREFIX
|
PATH_AS_SUFFIX
));
must_pass
(
ensure_dir_path_normalized
(
"dir/sub/../"
,
"dir/"
,
CWD_AS_PREFIX
|
PATH_AS_SUFFIX
));
must_pass
(
ensure_dir_path_normalized
(
"../
../a/..
/../b/c/d/../../e"
,
"b/e/"
,
PATH_AS_SUFFIX
));
must_pass
(
ensure_dir_path_normalized
(
"../
a
/../b/c/d/../../e"
,
"b/e/"
,
PATH_AS_SUFFIX
));
must_fail
(
ensure_dir_path_normalized
(
"...."
,
NULL
,
0
));
must_fail
(
ensure_dir_path_normalized
(
"...."
,
NULL
,
0
));
must_fail
(
ensure_dir_path_normalized
(
"..."
,
NULL
,
0
));
must_fail
(
ensure_dir_path_normalized
(
"..."
,
NULL
,
0
));
must_fail
(
ensure_dir_path_normalized
(
"./..."
,
NULL
,
0
));
must_fail
(
ensure_dir_path_normalized
(
"./..."
,
NULL
,
0
));
...
...
tests/t08-tag.c
View file @
55c197cd
...
@@ -119,13 +119,10 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
...
@@ -119,13 +119,10 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
END_TEST
END_TEST
BEGIN_TEST
(
write1
,
"write a tag to the repository which points to an unknown oid
and read it again
"
)
BEGIN_TEST
(
write1
,
"write a tag to the repository which points to an unknown oid
should fail
"
)
git_repository
*
repo
;
git_repository
*
repo
;
git_tag
*
tag
;
git_oid
target_id
,
tag_id
;
git_oid
target_id
,
tag_id
;
const
git_signature
*
tagger
;
const
git_signature
*
tagger
;
git_reference
*
ref_tag
;
git_object
*
zombie
;
must_pass
(
git_repository_open
(
&
repo
,
REPOSITORY_FOLDER
));
must_pass
(
git_repository_open
(
&
repo
,
REPOSITORY_FOLDER
));
...
@@ -135,7 +132,7 @@ BEGIN_TEST(write1, "write a tag to the repository which points to an unknown oid
...
@@ -135,7 +132,7 @@ BEGIN_TEST(write1, "write a tag to the repository which points to an unknown oid
tagger
=
git_signature_new
(
TAGGER_NAME
,
TAGGER_EMAIL
,
123456789
,
60
);
tagger
=
git_signature_new
(
TAGGER_NAME
,
TAGGER_EMAIL
,
123456789
,
60
);
must_be_true
(
tagger
!=
NULL
);
must_be_true
(
tagger
!=
NULL
);
must_
pass
(
git_tag_create
(
must_
fail
(
git_tag_create
(
&
tag_id
,
/* out id */
&
tag_id
,
/* out id */
repo
,
repo
,
"the-zombie-tag"
,
"the-zombie-tag"
,
...
@@ -146,17 +143,6 @@ BEGIN_TEST(write1, "write a tag to the repository which points to an unknown oid
...
@@ -146,17 +143,6 @@ BEGIN_TEST(write1, "write a tag to the repository which points to an unknown oid
git_signature_free
((
git_signature
*
)
tagger
);
git_signature_free
((
git_signature
*
)
tagger
);
must_pass
(
git_tag_lookup
(
&
tag
,
repo
,
&
tag_id
));
/* The non existent target can not be looked up */
must_fail
(
git_tag_target
(
&
zombie
,
tag
));
must_pass
(
git_reference_lookup
(
&
ref_tag
,
repo
,
"refs/tags/the-zombie-tag"
));
must_pass
(
git_reference_delete
(
ref_tag
));
must_pass
(
remove_loose_object
(
REPOSITORY_FOLDER
,
(
git_object
*
)
tag
));
git_tag_close
(
tag
);
git_repository_free
(
repo
);
git_repository_free
(
repo
);
END_TEST
END_TEST
...
...
tests/t09-tree.c
View file @
55c197cd
...
@@ -29,6 +29,10 @@
...
@@ -29,6 +29,10 @@
static
const
char
*
tree_oid
=
"1810dff58d8a660512d4832e740f692884338ccd"
;
static
const
char
*
tree_oid
=
"1810dff58d8a660512d4832e740f692884338ccd"
;
static
const
char
*
blob_oid
=
"fa49b077972391ad58037050f2a75f74e3671e92"
;
static
const
char
*
first_tree
=
"181037049a54a1eb5fab404658a3a250b44335d7"
;
static
const
char
*
second_tree
=
"f60079018b664e4e79329a7ef9559c8d9e0378d1"
;
#if 0
#if 0
static int print_tree(git_repository *repo, const git_oid *tree_oid, int depth)
static int print_tree(git_repository *repo, const git_oid *tree_oid, int depth)
{
{
...
@@ -126,11 +130,33 @@ BEGIN_TEST(write0, "write a tree from an index")
...
@@ -126,11 +130,33 @@ BEGIN_TEST(write0, "write a tree from an index")
END_TEST
END_TEST
#endif
#endif
BEGIN_TEST
(
write2
,
"write a tree from a memory"
)
git_repository
*
repo
;
git_treebuilder
*
builder
;
git_tree
*
tree
;
git_oid
id
,
bid
,
rid
,
id2
;
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
git_oid_mkstr
(
&
id
,
first_tree
);
git_oid_mkstr
(
&
id2
,
second_tree
);
git_oid_mkstr
(
&
bid
,
blob_oid
);
//create a second tree from first tree using `git_treebuilder_insert` on REPOSITORY_FOLDER.
must_pass
(
git_tree_lookup
(
&
tree
,
repo
,
&
id
));
must_pass
(
git_treebuilder_create
(
&
builder
,
tree
));
must_pass
(
git_treebuilder_insert
(
NULL
,
builder
,
"new.txt"
,
&
bid
,
0100644
));
must_pass
(
git_treebuilder_write
(
&
rid
,
repo
,
builder
));
must_be_true
(
git_oid_cmp
(
&
rid
,
&
id2
)
==
0
);
close_temp_repo
(
repo
);
END_TEST
BEGIN_SUITE
(
tree
)
BEGIN_SUITE
(
tree
)
//ADD_TEST(print0);
//ADD_TEST(print0);
ADD_TEST
(
read0
);
ADD_TEST
(
read0
);
ADD_TEST
(
read1
);
ADD_TEST
(
read1
);
//ADD_TEST(write0);
//ADD_TEST(write0);
//ADD_TEST(write1);
//ADD_TEST(write1);
ADD_TEST
(
write2
);
END_SUITE
END_SUITE
tests/t10-refs.c
View file @
55c197cd
...
@@ -456,6 +456,11 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
...
@@ -456,6 +456,11 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
must_be_true
((
reference
->
type
&
GIT_REF_PACKED
)
==
0
);
must_be_true
((
reference
->
type
&
GIT_REF_PACKED
)
==
0
);
must_be_true
(
strcmp
(
reference
->
name
,
loose_tag_ref_name
)
==
0
);
must_be_true
(
strcmp
(
reference
->
name
,
loose_tag_ref_name
)
==
0
);
/*
* We are now trying to pack also a loose reference
* called `points_to_blob`, to make sure we can properly
* pack weak tags
*/
must_pass
(
git_reference_packall
(
repo
));
must_pass
(
git_reference_packall
(
repo
));
/* Ensure the packed-refs file exists */
/* Ensure the packed-refs file exists */
...
@@ -877,10 +882,10 @@ BEGIN_TEST(list0, "try to list all the references in our test repo")
...
@@ -877,10 +882,10 @@ BEGIN_TEST(list0, "try to list all the references in our test repo")
printf("# %s\n", ref_list.strings[i]);
printf("# %s\n", ref_list.strings[i]);
}*/
}*/
/* We have exactly
7
refs in total if we include the packed ones:
/* We have exactly
8
refs in total if we include the packed ones:
* there is a reference that exists both in the packfile and as
* there is a reference that exists both in the packfile and as
* loose, but we only list it once */
* loose, but we only list it once */
must_be_true
(
ref_list
.
count
==
7
);
must_be_true
(
ref_list
.
count
==
8
);
git_strarray_free
(
&
ref_list
);
git_strarray_free
(
&
ref_list
);
git_repository_free
(
repo
);
git_repository_free
(
repo
);
...
...
tests/t12-repo.c
View file @
55c197cd
...
@@ -194,6 +194,8 @@ BEGIN_TEST(open0, "Open a bare repository that has just been initialized by git"
...
@@ -194,6 +194,8 @@ BEGIN_TEST(open0, "Open a bare repository that has just been initialized by git"
must_pass
(
remove_placeholders
(
TEMP_REPO_FOLDER
,
"dummy-marker.txt"
));
must_pass
(
remove_placeholders
(
TEMP_REPO_FOLDER
,
"dummy-marker.txt"
));
must_pass
(
git_repository_open
(
&
repo
,
TEMP_REPO_FOLDER
));
must_pass
(
git_repository_open
(
&
repo
,
TEMP_REPO_FOLDER
));
must_be_true
(
git_repository_path
(
repo
)
!=
NULL
);
must_be_true
(
git_repository_workdir
(
repo
)
==
NULL
);
git_repository_free
(
repo
);
git_repository_free
(
repo
);
must_pass
(
rmdir_recurs
(
TEMP_REPO_FOLDER
));
must_pass
(
rmdir_recurs
(
TEMP_REPO_FOLDER
));
...
@@ -211,6 +213,8 @@ BEGIN_TEST(open1, "Open a standard repository that has just been initialized by
...
@@ -211,6 +213,8 @@ BEGIN_TEST(open1, "Open a standard repository that has just been initialized by
must_pass
(
remove_placeholders
(
DEST_REPOSITORY_FOLDER
,
"dummy-marker.txt"
));
must_pass
(
remove_placeholders
(
DEST_REPOSITORY_FOLDER
,
"dummy-marker.txt"
));
must_pass
(
git_repository_open
(
&
repo
,
DEST_REPOSITORY_FOLDER
));
must_pass
(
git_repository_open
(
&
repo
,
DEST_REPOSITORY_FOLDER
));
must_be_true
(
git_repository_path
(
repo
)
!=
NULL
);
must_be_true
(
git_repository_workdir
(
repo
)
!=
NULL
);
git_repository_free
(
repo
);
git_repository_free
(
repo
);
must_pass
(
rmdir_recurs
(
TEMP_REPO_FOLDER
));
must_pass
(
rmdir_recurs
(
TEMP_REPO_FOLDER
));
...
@@ -244,6 +248,19 @@ BEGIN_TEST(open2, "Open a bare repository with a relative path escaping out of t
...
@@ -244,6 +248,19 @@ BEGIN_TEST(open2, "Open a bare repository with a relative path escaping out of t
rmdir_recurs
(
TEMP_REPO_FOLDER
);
rmdir_recurs
(
TEMP_REPO_FOLDER
);
END_TEST
END_TEST
BEGIN_TEST
(
empty0
,
"test if a repository is empty or not"
)
git_repository
*
repo_empty
,
*
repo_normal
;
must_pass
(
git_repository_open
(
&
repo_normal
,
REPOSITORY_FOLDER
));
must_be_true
(
git_repository_is_empty
(
repo_normal
)
==
0
);
git_repository_free
(
repo_normal
);
must_pass
(
git_repository_open
(
&
repo_empty
,
EMPTY_BARE_REPOSITORY_FOLDER
));
must_be_true
(
git_repository_is_empty
(
repo_empty
)
==
1
);
git_repository_free
(
repo_empty
);
END_TEST
BEGIN_SUITE
(
repository
)
BEGIN_SUITE
(
repository
)
ADD_TEST
(
odb0
);
ADD_TEST
(
odb0
);
ADD_TEST
(
odb1
);
ADD_TEST
(
odb1
);
...
@@ -253,5 +270,6 @@ BEGIN_SUITE(repository)
...
@@ -253,5 +270,6 @@ BEGIN_SUITE(repository)
ADD_TEST
(
open0
);
ADD_TEST
(
open0
);
ADD_TEST
(
open1
);
ADD_TEST
(
open1
);
ADD_TEST
(
open2
);
ADD_TEST
(
open2
);
ADD_TEST
(
empty0
);
END_SUITE
END_SUITE
tests/t14-hiredis.c
0 → 100644
View file @
55c197cd
/*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2,
* as published by the Free Software Foundation.
*
* In addition to the permissions in the GNU General Public License,
* the authors give you unlimited permission to link the compiled
* version of this file into combinations with other programs,
* and to distribute those combinations without any restriction
* coming from the use of this file. (The General Public License
* restrictions do apply in other respects; for example, they cover
* modification of the file, and distribution when not linked into
* a combined executable.)
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "test_lib.h"
#include "odb.h"
#ifdef GIT2_HIREDIS_BACKEND
#include "t03-data.h"
#include "fileops.h"
#include "git2/odb_backend.h"
static
int
cmp_objects
(
git_odb_object
*
odb_obj
,
git_rawobj
*
raw
)
{
if
(
raw
->
type
!=
git_odb_object_type
(
odb_obj
))
return
-
1
;
if
(
raw
->
len
!=
git_odb_object_size
(
odb_obj
))
return
-
1
;
if
((
raw
->
len
>
0
)
&&
(
memcmp
(
raw
->
data
,
git_odb_object_data
(
odb_obj
),
raw
->
len
)
!=
0
))
return
-
1
;
return
0
;
}
static
git_odb
*
open_hiredis_odb
(
void
)
{
git_odb
*
odb
;
git_odb_backend
*
hiredis
;
if
(
git_odb_new
(
&
odb
)
<
GIT_SUCCESS
)
return
NULL
;
if
(
git_odb_backend_hiredis
(
&
hiredis
,
"127.0.0.1"
,
6379
)
<
GIT_SUCCESS
)
return
NULL
;
if
(
git_odb_add_backend
(
odb
,
hiredis
,
0
)
<
GIT_SUCCESS
)
return
NULL
;
return
odb
;
}
#define TEST_WRITE(PTR) {\
git_odb *db; \
git_oid id1, id2; \
git_odb_object *obj; \
db = open_hiredis_odb(); \
must_be_true(db != NULL); \
must_pass(git_oid_mkstr(&id1, PTR.id)); \
must_pass(git_odb_write(&id2, db, PTR##_obj.data, PTR##_obj.len, PTR##_obj.type)); \
must_be_true(git_oid_cmp(&id1, &id2) == 0); \
must_pass(git_odb_read(&obj, db, &id1)); \
must_pass(cmp_objects(obj, &PTR##_obj)); \
git_odb_object_close(obj); \
git_odb_close(db); \
}
BEGIN_TEST
(
hiredis0
,
"write a commit, read it back (hiredis backend)"
)
TEST_WRITE
(
commit
);
END_TEST
BEGIN_TEST
(
hiredis1
,
"write a tree, read it back (hiredis backend)"
)
TEST_WRITE
(
tree
);
END_TEST
BEGIN_TEST
(
hiredis2
,
"write a tag, read it back (hiredis backend)"
)
TEST_WRITE
(
tag
);
END_TEST
BEGIN_TEST
(
hiredis3
,
"write a zero-byte entry, read it back (hiredis backend)"
)
TEST_WRITE
(
zero
);
END_TEST
BEGIN_TEST
(
hiredis4
,
"write a one-byte entry, read it back (hiredis backend)"
)
TEST_WRITE
(
one
);
END_TEST
BEGIN_TEST
(
hiredis5
,
"write a two-byte entry, read it back (hiredis backend)"
)
TEST_WRITE
(
two
);
END_TEST
BEGIN_TEST
(
hiredis6
,
"write some bytes in an entry, read it back (hiredis backend)"
)
TEST_WRITE
(
some
);
END_TEST
BEGIN_SUITE
(
hiredis
)
ADD_TEST
(
hiredis0
);
ADD_TEST
(
hiredis1
);
ADD_TEST
(
hiredis2
);
ADD_TEST
(
hiredis3
);
ADD_TEST
(
hiredis4
);
ADD_TEST
(
hiredis5
);
ADD_TEST
(
hiredis6
);
END_SUITE
#else
/* no hiredis builtin */
BEGIN_SUITE
(
hiredis
)
/* empty */
END_SUITE
#endif
tests/t1
4
-config.c
→
tests/t1
5
-config.c
View file @
55c197cd
File moved
tests/test_main.c
View file @
55c197cd
...
@@ -41,6 +41,7 @@ DECLARE_SUITE(tag);
...
@@ -41,6 +41,7 @@ DECLARE_SUITE(tag);
DECLARE_SUITE
(
tree
);
DECLARE_SUITE
(
tree
);
DECLARE_SUITE
(
refs
);
DECLARE_SUITE
(
refs
);
DECLARE_SUITE
(
sqlite
);
DECLARE_SUITE
(
sqlite
);
DECLARE_SUITE
(
hiredis
);
DECLARE_SUITE
(
repository
);
DECLARE_SUITE
(
repository
);
DECLARE_SUITE
(
threads
);
DECLARE_SUITE
(
threads
);
DECLARE_SUITE
(
config
);
DECLARE_SUITE
(
config
);
...
@@ -60,6 +61,7 @@ static libgit2_suite suite_methods[]= {
...
@@ -60,6 +61,7 @@ static libgit2_suite suite_methods[]= {
SUITE_NAME
(
sqlite
),
SUITE_NAME
(
sqlite
),
SUITE_NAME
(
repository
),
SUITE_NAME
(
repository
),
SUITE_NAME
(
threads
),
SUITE_NAME
(
threads
),
SUITE_NAME
(
hiredis
),
SUITE_NAME
(
config
),
SUITE_NAME
(
config
),
};
};
...
...
wscript
View file @
55c197cd
from __future__ import with_statement
from waflib.Context import Context
from waflib.Context import Context
from waflib.Build import BuildContext, CleanContext, \
from waflib.Build import BuildContext, CleanContext, \
InstallContext, UninstallContext
InstallContext, UninstallContext
...
@@ -16,7 +17,7 @@ CFLAGS_WIN32_L = ['/RELEASE'] # used for /both/ debug and release builds.
...
@@ -16,7 +17,7 @@ CFLAGS_WIN32_L = ['/RELEASE'] # used for /both/ debug and release builds.
# sets the module's checksum in the header.
# sets the module's checksum in the header.
CFLAGS_WIN32_L_DBG = ['/DEBUG']
CFLAGS_WIN32_L_DBG = ['/DEBUG']
ALL_LIBS = ['crypto', 'pthread', 'sqlite3']
ALL_LIBS = ['crypto', 'pthread', 'sqlite3'
, 'hiredis'
]
def options(opt):
def options(opt):
opt.load('compiler_c')
opt.load('compiler_c')
...
@@ -31,6 +32,8 @@ PPC optimized version (ppc) or the SHA1 functions from OpenSSL (openssl)")
...
@@ -31,6 +32,8 @@ PPC optimized version (ppc) or the SHA1 functions from OpenSSL (openssl)")
help='Select target architecture (ia64, x64, x86, x86_amd64, x86_ia64)')
help='Select target architecture (ia64, x64, x86, x86_amd64, x86_ia64)')
opt.add_option('--with-sqlite', action='store_true', default=False,
opt.add_option('--with-sqlite', action='store_true', default=False,
dest='use_sqlite', help='Enable sqlite support')
dest='use_sqlite', help='Enable sqlite support')
opt.add_option('--with-hiredis', action='store_true', default=False,
dest='use_hiredis', help='Enable redis support using hiredis')
opt.add_option('--threadsafe', action='store_true', default=False,
opt.add_option('--threadsafe', action='store_true', default=False,
help='Make libgit2 thread-safe (requires pthreads)')
help='Make libgit2 thread-safe (requires pthreads)')
...
@@ -72,6 +75,12 @@ def configure(conf):
...
@@ -72,6 +75,12 @@ def configure(conf):
lib='sqlite3', uselib_store='sqlite3', install_path=None, mandatory=False):
lib='sqlite3', uselib_store='sqlite3', install_path=None, mandatory=False):
conf.env.DEFINES += ['GIT2_SQLITE_BACKEND']
conf.env.DEFINES += ['GIT2_SQLITE_BACKEND']
# check for hiredis
if conf.options.use_hiredis and conf.check_cc(
lib='hiredis', uselib_store='hiredis', install_path=None, mandatory=False):
conf.env.DEFINES += ['GIT2_HIREDIS_BACKEND']
if conf.options.sha1 not in ['openssl', 'ppc', 'builtin']:
if conf.options.sha1 not in ['openssl', 'ppc', 'builtin']:
conf.fatal('Invalid SHA1 option')
conf.fatal('Invalid SHA1 option')
...
...
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