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
68bbcefd
Commit
68bbcefd
authored
Jul 29, 2022
by
yuangli
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'transportPR' into shallow-clone-network
parents
a491917f
f19ffc8a
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
549 additions
and
31 deletions
+549
-31
include/git2/remote.h
+6
-1
include/git2/repository.h
+11
-0
include/git2/sys/transport.h
+24
-2
src/libgit2/clone.c
+2
-1
src/libgit2/fetch.c
+26
-3
src/libgit2/object.c
+18
-3
src/libgit2/object.h
+6
-0
src/libgit2/remote.h
+1
-0
src/libgit2/repository.c
+155
-0
src/libgit2/repository.h
+3
-0
src/libgit2/transports/local.c
+2
-4
src/libgit2/transports/smart.c
+28
-0
src/libgit2/transports/smart.h
+18
-5
src/libgit2/transports/smart_pkt.c
+83
-7
src/libgit2/transports/smart_protocol.c
+58
-4
src/util/array.h
+3
-1
tests/clone/shallow.c
+105
-0
No files found.
include/git2/remote.h
View file @
68bbcefd
...
...
@@ -754,11 +754,16 @@ typedef struct {
* Extra headers for this fetch operation
*/
git_strarray
custom_headers
;
/**
* Depth of the fetch to perform
*/
int
depth
;
}
git_fetch_options
;
#define GIT_FETCH_OPTIONS_VERSION 1
#define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT, GIT_FETCH_PRUNE_UNSPECIFIED, 1, \
GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT }
GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT
, { NULL }, -1
}
/**
* Initialize git_fetch_options structure
...
...
include/git2/repository.h
View file @
68bbcefd
...
...
@@ -923,6 +923,17 @@ GIT_EXTERN(const char *) git_repository_get_namespace(git_repository *repo);
GIT_EXTERN
(
int
)
git_repository_is_shallow
(
git_repository
*
repo
);
/**
* Determine the shallow roots of the repository
*
* This oidarray is owned by the library. Do not free it.
*
* @param out An array of shallow oids.
* @param repo The repository
* @return 0 on success, an error otherwise.
*/
GIT_EXTERN
(
int
)
git_repository_shallow_roots
(
git_oidarray
*
out
,
git_repository
*
repo
);
/**
* Retrieve the configured identity to use for reflogs
*
* The memory is owned by the repository and must not be freed by the
...
...
include/git2/sys/transport.h
View file @
68bbcefd
...
...
@@ -25,6 +25,24 @@
GIT_BEGIN_DECL
/**
* Flags to pass to transport
*
* Currently unused.
*/
typedef
enum
{
GIT_TRANSPORTFLAGS_NONE
=
0
,
}
git_transport_flags_t
;
typedef
struct
git_shallowarray
git_shallowarray
;
typedef
struct
{
const
git_remote_head
*
const
*
refs
;
size_t
count
;
git_shallowarray
*
shallow_roots
;
int
depth
;
}
git_fetch_negotiation
;
struct
git_transport
{
unsigned
int
version
;
/**< The struct version */
...
...
@@ -84,8 +102,7 @@ struct git_transport {
int
GIT_CALLBACK
(
negotiate_fetch
)(
git_transport
*
transport
,
git_repository
*
repo
,
const
git_remote_head
*
const
*
refs
,
size_t
count
);
const
git_fetch_negotiation
*
fetch_data
);
/**
* Start downloading the packfile from the remote repository.
...
...
@@ -430,6 +447,11 @@ GIT_EXTERN(int) git_smart_subtransport_ssh(
git_transport
*
owner
,
void
*
param
);
GIT_EXTERN
(
size_t
)
git_shallowarray_count
(
git_shallowarray
*
array
);
GIT_EXTERN
(
const
git_oid
*
)
git_shallowarray_get
(
git_shallowarray
*
array
,
size_t
idx
);
GIT_EXTERN
(
int
)
git_shallowarray_add
(
git_shallowarray
*
array
,
git_oid
*
oid
);
GIT_EXTERN
(
int
)
git_shallowarray_remove
(
git_shallowarray
*
array
,
git_oid
*
oid
);
/** @} */
GIT_END_DECL
#endif
src/libgit2/clone.c
View file @
68bbcefd
...
...
@@ -409,8 +409,9 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch
memcpy
(
&
fetch_opts
,
opts
,
sizeof
(
git_fetch_options
));
fetch_opts
.
update_fetchhead
=
0
;
if
(
fetch_opts
.
depth
==
-
1
)
fetch_opts
.
download_tags
=
GIT_REMOTE_DOWNLOAD_TAGS_ALL
;
git_
str
_printf
(
&
reflog_message
,
"clone: from %s"
,
git_remote_url
(
remote
));
git_
buf
_printf
(
&
reflog_message
,
"clone: from %s"
,
git_remote_url
(
remote
));
if
((
error
=
git_remote_fetch
(
remote
,
NULL
,
&
fetch_opts
,
git_str_cstr
(
&
reflog_message
)))
!=
0
)
goto
cleanup
;
...
...
src/libgit2/fetch.c
View file @
68bbcefd
...
...
@@ -20,6 +20,7 @@
#include "netops.h"
#include "repository.h"
#include "refs.h"
#include "transports/smart.h"
static
int
maybe_want
(
git_remote
*
remote
,
git_remote_head
*
head
,
git_refspec
*
tagspec
,
git_remote_autotag_option_t
tagopt
)
{
...
...
@@ -184,20 +185,42 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
* Now we have everything set up so we can start tell the
* server what we want and what we have.
*/
remote
->
nego
.
refs
=
(
const
git_remote_head
*
const
*
)
remote
->
refs
.
contents
;
remote
->
nego
.
count
=
remote
->
refs
.
length
;
remote
->
nego
.
depth
=
opts
->
depth
;
remote
->
nego
.
shallow_roots
=
git__malloc
(
sizeof
(
git_shallowarray
));
git_array_init
(
remote
->
nego
.
shallow_roots
->
array
);
git_repository__shallow_roots
(
&
remote
->
nego
.
shallow_roots
->
array
,
remote
->
repo
);
return
t
->
negotiate_fetch
(
t
,
remote
->
repo
,
(
const
git_remote_head
*
const
*
)
remote
->
refs
.
contents
,
remote
->
refs
.
length
);
&
remote
->
nego
);
}
int
git_fetch_download_pack
(
git_remote
*
remote
)
{
git_transport
*
t
=
remote
->
transport
;
git_indexer_progress_cb
progress
=
NULL
;
void
*
payload
=
NULL
;
int
error
;
if
(
!
remote
->
need_pack
)
return
0
;
return
t
->
download_pack
(
t
,
remote
->
repo
,
&
remote
->
stats
);
if
(
callbacks
)
{
progress
=
callbacks
->
transfer_progress
;
payload
=
callbacks
->
payload
;
}
if
((
error
=
t
->
download_pack
(
t
,
remote
->
repo
,
&
remote
->
stats
,
progress
,
payload
))
<
0
)
return
error
;
if
((
error
=
git_repository__shallow_roots_write
(
remote
->
repo
,
remote
->
nego
.
shallow_roots
->
array
))
<
0
)
return
error
;
return
0
;
}
int
git_fetch_options_init
(
git_fetch_options
*
opts
,
unsigned
int
version
)
...
...
src/libgit2/object.c
View file @
68bbcefd
...
...
@@ -104,15 +104,13 @@ int git_object__from_raw(
return
0
;
}
int
git_object__from_odb_object
(
int
git_object__
init_
from_odb_object
(
git_object
**
object_out
,
git_repository
*
repo
,
git_odb_object
*
odb_obj
,
git_object_t
type
)
{
int
error
;
size_t
object_size
;
git_object_def
*
def
;
git_object
*
object
=
NULL
;
GIT_ASSERT_ARG
(
object_out
);
...
...
@@ -139,6 +137,23 @@ int git_object__from_odb_object(
object
->
cached
.
size
=
odb_obj
->
cached
.
size
;
object
->
repo
=
repo
;
*
object_out
=
object
;
return
0
;
}
int
git_object__from_odb_object
(
git_object
**
object_out
,
git_repository
*
repo
,
git_odb_object
*
odb_obj
,
git_object_t
type
)
{
int
error
;
git_object_def
*
def
;
git_object
*
object
=
NULL
;
if
((
error
=
git_object__init_from_odb_object
(
&
object
,
repo
,
odb_obj
,
type
))
<
0
)
return
error
;
/* Parse raw object data */
def
=
&
git_objects_table
[
odb_obj
->
cached
.
type
];
GIT_ASSERT
(
def
->
free
&&
def
->
parse
);
...
...
src/libgit2/object.h
View file @
68bbcefd
...
...
@@ -35,6 +35,12 @@ int git_object__from_raw(
size_t
size
,
git_object_t
type
);
int
git_object__init_from_odb_object
(
git_object
**
object_out
,
git_repository
*
repo
,
git_odb_object
*
odb_obj
,
git_object_t
type
);
int
git_object__from_odb_object
(
git_object
**
object_out
,
git_repository
*
repo
,
...
...
src/libgit2/remote.h
View file @
68bbcefd
...
...
@@ -37,6 +37,7 @@ struct git_remote {
git_remote_autotag_option_t
download_tags
;
int
prune_refs
;
int
passed_refspecs
;
git_fetch_negotiation
nego
;
};
int
git_remote__urlfordirection
(
git_str
*
url_out
,
struct
git_remote
*
remote
,
int
direction
,
const
git_remote_callbacks
*
callbacks
);
...
...
src/libgit2/repository.c
View file @
68bbcefd
...
...
@@ -3340,6 +3340,161 @@ int git_repository_state_cleanup(git_repository *repo)
return
git_repository__cleanup_files
(
repo
,
state_files
,
ARRAY_SIZE
(
state_files
));
}
// int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo)
// {
// git_buf path = GIT_BUF_INIT;
// git_buf contents = GIT_BUF_INIT;
// int error, updated, line_num = 1;
// char *line;
// chror = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_grafts->git_grafts->path_checksum, &updated);
// git_buf_dispose(&path);
// if (error < 0 && error != GIT_ENOTFOUND)
// return error;
// /* cancel out GIT_ENOTFOUND */
// git_error_clear();
// error = 0;
// if (!updated) {
// out = repo->shallow_grafts;
// goto cleanup;
// }
// git_array_clear(repo->shallow_grafts);
// buffer = contents.ptr;
// while ((line = git__strsep(&buffer, "\n")) != NULL) {
// git_oid *oid = git_array_alloc(repo->shallow_grafts);
// error = git_oid_fromstr(oid, line);
// if (error < 0) {
// git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num);
// git_array_clear(repo->shallow_grafts);
// error = -1;
// goto cleanup;
// }
// ++line_num;
// }
// if (*buffer) {
// git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num);
// git_array_clear(repo->shallow_grafts);
// error = -1;
// goto cleanup;
// }
// *out = repo->shallow_grafts;
// cleanup:
// git_buf_dispose(&contents);
// return error;ar *buffer;
// assert(out && repo);
// if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0)
// return error;
// //error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_checksum, &updated);
// error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_grafts->git_grafts->path_checksum, &updated);
// git_buf_dispose(&path);
// if (error < 0 && error != GIT_ENOTFOUND)
// return error;
// /* cancel out GIT_ENOTFOUND */
// git_error_clear();
// error = 0;
// if (!updated) {
// out = repo->shallow_grafts;
// goto cleanup;
// }
// git_array_clear(repo->shallow_grafts);
// buffer = contents.ptr;
// while ((line = git__strsep(&buffer, "\n")) != NULL) {
// git_oid *oid = git_array_alloc(repo->shallow_grafts);
// error = git_oid_fromstr(oid, line);
// if (error < 0) {
// git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num);
// git_array_clear(repo->shallow_grafts);
// error = -1;
// goto cleanup;
// }
// ++line_num;
// }
// if (*buffer) {
// git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num);
// git_array_clear(repo->shallow_grafts);
// error = -1;
// goto cleanup;
// }
// *out = repo->shallow_grafts;
// cleanup:
// git_buf_dispose(&contents);
// return error;
// }
int
git_repository__shallow_roots
(
git_array_oid_t
*
out
,
git_repository
*
repo
)
{
int
error
=
0
;
if
(
!
repo
->
shallow_grafts
)
load_grafts
(
repo
);
git_grafts_refresh
(
repo
->
shallow_grafts
);
return
git_grafts_get_oids
(
out
,
repo
->
shallow_grafts
);
}
int
git_repository__shallow_roots_write
(
git_repository
*
repo
,
git_array_oid_t
roots
)
{
git_filebuf
file
=
GIT_FILEBUF_INIT
;
git_buf
path
=
GIT_BUF_INIT
;
int
error
=
0
;
size_t
idx
;
git_oid
*
oid
;
assert
(
repo
);
if
((
error
=
git_buf_joinpath
(
&
path
,
repo
->
gitdir
,
"shallow"
))
<
0
)
return
error
;
if
((
error
=
git_filebuf_open
(
&
file
,
git_buf_cstr
(
&
path
),
GIT_FILEBUF_HASH_CONTENTS
,
0666
))
<
0
)
return
error
;
git_array_foreach
(
roots
,
idx
,
oid
)
{
git_filebuf_write
(
&
file
,
git_oid_tostr_s
(
oid
),
GIT_OID_HEXSZ
);
git_filebuf_write
(
&
file
,
"
\n
"
,
1
);
}
git_filebuf_commit
(
&
file
);
if
(
load_grafts
(
repo
)
<
0
)
return
-
1
;
return
0
;
}
int
git_repository_shallow_roots
(
git_oidarray
*
out
,
git_repository
*
repo
)
{
int
ret
;
git_array_oid_t
array
=
GIT_ARRAY_INIT
;
assert
(
out
);
ret
=
git_repository__shallow_roots
(
&
array
,
repo
);
git_oidarray__from_array
(
out
,
&
array
);
return
ret
;
}
int
git_repository_is_shallow
(
git_repository
*
repo
)
{
git_str
path
=
GIT_STR_INIT
;
...
...
src/libgit2/repository.h
View file @
68bbcefd
...
...
@@ -244,6 +244,9 @@ extern size_t git_repository__reserved_names_posix_len;
bool
git_repository__reserved_names
(
git_str
**
out
,
size_t
*
outlen
,
git_repository
*
repo
,
bool
include_ntfs
);
int
git_repository__shallow_roots
(
git_array_oid_t
*
out
,
git_repository
*
repo
);
int
git_repository__shallow_roots_write
(
git_repository
*
repo
,
git_array_oid_t
roots
);
/*
* The default branch for the repository; the `init.defaultBranch`
* configuration option, if set, or `master` if it is not.
...
...
src/libgit2/transports/local.c
View file @
68bbcefd
...
...
@@ -284,15 +284,13 @@ static int local_ls(const git_remote_head ***out, size_t *size, git_transport *t
static
int
local_negotiate_fetch
(
git_transport
*
transport
,
git_repository
*
repo
,
const
git_remote_head
*
const
*
refs
,
size_t
count
)
const
git_fetch_negotiation
*
wants
)
{
transport_local
*
t
=
(
transport_local
*
)
transport
;
git_remote_head
*
rhead
;
unsigned
int
i
;
GIT_UNUSED
(
refs
);
GIT_UNUSED
(
count
);
GIT_UNUSED
(
wants
);
/* Fill in the loids */
git_vector_foreach
(
&
t
->
refs
,
i
,
rhead
)
{
...
...
src/libgit2/transports/smart.c
View file @
68bbcefd
...
...
@@ -482,3 +482,31 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
*
out
=
(
git_transport
*
)
t
;
return
0
;
}
size_t
git_shallowarray_count
(
git_shallowarray
*
array
)
{
return
git_array_size
(
array
->
array
);
}
const
git_oid
*
git_shallowarray_get
(
git_shallowarray
*
array
,
size_t
idx
)
{
return
git_array_get
(
array
->
array
,
idx
);
}
int
git_shallowarray_add
(
git_shallowarray
*
array
,
git_oid
*
oid
)
{
size_t
oid_index
;
if
(
git_array_search
(
&
oid_index
,
array
->
array
,
(
git_array_compare_cb
)
git_oid_cmp
,
&
oid
)
<
0
)
{
git_oid
*
tmp
=
git_array_alloc
(
array
->
array
);
git_oid_cpy
(
tmp
,
oid
);
}
return
0
;
}
int
git_shallowarray_remove
(
git_shallowarray
*
array
,
git_oid
*
oid
)
{
GIT_UNUSED
(
array
);
GIT_UNUSED
(
oid
);
/* no git_array_remove… meh */
return
-
1
;
}
src/libgit2/transports/smart.h
View file @
68bbcefd
...
...
@@ -14,6 +14,7 @@
#include "netops.h"
#include "push.h"
#include "str.h"
#include "oidarray.h"
#include "git2/sys/transport.h"
#define GIT_SIDE_BAND_DATA 1
...
...
@@ -32,6 +33,7 @@
#define GIT_CAP_SYMREF "symref"
#define GIT_CAP_WANT_TIP_SHA1 "allow-tip-sha1-in-want"
#define GIT_CAP_WANT_REACHABLE_SHA1 "allow-reachable-sha1-in-want"
#define GIT_CAP_SHALLOW "shallow"
extern
bool
git_smart__ofs_delta_enabled
;
...
...
@@ -48,7 +50,9 @@ typedef enum {
GIT_PKT_PROGRESS
,
GIT_PKT_OK
,
GIT_PKT_NG
,
GIT_PKT_UNPACK
GIT_PKT_UNPACK
,
GIT_PKT_SHALLOW
,
GIT_PKT_UNSHALLOW
,
}
git_pkt_type
;
/* Used for multi_ack and multi_ack_detailed */
...
...
@@ -120,6 +124,11 @@ typedef struct {
int
unpack_ok
;
}
git_pkt_unpack
;
typedef
struct
{
git_pkt_type
type
;
git_oid
oid
;
}
git_pkt_shallow
;
typedef
struct
transport_smart_caps
{
unsigned
int
common
:
1
,
ofs_delta
:
1
,
...
...
@@ -132,7 +141,8 @@ typedef struct transport_smart_caps {
report_status
:
1
,
thin_pack
:
1
,
want_tip_sha1
:
1
,
want_reachable_sha1
:
1
;
want_reachable_sha1
:
1
,
shallow
:
1
;
}
transport_smart_caps
;
typedef
int
(
*
packetsize_cb
)(
size_t
received
,
void
*
payload
);
...
...
@@ -167,8 +177,7 @@ int git_smart__push(git_transport *transport, git_push *push);
int
git_smart__negotiate_fetch
(
git_transport
*
transport
,
git_repository
*
repo
,
const
git_remote_head
*
const
*
refs
,
size_t
count
);
const
git_fetch_negotiation
*
wants
);
int
git_smart__download_pack
(
git_transport
*
transport
,
...
...
@@ -186,8 +195,12 @@ int git_pkt_parse_line(git_pkt **head, const char **endptr, const char *line, si
int
git_pkt_buffer_flush
(
git_str
*
buf
);
int
git_pkt_send_flush
(
GIT_SOCKET
s
);
int
git_pkt_buffer_done
(
git_str
*
buf
);
int
git_pkt_buffer_wants
(
const
git_
remote_head
*
const
*
refs
,
size_t
count
,
transport_smart_caps
*
caps
,
git_str
*
buf
);
int
git_pkt_buffer_wants
(
const
git_
fetch_negotiation
*
wants
,
transport_smart_caps
*
caps
,
git_str
*
buf
);
int
git_pkt_buffer_have
(
git_oid
*
oid
,
git_str
*
buf
);
void
git_pkt_free
(
git_pkt
*
pkt
);
struct
git_shallowarray
{
git_array_oid_t
array
;
};
#endif
src/libgit2/transports/smart_pkt.c
View file @
68bbcefd
...
...
@@ -366,6 +366,50 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
return
0
;
}
static
int
shallow_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
{
git_pkt_shallow
*
pkt
;
pkt
=
git__calloc
(
1
,
sizeof
(
git_pkt_shallow
));
GIT_ERROR_CHECK_ALLOC
(
pkt
);
pkt
->
type
=
GIT_PKT_SHALLOW
;
line
+=
7
;
len
-=
7
;
if
(
len
>=
GIT_OID_HEXSZ
)
{
git_oid_fromstr
(
&
pkt
->
oid
,
line
+
1
);
line
+=
GIT_OID_HEXSZ
+
1
;
len
-=
GIT_OID_HEXSZ
+
1
;
}
*
out
=
(
git_pkt
*
)
pkt
;
return
0
;
}
static
int
unshallow_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
{
git_pkt_shallow
*
pkt
;
pkt
=
git__calloc
(
1
,
sizeof
(
git_pkt_shallow
));
GIT_ERROR_CHECK_ALLOC
(
pkt
);
pkt
->
type
=
GIT_PKT_UNSHALLOW
;
line
+=
9
;
len
-=
9
;
if
(
len
>=
GIT_OID_HEXSZ
)
{
git_oid_fromstr
(
&
pkt
->
oid
,
line
+
1
);
line
+=
GIT_OID_HEXSZ
+
1
;
len
-=
GIT_OID_HEXSZ
+
1
;
}
*
out
=
(
git_pkt
*
)
pkt
;
return
0
;
}
static
int
parse_len
(
size_t
*
out
,
const
char
*
line
,
size_t
linelen
)
{
char
num
[
PKT_LEN_SIZE
+
1
];
...
...
@@ -492,6 +536,10 @@ int git_pkt_parse_line(
error
=
ng_pkt
(
pkt
,
line
,
len
);
else
if
(
!
git__prefixncmp
(
line
,
len
,
"unpack"
))
error
=
unpack_pkt
(
pkt
,
line
,
len
);
else
if
(
!
git__prefixcmp
(
line
,
"shallow"
))
error
=
shallow_pkt
(
pkt
,
line
,
len
);
else
if
(
!
git__prefixcmp
(
line
,
"unshallow"
))
error
=
unshallow_pkt
(
pkt
,
line
,
len
);
else
error
=
ref_pkt
(
pkt
,
line
,
len
);
...
...
@@ -557,6 +605,9 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca
if
(
caps
->
ofs_delta
)
git_str_puts
(
&
str
,
GIT_CAP_OFS_DELTA
" "
);
if
(
caps
->
shallow
)
git_str_puts
(
&
str
,
GIT_CAP_SHALLOW
" "
);
if
(
git_str_oom
(
&
str
))
return
-
1
;
...
...
@@ -586,8 +637,7 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca
*/
int
git_pkt_buffer_wants
(
const
git_remote_head
*
const
*
refs
,
size_t
count
,
const
git_fetch_negotiation
*
wants
,
transport_smart_caps
*
caps
,
git_str
*
buf
)
{
...
...
@@ -595,22 +645,22 @@ int git_pkt_buffer_wants(
const
git_remote_head
*
head
;
if
(
caps
->
common
)
{
for
(;
i
<
count
;
++
i
)
{
head
=
refs
[
i
];
for
(;
i
<
wants
->
count
;
++
i
)
{
head
=
wants
->
refs
[
i
];
if
(
!
head
->
local
)
break
;
}
if
(
buffer_want_with_caps
(
refs
[
i
],
caps
,
buf
)
<
0
)
if
(
buffer_want_with_caps
(
wants
->
refs
[
i
],
caps
,
buf
)
<
0
)
return
-
1
;
i
++
;
}
for
(;
i
<
count
;
++
i
)
{
for
(;
i
<
wants
->
count
;
++
i
)
{
char
oid
[
GIT_OID_SHA1_HEXSIZE
];
head
=
refs
[
i
];
head
=
wants
->
refs
[
i
];
if
(
head
->
local
)
continue
;
...
...
@@ -622,6 +672,32 @@ int git_pkt_buffer_wants(
return
-
1
;
}
/* Tell the server about our shallow objects */
for
(
i
=
0
;
i
<
git_shallowarray_count
(
wants
->
shallow_roots
);
i
++
)
{
char
oid
[
GIT_OID_HEXSZ
];
git_buf
shallow_buf
=
GIT_BUF_INIT
;
git_oid_fmt
(
oid
,
git_shallowarray_get
(
wants
->
shallow_roots
,
i
));
git_buf_puts
(
&
shallow_buf
,
"shallow "
);
git_buf_put
(
&
shallow_buf
,
oid
,
GIT_OID_HEXSZ
);
git_buf_putc
(
&
shallow_buf
,
'\n'
);
git_buf_printf
(
buf
,
"%04x%s"
,
(
unsigned
int
)
git_buf_len
(
&
shallow_buf
)
+
4
,
git_buf_cstr
(
&
shallow_buf
));
if
(
git_buf_oom
(
buf
))
return
-
1
;
}
if
(
wants
->
depth
>
0
)
{
git_buf
deepen_buf
=
GIT_BUF_INIT
;
git_buf_printf
(
&
deepen_buf
,
"deepen %d
\n
"
,
wants
->
depth
);
git_buf_printf
(
buf
,
"%04x%s"
,
(
unsigned
int
)
git_buf_len
(
&
deepen_buf
)
+
4
,
git_buf_cstr
(
&
deepen_buf
));
if
(
git_buf_oom
(
buf
))
return
-
1
;
}
return
git_pkt_buffer_flush
(
buf
);
}
...
...
src/libgit2/transports/smart_protocol.c
View file @
68bbcefd
...
...
@@ -214,6 +214,11 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
if
(
!
git__prefixcmp
(
ptr
,
GIT_CAP_WANT_REACHABLE_SHA1
))
{
caps
->
common
=
caps
->
want_reachable_sha1
=
1
;
ptr
+=
strlen
(
GIT_CAP_DELETE_REFS
);
}
if
(
!
git__prefixcmp
(
ptr
,
GIT_CAP_SHALLOW
))
{
caps
->
common
=
caps
->
shallow
=
1
;
ptr
+=
strlen
(
GIT_CAP_SHALLOW
);
continue
;
}
...
...
@@ -317,7 +322,26 @@ static int wait_while_ack(gitno_buffer *buf)
return
0
;
}
int
git_smart__negotiate_fetch
(
git_transport
*
transport
,
git_repository
*
repo
,
const
git_remote_head
*
const
*
wants
,
size_t
count
)
static
int
cap_not_sup_err
(
const
char
*
cap_name
)
{
git_error_set
(
GIT_ERROR_NET
,
"server doesn't support %s"
,
cap_name
);
return
GIT_EINVALID
;
}
/* Disables server capabilities we're not interested in */
static
int
setup_caps
(
transport_smart_caps
*
caps
,
const
git_fetch_negotiation
*
wants
)
{
if
(
wants
->
depth
)
{
if
(
!
caps
->
shallow
)
return
cap_not_sup_err
(
GIT_CAP_SHALLOW
);
}
else
{
caps
->
shallow
=
0
;
}
return
0
;
}
int
git_smart__negotiate_fetch
(
git_transport
*
transport
,
git_repository
*
repo
,
const
git_fetch_negotiation
*
wants
)
{
transport_smart
*
t
=
(
transport_smart
*
)
transport
;
git_revwalk__push_options
opts
=
GIT_REVWALK__PUSH_OPTIONS_INIT
;
...
...
@@ -329,7 +353,10 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
unsigned
int
i
;
git_oid
oid
;
if
((
error
=
git_pkt_buffer_wants
(
wants
,
count
,
&
t
->
caps
,
&
data
))
<
0
)
if
((
error
=
setup_caps
(
&
t
->
caps
,
wants
))
<
0
)
return
error
;
if
((
error
=
git_pkt_buffer_wants
(
wants
,
&
t
->
caps
,
&
data
))
<
0
)
return
error
;
if
((
error
=
git_revwalk_new
(
&
walk
,
repo
))
<
0
)
...
...
@@ -339,6 +366,33 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
if
((
error
=
git_revwalk__push_glob
(
walk
,
"refs/*"
,
&
opts
))
<
0
)
goto
on_error
;
if
(
wants
->
depth
>
0
)
{
git_pkt_shallow
*
pkt
;
if
((
error
=
git_smart__negotiation_step
(
&
t
->
parent
,
data
.
ptr
,
data
.
size
))
<
0
)
goto
on_error
;
while
((
error
=
recv_pkt
((
git_pkt
**
)
&
pkt
,
NULL
,
buf
))
==
0
)
{
if
(
pkt
->
type
==
GIT_PKT_SHALLOW
)
{
printf
(
"shallow %s
\n
"
,
git_oid_tostr_s
(
&
pkt
->
oid
));
git_shallowarray_add
(
wants
->
shallow_roots
,
&
pkt
->
oid
);
}
else
if
(
pkt
->
type
==
GIT_PKT_UNSHALLOW
)
{
printf
(
"unshallow %s
\n
"
,
git_oid_tostr_s
(
&
pkt
->
oid
));
git_shallowarray_remove
(
wants
->
shallow_roots
,
&
pkt
->
oid
);
}
else
if
(
pkt
->
type
==
GIT_PKT_FLUSH
)
{
/* Server is done, stop processing shallow oids */
break
;
}
else
{
git_error_set
(
GIT_ERROR_NET
,
"Unexpected pkt type"
);
goto
on_error
;
}
}
if
(
error
<
0
)
{
goto
on_error
;
}
}
/*
* Our support for ACK extensions is simply to parse them. On
* the first ACK we will accept that as enough common
...
...
@@ -401,7 +455,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
git_pkt_ack
*
pkt
;
unsigned
int
j
;
if
((
error
=
git_pkt_buffer_wants
(
wants
,
count
,
&
t
->
caps
,
&
data
))
<
0
)
if
((
error
=
git_pkt_buffer_wants
(
wants
,
&
t
->
caps
,
&
data
))
<
0
)
goto
on_error
;
git_vector_foreach
(
&
t
->
common
,
j
,
pkt
)
{
...
...
@@ -421,7 +475,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
git_pkt_ack
*
pkt
;
unsigned
int
j
;
if
((
error
=
git_pkt_buffer_wants
(
wants
,
count
,
&
t
->
caps
,
&
data
))
<
0
)
if
((
error
=
git_pkt_buffer_wants
(
wants
,
&
t
->
caps
,
&
data
))
<
0
)
goto
on_error
;
git_vector_foreach
(
&
t
->
common
,
j
,
pkt
)
{
...
...
src/util/array.h
View file @
68bbcefd
...
...
@@ -85,12 +85,14 @@ on_oom:
#define git_array_foreach(a, i, element) \
for ((i) = 0; (i) < (a).size && ((element) = &(a).ptr[(i)]); (i)++)
typedef
int
(
*
git_array_compare_cb
)(
const
void
*
,
const
void
*
);
GIT_INLINE
(
int
)
git_array__search
(
size_t
*
out
,
void
*
array_ptr
,
size_t
item_size
,
size_t
array_len
,
int
(
*
compare
)(
const
void
*
,
const
void
*
)
,
git_array_compare_cb
compare
,
const
void
*
key
)
{
size_t
lim
;
...
...
tests/clone/shallow.c
0 → 100644
View file @
68bbcefd
#include "clar_libgit2.h"
#include "futils.h"
#include "repository.h"
void
test_clone_shallow__initialize
(
void
)
{
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_ENABLE_SHALLOW
,
1
));
}
void
test_clone_shallow__cleanup
(
void
)
{
git_libgit2_opts
(
GIT_OPT_ENABLE_SHALLOW
,
0
);
cl_git_sandbox_cleanup
();
}
static
int
remote_single_branch
(
git_remote
**
out
,
git_repository
*
repo
,
const
char
*
name
,
const
char
*
url
,
void
*
payload
)
{
GIT_UNUSED
(
payload
);
cl_git_pass
(
git_remote_create_with_fetchspec
(
out
,
repo
,
name
,
url
,
"+refs/heads/master:refs/remotes/origin/master"
));
return
0
;
}
void
test_clone_shallow__clone_depth_one
(
void
)
{
git_buf
path
=
GIT_BUF_INIT
;
git_repository
*
repo
;
git_revwalk
*
walk
;
git_clone_options
clone_opts
=
GIT_CLONE_OPTIONS_INIT
;
git_oid
oid
;
git_oidarray
roots
;
size_t
num_commits
=
0
;
int
error
=
0
;
clone_opts
.
fetch_opts
.
depth
=
1
;
clone_opts
.
remote_cb
=
remote_single_branch
;
git_buf_joinpath
(
&
path
,
clar_sandbox_path
(),
"shallowclone_1"
);
cl_git_pass
(
git_clone
(
&
repo
,
"https://github.com/libgit2/TestGitRepository"
,
git_buf_cstr
(
&
path
),
&
clone_opts
));
cl_assert_equal_b
(
true
,
git_repository_is_shallow
(
repo
));
cl_git_pass
(
git_repository_shallow_roots
(
&
roots
,
repo
));
cl_assert_equal_i
(
1
,
roots
.
count
);
cl_assert_equal_s
(
"49322bb17d3acc9146f98c97d078513228bbf3c0"
,
git_oid_tostr_s
(
&
roots
.
ids
[
0
]));
git_revwalk_new
(
&
walk
,
repo
);
git_revwalk_push_head
(
walk
);
while
((
error
=
git_revwalk_next
(
&
oid
,
walk
))
==
GIT_OK
)
{
num_commits
++
;
}
cl_assert_equal_i
(
num_commits
,
1
);
cl_assert_equal_i
(
error
,
GIT_ITEROVER
);
git_buf_dispose
(
&
path
);
git_revwalk_free
(
walk
);
git_repository_free
(
repo
);
}
void
test_clone_shallow__clone_depth_five
(
void
)
{
git_buf
path
=
GIT_BUF_INIT
;
git_repository
*
repo
;
git_revwalk
*
walk
;
git_clone_options
clone_opts
=
GIT_CLONE_OPTIONS_INIT
;
git_oid
oid
;
git_oidarray
roots
;
size_t
num_commits
=
0
;
int
error
=
0
;
clone_opts
.
fetch_opts
.
depth
=
5
;
clone_opts
.
remote_cb
=
remote_single_branch
;
git_buf_joinpath
(
&
path
,
clar_sandbox_path
(),
"shallowclone_5"
);
cl_git_pass
(
git_clone
(
&
repo
,
"https://github.com/libgit2/TestGitRepository"
,
git_buf_cstr
(
&
path
),
&
clone_opts
));
cl_assert_equal_b
(
true
,
git_repository_is_shallow
(
repo
));
cl_git_pass
(
git_repository_shallow_roots
(
&
roots
,
repo
));
cl_assert_equal_i
(
3
,
roots
.
count
);
cl_assert_equal_s
(
"c070ad8c08840c8116da865b2d65593a6bb9cd2a"
,
git_oid_tostr_s
(
&
roots
.
ids
[
0
]));
cl_assert_equal_s
(
"0966a434eb1a025db6b71485ab63a3bfbea520b6"
,
git_oid_tostr_s
(
&
roots
.
ids
[
1
]));
cl_assert_equal_s
(
"83834a7afdaa1a1260568567f6ad90020389f664"
,
git_oid_tostr_s
(
&
roots
.
ids
[
2
]));
git_revwalk_new
(
&
walk
,
repo
);
git_revwalk_push_head
(
walk
);
while
((
error
=
git_revwalk_next
(
&
oid
,
walk
))
==
GIT_OK
)
{
num_commits
++
;
}
cl_assert_equal_i
(
num_commits
,
13
);
cl_assert_equal_i
(
error
,
GIT_ITEROVER
);
git_buf_dispose
(
&
path
);
git_revwalk_free
(
walk
);
git_repository_free
(
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