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
9d88300a
Commit
9d88300a
authored
Feb 05, 2022
by
Edward Thomson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fetch: support oids in fetch specs
parent
07264ea7
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
160 additions
and
15 deletions
+160
-15
src/fetch.c
+66
-14
src/remote.c
+31
-1
src/remote.h
+1
-0
tests/fetch/local.c
+31
-0
tests/online/fetch.c
+31
-0
No files found.
src/fetch.c
View file @
9d88300a
...
...
@@ -11,6 +11,7 @@
#include "git2/refs.h"
#include "git2/revwalk.h"
#include "git2/transport.h"
#include "git2/sys/remote.h"
#include "remote.h"
#include "refspec.h"
...
...
@@ -19,7 +20,7 @@
#include "repository.h"
#include "refs.h"
static
int
maybe_want
(
git_remote
*
remote
,
git_remote_head
*
head
,
git_
odb
*
odb
,
git_
refspec
*
tagspec
,
git_remote_autotag_option_t
tagopt
)
static
int
maybe_want
(
git_remote
*
remote
,
git_remote_head
*
head
,
git_refspec
*
tagspec
,
git_remote_autotag_option_t
tagopt
)
{
int
match
=
0
,
valid
;
...
...
@@ -44,23 +45,57 @@ static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, g
if
(
!
match
)
return
0
;
/* If we have the object, mark it so we don't ask for it */
if
(
git_odb_exists
(
odb
,
&
head
->
oid
))
{
head
->
local
=
1
;
return
git_vector_insert
(
&
remote
->
refs
,
head
);
}
static
int
mark_local
(
git_remote
*
remote
)
{
git_remote_head
*
head
;
git_odb
*
odb
;
size_t
i
;
if
(
git_repository_odb__weakptr
(
&
odb
,
remote
->
repo
)
<
0
)
return
-
1
;
git_vector_foreach
(
&
remote
->
refs
,
i
,
head
)
{
/* If we have the object, mark it so we don't ask for it */
if
(
git_odb_exists
(
odb
,
&
head
->
oid
))
head
->
local
=
1
;
else
remote
->
need_pack
=
1
;
}
else
remote
->
need_pack
=
1
;
return
git_vector_insert
(
&
remote
->
refs
,
head
);
return
0
;
}
static
int
maybe_want_oid
(
git_remote
*
remote
,
git_refspec
*
spec
)
{
git_remote_head
*
oid_head
;
oid_head
=
git__calloc
(
1
,
sizeof
(
git_remote_head
));
GIT_ERROR_CHECK_ALLOC
(
oid_head
);
git_oid_fromstr
(
&
oid_head
->
oid
,
spec
->
src
);
oid_head
->
name
=
git__strdup
(
spec
->
dst
);
GIT_ERROR_CHECK_ALLOC
(
oid_head
->
name
);
if
(
git_vector_insert
(
&
remote
->
local_heads
,
oid_head
)
<
0
||
git_vector_insert
(
&
remote
->
refs
,
oid_head
)
<
0
)
return
-
1
;
return
0
;
}
static
int
filter_wants
(
git_remote
*
remote
,
const
git_fetch_options
*
opts
)
{
git_remote_head
**
heads
;
git_refspec
tagspec
,
head
;
git_refspec
tagspec
,
head
,
*
spec
;
int
error
=
0
;
git_odb
*
odb
;
size_t
i
,
heads_len
;
unsigned
int
remote_caps
;
unsigned
int
oid_mask
=
GIT_REMOTE_CAPABILITY_TIP_OID
|
GIT_REMOTE_CAPABILITY_REACHABLE_OID
;
git_remote_autotag_option_t
tagopt
=
remote
->
download_tags
;
if
(
opts
&&
opts
->
download_tags
!=
GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED
)
...
...
@@ -90,14 +125,33 @@ static int filter_wants(git_remote *remote, const git_fetch_options *opts)
if
((
error
=
git_repository_odb__weakptr
(
&
odb
,
remote
->
repo
))
<
0
)
goto
cleanup
;
if
((
error
=
git_remote_ls
((
const
git_remote_head
***
)
&
heads
,
&
heads_len
,
remote
))
<
0
)
if
((
error
=
git_remote_ls
((
const
git_remote_head
***
)
&
heads
,
&
heads_len
,
remote
))
<
0
||
(
error
=
git_remote_capabilities
(
&
remote_caps
,
remote
))
<
0
)
goto
cleanup
;
/* Handle remote heads */
for
(
i
=
0
;
i
<
heads_len
;
i
++
)
{
if
((
error
=
maybe_want
(
remote
,
heads
[
i
],
odb
,
&
tagspec
,
tagopt
))
<
0
)
break
;
if
((
error
=
maybe_want
(
remote
,
heads
[
i
],
&
tagspec
,
tagopt
))
<
0
)
goto
cleanup
;
}
/* Handle explicitly specified OID specs */
git_vector_foreach
(
&
remote
->
active_refspecs
,
i
,
spec
)
{
if
(
!
git_oid__is_hexstr
(
spec
->
src
))
continue
;
if
(
!
(
remote_caps
&
oid_mask
))
{
git_error_set
(
GIT_ERROR_INVALID
,
"cannot fetch a specific object from the remote repository"
);
error
=
-
1
;
goto
cleanup
;
}
if
((
error
=
maybe_want_oid
(
remote
,
spec
))
<
0
)
goto
cleanup
;
}
error
=
mark_local
(
remote
);
cleanup:
git_refspec__dispose
(
&
tagspec
);
...
...
@@ -115,10 +169,8 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
remote
->
need_pack
=
0
;
if
(
filter_wants
(
remote
,
opts
)
<
0
)
{
git_error_set
(
GIT_ERROR_NET
,
"failed to filter the reference list for wants"
);
if
(
filter_wants
(
remote
,
opts
)
<
0
)
return
-
1
;
}
/* Don't try to negotiate when we don't want anything */
if
(
!
remote
->
need_pack
)
...
...
src/remote.c
View file @
9d88300a
...
...
@@ -1871,7 +1871,7 @@ static int update_tips_for_spec(
const
char
*
log_message
)
{
git_refspec
tagspec
;
git_remote_head
*
head
;
git_remote_head
*
head
,
oid_head
;
git_vector
update_heads
;
int
error
=
0
;
size_t
i
;
...
...
@@ -1885,11 +1885,27 @@ static int update_tips_for_spec(
if
(
git_vector_init
(
&
update_heads
,
16
,
NULL
)
<
0
)
return
-
1
;
/* Update tips based on the remote heads */
git_vector_foreach
(
refs
,
i
,
head
)
{
if
(
update_one_tip
(
&
update_heads
,
remote
,
spec
,
head
,
&
tagspec
,
tagopt
,
log_message
,
callbacks
)
<
0
)
goto
on_error
;
}
/* Handle specified oid sources */
if
(
git_oid__is_hexstr
(
spec
->
src
))
{
git_oid
id
;
if
((
error
=
git_oid_fromstr
(
&
id
,
spec
->
src
))
<
0
||
(
error
=
update_ref
(
remote
,
spec
->
dst
,
&
id
,
log_message
,
callbacks
))
<
0
)
goto
on_error
;
git_oid_cpy
(
&
oid_head
.
oid
,
&
id
);
oid_head
.
name
=
spec
->
src
;
if
((
error
=
git_vector_insert
(
&
update_heads
,
&
oid_head
))
<
0
)
goto
on_error
;
}
if
(
update_fetchhead
&&
(
error
=
git_remote_write_fetchhead
(
remote
,
spec
,
&
update_heads
))
<
0
)
goto
on_error
;
...
...
@@ -2107,6 +2123,17 @@ int git_remote_disconnect(git_remote *remote)
return
0
;
}
static
void
free_heads
(
git_vector
*
heads
)
{
git_remote_head
*
head
;
size_t
i
;
git_vector_foreach
(
heads
,
i
,
head
)
{
git__free
(
head
->
name
);
git__free
(
head
);
}
}
void
git_remote_free
(
git_remote
*
remote
)
{
if
(
remote
==
NULL
)
...
...
@@ -2130,6 +2157,9 @@ void git_remote_free(git_remote *remote)
free_refspecs
(
&
remote
->
passive_refspecs
);
git_vector_free
(
&
remote
->
passive_refspecs
);
free_heads
(
&
remote
->
local_heads
);
git_vector_free
(
&
remote
->
local_heads
);
git_push_free
(
remote
->
push
);
git__free
(
remote
->
url
);
git__free
(
remote
->
pushurl
);
...
...
src/remote.h
View file @
9d88300a
...
...
@@ -27,6 +27,7 @@ struct git_remote {
git_vector
refspecs
;
git_vector
active_refspecs
;
git_vector
passive_refspecs
;
git_vector
local_heads
;
git_transport
*
transport
;
git_repository
*
repo
;
git_push
*
push
;
...
...
tests/fetch/local.c
View file @
9d88300a
...
...
@@ -34,3 +34,34 @@ void test_fetch_local__defaults(void)
git_object_free
(
obj
);
git_remote_free
(
remote
);
}
void
test_fetch_local__reachable_commit
(
void
)
{
git_remote
*
remote
;
git_strarray
refspecs
;
git_object
*
obj
;
git_oid
expected_id
;
git_str
fetchhead
=
GIT_STR_INIT
;
char
*
refspec
=
"+5b5b025afb0b4c913b4c338a42934a3863bf3644:refs/success"
;
refspecs
.
strings
=
&
refspec
;
refspecs
.
count
=
1
;
git_oid_fromstr
(
&
expected_id
,
"5b5b025afb0b4c913b4c338a42934a3863bf3644"
);
cl_git_pass
(
git_remote_create
(
&
remote
,
repo
,
"test"
,
cl_fixture
(
"testrepo.git"
)));
cl_git_pass
(
git_remote_fetch
(
remote
,
&
refspecs
,
NULL
,
NULL
));
cl_git_pass
(
git_revparse_single
(
&
obj
,
repo
,
"refs/success"
));
cl_assert_equal_oid
(
&
expected_id
,
git_object_id
(
obj
));
cl_git_pass
(
git_futils_readbuffer
(
&
fetchhead
,
"./fetch/.git/FETCH_HEAD"
));
cl_assert_equal_strn
(
fetchhead
.
ptr
,
"5b5b025afb0b4c913b4c338a42934a3863bf3644
\t\t
'5b5b025afb0b4c913b4c338a42934a3863bf3644' of "
,
strlen
(
"5b5b025afb0b4c913b4c338a42934a3863bf3644
\t\t
'5b5b025afb0b4c913b4c338a42934a3863bf3644' of "
));
git_str_dispose
(
&
fetchhead
);
git_object_free
(
obj
);
git_remote_free
(
remote
);
}
tests/online/fetch.c
View file @
9d88300a
#include "clar_libgit2.h"
#include "futils.h"
static
git_repository
*
_repo
;
static
int
counter
;
...
...
@@ -290,3 +291,33 @@ void test_online_fetch__redirect_config(void)
cl_git_fail
(
do_redirected_fetch
(
_remote_redirect_initial
,
"initial"
,
"false"
));
cl_git_fail
(
do_redirected_fetch
(
_remote_redirect_subsequent
,
"subsequent"
,
"false"
));
}
void
test_online_fetch__reachable_commit
(
void
)
{
git_remote
*
remote
;
git_strarray
refspecs
;
git_object
*
obj
;
git_oid
expected_id
;
git_str
fetchhead
=
GIT_STR_INIT
;
char
*
refspec
=
"+2c349335b7f797072cf729c4f3bb0914ecb6dec9:refs/success"
;
refspecs
.
strings
=
&
refspec
;
refspecs
.
count
=
1
;
git_oid_fromstr
(
&
expected_id
,
"2c349335b7f797072cf729c4f3bb0914ecb6dec9"
);
cl_git_pass
(
git_remote_create
(
&
remote
,
_repo
,
"test"
,
"https://github.com/libgit2/TestGitRepository"
));
cl_git_pass
(
git_remote_fetch
(
remote
,
&
refspecs
,
NULL
,
NULL
));
cl_git_pass
(
git_revparse_single
(
&
obj
,
_repo
,
"refs/success"
));
cl_assert_equal_oid
(
&
expected_id
,
git_object_id
(
obj
));
cl_git_pass
(
git_futils_readbuffer
(
&
fetchhead
,
"./fetch/.git/FETCH_HEAD"
));
cl_assert_equal_s
(
fetchhead
.
ptr
,
"2c349335b7f797072cf729c4f3bb0914ecb6dec9
\t\t
'2c349335b7f797072cf729c4f3bb0914ecb6dec9' of https://github.com/libgit2/TestGitRepository
\n
"
);
git_str_dispose
(
&
fetchhead
);
git_object_free
(
obj
);
git_remote_free
(
remote
);
}
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