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
40e73d6f
Commit
40e73d6f
authored
Dec 09, 2011
by
Vicent Marti
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'arrbee/git-buf-for-paths' into development
Conflicts: tests-clay/clay_main.c
parents
e9238687
97769280
Hide whitespace changes
Inline
Side-by-side
Showing
47 changed files
with
1852 additions
and
1198 deletions
+1852
-1198
src/blob.c
+29
-22
src/buffer.c
+74
-22
src/buffer.h
+66
-13
src/commit.c
+2
-1
src/config.c
+48
-16
src/config.h
+3
-0
src/fetch.c
+14
-8
src/filebuf.c
+4
-3
src/fileops.c
+114
-67
src/fileops.h
+24
-7
src/index.c
+6
-16
src/indexer.c
+34
-16
src/odb.c
+17
-10
src/odb_loose.c
+170
-113
src/odb_pack.c
+29
-23
src/path.c
+68
-99
src/path.h
+15
-22
src/pkt.c
+4
-9
src/posix.c
+2
-1
src/reflog.c
+74
-45
src/refs.c
+119
-64
src/refspec.c
+18
-0
src/refspec.h
+12
-0
src/remote.c
+8
-8
src/repository.c
+224
-181
src/signature.c
+2
-0
src/status.c
+94
-73
src/tag.c
+63
-57
src/transports/git.c
+1
-1
src/transports/http.c
+10
-9
src/tree.c
+46
-34
src/win32/posix_w32.c
+20
-15
tests-clay/clay.h
+1
-0
tests-clay/clay_libgit2.h
+9
-0
tests-clay/clay_main.c
+4
-3
tests-clay/core/buffer.c
+38
-16
tests-clay/core/dirent.c
+25
-23
tests-clay/core/path.c
+115
-18
tests-clay/core/rmdir.c
+19
-15
tests-clay/repo/init.c
+6
-4
tests-clay/repo/open.c
+9
-8
tests/t00-core.c
+76
-68
tests/t10-refs.c
+45
-35
tests/t12-repo.c
+26
-17
tests/t18-status.c
+4
-3
tests/test_helpers.c
+60
-32
tests/test_helpers.h
+1
-1
No files found.
src/blob.c
View file @
40e73d6f
...
...
@@ -67,12 +67,13 @@ int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *b
int
git_blob_create_fromfile
(
git_oid
*
oid
,
git_repository
*
repo
,
const
char
*
path
)
{
int
error
,
islnk
;
int
error
=
GIT_SUCCESS
;
int
islnk
=
0
;
int
fd
=
0
;
char
full_path
[
GIT_PATH_MAX
]
;
git_buf
full_path
=
GIT_BUF_INIT
;
char
buffer
[
2048
];
git_off_t
size
;
git_odb_stream
*
stream
;
git_odb_stream
*
stream
=
NULL
;
struct
stat
st
;
const
char
*
workdir
;
git_odb
*
odb
;
...
...
@@ -81,11 +82,14 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
if
(
workdir
==
NULL
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to create blob. (No working directory found)"
);
git_path_join
(
full_path
,
workdir
,
path
);
error
=
git_buf_joinpath
(
&
full_path
,
workdir
,
path
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
error
=
p_lstat
(
full_path
,
&
st
);
error
=
p_lstat
(
full_path
.
ptr
,
&
st
);
if
(
error
<
0
)
{
return
git__throw
(
GIT_EOSERR
,
"Failed to stat blob. %s"
,
strerror
(
errno
));
error
=
git__throw
(
GIT_EOSERR
,
"Failed to stat blob. %s"
,
strerror
(
errno
));
goto
cleanup
;
}
islnk
=
S_ISLNK
(
st
.
st_mode
);
...
...
@@ -93,18 +97,18 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
goto
cleanup
;
if
(
!
islnk
)
{
if
((
fd
=
p_open
(
full_path
,
O_RDONLY
))
<
0
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to create blob. Could not open '%s'"
,
full_path
);
if
((
fd
=
p_open
(
full_path
.
ptr
,
O_RDONLY
))
<
0
)
{
error
=
git__throw
(
GIT_ENOTFOUND
,
"Failed to create blob. Could not open '%s'"
,
full_path
.
ptr
);
goto
cleanup
;
}
}
if
((
error
=
git_odb_open_wstream
(
&
stream
,
odb
,
(
size_t
)
size
,
GIT_OBJ_BLOB
))
<
GIT_SUCCESS
)
{
if
(
!
islnk
)
p_close
(
fd
);
return
git__rethrow
(
error
,
"Failed to create blob"
);
}
if
((
error
=
git_odb_open_wstream
(
&
stream
,
odb
,
(
size_t
)
size
,
GIT_OBJ_BLOB
))
<
GIT_SUCCESS
)
goto
cleanup
;
while
(
size
>
0
)
{
ssize_t
read_len
;
...
...
@@ -112,13 +116,11 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
if
(
!
islnk
)
read_len
=
p_read
(
fd
,
buffer
,
sizeof
(
buffer
));
else
read_len
=
p_readlink
(
full_path
,
buffer
,
sizeof
(
buffer
));
read_len
=
p_readlink
(
full_path
.
ptr
,
buffer
,
sizeof
(
buffer
));
if
(
read_len
<
0
)
{
if
(
!
islnk
)
p_close
(
fd
);
stream
->
free
(
stream
);
return
git__throw
(
GIT_EOSERR
,
"Failed to create blob. Can't read full file"
);
error
=
git__throw
(
GIT_EOSERR
,
"Failed to create blob. Can't read full file"
);
goto
cleanup
;
}
stream
->
write
(
stream
,
buffer
,
read_len
);
...
...
@@ -126,10 +128,15 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
}
error
=
stream
->
finalize_write
(
oid
,
stream
);
stream
->
free
(
stream
);
if
(
!
islnk
)
cleanup:
if
(
stream
)
stream
->
free
(
stream
);
if
(
!
islnk
&&
fd
)
p_close
(
fd
);
git_buf_free
(
&
full_path
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to create blob"
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to create blob"
);
}
src/buffer.c
View file @
40e73d6f
...
...
@@ -15,7 +15,8 @@ char git_buf_initbuf[1];
#define ENSURE_SIZE(b, d) \
if ((ssize_t)(d) > buf->asize && git_buf_grow(b, (d)) < GIT_SUCCESS)\
return;
return GIT_ENOMEM;
void
git_buf_init
(
git_buf
*
buf
,
size_t
initial_size
)
{
...
...
@@ -29,6 +30,14 @@ void git_buf_init(git_buf *buf, size_t initial_size)
int
git_buf_grow
(
git_buf
*
buf
,
size_t
target_size
)
{
int
error
=
git_buf_try_grow
(
buf
,
target_size
);
if
(
error
!=
GIT_SUCCESS
)
buf
->
asize
=
-
1
;
return
error
;
}
int
git_buf_try_grow
(
git_buf
*
buf
,
size_t
target_size
)
{
char
*
new_ptr
;
size_t
new_size
;
...
...
@@ -55,10 +64,9 @@ int git_buf_grow(git_buf *buf, size_t target_size)
new_size
=
(
new_size
+
7
)
&
~
7
;
new_ptr
=
git__realloc
(
new_ptr
,
new_size
);
if
(
!
new_ptr
)
{
buf
->
asize
=
-
1
;
/* if realloc fails, return without modifying the git_buf */
if
(
!
new_ptr
)
return
GIT_ENOMEM
;
}
buf
->
asize
=
new_size
;
buf
->
ptr
=
new_ptr
;
...
...
@@ -93,7 +101,12 @@ int git_buf_oom(const git_buf *buf)
return
(
buf
->
asize
<
0
);
}
void
git_buf_set
(
git_buf
*
buf
,
const
char
*
data
,
size_t
len
)
int
git_buf_lasterror
(
const
git_buf
*
buf
)
{
return
(
buf
->
asize
<
0
)
?
GIT_ENOMEM
:
GIT_SUCCESS
;
}
int
git_buf_set
(
git_buf
*
buf
,
const
char
*
data
,
size_t
len
)
{
if
(
len
==
0
||
data
==
NULL
)
{
git_buf_clear
(
buf
);
...
...
@@ -103,35 +116,38 @@ void git_buf_set(git_buf *buf, const char *data, size_t len)
buf
->
size
=
len
;
buf
->
ptr
[
buf
->
size
]
=
'\0'
;
}
return
GIT_SUCCESS
;
}
void
git_buf_sets
(
git_buf
*
buf
,
const
char
*
string
)
int
git_buf_sets
(
git_buf
*
buf
,
const
char
*
string
)
{
git_buf_set
(
buf
,
string
,
string
?
strlen
(
string
)
:
0
);
return
git_buf_set
(
buf
,
string
,
string
?
strlen
(
string
)
:
0
);
}
void
git_buf_putc
(
git_buf
*
buf
,
char
c
)
int
git_buf_putc
(
git_buf
*
buf
,
char
c
)
{
ENSURE_SIZE
(
buf
,
buf
->
size
+
2
);
buf
->
ptr
[
buf
->
size
++
]
=
c
;
buf
->
ptr
[
buf
->
size
]
=
'\0'
;
return
GIT_SUCCESS
;
}
void
git_buf_put
(
git_buf
*
buf
,
const
char
*
data
,
size_t
len
)
int
git_buf_put
(
git_buf
*
buf
,
const
char
*
data
,
size_t
len
)
{
ENSURE_SIZE
(
buf
,
buf
->
size
+
len
+
1
);
memmove
(
buf
->
ptr
+
buf
->
size
,
data
,
len
);
buf
->
size
+=
len
;
buf
->
ptr
[
buf
->
size
]
=
'\0'
;
return
GIT_SUCCESS
;
}
void
git_buf_puts
(
git_buf
*
buf
,
const
char
*
string
)
int
git_buf_puts
(
git_buf
*
buf
,
const
char
*
string
)
{
assert
(
string
);
git_buf_put
(
buf
,
string
,
strlen
(
string
));
return
git_buf_put
(
buf
,
string
,
strlen
(
string
));
}
void
git_buf_printf
(
git_buf
*
buf
,
const
char
*
format
,
...)
int
git_buf_printf
(
git_buf
*
buf
,
const
char
*
format
,
...)
{
int
len
;
va_list
arglist
;
...
...
@@ -145,16 +161,18 @@ void git_buf_printf(git_buf *buf, const char *format, ...)
if
(
len
<
0
)
{
buf
->
asize
=
-
1
;
return
;
return
GIT_ENOMEM
;
}
if
(
len
+
1
<=
buf
->
asize
-
buf
->
size
)
{
buf
->
size
+=
len
;
return
;
break
;
}
ENSURE_SIZE
(
buf
,
buf
->
size
+
len
+
1
);
}
return
GIT_SUCCESS
;
}
const
char
*
git_buf_cstr
(
git_buf
*
buf
)
...
...
@@ -162,7 +180,7 @@ const char *git_buf_cstr(git_buf *buf)
return
buf
->
ptr
;
}
void
git_buf_copy_cstr
(
char
*
data
,
size_t
datasize
,
git_buf
*
buf
)
void
git_buf_copy_cstr
(
char
*
data
,
size_t
datasize
,
const
git_buf
*
buf
)
{
size_t
copylen
;
...
...
@@ -190,6 +208,14 @@ void git_buf_consume(git_buf *buf, const char *end)
}
}
void
git_buf_truncate
(
git_buf
*
buf
,
ssize_t
len
)
{
if
(
len
<
buf
->
size
)
{
buf
->
size
=
len
;
buf
->
ptr
[
buf
->
size
]
=
'\0'
;
}
}
void
git_buf_swap
(
git_buf
*
buf_a
,
git_buf
*
buf_b
)
{
git_buf
t
=
*
buf_a
;
...
...
@@ -197,7 +223,7 @@ void git_buf_swap(git_buf *buf_a, git_buf *buf_b)
*
buf_b
=
t
;
}
char
*
git_buf_
take_cstr
(
git_buf
*
buf
)
char
*
git_buf_
detach
(
git_buf
*
buf
)
{
char
*
data
=
buf
->
ptr
;
...
...
@@ -209,18 +235,34 @@ char *git_buf_take_cstr(git_buf *buf)
return
data
;
}
void
git_buf_
join_n
(
git_buf
*
buf
,
char
separator
,
int
nbuf
,
...
)
void
git_buf_
attach
(
git_buf
*
buf
,
char
*
ptr
,
ssize_t
asize
)
{
/* Make two passes to avoid multiple reallocation */
git_buf_free
(
buf
);
if
(
ptr
)
{
buf
->
ptr
=
ptr
;
buf
->
size
=
strlen
(
ptr
);
if
(
asize
)
buf
->
asize
=
(
asize
<
buf
->
size
)
?
buf
->
size
+
1
:
asize
;
else
/* pass 0 to fall back on strlen + 1 */
buf
->
asize
=
buf
->
size
+
1
;
}
else
{
git_buf_grow
(
buf
,
asize
);
}
}
int
git_buf_join_n
(
git_buf
*
buf
,
char
separator
,
int
nbuf
,
...)
{
va_list
ap
;
int
i
;
int
i
,
error
=
GIT_SUCCESS
;
size_t
total_size
=
0
;
char
*
out
;
if
(
buf
->
size
>
0
&&
buf
->
ptr
[
buf
->
size
-
1
]
!=
separator
)
++
total_size
;
/* space for initial separator */
/* Make two passes to avoid multiple reallocation */
va_start
(
ap
,
nbuf
);
for
(
i
=
0
;
i
<
nbuf
;
++
i
)
{
const
char
*
segment
;
...
...
@@ -237,7 +279,10 @@ void git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
}
va_end
(
ap
);
ENSURE_SIZE
(
buf
,
buf
->
size
+
total_size
+
1
);
/* expand buffer if needed */
if
(
total_size
>
0
&&
(
error
=
git_buf_grow
(
buf
,
buf
->
size
+
total_size
+
1
))
<
GIT_SUCCESS
)
return
error
;
out
=
buf
->
ptr
+
buf
->
size
;
...
...
@@ -274,14 +319,17 @@ void git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
/* set size based on num characters actually written */
buf
->
size
=
out
-
buf
->
ptr
;
buf
->
ptr
[
buf
->
size
]
=
'\0'
;
return
error
;
}
void
git_buf_join
(
int
git_buf_join
(
git_buf
*
buf
,
char
separator
,
const
char
*
str_a
,
const
char
*
str_b
)
{
int
error
=
GIT_SUCCESS
;
size_t
strlen_a
=
strlen
(
str_a
);
size_t
strlen_b
=
strlen
(
str_b
);
int
need_sep
=
0
;
...
...
@@ -293,7 +341,9 @@ void git_buf_join(
need_sep
=
1
;
}
ENSURE_SIZE
(
buf
,
strlen_a
+
strlen_b
+
need_sep
+
1
);
error
=
git_buf_grow
(
buf
,
strlen_a
+
strlen_b
+
need_sep
+
1
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
memmove
(
buf
->
ptr
,
str_a
,
strlen_a
);
if
(
need_sep
)
...
...
@@ -302,4 +352,6 @@ void git_buf_join(
buf
->
size
=
strlen_a
+
strlen_b
+
need_sep
;
buf
->
ptr
[
buf
->
size
]
=
'\0'
;
return
error
;
}
src/buffer.h
View file @
40e73d6f
...
...
@@ -18,34 +18,87 @@ extern char git_buf_initbuf[];
#define GIT_BUF_INIT { git_buf_initbuf, 0, 0 }
/**
* Initialize a git_buf structure.
*
* For the cases where GIT_BUF_INIT cannot be used to do static
* initialization.
*/
void
git_buf_init
(
git_buf
*
buf
,
size_t
initial_size
);
/**
* Grow the buffer to hold at least `target_size` bytes.
*
* If the allocation fails, this will return an error and the buffer
* will be marked as invalid for future operations. The existing
* contents of the buffer will be preserved however.
* @return GIT_SUCCESS or GIT_ENOMEM on failure
*/
int
git_buf_grow
(
git_buf
*
buf
,
size_t
target_size
);
/**
* Attempt to grow the buffer to hold at least `target_size` bytes.
*
* This is just like `git_buf_grow` except that even if the allocation
* fails, the git_buf will still be left in a valid state.
*/
int
git_buf_try_grow
(
git_buf
*
buf
,
size_t
target_size
);
void
git_buf_free
(
git_buf
*
buf
);
void
git_buf_swap
(
git_buf
*
buf_a
,
git_buf
*
buf_b
);
char
*
git_buf_detach
(
git_buf
*
buf
);
void
git_buf_attach
(
git_buf
*
buf
,
char
*
ptr
,
ssize_t
asize
);
/**
* Test if there have been any reallocation failures with this git_buf.
*
* Any function that writes to a git_buf can fail due to memory allocation
* issues. If one fails, the git_buf will be marked with an OOM error and
* further calls to modify the buffer will fail. You just check
* git_buf_oom() at the end of your sequence and it will be true if you ran
* out of memory at any point with that buffer.
* further calls to modify the buffer will fail. Check git_buf_oom() at the
* end of your sequence and it will be true if you ran out of memory at any
* point with that buffer.
* @return 0 if no error, 1 if allocation error.
*/
int
git_buf_oom
(
const
git_buf
*
buf
);
void
git_buf_set
(
git_buf
*
buf
,
const
char
*
data
,
size_t
len
);
void
git_buf_sets
(
git_buf
*
buf
,
const
char
*
string
);
void
git_buf_putc
(
git_buf
*
buf
,
char
c
);
void
git_buf_put
(
git_buf
*
buf
,
const
char
*
data
,
size_t
len
);
void
git_buf_puts
(
git_buf
*
buf
,
const
char
*
string
);
void
git_buf_printf
(
git_buf
*
buf
,
const
char
*
format
,
...)
GIT_FORMAT_PRINTF
(
2
,
3
);
/**
* Just like git_buf_oom, except returns appropriate error code.
* @return GIT_ENOMEM if allocation error, GIT_SUCCESS if not.
*/
int
git_buf_lasterror
(
const
git_buf
*
buf
);
/*
* The functions below that return int values, will return GIT_ENOMEM
* if they fail to expand the git_buf when they are called, otherwise
* GIT_SUCCESS. Passing a git_buf that has failed an allocation will
* automatically return GIT_ENOMEM for all further calls. As a result,
* you can ignore the return code of these functions and call them in a
* series then just call git_buf_lasterror at the end.
*/
int
git_buf_set
(
git_buf
*
buf
,
const
char
*
data
,
size_t
len
);
int
git_buf_sets
(
git_buf
*
buf
,
const
char
*
string
);
int
git_buf_putc
(
git_buf
*
buf
,
char
c
);
int
git_buf_put
(
git_buf
*
buf
,
const
char
*
data
,
size_t
len
);
int
git_buf_puts
(
git_buf
*
buf
,
const
char
*
string
);
int
git_buf_printf
(
git_buf
*
buf
,
const
char
*
format
,
...)
GIT_FORMAT_PRINTF
(
2
,
3
);
void
git_buf_clear
(
git_buf
*
buf
);
void
git_buf_consume
(
git_buf
*
buf
,
const
char
*
end
);
void
git_buf_join_n
(
git_buf
*
buf
,
char
separator
,
int
nbuf
,
...);
void
git_buf_join
(
git_buf
*
buf
,
char
separator
,
const
char
*
str_a
,
const
char
*
str_b
);
void
git_buf_truncate
(
git_buf
*
buf
,
ssize_t
len
);
int
git_buf_join_n
(
git_buf
*
buf
,
char
separator
,
int
nbuf
,
...);
int
git_buf_join
(
git_buf
*
buf
,
char
separator
,
const
char
*
str_a
,
const
char
*
str_b
);
/**
* Join two strings as paths, inserting a slash between as needed.
* @return error code or GIT_SUCCESS
*/
GIT_INLINE
(
int
)
git_buf_joinpath
(
git_buf
*
buf
,
const
char
*
a
,
const
char
*
b
)
{
return
git_buf_join
(
buf
,
'/'
,
a
,
b
);
}
const
char
*
git_buf_cstr
(
git_buf
*
buf
);
char
*
git_buf_take_cstr
(
git_buf
*
buf
);
void
git_buf_copy_cstr
(
char
*
data
,
size_t
datasize
,
git_buf
*
buf
);
void
git_buf_copy_cstr
(
char
*
data
,
size_t
datasize
,
const
git_buf
*
buf
);
#define git_buf_PUTS(buf, str) git_buf_put(buf, str, sizeof(str) - 1)
...
...
src/commit.c
View file @
40e73d6f
...
...
@@ -129,7 +129,8 @@ int git_commit_create(
git_buf_puts
(
&
commit
,
message
);
if
(
git_buf_oom
(
&
commit
))
{
error
=
git__throw
(
GIT_ENOMEM
,
"Not enough memory to build the commit data"
);
error
=
git__throw
(
git_buf_lasterror
(
&
commit
),
"Not enough memory to build the commit data"
);
goto
cleanup
;
}
...
...
src/config.c
View file @
40e73d6f
...
...
@@ -330,9 +330,25 @@ int git_config_get_string(git_config *cfg, const char *name, const char **out)
int
git_config_find_global
(
char
*
global_config_path
)
{
const
char
*
home
;
git_buf
path
=
GIT_BUF_INIT
;
int
error
=
git_config_find_global_r
(
&
path
);
if
(
error
==
GIT_SUCCESS
)
{
if
(
path
.
size
>
GIT_PATH_MAX
)
error
=
git__throw
(
GIT_ESHORTBUFFER
,
"Path is too long"
);
else
git_buf_copy_cstr
(
global_config_path
,
GIT_PATH_MAX
,
&
path
);
}
git_buf_free
(
&
path
);
home
=
getenv
(
"HOME"
);
return
error
;
}
int
git_config_find_global_r
(
git_buf
*
path
)
{
int
error
;
const
char
*
home
=
getenv
(
"HOME"
);
#ifdef GIT_WIN32
if
(
home
==
NULL
)
...
...
@@ -342,10 +358,13 @@ int git_config_find_global(char *global_config_path)
if
(
home
==
NULL
)
return
git__throw
(
GIT_EOSERR
,
"Failed to open global config file. Cannot locate the user's home directory"
);
git_path_join
(
global_config_path
,
home
,
GIT_CONFIG_FILENAME
);
if
((
error
=
git_buf_joinpath
(
path
,
home
,
GIT_CONFIG_FILENAME
))
<
GIT_SUCCESS
)
return
error
;
if
(
git_futils_exists
(
global_config_path
)
<
GIT_SUCCESS
)
if
(
git_futils_exists
(
path
->
ptr
)
<
GIT_SUCCESS
)
{
git_buf_clear
(
path
);
return
git__throw
(
GIT_EOSERR
,
"Failed to open global config file. The file does not exist"
);
}
return
GIT_SUCCESS
;
}
...
...
@@ -353,7 +372,7 @@ int git_config_find_global(char *global_config_path)
#if GIT_WIN32
static
int
win32_find_system
(
char
*
system_config_path
)
static
int
win32_find_system
(
git_buf
*
system_config_path
)
{
const
wchar_t
*
query
=
L"%PROGRAMFILES%
\\
Git
\\
etc
\\
gitconfig"
;
wchar_t
*
apphome_utf16
;
...
...
@@ -378,25 +397,21 @@ static int win32_find_system(char *system_config_path)
apphome_utf8
=
gitwin_from_utf16
(
apphome_utf16
);
git__free
(
apphome_utf16
);
if
(
strlen
(
apphome_utf8
)
>=
GIT_PATH_MAX
)
{
git__free
(
apphome_utf8
);
return
git__throw
(
GIT_ESHORTBUFFER
,
"Path is too long"
);
}
git_buf_attach
(
system_config_path
,
apphome_utf8
,
0
);
strcpy
(
system_config_path
,
apphome_utf8
);
git__free
(
apphome_utf8
);
return
GIT_SUCCESS
;
}
#endif
int
git_config_find_system
(
char
*
system_config_path
)
int
git_config_find_system
_r
(
git_buf
*
system_config_path
)
{
const
char
*
etc
=
"/etc/gitconfig"
;
if
(
git_buf_sets
(
system_config_path
,
"/etc/gitconfig"
)
<
GIT_SUCCESS
)
return
git_buf_lasterror
(
system_config_path
);
if
(
git_futils_exists
(
etc
)
==
GIT_SUCCESS
)
{
memcpy
(
system_config_path
,
etc
,
strlen
(
etc
)
+
1
);
if
(
git_futils_exists
(
system_config_path
->
ptr
)
==
GIT_SUCCESS
)
return
GIT_SUCCESS
;
}
git_buf_clear
(
system_config_path
);
#if GIT_WIN32
return
win32_find_system
(
system_config_path
);
...
...
@@ -405,6 +420,23 @@ int git_config_find_system(char *system_config_path)
#endif
}
int
git_config_find_system
(
char
*
system_config_path
)
{
git_buf
path
=
GIT_BUF_INIT
;
int
error
=
git_config_find_system_r
(
&
path
);
if
(
error
==
GIT_SUCCESS
)
{
if
(
path
.
size
>
GIT_PATH_MAX
)
error
=
git__throw
(
GIT_ESHORTBUFFER
,
"Path is too long"
);
else
git_buf_copy_cstr
(
system_config_path
,
GIT_PATH_MAX
,
&
path
);
}
git_buf_free
(
&
path
);
return
error
;
}
int
git_config_open_global
(
git_config
**
out
)
{
int
error
;
...
...
src/config.h
View file @
40e73d6f
...
...
@@ -21,4 +21,7 @@ struct git_config {
git_vector
files
;
};
extern
int
git_config_find_global_r
(
git_buf
*
global_config_path
);
extern
int
git_config_find_system_r
(
git_buf
*
system_config_path
);
#endif
src/fetch.c
View file @
40e73d6f
...
...
@@ -115,25 +115,31 @@ int git_fetch_download_pack(char **out, git_remote *remote)
}
/* Receiving data from a socket and storing it is pretty much the same for git and HTTP */
int
git_fetch__download_pack
(
char
**
out
,
const
char
*
buffered
,
size_t
buffered_size
,
GIT_SOCKET
fd
,
git_repository
*
repo
)
int
git_fetch__download_pack
(
char
**
out
,
const
char
*
buffered
,
size_t
buffered_size
,
GIT_SOCKET
fd
,
git_repository
*
repo
)
{
git_filebuf
file
=
GIT_FILEBUF_INIT
;
int
error
;
char
buff
[
1024
],
path
[
GIT_PATH_MAX
];
char
buff
[
1024
];
git_buf
path
=
GIT_BUF_INIT
;
static
const
char
suff
[]
=
"/objects/pack/pack-received"
;
gitno_buffer
buf
;
git_path_join
(
path
,
repo
->
path_repository
,
suff
);
gitno_buffer_setup
(
&
buf
,
buff
,
sizeof
(
buff
),
fd
);
if
(
memcmp
(
buffered
,
"PACK"
,
strlen
(
"PACK"
)))
{
return
git__throw
(
GIT_ERROR
,
"The pack doesn't start with the signature"
);
}
error
=
git_filebuf_open
(
&
file
,
path
,
GIT_FILEBUF_TEMPORARY
);
error
=
git_buf_joinpath
(
&
path
,
repo
->
path_repository
,
suff
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_filebuf_open
(
&
file
,
path
.
ptr
,
GIT_FILEBUF_TEMPORARY
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
...
...
@@ -166,7 +172,7 @@ int git_fetch__download_pack(char **out, const char *buffered, size_t buffered_s
cleanup:
if
(
error
<
GIT_SUCCESS
)
git_filebuf_cleanup
(
&
file
);
git_buf_free
(
&
path
);
return
error
;
}
src/filebuf.c
View file @
40e73d6f
...
...
@@ -196,18 +196,19 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)
/* If we are writing to a temp file */
if
(
flags
&
GIT_FILEBUF_TEMPORARY
)
{
char
tmp_path
[
GIT_PATH_MAX
]
;
git_buf
tmp_path
=
GIT_BUF_INIT
;
/* Open the file as temporary for locking */
file
->
fd
=
git_futils_mktmp
(
tmp_path
,
path
);
file
->
fd
=
git_futils_mktmp
(
&
tmp_path
,
path
);
if
(
file
->
fd
<
0
)
{
git_buf_free
(
&
tmp_path
);
error
=
GIT_EOSERR
;
goto
cleanup
;
}
/* No original path */
file
->
path_original
=
NULL
;
file
->
path_lock
=
git_
_strdup
(
tmp_path
);
file
->
path_lock
=
git_
buf_detach
(
&
tmp_path
);
if
(
file
->
path_lock
==
NULL
)
{
error
=
GIT_ENOMEM
;
...
...
src/fileops.c
View file @
40e73d6f
...
...
@@ -10,35 +10,40 @@
int
git_futils_mkpath2file
(
const
char
*
file_path
,
const
mode_t
mode
)
{
int
error
=
GIT_SUCCESS
;
char
target_folder_path
[
GIT_PATH_MAX
]
;
int
error
;
git_buf
target_folder
=
GIT_BUF_INIT
;
error
=
git_path_dirname_r
(
target_folder_path
,
sizeof
(
target_folder_path
),
file_path
);
if
(
error
<
GIT_SUCCESS
)
error
=
git_path_dirname_r
(
&
target_folder
,
file_path
);
if
(
error
<
GIT_SUCCESS
)
{
git_buf_free
(
&
target_folder
);
return
git__throw
(
GIT_EINVALIDPATH
,
"Failed to recursively build `%s` tree structure. Unable to parse parent folder name"
,
file_path
);
}
else
{
/* reset error */
error
=
GIT_SUCCESS
;
}
/* Does the containing folder exist? */
if
(
git_futils_isdir
(
target_folder_path
))
{
git_path_join
(
target_folder_path
,
target_folder_path
,
""
);
/* Ensure there's a trailing slash */
if
(
git_futils_isdir
(
target_folder
.
ptr
)
!=
GIT_SUCCESS
)
/* Let's create the tree structure */
error
=
git_futils_mkdir_r
(
target_folder_path
,
mode
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
/* The callee already takes care of setting the correct error message. */
}
error
=
git_futils_mkdir_r
(
target_folder
.
ptr
,
NULL
,
mode
);
return
GIT_SUCCESS
;
git_buf_free
(
&
target_folder
);
return
error
;
}
int
git_futils_mktmp
(
char
*
path_out
,
const
char
*
filename
)
int
git_futils_mktmp
(
git_buf
*
path_out
,
const
char
*
filename
)
{
int
fd
;
strcpy
(
path_out
,
filename
);
strcat
(
path_out
,
"_git2_XXXXXX"
);
git_buf_sets
(
path_out
,
filename
);
git_buf_puts
(
path_out
,
"_git2_XXXXXX"
);
if
(
git_buf_oom
(
path_out
))
return
git__rethrow
(
git_buf_lasterror
(
path_out
),
"Failed to create temporary file for %s"
,
filename
);
if
((
fd
=
p_mkstemp
(
path_out
))
<
0
)
return
git__throw
(
GIT_EOSERR
,
"Failed to create temporary file %s"
,
path_out
);
if
((
fd
=
p_mkstemp
(
path_out
->
ptr
))
<
0
)
return
git__throw
(
GIT_EOSERR
,
"Failed to create temporary file %s"
,
path_out
->
ptr
);
return
fd
;
}
...
...
@@ -180,6 +185,14 @@ int git_futils_readbuffer(git_fbuffer *obj, const char *path)
return
git_futils_readbuffer_updated
(
obj
,
path
,
NULL
,
NULL
);
}
void
git_futils_fbuffer_rtrim
(
git_fbuffer
*
obj
)
{
unsigned
char
*
buff
=
obj
->
data
;
while
(
obj
->
len
>
0
&&
isspace
(
buff
[
obj
->
len
-
1
]))
obj
->
len
--
;
buff
[
obj
->
len
]
=
'\0'
;
}
void
git_futils_freebuffer
(
git_fbuffer
*
obj
)
{
assert
(
obj
);
...
...
@@ -215,76 +228,72 @@ GIT_INLINE(int) is_dot_or_dotdot(const char *name)
}
int
git_futils_direach
(
char
*
path
,
size_t
path_sz
,
int
(
*
fn
)(
void
*
,
char
*
),
git_buf
*
path
,
int
(
*
fn
)(
void
*
,
git_buf
*
),
void
*
arg
)
{
s
ize_t
wd_len
=
strlen
(
path
)
;
s
size_t
wd_len
;
DIR
*
dir
;
struct
dirent
*
de
;
if
(
!
wd_len
||
path_sz
<
wd_len
+
2
)
return
git__throw
(
GIT_EINVALIDARGS
,
"Failed to process `%s` tree structure. Path is either empty or buffer size is too short"
,
path
);
while
(
path
[
wd_len
-
1
]
==
'/'
)
wd_len
--
;
path
[
wd_len
++
]
=
'/'
;
path
[
wd_len
]
=
'\0'
;
if
(
git_path_to_dir
(
path
)
<
GIT_SUCCESS
)
return
git_buf_lasterror
(
path
);
dir
=
opendir
(
path
);
wd_len
=
path
->
size
;
dir
=
opendir
(
path
->
ptr
);
if
(
!
dir
)
return
git__throw
(
GIT_EOSERR
,
"Failed to process `%s` tree structure. An error occured while opening the directory"
,
path
);
return
git__throw
(
GIT_EOSERR
,
"Failed to process `%s` tree structure. An error occured while opening the directory"
,
path
->
ptr
);
while
((
de
=
readdir
(
dir
))
!=
NULL
)
{
size_t
de_len
;
int
result
;
if
(
is_dot_or_dotdot
(
de
->
d_name
))
continue
;
de_len
=
strlen
(
de
->
d_name
);
if
(
path_sz
<
wd_len
+
de_len
+
1
)
{
closedir
(
dir
);
return
git__throw
(
GIT_ERROR
,
"Failed to process `%s` tree structure. Buffer size is too short"
,
path
);
}
if
(
git_buf_puts
(
path
,
de
->
d_name
)
<
GIT_SUCCESS
)
return
git_buf_lasterror
(
path
);
strcpy
(
path
+
wd_len
,
de
->
d_name
);
result
=
fn
(
arg
,
path
);
if
(
result
<
GIT_SUCCESS
)
{
git_buf_truncate
(
path
,
wd_len
);
/* restore path */
if
(
result
!=
GIT_SUCCESS
)
{
closedir
(
dir
);
return
result
;
/* The callee is reponsible for setting the correct error message */
}
if
(
result
>
0
)
{
closedir
(
dir
);
return
result
;
}
}
closedir
(
dir
);
return
GIT_SUCCESS
;
}
int
git_futils_mkdir_r
(
const
char
*
path
,
const
mode_t
mode
)
int
git_futils_mkdir_r
(
const
char
*
path
,
const
char
*
base
,
const
mode_t
mode
)
{
int
error
,
root_path_offset
;
git_buf
make_path
=
GIT_BUF_INIT
;
size_t
start
;
char
*
pp
,
*
sp
;
char
*
path_copy
=
git__strdup
(
path
);
if
(
path_copy
==
NULL
)
return
GIT_ENOMEM
;
if
(
base
!=
NULL
)
{
start
=
strlen
(
base
);
error
=
git_buf_joinpath
(
&
make_path
,
base
,
path
);
}
else
{
start
=
0
;
error
=
git_buf_puts
(
&
make_path
,
path
);
}
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to create `%s` tree structure"
,
path
);
error
=
GIT_SUCCESS
;
pp
=
path_copy
;
pp
=
make_path
.
ptr
+
start
;
root_path_offset
=
git_path_root
(
pp
);
root_path_offset
=
git_path_root
(
make_path
.
ptr
);
if
(
root_path_offset
>
0
)
pp
+=
root_path_offset
;
/* On Windows, will skip the drive name (eg. C: or D:) */
while
(
error
==
GIT_SUCCESS
&&
(
sp
=
strchr
(
pp
,
'/'
))
!=
NULL
)
{
if
(
sp
!=
pp
&&
git_futils_isdir
(
path_copy
)
<
GIT_SUCCESS
)
{
if
(
sp
!=
pp
&&
git_futils_isdir
(
make_path
.
ptr
)
<
GIT_SUCCESS
)
{
*
sp
=
0
;
error
=
p_mkdir
(
path_copy
,
mode
);
error
=
p_mkdir
(
make_path
.
ptr
,
mode
);
/* Do not choke while trying to recreate an existing directory */
if
(
errno
==
EEXIST
)
...
...
@@ -297,12 +306,12 @@ int git_futils_mkdir_r(const char *path, const mode_t mode)
}
if
(
*
pp
!=
'\0'
&&
error
==
GIT_SUCCESS
)
{
error
=
p_mkdir
(
path
,
mode
);
error
=
p_mkdir
(
make_path
.
ptr
,
mode
);
if
(
errno
==
EEXIST
)
error
=
GIT_SUCCESS
;
}
git_
_free
(
path_copy
);
git_
buf_free
(
&
make_path
);
if
(
error
<
GIT_SUCCESS
)
return
git__throw
(
error
,
"Failed to recursively create `%s` tree structure"
,
path
);
...
...
@@ -310,32 +319,34 @@ int git_futils_mkdir_r(const char *path, const mode_t mode)
return
GIT_SUCCESS
;
}
static
int
_rmdir_recurs_foreach
(
void
*
opaque
,
char
*
path
)
static
int
_rmdir_recurs_foreach
(
void
*
opaque
,
git_buf
*
path
)
{
int
error
=
GIT_SUCCESS
;
int
force
=
*
(
int
*
)
opaque
;
if
(
git_futils_isdir
(
path
)
==
GIT_SUCCESS
)
{
size_t
root_size
=
strlen
(
path
);
if
((
error
=
git_futils_direach
(
path
,
GIT_PATH_MAX
,
_rmdir_recurs_foreach
,
opaque
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to remove directory `%s`"
,
path
);
path
[
root_size
]
=
'\0'
;
return
p_rmdir
(
path
);
if
(
git_futils_isdir
(
path
->
ptr
)
==
GIT_SUCCESS
)
{
error
=
git_futils_direach
(
path
,
_rmdir_recurs_foreach
,
opaque
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to remove directory `%s`"
,
path
->
ptr
);
return
p_rmdir
(
path
->
ptr
);
}
else
if
(
force
)
{
return
p_unlink
(
path
);
return
p_unlink
(
path
->
ptr
);
}
return
git__rethrow
(
error
,
"Failed to remove directory. `%s` is not empty"
,
path
);
return
git__rethrow
(
error
,
"Failed to remove directory. `%s` is not empty"
,
path
->
ptr
);
}
int
git_futils_rmdir_r
(
const
char
*
path
,
int
force
)
{
char
p
[
GIT_PATH_MAX
];
strncpy
(
p
,
path
,
GIT_PATH_MAX
);
return
_rmdir_recurs_foreach
(
&
force
,
p
);
int
error
;
git_buf
p
=
GIT_BUF_INIT
;
error
=
git_buf_sets
(
&
p
,
path
);
if
(
error
==
GIT_SUCCESS
)
error
=
_rmdir_recurs_foreach
(
&
force
,
&
p
);
git_buf_free
(
&
p
);
return
error
;
}
int
git_futils_cmp_path
(
const
char
*
name1
,
int
len1
,
int
isdir1
,
...
...
@@ -356,3 +367,39 @@ int git_futils_cmp_path(const char *name1, int len1, int isdir1,
return
0
;
}
static
int
_check_dir_contents
(
git_buf
*
dir
,
const
char
*
sub
,
int
append_on_success
,
int
(
*
predicate
)(
const
char
*
))
{
int
error
=
GIT_SUCCESS
;
size_t
dir_size
=
dir
->
size
;
size_t
sub_size
=
strlen
(
sub
);
/* leave base valid even if we could not make space for subdir */
if
((
error
=
git_buf_try_grow
(
dir
,
dir_size
+
sub_size
+
2
))
<
GIT_SUCCESS
)
return
error
;
/* save excursion */
git_buf_joinpath
(
dir
,
dir
->
ptr
,
sub
);
error
=
(
*
predicate
)(
dir
->
ptr
);
/* restore excursion */
if
(
!
append_on_success
||
error
!=
GIT_SUCCESS
)
git_buf_truncate
(
dir
,
dir_size
);
return
error
;
}
int
git_futils_contains_dir
(
git_buf
*
base
,
const
char
*
subdir
,
int
append_if_exists
)
{
return
_check_dir_contents
(
base
,
subdir
,
append_if_exists
,
&
git_futils_isdir
);
}
int
git_futils_contains_file
(
git_buf
*
base
,
const
char
*
file
,
int
append_if_exists
)
{
return
_check_dir_contents
(
base
,
file
,
append_if_exists
,
&
git_futils_isfile
);
}
src/fileops.h
View file @
40e73d6f
...
...
@@ -28,6 +28,7 @@ typedef struct { /* file io buffer */
extern
int
git_futils_readbuffer
(
git_fbuffer
*
obj
,
const
char
*
path
);
extern
int
git_futils_readbuffer_updated
(
git_fbuffer
*
obj
,
const
char
*
path
,
time_t
*
mtime
,
int
*
updated
);
extern
void
git_futils_freebuffer
(
git_fbuffer
*
obj
);
extern
void
git_futils_fbuffer_rtrim
(
git_fbuffer
*
obj
);
/**
* File utils
...
...
@@ -72,9 +73,25 @@ extern int git_futils_isdir(const char *path);
extern
int
git_futils_isfile
(
const
char
*
path
);
/**
* Check if the given path contains the given subdirectory.
*
* If `append_if_exists` is true, then the subdir will be appended to the
* parent path if it does exists.
*/
extern
int
git_futils_contains_dir
(
git_buf
*
parent
,
const
char
*
subdir
,
int
append_if_exists
);
/**
* Check if the given path contains the given file
*
* If `append_if_exists` is true, then the filename will be appended to the
* parent path if it does exists.
*/
extern
int
git_futils_contains_file
(
git_buf
*
parent
,
const
char
*
file
,
int
append_if_exists
);
/**
* Create a path recursively
*/
extern
int
git_futils_mkdir_r
(
const
char
*
path
,
const
mode_t
mode
);
extern
int
git_futils_mkdir_r
(
const
char
*
path
,
const
char
*
base
,
const
mode_t
mode
);
/**
* Create all the folders required to contain
...
...
@@ -85,9 +102,11 @@ extern int git_futils_mkpath2file(const char *path, const mode_t mode);
extern
int
git_futils_rmdir_r
(
const
char
*
path
,
int
force
);
/**
* Create and open a temporary file with a `_git2_` suffix
* Create and open a temporary file with a `_git2_` suffix.
* Writes the filename into path_out.
* @return On success, an open file descriptor, else an error code < 0.
*/
extern
int
git_futils_mktmp
(
char
*
path_out
,
const
char
*
filename
);
extern
int
git_futils_mktmp
(
git_buf
*
path_out
,
const
char
*
filename
);
/**
* Move a file on the filesystem, create the
...
...
@@ -133,16 +152,14 @@ extern void git_futils_mmap_free(git_map *map);
*
* @param pathbuf buffer the function reads the initial directory
* path from, and updates with each successive entry's name.
* @param pathmax maximum allocation of pathbuf.
* @param fn function to invoke with each entry. The first arg is
* the input state and the second arg is pathbuf. The function
* may modify the pathbuf, but only by appending new text.
* @param state to pass to fn as the first arg.
*/
extern
int
git_futils_direach
(
char
*
pathbuf
,
size_t
pathmax
,
int
(
*
fn
)(
void
*
,
char
*
),
git_buf
*
pathbuf
,
int
(
*
fn
)(
void
*
,
git_buf
*
),
void
*
state
);
extern
int
git_futils_cmp_path
(
const
char
*
name1
,
int
len1
,
int
isdir1
,
...
...
src/index.c
View file @
40e73d6f
...
...
@@ -294,40 +294,30 @@ git_index_entry *git_index_get(git_index *index, unsigned int n)
static
int
index_entry_init
(
git_index_entry
**
entry_out
,
git_index
*
index
,
const
char
*
rel_path
,
int
stage
)
{
git_index_entry
*
entry
;
char
full_path
[
GIT_PATH_MAX
];
git_index_entry
*
entry
=
NULL
;
struct
stat
st
;
git_oid
oid
;
int
error
;
const
char
*
workdir
;
if
(
INDEX_OWNER
(
index
)
==
NULL
)
return
git__throw
(
GIT_EBAREINDEX
,
"Failed to initialize entry. Repository is bare"
);
workdir
=
git_repository_workdir
(
INDEX_OWNER
(
index
));
if
(
workdir
==
NULL
)
return
git__throw
(
GIT_EBAREINDEX
,
"Failed to initialize entry. Cannot resolved workdir"
);
git_path_join
(
full_path
,
workdir
,
rel_path
);
if
(
p_lstat
(
full_path
,
&
st
)
<
0
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to initialize entry. '%s' cannot be opened"
,
full_path
);
if
(
stage
<
0
||
stage
>
3
)
return
git__throw
(
GIT_ERROR
,
"Failed to initialize entry. Invalid stage %i"
,
stage
);
/* There is no need to validate the rel_path here, since it will be
* immediately validated by the call to git_blob_create_fromfile.
*/
/* write the blob to disk and get the oid */
if
((
error
=
git_blob_create_fromfile
(
&
oid
,
INDEX_OWNER
(
index
),
rel_path
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to initialize index entry"
);
entry
=
git__
malloc
(
sizeof
(
git_index_entry
));
entry
=
git__
calloc
(
1
,
sizeof
(
git_index_entry
));
if
(
!
entry
)
return
GIT_ENOMEM
;
memset
(
entry
,
0x0
,
sizeof
(
git_index_entry
));
entry
->
ctime
.
seconds
=
(
git_time_t
)
st
.
st_ctime
;
entry
->
mtime
.
seconds
=
(
git_time_t
)
st
.
st_mtime
;
...
...
src/indexer.c
View file @
40e73d6f
...
...
@@ -151,28 +151,35 @@ cleanup:
return
error
;
}
static
void
index_path
(
char
*
path
,
git_indexer
*
idx
)
static
int
index_path
(
git_buf
*
path
,
git_indexer
*
idx
)
{
char
*
ptr
;
const
char
prefix
[]
=
"pack-"
,
suffix
[]
=
".idx"
;
size_t
slash
=
(
size_t
)
path
->
size
;
ptr
=
strrchr
(
path
,
'/'
)
+
1
;
/* search backwards for '/' */
while
(
slash
>
0
&&
path
->
ptr
[
slash
-
1
]
!=
'/'
)
slash
--
;
memcpy
(
ptr
,
prefix
,
strlen
(
prefix
));
ptr
+=
strlen
(
prefix
);
git_oid_fmt
(
ptr
,
&
idx
->
hash
);
ptr
+=
GIT_OID_HEXSZ
;
memcpy
(
ptr
,
suffix
,
strlen
(
suffix
)
+
1
);
if
(
git_buf_grow
(
path
,
slash
+
1
+
strlen
(
prefix
)
+
GIT_OID_HEXSZ
+
strlen
(
suffix
)
+
1
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
git_buf_truncate
(
path
,
slash
+
1
);
git_buf_puts
(
path
,
prefix
);
git_oid_fmt
(
path
->
ptr
+
path
->
size
,
&
idx
->
hash
);
path
->
size
+=
GIT_OID_HEXSZ
;
git_buf_puts
(
path
,
suffix
);
return
git_buf_lasterror
(
path
);
}
int
git_indexer_write
(
git_indexer
*
idx
)
{
git_mwindow
*
w
=
NULL
;
int
error
;
size_t
namelen
;
unsigned
int
i
,
long_offsets
=
0
,
left
;
struct
git_pack_idx_header
hdr
;
char
filename
[
GIT_PATH_MAX
]
;
git_buf
filename
=
GIT_BUF_INIT
;
struct
entry
*
entry
;
void
*
packfile_hash
;
git_oid
file_hash
;
...
...
@@ -180,16 +187,23 @@ int git_indexer_write(git_indexer *idx)
git_vector_sort
(
&
idx
->
objects
);
namelen
=
strlen
(
idx
->
pack
->
pack_name
);
memcpy
(
filename
,
idx
->
pack
->
pack_name
,
namelen
);
memcpy
(
filename
+
namelen
-
strlen
(
"pack"
),
"idx"
,
strlen
(
"idx"
)
+
1
);
git_buf_sets
(
&
filename
,
idx
->
pack
->
pack_name
);
git_buf_truncate
(
&
filename
,
filename
.
size
-
strlen
(
"pack"
)
);
git_buf_puts
(
&
filename
,
"idx"
);
error
=
git_filebuf_open
(
&
idx
->
file
,
filename
,
GIT_FILEBUF_HASH_CONTENTS
);
if
((
error
=
git_buf_lasterror
(
&
filename
))
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_filebuf_open
(
&
idx
->
file
,
filename
.
ptr
,
GIT_FILEBUF_HASH_CONTENTS
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
/* Write out the header */
hdr
.
idx_signature
=
htonl
(
PACK_IDX_SIGNATURE
);
hdr
.
idx_version
=
htonl
(
2
);
error
=
git_filebuf_write
(
&
idx
->
file
,
&
hdr
,
sizeof
(
hdr
));
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
/* Write out the fanout table */
for
(
i
=
0
;
i
<
256
;
++
i
)
{
...
...
@@ -270,14 +284,18 @@ int git_indexer_write(git_indexer *idx)
goto
cleanup
;
/* Figure out what the final name should be */
index_path
(
filename
,
idx
);
error
=
index_path
(
&
filename
,
idx
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
/* Commit file */
error
=
git_filebuf_commit_at
(
&
idx
->
file
,
filename
,
GIT_PACK_FILE_MODE
);
error
=
git_filebuf_commit_at
(
&
idx
->
file
,
filename
.
ptr
,
GIT_PACK_FILE_MODE
);
cleanup:
git_mwindow_free_all
(
&
idx
->
pack
->
mwf
);
if
(
error
<
GIT_SUCCESS
)
git_filebuf_cleanup
(
&
idx
->
file
);
git_buf_free
(
&
filename
);
return
error
;
}
...
...
src/odb.c
View file @
40e73d6f
...
...
@@ -344,40 +344,47 @@ static int add_default_backends(git_odb *db, const char *objects_dir, int as_alt
static
int
load_alternates
(
git_odb
*
odb
,
const
char
*
objects_dir
)
{
char
alternates_path
[
GIT_PATH_MAX
];
char
*
buffer
,
*
alternate
;
git_buf
alternates_path
=
GIT_BUF_INIT
;
char
*
buffer
;
git_fbuffer
alternates_buf
=
GIT_FBUFFER_INIT
;
const
char
*
alternate
;
int
error
;
git_path_join
(
alternates_path
,
objects_dir
,
GIT_ALTERNATES_FILE
);
error
=
git_buf_joinpath
(
&
alternates_path
,
objects_dir
,
GIT_ALTERNATES_FILE
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
if
(
git_futils_exists
(
alternates_path
)
<
GIT_SUCCESS
)
if
(
git_futils_exists
(
alternates_path
.
ptr
)
<
GIT_SUCCESS
)
{
git_buf_free
(
&
alternates_path
);
return
GIT_SUCCESS
;
}
if
(
git_futils_readbuffer
(
&
alternates_buf
,
alternates_path
)
<
GIT_SUCCESS
)
if
(
git_futils_readbuffer
(
&
alternates_buf
,
alternates_path
.
ptr
)
<
GIT_SUCCESS
)
{
git_buf_free
(
&
alternates_path
);
return
git__throw
(
GIT_EOSERR
,
"Failed to add backend. Can't read alternates"
);
}
buffer
=
(
char
*
)
alternates_buf
.
data
;
error
=
GIT_SUCCESS
;
/* add each alternate as a new backend; one alternate per line */
while
((
alternate
=
git__strtok
(
&
buffer
,
"
\r\n
"
))
!=
NULL
)
{
char
full_path
[
GIT_PATH_MAX
];
if
(
*
alternate
==
'\0'
||
*
alternate
==
'#'
)
continue
;
/* relative path: build based on the current `objects` folder */
if
(
*
alternate
==
'.'
)
{
git_path_join
(
full_path
,
objects_dir
,
alternate
);
alternate
=
full_path
;
error
=
git_buf_joinpath
(
&
alternates_path
,
objects_dir
,
alternate
);
if
(
error
<
GIT_SUCCESS
)
break
;
alternate
=
git_buf_cstr
(
&
alternates_path
);
}
if
((
error
=
add_default_backends
(
odb
,
alternate
,
1
))
<
GIT_SUCCESS
)
break
;
}
git_buf_free
(
&
alternates_path
);
git_futils_freebuffer
(
&
alternates_buf
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to load alternates"
);
...
...
src/odb_loose.c
View file @
40e73d6f
...
...
@@ -26,7 +26,6 @@ typedef struct { /* object header data */
typedef
struct
{
git_odb_stream
stream
;
git_filebuf
fbuf
;
int
finished
;
}
loose_writestream
;
typedef
struct
loose_backend
{
...
...
@@ -51,31 +50,28 @@ typedef struct {
}
loose_locate_object_state
;
/***********************************************************
*
* MISCELANEOUS HELPER FUNCTIONS
*
***********************************************************/
static
size_t
object_file_name
(
char
*
name
,
size_t
n
,
char
*
dir
,
const
git_oid
*
id
)
static
int
object_file_name
(
git_buf
*
name
,
const
char
*
dir
,
const
git_oid
*
id
)
{
size_t
len
=
strlen
(
dir
);
git_buf_sets
(
name
,
dir
);
/*
check length: 43 =
40 hex sha1 chars + 2 * '/' + '\0' */
if
(
len
+
43
>
n
)
return
len
+
43
;
/*
expand length for
40 hex sha1 chars + 2 * '/' + '\0' */
if
(
git_buf_grow
(
name
,
name
->
size
+
GIT_OID_HEXSZ
+
3
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
/* the object dir: eg $GIT_DIR/objects */
strcpy
(
name
,
dir
);
if
(
name
[
len
-
1
]
!=
'/'
)
name
[
len
++
]
=
'/'
;
git_path_to_dir
(
name
);
/* loose object filename: aa/aaa... (41 bytes) */
git_oid_pathfmt
(
&
name
[
len
],
id
);
name
[
len
+
41
]
=
'\0'
;
git_oid_pathfmt
(
name
->
ptr
+
name
->
size
,
id
);
name
->
size
+=
GIT_OID_HEXSZ
+
1
;
name
->
ptr
[
name
->
size
]
=
'\0'
;
return
0
;
return
GIT_SUCCESS
;
}
...
...
@@ -384,18 +380,21 @@ static int inflate_disk_obj(git_rawobj *out, git_fbuffer *obj)
*
***********************************************************/
static
int
read_loose
(
git_rawobj
*
out
,
const
char
*
loc
)
static
int
read_loose
(
git_rawobj
*
out
,
git_buf
*
loc
)
{
int
error
;
git_fbuffer
obj
=
GIT_FBUFFER_INIT
;
assert
(
out
&&
loc
);
if
((
error
=
git_buf_lasterror
(
loc
))
<
GIT_SUCCESS
)
return
error
;
out
->
data
=
NULL
;
out
->
len
=
0
;
out
->
type
=
GIT_OBJ_BAD
;
if
(
git_futils_readbuffer
(
&
obj
,
loc
)
<
0
)
if
(
git_futils_readbuffer
(
&
obj
,
loc
->
ptr
)
<
0
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to read loose object. File not found"
);
error
=
inflate_disk_obj
(
out
,
&
obj
);
...
...
@@ -404,7 +403,7 @@ static int read_loose(git_rawobj *out, const char *loc)
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to read loose object"
);
}
static
int
read_header_loose
(
git_rawobj
*
out
,
const
char
*
loc
)
static
int
read_header_loose
(
git_rawobj
*
out
,
git_buf
*
loc
)
{
int
error
=
GIT_SUCCESS
,
z_return
=
Z_ERRNO
,
read_bytes
;
git_file
fd
;
...
...
@@ -414,9 +413,12 @@ static int read_header_loose(git_rawobj *out, const char *loc)
assert
(
out
&&
loc
);
if
((
error
=
git_buf_lasterror
(
loc
))
<
GIT_SUCCESS
)
return
error
;
out
->
data
=
NULL
;
if
((
fd
=
p_open
(
loc
,
O_RDONLY
))
<
0
)
if
((
fd
=
p_open
(
loc
->
ptr
,
O_RDONLY
))
<
0
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to read loose object header. File not found"
);
init_stream
(
&
zs
,
inflated_buffer
,
sizeof
(
inflated_buffer
));
...
...
@@ -456,33 +458,39 @@ cleanup:
return
GIT_SUCCESS
;
}
static
int
locate_object
(
char
*
object_location
,
loose_backend
*
backend
,
const
git_oid
*
oid
)
static
int
locate_object
(
git_buf
*
object_location
,
loose_backend
*
backend
,
const
git_oid
*
oid
)
{
object_file_name
(
object_location
,
GIT_PATH_MAX
,
backend
->
objects_dir
,
oid
);
return
git_futils_exists
(
object_location
);
int
error
=
object_file_name
(
object_location
,
backend
->
objects_dir
,
oid
);
if
(
error
==
GIT_SUCCESS
)
error
=
git_futils_exists
(
git_buf_cstr
(
object_location
));
return
error
;
}
/* Explore an entry of a directory and see if it matches a short oid */
static
int
fn_locate_object_short_oid
(
void
*
state
,
char
*
pathbuf
)
{
static
int
fn_locate_object_short_oid
(
void
*
state
,
git_buf
*
pathbuf
)
{
loose_locate_object_state
*
sstate
=
(
loose_locate_object_state
*
)
state
;
size_t
pathbuf_len
=
strlen
(
pathbuf
);
if
(
pathbuf_len
-
sstate
->
dir_len
!=
GIT_OID_HEXSZ
-
2
)
{
if
(
pathbuf
->
size
-
sstate
->
dir_len
!=
GIT_OID_HEXSZ
-
2
)
{
/* Entry cannot be an object. Continue to next entry */
return
GIT_SUCCESS
;
}
if
(
!
git_futils_exists
(
pathbuf
)
&&
git_futils_isdir
(
pathbuf
))
{
if
(
!
git_futils_exists
(
pathbuf
->
ptr
)
&&
git_futils_isdir
(
pathbuf
->
ptr
))
{
/* We are already in the directory matching the 2 first hex characters,
* compare the first ncmp characters of the oids */
if
(
!
memcmp
(
sstate
->
short_oid
+
2
,
(
unsigned
char
*
)
pathbuf
+
sstate
->
dir_len
,
(
unsigned
char
*
)
pathbuf
->
ptr
+
sstate
->
dir_len
,
sstate
->
short_oid_len
-
2
))
{
if
(
!
sstate
->
found
)
{
sstate
->
res_oid
[
0
]
=
sstate
->
short_oid
[
0
];
sstate
->
res_oid
[
1
]
=
sstate
->
short_oid
[
1
];
memcpy
(
sstate
->
res_oid
+
2
,
pathbuf
+
sstate
->
dir_len
,
GIT_OID_HEXSZ
-
2
);
memcpy
(
sstate
->
res_oid
+
2
,
pathbuf
->
ptr
+
sstate
->
dir_len
,
GIT_OID_HEXSZ
-
2
);
}
sstate
->
found
++
;
}
...
...
@@ -494,39 +502,50 @@ static int fn_locate_object_short_oid(void *state, char *pathbuf) {
}
/* Locate an object matching a given short oid */
static
int
locate_object_short_oid
(
char
*
object_location
,
git_oid
*
res_oid
,
loose_backend
*
backend
,
const
git_oid
*
short_oid
,
unsigned
int
len
)
static
int
locate_object_short_oid
(
git_buf
*
object_location
,
git_oid
*
res_oid
,
loose_backend
*
backend
,
const
git_oid
*
short_oid
,
unsigned
int
len
)
{
char
*
objects_dir
=
backend
->
objects_dir
;
size_t
dir_len
=
strlen
(
objects_dir
);
loose_locate_object_state
state
;
int
error
;
if
(
dir_len
+
43
>
GIT_PATH_MAX
)
return
git__throw
(
GIT_ERROR
,
"Failed to locate object from short oid. Object path too long"
);
/* prealloc memory for OBJ_DIR/xx/ */
if
((
error
=
git_buf_grow
(
object_location
,
dir_len
+
5
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to locate object from short oid"
);
strcpy
(
object_location
,
objects_dir
);
git_buf_sets
(
object_location
,
objects_dir
);
git_path_to_dir
(
object_location
);
/* Add a separator if not already there */
if
(
object_location
[
dir_len
-
1
]
!=
'/'
)
object_location
[
dir_len
++
]
=
'/'
;
/* save adjusted position at end of dir so it can be restored later */
dir_len
=
object_location
->
size
;
/* Convert raw oid to hex formatted oid */
git_oid_fmt
((
char
*
)
state
.
short_oid
,
short_oid
);
/* Explore OBJ_DIR/xx/ where xx is the beginning of hex formatted short oid */
sprintf
(
object_location
+
dir_len
,
"%.2s/"
,
state
.
short_oid
);
error
=
git_buf_printf
(
object_location
,
"%.2s/"
,
state
.
short_oid
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to locate object from short oid"
);
/* Check that directory exists */
if
(
git_futils_exists
(
object_location
)
||
git_futils_isdir
(
object_location
))
if
(
git_futils_exists
(
object_location
->
ptr
)
||
git_futils_isdir
(
object_location
->
ptr
))
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to locate object from short oid. Object not found"
);
state
.
dir_len
=
dir_len
+
3
;
state
.
dir_len
=
object_location
->
size
;
state
.
short_oid_len
=
len
;
state
.
found
=
0
;
/* Explore directory to find a unique object matching short_oid */
error
=
git_futils_direach
(
object_location
,
GIT_PATH_MAX
,
fn_locate_object_short_oid
,
&
state
);
if
(
error
)
{
error
=
git_futils_direach
(
object_location
,
fn_locate_object_short_oid
,
&
state
);
if
(
error
)
return
git__rethrow
(
error
,
"Failed to locate object from short oid"
);
}
if
(
!
state
.
found
)
{
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to locate object from short oid. Object not found"
);
}
...
...
@@ -538,7 +557,16 @@ static int locate_object_short_oid(char *object_location, git_oid *res_oid, loos
}
/* Update the location according to the oid obtained */
git_oid_pathfmt
(
object_location
+
dir_len
,
res_oid
);
git_buf_truncate
(
object_location
,
dir_len
);
error
=
git_buf_grow
(
object_location
,
dir_len
+
GIT_OID_HEXSZ
+
2
);
if
(
error
)
return
git__rethrow
(
error
,
"Failed to locate object from short oid"
);
git_oid_pathfmt
(
object_location
->
ptr
+
dir_len
,
res_oid
);
object_location
->
size
+=
GIT_OID_HEXSZ
+
1
;
object_location
->
ptr
[
object_location
->
size
]
=
'\0'
;
return
GIT_SUCCESS
;
}
...
...
@@ -561,45 +589,49 @@ static int locate_object_short_oid(char *object_location, git_oid *res_oid, loos
static
int
loose_backend__read_header
(
size_t
*
len_p
,
git_otype
*
type_p
,
git_odb_backend
*
backend
,
const
git_oid
*
oid
)
{
char
object_path
[
GIT_PATH_MAX
]
;
git_buf
object_path
=
GIT_BUF_INIT
;
git_rawobj
raw
;
int
error
;
int
error
=
GIT_SUCCESS
;
assert
(
backend
&&
oid
);
raw
.
len
=
0
;
raw
.
type
=
GIT_OBJ_BAD
;
if
(
locate_object
(
object_path
,
(
loose_backend
*
)
backend
,
oid
)
<
0
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to read loose backend header. Object not found"
);
if
(
locate_object
(
&
object_path
,
(
loose_backend
*
)
backend
,
oid
)
<
0
)
error
=
git__throw
(
GIT_ENOTFOUND
,
"Failed to read loose backend header. Object not found"
);
else
if
((
error
=
read_header_loose
(
&
raw
,
&
object_path
))
==
GIT_SUCCESS
)
{
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
}
if
((
error
=
read_header_loose
(
&
raw
,
object_path
))
<
GIT_SUCCESS
)
return
error
;
git_buf_free
(
&
object_path
);
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
return
GIT_SUCCESS
;
return
error
;
}
static
int
loose_backend__read
(
void
**
buffer_p
,
size_t
*
len_p
,
git_otype
*
type_p
,
git_odb_backend
*
backend
,
const
git_oid
*
oid
)
{
char
object_path
[
GIT_PATH_MAX
]
;
git_buf
object_path
=
GIT_BUF_INIT
;
git_rawobj
raw
;
int
error
;
int
error
=
GIT_SUCCESS
;
assert
(
backend
&&
oid
);
if
(
locate_object
(
object_path
,
(
loose_backend
*
)
backend
,
oid
)
<
0
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to read loose backend. Object not found"
);
if
((
error
=
read_loose
(
&
raw
,
object_path
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to read loose backend"
);
if
(
locate_object
(
&
object_path
,
(
loose_backend
*
)
backend
,
oid
)
<
0
)
error
=
git__throw
(
GIT_ENOTFOUND
,
"Failed to read loose backend. Object not found"
);
else
if
((
error
=
read_loose
(
&
raw
,
&
object_path
))
==
GIT_SUCCESS
)
{
*
buffer_p
=
raw
.
data
;
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
}
else
{
git__rethrow
(
error
,
"Failed to read loose backend"
);
}
*
buffer_p
=
raw
.
data
;
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
git_buf_free
(
&
object_path
);
return
GIT_SUCCESS
;
return
error
;
}
static
int
loose_backend__read_prefix
(
...
...
@@ -611,45 +643,52 @@ static int loose_backend__read_prefix(
const
git_oid
*
short_oid
,
unsigned
int
len
)
{
int
error
=
GIT_SUCCESS
;
if
(
len
<
GIT_OID_MINPREFIXLEN
)
return
git__throw
(
GIT_EAMBIGUOUSOIDPREFIX
,
"Failed to read loose backend. Prefix length is lower than %d."
,
GIT_OID_MINPREFIXLEN
);
return
git__throw
(
GIT_EAMBIGUOUSOIDPREFIX
,
"Failed to read loose "
"backend. Prefix length is lower than %d."
,
GIT_OID_MINPREFIXLEN
);
if
(
len
>=
GIT_OID_HEXSZ
)
{
/* We can fall back to regular read method */
int
error
=
loose_backend__read
(
buffer_p
,
len_p
,
type_p
,
backend
,
short_oid
);
error
=
loose_backend__read
(
buffer_p
,
len_p
,
type_p
,
backend
,
short_oid
);
if
(
error
==
GIT_SUCCESS
)
git_oid_cpy
(
out_oid
,
short_oid
);
return
error
;
}
else
{
char
object_path
[
GIT_PATH_MAX
]
;
git_buf
object_path
=
GIT_BUF_INIT
;
git_rawobj
raw
;
int
error
;
assert
(
backend
&&
short_oid
);
if
((
error
=
locate_object_short_oid
(
object_path
,
out_oid
,
(
loose_backend
*
)
backend
,
short_oid
,
len
))
<
0
)
{
return
git__rethrow
(
error
,
"Failed to read loose backend"
);
if
((
error
=
locate_object_short_oid
(
&
object_path
,
out_oid
,
(
loose_backend
*
)
backend
,
short_oid
,
len
))
<
0
)
git__rethrow
(
error
,
"Failed to read loose backend"
);
else
if
((
error
=
read_loose
(
&
raw
,
&
object_path
))
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"Failed to read loose backend"
);
else
{
*
buffer_p
=
raw
.
data
;
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
}
if
((
error
=
read_loose
(
&
raw
,
object_path
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to read loose backend"
);
*
buffer_p
=
raw
.
data
;
*
len_p
=
raw
.
len
;
*
type_p
=
raw
.
type
;
git_buf_free
(
&
object_path
);
}
return
GIT_SUCCESS
;
return
error
;
}
static
int
loose_backend__exists
(
git_odb_backend
*
backend
,
const
git_oid
*
oid
)
{
char
object_path
[
GIT_PATH_MAX
];
git_buf
object_path
=
GIT_BUF_INIT
;
int
error
;
assert
(
backend
&&
oid
);
return
locate_object
(
object_path
,
(
loose_backend
*
)
backend
,
oid
)
==
GIT_SUCCESS
;
error
=
locate_object
(
&
object_path
,
(
loose_backend
*
)
backend
,
oid
);
git_buf_free
(
&
object_path
);
return
(
error
==
GIT_SUCCESS
);
}
static
int
loose_backend__stream_fwrite
(
git_oid
*
oid
,
git_odb_stream
*
_stream
)
...
...
@@ -658,30 +697,39 @@ static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
loose_backend
*
backend
=
(
loose_backend
*
)
_stream
->
backend
;
int
error
;
char
final_path
[
GIT_PATH_MAX
]
;
git_buf
final_path
=
GIT_BUF_INIT
;
if
((
error
=
git_filebuf_hash
(
oid
,
&
stream
->
fbuf
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to write loose backend"
)
;
goto
cleanup
;
if
(
object_file_name
(
final_path
,
sizeof
(
final_path
),
backend
->
objects_dir
,
oid
)
)
return
GIT_ENOMEM
;
if
(
(
error
=
object_file_name
(
&
final_path
,
backend
->
objects_dir
,
oid
))
<
GIT_SUCCESS
)
goto
cleanup
;
if
((
error
=
git_
futils_mkpath2file
(
final_path
,
GIT_OBJECT_DIR_MODE
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to write loose backend"
)
;
if
((
error
=
git_
buf_lasterror
(
&
final_path
))
<
GIT_SUCCESS
)
goto
cleanup
;
stream
->
finished
=
1
;
if
((
error
=
git_futils_mkpath2file
(
final_path
.
ptr
,
GIT_OBJECT_DIR_MODE
))
<
GIT_SUCCESS
)
goto
cleanup
;
/*
* Don't try to add an existing object to the repository. This
* is what git does and allows us to sidestep the fact that
* we're not allowed to overwrite a read-only file on Windows.
*/
if
(
git_futils_exists
(
final_path
)
==
GIT_SUCCESS
)
{
if
(
git_futils_exists
(
final_path
.
ptr
)
==
GIT_SUCCESS
)
{
git_filebuf_cleanup
(
&
stream
->
fbuf
);
return
GIT_SUCCESS
;
goto
cleanup
;
}
return
git_filebuf_commit_at
(
&
stream
->
fbuf
,
final_path
,
GIT_OBJECT_FILE_MODE
);
error
=
git_filebuf_commit_at
(
&
stream
->
fbuf
,
final_path
.
ptr
,
GIT_OBJECT_FILE_MODE
);
cleanup:
git_buf_free
(
&
final_path
);
if
(
error
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"Failed to write loose backend"
);
return
error
;
}
static
int
loose_backend__stream_write
(
git_odb_stream
*
_stream
,
const
char
*
data
,
size_t
len
)
...
...
@@ -694,9 +742,7 @@ static void loose_backend__stream_free(git_odb_stream *_stream)
{
loose_writestream
*
stream
=
(
loose_writestream
*
)
_stream
;
if
(
!
stream
->
finished
)
git_filebuf_cleanup
(
&
stream
->
fbuf
);
git_filebuf_cleanup
(
&
stream
->
fbuf
);
git__free
(
stream
);
}
...
...
@@ -718,7 +764,8 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_
loose_backend
*
backend
;
loose_writestream
*
stream
;
char
hdr
[
64
],
tmp_path
[
GIT_PATH_MAX
];
char
hdr
[
64
];
git_buf
tmp_path
=
GIT_BUF_INIT
;
int
hdrlen
;
int
error
;
...
...
@@ -742,33 +789,38 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_
stream
->
stream
.
free
=
&
loose_backend__stream_free
;
stream
->
stream
.
mode
=
GIT_STREAM_WRONLY
;
git_path_join
(
tmp_path
,
backend
->
objects_dir
,
"tmp_object"
);
error
=
git_buf_joinpath
(
&
tmp_path
,
backend
->
objects_dir
,
"tmp_object"
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_filebuf_open
(
&
stream
->
fbuf
,
tmp_path
,
error
=
git_filebuf_open
(
&
stream
->
fbuf
,
tmp_path
.
ptr
,
GIT_FILEBUF_HASH_CONTENTS
|
GIT_FILEBUF_TEMPORARY
|
(
backend
->
object_zlib_level
<<
GIT_FILEBUF_DEFLATE_SHIFT
));
if
(
error
<
GIT_SUCCESS
)
{
git__free
(
stream
);
return
git__rethrow
(
error
,
"Failed to create loose backend stream"
);
}
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
stream
->
stream
.
write
((
git_odb_stream
*
)
stream
,
hdr
,
hdrlen
);
if
(
error
<
GIT_SUCCESS
)
{
git_filebuf_cleanup
(
&
stream
->
fbuf
);
git__free
(
stream
);
return
git__rethrow
(
error
,
"Failed to create loose backend stream"
);
}
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
git_buf_free
(
&
tmp_path
);
*
stream_out
=
(
git_odb_stream
*
)
stream
;
return
GIT_SUCCESS
;
cleanup:
git_buf_free
(
&
tmp_path
);
git_filebuf_cleanup
(
&
stream
->
fbuf
);
git__free
(
stream
);
return
git__rethrow
(
error
,
"Failed to create loose backend stream"
);
}
static
int
loose_backend__write
(
git_oid
*
oid
,
git_odb_backend
*
_backend
,
const
void
*
data
,
size_t
len
,
git_otype
type
)
{
int
error
,
header_len
;
char
final_path
[
GIT_PATH_MAX
],
header
[
64
];
git_buf
final_path
=
GIT_BUF_INIT
;
char
header
[
64
];
git_filebuf
fbuf
=
GIT_FILEBUF_INIT
;
loose_backend
*
backend
;
...
...
@@ -781,30 +833,35 @@ static int loose_backend__write(git_oid *oid, git_odb_backend *_backend, const v
return
GIT_EOBJCORRUPTED
;
}
git_path_join
(
final_path
,
backend
->
objects_dir
,
"tmp_object"
);
error
=
git_buf_joinpath
(
&
final_path
,
backend
->
objects_dir
,
"tmp_object"
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_filebuf_open
(
&
fbuf
,
final_path
,
error
=
git_filebuf_open
(
&
fbuf
,
final_path
.
ptr
,
GIT_FILEBUF_HASH_CONTENTS
|
GIT_FILEBUF_TEMPORARY
|
(
backend
->
object_zlib_level
<<
GIT_FILEBUF_DEFLATE_SHIFT
));
if
(
error
<
GIT_SUCCESS
)
return
error
;
goto
cleanup
;
git_filebuf_write
(
&
fbuf
,
header
,
header_len
);
git_filebuf_write
(
&
fbuf
,
data
,
len
);
git_filebuf_hash
(
oid
,
&
fbuf
);
if
((
error
=
object_file_name
(
final_path
,
sizeof
(
final_path
),
backend
->
objects_dir
,
oid
))
<
GIT_SUCCESS
)
error
=
object_file_name
(
&
final_path
,
backend
->
objects_dir
,
oid
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
((
error
=
git_futils_mkpath2file
(
final_path
,
GIT_OBJECT_DIR_MODE
))
<
GIT_SUCCESS
)
error
=
git_futils_mkpath2file
(
final_path
.
ptr
,
GIT_OBJECT_DIR_MODE
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
return
git_filebuf_commit_at
(
&
fbuf
,
final_path
,
GIT_OBJECT_FILE_MODE
);
error
=
git_filebuf_commit_at
(
&
fbuf
,
final_path
.
ptr
,
GIT_OBJECT_FILE_MODE
);
cleanup:
git_filebuf_cleanup
(
&
fbuf
);
if
(
error
<
GIT_SUCCESS
)
git_filebuf_cleanup
(
&
fbuf
);
git_buf_free
(
&
final_path
);
return
error
;
}
...
...
src/odb_pack.c
View file @
40e73d6f
...
...
@@ -133,7 +133,7 @@ static int pack_window_contains(git_mwindow *win, off_t offset);
static
int
packfile_sort__cb
(
const
void
*
a_
,
const
void
*
b_
);
static
int
packfile_load__cb
(
void
*
_data
,
char
*
path
);
static
int
packfile_load__cb
(
void
*
_data
,
git_buf
*
path
);
static
int
packfile_refresh_all
(
struct
pack_backend
*
backend
);
static
int
pack_entry_find
(
struct
git_pack_entry
*
e
,
...
...
@@ -207,23 +207,23 @@ static int packfile_sort__cb(const void *a_, const void *b_)
static
int
packfile_load__cb
(
void
*
_data
,
char
*
path
)
static
int
packfile_load__cb
(
void
*
_data
,
git_buf
*
path
)
{
struct
pack_backend
*
backend
=
(
struct
pack_backend
*
)
_data
;
struct
git_pack_file
*
pack
;
int
error
;
size_t
i
;
if
(
git__suffixcmp
(
path
,
".idx"
)
!=
0
)
if
(
git__suffixcmp
(
path
->
ptr
,
".idx"
)
!=
0
)
return
GIT_SUCCESS
;
/* not an index */
for
(
i
=
0
;
i
<
backend
->
packs
.
length
;
++
i
)
{
struct
git_pack_file
*
p
=
git_vector_get
(
&
backend
->
packs
,
i
);
if
(
memcmp
(
p
->
pack_name
,
path
,
strlen
(
path
)
-
strlen
(
".idx"
))
==
0
)
if
(
memcmp
(
p
->
pack_name
,
path
->
ptr
,
path
->
size
-
strlen
(
".idx"
))
==
0
)
return
GIT_SUCCESS
;
}
error
=
git_packfile_check
(
&
pack
,
path
);
error
=
git_packfile_check
(
&
pack
,
path
->
ptr
);
if
(
error
==
GIT_ENOTFOUND
)
{
/* ignore missing .pack file as git does */
return
GIT_SUCCESS
;
...
...
@@ -250,11 +250,13 @@ static int packfile_refresh_all(struct pack_backend *backend)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to refresh packfiles. Backend not found"
);
if
(
st
.
st_mtime
!=
backend
->
pack_folder_mtime
)
{
char
path
[
GIT_PATH_MAX
]
;
strcpy
(
path
,
backend
->
pack_folder
);
git_buf
path
=
GIT_BUF_INIT
;
git_buf_sets
(
&
path
,
backend
->
pack_folder
);
/* reload all packs */
error
=
git_futils_direach
(
path
,
GIT_PATH_MAX
,
packfile_load__cb
,
(
void
*
)
backend
);
error
=
git_futils_direach
(
&
path
,
packfile_load__cb
,
(
void
*
)
backend
);
git_buf_free
(
&
path
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to refresh packfiles"
);
...
...
@@ -451,27 +453,25 @@ static void pack_backend__free(git_odb_backend *_backend)
int
git_odb_backend_pack
(
git_odb_backend
**
backend_out
,
const
char
*
objects_dir
)
{
struct
pack_backend
*
backend
;
char
path
[
GIT_PATH_MAX
];
struct
pack_backend
*
backend
=
NULL
;
git_buf
path
=
GIT_BUF_INIT
;
int
error
=
GIT_SUCCESS
;
backend
=
git__calloc
(
1
,
sizeof
(
struct
pack_backend
));
if
(
backend
==
NULL
)
return
GIT_ENOMEM
;
if
(
git_vector_init
(
&
backend
->
packs
,
8
,
packfile_sort__cb
)
<
GIT_SUCCESS
)
{
git__free
(
backend
);
return
GIT_ENOMEM
;
}
error
=
git_vector_init
(
&
backend
->
packs
,
8
,
packfile_sort__cb
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
git_path_join
(
path
,
objects_dir
,
"pack"
);
if
(
git_futils_isdir
(
path
)
==
GIT_SUCCESS
)
{
backend
->
pack_folder
=
git__strdup
(
path
);
backend
->
pack_folder_mtime
=
0
;
error
=
git_buf_joinpath
(
&
path
,
objects_dir
,
"pack"
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
backend
->
pack_folder
==
NULL
)
{
git__free
(
backend
);
return
GIT_ENOMEM
;
}
if
(
git_futils_isdir
(
git_buf_cstr
(
&
path
))
==
GIT_SUCCESS
)
{
backend
->
pack_folder
=
git_buf_detach
(
&
path
);
backend
->
pack_folder_mtime
=
0
;
}
backend
->
parent
.
read
=
&
pack_backend__read
;
...
...
@@ -481,5 +481,11 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
backend
->
parent
.
free
=
&
pack_backend__free
;
*
backend_out
=
(
git_odb_backend
*
)
backend
;
return
GIT_SUCCESS
;
cleanup
:
if
(
error
<
GIT_SUCCESS
)
git__free
(
backend
);
git_buf_free
(
&
path
);
return
error
;
}
src/path.c
View file @
40e73d6f
...
...
@@ -16,7 +16,7 @@
* Based on the Android implementation, BSD licensed.
* Check http://android.git.kernel.org/
*/
int
git_path_basename_r
(
char
*
buffer
,
size_t
bufflen
,
const
char
*
path
)
int
git_path_basename_r
(
git_buf
*
buffer
,
const
char
*
path
)
{
const
char
*
endp
,
*
startp
;
int
len
,
result
;
...
...
@@ -49,18 +49,13 @@ int git_path_basename_r(char *buffer, size_t bufflen, const char *path)
Exit:
result
=
len
;
if
(
buffer
==
NULL
)
{
return
result
;
}
if
(
len
>
(
int
)
bufflen
-
1
)
{
len
=
(
int
)
bufflen
-
1
;
result
=
GIT_ENOMEM
;
}
if
(
len
>=
0
)
{
memmove
(
buffer
,
startp
,
len
);
buffer
[
len
]
=
0
;
if
(
buffer
!=
NULL
)
{
if
(
git_buf_set
(
buffer
,
startp
,
len
)
<
GIT_SUCCESS
)
return
git__rethrow
(
git_buf_lasterror
(
buffer
),
"Could not get basename of '%s'"
,
path
);
}
return
result
;
}
...
...
@@ -68,7 +63,7 @@ Exit:
* Based on the Android implementation, BSD licensed.
* Check http://android.git.kernel.org/
*/
int
git_path_dirname_r
(
char
*
buffer
,
size_t
bufflen
,
const
char
*
path
)
int
git_path_dirname_r
(
git_buf
*
buffer
,
const
char
*
path
)
{
const
char
*
endp
;
int
result
,
len
;
...
...
@@ -114,59 +109,39 @@ int git_path_dirname_r(char *buffer, size_t bufflen, const char *path)
Exit:
result
=
len
;
if
(
len
+
1
>
GIT_PATH_MAX
)
{
return
GIT_ENOMEM
;
}
if
(
buffer
==
NULL
)
return
result
;
if
(
len
>
(
int
)
bufflen
-
1
)
{
len
=
(
int
)
bufflen
-
1
;
result
=
GIT_ENOMEM
;
if
(
buffer
!=
NULL
)
{
if
(
git_buf_set
(
buffer
,
path
,
len
)
<
GIT_SUCCESS
)
return
git__rethrow
(
git_buf_lasterror
(
buffer
),
"Could not get dirname of '%s'"
,
path
);
}
if
(
len
>=
0
)
{
memmove
(
buffer
,
path
,
len
);
buffer
[
len
]
=
0
;
}
return
result
;
}
char
*
git_path_dirname
(
const
char
*
path
)
{
char
*
dname
=
NULL
;
int
len
;
git_buf
buf
=
GIT_BUF_INIT
;
char
*
dirname
;
len
=
(
path
?
strlen
(
path
)
:
0
)
+
2
;
dname
=
(
char
*
)
git__malloc
(
len
);
if
(
dname
==
NULL
)
return
NULL
;
git_path_dirname_r
(
&
buf
,
path
);
dirname
=
git_buf_detach
(
&
buf
);
git_buf_free
(
&
buf
);
/* avoid memleak if error occurs */
if
(
git_path_dirname_r
(
dname
,
len
,
path
)
<
GIT_SUCCESS
)
{
git__free
(
dname
);
return
NULL
;
}
return
dname
;
return
dirname
;
}
char
*
git_path_basename
(
const
char
*
path
)
{
char
*
bname
=
NULL
;
int
len
;
len
=
(
path
?
strlen
(
path
)
:
0
)
+
2
;
bname
=
(
char
*
)
git__malloc
(
len
);
if
(
bname
==
NULL
)
return
NULL
;
git_buf
buf
=
GIT_BUF_INIT
;
char
*
basename
;
if
(
git_path_basename_r
(
bname
,
len
,
path
)
<
GIT_SUCCESS
)
{
git__free
(
bname
);
return
NULL
;
}
git_path_basename_r
(
&
buf
,
path
);
basename
=
git_buf_detach
(
&
buf
);
git_buf_free
(
&
buf
);
/* avoid memleak if error occurs */
return
bname
;
return
b
ase
name
;
}
...
...
@@ -188,39 +163,6 @@ const char *git_path_topdir(const char *path)
return
&
path
[
i
+
1
];
}
void
git_path_join_n
(
char
*
buffer_out
,
int
count
,
...)
{
va_list
ap
;
int
i
;
char
*
buffer_start
=
buffer_out
;
va_start
(
ap
,
count
);
for
(
i
=
0
;
i
<
count
;
++
i
)
{
const
char
*
path
;
int
len
;
path
=
va_arg
(
ap
,
const
char
*
);
assert
((
i
==
0
)
||
path
!=
buffer_start
);
if
(
i
>
0
&&
*
path
==
'/'
&&
buffer_out
>
buffer_start
&&
buffer_out
[
-
1
]
==
'/'
)
path
++
;
if
(
!*
path
)
continue
;
len
=
strlen
(
path
);
memmove
(
buffer_out
,
path
,
len
);
buffer_out
=
buffer_out
+
len
;
if
(
i
<
count
-
1
&&
buffer_out
[
-
1
]
!=
'/'
)
*
buffer_out
++
=
'/'
;
}
va_end
(
ap
);
*
buffer_out
=
'\0'
;
}
int
git_path_root
(
const
char
*
path
)
{
int
offset
=
0
;
...
...
@@ -237,34 +179,61 @@ int git_path_root(const char *path)
return
-
1
;
/* Not a real error. Rather a signal than the path is not rooted */
}
int
git_path_prettify
(
char
*
path_out
,
const
char
*
path
,
const
char
*
base
)
int
git_path_prettify
(
git_buf
*
path_out
,
const
char
*
path
,
const
char
*
base
)
{
char
*
result
;
char
*
result
=
NULL
;
int
error
=
GIT_SUCCESS
;
git_buf_clear
(
path_out
);
/* construct path if needed */
if
(
base
!=
NULL
&&
git_path_root
(
path
)
<
0
)
{
if
((
error
=
git_buf_joinpath
(
path_out
,
base
,
path
))
<
GIT_SUCCESS
)
return
error
;
path
=
path_out
->
ptr
;
}
/* allow realpath to allocate the buffer */
if
(
path
!=
NULL
)
result
=
p_realpath
(
path
,
NULL
);
if
(
base
==
NULL
||
git_path_root
(
path
)
>=
0
)
{
result
=
p_realpath
(
path
,
path_out
);
if
(
result
)
{
error
=
git_buf_sets
(
path_out
,
result
);
git__free
(
result
);
}
else
{
char
aux_path
[
GIT_PATH_MAX
];
git_path_join
(
aux_path
,
base
,
path
);
result
=
p_realpath
(
aux_path
,
path_out
);
error
=
GIT_EOSERR
;
}
return
result
?
GIT_SUCCESS
:
GIT_EOSERR
;
return
error
;
}
int
git_path_prettify_dir
(
char
*
path_out
,
const
char
*
path
,
const
char
*
base
)
int
git_path_prettify_dir
(
git_buf
*
path_out
,
const
char
*
path
,
const
char
*
base
)
{
size_t
end
;
int
error
=
git_path_prettify
(
path_out
,
path
,
base
)
;
if
(
git_path_prettify
(
path_out
,
path
,
base
)
<
GIT_SUCCESS
)
return
GIT_EOSERR
;
if
(
error
==
GIT_SUCCESS
)
error
=
git_path_to_dir
(
path_out
)
;
end
=
strlen
(
path_out
);
return
error
;
}
if
(
end
&&
path_out
[
end
-
1
]
!=
'/'
)
{
path_out
[
end
]
=
'/'
;
path_out
[
end
+
1
]
=
'\0'
;
}
int
git_path_to_dir
(
git_buf
*
path
)
{
if
(
path
->
asize
>
0
&&
path
->
size
>
0
&&
path
->
ptr
[
path
->
size
-
1
]
!=
'/'
)
git_buf_putc
(
path
,
'/'
);
return
GIT_SUCCESS
;
return
git_buf_lasterror
(
path
)
;
}
void
git_path_string_to_dir
(
char
*
path
,
size_t
size
)
{
size_t
end
=
strlen
(
path
);
if
(
end
&&
path
[
end
-
1
]
!=
'/'
&&
end
<
size
)
{
path
[
end
]
=
'/'
;
path
[
end
+
1
]
=
'\0'
;
}
}
src/path.h
View file @
40e73d6f
...
...
@@ -8,6 +8,7 @@
#define INCLUDE_path_h__
#include "common.h"
#include "buffer.h"
/*
* The dirname() function shall take a pointer to a character string
...
...
@@ -22,11 +23,13 @@
* The `git_path_dirname` implementation is thread safe. The returned
* string must be manually free'd.
*
* The `git_path_dirname_r` implementation expects a string allocated
* by the user with big enough size.
* The `git_path_dirname_r` implementation writes the dirname to a `git_buf`
* if the buffer pointer is not NULL.
* It returns an error code < 0 if there is an allocation error, otherwise
* the length of the dirname (which will be > 0).
*/
extern
char
*
git_path_dirname
(
const
char
*
path
);
extern
int
git_path_dirname_r
(
char
*
buffer
,
size_t
bufflen
,
const
char
*
path
);
extern
int
git_path_dirname_r
(
git_buf
*
buffer
,
const
char
*
path
);
/*
* This function returns the basename of the file, which is the last
...
...
@@ -40,32 +43,22 @@ extern int git_path_dirname_r(char *buffer, size_t bufflen, const char *path);
* The `git_path_basename` implementation is thread safe. The returned
* string must be manually free'd.
*
* The `git_path_basename_r` implementation expects a string allocated
* by the user with big enough size.
* The `git_path_basename_r` implementation writes the basename to a `git_buf`.
* It returns an error code < 0 if there is an allocation error, otherwise
* the length of the basename (which will be >= 0).
*/
extern
char
*
git_path_basename
(
const
char
*
path
);
extern
int
git_path_basename_r
(
char
*
buffer
,
size_t
bufflen
,
const
char
*
path
);
extern
int
git_path_basename_r
(
git_buf
*
buffer
,
const
char
*
path
);
extern
const
char
*
git_path_topdir
(
const
char
*
path
);
/**
* Join two paths together. Takes care of properly fixing the
* middle slashes and everything
*
* The paths are joined together into buffer_out; this is expected
* to be an user allocated buffer of `GIT_PATH_MAX` size
*/
extern
void
git_path_join_n
(
char
*
buffer_out
,
int
npath
,
...);
GIT_INLINE
(
void
)
git_path_join
(
char
*
buffer_out
,
const
char
*
path_a
,
const
char
*
path_b
)
{
git_path_join_n
(
buffer_out
,
2
,
path_a
,
path_b
);
}
extern
int
git_path_root
(
const
char
*
path
);
int
git_path_root
(
const
char
*
path
);
extern
int
git_path_prettify
(
git_buf
*
path_out
,
const
char
*
path
,
const
char
*
base
);
extern
int
git_path_prettify_dir
(
git_buf
*
path_out
,
const
char
*
path
,
const
char
*
base
);
int
git_path_prettify
(
char
*
path_out
,
const
char
*
path
,
const
char
*
base
);
int
git_path_prettify_dir
(
char
*
path_out
,
const
char
*
path
,
const
char
*
bas
e
);
extern
int
git_path_to_dir
(
git_buf
*
path
);
extern
void
git_path_string_to_dir
(
char
*
path
,
size_t
siz
e
);
#ifdef GIT_WIN32
GIT_INLINE
(
void
)
git_path_mkposix
(
char
*
path
)
...
...
src/pkt.c
View file @
40e73d6f
...
...
@@ -268,8 +268,7 @@ void git_pkt_free(git_pkt *pkt)
int
git_pkt_buffer_flush
(
git_buf
*
buf
)
{
git_buf_put
(
buf
,
pkt_flush_str
,
strlen
(
pkt_flush_str
));
return
git_buf_oom
(
buf
)
?
GIT_ENOMEM
:
GIT_SUCCESS
;
return
git_buf_put
(
buf
,
pkt_flush_str
,
strlen
(
pkt_flush_str
));
}
int
git_pkt_send_flush
(
int
s
)
...
...
@@ -291,9 +290,7 @@ static int buffer_want_with_caps(git_remote_head *head, git_transport_caps *caps
git_buf_grow
(
buf
,
buf
->
size
+
len
);
git_oid_fmt
(
oid
,
&
head
->
oid
);
git_buf_printf
(
buf
,
"%04xwant %s%c%s
\n
"
,
len
,
oid
,
0
,
capstr
);
return
git_buf_oom
(
buf
)
?
GIT_ENOMEM
:
GIT_SUCCESS
;
return
git_buf_printf
(
buf
,
"%04xwant %s%c%s
\n
"
,
len
,
oid
,
0
,
capstr
);
}
static
int
send_want_with_caps
(
git_remote_head
*
head
,
git_transport_caps
*
caps
,
GIT_SOCKET
fd
)
...
...
@@ -401,8 +398,7 @@ int git_pkt_buffer_have(git_oid *oid, git_buf *buf)
memset
(
oidhex
,
0x0
,
sizeof
(
oidhex
));
git_oid_fmt
(
oidhex
,
oid
);
git_buf_printf
(
buf
,
"%s%s
\n
"
,
pkt_have_prefix
,
oidhex
);
return
git_buf_oom
(
buf
)
?
GIT_ENOMEM
:
GIT_SUCCESS
;
return
git_buf_printf
(
buf
,
"%s%s
\n
"
,
pkt_have_prefix
,
oidhex
);
}
int
git_pkt_send_have
(
git_oid
*
oid
,
int
fd
)
...
...
@@ -416,8 +412,7 @@ int git_pkt_send_have(git_oid *oid, int fd)
int
git_pkt_buffer_done
(
git_buf
*
buf
)
{
git_buf_puts
(
buf
,
pkt_done_str
);
return
git_buf_oom
(
buf
)
?
GIT_ENOMEM
:
GIT_SUCCESS
;
return
git_buf_puts
(
buf
,
pkt_done_str
);
}
int
git_pkt_send_done
(
int
fd
)
...
...
src/posix.c
View file @
40e73d6f
...
...
@@ -35,7 +35,8 @@ int p_getcwd(char *buffer_out, size_t size)
git_path_mkposix
(
buffer_out
);
git_path_join
(
buffer_out
,
buffer_out
,
""
);
//Ensure the path ends with a trailing slash
git_path_string_to_dir
(
buffer_out
,
size
);
//Ensure the path ends with a trailing slash
return
GIT_SUCCESS
;
}
...
...
src/reflog.c
View file @
40e73d6f
...
...
@@ -51,7 +51,7 @@ static int reflog_write(const char *log_path, const char *oid_old,
git_buf_puts
(
&
log
,
oid_new
);
git_signature__writebuf
(
&
log
,
" "
,
committer
);
log
.
size
--
;
/* drop LF */
git_buf_truncate
(
&
log
,
log
.
size
-
1
)
;
/* drop LF */
if
(
msg
)
{
if
(
strchr
(
msg
,
'\n'
))
{
...
...
@@ -65,15 +65,21 @@ static int reflog_write(const char *log_path, const char *oid_old,
git_buf_putc
(
&
log
,
'\n'
);
if
((
error
=
git_buf_lasterror
(
&
log
))
<
GIT_SUCCESS
)
{
git_buf_free
(
&
log
);
return
git__rethrow
(
error
,
"Failed to write reflog. Memory allocation failure"
);
}
if
((
error
=
git_filebuf_open
(
&
fbuf
,
log_path
,
GIT_FILEBUF_APPEND
))
<
GIT_SUCCESS
)
{
git_buf_free
(
&
log
);
return
git__
throw
(
GIT_ERROR
,
"Failed to write reflog. Cannot open reflog `%s`"
,
log_path
);
return
git__
rethrow
(
error
,
"Failed to write reflog. Cannot open reflog `%s`"
,
log_path
);
}
git_filebuf_write
(
&
fbuf
,
log
.
ptr
,
log
.
size
);
error
=
git_filebuf_commit
(
&
fbuf
,
GIT_REFLOG_FILE_MODE
);
git_buf_free
(
&
log
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to write reflog"
);
}
...
...
@@ -176,7 +182,7 @@ void git_reflog_free(git_reflog *reflog)
int
git_reflog_read
(
git_reflog
**
reflog
,
git_reference
*
ref
)
{
int
error
;
char
log_path
[
GIT_PATH_MAX
]
;
git_buf
log_path
=
GIT_BUF_INIT
;
git_fbuffer
log_file
=
GIT_FBUFFER_INIT
;
git_reflog
*
log
=
NULL
;
...
...
@@ -185,23 +191,28 @@ int git_reflog_read(git_reflog **reflog, git_reference *ref)
if
((
error
=
reflog_init
(
&
log
,
ref
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to read reflog. Cannot init reflog"
);
git_path_join_n
(
log_path
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
);
error
=
git_buf_join_n
(
&
log_path
,
'/'
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
((
error
=
git_futils_readbuffer
(
&
log_file
,
log_path
))
<
GIT_SUCCESS
)
{
git_
reflog_free
(
log
);
return
git__rethrow
(
error
,
"Failed to read reflog. Cannot read file `%s`"
,
log_path
)
;
if
((
error
=
git_futils_readbuffer
(
&
log_file
,
log_path
.
ptr
))
<
GIT_SUCCESS
)
{
git_
_rethrow
(
error
,
"Failed to read reflog. Cannot read file `%s`"
,
log_path
.
ptr
);
goto
cleanup
;
}
error
=
reflog_parse
(
log
,
log_file
.
data
,
log_file
.
len
);
git_futils_freebuffer
(
&
log_file
);
if
(
error
==
GIT_SUCCESS
)
*
reflog
=
log
;
if
((
error
=
reflog_parse
(
log
,
log_file
.
data
,
log_file
.
len
))
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"Failed to read reflog"
);
else
*
reflog
=
log
;
cleanup:
if
(
error
!=
GIT_SUCCESS
&&
log
!=
NULL
)
git_reflog_free
(
log
);
git_futils_freebuffer
(
&
log_file
);
git_buf_free
(
&
log_path
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to read reflog"
)
;
return
error
;
}
int
git_reflog_write
(
git_reference
*
ref
,
const
git_oid
*
oid_old
,
...
...
@@ -210,7 +221,7 @@ int git_reflog_write(git_reference *ref, const git_oid *oid_old,
int
error
;
char
old
[
GIT_OID_HEXSZ
+
1
];
char
new
[
GIT_OID_HEXSZ
+
1
];
char
log_path
[
GIT_PATH_MAX
]
;
git_buf
log_path
=
GIT_BUF_INIT
;
git_reference
*
r
;
const
git_oid
*
oid
;
...
...
@@ -220,65 +231,83 @@ int git_reflog_write(git_reference *ref, const git_oid *oid_old,
oid
=
git_reference_oid
(
r
);
if
(
oid
==
NULL
)
{
git_reference_free
(
r
);
return
git__throw
(
GIT_ERROR
,
error
=
git__throw
(
GIT_ERROR
,
"Failed to write reflog. Cannot resolve reference `%s`"
,
r
->
name
);
git_reference_free
(
r
);
return
error
;
}
git_reference_free
(
r
);
git_oid_to_string
(
new
,
GIT_OID_HEXSZ
+
1
,
oid
);
git_path_join_n
(
log_path
,
3
,
error
=
git_buf_join_n
(
&
log_path
,
'/'
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
git_reference_free
(
r
);
if
(
git_futils_exists
(
log_path
))
{
error
=
git_futils_mkpath2file
(
log_path
,
GIT_REFLOG_DIR_MODE
);
if
(
git_futils_exists
(
log_path
.
ptr
))
{
error
=
git_futils_mkpath2file
(
log_path
.
ptr
,
GIT_REFLOG_DIR_MODE
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
git__rethrow
(
error
,
"Failed to write reflog. Cannot create reflog directory"
);
}
else
if
(
git_futils_isfile
(
log_path
))
{
return
git__throw
(
GIT_ERROR
,
"Failed to write reflog. `%s` is directory"
,
log_path
);
}
else
if
(
git_futils_isfile
(
log_path
.
ptr
))
{
error
=
git__throw
(
GIT_ERROR
,
"Failed to write reflog. `%s` is directory"
,
log_path
.
ptr
);
}
else
if
(
oid_old
==
NULL
)
{
return
git__throw
(
GIT_ERROR
,
error
=
git__throw
(
GIT_ERROR
,
"Failed to write reflog. Old OID cannot be NULL for existing reference"
);
}
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
oid_old
)
git_oid_to_string
(
old
,
GIT_OID_HEXSZ
+
1
,
oid_old
);
git_oid_to_string
(
old
,
sizeof
(
old
)
,
oid_old
);
else
p_snprintf
(
old
,
GIT_OID_HEXSZ
+
1
,
"%0*d"
,
GIT_OID_HEXSZ
,
0
);
p_snprintf
(
old
,
sizeof
(
old
),
"%0*d"
,
GIT_OID_HEXSZ
,
0
);
error
=
reflog_write
(
log_path
.
ptr
,
old
,
new
,
committer
,
msg
);
return
reflog_write
(
log_path
,
old
,
new
,
committer
,
msg
);
cleanup:
git_buf_free
(
&
log_path
);
return
error
;
}
int
git_reflog_rename
(
git_reference
*
ref
,
const
char
*
new_name
)
{
char
old_path
[
GIT_PATH_MAX
];
char
new_path
[
GIT_PATH_MAX
];
int
error
;
git_buf
old_path
=
GIT_BUF_INIT
;
git_buf
new_path
=
GIT_BUF_INIT
;
if
(
git_buf_join_n
(
&
old_path
,
'/'
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
)
&&
git_buf_join_n
(
&
new_path
,
'/'
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
new_name
))
error
=
p_rename
(
git_buf_cstr
(
&
old_path
),
git_buf_cstr
(
&
new_path
));
else
error
=
GIT_ENOMEM
;
git_path_join_n
(
old_path
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
);
git_path_join_n
(
new_path
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
new_name
);
git_buf_free
(
&
old_path
);
git_buf_free
(
&
new_path
);
return
p_rename
(
old_path
,
new_path
)
;
return
error
;
}
int
git_reflog_delete
(
git_reference
*
ref
)
{
char
path
[
GIT_PATH_MAX
];
int
error
=
GIT_SUCCESS
;
git_buf
path
=
GIT_BUF_INIT
;
error
=
git_buf_join_n
(
&
path
,
'/'
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
);
git_path_join_n
(
path
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
);
if
(
error
==
GIT_SUCCESS
&&
git_futils_exists
(
path
.
ptr
)
==
0
)
error
=
p_unlink
(
path
.
ptr
);
if
(
git_futils_exists
(
path
))
return
GIT_SUCCESS
;
git_buf_free
(
&
path
);
return
p_unlink
(
path
)
;
return
error
;
}
unsigned
int
git_reflog_entrycount
(
git_reflog
*
reflog
)
...
...
src/refs.c
View file @
40e73d6f
...
...
@@ -88,9 +88,12 @@ void git_reference_free(git_reference *reference)
return
;
git__free
(
reference
->
name
);
reference
->
name
=
NULL
;
if
(
reference
->
flags
&
GIT_REF_SYMBOLIC
)
if
(
reference
->
flags
&
GIT_REF_SYMBOLIC
)
{
git__free
(
reference
->
target
.
symbolic
);
reference
->
target
.
symbolic
=
NULL
;
}
git__free
(
reference
);
}
...
...
@@ -123,14 +126,18 @@ static int reference_create(
static
int
reference_read
(
git_fbuffer
*
file_content
,
time_t
*
mtime
,
const
char
*
repo_path
,
const
char
*
ref_name
,
int
*
updated
)
{
char
path
[
GIT_PATH_MAX
];
git_buf
path
=
GIT_BUF_INIT
;
int
error
=
GIT_SUCCESS
;
assert
(
file_content
&&
repo_path
&&
ref_name
);
/* Determine the full path of the file */
git_path_join
(
path
,
repo_path
,
ref_name
);
if
((
error
=
git_buf_joinpath
(
&
path
,
repo_path
,
ref_name
))
==
GIT_SUCCESS
)
error
=
git_futils_readbuffer_updated
(
file_content
,
path
.
ptr
,
mtime
,
updated
);
git_buf_free
(
&
path
);
return
git_futils_readbuffer_updated
(
file_content
,
path
,
mtime
,
updated
)
;
return
error
;
}
static
int
loose_parse_symbolic
(
git_reference
*
ref
,
git_fbuffer
*
file_content
)
...
...
@@ -195,14 +202,14 @@ static int loose_parse_oid(git_oid *oid, git_fbuffer *file_content)
return
GIT_SUCCESS
;
}
static
git_rtype
loose_guess_rtype
(
const
char
*
full_path
)
static
git_rtype
loose_guess_rtype
(
const
git_buf
*
full_path
)
{
git_fbuffer
ref_file
=
GIT_FBUFFER_INIT
;
git_rtype
type
;
type
=
GIT_REF_INVALID
;
if
(
git_futils_readbuffer
(
&
ref_file
,
full_path
)
==
GIT_SUCCESS
)
{
if
(
git_futils_readbuffer
(
&
ref_file
,
full_path
->
ptr
)
==
GIT_SUCCESS
)
{
if
(
git__prefixcmp
((
const
char
*
)(
ref_file
.
data
),
GIT_SYMREF
)
==
0
)
type
=
GIT_REF_SYMBOLIC
;
else
...
...
@@ -287,14 +294,17 @@ cleanup:
static
int
loose_write
(
git_reference
*
ref
)
{
git_filebuf
file
=
GIT_FILEBUF_INIT
;
char
ref_path
[
GIT_PATH_MAX
]
;
git_buf
ref_path
=
GIT_BUF_INIT
;
int
error
;
struct
stat
st
;
git_path_join
(
ref_path
,
ref
->
owner
->
path_repository
,
ref
->
name
);
error
=
git_buf_joinpath
(
&
ref_path
,
ref
->
owner
->
path_repository
,
ref
->
name
);
if
(
error
<
GIT_SUCCESS
)
goto
unlock
;
if
((
error
=
git_filebuf_open
(
&
file
,
ref_path
,
GIT_FILEBUF_FORCE
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to write loose reference"
);
error
=
git_filebuf_open
(
&
file
,
ref_path
.
ptr
,
GIT_FILEBUF_FORCE
);
if
(
error
<
GIT_SUCCESS
)
goto
unlock
;
if
(
ref
->
flags
&
GIT_REF_OID
)
{
char
oid
[
GIT_OID_HEXSZ
+
1
];
...
...
@@ -314,12 +324,15 @@ static int loose_write(git_reference *ref)
goto
unlock
;
}
if
(
p_stat
(
ref_path
,
&
st
)
==
GIT_SUCCESS
)
if
(
p_stat
(
ref_path
.
ptr
,
&
st
)
==
GIT_SUCCESS
)
ref
->
mtime
=
st
.
st_mtime
;
git_buf_free
(
&
ref_path
);
return
git_filebuf_commit
(
&
file
,
GIT_REFS_FILE_MODE
);
unlock:
git_buf_free
(
&
ref_path
);
git_filebuf_cleanup
(
&
file
);
return
git__rethrow
(
error
,
"Failed to write loose reference"
);
}
...
...
@@ -518,14 +531,13 @@ struct dirent_list_data {
void
*
callback_payload
;
};
static
int
_dirent_loose_listall
(
void
*
_data
,
char
*
full_path
)
static
int
_dirent_loose_listall
(
void
*
_data
,
git_buf
*
full_path
)
{
struct
dirent_list_data
*
data
=
(
struct
dirent_list_data
*
)
_data
;
c
har
*
file_path
=
full_path
+
data
->
repo_path_len
;
c
onst
char
*
file_path
=
full_path
->
ptr
+
data
->
repo_path_len
;
if
(
git_futils_isdir
(
full_path
)
==
GIT_SUCCESS
)
return
git_futils_direach
(
full_path
,
GIT_PATH_MAX
,
_dirent_loose_listall
,
_data
);
if
(
git_futils_isdir
(
full_path
->
ptr
)
==
GIT_SUCCESS
)
return
git_futils_direach
(
full_path
,
_dirent_loose_listall
,
_data
);
/* do not add twice a reference that exists already in the packfile */
if
((
data
->
list_flags
&
GIT_REF_PACKED
)
!=
0
&&
...
...
@@ -540,20 +552,18 @@ static int _dirent_loose_listall(void *_data, char *full_path)
return
data
->
callback
(
file_path
,
data
->
callback_payload
);
}
static
int
_dirent_loose_load
(
void
*
data
,
char
*
full_path
)
static
int
_dirent_loose_load
(
void
*
data
,
git_buf
*
full_path
)
{
git_repository
*
repository
=
(
git_repository
*
)
data
;
void
*
old_ref
=
NULL
;
struct
packref
*
ref
;
char
*
file_path
;
c
onst
c
har
*
file_path
;
int
error
;
if
(
git_futils_isdir
(
full_path
)
==
GIT_SUCCESS
)
return
git_futils_direach
(
full_path
,
GIT_PATH_MAX
,
_dirent_loose_load
,
repository
);
if
(
git_futils_isdir
(
full_path
->
ptr
)
==
GIT_SUCCESS
)
return
git_futils_direach
(
full_path
,
_dirent_loose_load
,
repository
);
file_path
=
full_path
+
strlen
(
repository
->
path_repository
);
file_path
=
full_path
->
ptr
+
strlen
(
repository
->
path_repository
);
error
=
loose_lookup_to_packfile
(
&
ref
,
repository
,
file_path
);
if
(
error
==
GIT_SUCCESS
)
{
...
...
@@ -582,21 +592,24 @@ static int _dirent_loose_load(void *data, char *full_path)
*/
static
int
packed_loadloose
(
git_repository
*
repository
)
{
char
refs_path
[
GIT_PATH_MAX
];
int
error
=
GIT_SUCCESS
;
git_buf
refs_path
=
GIT_BUF_INIT
;
/* the packfile must have been previously loaded! */
assert
(
repository
->
references
.
packfile
);
git_path_join
(
refs_path
,
repository
->
path_repository
,
GIT_REFS_DIR
);
if
((
error
=
git_buf_joinpath
(
&
refs_path
,
repository
->
path_repository
,
GIT_REFS_DIR
))
<
GIT_SUCCESS
)
return
error
;
/*
* Load all the loose files from disk into the Packfile table.
* This will overwrite any old packed entries with their
* updated loose versions
*/
return
git_futils_direach
(
refs_path
,
GIT_PATH_MAX
,
_dirent_loose_load
,
repository
)
;
error
=
git_futils_direach
(
&
refs_path
,
_dirent_loose_load
,
repository
);
git_buf_free
(
&
refs_path
);
return
error
;
}
/*
...
...
@@ -704,20 +717,26 @@ static int packed_find_peel(git_repository *repo, struct packref *ref)
static
int
packed_remove_loose
(
git_repository
*
repo
,
git_vector
*
packing_list
)
{
unsigned
int
i
;
char
full_path
[
GIT_PATH_MAX
]
;
git_buf
full_path
=
GIT_BUF_INIT
;
int
error
=
GIT_SUCCESS
;
for
(
i
=
0
;
i
<
packing_list
->
length
;
++
i
)
{
struct
packref
*
ref
=
git_vector_get
(
packing_list
,
i
);
int
an_error
;
if
((
ref
->
flags
&
GIT_PACKREF_WAS_LOOSE
)
==
0
)
continue
;
git_path_join
(
full_path
,
repo
->
path_repository
,
ref
->
name
);
an_error
=
git_buf_joinpath
(
&
full_path
,
repo
->
path_repository
,
ref
->
name
);
if
(
an_error
==
GIT_SUCCESS
&&
git_futils_exists
(
full_path
.
ptr
)
==
GIT_SUCCESS
&&
p_unlink
(
full_path
.
ptr
)
<
GIT_SUCCESS
)
an_error
=
GIT_EOSERR
;
if
(
git_futils_exists
(
full_path
)
==
GIT_SUCCESS
&&
p_unlink
(
full_path
)
<
GIT_SUCCESS
)
error
=
GIT_EOSERR
;
/* keep the error if we haven't seen one yet */
if
(
error
>
an_error
)
error
=
an_error
;
/*
* if we fail to remove a single file, this is *not* good,
...
...
@@ -727,6 +746,8 @@ static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
*/
}
git_buf_free
(
&
full_path
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to remove loose packed reference"
);
...
...
@@ -747,9 +768,9 @@ static int packed_write(git_repository *repo)
{
git_filebuf
pack_file
=
GIT_FILEBUF_INIT
;
int
error
;
const
char
*
errmsg
=
"Failed to write packed references file"
;
unsigned
int
i
;
char
pack_file_path
[
GIT_PATH_MAX
];
git_buf
pack_file_path
=
GIT_BUF_INIT
;
git_vector
packing_list
;
size_t
total_refs
;
...
...
@@ -758,7 +779,7 @@ static int packed_write(git_repository *repo)
total_refs
=
repo
->
references
.
packfile
->
key_count
;
if
((
error
=
git_vector_init
(
&
packing_list
,
total_refs
,
packed_sort
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to init packed refernces list"
);
return
git__rethrow
(
error
,
"Failed to init packed refer
e
nces list"
);
/* Load all the packfile into a vector */
{
...
...
@@ -775,16 +796,23 @@ static int packed_write(git_repository *repo)
git_vector_sort
(
&
packing_list
);
/* Now we can open the file! */
git_path_join
(
pack_file_path
,
repo
->
path_repository
,
GIT_PACKEDREFS_FILE
);
if
((
error
=
git_filebuf_open
(
&
pack_file
,
pack_file_path
,
0
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to write open packed references file"
);
error
=
git_buf_joinpath
(
&
pack_file_path
,
repo
->
path_repository
,
GIT_PACKEDREFS_FILE
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
((
error
=
git_filebuf_open
(
&
pack_file
,
pack_file_path
.
ptr
,
0
))
<
GIT_SUCCESS
)
{
errmsg
=
"Failed to open packed references file"
;
goto
cleanup
;
}
/* Packfiles have a header... apparently
* This is in fact not required, but we might as well print it
* just for kicks */
if
((
error
=
git_filebuf_printf
(
&
pack_file
,
"%s
\n
"
,
GIT_PACKEDREFS_HEADER
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to write packed references file header"
);
git_filebuf_printf
(
&
pack_file
,
"%s
\n
"
,
GIT_PACKEDREFS_HEADER
))
<
GIT_SUCCESS
)
{
errmsg
=
"Failed to write packed references file header"
;
goto
cleanup
;
}
for
(
i
=
0
;
i
<
packing_list
.
length
;
++
i
)
{
struct
packref
*
ref
=
(
struct
packref
*
)
git_vector_get
(
&
packing_list
,
i
);
...
...
@@ -812,17 +840,19 @@ cleanup:
error
=
packed_remove_loose
(
repo
,
&
packing_list
);
if
(
p_stat
(
pack_file_path
,
&
st
)
==
GIT_SUCCESS
)
if
(
p_stat
(
pack_file_path
.
ptr
,
&
st
)
==
GIT_SUCCESS
)
repo
->
references
.
packfile_time
=
st
.
st_mtime
;
}
}
else
git_filebuf_cleanup
(
&
pack_file
);
git_vector_free
(
&
packing_list
);
git_buf_free
(
&
pack_file_path
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to write packed references file"
);
if
(
error
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"%s"
,
errmsg
);
return
error
;
}
static
int
_reference_available_cb
(
const
char
*
ref
,
void
*
data
)
...
...
@@ -873,21 +903,25 @@ static int reference_available(
static
int
reference_exists
(
int
*
exists
,
git_repository
*
repo
,
const
char
*
ref_name
)
{
int
error
;
char
ref_path
[
GIT_PATH_MAX
]
;
git_buf
ref_path
=
GIT_BUF_INIT
;
error
=
packed_load
(
repo
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Cannot resolve if a reference exists"
);
git_path_join
(
ref_path
,
repo
->
path_repository
,
ref_name
);
error
=
git_buf_joinpath
(
&
ref_path
,
repo
->
path_repository
,
ref_name
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Cannot resolve if a reference exists"
);
if
(
git_futils_isfile
(
ref_path
)
==
GIT_SUCCESS
||
git_hashtable_lookup
(
repo
->
references
.
packfile
,
ref_path
)
!=
NULL
)
{
if
(
git_futils_isfile
(
ref_path
.
ptr
)
==
GIT_SUCCESS
||
git_hashtable_lookup
(
repo
->
references
.
packfile
,
ref_path
.
ptr
)
!=
NULL
)
{
*
exists
=
1
;
}
else
{
*
exists
=
0
;
}
git_buf_free
(
&
ref_path
);
return
GIT_SUCCESS
;
}
...
...
@@ -972,12 +1006,15 @@ static int reference_delete(git_reference *ref)
/* If the reference is loose, we can just remove the reference
* from the filesystem */
}
else
{
char
full_path
[
GIT_PATH_MAX
];
git_reference
*
ref_in_pack
;
git_buf
full_path
=
GIT_BUF_INIT
;
git_path_join
(
full_path
,
ref
->
owner
->
path_repository
,
ref
->
name
);
error
=
git_buf_joinpath
(
&
full_path
,
ref
->
owner
->
path_repository
,
ref
->
name
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
p_unlink
(
full_path
);
error
=
p_unlink
(
full_path
.
ptr
);
git_buf_free
(
&
full_path
);
/* done with path at this point */
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
...
...
@@ -1261,8 +1298,7 @@ int git_reference_set_target(git_reference *ref, const char *target)
int
git_reference_rename
(
git_reference
*
ref
,
const
char
*
new_name
,
int
force
)
{
int
error
;
char
aux_path
[
GIT_PATH_MAX
];
git_buf
aux_path
=
GIT_BUF_INIT
;
char
normalized
[
GIT_REFNAME_MAX
];
const
char
*
head_target
=
NULL
;
...
...
@@ -1309,6 +1345,13 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
return
git__rethrow
(
error
,
"Failed to rename reference. Reference already exists"
);
/* Initialize path now so we won't get an allocation failure once
* we actually start removing things.
*/
error
=
git_buf_joinpath
(
&
aux_path
,
ref
->
owner
->
path_repository
,
new_name
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
/*
* Now delete the old ref and remove an possibly existing directory
* named `new_name`. Note that using the internal `reference_delete`
...
...
@@ -1318,10 +1361,9 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
if
((
error
=
reference_delete
(
ref
))
<
GIT_SUCCESS
)
goto
cleanup
;
git_path_join
(
aux_path
,
ref
->
owner
->
path_repository
,
new_name
);
if
(
git_futils_exists
(
aux_path
)
==
GIT_SUCCESS
)
{
if
(
git_futils_isdir
(
aux_path
)
==
GIT_SUCCESS
)
{
if
((
error
=
git_futils_rmdir_r
(
aux_path
,
0
))
<
GIT_SUCCESS
)
if
(
git_futils_exists
(
aux_path
.
ptr
)
==
GIT_SUCCESS
)
{
if
(
git_futils_isdir
(
aux_path
.
ptr
)
==
GIT_SUCCESS
)
{
if
((
error
=
git_futils_rmdir_r
(
aux_path
.
ptr
,
0
))
<
GIT_SUCCESS
)
goto
rollback
;
}
else
goto
rollback
;
}
...
...
@@ -1360,9 +1402,12 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
/*
* Rename the reflog file.
*/
git_path_join_n
(
aux_path
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
);
if
(
git_futils_exists
(
aux_path
)
==
GIT_SUCCESS
)
error
=
git_buf_join_n
(
&
aux_path
,
'/'
,
3
,
ref
->
owner
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
git_futils_exists
(
aux_path
.
ptr
)
==
GIT_SUCCESS
)
error
=
git_reflog_rename
(
ref
,
new_name
);
/*
...
...
@@ -1377,6 +1422,7 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
cleanup:
/* We no longer need the newly created reference nor the head */
git_reference_free
(
head
);
git_buf_free
(
&
aux_path
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to rename reference"
);
...
...
@@ -1395,6 +1441,8 @@ rollback:
/* The reference is no longer packed */
ref
->
flags
&=
~
GIT_REF_PACKED
;
git_buf_free
(
&
aux_path
);
return
error
==
GIT_SUCCESS
?
git__rethrow
(
GIT_ERROR
,
"Failed to rename reference. Did rollback"
)
:
git__rethrow
(
error
,
"Failed to rename reference. Failed to rollback"
);
...
...
@@ -1467,7 +1515,7 @@ int git_reference_foreach(
{
int
error
;
struct
dirent_list_data
data
;
char
refs_path
[
GIT_PATH_MAX
]
;
git_buf
refs_path
=
GIT_BUF_INIT
;
/* list all the packed references first */
if
(
list_flags
&
GIT_REF_PACKED
)
{
...
...
@@ -1493,8 +1541,15 @@ int git_reference_foreach(
data
.
callback
=
callback
;
data
.
callback_payload
=
payload
;
git_path_join
(
refs_path
,
repo
->
path_repository
,
GIT_REFS_DIR
);
return
git_futils_direach
(
refs_path
,
GIT_PATH_MAX
,
_dirent_loose_listall
,
&
data
);
if
((
error
=
git_buf_joinpath
(
&
refs_path
,
repo
->
path_repository
,
GIT_REFS_DIR
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to alloc space for references"
);
error
=
git_futils_direach
(
&
refs_path
,
_dirent_loose_listall
,
&
data
);
git_buf_free
(
&
refs_path
);
return
error
;
}
static
int
cb__reflist_add
(
const
char
*
ref
,
void
*
data
)
...
...
src/refspec.c
View file @
40e73d6f
...
...
@@ -93,3 +93,21 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
return
GIT_SUCCESS
;
}
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_buf_lasterror
(
out
);
/*
* No '*' at the end means that it's mapped to one specific local
* branch, so no actual transformation is needed.
*/
if
(
out
->
size
>
0
&&
out
->
ptr
[
out
->
size
-
1
]
!=
'*'
)
return
GIT_SUCCESS
;
git_buf_truncate
(
out
,
out
->
size
-
1
);
/* remove trailing '*' */
git_buf_puts
(
out
,
name
);
return
git_buf_lasterror
(
out
);
}
src/refspec.h
View file @
40e73d6f
...
...
@@ -8,6 +8,7 @@
#define INCLUDE_refspec_h__
#include "git2/refspec.h"
#include "buffer.h"
struct
git_refspec
{
struct
git_refspec
*
next
;
...
...
@@ -20,4 +21,15 @@ struct git_refspec {
int
git_refspec_parse
(
struct
git_refspec
*
refspec
,
const
char
*
str
);
/**
* Transform a reference to its target following the refspec's rules,
* and writes the results into a git_buf.
*
* @param out where to store the target name
* @param spec the refspec
* @param name the name of the reference to transform
* @return GIT_SUCCESS or error if buffer allocation fails
*/
int
git_refspec_transform_r
(
git_buf
*
out
,
const
git_refspec
*
spec
,
const
char
*
name
);
#endif
src/remote.c
View file @
40e73d6f
...
...
@@ -263,7 +263,7 @@ int git_remote_update_tips(git_remote *remote)
{
int
error
=
GIT_SUCCESS
;
unsigned
int
i
=
0
;
char
refname
[
GIT_PATH_MAX
]
;
git_buf
refname
=
GIT_BUF_INIT
;
git_vector
*
refs
=
&
remote
->
refs
;
git_remote_head
*
head
;
git_reference
*
ref
;
...
...
@@ -271,8 +271,6 @@ int git_remote_update_tips(git_remote *remote)
assert
(
remote
);
memset
(
refname
,
0x0
,
sizeof
(
refname
));
if
(
refs
->
length
==
0
)
return
GIT_SUCCESS
;
...
...
@@ -289,18 +287,20 @@ int git_remote_update_tips(git_remote *remote)
for
(;
i
<
refs
->
length
;
++
i
)
{
head
=
refs
->
contents
[
i
];
error
=
git_refspec_transform
(
refname
,
sizeof
(
refname
)
,
spec
,
head
->
name
);
error
=
git_refspec_transform
_r
(
&
refname
,
spec
,
head
->
name
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
break
;
error
=
git_reference_create_oid
(
&
ref
,
remote
->
repo
,
refname
,
&
head
->
oid
,
1
);
error
=
git_reference_create_oid
(
&
ref
,
remote
->
repo
,
refname
.
ptr
,
&
head
->
oid
,
1
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
break
;
git_reference_free
(
ref
);
}
return
GIT_SUCCESS
;
git_buf_free
(
&
refname
);
return
error
;
}
int
git_remote_connected
(
git_remote
*
remote
)
...
...
src/repository.c
View file @
40e73d6f
...
...
@@ -75,21 +75,17 @@ void git_repository_free(git_repository *repo)
*
* Open a repository object from its path
*/
static
int
quickcheck_repository_dir
(
const
char
*
repository_path
)
static
int
quickcheck_repository_dir
(
git_buf
*
repository_path
)
{
char
path_aux
[
GIT_PATH_MAX
];
/* Ensure HEAD file exists */
git_path_join
(
path_aux
,
repository_path
,
GIT_HEAD_FILE
);
if
(
git_futils_isfile
(
path_aux
)
<
0
)
/* Check OBJECTS_DIR first, since it will generate the longest path name */
if
(
git_futils_contains_dir
(
repository_path
,
GIT_OBJECTS_DIR
,
0
)
<
0
)
return
GIT_ERROR
;
git_path_join
(
path_aux
,
repository_path
,
GIT_OBJECTS_DIR
);
if
(
git_futils_
isdir
(
path_aux
)
<
0
)
/* Ensure HEAD file exists */
if
(
git_futils_
contains_file
(
repository_path
,
GIT_HEAD_FILE
,
0
)
<
0
)
return
GIT_ERROR
;
git_path_join
(
path_aux
,
repository_path
,
GIT_REFS_DIR
);
if
(
git_futils_isdir
(
path_aux
)
<
0
)
if
(
git_futils_contains_dir
(
repository_path
,
GIT_REFS_DIR
,
0
)
<
0
)
return
GIT_ERROR
;
return
GIT_SUCCESS
;
...
...
@@ -135,74 +131,74 @@ static int load_config_data(git_repository *repo)
static
int
load_workdir
(
git_repository
*
repo
)
{
i
f
(
!
repo
->
is_bare
)
{
char
workdir_buf
[
GIT_PATH_MAX
]
;
i
nt
error
;
git_buf
workdir_buf
=
GIT_BUF_INIT
;
if
(
git_path_dirname_r
(
workdir_buf
,
sizeof
(
workdir_buf
),
repo
->
path_repository
)
<
0
)
return
git__throw
(
GIT_EOSERR
,
"Failed to resolved working directory"
);
if
(
repo
->
is_bare
)
return
GIT_SUCCESS
;
git_path_join
(
workdir_buf
,
workdir_buf
,
""
);
git_path_dirname_r
(
&
workdir_buf
,
repo
->
path_repository
);
git_path_to_dir
(
&
workdir_buf
);
repo
->
workdir
=
git__strdup
(
workdir_buf
);
if
(
repo
->
workdir
==
NULL
)
return
GIT_ENOMEM
;
}
if
((
error
=
git_buf_lasterror
(
&
workdir_buf
))
==
GIT_SUCCESS
)
repo
->
workdir
=
git_buf_detach
(
&
workdir_buf
);
return
GIT_SUCCESS
;
git_buf_free
(
&
workdir_buf
);
return
error
;
}
int
git_repository_open
(
git_repository
**
repo_out
,
const
char
*
path
)
{
int
error
=
GIT_SUCCESS
;
char
path_buf
[
GIT_PATH_MAX
];
size_t
path_len
;
git_buf
path_buf
=
GIT_BUF_INIT
;
git_repository
*
repo
=
NULL
;
error
=
git_path_prettify_dir
(
path_buf
,
path
,
NULL
);
error
=
git_path_prettify_dir
(
&
path_buf
,
path
,
NULL
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to open repository"
);
path_len
=
strlen
(
path_buf
);
goto
cleanup
;
/**
* Check if the path we've been given is actually the path
* of the working dir, by testing if it contains a `.git`
* folder inside of it.
*/
git_path_join
(
path_buf
,
path_buf
,
DOT_GIT
);
if
(
git_futils_isdir
(
path_buf
)
<
GIT_SUCCESS
)
{
path_buf
[
path_len
]
=
0
;
}
git_futils_contains_dir
(
&
path_buf
,
DOT_GIT
,
1
);
/* append on success */
/* ignore error, since it just means `path/.git` doesn't exist */
if
(
quickcheck_repository_dir
(
path_buf
)
<
GIT_SUCCESS
)
return
git__throw
(
GIT_ENOTAREPO
,
if
(
quickcheck_repository_dir
(
&
path_buf
)
<
GIT_SUCCESS
)
{
error
=
git__throw
(
GIT_ENOTAREPO
,
"The given path is not a valid Git repository"
);
goto
cleanup
;
}
repo
=
repository_alloc
();
if
(
repo
==
NULL
)
return
GIT_ENOMEM
;
if
(
repo
==
NULL
)
{
error
=
GIT_ENOMEM
;
goto
cleanup
;
}
repo
->
path_repository
=
git_
_strdup
(
path_buf
);
repo
->
path_repository
=
git_
buf_detach
(
&
path_buf
);
if
(
repo
->
path_repository
==
NULL
)
{
git_repository_free
(
repo
)
;
return
GIT_ENOMEM
;
error
=
GIT_ENOMEM
;
goto
cleanup
;
}
error
=
load_config_data
(
repo
);
if
(
error
<
GIT_SUCCESS
)
{
git_repository_free
(
repo
);
return
error
;
}
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
load_workdir
(
repo
);
if
(
error
<
GIT_SUCCESS
)
{
git_repository_free
(
repo
);
return
error
;
}
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
*
repo_out
=
repo
;
return
GIT_SUCCESS
;
cleanup:
git_repository_free
(
repo
);
git_buf_free
(
&
path_buf
);
return
error
;
}
static
int
load_config
(
...
...
@@ -211,7 +207,7 @@ static int load_config(
const
char
*
global_config_path
,
const
char
*
system_config_path
)
{
char
config_path
[
GIT_PATH_MAX
]
;
git_buf
config_path
=
GIT_BUF_INIT
;
int
error
;
git_config
*
cfg
=
NULL
;
...
...
@@ -221,8 +217,13 @@ static int load_config(
if
(
error
<
GIT_SUCCESS
)
return
error
;
git_path_join
(
config_path
,
repo
->
path_repository
,
GIT_CONFIG_FILENAME_INREPO
);
error
=
git_config_add_file_ondisk
(
cfg
,
config_path
,
3
);
error
=
git_buf_joinpath
(
&
config_path
,
repo
->
path_repository
,
GIT_CONFIG_FILENAME_INREPO
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_config_add_file_ondisk
(
cfg
,
config_path
.
ptr
,
3
);
git_buf_free
(
&
config_path
);
/* done with config_path now */
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
...
...
@@ -251,19 +252,22 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
{
if
(
repo
->
_config
==
NULL
)
{
int
error
;
char
buf_global
[
GIT_PATH_MAX
],
buf_system
[
GIT_PATH_MAX
];
git_buf
global_buf
=
GIT_BUF_INIT
,
system_buf
=
GIT_BUF_INIT
;
const
char
*
global_config_path
=
NULL
;
const
char
*
system_config_path
=
NULL
;
if
(
git_config_find_global
(
buf_global
)
==
GIT_SUCCESS
)
global_config_path
=
buf_global
;
if
(
git_config_find_global
_r
(
&
global_buf
)
==
GIT_SUCCESS
)
global_config_path
=
global_buf
.
ptr
;
if
(
git_config_find_system
(
buf_system
)
==
GIT_SUCCESS
)
system_config_path
=
buf_system
;
if
(
git_config_find_system
_r
(
&
system_buf
)
==
GIT_SUCCESS
)
system_config_path
=
system_buf
.
ptr
;
error
=
load_config
(
&
repo
->
_config
,
repo
,
global_config_path
,
system_config_path
);
git_buf_free
(
&
global_buf
);
git_buf_free
(
&
system_buf
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
...
...
@@ -301,11 +305,14 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
if
(
repo
->
_odb
==
NULL
)
{
int
error
;
char
odb_path
[
GIT_PATH_MAX
]
;
git_buf
odb_path
=
GIT_BUF_INIT
;
git_path_join
(
odb_path
,
repo
->
path_repository
,
GIT_OBJECTS_DIR
);
error
=
git_buf_joinpath
(
&
odb_path
,
repo
->
path_repository
,
GIT_OBJECTS_DIR
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
error
=
git_odb_open
(
&
repo
->
_odb
,
odb_path
);
error
=
git_odb_open
(
&
repo
->
_odb
,
odb_path
.
ptr
);
git_buf_free
(
&
odb_path
);
/* done with path */
if
(
error
<
GIT_SUCCESS
)
return
error
;
...
...
@@ -346,11 +353,14 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
if
(
repo
->
_index
==
NULL
)
{
int
error
;
char
index_path
[
GIT_PATH_MAX
]
;
git_buf
index_path
=
GIT_BUF_INIT
;
git_path_join
(
index_path
,
repo
->
path_repository
,
GIT_INDEX_FILE
);
error
=
git_buf_joinpath
(
&
index_path
,
repo
->
path_repository
,
GIT_INDEX_FILE
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
error
=
git_index_open
(
&
repo
->
_index
,
index_path
);
error
=
git_index_open
(
&
repo
->
_index
,
index_path
.
ptr
);
git_buf_free
(
&
index_path
);
/* done with path */
if
(
error
<
GIT_SUCCESS
)
return
error
;
...
...
@@ -397,7 +407,17 @@ static int retrieve_device(dev_t *device_out, const char *path)
return
GIT_SUCCESS
;
}
static
int
retrieve_ceiling_directories_offset
(
const
char
*
path
,
const
char
*
ceiling_directories
)
/*
* This function returns furthest offset into path where a ceiling dir
* is found, so we can stop processing the path at that point.
*
* Note: converting this to use git_bufs instead of GIT_PATH_MAX buffers on
* the stack could remove directories name limits, but at the cost of doing
* repeated malloc/frees inside the loop below, so let's not do it now.
*/
static
int
retrieve_ceiling_directories_offset
(
const
char
*
path
,
const
char
*
ceiling_directories
)
{
char
buf
[
GIT_PATH_MAX
+
1
];
char
buf2
[
GIT_PATH_MAX
+
1
];
...
...
@@ -416,7 +436,7 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
for
(
sep
=
ceil
;
*
sep
&&
*
sep
!=
GIT_PATH_LIST_SEPARATOR
;
sep
++
);
len
=
sep
-
ceil
;
if
(
len
==
0
||
len
>
GIT_PATH_MAX
||
git_path_root
(
ceil
)
==
-
1
)
if
(
len
==
0
||
len
>
=
(
int
)
sizeof
(
buf
)
||
git_path_root
(
ceil
)
==
-
1
)
continue
;
strncpy
(
buf
,
ceil
,
len
);
...
...
@@ -440,45 +460,43 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
return
max_len
<=
min_len
?
min_len
:
max_len
;
}
static
int
read_gitfile
(
char
*
path_out
,
const
char
*
file_path
,
const
char
*
base_path
)
/*
* Read the contents of `file_path` and set `path_out` to the repo dir that
* it points to. Before calling, set `path_out` to the base directory that
* should be used if the contents of `file_path` are a relative path.
*/
static
int
read_gitfile
(
git_buf
*
path_out
,
const
char
*
file_path
,
const
char
*
base_path
)
{
git_fbuffer
file
;
int
error
;
size_t
end_offset
;
char
*
data
;
assert
(
path_out
&&
file_path
&&
base_path
);
assert
(
path_out
&&
file_path
);
error
=
git_futils_readbuffer
(
&
file
,
file_path
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
data
=
(
char
*
)(
file
.
data
);
if
(
git__prefixcmp
(
data
,
GIT_FILE_CONTENT_PREFIX
))
{
if
(
git__prefixcmp
((
char
*
)
file
.
data
,
GIT_FILE_CONTENT_PREFIX
))
{
git_futils_freebuffer
(
&
file
);
return
git__throw
(
GIT_ENOTFOUND
,
"Invalid gitfile format `%s`"
,
file_path
);
}
end_offset
=
strlen
(
data
)
-
1
;
git_futils_fbuffer_rtrim
(
&
file
)
;
for
(;
data
[
end_offset
]
==
'\r'
||
data
[
end_offset
]
==
'\n'
;
--
end_offset
);
data
[
end_offset
+
1
]
=
'\0'
;
if
(
strlen
(
GIT_FILE_CONTENT_PREFIX
)
==
end_offset
+
1
)
{
if
(
strlen
(
GIT_FILE_CONTENT_PREFIX
)
==
file
.
len
)
{
git_futils_freebuffer
(
&
file
);
return
git__throw
(
GIT_ENOTFOUND
,
"No path in git file `%s`"
,
file_path
);
}
data
=
data
+
strlen
(
GIT_FILE_CONTENT_PREFIX
);
error
=
git_path_prettify_dir
(
path_out
,
data
,
base_path
);
error
=
git_path_prettify_dir
(
path_out
,
((
char
*
)
file
.
data
)
+
strlen
(
GIT_FILE_CONTENT_PREFIX
),
base_path
);
git_futils_freebuffer
(
&
file
);
if
(
error
==
0
&&
git_futils_exists
(
path_out
)
==
0
)
if
(
error
==
GIT_SUCCESS
&&
git_futils_exists
(
path_out
->
ptr
)
==
0
)
return
GIT_SUCCESS
;
return
git__throw
(
GIT_EOBJCORRUPTED
,
"The `.git` file points to a
n inexisting
path"
);
return
git__throw
(
GIT_EOBJCORRUPTED
,
"The `.git` file points to a
nonexistent
path"
);
}
int
git_repository_discover
(
...
...
@@ -489,54 +507,62 @@ int git_repository_discover(
const
char
*
ceiling_dirs
)
{
int
error
,
ceiling_offset
;
char
bare_path
[
GIT_PATH_MAX
]
;
char
normal_path
[
GIT_PATH_MAX
]
;
char
*
found_path
;
git_buf
bare_path
=
GIT_BUF_INIT
;
git_buf
normal_path
=
GIT_BUF_INIT
;
git_buf
*
found_path
=
NULL
;
dev_t
current_device
=
0
;
assert
(
start_path
&&
repository_path
);
error
=
git_path_prettify_dir
(
bare_path
,
start_path
,
NULL
);
*
repository_path
=
'\0'
;
error
=
git_path_prettify_dir
(
&
bare_path
,
start_path
,
NULL
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
goto
cleanup
;
if
(
!
across_fs
)
{
error
=
retrieve_device
(
&
current_device
,
bare_path
);
error
=
retrieve_device
(
&
current_device
,
bare_path
.
ptr
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
goto
cleanup
;
}
ceiling_offset
=
retrieve_ceiling_directories_offset
(
bare_path
,
ceiling_dirs
);
git_path_join
(
normal_path
,
bare_path
,
DOT_GIT
);
ceiling_offset
=
retrieve_ceiling_directories_offset
(
bare_path
.
ptr
,
ceiling_dirs
);
while
(
1
)
{
error
=
git_buf_joinpath
(
&
normal_path
,
bare_path
.
ptr
,
DOT_GIT
);
if
(
error
<
GIT_SUCCESS
)
break
;
/**
* If the `.git` file is regular instead of
* a directory, it should contain the path of the actual git repository
*/
if
(
git_futils_isfile
(
normal_path
)
==
GIT_SUCCESS
)
{
error
=
read_gitfile
(
repository_path
,
normal_path
,
bare_path
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Unable to read git file `%s`"
,
normal_path
);
if
(
git_futils_isfile
(
normal_path
.
ptr
)
==
GIT_SUCCESS
)
{
git_buf
gitfile_path
=
GIT_BUF_INIT
;
error
=
quickcheck_repository_dir
(
repository_path
);
error
=
read_gitfile
(
&
gitfile_path
,
normal_path
.
ptr
,
bare_path
.
ptr
);
if
(
error
<
GIT_SUCCESS
)
return
git__throw
(
GIT_ENOTFOUND
,
"The `.git` file found at '%s' points"
"to an inexisting Git folder"
,
normal_path
);
git__rethrow
(
error
,
"Unable to read git file `%s`"
,
normal_path
.
ptr
);
else
if
((
error
=
quickcheck_repository_dir
(
&
gitfile_path
))
<
GIT_SUCCESS
)
git__throw
(
GIT_ENOTFOUND
,
"The `.git` file found at '%s' points "
"to a nonexistent git folder"
,
normal_path
.
ptr
);
else
{
git_buf_swap
(
&
normal_path
,
&
gitfile_path
);
found_path
=
&
normal_path
;
}
return
GIT_SUCCESS
;
git_buf_free
(
&
gitfile_path
);
break
;
}
/**
* If the `.git` file is a folder, we check inside of it
*/
if
(
git_futils_isdir
(
normal_path
)
==
GIT_SUCCESS
)
{
error
=
quickcheck_repository_dir
(
normal_path
);
if
(
git_futils_isdir
(
normal_path
.
ptr
)
==
GIT_SUCCESS
)
{
error
=
quickcheck_repository_dir
(
&
normal_path
);
if
(
error
==
GIT_SUCCESS
)
{
found_path
=
normal_path
;
found_path
=
&
normal_path
;
break
;
}
}
...
...
@@ -545,44 +571,63 @@ int git_repository_discover(
* Otherwise, the repository may be bare, let's check
* the root anyway
*/
error
=
quickcheck_repository_dir
(
bare_path
);
error
=
quickcheck_repository_dir
(
&
bare_path
);
if
(
error
==
GIT_SUCCESS
)
{
found_path
=
bare_path
;
found_path
=
&
bare_path
;
break
;
}
if
(
git_path_dirname_r
(
normal_path
,
sizeof
(
normal_path
),
bare_path
)
<
GIT_SUCCESS
)
return
git__throw
(
GIT_EOSERR
,
"Failed to dirname '%s'"
,
bare_path
);
/**
* If we didn't find it, walk up the tree
*/
error
=
git_path_dirname_r
(
&
normal_path
,
bare_path
.
ptr
);
if
(
error
<
GIT_SUCCESS
)
{
git__rethrow
(
GIT_EOSERR
,
"Failed to dirname '%s'"
,
bare_path
.
ptr
);
break
;
}
git_buf_swap
(
&
bare_path
,
&
normal_path
);
if
(
!
across_fs
)
{
dev_t
new_device
;
error
=
retrieve_device
(
&
new_device
,
normal_path
);
error
=
retrieve_device
(
&
new_device
,
bare_path
.
ptr
);
if
(
error
<
GIT_SUCCESS
||
current_device
!=
new_device
)
{
return
git__throw
(
GIT_ENOTAREPO
,
error
=
git__throw
(
GIT_ENOTAREPO
,
"Not a git repository (or any parent up to mount parent %s)
\n
"
"Stopping at filesystem boundary."
,
bare_path
);
"Stopping at filesystem boundary."
,
normal_path
.
ptr
);
break
;
}
current_device
=
new_device
;
}
strcpy
(
bare_path
,
normal_path
);
git_path_join
(
normal_path
,
bare_path
,
DOT_GIT
);
// nothing has been found, lets try the parent directory
if
(
bare_path
[
ceiling_offset
]
==
'\0'
)
{
return
git__throw
(
GIT_ENOTAREPO
,
/* nothing has been found, lets try the parent directory
* but stop if we hit one of the ceiling directories
*/
if
(
bare_path
.
ptr
[
ceiling_offset
]
==
'\0'
)
{
error
=
git__throw
(
GIT_ENOTAREPO
,
"Not a git repository (or any of the parent directories): %s"
,
start_path
);
break
;
}
}
if
(
size
<
strlen
(
found_path
)
+
2
)
{
return
git__throw
(
GIT_ESHORTBUFFER
,
"The repository buffer is not long enough to handle the repository path `%s`"
,
found_path
);
assert
(
found_path
||
error
!=
GIT_SUCCESS
);
if
(
found_path
)
{
if
((
error
=
git_path_to_dir
(
found_path
))
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"Could not convert git repository to directory"
);
else
if
(
size
<
(
size_t
)(
found_path
->
size
+
1
))
error
=
git__throw
(
GIT_ESHORTBUFFER
,
"The repository buffer is not long enough to "
"handle the repository path `%s`"
,
found_path
->
ptr
);
else
git_buf_copy_cstr
(
repository_path
,
size
,
found_path
);
}
git_path_join
(
repository_path
,
found_path
,
""
);
return
GIT_SUCCESS
;
cleanup:
git_buf_free
(
&
bare_path
);
git_buf_free
(
&
normal_path
);
return
error
;
}
static
int
repo_init_reinit
(
const
char
*
repository_path
,
int
is_bare
)
...
...
@@ -596,21 +641,23 @@ static int repo_init_reinit(const char *repository_path, int is_bare)
static
int
repo_init_createhead
(
const
char
*
git_dir
)
{
char
ref_path
[
GIT_PATH_MAX
];
int
error
;
git_buf
ref_path
=
GIT_BUF_INIT
;
git_filebuf
ref
=
GIT_FILEBUF_INIT
;
git_path_join
(
ref_path
,
git_dir
,
GIT_HEAD_FILE
);
git_filebuf_open
(
&
ref
,
ref_path
,
0
);
git_filebuf_printf
(
&
ref
,
"ref: refs/heads/master
\n
"
);
if
(
!
(
error
=
git_buf_joinpath
(
&
ref_path
,
git_dir
,
GIT_HEAD_FILE
))
&&
!
(
error
=
git_filebuf_open
(
&
ref
,
ref_path
.
ptr
,
0
))
&&
!
(
error
=
git_filebuf_printf
(
&
ref
,
"ref: refs/heads/master
\n
"
)))
error
=
git_filebuf_commit
(
&
ref
,
GIT_REFS_FILE_MODE
);
return
git_filebuf_commit
(
&
ref
,
GIT_REFS_FILE_MODE
);
git_buf_free
(
&
ref_path
);
return
error
;
}
static
int
repo_init_config
(
const
char
*
git_dir
,
int
is_bare
)
{
char
cfg_path
[
GIT_PATH_MAX
]
;
git_config
*
config
;
git_buf
cfg_path
=
GIT_BUF_INIT
;
git_config
*
config
=
NULL
;
int
error
=
GIT_SUCCESS
;
#define SET_REPO_CONFIG(type, name, val) {\
...
...
@@ -619,29 +666,40 @@ static int repo_init_config(const char *git_dir, int is_bare)
goto cleanup;\
}
git_path_join
(
cfg_path
,
git_dir
,
GIT_CONFIG_FILENAME_INREPO
);
error
=
git_buf_joinpath
(
&
cfg_path
,
git_dir
,
GIT_CONFIG_FILENAME_INREPO
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_config_open_ondisk
(
&
config
,
cfg_path
);
error
=
git_config_open_ondisk
(
&
config
,
cfg_path
.
ptr
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
goto
cleanup
;
SET_REPO_CONFIG
(
bool
,
"core.bare"
,
is_bare
);
SET_REPO_CONFIG
(
int32
,
"core.repositoryformatversion"
,
0
);
/* TODO: what other defaults? */
cleanup:
git_buf_free
(
&
cfg_path
);
git_config_free
(
config
);
return
error
;
}
static
int
repo_init_structure
(
const
char
*
git_dir
,
int
is_bare
)
{
int
error
;
char
temp_path
[
GIT_PATH_MAX
];
if
(
git_futils_mkdir_r
(
git_dir
,
is_bare
?
GIT_BARE_DIR_MODE
:
GIT_DIR_MODE
))
return
git__throw
(
GIT_ERROR
,
"Failed to initialize repository structure. Could not mkdir"
);
int
error
,
i
;
struct
{
const
char
*
dir
;
mode_t
mode
;
}
dirs
[]
=
{
{
GIT_OBJECTS_INFO_DIR
,
GIT_OBJECT_DIR_MODE
},
/* '/objects/info/' */
{
GIT_OBJECTS_PACK_DIR
,
GIT_OBJECT_DIR_MODE
},
/* '/objects/pack/' */
{
GIT_REFS_HEADS_DIR
,
GIT_REFS_DIR_MODE
},
/* '/refs/heads/' */
{
GIT_REFS_TAGS_DIR
,
GIT_REFS_DIR_MODE
},
/* '/refs/tags/' */
{
NULL
,
0
}
};
/* Make the base directory */
error
=
git_futils_mkdir_r
(
git_dir
,
NULL
,
is_bare
?
GIT_BARE_DIR_MODE
:
GIT_DIR_MODE
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to initialize repository structure. Could not mkdir"
);
/* Hides the ".git" directory */
if
(
!
is_bare
)
{
...
...
@@ -652,67 +710,52 @@ static int repo_init_structure(const char *git_dir, int is_bare)
#endif
}
/* Creates the '/objects/info/' directory */
git_path_join
(
temp_path
,
git_dir
,
GIT_OBJECTS_INFO_DIR
);
error
=
git_futils_mkdir_r
(
temp_path
,
GIT_OBJECT_DIR_MODE
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to initialize repository structure"
);
/* Creates the '/objects/pack/' directory */
git_path_join
(
temp_path
,
git_dir
,
GIT_OBJECTS_PACK_DIR
);
error
=
p_mkdir
(
temp_path
,
GIT_OBJECT_DIR_MODE
);
if
(
error
<
GIT_SUCCESS
)
return
git__throw
(
error
,
"Unable to create `%s` folder"
,
temp_path
);
/* Creates the '/refs/heads/' directory */
git_path_join
(
temp_path
,
git_dir
,
GIT_REFS_HEADS_DIR
);
error
=
git_futils_mkdir_r
(
temp_path
,
GIT_REFS_DIR_MODE
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to initialize repository structure"
);
/* Creates the '/refs/tags/' directory */
git_path_join
(
temp_path
,
git_dir
,
GIT_REFS_TAGS_DIR
);
error
=
p_mkdir
(
temp_path
,
GIT_REFS_DIR_MODE
);
if
(
error
<
GIT_SUCCESS
)
return
git__throw
(
error
,
"Unable to create `%s` folder"
,
temp_path
);
/* Make subdirectories as needed */
for
(
i
=
0
;
dirs
[
i
].
dir
!=
NULL
;
++
i
)
{
error
=
git_futils_mkdir_r
(
dirs
[
i
].
dir
,
git_dir
,
dirs
[
i
].
mode
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to create repository folder `%s`"
,
dirs
[
i
].
dir
);
}
/* TODO: what's left? templates? */
return
GIT_SUCCESS
;
return
error
;
}
int
git_repository_init
(
git_repository
**
repo_out
,
const
char
*
path
,
unsigned
is_bare
)
{
int
error
=
GIT_SUCCESS
;
git_repository
*
repo
=
NULL
;
char
repository_path
[
GIT_PATH_MAX
]
;
git_buf
repository_path
=
GIT_BUF_INIT
;
assert
(
repo_out
&&
path
);
git_path_join
(
repository_path
,
path
,
is_bare
?
""
:
GIT_DIR
);
error
=
git_buf_joinpath
(
&
repository_path
,
path
,
is_bare
?
""
:
GIT_DIR
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
if
(
git_futils_isdir
(
repository_path
))
{
if
(
quickcheck_repository_dir
(
repository_path
)
==
GIT_SUCCESS
)
return
repo_init_reinit
(
repository_path
,
is_bare
);
if
(
git_futils_isdir
(
repository_path
.
ptr
)
==
GIT_SUCCESS
)
{
if
(
quickcheck_repository_dir
(
&
repository_path
)
==
GIT_SUCCESS
)
{
error
=
repo_init_reinit
(
repository_path
.
ptr
,
is_bare
);
git_buf_free
(
&
repository_path
);
return
error
;
}
}
error
=
repo_init_structure
(
repository_path
,
is_bare
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
repo_init_config
(
repository_path
,
is_bare
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
!
(
error
=
repo_init_structure
(
repository_path
.
ptr
,
is_bare
))
&&
!
(
error
=
repo_init_config
(
repository_path
.
ptr
,
is_bare
))
&&
!
(
error
=
repo_init_createhead
(
repository_path
.
ptr
)))
error
=
git_repository_open
(
repo_out
,
repository_path
.
ptr
);
else
git_repository_free
(
repo
);
error
=
repo_init_createhead
(
repository_path
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
git_buf_free
(
&
repository_path
);
return
git_repository_open
(
repo_out
,
repository_path
);
if
(
error
!=
GIT_SUCCESS
)
git__rethrow
(
error
,
"Failed to (re)init the repository `%s`"
,
path
);
cleanup:
git_repository_free
(
repo
);
return
git__rethrow
(
error
,
"Failed to (re)init the repository `%s`"
,
path
);
return
error
;
}
int
git_repository_head_detached
(
git_repository
*
repo
)
...
...
src/signature.c
View file @
40e73d6f
...
...
@@ -16,7 +16,9 @@ void git_signature_free(git_signature *sig)
return
;
git__free
(
sig
->
name
);
sig
->
name
=
NULL
;
git__free
(
sig
->
email
);
sig
->
email
=
NULL
;
git__free
(
sig
);
}
...
...
src/status.c
View file @
40e73d6f
...
...
@@ -28,12 +28,10 @@ struct status_entry {
static
struct
status_entry
*
status_entry_new
(
git_vector
*
entries
,
const
char
*
path
)
{
struct
status_entry
*
e
=
git__
malloc
(
sizeof
(
*
e
)
+
strlen
(
path
)
+
1
);
struct
status_entry
*
e
=
git__
calloc
(
sizeof
(
*
e
)
+
strlen
(
path
)
+
1
,
1
);
if
(
e
==
NULL
)
return
NULL
;
memset
(
e
,
0x0
,
sizeof
(
*
e
));
if
(
entries
!=
NULL
)
git_vector_insert
(
entries
,
e
);
...
...
@@ -73,7 +71,7 @@ static void status_entry_update_from_index(struct status_entry *e, git_index *in
status_entry_update_from_index_entry
(
e
,
index_entry
);
}
static
int
status_entry_update_from_workdir
(
struct
status_entry
*
e
,
char
*
full_path
)
static
int
status_entry_update_from_workdir
(
struct
status_entry
*
e
,
c
onst
c
har
*
full_path
)
{
struct
stat
filest
;
...
...
@@ -125,7 +123,7 @@ struct status_st {
git_tree
*
tree
;
int
workdir_path_len
;
char
*
head_tree_relative_path
;
git_buf
head_tree_relative_path
;
int
head_tree_relative_path_len
;
unsigned
int
tree_position
;
unsigned
int
index_position
;
...
...
@@ -155,6 +153,7 @@ static int retrieve_head_tree(git_tree **tree_out, git_repository *repo)
return
git__rethrow
(
error
,
"The tip of HEAD can't be retrieved"
);
git_reference_free
(
resolved_head_ref
);
if
((
error
=
git_commit_tree
(
&
tree
,
head_commit
))
<
GIT_SUCCESS
)
{
error
=
git__rethrow
(
error
,
"The tree of HEAD can't be retrieved"
);
goto
exit
;
...
...
@@ -174,12 +173,15 @@ enum path_type {
GIT_STATUS_PATH_FOLDER
,
};
static
int
dirent_cb
(
void
*
state
,
char
*
full_path
);
static
int
dirent_cb
(
void
*
state
,
git_buf
*
full_path
);
static
int
alphasorted_futils_direach
(
char
*
path
,
size_t
path_sz
,
int
(
*
fn
)(
void
*
,
char
*
),
void
*
arg
);
git_buf
*
path
,
int
(
*
fn
)(
void
*
,
git_buf
*
),
void
*
arg
);
static
int
process_folder
(
struct
status_st
*
st
,
const
git_tree_entry
*
tree_entry
,
char
*
full_path
,
enum
path_type
path_type
)
static
int
process_folder
(
struct
status_st
*
st
,
const
git_tree_entry
*
tree_entry
,
git_buf
*
full_path
,
enum
path_type
path_type
)
{
git_object
*
subtree
=
NULL
;
git_tree
*
pushed_tree
=
NULL
;
...
...
@@ -209,10 +211,9 @@ static int process_folder(struct status_st *st, const git_tree_entry *tree_entry
}
if
(
full_path
!=
NULL
&&
path_type
==
GIT_STATUS_PATH_FOLDER
)
error
=
alphasorted_futils_direach
(
full_path
,
GIT_PATH_MAX
,
dirent_cb
,
st
);
else
{
error
=
alphasorted_futils_direach
(
full_path
,
dirent_cb
,
st
);
else
error
=
dirent_cb
(
st
,
NULL
);
}
if
(
tree_entry_type
==
GIT_OBJ_TREE
)
{
git_object_free
(
subtree
);
...
...
@@ -229,7 +230,7 @@ static int store_if_changed(struct status_st *st, struct status_entry *e)
{
int
error
;
if
((
error
=
status_entry_update_flags
(
e
))
<
GIT_SUCCESS
)
return
git__throw
(
error
,
"Failed to process the file '%s'. It doesn't exist in the workdir, in the HEAD nor in the index"
,
e
->
path
);
return
git__throw
(
error
,
"Failed to process the file '%s'. It doesn't exist in the workdir, in the HEAD nor in the index"
,
e
->
path
);
if
(
e
->
status_flags
==
GIT_STATUS_CURRENT
)
{
git__free
(
e
);
...
...
@@ -243,7 +244,7 @@ static int determine_status(struct status_st *st,
int
in_head
,
int
in_index
,
int
in_workdir
,
const
git_tree_entry
*
tree_entry
,
const
git_index_entry
*
index_entry
,
char
*
full_path
,
git_buf
*
full_path
,
const
char
*
status_path
,
enum
path_type
path_type
)
{
...
...
@@ -273,7 +274,8 @@ static int determine_status(struct status_st *st,
}
if
(
in_workdir
)
if
((
error
=
status_entry_update_from_workdir
(
e
,
full_path
))
<
GIT_SUCCESS
)
if
((
error
=
status_entry_update_from_workdir
(
e
,
full_path
->
ptr
))
<
GIT_SUCCESS
)
return
error
;
/* The callee has already set the error message */
return
store_if_changed
(
st
,
e
);
...
...
@@ -284,7 +286,7 @@ static int determine_status(struct status_st *st,
return
process_folder
(
st
,
tree_entry
,
full_path
,
path_type
);
}
static
int
path_type_from
(
char
*
full_path
,
int
is_dir
)
static
int
path_type_from
(
git_buf
*
full_path
,
int
is_dir
)
{
if
(
full_path
==
NULL
)
return
GIT_STATUS_PATH_NULL
;
...
...
@@ -292,7 +294,7 @@ static int path_type_from(char *full_path, int is_dir)
if
(
!
is_dir
)
return
GIT_STATUS_PATH_FILE
;
if
(
!
git__suffixcmp
(
full_path
,
"/"
DOT_GIT
"/"
))
if
(
!
git__suffixcmp
(
full_path
->
ptr
,
"/"
DOT_GIT
"/"
))
return
GIT_STATUS_PATH_IGNORE
;
return
GIT_STATUS_PATH_FOLDER
;
...
...
@@ -330,7 +332,7 @@ static int compare(const char *left, const char *right)
/* Greatly inspired from JGit IndexTreeWalker */
/* https://github.com/spearce/jgit/blob/ed47e29c777accfa78c6f50685a5df2b8f5b8ff5/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java#L88 */
static
int
dirent_cb
(
void
*
state
,
char
*
a
)
static
int
dirent_cb
(
void
*
state
,
git_buf
*
a
)
{
const
git_tree_entry
*
m
;
const
git_index_entry
*
entry
;
...
...
@@ -346,7 +348,7 @@ static int dirent_cb(void *state, char *a)
if
(
path_type
==
GIT_STATUS_PATH_IGNORE
)
return
GIT_SUCCESS
;
/* Let's skip the ".git" directory */
a_name
=
(
path_type
!=
GIT_STATUS_PATH_NULL
)
?
a
+
st
->
workdir_path_len
:
NULL
;
a_name
=
(
path_type
!=
GIT_STATUS_PATH_NULL
)
?
a
->
ptr
+
st
->
workdir_path_len
:
NULL
;
while
(
1
)
{
if
(
st
->
tree
==
NULL
)
...
...
@@ -360,15 +362,18 @@ static int dirent_cb(void *state, char *a)
return
GIT_SUCCESS
;
if
(
m
!=
NULL
)
{
st
->
head_tree_relative_path
[
st
->
head_tree_relative_path_len
]
=
'\0'
;
git_buf_truncate
(
&
st
->
head_tree_relative_path
,
st
->
head_tree_relative_path_len
);
git_buf_joinpath
(
&
st
->
head_tree_relative_path
,
st
->
head_tree_relative_path
.
ptr
,
m
->
filename
);
/* When the tree entry is a folder, append a forward slash to its name */
if
(
git_tree_entry_type
(
m
)
==
GIT_OBJ_TREE
)
git_path_join_n
(
st
->
head_tree_relative_path
,
3
,
st
->
head_tree_relative_path
,
m
->
filename
,
""
);
else
git_path_join
(
st
->
head_tree_relative_path
,
st
->
head_tree_relative_path
,
m
->
filename
);
m_name
=
st
->
head_tree_relative_path
;
git_path_to_dir
(
&
st
->
head_tree_relative_path
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"An error occured while determining the status of '%s'"
,
a
->
ptr
);
m_name
=
st
->
head_tree_relative_path
.
ptr
;
}
else
m_name
=
NULL
;
...
...
@@ -383,7 +388,7 @@ static int dirent_cb(void *state, char *a)
pi
=
((
cmpmi
>=
0
)
&&
(
cmpai
>=
0
))
?
i_name
:
NULL
;
if
((
error
=
determine_status
(
st
,
pm
!=
NULL
,
pi
!=
NULL
,
pa
!=
NULL
,
m
,
entry
,
a
,
status_path
(
pm
,
pi
,
pa
),
path_type
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"An error occured while determining the status of '%s'"
,
a
);
return
git__rethrow
(
error
,
"An error occured while determining the status of '%s'"
,
a
->
ptr
);
if
((
pa
!=
NULL
)
||
(
path_type
==
GIT_STATUS_PATH_FOLDER
))
return
GIT_SUCCESS
;
...
...
@@ -404,9 +409,8 @@ int git_status_foreach(git_repository *repo, int (*callback)(const char *, unsig
{
git_vector
entries
;
git_index
*
index
=
NULL
;
char
temp_path
[
GIT_PATH_MAX
];
char
tree_path
[
GIT_PATH_MAX
]
=
""
;
struct
status_st
dirent_st
;
git_buf
temp_path
=
GIT_BUF_INIT
;
struct
status_st
dirent_st
=
{
0
};
int
error
=
GIT_SUCCESS
;
unsigned
int
i
;
git_tree
*
tree
;
...
...
@@ -435,23 +439,21 @@ int git_status_foreach(git_repository *repo, int (*callback)(const char *, unsig
dirent_st
.
tree
=
tree
;
dirent_st
.
index
=
index
;
dirent_st
.
vector
=
&
entries
;
dirent_st
.
head_tree_relative_path
=
tree_path
;
git_buf_init
(
&
dirent_st
.
head_tree_relative_path
,
0
)
;
dirent_st
.
head_tree_relative_path_len
=
0
;
dirent_st
.
is_dir
=
1
;
strcpy
(
temp_path
,
workdir
);
if
(
git_futils_isdir
(
temp_path
))
{
if
(
git_futils_isdir
(
workdir
))
{
error
=
git__throw
(
GIT_EINVALIDPATH
,
"Failed to determine status of file '%s'. "
"The given path doesn't lead to a folder"
,
temp_path
);
"The given path doesn't lead to a folder"
,
workdir
);
goto
exit
;
}
git_buf_sets
(
&
temp_path
,
workdir
);
error
=
alphasorted_futils_direach
(
temp_path
,
sizeof
(
temp_path
),
dirent_cb
,
&
dirent_st
);
&
temp_path
,
dirent_cb
,
&
dirent_st
);
if
(
error
<
GIT_SUCCESS
)
error
=
git__rethrow
(
error
,
...
...
@@ -477,6 +479,8 @@ int git_status_foreach(git_repository *repo, int (*callback)(const char *, unsig
}
exit:
git_buf_free
(
&
dirent_st
.
head_tree_relative_path
);
git_buf_free
(
&
temp_path
);
git_vector_free
(
&
entries
);
git_tree_free
(
tree
);
return
error
;
...
...
@@ -521,7 +525,7 @@ int git_status_file(unsigned int *status_flags, git_repository *repo, const char
{
struct
status_entry
*
e
;
git_index
*
index
=
NULL
;
char
temp_path
[
GIT_PATH_MAX
]
;
git_buf
temp_path
=
GIT_BUF_INIT
;
int
error
=
GIT_SUCCESS
;
git_tree
*
tree
=
NULL
;
const
char
*
workdir
;
...
...
@@ -532,60 +536,72 @@ int git_status_file(unsigned int *status_flags, git_repository *repo, const char
return
git__throw
(
GIT_ERROR
,
"Cannot retrieve status on a bare repository"
);
git_path_join
(
temp_path
,
workdir
,
path
);
if
(
git_futils_isdir
(
temp_path
)
==
GIT_SUCCESS
)
if
((
error
=
git_buf_joinpath
(
&
temp_path
,
workdir
,
path
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to determine status of file '%s'"
,
path
);
if
(
git_futils_isdir
(
temp_path
.
ptr
)
==
GIT_SUCCESS
)
{
git_buf_free
(
&
temp_path
);
return
git__throw
(
GIT_EINVALIDPATH
,
"Failed to determine status of file '%s'. "
"Given path leads to a folder, not a file"
,
path
);
}
e
=
status_entry_new
(
NULL
,
path
);
if
(
e
==
NULL
)
if
(
e
==
NULL
)
{
git_buf_free
(
&
temp_path
);
return
GIT_ENOMEM
;
}
/* Find file in Workdir */
if
(
git_futils_exists
(
temp_path
)
==
GIT_SUCCESS
)
{
if
((
error
=
status_entry_update_from_workdir
(
e
,
temp_path
))
<
GIT_SUCCESS
)
goto
exit
;
/* The callee has already set the error message */
if
(
git_futils_exists
(
temp_path
.
ptr
)
==
GIT_SUCCESS
)
{
if
((
error
=
status_entry_update_from_workdir
(
e
,
temp_path
.
ptr
))
<
GIT_SUCCESS
)
goto
cleanup
;
/* The callee has already set the error message */
}
/* Find file in Index */
if
((
error
=
git_repository_index__weakptr
(
&
index
,
repo
))
<
GIT_SUCCESS
)
{
error
=
git__rethrow
(
error
,
git__rethrow
(
error
,
"Failed to determine status of file '%s'."
"Index can't be opened"
,
path
);
goto
exit
;
goto
cleanup
;
}
status_entry_update_from_index
(
e
,
index
);
if
((
error
=
retrieve_head_tree
(
&
tree
,
repo
))
<
GIT_SUCCESS
)
{
error
=
git__rethrow
(
error
,
git__rethrow
(
error
,
"Failed to determine status of file '%s'"
,
path
);
goto
exit
;
goto
cleanup
;
}
/* If the repository is not empty, try and locate the file in HEAD */
if
(
tree
!=
NULL
)
{
strcpy
(
temp_path
,
path
);
if
((
error
=
git_buf_sets
(
&
temp_path
,
path
))
<
GIT_SUCCESS
)
{
git__rethrow
(
error
,
"Failed to determine status of file '%s'"
,
path
);
goto
cleanup
;
}
error
=
recurse_tree_entry
(
tree
,
e
,
temp_path
);
error
=
recurse_tree_entry
(
tree
,
e
,
temp_path
.
ptr
);
if
(
error
<
GIT_SUCCESS
)
{
error
=
git__rethrow
(
error
,
git__rethrow
(
error
,
"Failed to determine status of file '%s'. "
"An error occured while processing the tree"
,
path
);
goto
exit
;
goto
cleanup
;
}
}
/* Determine status */
if
((
error
=
status_entry_update_flags
(
e
))
<
GIT_SUCCESS
)
{
error
=
git__throw
(
error
,
"Nonexistent file"
);
goto
exit
;
git__throw
(
error
,
"Nonexistent file"
);
goto
cleanup
;
}
*
status_flags
=
e
->
status_flags
;
exit:
cleanup:
git_buf_free
(
&
temp_path
);
git_tree_free
(
tree
);
git__free
(
e
);
return
error
;
...
...
@@ -600,37 +616,34 @@ exit:
struct
alphasorted_dirent_info
{
int
is_dir
;
char
path
[
GIT_FLEX_ARRAY
];
/* more */
};
static
struct
alphasorted_dirent_info
*
alphasorted_dirent_info_new
(
const
char
*
path
)
static
struct
alphasorted_dirent_info
*
alphasorted_dirent_info_new
(
const
git_buf
*
path
)
{
int
is_dir
,
size
;
struct
alphasorted_dirent_info
*
di
;
is_dir
=
git_futils_isdir
(
path
)
==
GIT_SUCCESS
?
1
:
0
;
size
=
sizeof
(
*
di
)
+
(
is_dir
?
GIT_PATH_MAX
:
strlen
(
path
))
+
2
;
is_dir
=
git_futils_isdir
(
path
->
ptr
)
==
GIT_SUCCESS
?
1
:
0
;
size
=
sizeof
(
*
di
)
+
path
->
size
+
is_dir
+
1
;
di
=
git__
malloc
(
size
);
di
=
git__
calloc
(
size
,
1
);
if
(
di
==
NULL
)
return
NULL
;
memset
(
di
,
0x0
,
size
);
strcpy
(
di
->
path
,
path
);
git_buf_copy_cstr
(
di
->
path
,
path
->
size
+
1
,
path
);
if
(
is_dir
)
{
di
->
is_dir
=
1
;
/*
* Append a forward slash to the name to force folders
/*
* Append a forward slash to the name to force folders
* to be ordered in a similar way than in a tree
*
* The file "subdir" should appear before the file "subdir.txt"
* The folder "subdir" should appear after the file "subdir.txt"
*/
di
->
path
[
strlen
(
path
)
]
=
'/'
;
di
->
path
[
path
->
size
]
=
'/'
;
}
return
di
;
...
...
@@ -644,7 +657,7 @@ static int alphasorted_dirent_info_cmp(const void *a, const void *b)
return
strcmp
(
stra
->
path
,
strb
->
path
);
}
static
int
alphasorted_dirent_cb
(
void
*
state
,
char
*
full_path
)
static
int
alphasorted_dirent_cb
(
void
*
state
,
git_buf
*
full_path
)
{
struct
alphasorted_dirent_info
*
entry
;
git_vector
*
entry_names
;
...
...
@@ -664,34 +677,42 @@ static int alphasorted_dirent_cb(void *state, char *full_path)
}
static
int
alphasorted_futils_direach
(
char
*
path
,
size_t
path_sz
,
int
(
*
fn
)(
void
*
,
char
*
),
git_buf
*
path
,
int
(
*
fn
)(
void
*
,
git_buf
*
),
void
*
arg
)
{
struct
alphasorted_dirent_info
*
entry
;
git_vector
entry_names
;
unsigned
int
idx
;
int
error
=
GIT_SUCCESS
;
git_buf
entry_path
=
GIT_BUF_INIT
;
if
(
git_vector_init
(
&
entry_names
,
16
,
alphasorted_dirent_info_cmp
)
<
GIT_SUCCESS
)
return
GIT_ENOMEM
;
error
=
git_futils_direach
(
path
,
path_sz
,
alphasorted_dirent_cb
,
&
entry_names
);
error
=
git_futils_direach
(
path
,
alphasorted_dirent_cb
,
&
entry_names
);
git_vector_sort
(
&
entry_names
);
for
(
idx
=
0
;
idx
<
entry_names
.
length
;
++
idx
)
{
entry
=
(
struct
alphasorted_dirent_info
*
)
git_vector_get
(
&
entry_names
,
idx
);
/* We have to walk the entire vector even if there was an error,
* in order to free up memory, but we stop making callbacks after
* an error.
*/
if
(
error
==
GIT_SUCCESS
)
error
=
git_buf_sets
(
&
entry_path
,
entry
->
path
);
if
(
error
==
GIT_SUCCESS
)
{
((
struct
status_st
*
)
arg
)
->
is_dir
=
entry
->
is_dir
;
error
=
fn
(
arg
,
entry
->
path
);
error
=
fn
(
arg
,
&
entry_
path
);
}
git__free
(
entry
);
}
git_buf_free
(
&
entry_path
);
git_vector_free
(
&
entry_names
);
return
error
;
}
src/tag.c
View file @
40e73d6f
...
...
@@ -148,15 +148,22 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
return
GIT_SUCCESS
;
}
static
int
retrieve_tag_reference
(
git_reference
**
tag_reference_out
,
char
*
ref_name_out
,
git_repository
*
repo
,
const
char
*
tag_name
)
static
int
retrieve_tag_reference
(
git_reference
**
tag_reference_out
,
git_buf
*
ref_name_out
,
git_repository
*
repo
,
const
char
*
tag_name
)
{
git_reference
*
tag_ref
;
int
error
;
*
tag_reference_out
=
NULL
;
git_path_join
(
ref_name_out
,
GIT_REFS_TAGS_DIR
,
tag_name
);
error
=
git_reference_lookup
(
&
tag_ref
,
repo
,
ref_name_out
);
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"
);
error
=
git_reference_lookup
(
&
tag_ref
,
repo
,
ref_name_out
->
ptr
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to retrieve tag reference"
);
...
...
@@ -184,9 +191,10 @@ static int write_tag_annotation(
git_buf_putc
(
&
tag
,
'\n'
);
git_buf_puts
(
&
tag
,
message
);
if
(
git_buf_oom
(
&
tag
))
{
error
=
git_buf_lasterror
(
&
tag
);
if
(
error
<
GIT_SUCCESS
)
{
git_buf_free
(
&
tag
);
return
git__
throw
(
GIT_ENOMEM
,
"Not enough memory to build the tag data"
);
return
git__
rethrow
(
error
,
"Not enough memory to build the tag data"
);
}
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
...
...
@@ -215,56 +223,54 @@ static int git_tag_create__internal(
int
create_tag_annotation
)
{
git_reference
*
new_ref
=
NULL
;
char
ref_name
[
GIT_REFNAME_MAX
]
;
git_buf
ref_name
=
GIT_BUF_INIT
;
int
error
,
should_update_ref
=
0
;
const
char
*
errmsg
=
"Failed to create tag"
;
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"
);
error
=
retrieve_tag_reference
(
&
new_ref
,
ref_name
,
repo
,
tag_name
);
switch
(
error
)
{
case
GIT_SUCCESS
:
case
GIT_ENOTFOUND
:
break
;
return
git__throw
(
GIT_EINVALIDARGS
,
"The given target does not belong to this repository"
);
default:
git_reference_free
(
new_ref
);
return
git__rethrow
(
error
,
"Failed to create tag"
);
}
error
=
retrieve_tag_reference
(
&
new_ref
,
&
ref_name
,
repo
,
tag_name
);
if
(
error
<
GIT_SUCCESS
&&
error
!=
GIT_ENOTFOUND
)
goto
cleanup
;
/** 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
));
git_reference_free
(
new_ref
);
return
git__throw
(
GIT_EEXISTS
,
"Tag already exists"
);
error
=
GIT_EEXISTS
;
errmsg
=
"Tag already exists"
;
goto
cleanup
;
}
else
{
should_update_ref
=
1
;
}
}
if
(
create_tag_annotation
)
{
if
((
error
=
write_tag_annotation
(
oid
,
repo
,
tag_name
,
target
,
tagger
,
message
))
<
GIT_SUCCESS
)
{
git_reference_free
(
new_ref
);
return
error
;
}
if
((
error
=
write_tag_annotation
(
oid
,
repo
,
tag_name
,
target
,
tagger
,
message
))
<
GIT_SUCCESS
)
goto
cleanup
;
}
else
git_oid_cpy
(
oid
,
git_object_id
(
target
));
if
(
!
should_update_ref
)
error
=
git_reference_create_oid
(
&
new_ref
,
repo
,
ref_name
,
oid
,
0
);
error
=
git_reference_create_oid
(
&
new_ref
,
repo
,
ref_name
.
ptr
,
oid
,
0
);
else
error
=
git_reference_set_oid
(
new_ref
,
oid
);
cleanup:
git_reference_free
(
new_ref
);
git_buf_free
(
&
ref_name
);
if
(
error
<
GIT_SUCCESS
)
git__rethrow
(
error
,
"%s"
,
errmsg
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to create tag"
)
;
return
error
;
}
int
git_tag_create
(
...
...
@@ -293,12 +299,13 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
{
git_tag
tag
;
int
error
,
should_update_ref
=
0
;
const
char
*
errmsg
=
"Failed to create tag"
;
git_odb
*
odb
;
git_odb_stream
*
stream
;
git_odb_object
*
target_obj
;
git_reference
*
new_ref
=
NULL
;
char
ref_name
[
GIT_REFNAME_MAX
]
;
git_buf
ref_name
=
GIT_BUF_INIT
;
assert
(
oid
&&
buffer
);
...
...
@@ -310,78 +317,77 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
/* validate the buffer */
if
((
error
=
parse_tag_buffer
(
&
tag
,
buffer
,
buffer
+
strlen
(
buffer
)))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to create tag"
)
;
goto
cleanup
;
/* validate the target */
if
((
error
=
git_odb_read
(
&
target_obj
,
odb
,
&
tag
.
target
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to create tag"
)
;
goto
cleanup
;
if
(
tag
.
type
!=
target_obj
->
raw
.
type
)
return
git__throw
(
error
,
"The type for the given target is invalid"
);
if
(
tag
.
type
!=
target_obj
->
raw
.
type
)
{
error
=
GIT_EINVALIDTYPE
;
errmsg
=
"The type for the given target is invalid"
;
goto
cleanup
;
}
git_odb_object_free
(
target_obj
);
error
=
retrieve_tag_reference
(
&
new_ref
,
ref_name
,
repo
,
tag
.
tag_name
);
switch
(
error
)
{
case
GIT_SUCCESS
:
case
GIT_ENOTFOUND
:
break
;
default:
git_reference_free
(
new_ref
);
return
git__rethrow
(
error
,
"Failed to create tag"
);
}
error
=
retrieve_tag_reference
(
&
new_ref
,
&
ref_name
,
repo
,
tag
.
tag_name
);
if
(
error
<
GIT_SUCCESS
&&
error
!=
GIT_ENOTFOUND
)
goto
cleanup
;
/** 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
));
git_reference_free
(
new_ref
);
return
git__throw
(
GIT_EEXISTS
,
"Tag already exists"
);
error
=
GIT_EEXISTS
;
errmsg
=
"Tag already exists"
;
goto
cleanup
;
}
else
{
should_update_ref
=
1
;
}
}
/* write the buffer */
if
((
error
=
git_odb_open_wstream
(
&
stream
,
odb
,
strlen
(
buffer
),
GIT_OBJ_TAG
))
<
GIT_SUCCESS
)
{
git_reference_free
(
new_ref
);
return
git__rethrow
(
error
,
"Failed to create tag"
);
}
if
((
error
=
git_odb_open_wstream
(
&
stream
,
odb
,
strlen
(
buffer
),
GIT_OBJ_TAG
))
<
GIT_SUCCESS
)
goto
cleanup
;
stream
->
write
(
stream
,
buffer
,
strlen
(
buffer
));
error
=
stream
->
finalize_write
(
oid
,
stream
);
stream
->
free
(
stream
);
if
(
error
<
GIT_SUCCESS
)
{
git_reference_free
(
new_ref
);
return
git__rethrow
(
error
,
"Failed to create tag"
);
}
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
if
(
!
should_update_ref
)
error
=
git_reference_create_oid
(
&
new_ref
,
repo
,
ref_name
,
oid
,
0
);
error
=
git_reference_create_oid
(
&
new_ref
,
repo
,
ref_name
.
ptr
,
oid
,
0
);
else
error
=
git_reference_set_oid
(
new_ref
,
oid
);
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
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to create tag"
)
;
return
error
;
}
int
git_tag_delete
(
git_repository
*
repo
,
const
char
*
tag_name
)
{
int
error
;
git_reference
*
tag_ref
;
char
ref_name
[
GIT_REFNAME_MAX
];
git_buf
ref_name
=
GIT_BUF_INIT
;
error
=
retrieve_tag_reference
(
&
tag_ref
,
&
ref_name
,
repo
,
tag_name
);
git_buf_free
(
&
ref_name
);
error
=
retrieve_tag_reference
(
&
tag_ref
,
ref_name
,
repo
,
tag_name
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to delete tag"
);
...
...
src/transports/git.c
View file @
40e73d6f
...
...
@@ -68,7 +68,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
git_buf_put
(
request
,
url
,
delim
-
url
);
git_buf_putc
(
request
,
'\0'
);
return
git_buf_
oom
(
request
);
return
git_buf_
lasterror
(
request
);
}
static
int
send_request
(
GIT_SOCKET
s
,
const
char
*
cmd
,
const
char
*
url
)
...
...
src/transports/http.c
View file @
40e73d6f
...
...
@@ -77,10 +77,7 @@ static int gen_request(git_buf *buf, const char *url, const char *host, const ch
}
git_buf_puts
(
buf
,
"
\r\n
"
);
if
(
git_buf_oom
(
buf
))
return
GIT_ENOMEM
;
return
GIT_SUCCESS
;
return
git_buf_lasterror
(
buf
);
}
static
int
do_connect
(
transport_http
*
t
,
const
char
*
host
,
const
char
*
port
)
...
...
@@ -608,8 +605,9 @@ static int http_download_pack(char **out, git_transport *transport, git_reposito
char
buffer
[
1024
];
gitno_buffer
buf
;
download_pack_cbdata
data
;
git_filebuf
file
;
char
path
[
GIT_PATH_MAX
],
suff
[]
=
"/objects/pack/pack-received
\0
"
;
git_filebuf
file
=
GIT_FILEBUF_INIT
;
git_buf
path
=
GIT_BUF_INIT
;
char
suff
[]
=
"/objects/pack/pack-received
\0
"
;
/*
* This is part of the previous response, so we don't want to
...
...
@@ -625,13 +623,15 @@ static int http_download_pack(char **out, git_transport *transport, git_reposito
gitno_buffer_setup
(
&
buf
,
buffer
,
sizeof
(
buffer
),
t
->
socket
);
git_path_join
(
path
,
repo
->
path_repository
,
suff
);
if
(
memcmp
(
oldbuf
->
ptr
,
"PACK"
,
strlen
(
"PACK"
)))
{
return
git__throw
(
GIT_ERROR
,
"The pack doesn't start with the signature"
);
}
error
=
git_filebuf_open
(
&
file
,
path
,
GIT_FILEBUF_TEMPORARY
);
error
=
git_buf_joinpath
(
&
path
,
repo
->
path_repository
,
suff
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
error
=
git_filebuf_open
(
&
file
,
path
.
ptr
,
GIT_FILEBUF_TEMPORARY
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
...
...
@@ -671,6 +671,7 @@ static int http_download_pack(char **out, git_transport *transport, git_reposito
cleanup:
if
(
error
<
GIT_SUCCESS
)
git_filebuf_cleanup
(
&
file
);
git_buf_free
(
&
path
);
return
error
;
}
...
...
src/tree.c
View file @
40e73d6f
...
...
@@ -577,9 +577,9 @@ 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
)
)
{
if
(
(
error
=
git_buf_lasterror
(
&
tree
))
<
GIT_SUCCESS
)
{
git_buf_free
(
&
tree
);
return
git__
throw
(
GIT_ENOMEM
,
"Not enough memory to build the tree data"
);
return
git__
rethrow
(
error
,
"Not enough memory to build the tree data"
);
}
error
=
git_repository_odb__weakptr
(
&
odb
,
repo
);
...
...
@@ -631,7 +631,7 @@ void git_treebuilder_free(git_treebuilder *bld)
static
int
tree_frompath
(
git_tree
**
parent_out
,
git_tree
*
root
,
const
char
*
treeentry_path
,
git_buf
*
treeentry_path
,
int
offset
)
{
char
*
slash_pos
=
NULL
;
...
...
@@ -639,11 +639,11 @@ static int tree_frompath(
int
error
=
GIT_SUCCESS
;
git_tree
*
subtree
;
if
(
!*
(
treeentry_path
+
offset
))
if
(
!*
(
treeentry_path
->
ptr
+
offset
))
return
git__rethrow
(
GIT_EINVALIDPATH
,
"Invalid relative path to a tree entry '%s'."
,
treeentry_path
);
"Invalid relative path to a tree entry '%s'."
,
treeentry_path
->
ptr
);
slash_pos
=
(
char
*
)
strchr
(
treeentry_path
+
offset
,
'/'
);
slash_pos
=
(
char
*
)
strchr
(
treeentry_path
->
ptr
+
offset
,
'/'
);
if
(
slash_pos
==
NULL
)
return
git_tree_lookup
(
...
...
@@ -652,13 +652,13 @@ static int tree_frompath(
git_object_id
((
const
git_object
*
)
root
)
);
if
(
slash_pos
==
treeentry_path
+
offset
)
if
(
slash_pos
==
treeentry_path
->
ptr
+
offset
)
return
git__rethrow
(
GIT_EINVALIDPATH
,
"Invalid relative path to a tree entry '%s'."
,
treeentry_path
);
"Invalid relative path to a tree entry '%s'."
,
treeentry_path
->
ptr
);
*
slash_pos
=
'\0'
;
entry
=
git_tree_entry_byname
(
root
,
treeentry_path
+
offset
);
entry
=
git_tree_entry_byname
(
root
,
treeentry_path
->
ptr
+
offset
);
if
(
slash_pos
!=
NULL
)
*
slash_pos
=
'/'
;
...
...
@@ -666,7 +666,7 @@ static int tree_frompath(
if
(
entry
==
NULL
)
return
git__rethrow
(
GIT_ENOTFOUND
,
"No tree entry can be found from "
"the given tree and relative path '%s'."
,
treeentry_path
);
"the given tree and relative path '%s'."
,
treeentry_path
->
ptr
);
error
=
git_tree_lookup
(
&
subtree
,
root
->
object
.
repo
,
&
entry
->
oid
);
...
...
@@ -677,7 +677,7 @@ static int tree_frompath(
parent_out
,
subtree
,
treeentry_path
,
slash_pos
-
treeentry_path
+
1
(
slash_pos
-
treeentry_path
->
ptr
)
+
1
);
git_tree_free
(
subtree
);
...
...
@@ -689,72 +689,84 @@ int git_tree_get_subtree(
git_tree
*
root
,
const
char
*
subtree_path
)
{
char
buffer
[
GIT_PATH_MAX
];
int
error
;
git_buf
buffer
=
GIT_BUF_INIT
;
assert
(
subtree
&&
root
&&
subtree_path
);
strncpy
(
buffer
,
subtree_path
,
GIT_PATH_MAX
);
return
tree_frompath
(
subtree
,
root
,
buffer
,
0
);
if
((
error
=
git_buf_sets
(
&
buffer
,
subtree_path
))
==
GIT_SUCCESS
)
error
=
tree_frompath
(
subtree
,
root
,
&
buffer
,
0
);
git_buf_free
(
&
buffer
);
return
error
;
}
static
int
tree_walk_post
(
git_tree
*
tree
,
git_treewalk_cb
callback
,
char
*
root
,
size_t
root_len
,
git_buf
*
path
,
void
*
payload
)
{
int
error
;
int
error
=
GIT_SUCCESS
;
unsigned
int
i
;
for
(
i
=
0
;
i
<
tree
->
entries
.
length
;
++
i
)
{
git_tree_entry
*
entry
=
tree
->
entries
.
contents
[
i
];
root
[
root_len
]
=
'\0'
;
if
(
callback
(
root
,
entry
,
payload
)
<
0
)
if
(
callback
(
path
->
ptr
,
entry
,
payload
)
<
0
)
continue
;
if
(
ENTRY_IS_TREE
(
entry
))
{
git_tree
*
subtree
;
size_t
path_len
=
path
->
size
;
if
((
error
=
git_tree_lookup
(
&
subtree
,
tree
->
object
.
repo
,
&
entry
->
oid
))
<
0
)
return
error
;
break
;
strcpy
(
root
+
root_len
,
entry
->
filename
);
root
[
root_len
+
entry
->
filename_len
]
=
'/'
;
/* append the next entry to the path */
git_buf_puts
(
path
,
entry
->
filename
);
git_buf_putc
(
path
,
'/'
);
if
((
error
=
git_buf_lasterror
(
path
))
<
GIT_SUCCESS
)
break
;
tree_walk_post
(
subtree
,
callback
,
root
,
root_len
+
entry
->
filename_len
+
1
,
payload
);
error
=
tree_walk_post
(
subtree
,
callback
,
path
,
payload
);
if
(
error
<
GIT_SUCCESS
)
break
;
git_buf_truncate
(
path
,
path_len
);
git_tree_free
(
subtree
);
}
}
return
GIT_SUCCESS
;
return
error
;
}
int
git_tree_walk
(
git_tree
*
tree
,
git_treewalk_cb
callback
,
int
mode
,
void
*
payload
)
{
char
root_path
[
GIT_PATH_MAX
];
int
error
=
GIT_SUCCESS
;
git_buf
root_path
=
GIT_BUF_INIT
;
root_path
[
0
]
=
'\0'
;
switch
(
mode
)
{
case
GIT_TREEWALK_POST
:
return
tree_walk_post
(
tree
,
callback
,
root_path
,
0
,
payload
);
error
=
tree_walk_post
(
tree
,
callback
,
&
root_path
,
payload
);
break
;
case
GIT_TREEWALK_PRE
:
return
git__throw
(
GIT_ENOTIMPLEMENTED
,
error
=
git__throw
(
GIT_ENOTIMPLEMENTED
,
"Preorder tree walking is still not implemented"
);
break
;
default:
return
git__throw
(
GIT_EINVALIDARGS
,
error
=
git__throw
(
GIT_EINVALIDARGS
,
"Invalid walking mode for tree walk"
);
break
;
}
git_buf_free
(
&
root_path
);
return
error
;
}
static
int
tree_entry_cmp
(
const
git_tree_entry
*
a
,
const
git_tree_entry
*
b
)
...
...
src/win32/posix_w32.c
View file @
40e73d6f
...
...
@@ -304,32 +304,37 @@ int p_hide_directory__w32(const char *path)
char
*
p_realpath
(
const
char
*
orig_path
,
char
*
buffer
)
{
int
ret
,
alloc
=
0
;
int
ret
;
wchar_t
*
orig_path_w
=
gitwin_to_utf16
(
orig_path
);
wchar_t
*
buffer_w
=
(
wchar_t
*
)
git__malloc
(
GIT_PATH_MAX
*
sizeof
(
wchar_t
));
if
(
buffer
==
NULL
)
{
buffer
=
(
char
*
)
git__malloc
(
GIT_PATH_MAX
);
alloc
=
1
;
}
ret
=
GetFullPathNameW
(
orig_path_w
,
GIT_PATH_MAX
,
buffer_w
,
NULL
);
git__free
(
orig_path_w
);
if
(
!
ret
||
ret
>
GIT_PATH_MAX
)
{
git__free
(
buffer_w
);
if
(
alloc
)
git__free
(
buffer
);
return
NULL
;
buffer
=
NULL
;
goto
done
;
}
if
(
!
WideCharToMultiByte
(
CP_UTF8
,
0
,
buffer_w
,
-
1
,
buffer
,
GIT_PATH_MAX
,
NULL
,
NULL
))
{
git__free
(
buffer_w
);
if
(
alloc
)
git__free
(
buffer
);
if
(
buffer
==
NULL
)
{
int
buffer_sz
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
buffer_w
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
!
buffer_sz
||
!
(
buffer
=
(
char
*
)
git__malloc
(
buffer_sz
))
||
!
WideCharToMultiByte
(
CP_UTF8
,
0
,
buffer_w
,
-
1
,
buffer
,
buffer_sz
,
NULL
,
NULL
))
{
git__free
(
buffer
);
buffer
=
NULL
;
}
}
else
{
if
(
!
WideCharToMultiByte
(
CP_UTF8
,
0
,
buffer_w
,
-
1
,
buffer
,
GIT_PATH_MAX
,
NULL
,
NULL
))
buffer
=
NULL
;
}
done
:
git__free
(
buffer_w
);
git_path_mkposix
(
buffer
);
if
(
buffer
)
git_path_mkposix
(
buffer
);
return
buffer
;
}
...
...
tests-clay/clay.h
View file @
40e73d6f
...
...
@@ -111,6 +111,7 @@ extern void test_core_path__1(void);
extern
void
test_core_path__2
(
void
);
extern
void
test_core_path__5
(
void
);
extern
void
test_core_path__6
(
void
);
extern
void
test_core_path__7
(
void
);
extern
void
test_core_rmdir__delete_recursive
(
void
);
extern
void
test_core_rmdir__fail_to_delete_non_empty_dir
(
void
);
extern
void
test_core_rmdir__initialize
(
void
);
...
...
tests-clay/clay_libgit2.h
View file @
40e73d6f
...
...
@@ -42,4 +42,13 @@ GIT_INLINE(void) cl_assert_strequal_internal(
}
}
/*
* Some utility macros for building long strings
*/
#define REP4(STR) STR STR STR STR
#define REP15(STR) REP4(STR) REP4(STR) REP4(STR) STR STR STR
#define REP16(STR) REP4(REP4(STR))
#define REP256(STR) REP16(REP16(STR))
#define REP1024(STR) REP4(REP256(STR))
#endif
tests-clay/clay_main.c
View file @
40e73d6f
...
...
@@ -171,7 +171,8 @@ static const struct clay_func _clay_cb_core_path[] = {
{
"1"
,
&
test_core_path__1
},
{
"2"
,
&
test_core_path__2
},
{
"5"
,
&
test_core_path__5
},
{
"6"
,
&
test_core_path__6
}
{
"6"
,
&
test_core_path__6
},
{
"7"
,
&
test_core_path__7
}
};
static
const
struct
clay_func
_clay_cb_core_rmdir
[]
=
{
{
"delete_recursive"
,
&
test_core_rmdir__delete_recursive
},
...
...
@@ -357,7 +358,7 @@ static const struct clay_suite _clay_suites[] = {
"core::path"
,
{
NULL
,
NULL
},
{
NULL
,
NULL
},
_clay_cb_core_path
,
5
_clay_cb_core_path
,
6
},
{
"core::rmdir"
,
...
...
@@ -506,7 +507,7 @@ static const struct clay_suite _clay_suites[] = {
};
static
size_t
_clay_suite_count
=
35
;
static
size_t
_clay_callback_count
=
11
7
;
static
size_t
_clay_callback_count
=
11
8
;
/* Core test functions */
static
void
...
...
tests-clay/core/buffer.c
View file @
40e73d6f
...
...
@@ -5,9 +5,6 @@
const
char
*
test_string
=
TESTSTR
;
const
char
*
test_string_x2
=
TESTSTR
TESTSTR
;
#define REP4(STR) STR STR STR STR
#define REP16(STR) REP4(REP4(STR))
#define REP1024(STR) REP16(REP16(REP4(STR)))
#define TESTSTR_4096 REP1024("1234")
#define TESTSTR_8192 REP1024("12341234")
const
char
*
test_4096
=
TESTSTR_4096
;
...
...
@@ -52,7 +49,7 @@ void test_core_buffer__2(void)
{
git_buf
buf
=
GIT_BUF_INIT
;
int
i
;
char
data
[
1
00
];
char
data
[
1
28
];
cl_assert
(
buf
.
size
==
0
);
...
...
@@ -135,22 +132,28 @@ void test_core_buffer__2(void)
git_buf_puts
(
&
buf
,
REP4
(
"0123456789"
));
cl_assert
(
git_buf_oom
(
&
buf
)
==
0
);
git_buf_copy_cstr
(
data
,
100
,
&
buf
);
cl_assert_strequal
(
data
,
REP4
(
"0123456789"
)
);
git_buf_copy_cstr
(
data
,
sizeof
(
data
)
,
&
buf
);
cl_assert_strequal
(
REP4
(
"0123456789"
),
data
);
git_buf_copy_cstr
(
data
,
11
,
&
buf
);
cl_assert_strequal
(
data
,
"0123456789"
);
cl_assert_strequal
(
"0123456789"
,
data
);
git_buf_copy_cstr
(
data
,
3
,
&
buf
);
cl_assert_strequal
(
data
,
"01"
);
cl_assert_strequal
(
"01"
,
data
);
git_buf_copy_cstr
(
data
,
1
,
&
buf
);
cl_assert_strequal
(
data
,
""
);
cl_assert_strequal
(
""
,
data
);
git_buf_copy_cstr
(
data
,
100
,
&
buf
);
cl_assert_strequal
(
data
,
REP4
(
"0123456789"
));
git_buf_copy_cstr
(
data
,
sizeof
(
data
),
&
buf
);
cl_assert_strequal
(
REP4
(
"0123456789"
),
data
);
git_buf_sets
(
&
buf
,
REP256
(
"x"
));
git_buf_copy_cstr
(
data
,
sizeof
(
data
),
&
buf
);
/* since sizeof(data) == 128, only 127 bytes should be copied */
cl_assert_strequal
(
REP4
(
REP16
(
"x"
))
REP16
(
"x"
)
REP16
(
"x"
)
REP16
(
"x"
)
"xxxxxxxxxxxxxxx"
,
data
);
git_buf_free
(
&
buf
);
git_buf_copy_cstr
(
data
,
100
,
&
buf
);
cl_assert_strequal
(
data
,
""
);
git_buf_copy_cstr
(
data
,
sizeof
(
data
)
,
&
buf
);
cl_assert_strequal
(
""
,
data
);
}
/* let's do some tests with larger buffers to push our limits */
...
...
@@ -340,9 +343,10 @@ void test_core_buffer__6(void)
}
/* test
take cstr
data */
/* test
detach/attach
data */
void
test_core_buffer__7
(
void
)
{
const
char
*
fun
=
"This is fun"
;
git_buf
a
=
GIT_BUF_INIT
;
char
*
b
=
NULL
;
...
...
@@ -350,18 +354,36 @@ void test_core_buffer__7(void)
cl_assert
(
git_buf_oom
(
&
a
)
==
0
);
cl_assert_strequal
(
"foo"
,
git_buf_cstr
(
&
a
));
b
=
git_buf_
take_cstr
(
&
a
);
b
=
git_buf_
detach
(
&
a
);
cl_assert_strequal
(
"foo"
,
b
);
cl_assert_strequal
(
""
,
a
.
ptr
);
git__free
(
b
);
b
=
git_buf_
take_cstr
(
&
a
);
b
=
git_buf_
detach
(
&
a
);
cl_assert_strequal
(
NULL
,
b
);
cl_assert_strequal
(
""
,
a
.
ptr
);
git_buf_free
(
&
a
);
b
=
git__strdup
(
fun
);
git_buf_attach
(
&
a
,
b
,
0
);
cl_assert_strequal
(
fun
,
a
.
ptr
);
cl_assert
(
a
.
size
==
(
ssize_t
)
strlen
(
fun
));
cl_assert
(
a
.
asize
==
(
ssize_t
)
strlen
(
fun
)
+
1
);
git_buf_free
(
&
a
);
b
=
git__strdup
(
fun
);
git_buf_attach
(
&
a
,
b
,
strlen
(
fun
)
+
1
);
cl_assert_strequal
(
fun
,
a
.
ptr
);
cl_assert
(
a
.
size
==
(
ssize_t
)
strlen
(
fun
));
cl_assert
(
a
.
asize
==
(
ssize_t
)
strlen
(
fun
)
+
1
);
git_buf_free
(
&
a
);
}
...
...
tests-clay/core/dirent.c
View file @
40e73d6f
...
...
@@ -9,10 +9,10 @@ typedef struct name_data {
typedef
struct
walk_data
{
char
*
sub
;
/* sub-directory name */
name_data
*
names
;
/* name state data */
git_buf
path
;
}
walk_data
;
static
char
path_buffer
[
GIT_PATH_MAX
];
static
char
*
top_dir
=
"dir-walk"
;
static
walk_data
*
state_loc
;
...
...
@@ -27,7 +27,8 @@ static void setup(walk_data *d)
if
(
strcmp
(
d
->
sub
,
"."
)
!=
0
)
cl_must_pass
(
p_mkdir
(
d
->
sub
,
0777
));
strcpy
(
path_buffer
,
d
->
sub
);
cl_git_pass
(
git_buf_sets
(
&
d
->
path
,
d
->
sub
));
state_loc
=
d
;
for
(
n
=
d
->
names
;
n
->
name
;
n
++
)
{
...
...
@@ -53,6 +54,8 @@ static void dirent_cleanup__cb(void *_d)
cl_must_pass
(
p_chdir
(
".."
));
cl_must_pass
(
p_rmdir
(
top_dir
));
git_buf_free
(
&
d
->
path
);
}
static
void
check_counts
(
walk_data
*
d
)
...
...
@@ -64,7 +67,7 @@ static void check_counts(walk_data *d)
}
}
static
int
one_entry
(
void
*
state
,
char
*
path
)
static
int
one_entry
(
void
*
state
,
git_buf
*
path
)
{
walk_data
*
d
=
(
walk_data
*
)
state
;
name_data
*
n
;
...
...
@@ -72,11 +75,11 @@ static int one_entry(void *state, char *path)
if
(
state
!=
state_loc
)
return
GIT_ERROR
;
if
(
path
!=
path_buffer
)
if
(
path
!=
&
d
->
path
)
return
GIT_ERROR
;
for
(
n
=
d
->
names
;
n
->
name
;
n
++
)
{
if
(
!
strcmp
(
n
->
name
,
path
))
{
if
(
!
strcmp
(
n
->
name
,
path
->
ptr
))
{
n
->
count
++
;
return
0
;
}
...
...
@@ -85,7 +88,7 @@ static int one_entry(void *state, char *path)
return
GIT_ERROR
;
}
static
int
dont_call_me
(
void
*
GIT_UNUSED
(
state
),
char
*
GIT_UNUSED
(
path
))
static
int
dont_call_me
(
void
*
GIT_UNUSED
(
state
),
git_buf
*
GIT_UNUSED
(
path
))
{
GIT_UNUSED_ARG
(
state
)
GIT_UNUSED_ARG
(
path
)
...
...
@@ -102,7 +105,8 @@ static name_data dot_names[] = {
};
static
walk_data
dot
=
{
"."
,
dot_names
dot_names
,
GIT_BUF_INIT
};
/* make sure that the '.' folder is not traversed */
...
...
@@ -111,8 +115,7 @@ void test_core_dirent__dont_traverse_dot(void)
cl_set_cleanup
(
&
dirent_cleanup__cb
,
&
dot
);
setup
(
&
dot
);
cl_git_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
cl_git_pass
(
git_futils_direach
(
&
dot
.
path
,
one_entry
,
&
dot
));
...
...
@@ -128,7 +131,8 @@ static name_data sub_names[] = {
};
static
walk_data
sub
=
{
"sub"
,
sub_names
sub_names
,
GIT_BUF_INIT
};
/* traverse a subfolder */
...
...
@@ -137,8 +141,7 @@ void test_core_dirent__traverse_subfolder(void)
cl_set_cleanup
(
&
dirent_cleanup__cb
,
&
sub
);
setup
(
&
sub
);
cl_git_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
cl_git_pass
(
git_futils_direach
(
&
sub
.
path
,
one_entry
,
&
sub
));
...
...
@@ -148,7 +151,8 @@ void test_core_dirent__traverse_subfolder(void)
static
walk_data
sub_slash
=
{
"sub/"
,
sub_names
sub_names
,
GIT_BUF_INIT
};
/* traverse a slash-terminated subfolder */
...
...
@@ -157,8 +161,7 @@ void test_core_dirent__traverse_slash_terminated_folder(void)
cl_set_cleanup
(
&
dirent_cleanup__cb
,
&
sub_slash
);
setup
(
&
sub_slash
);
cl_git_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
cl_git_pass
(
git_futils_direach
(
&
sub_slash
.
path
,
one_entry
,
&
sub_slash
));
...
...
@@ -171,7 +174,8 @@ static name_data empty_names[] = {
};
static
walk_data
empty
=
{
"empty"
,
empty_names
empty_names
,
GIT_BUF_INIT
};
/* make sure that empty folders are not traversed */
...
...
@@ -180,16 +184,14 @@ void test_core_dirent__dont_traverse_empty_folders(void)
cl_set_cleanup
(
&
dirent_cleanup__cb
,
&
empty
);
setup
(
&
empty
);
cl_git_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
cl_git_pass
(
git_futils_direach
(
&
empty
.
path
,
one_entry
,
&
empty
));
check_counts
(
&
empty
);
/* make sure callback not called */
cl_git_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
cl_git_pass
(
git_futils_direach
(
&
empty
.
path
,
dont_call_me
,
&
empty
));
}
...
...
@@ -204,7 +206,8 @@ static name_data odd_names[] = {
};
static
walk_data
odd
=
{
"odd"
,
odd_names
odd_names
,
GIT_BUF_INIT
};
/* make sure that strange looking filenames ('..c') are traversed */
...
...
@@ -213,8 +216,7 @@ void test_core_dirent__traverse_weird_filenames(void)
cl_set_cleanup
(
&
dirent_cleanup__cb
,
&
odd
);
setup
(
&
odd
);
cl_git_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
cl_git_pass
(
git_futils_direach
(
&
odd
.
path
,
one_entry
,
&
odd
));
...
...
tests-clay/core/path.c
View file @
40e73d6f
...
...
@@ -4,26 +4,30 @@
static
void
check_dirname
(
const
char
*
A
,
const
char
*
B
)
{
char
dir
[
64
],
*
dir2
;
git_buf
dir
=
GIT_BUF_INIT
;
char
*
dir2
;
cl_assert
(
git_path_dirname_r
(
dir
,
sizeof
(
dir
),
A
)
>=
0
);
cl_assert
(
strcmp
(
dir
,
B
)
==
0
);
cl_assert
((
dir2
=
git_path_dirname
(
A
))
!=
NULL
);
cl_assert
(
strcmp
(
dir2
,
B
)
==
0
);
cl_assert
(
git_path_dirname_r
(
&
dir
,
A
)
>=
0
);
cl_assert_strequal
(
B
,
dir
.
ptr
);
git_buf_free
(
&
dir
);
cl_assert
((
dir2
=
git_path_dirname
(
A
))
!=
NULL
);
cl_assert_strequal
(
B
,
dir2
);
git__free
(
dir2
);
}
static
void
check_basename
(
const
char
*
A
,
const
char
*
B
)
{
char
base
[
64
],
*
base2
;
git_buf
base
=
GIT_BUF_INIT
;
char
*
base2
;
cl_assert
(
git_path_basename_r
(
base
,
sizeof
(
base
),
A
)
>=
0
);
cl_assert
(
strcmp
(
base
,
B
)
==
0
);
cl_assert
((
base2
=
git_path_basename
(
A
))
!=
NULL
);
cl_assert
(
strcmp
(
base2
,
B
)
==
0
);
cl_assert
(
git_path_basename_r
(
&
base
,
A
)
>=
0
);
cl_assert_strequal
(
B
,
base
.
ptr
);
git_buf_free
(
&
base
);
cl_assert
((
base2
=
git_path_basename
(
A
))
!=
NULL
);
cl_assert_strequal
(
B
,
base2
);
git__free
(
base2
);
}
...
...
@@ -33,16 +37,18 @@ check_topdir(const char *A, const char *B)
const
char
*
dir
;
cl_assert
((
dir
=
git_path_topdir
(
A
))
!=
NULL
);
cl_assert
(
strcmp
(
dir
,
B
)
==
0
);
cl_assert
_strequal
(
B
,
dir
);
}
static
void
check_joinpath
(
const
char
*
path_a
,
const
char
*
path_b
,
const
char
*
expected_path
)
{
char
joined_path
[
GIT_PATH_MAX
]
;
git_buf
joined_path
=
GIT_BUF_INIT
;
git_path_join
(
joined_path
,
path_a
,
path_b
);
cl_assert
(
strcmp
(
joined_path
,
expected_path
)
==
0
);
cl_git_pass
(
git_buf_joinpath
(
&
joined_path
,
path_a
,
path_b
));
cl_assert_strequal
(
expected_path
,
joined_path
.
ptr
);
git_buf_free
(
&
joined_path
);
}
static
void
...
...
@@ -53,17 +59,19 @@ check_joinpath_n(
const
char
*
path_d
,
const
char
*
expected_path
)
{
char
joined_path
[
GIT_PATH_MAX
];
git_buf
joined_path
=
GIT_BUF_INIT
;
cl_git_pass
(
git_buf_join_n
(
&
joined_path
,
'/'
,
4
,
path_a
,
path_b
,
path_c
,
path_d
));
cl_assert_strequal
(
expected_path
,
joined_path
.
ptr
);
git_path_join_n
(
joined_path
,
4
,
path_a
,
path_b
,
path_c
,
path_d
);
cl_assert
(
strcmp
(
joined_path
,
expected_path
)
==
0
);
git_buf_free
(
&
joined_path
);
}
/* get the dirname of a path */
void
test_core_path__0
(
void
)
{
check_dirname
(
NULL
,
"."
);
check_dirname
(
""
,
"."
);
check_dirname
(
"a"
,
"."
);
...
...
@@ -77,6 +85,8 @@ void test_core_path__0(void)
check_dirname
(
"usr/lib/"
,
"usr"
);
check_dirname
(
"usr/lib//"
,
"usr"
);
check_dirname
(
".git/"
,
"."
);
check_dirname
(
REP16
(
"/abc"
),
REP15
(
"/abc"
));
}
/* get the base name of a path */
...
...
@@ -91,6 +101,9 @@ void test_core_path__1(void)
check_basename
(
"/usr/lib"
,
"lib"
);
check_basename
(
"/usr/lib//"
,
"lib"
);
check_basename
(
"usr/lib"
,
"lib"
);
check_basename
(
REP16
(
"/abc"
),
"abc"
);
check_basename
(
REP1024
(
"/abc"
),
"abc"
);
}
/* get the latest component in a path */
...
...
@@ -125,6 +138,20 @@ void test_core_path__5(void)
check_joinpath
(
"/a"
,
"/b/"
,
"/a/b/"
);
check_joinpath
(
"/a/"
,
"b/"
,
"/a/b/"
);
check_joinpath
(
"/a/"
,
"/b/"
,
"/a/b/"
);
check_joinpath
(
"/abcd"
,
"/defg"
,
"/abcd/defg"
);
check_joinpath
(
"/abcd"
,
"/defg/"
,
"/abcd/defg/"
);
check_joinpath
(
"/abcd/"
,
"defg/"
,
"/abcd/defg/"
);
check_joinpath
(
"/abcd/"
,
"/defg/"
,
"/abcd/defg/"
);
check_joinpath
(
"/abcdefgh"
,
"/12345678"
,
"/abcdefgh/12345678"
);
check_joinpath
(
"/abcdefgh"
,
"/12345678/"
,
"/abcdefgh/12345678/"
);
check_joinpath
(
"/abcdefgh/"
,
"12345678/"
,
"/abcdefgh/12345678/"
);
check_joinpath
(
REP1024
(
"aaaa"
),
REP1024
(
"bbbb"
),
REP1024
(
"aaaa"
)
"/"
REP1024
(
"bbbb"
));
check_joinpath
(
REP1024
(
"/aaaa"
),
REP1024
(
"/bbbb"
),
REP1024
(
"/aaaa"
)
REP1024
(
"/bbbb"
));
}
/* properly join path components for more than one path */
...
...
@@ -136,4 +163,74 @@ void test_core_path__6(void)
check_joinpath_n
(
""
,
""
,
""
,
"a"
,
"a"
);
check_joinpath_n
(
"a"
,
"b"
,
""
,
"/c/d/"
,
"a/b/c/d/"
);
check_joinpath_n
(
"a"
,
"b"
,
""
,
"/c/d"
,
"a/b/c/d"
);
check_joinpath_n
(
"abcd"
,
"efgh"
,
"ijkl"
,
"mnop"
,
"abcd/efgh/ijkl/mnop"
);
check_joinpath_n
(
"abcd/"
,
"efgh/"
,
"ijkl/"
,
"mnop/"
,
"abcd/efgh/ijkl/mnop/"
);
check_joinpath_n
(
"/abcd/"
,
"/efgh/"
,
"/ijkl/"
,
"/mnop/"
,
"/abcd/efgh/ijkl/mnop/"
);
check_joinpath_n
(
REP1024
(
"a"
),
REP1024
(
"b"
),
REP1024
(
"c"
),
REP1024
(
"d"
),
REP1024
(
"a"
)
"/"
REP1024
(
"b"
)
"/"
REP1024
(
"c"
)
"/"
REP1024
(
"d"
));
check_joinpath_n
(
REP1024
(
"/a"
),
REP1024
(
"/b"
),
REP1024
(
"/c"
),
REP1024
(
"/d"
),
REP1024
(
"/a"
)
REP1024
(
"/b"
)
REP1024
(
"/c"
)
REP1024
(
"/d"
));
}
static
void
check_path_to_dir
(
const
char
*
path
,
const
char
*
expected
)
{
git_buf
tgt
=
GIT_BUF_INIT
;
git_buf_sets
(
&
tgt
,
path
);
cl_git_pass
(
git_path_to_dir
(
&
tgt
));
cl_assert_strequal
(
expected
,
tgt
.
ptr
);
git_buf_free
(
&
tgt
);
}
static
void
check_string_to_dir
(
const
char
*
path
,
int
maxlen
,
const
char
*
expected
)
{
int
len
=
strlen
(
path
);
char
*
buf
=
git__malloc
(
len
+
2
);
strncpy
(
buf
,
path
,
len
+
2
);
git_path_string_to_dir
(
buf
,
maxlen
);
cl_assert_strequal
(
expected
,
buf
);
git__free
(
buf
);
}
/* convert paths to dirs */
void
test_core_path__7
(
void
)
{
check_path_to_dir
(
""
,
""
);
check_path_to_dir
(
"."
,
"./"
);
check_path_to_dir
(
"./"
,
"./"
);
check_path_to_dir
(
"a/"
,
"a/"
);
check_path_to_dir
(
"ab"
,
"ab/"
);
/* make sure we try just under and just over an expansion that will
* require a realloc
*/
check_path_to_dir
(
"abcdef"
,
"abcdef/"
);
check_path_to_dir
(
"abcdefg"
,
"abcdefg/"
);
check_path_to_dir
(
"abcdefgh"
,
"abcdefgh/"
);
check_path_to_dir
(
"abcdefghi"
,
"abcdefghi/"
);
check_path_to_dir
(
REP1024
(
"abcd"
)
"/"
,
REP1024
(
"abcd"
)
"/"
);
check_path_to_dir
(
REP1024
(
"abcd"
),
REP1024
(
"abcd"
)
"/"
);
check_string_to_dir
(
""
,
1
,
""
);
check_string_to_dir
(
"."
,
1
,
"."
);
check_string_to_dir
(
"."
,
2
,
"./"
);
check_string_to_dir
(
"."
,
3
,
"./"
);
check_string_to_dir
(
"abcd"
,
3
,
"abcd"
);
check_string_to_dir
(
"abcd"
,
4
,
"abcd"
);
check_string_to_dir
(
"abcd"
,
5
,
"abcd/"
);
check_string_to_dir
(
"abcd"
,
6
,
"abcd/"
);
}
tests-clay/core/rmdir.c
View file @
40e73d6f
...
...
@@ -5,24 +5,26 @@ static const char *empty_tmp_dir = "test_gitfo_rmdir_recurs_test";
void
test_core_rmdir__initialize
(
void
)
{
char
path
[
GIT_PATH_MAX
]
;
git_buf
path
=
GIT_BUF_INIT
;
cl_must_pass
(
p_mkdir
(
empty_tmp_dir
,
0777
));
git_path_join
(
path
,
empty_tmp_dir
,
"/one"
);
cl_must_pass
(
p_mkdir
(
path
,
0777
));
cl_git_pass
(
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/one"
)
);
cl_must_pass
(
p_mkdir
(
path
.
ptr
,
0777
));
git_path_join
(
path
,
empty_tmp_dir
,
"/one/two_one"
);
cl_must_pass
(
p_mkdir
(
path
,
0777
));
cl_git_pass
(
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/one/two_one"
)
);
cl_must_pass
(
p_mkdir
(
path
.
ptr
,
0777
));
git_path_join
(
path
,
empty_tmp_dir
,
"/one/two_two"
);
cl_must_pass
(
p_mkdir
(
path
,
0777
));
cl_git_pass
(
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/one/two_two"
)
);
cl_must_pass
(
p_mkdir
(
path
.
ptr
,
0777
));
git_path_join
(
path
,
empty_tmp_dir
,
"/one/two_two/three"
);
cl_must_pass
(
p_mkdir
(
path
,
0777
));
cl_git_pass
(
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/one/two_two/three"
)
);
cl_must_pass
(
p_mkdir
(
path
.
ptr
,
0777
));
git_path_join
(
path
,
empty_tmp_dir
,
"/two"
);
cl_must_pass
(
p_mkdir
(
path
,
0777
));
cl_git_pass
(
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/two"
));
cl_must_pass
(
p_mkdir
(
path
.
ptr
,
0777
));
git_buf_free
(
&
path
);
}
/* make sure empty dir can be deleted recusively */
...
...
@@ -34,17 +36,19 @@ void test_core_rmdir__delete_recursive(void)
/* make sure non-empty dir cannot be deleted recusively */
void
test_core_rmdir__fail_to_delete_non_empty_dir
(
void
)
{
char
file
[
GIT_PATH_MAX
]
;
git_buf
file
=
GIT_BUF_INIT
;
int
fd
;
git_path_join
(
file
,
empty_tmp_dir
,
"/two/file.txt"
);
cl_git_pass
(
git_buf_joinpath
(
&
file
,
empty_tmp_dir
,
"/two/file.txt"
)
);
fd
=
p_creat
(
file
,
0666
);
fd
=
p_creat
(
file
.
ptr
,
0666
);
cl_assert
(
fd
>=
0
);
cl_must_pass
(
p_close
(
fd
));
cl_git_fail
(
git_futils_rmdir_r
(
empty_tmp_dir
,
0
));
cl_must_pass
(
p_unlink
(
file
));
cl_must_pass
(
p_unlink
(
file
.
ptr
));
cl_git_pass
(
git_futils_rmdir_r
(
empty_tmp_dir
,
0
));
git_buf_free
(
&
file
);
}
tests-clay/repo/init.c
View file @
40e73d6f
...
...
@@ -77,17 +77,19 @@ void test_repo_init__bare_repo_noslash(void)
#if 0
BEGIN_TEST(init2, "Initialize and open a bare repo with a relative path escaping out of the current working directory")
char path_repository[GIT_PATH_MAX]
;
git_buf path_repository = GIT_BUF_INIT
;
char current_workdir[GIT_PATH_MAX];
const mode_t mode = 0777;
git_repository* repo;
must_pass(p_getcwd(current_workdir, sizeof(current_workdir)));
git_path_join(path_repository, TEMP_REPO_FOLDER, "a/b/c/"
);
must_pass(git_futils_mkdir_r(path_repository, mode));
must_pass(git_buf_joinpath(&path_repository, TEMP_REPO_FOLDER, "a/b/c/")
);
must_pass(git_futils_mkdir_r(path_repository
.ptr
, mode));
must_pass(chdir(path_repository));
must_pass(chdir(path_repository.ptr));
git_buf_free(&path_repository);
must_pass(git_repository_init(&repo, "../d/e.git", 1));
must_pass(git__suffixcmp(git_repository_path(_repo), "/a/b/d/e.git/"));
...
...
tests-clay/repo/open.c
View file @
40e73d6f
...
...
@@ -26,23 +26,24 @@ void test_repo_open__standard_empty_repo(void)
/* TODO TODO */
#if 0
BEGIN_TEST(open2, "Open a bare repository with a relative path escaping out of the current working directory")
char new_current_workdir[GIT_PATH_MAX];
char current_workdir[GIT_PATH_MAX];
char path_repository[GIT_PATH_MAX];
git_buf new_current_workdir = GIT_BUF_INIT;
git_buf path_repository = GIT_BUF_INIT;
const mode_t mode = 0777;
git_repository* repo;
/* Setup the repository to open */
must_pass(p_getcwd(current_workdir, sizeof(current_workdir)));
strcpy(path_repository, current_workdir
);
git_path_join_n(path_repository, 3, path_repository, TEMP_REPO_FOLDER, "a/d/e.git"
);
must_pass(copydir_recurs(REPOSITORY_FOLDER, path_repository)
);
must_pass(git_buf_join_n(&path_repository, 3, current_workdir, TEMP_REPO_FOLDER, "a/d/e.git")
);
must_pass(copydir_recurs(REPOSITORY_FOLDER, path_repository.ptr)
);
git_buf_free(&path_repository
);
/* Change the current working directory */
git_path_join(new_current_workdir, TEMP_REPO_FOLDER, "a/b/c/");
must_pass(git_futils_mkdir_r(new_current_workdir, mode));
must_pass(chdir(new_current_workdir));
must_pass(git_buf_joinpath(&new_current_workdir, TEMP_REPO_FOLDER, "a/b/c/"));
must_pass(git_futils_mkdir_r(new_current_workdir.ptr, mode));
must_pass(chdir(new_current_workdir.ptr));
git_buf_free(&new_current_workdir);
must_pass(git_repository_open(&repo, "../../d/e.git"));
...
...
tests/t00-core.c
View file @
40e73d6f
...
...
@@ -105,14 +105,15 @@ END_TEST
BEGIN_TEST
(
path0
,
"get the dirname of a path"
)
char
dir
[
64
],
*
dir2
;
git_buf
dir
=
GIT_BUF_INIT
;
char
*
dir2
;
#define DIRNAME_TEST(A, B) { \
must_be_true(git_path_dirname_r(
dir, sizeof(dir)
, A) >= 0); \
must_be_true(strcmp(
dir, B) == 0);
\
must_be_true(git_path_dirname_r(
&dir
, A) >= 0); \
must_be_true(strcmp(
B, dir.ptr) == 0);
\
must_be_true((dir2 = git_path_dirname(A)) != NULL); \
must_be_true(strcmp(dir2, B) == 0); \
git__free(dir2);
\
git__free(dir2); \
}
DIRNAME_TEST
(
NULL
,
"."
);
...
...
@@ -131,16 +132,18 @@ BEGIN_TEST(path0, "get the dirname of a path")
#undef DIRNAME_TEST
git_buf_free
(
&
dir
);
END_TEST
BEGIN_TEST
(
path1
,
"get the base name of a path"
)
char
base
[
64
],
*
base2
;
git_buf
base
=
GIT_BUF_INIT
;
char
*
base2
;
#define BASENAME_TEST(A, B) { \
must_be_true(git_path_basename_r(
base, sizeof(base), A) >= 0);
\
must_be_true(strcmp(
base, B
) == 0); \
must_be_true(git_path_basename_r(
&base, A) >= 0);
\
must_be_true(strcmp(
B, base.ptr
) == 0); \
must_be_true((base2 = git_path_basename(A)) != NULL); \
must_be_true(strcmp(base2, B) == 0); \
must_be_true(strcmp(base2, B) == 0);
\
git__free(base2); \
}
...
...
@@ -156,6 +159,7 @@ BEGIN_TEST(path1, "get the base name of a path")
#undef BASENAME_TEST
git_buf_free
(
&
base
);
END_TEST
BEGIN_TEST
(
path2
,
"get the latest component in a path"
)
...
...
@@ -184,9 +188,13 @@ END_TEST
static
int
ensure_joinpath
(
const
char
*
path_a
,
const
char
*
path_b
,
const
char
*
expected_path
)
{
char
joined_path
[
GIT_PATH_MAX
];
git_path_join
(
joined_path
,
path_a
,
path_b
);
return
strcmp
(
joined_path
,
expected_path
)
==
0
?
GIT_SUCCESS
:
GIT_ERROR
;
int
error
=
GIT_SUCCESS
;
git_buf
joined_path
=
GIT_BUF_INIT
;
if
(
!
(
error
=
git_buf_joinpath
(
&
joined_path
,
path_a
,
path_b
)))
error
=
strcmp
(
joined_path
.
ptr
,
expected_path
)
==
0
?
GIT_SUCCESS
:
GIT_ERROR
;
git_buf_free
(
&
joined_path
);
return
error
;
}
BEGIN_TEST
(
path5
,
"properly join path components"
)
...
...
@@ -206,9 +214,14 @@ END_TEST
static
int
ensure_joinpath_n
(
const
char
*
path_a
,
const
char
*
path_b
,
const
char
*
path_c
,
const
char
*
path_d
,
const
char
*
expected_path
)
{
char
joined_path
[
GIT_PATH_MAX
];
git_path_join_n
(
joined_path
,
4
,
path_a
,
path_b
,
path_c
,
path_d
);
return
strcmp
(
joined_path
,
expected_path
)
==
0
?
GIT_SUCCESS
:
GIT_ERROR
;
int
error
=
GIT_SUCCESS
;
git_buf
joined_path
=
GIT_BUF_INIT
;
if
(
!
(
error
=
git_buf_join_n
(
&
joined_path
,
'/'
,
4
,
path_a
,
path_b
,
path_c
,
path_d
)))
error
=
strcmp
(
joined_path
.
ptr
,
expected_path
)
==
0
?
GIT_SUCCESS
:
GIT_ERROR
;
git_buf_free
(
&
joined_path
);
return
error
;
}
BEGIN_TEST
(
path6
,
"properly join path components for more than one path"
)
...
...
@@ -228,10 +241,10 @@ typedef struct name_data {
typedef
struct
walk_data
{
char
*
sub
;
/* sub-directory name */
name_data
*
names
;
/* name state data */
git_buf
path
;
/* buffer to store path */
}
walk_data
;
static
char
path_buffer
[
GIT_PATH_MAX
];
static
char
*
top_dir
=
"dir-walk"
;
static
walk_data
*
state_loc
;
...
...
@@ -260,7 +273,9 @@ static int setup(walk_data *d)
if
(
p_mkdir
(
d
->
sub
,
0777
)
<
0
)
return
error
(
"can't mkdir(
\"
%s
\"
)"
,
d
->
sub
);
strcpy
(
path_buffer
,
d
->
sub
);
if
(
git_buf_sets
(
&
d
->
path
,
d
->
sub
)
<
0
)
return
error
(
"can't allocate space for
\"
%s
\"
"
,
d
->
sub
);
state_loc
=
d
;
for
(
n
=
d
->
names
;
n
->
name
;
n
++
)
{
...
...
@@ -278,6 +293,8 @@ static int knockdown(walk_data *d)
{
name_data
*
n
;
git_buf_free
(
&
d
->
path
);
for
(
n
=
d
->
names
;
n
->
name
;
n
++
)
{
if
(
p_unlink
(
n
->
name
)
<
0
)
return
error
(
"can't unlink(
\"
%s
\"
)"
,
n
->
name
);
...
...
@@ -308,7 +325,7 @@ static int check_counts(walk_data *d)
return
ret
;
}
static
int
one_entry
(
void
*
state
,
char
*
path
)
static
int
one_entry
(
void
*
state
,
git_buf
*
path
)
{
walk_data
*
d
=
(
walk_data
*
)
state
;
name_data
*
n
;
...
...
@@ -316,11 +333,11 @@ static int one_entry(void *state, char *path)
if
(
state
!=
state_loc
)
return
GIT_ERROR
;
if
(
path
!=
path_buffer
)
if
(
path
!=
&
d
->
path
)
return
GIT_ERROR
;
for
(
n
=
d
->
names
;
n
->
name
;
n
++
)
{
if
(
!
strcmp
(
n
->
name
,
path
))
{
if
(
!
strcmp
(
n
->
name
,
path
->
ptr
))
{
n
->
count
++
;
return
0
;
}
...
...
@@ -338,15 +355,14 @@ static name_data dot_names[] = {
};
static
walk_data
dot
=
{
"."
,
dot_names
dot_names
,
GIT_BUF_INIT
};
BEGIN_TEST
(
dirent0
,
"make sure that the '.' folder is not traversed"
)
must_pass
(
setup
(
&
dot
));
must_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
must_pass
(
git_futils_direach
(
&
dot
.
path
,
one_entry
,
&
dot
));
...
...
@@ -363,15 +379,15 @@ static name_data sub_names[] = {
};
static
walk_data
sub
=
{
"sub"
,
sub_names
sub_names
,
GIT_BUF_INIT
};
BEGIN_TEST
(
dirent1
,
"traverse a subfolder"
)
must_pass
(
setup
(
&
sub
));
must_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
must_pass
(
git_futils_direach
(
&
sub
.
path
,
one_entry
,
&
sub
));
...
...
@@ -382,15 +398,15 @@ END_TEST
static
walk_data
sub_slash
=
{
"sub/"
,
sub_names
sub_names
,
GIT_BUF_INIT
};
BEGIN_TEST
(
dirent2
,
"traverse a slash-terminated subfolder"
)
must_pass
(
setup
(
&
sub_slash
));
must_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
must_pass
(
git_futils_direach
(
&
sub_slash
.
path
,
one_entry
,
&
sub_slash
));
...
...
@@ -404,10 +420,11 @@ static name_data empty_names[] = {
};
static
walk_data
empty
=
{
"empty"
,
empty_names
empty_names
,
GIT_BUF_INIT
};
static
int
dont_call_me
(
void
*
GIT_UNUSED
(
state
),
char
*
GIT_UNUSED
(
path
))
static
int
dont_call_me
(
void
*
GIT_UNUSED
(
state
),
git_buf
*
GIT_UNUSED
(
path
))
{
GIT_UNUSED_ARG
(
state
)
GIT_UNUSED_ARG
(
path
)
...
...
@@ -418,16 +435,14 @@ BEGIN_TEST(dirent3, "make sure that empty folders are not traversed")
must_pass
(
setup
(
&
empty
));
must_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
must_pass
(
git_futils_direach
(
&
empty
.
path
,
one_entry
,
&
empty
));
must_pass
(
check_counts
(
&
empty
));
/* make sure callback not called */
must_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
must_pass
(
git_futils_direach
(
&
empty
.
path
,
dont_call_me
,
&
empty
));
...
...
@@ -444,15 +459,15 @@ static name_data odd_names[] = {
};
static
walk_data
odd
=
{
"odd"
,
odd_names
odd_names
,
GIT_BUF_INIT
};
BEGIN_TEST
(
dirent4
,
"make sure that strange looking filenames ('..c') are traversed"
)
must_pass
(
setup
(
&
odd
));
must_pass
(
git_futils_direach
(
path_buffer
,
sizeof
(
path_buffer
),
must_pass
(
git_futils_direach
(
&
odd
.
path
,
one_entry
,
&
odd
));
...
...
@@ -508,32 +523,24 @@ static char *empty_tmp_dir = "test_gitfo_rmdir_recurs_test";
static
int
setup_empty_tmp_dir
(
void
)
{
char
path
[
GIT_PATH_MAX
];
if
(
p_mkdir
(
empty_tmp_dir
,
0777
))
return
-
1
;
git_path_join
(
path
,
empty_tmp_dir
,
"/one"
);
if
(
p_mkdir
(
path
,
0777
))
return
-
1
;
git_path_join
(
path
,
empty_tmp_dir
,
"/one/two_one"
);
if
(
p_mkdir
(
path
,
0777
))
return
-
1
;
git_path_join
(
path
,
empty_tmp_dir
,
"/one/two_two"
);
if
(
p_mkdir
(
path
,
0777
))
return
-
1
;
git_path_join
(
path
,
empty_tmp_dir
,
"/one/two_two/three"
);
if
(
p_mkdir
(
path
,
0777
))
return
-
1
;
git_path_join
(
path
,
empty_tmp_dir
,
"/two"
);
if
(
p_mkdir
(
path
,
0777
))
return
-
1
;
return
0
;
git_buf
path
=
GIT_BUF_INIT
;
int
error
=
p_mkdir
(
empty_tmp_dir
,
0777
)
||
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/one"
)
||
p_mkdir
(
path
.
ptr
,
0777
)
||
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/one/two_one"
)
||
p_mkdir
(
path
.
ptr
,
0777
)
||
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/one/two_two"
)
||
p_mkdir
(
path
.
ptr
,
0777
)
||
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/one/two_two/three"
)
||
p_mkdir
(
path
.
ptr
,
0777
)
||
git_buf_joinpath
(
&
path
,
empty_tmp_dir
,
"/two"
)
||
p_mkdir
(
path
.
ptr
,
0777
);
git_buf_free
(
&
path
);
return
error
?
-
1
:
0
;
}
BEGIN_TEST
(
rmdir0
,
"make sure empty dir can be deleted recusively"
)
...
...
@@ -542,17 +549,18 @@ BEGIN_TEST(rmdir0, "make sure empty dir can be deleted recusively")
END_TEST
BEGIN_TEST
(
rmdir1
,
"make sure non-empty dir cannot be deleted recusively"
)
char
file
[
GIT_PATH_MAX
]
;
git_buf
file
=
GIT_BUF_INIT
;
int
fd
;
must_pass
(
setup_empty_tmp_dir
());
git_path_join
(
file
,
empty_tmp_dir
,
"/two/file.txt"
);
fd
=
p_creat
(
file
,
0777
);
must_pass
(
git_buf_joinpath
(
&
file
,
empty_tmp_dir
,
"/two/file.txt"
)
);
fd
=
p_creat
(
file
.
ptr
,
0777
);
must_pass
(
fd
);
must_pass
(
p_close
(
fd
));
must_fail
(
git_futils_rmdir_r
(
empty_tmp_dir
,
0
));
must_pass
(
p_unlink
(
file
));
must_pass
(
p_unlink
(
file
.
ptr
));
must_pass
(
git_futils_rmdir_r
(
empty_tmp_dir
,
0
));
git_buf_free
(
&
file
);
END_TEST
BEGIN_TEST
(
strtol0
,
"parsing out 32 integers from a string"
)
...
...
tests/t10-refs.c
View file @
40e73d6f
...
...
@@ -37,7 +37,7 @@ BEGIN_TEST(readtag0, "lookup a loose tag reference")
git_repository
*
repo
;
git_reference
*
reference
;
git_object
*
object
;
char
ref_name_from_tag_name
[
GIT_REFNAME_MAX
]
;
git_buf
ref_name_from_tag_name
=
GIT_BUF_INIT
;
must_pass
(
git_repository_open
(
&
repo
,
REPOSITORY_FOLDER
));
...
...
@@ -51,8 +51,9 @@ BEGIN_TEST(readtag0, "lookup a loose tag reference")
must_be_true
(
git_object_type
(
object
)
==
GIT_OBJ_TAG
);
/* Ensure the name of the tag matches the name of the reference */
git_path_join
(
ref_name_from_tag_name
,
GIT_REFS_TAGS_DIR
,
git_tag_name
((
git_tag
*
)
object
));
must_be_true
(
strcmp
(
ref_name_from_tag_name
,
loose_tag_ref_name
)
==
0
);
must_pass
(
git_buf_joinpath
(
&
ref_name_from_tag_name
,
GIT_REFS_TAGS_DIR
,
git_tag_name
((
git_tag
*
)
object
)));
must_be_true
(
strcmp
(
ref_name_from_tag_name
.
ptr
,
loose_tag_ref_name
)
==
0
);
git_buf_free
(
&
ref_name_from_tag_name
);
git_object_free
(
object
);
git_repository_free
(
repo
);
...
...
@@ -227,7 +228,7 @@ BEGIN_TEST(create0, "create a new symbolic reference")
git_reference
*
new_reference
,
*
looked_up_ref
,
*
resolved_ref
;
git_repository
*
repo
,
*
repo2
;
git_oid
id
;
char
ref_path
[
GIT_PATH_MAX
]
;
git_buf
ref_path
=
GIT_BUF_INIT
;
const
char
*
new_head_tracker
=
"another-head-tracker"
;
...
...
@@ -236,7 +237,8 @@ BEGIN_TEST(create0, "create a new symbolic reference")
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
/* Retrieve the physical path to the symbolic ref for further cleaning */
git_path_join
(
ref_path
,
repo
->
path_repository
,
new_head_tracker
);
must_pass
(
git_buf_joinpath
(
&
ref_path
,
repo
->
path_repository
,
new_head_tracker
));
git_buf_free
(
&
ref_path
);
/* Create and write the new symbolic reference */
must_pass
(
git_reference_create_symbolic
(
&
new_reference
,
repo
,
new_head_tracker
,
current_head_target
,
0
));
...
...
@@ -276,7 +278,7 @@ BEGIN_TEST(create1, "create a deep symbolic reference")
git_reference
*
new_reference
,
*
looked_up_ref
,
*
resolved_ref
;
git_repository
*
repo
;
git_oid
id
;
char
ref_path
[
GIT_PATH_MAX
]
;
git_buf
ref_path
=
GIT_BUF_INIT
;
const
char
*
new_head_tracker
=
"deep/rooted/tracker"
;
...
...
@@ -284,7 +286,7 @@ BEGIN_TEST(create1, "create a deep symbolic reference")
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
git_path_join
(
ref_path
,
repo
->
path_repository
,
new_head_tracker
);
must_pass
(
git_buf_joinpath
(
&
ref_path
,
repo
->
path_repository
,
new_head_tracker
)
);
must_pass
(
git_reference_create_symbolic
(
&
new_reference
,
repo
,
new_head_tracker
,
current_head_target
,
0
));
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
new_head_tracker
));
must_pass
(
git_reference_resolve
(
&
resolved_ref
,
looked_up_ref
));
...
...
@@ -295,13 +297,14 @@ BEGIN_TEST(create1, "create a deep symbolic reference")
git_reference_free
(
new_reference
);
git_reference_free
(
looked_up_ref
);
git_reference_free
(
resolved_ref
);
git_buf_free
(
&
ref_path
);
END_TEST
BEGIN_TEST
(
create2
,
"create a new OID reference"
)
git_reference
*
new_reference
,
*
looked_up_ref
;
git_repository
*
repo
,
*
repo2
;
git_oid
id
;
char
ref_path
[
GIT_PATH_MAX
]
;
git_buf
ref_path
=
GIT_BUF_INIT
;
const
char
*
new_head
=
"refs/heads/new-head"
;
...
...
@@ -310,7 +313,7 @@ BEGIN_TEST(create2, "create a new OID reference")
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
/* Retrieve the physical path to the symbolic ref for further cleaning */
git_path_join
(
ref_path
,
repo
->
path_repository
,
new_head
);
must_pass
(
git_buf_joinpath
(
&
ref_path
,
repo
->
path_repository
,
new_head
)
);
/* Create and write the new object id reference */
must_pass
(
git_reference_create_oid
(
&
new_reference
,
repo
,
new_head
,
&
id
,
0
));
...
...
@@ -337,6 +340,7 @@ BEGIN_TEST(create2, "create a new OID reference")
git_reference_free
(
new_reference
);
git_reference_free
(
looked_up_ref
);
git_buf_free
(
&
ref_path
);
END_TEST
BEGIN_TEST
(
create3
,
"Can not create a new OID reference which targets at an unknown id"
)
...
...
@@ -491,12 +495,13 @@ END_TEST
BEGIN_TEST
(
pack0
,
"create a packfile for an empty folder"
)
git_repository
*
repo
;
char
temp_path
[
GIT_PATH_MAX
]
;
git_buf
temp_path
=
GIT_BUF_INIT
;
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
git_path_join_n
(
temp_path
,
3
,
repo
->
path_repository
,
GIT_REFS_HEADS_DIR
,
"empty_dir"
);
must_pass
(
git_futils_mkdir_r
(
temp_path
,
GIT_REFS_DIR_MODE
));
must_pass
(
git_buf_join_n
(
&
temp_path
,
'/'
,
3
,
repo
->
path_repository
,
GIT_REFS_HEADS_DIR
,
"empty_dir"
));
must_pass
(
git_futils_mkdir_r
(
temp_path
.
ptr
,
NULL
,
GIT_REFS_DIR_MODE
));
git_buf_free
(
&
temp_path
);
must_pass
(
git_reference_packall
(
repo
));
...
...
@@ -506,7 +511,7 @@ END_TEST
BEGIN_TEST
(
pack1
,
"create a packfile from all the loose rn a repo"
)
git_repository
*
repo
;
git_reference
*
reference
;
char
temp_path
[
GIT_PATH_MAX
]
;
git_buf
temp_path
=
GIT_BUF_INIT
;
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
...
...
@@ -524,8 +529,8 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
must_pass
(
git_reference_packall
(
repo
));
/* Ensure the packed-refs file exists */
git_path_join
(
temp_path
,
repo
->
path_repository
,
GIT_PACKEDREFS_FILE
);
must_pass
(
git_futils_exists
(
temp_path
));
must_pass
(
git_buf_joinpath
(
&
temp_path
,
repo
->
path_repository
,
GIT_PACKEDREFS_FILE
)
);
must_pass
(
git_futils_exists
(
temp_path
.
ptr
));
/* Ensure the known ref can still be looked up but is now packed */
must_pass
(
git_reference_lookup
(
&
reference
,
repo
,
loose_tag_ref_name
));
...
...
@@ -533,25 +538,26 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
must_be_true
(
strcmp
(
reference
->
name
,
loose_tag_ref_name
)
==
0
);
/* Ensure the known ref has been removed from the loose folder structure */
git_path_join
(
temp_path
,
repo
->
path_repository
,
loose_tag_ref_name
);
must_pass
(
!
git_futils_exists
(
temp_path
));
must_pass
(
git_buf_joinpath
(
&
temp_path
,
repo
->
path_repository
,
loose_tag_ref_name
)
);
must_pass
(
!
git_futils_exists
(
temp_path
.
ptr
));
close_temp_repo
(
repo
);
git_reference_free
(
reference
);
git_buf_free
(
&
temp_path
);
END_TEST
BEGIN_TEST
(
rename0
,
"rename a loose reference"
)
git_reference
*
looked_up_ref
,
*
another_looked_up_ref
;
git_repository
*
repo
;
char
temp_path
[
GIT_PATH_MAX
]
;
git_buf
temp_path
=
GIT_BUF_INIT
;
const
char
*
new_name
=
"refs/tags/Nemo/knows/refs.kung-fu"
;
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
/* Ensure the ref doesn't exist on the file system */
git_path_join
(
temp_path
,
repo
->
path_repository
,
new_name
);
must_pass
(
!
git_futils_exists
(
temp_path
));
must_pass
(
git_buf_joinpath
(
&
temp_path
,
repo
->
path_repository
,
new_name
)
);
must_pass
(
!
git_futils_exists
(
temp_path
.
ptr
));
/* Retrieval of the reference to rename */
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
loose_tag_ref_name
));
...
...
@@ -575,26 +581,27 @@ BEGIN_TEST(rename0, "rename a loose reference")
must_be_true
(
git_reference_is_packed
(
looked_up_ref
)
==
0
);
/* ...and the ref can be found in the file system */
git_path_join
(
temp_path
,
repo
->
path_repository
,
new_name
);
must_pass
(
git_futils_exists
(
temp_path
));
must_pass
(
git_buf_joinpath
(
&
temp_path
,
repo
->
path_repository
,
new_name
)
);
must_pass
(
git_futils_exists
(
temp_path
.
ptr
));
close_temp_repo
(
repo
);
git_reference_free
(
looked_up_ref
);
git_reference_free
(
another_looked_up_ref
);
git_buf_free
(
&
temp_path
);
END_TEST
BEGIN_TEST
(
rename1
,
"rename a packed reference (should make it loose)"
)
git_reference
*
looked_up_ref
,
*
another_looked_up_ref
;
git_repository
*
repo
;
char
temp_path
[
GIT_PATH_MAX
]
;
git_buf
temp_path
=
GIT_BUF_INIT
;
const
char
*
brand_new_name
=
"refs/heads/brand_new_name"
;
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
/* Ensure the ref doesn't exist on the file system */
git_path_join
(
temp_path
,
repo
->
path_repository
,
packed_head_name
);
must_pass
(
!
git_futils_exists
(
temp_path
));
must_pass
(
git_buf_joinpath
(
&
temp_path
,
repo
->
path_repository
,
packed_head_name
)
);
must_pass
(
!
git_futils_exists
(
temp_path
.
ptr
));
/* The reference can however be looked-up... */
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
packed_head_name
));
...
...
@@ -618,26 +625,27 @@ BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
must_be_true
(
git_reference_is_packed
(
looked_up_ref
)
==
0
);
/* ...and the ref now happily lives in the file system */
git_path_join
(
temp_path
,
repo
->
path_repository
,
brand_new_name
);
must_pass
(
git_futils_exists
(
temp_path
));
must_pass
(
git_buf_joinpath
(
&
temp_path
,
repo
->
path_repository
,
brand_new_name
)
);
must_pass
(
git_futils_exists
(
temp_path
.
ptr
));
close_temp_repo
(
repo
);
git_reference_free
(
looked_up_ref
);
git_reference_free
(
another_looked_up_ref
);
git_buf_free
(
&
temp_path
);
END_TEST
BEGIN_TEST
(
rename2
,
"renaming a packed reference does not pack another reference which happens to be in both loose and pack state"
)
git_reference
*
looked_up_ref
,
*
another_looked_up_ref
;
git_repository
*
repo
;
char
temp_path
[
GIT_PATH_MAX
]
;
git_buf
temp_path
=
GIT_BUF_INIT
;
const
char
*
brand_new_name
=
"refs/heads/brand_new_name"
;
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
/* Ensure the other reference exists on the file system */
git_path_join
(
temp_path
,
repo
->
path_repository
,
packed_test_head_name
);
must_pass
(
git_futils_exists
(
temp_path
));
must_pass
(
git_buf_joinpath
(
&
temp_path
,
repo
->
path_repository
,
packed_test_head_name
)
);
must_pass
(
git_futils_exists
(
temp_path
.
ptr
));
/* Lookup the other reference */
must_pass
(
git_reference_lookup
(
&
another_looked_up_ref
,
repo
,
packed_test_head_name
));
...
...
@@ -662,12 +670,13 @@ BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference
must_be_true
(
git_reference_is_packed
(
another_looked_up_ref
)
==
0
);
/* Ensure the other ref still exists on the file system */
must_pass
(
git_futils_exists
(
temp_path
));
must_pass
(
git_futils_exists
(
temp_path
.
ptr
));
close_temp_repo
(
repo
);
git_reference_free
(
looked_up_ref
);
git_reference_free
(
another_looked_up_ref
);
git_buf_free
(
&
temp_path
);
END_TEST
BEGIN_TEST
(
rename3
,
"can not rename a reference with the name of an existing reference"
)
...
...
@@ -884,13 +893,13 @@ END_TEST
BEGIN_TEST
(
delete0
,
"deleting a ref which is both packed and loose should remove both tracks in the filesystem"
)
git_reference
*
looked_up_ref
,
*
another_looked_up_ref
;
git_repository
*
repo
;
char
temp_path
[
GIT_PATH_MAX
]
;
git_buf
temp_path
=
GIT_BUF_INIT
;
must_pass
(
open_temp_repo
(
&
repo
,
REPOSITORY_FOLDER
));
/* Ensure the loose reference exists on the file system */
git_path_join
(
temp_path
,
repo
->
path_repository
,
packed_test_head_name
);
must_pass
(
git_futils_exists
(
temp_path
));
must_pass
(
git_buf_joinpath
(
&
temp_path
,
repo
->
path_repository
,
packed_test_head_name
)
);
must_pass
(
git_futils_exists
(
temp_path
.
ptr
));
/* Lookup the reference */
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
packed_test_head_name
));
...
...
@@ -905,11 +914,12 @@ BEGIN_TEST(delete0, "deleting a ref which is both packed and loose should remove
must_fail
(
git_reference_lookup
(
&
another_looked_up_ref
,
repo
,
packed_test_head_name
));
/* Ensure the loose reference doesn't exist any longer on the file system */
must_pass
(
!
git_futils_exists
(
temp_path
));
must_pass
(
!
git_futils_exists
(
temp_path
.
ptr
));
close_temp_repo
(
repo
);
git_reference_free
(
another_looked_up_ref
);
git_buf_free
(
&
temp_path
);
END_TEST
BEGIN_TEST
(
delete1
,
"can delete a just packed reference"
)
...
...
tests/t12-repo.c
View file @
40e73d6f
...
...
@@ -87,31 +87,37 @@ static int write_file(const char *path, const char *content)
}
//no check is performed on ceiling_dirs length, so be sure it's long enough
static
int
append_ceiling_dir
(
char
*
ceiling_dirs
,
const
char
*
path
)
static
int
append_ceiling_dir
(
git_buf
*
ceiling_dirs
,
const
char
*
path
)
{
int
len
=
strlen
(
ceiling_dirs
)
;
git_buf
pretty_path
=
GIT_BUF_INIT
;
int
error
;
char
ceiling_separator
[
2
]
=
{
GIT_PATH_LIST_SEPARATOR
,
'\0'
};
error
=
git_path_prettify_dir
(
ceiling_dirs
+
len
+
(
len
?
1
:
0
)
,
path
,
NULL
);
error
=
git_path_prettify_dir
(
&
pretty_path
,
path
,
NULL
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to append ceiling directory."
);
if
(
len
)
ceiling_dirs
[
len
]
=
GIT_PATH_LIST_SEPARATOR
;
if
(
ceiling_dirs
->
size
>
0
)
git_buf_puts
(
ceiling_dirs
,
ceiling_separator
);
git_buf_puts
(
ceiling_dirs
,
pretty_path
.
ptr
);
return
GIT_SUCCESS
;
git_buf_free
(
&
pretty_path
);
return
git_buf_lasterror
(
ceiling_dirs
);
}
BEGIN_TEST
(
discover0
,
"test discover"
)
git_repository
*
repo
;
char
ceiling_dirs
[
GIT_PATH_MAX
*
2
]
=
""
;
git_buf
ceiling_dirs_buf
=
GIT_BUF_INIT
;
const
char
*
ceiling_dirs
;
char
repository_path
[
GIT_PATH_MAX
];
char
sub_repository_path
[
GIT_PATH_MAX
];
char
found_path
[
GIT_PATH_MAX
];
const
mode_t
mode
=
0777
;
git_futils_mkdir_r
(
DISCOVER_FOLDER
,
mode
);
must_pass
(
append_ceiling_dir
(
ceiling_dirs
,
TEMP_REPO_FOLDER
));
git_futils_mkdir_r
(
DISCOVER_FOLDER
,
NULL
,
mode
);
must_pass
(
append_ceiling_dir
(
&
ceiling_dirs_buf
,
TEMP_REPO_FOLDER
));
ceiling_dirs
=
git_buf_cstr
(
&
ceiling_dirs_buf
);
must_be_true
(
git_repository_discover
(
repository_path
,
sizeof
(
repository_path
),
DISCOVER_FOLDER
,
0
,
ceiling_dirs
)
==
GIT_ENOTAREPO
);
...
...
@@ -120,15 +126,15 @@ BEGIN_TEST(discover0, "test discover")
git_repository_free
(
repo
);
must_pass
(
git_repository_init
(
&
repo
,
SUB_REPOSITORY_FOLDER
,
0
));
must_pass
(
git_futils_mkdir_r
(
SUB_REPOSITORY_FOLDER_SUB_SUB_SUB
,
mode
));
must_pass
(
git_futils_mkdir_r
(
SUB_REPOSITORY_FOLDER_SUB_SUB_SUB
,
NULL
,
mode
));
must_pass
(
git_repository_discover
(
sub_repository_path
,
sizeof
(
sub_repository_path
),
SUB_REPOSITORY_FOLDER
,
0
,
ceiling_dirs
));
must_pass
(
git_futils_mkdir_r
(
SUB_REPOSITORY_FOLDER_SUB_SUB_SUB
,
mode
));
must_pass
(
git_futils_mkdir_r
(
SUB_REPOSITORY_FOLDER_SUB_SUB_SUB
,
NULL
,
mode
));
must_pass
(
ensure_repository_discover
(
SUB_REPOSITORY_FOLDER_SUB
,
ceiling_dirs
,
sub_repository_path
));
must_pass
(
ensure_repository_discover
(
SUB_REPOSITORY_FOLDER_SUB_SUB
,
ceiling_dirs
,
sub_repository_path
));
must_pass
(
ensure_repository_discover
(
SUB_REPOSITORY_FOLDER_SUB_SUB_SUB
,
ceiling_dirs
,
sub_repository_path
));
must_pass
(
git_futils_mkdir_r
(
REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB
,
mode
));
must_pass
(
git_futils_mkdir_r
(
REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB
,
NULL
,
mode
));
must_pass
(
write_file
(
REPOSITORY_ALTERNATE_FOLDER
"/"
DOT_GIT
,
"gitdir: ../"
SUB_REPOSITORY_FOLDER_NAME
"/"
DOT_GIT
));
must_pass
(
write_file
(
REPOSITORY_ALTERNATE_FOLDER_SUB_SUB
"/"
DOT_GIT
,
"gitdir: ../../../"
SUB_REPOSITORY_FOLDER_NAME
"/"
DOT_GIT
));
must_pass
(
write_file
(
REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB
"/"
DOT_GIT
,
"gitdir: ../../../../"
));
...
...
@@ -137,20 +143,22 @@ BEGIN_TEST(discover0, "test discover")
must_pass
(
ensure_repository_discover
(
REPOSITORY_ALTERNATE_FOLDER_SUB_SUB
,
ceiling_dirs
,
sub_repository_path
));
must_pass
(
ensure_repository_discover
(
REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB
,
ceiling_dirs
,
repository_path
));
must_pass
(
git_futils_mkdir_r
(
ALTERNATE_MALFORMED_FOLDER1
,
mode
));
must_pass
(
git_futils_mkdir_r
(
ALTERNATE_MALFORMED_FOLDER1
,
NULL
,
mode
));
must_pass
(
write_file
(
ALTERNATE_MALFORMED_FOLDER1
"/"
DOT_GIT
,
"Anything but not gitdir:"
));
must_pass
(
git_futils_mkdir_r
(
ALTERNATE_MALFORMED_FOLDER2
,
mode
));
must_pass
(
git_futils_mkdir_r
(
ALTERNATE_MALFORMED_FOLDER2
,
NULL
,
mode
));
must_pass
(
write_file
(
ALTERNATE_MALFORMED_FOLDER2
"/"
DOT_GIT
,
"gitdir:"
));
must_pass
(
git_futils_mkdir_r
(
ALTERNATE_MALFORMED_FOLDER3
,
mode
));
must_pass
(
git_futils_mkdir_r
(
ALTERNATE_MALFORMED_FOLDER3
,
NULL
,
mode
));
must_pass
(
write_file
(
ALTERNATE_MALFORMED_FOLDER3
"/"
DOT_GIT
,
"gitdir:
\n\n\n
"
));
must_pass
(
git_futils_mkdir_r
(
ALTERNATE_NOT_FOUND_FOLDER
,
mode
));
must_pass
(
git_futils_mkdir_r
(
ALTERNATE_NOT_FOUND_FOLDER
,
NULL
,
mode
));
must_pass
(
write_file
(
ALTERNATE_NOT_FOUND_FOLDER
"/"
DOT_GIT
,
"gitdir: a_repository_that_surely_does_not_exist"
));
must_fail
(
git_repository_discover
(
found_path
,
sizeof
(
found_path
),
ALTERNATE_MALFORMED_FOLDER1
,
0
,
ceiling_dirs
));
must_fail
(
git_repository_discover
(
found_path
,
sizeof
(
found_path
),
ALTERNATE_MALFORMED_FOLDER2
,
0
,
ceiling_dirs
));
must_fail
(
git_repository_discover
(
found_path
,
sizeof
(
found_path
),
ALTERNATE_MALFORMED_FOLDER3
,
0
,
ceiling_dirs
));
must_fail
(
git_repository_discover
(
found_path
,
sizeof
(
found_path
),
ALTERNATE_NOT_FOUND_FOLDER
,
0
,
ceiling_dirs
));
must_pass
(
append_ceiling_dir
(
ceiling_dirs
,
SUB_REPOSITORY_FOLDER
));
must_pass
(
append_ceiling_dir
(
&
ceiling_dirs_buf
,
SUB_REPOSITORY_FOLDER
));
ceiling_dirs
=
git_buf_cstr
(
&
ceiling_dirs_buf
);
//this must pass as ceiling_directories cannot predent the current
//working directory to be checked
must_pass
(
git_repository_discover
(
found_path
,
sizeof
(
found_path
),
SUB_REPOSITORY_FOLDER
,
0
,
ceiling_dirs
));
...
...
@@ -166,6 +174,7 @@ BEGIN_TEST(discover0, "test discover")
must_pass
(
git_futils_rmdir_r
(
TEMP_REPO_FOLDER
,
1
));
git_repository_free
(
repo
);
git_buf_free
(
&
ceiling_dirs_buf
);
END_TEST
BEGIN_SUITE
(
repository
)
...
...
tests/t18-status.c
View file @
40e73d6f
...
...
@@ -392,15 +392,15 @@ END_TEST
BEGIN_TEST
(
singlestatus3
,
"test retrieving status for a new file in an empty repository"
)
git_repository
*
repo
;
unsigned
int
status_flags
;
char
file_path
[
GIT_PATH_MAX
]
;
git_buf
file_path
=
GIT_BUF_INIT
;
char
filename
[]
=
"new_file"
;
int
fd
;
must_pass
(
copydir_recurs
(
EMPTY_REPOSITORY_FOLDER
,
TEST_STD_REPO_FOLDER
));
must_pass
(
remove_placeholders
(
TEST_STD_REPO_FOLDER
,
"dummy-marker.txt"
));
git_path_join
(
file_path
,
TEMP_REPO_FOLDER
,
filename
);
fd
=
p_creat
(
file_path
,
0666
);
must_pass
(
git_buf_joinpath
(
&
file_path
,
TEMP_REPO_FOLDER
,
filename
)
);
fd
=
p_creat
(
file_path
.
ptr
,
0666
);
must_pass
(
fd
);
must_pass
(
p_write
(
fd
,
"new_file
\n
"
,
9
));
must_pass
(
p_close
(
fd
));
...
...
@@ -411,6 +411,7 @@ BEGIN_TEST(singlestatus3, "test retrieving status for a new file in an empty rep
must_be_true
(
status_flags
==
GIT_STATUS_WT_NEW
);
git_repository_free
(
repo
);
git_buf_free
(
&
file_path
);
git_futils_rmdir_r
(
TEMP_REPO_FOLDER
,
1
);
END_TEST
...
...
tests/test_helpers.c
View file @
40e73d6f
...
...
@@ -225,42 +225,49 @@ int cmp_files(const char *a, const char *b)
}
typedef
struct
{
size_t
src_len
,
dst_len
;
char
*
dst
;
git_buf
src
;
size_t
src_baselen
;
git_buf
dst
;
size_t
dst_baselen
;
}
copydir_data
;
static
int
copy_filesystem_element_recurs
(
void
*
_data
,
char
*
source
)
static
int
copy_filesystem_element_recurs
(
void
*
_data
,
git_buf
*
source
)
{
copydir_data
*
data
=
(
copydir_data
*
)
_data
;
data
->
dst
[
data
->
dst_len
]
=
0
;
git_
path_join
(
data
->
dst
,
data
->
dst
,
source
+
data
->
src_
len
);
git_buf_truncate
(
&
data
->
dst
,
data
->
dst_baselen
)
;
git_
buf_joinpath
(
&
data
->
dst
,
data
->
dst
.
ptr
,
source
->
ptr
+
data
->
src_base
len
);
if
(
git_futils_isdir
(
source
)
==
GIT_SUCCESS
)
return
git_futils_direach
(
source
,
GIT_PATH_MAX
,
copy_filesystem_element_recurs
,
_data
);
return
copy_file
(
source
,
data
->
dst
);
if
(
git_futils_isdir
(
source
->
ptr
)
==
GIT_SUCCESS
)
return
git_futils_direach
(
source
,
copy_filesystem_element_recurs
,
_data
);
else
return
copy_file
(
source
->
ptr
,
data
->
dst
.
ptr
);
}
int
copydir_recurs
(
const
char
*
source_directory_path
,
const
char
*
destination_directory_path
)
int
copydir_recurs
(
const
char
*
source_directory_path
,
const
char
*
destination_directory_path
)
{
char
source_buffer
[
GIT_PATH_MAX
];
char
dest_buffer
[
GIT_PATH_MAX
];
copydir_data
data
;
int
error
;
copydir_data
data
=
{
GIT_BUF_INIT
,
0
,
GIT_BUF_INIT
,
0
};
/* Source has to exist, Destination hast to _not_ exist */
if
(
git_futils_isdir
(
source_directory_path
)
!=
GIT_SUCCESS
||
git_futils_isdir
(
destination_directory_path
)
==
GIT_SUCCESS
)
return
GIT_EINVALIDPATH
;
git_path_join
(
source_buffer
,
source_directory_path
,
""
);
data
.
src_len
=
strlen
(
source_buffer
);
git_buf_joinpath
(
&
data
.
src
,
source_directory_path
,
""
);
data
.
src_baselen
=
data
.
src
.
size
;
git_buf_joinpath
(
&
data
.
dst
,
destination_directory_path
,
""
);
data
.
dst_baselen
=
data
.
dst
.
size
;
error
=
copy_filesystem_element_recurs
(
&
data
,
&
data
.
src
);
git_path_join
(
dest_buffer
,
destination_directory_path
,
""
);
data
.
dst
=
dest_buffer
;
data
.
dst_len
=
strlen
(
dest_buffer
);
git_buf_free
(
&
data
.
src
);
git_buf_free
(
&
data
.
dst
);
return
copy_filesystem_element_recurs
(
&
data
,
source_buffer
)
;
return
error
;
}
int
open_temp_repo
(
git_repository
**
repo
,
const
char
*
path
)
...
...
@@ -281,30 +288,51 @@ void close_temp_repo(git_repository *repo)
}
}
static
int
remove_placeholders_recurs
(
void
*
filename
,
char
*
path
)
typedef
struct
{
const
char
*
filename
;
size_t
filename_len
;
}
remove_data
;
static
int
remove_placeholders_recurs
(
void
*
_data
,
git_buf
*
path
)
{
char
passed_filename
[
GIT_PATH_MAX
]
;
char
*
data
=
(
char
*
)
filename
;
remove_data
*
data
=
(
remove_data
*
)
_data
;
size_t
pathlen
;
if
(
!
git_futils_isdir
(
path
))
return
git_futils_direach
(
path
,
GIT_PATH_MAX
,
remove_placeholders_recurs
,
data
);
if
(
!
git_futils_isdir
(
path
->
ptr
))
return
git_futils_direach
(
path
,
remove_placeholders_recurs
,
data
);
if
(
git_path_basename_r
(
passed_filename
,
sizeof
(
passed_filename
),
path
)
<
GIT_SUCCESS
)
return
GIT_EINVALIDPATH
;
pathlen
=
path
->
size
;
if
(
!
strcmp
(
data
,
passed_filename
))
return
p_unlink
(
path
);
if
(
pathlen
<
data
->
filename_len
)
return
GIT_SUCCESS
;
/* if path ends in '/'+filename (or equals filename) */
if
(
!
strcmp
(
data
->
filename
,
path
->
ptr
+
pathlen
-
data
->
filename_len
)
&&
(
pathlen
==
data
->
filename_len
||
path
->
ptr
[
pathlen
-
data
->
filename_len
-
1
]
==
'/'
))
return
p_unlink
(
path
->
ptr
);
return
GIT_SUCCESS
;
}
int
remove_placeholders
(
c
har
*
directory_path
,
char
*
filename
)
int
remove_placeholders
(
c
onst
char
*
directory_path
,
const
char
*
filename
)
{
char
buffer
[
GIT_PATH_MAX
];
int
error
;
remove_data
data
;
git_buf
buffer
=
GIT_BUF_INIT
;
if
(
git_futils_isdir
(
directory_path
))
return
GIT_EINVALIDPATH
;
strcpy
(
buffer
,
directory_path
);
return
remove_placeholders_recurs
(
filename
,
buffer
);
if
((
error
=
git_buf_sets
(
&
buffer
,
directory_path
))
<
GIT_SUCCESS
)
return
error
;
data
.
filename
=
filename
;
data
.
filename_len
=
strlen
(
filename
);
error
=
remove_placeholders_recurs
(
&
data
,
&
buffer
);
git_buf_free
(
&
buffer
);
return
error
;
}
tests/test_helpers.h
View file @
40e73d6f
...
...
@@ -74,7 +74,7 @@ extern int cmp_files(const char *a, const char *b);
extern
int
copy_file
(
const
char
*
source
,
const
char
*
dest
);
extern
int
rmdir_recurs
(
const
char
*
directory_path
);
extern
int
copydir_recurs
(
const
char
*
source_directory_path
,
const
char
*
destination_directory_path
);
extern
int
remove_placeholders
(
c
har
*
directory_path
,
char
*
filename
);
extern
int
remove_placeholders
(
c
onst
char
*
directory_path
,
const
char
*
filename
);
extern
int
open_temp_repo
(
git_repository
**
repo
,
const
char
*
path
);
extern
void
close_temp_repo
(
git_repository
*
repo
);
...
...
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