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
6414fd33
Commit
6414fd33
authored
Nov 11, 2013
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1956 from libgit2/cmn/fetch-default-head
Remote revamp (director's cut)
parents
5e1281f8
a6192d7c
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
433 additions
and
287 deletions
+433
-287
examples/network/ls-remote.c
+14
-12
include/git2/remote.h
+35
-17
include/git2/transport.h
+6
-6
src/clone.c
+20
-21
src/fetch.c
+32
-27
src/fetchhead.c
+6
-0
src/push.c
+13
-7
src/refspec.c
+68
-0
src/refspec.h
+7
-1
src/remote.c
+114
-91
src/remote.h
+1
-0
src/transports/local.c
+3
-7
src/transports/smart.c
+30
-14
src/transports/smart.h
+3
-0
src/transports/smart_protocol.c
+16
-10
tests-clar/network/remote/local.c
+21
-30
tests-clar/online/fetch.c
+5
-14
tests-clar/online/push.c
+8
-7
tests-clar/online/push_util.c
+23
-17
tests-clar/online/push_util.h
+8
-6
No files found.
examples/network/ls-remote.c
View file @
6414fd33
...
...
@@ -4,21 +4,12 @@
#include <string.h>
#include "common.h"
/** Callback to show each item */
static
int
show_ref__cb
(
git_remote_head
*
head
,
void
*
payload
)
{
char
oid
[
GIT_OID_HEXSZ
+
1
]
=
{
0
};
(
void
)
payload
;
git_oid_fmt
(
oid
,
&
head
->
oid
);
printf
(
"%s
\t
%s
\n
"
,
oid
,
head
->
name
);
return
0
;
}
static
int
use_remote
(
git_repository
*
repo
,
char
*
name
)
{
git_remote
*
remote
=
NULL
;
int
error
;
const
git_remote_head
**
refs
;
size_t
refs_len
,
i
;
git_remote_callbacks
callbacks
=
GIT_REMOTE_CALLBACKS_INIT
;
// Find the remote by name
...
...
@@ -40,7 +31,18 @@ static int use_remote(git_repository *repo, char *name)
if
(
error
<
0
)
goto
cleanup
;
error
=
git_remote_ls
(
remote
,
&
show_ref__cb
,
NULL
);
/**
* Get the list of references on the remote and print out
* their name next to what they point to.
*/
if
(
git_remote_ls
(
&
refs
,
&
refs_len
,
remote
)
<
0
)
goto
cleanup
;
for
(
i
=
0
;
i
<
refs_len
;
i
++
)
{
char
oid
[
GIT_OID_HEXSZ
+
1
]
=
{
0
};
git_oid_fmt
(
oid
,
&
refs
[
i
]
->
oid
);
printf
(
"%s
\t
%s
\n
"
,
oid
,
refs
[
i
]
->
name
);
}
cleanup:
git_remote_free
(
remote
);
...
...
include/git2/remote.h
View file @
6414fd33
...
...
@@ -54,7 +54,7 @@ GIT_EXTERN(int) git_remote_create(
*
* @param out pointer to the new remote object
* @param repo the associated repository
* @param fetch the fetch refspec to use for this remote.
May be NULL for defaults.
* @param fetch the fetch refspec to use for this remote.
* @param url the remote repository's URL
* @return 0 or an error code
*/
...
...
@@ -145,8 +145,11 @@ GIT_EXTERN(int) git_remote_set_pushurl(git_remote *remote, const char* url);
/**
* Add a fetch refspec to the remote
*
* Convenience function for adding a single fetch refspec to the
* current list in the remote.
*
* @param remote the remote
* @
ap
ram refspec the new fetch refspec
* @
pa
ram refspec the new fetch refspec
* @return 0 or an error value
*/
GIT_EXTERN
(
int
)
git_remote_add_fetch
(
git_remote
*
remote
,
const
char
*
refspec
);
...
...
@@ -163,8 +166,21 @@ GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec);
GIT_EXTERN
(
int
)
git_remote_get_fetch_refspecs
(
git_strarray
*
array
,
git_remote
*
remote
);
/**
* Set the remote's list of fetch refspecs
*
* The contents of the string array are copied.
*
* @param remote the remote to modify
* @param array the new list of fetch resfpecs
*/
GIT_EXTERN
(
int
)
git_remote_set_fetch_refspecs
(
git_remote
*
remote
,
git_strarray
*
array
);
/**
* Add a push refspec to the remote
*
* Convenience function for adding a single push refspec to the
* current list in the remote.
*
* @param remote the remote
* @param refspec the new push refspec
* @return 0 or an error value
...
...
@@ -183,6 +199,16 @@ GIT_EXTERN(int) git_remote_add_push(git_remote *remote, const char *refspec);
GIT_EXTERN
(
int
)
git_remote_get_push_refspecs
(
git_strarray
*
array
,
git_remote
*
remote
);
/**
* Set the remote's list of push refspecs
*
* The contents of the string array are copied.
*
* @param remote the remote to modify
* @param array the new list of push resfpecs
*/
GIT_EXTERN
(
int
)
git_remote_set_push_refspecs
(
git_remote
*
remote
,
git_strarray
*
array
);
/**
* Clear the refspecs
*
* Remove all configured fetch and push refspecs from the remote.
...
...
@@ -209,15 +235,6 @@ GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote);
GIT_EXTERN
(
const
git_refspec
*
)
git_remote_get_refspec
(
git_remote
*
remote
,
size_t
n
);
/**
* Remove a refspec from the remote
*
* @param remote the remote to query
* @param n the refspec to remove
* @return 0 or GIT_ENOTFOUND
*/
GIT_EXTERN
(
int
)
git_remote_remove_refspec
(
git_remote
*
remote
,
size_t
n
);
/**
* Open a connection to a remote
*
* The transport is selected based on the URL. The direction argument
...
...
@@ -237,15 +254,16 @@ GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction);
* The remote (or more exactly its transport) must be connected. The
* memory belongs to the remote.
*
* If you a return a non-zero value from the callback, this will stop
* looping over the refs.
* The array will stay valid as long as the remote object exists and
* its transport isn't changed, but a copy is recommended for usage of
* the data.
*
* @param out pointer to the array
* @param size the number of remote heads
* @param remote the remote
* @param list_cb function to call with each ref discovered at the remote
* @param payload additional data to pass to the callback
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
* @return 0 on success, or an error code
*/
GIT_EXTERN
(
int
)
git_remote_ls
(
git_remote
*
remote
,
git_headlist_cb
list_cb
,
void
*
payload
);
GIT_EXTERN
(
int
)
git_remote_ls
(
const
git_remote_head
***
out
,
size_t
*
size
,
git_remote
*
remote
);
/**
* Download and index the packfile
...
...
include/git2/transport.h
View file @
6414fd33
...
...
@@ -203,13 +203,13 @@ struct git_transport {
int
direction
,
int
flags
);
/* This function may be called after a successful call to
connect(). The
*
provided callback is invoked for each ref discovered on the remote
*
end
. */
/* This function may be called after a successful call to
*
connect(). The array returned is owned by the transport and
*
is guranteed until the next call of a transport function
. */
int
(
*
ls
)(
git_transport
*
transpor
t
,
git_headlist_cb
list_cb
,
void
*
payload
);
const
git_remote_head
***
ou
t
,
size_t
*
size
,
git_transport
*
transport
);
/* Executes the push whose context is in the git_push object. */
int
(
*
push
)(
git_transport
*
transport
,
git_push
*
push
);
...
...
src/clone.c
View file @
6414fd33
...
...
@@ -176,25 +176,20 @@ static int update_head_to_new_branch(
return
error
;
}
static
int
get_head_callback
(
git_remote_head
*
head
,
void
*
payload
)
{
git_remote_head
**
destination
=
(
git_remote_head
**
)
payload
;
/* Save the first entry, and terminate the enumeration */
*
destination
=
head
;
return
1
;
}
static
int
update_head_to_remote
(
git_repository
*
repo
,
git_remote
*
remote
)
{
int
retcode
=
-
1
;
size_t
refs_len
;
git_refspec
dummy_spec
;
git_remote_head
*
remote_head
;
const
git_remote_head
*
remote_head
,
**
refs
;
struct
head_info
head_info
;
git_buf
remote_master_name
=
GIT_BUF_INIT
;
if
(
git_remote_ls
(
&
refs
,
&
refs_len
,
remote
)
<
0
)
return
-
1
;
/* Did we just clone an empty repository? */
if
(
re
mote
->
refs
.
length
==
0
)
{
if
(
re
fs_len
==
0
)
{
return
setup_tracking_config
(
repo
,
"master"
,
...
...
@@ -202,12 +197,8 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
GIT_REFS_HEADS_MASTER_FILE
);
}
/* Get the remote's HEAD. This is always the first ref in remote->refs. */
remote_head
=
NULL
;
if
(
!
remote
->
transport
->
ls
(
remote
->
transport
,
get_head_callback
,
&
remote_head
))
return
-
1
;
/* Get the remote's HEAD. This is always the first ref in the list. */
remote_head
=
refs
[
0
];
assert
(
remote_head
);
git_oid_cpy
(
&
head_info
.
remote_head_oid
,
&
remote_head
->
oid
);
...
...
@@ -349,7 +340,7 @@ static bool should_checkout(
int
git_clone_into
(
git_repository
*
repo
,
git_remote
*
remote
,
const
git_checkout_opts
*
co_opts
,
const
char
*
branch
)
{
int
error
=
0
,
old_fetchhead
;
size_t
n
specs
;
git_strarray
ref
specs
;
assert
(
repo
&&
remote
);
...
...
@@ -358,6 +349,10 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_
return
-
1
;
}
if
((
error
=
git_remote_get_fetch_refspecs
(
&
refspecs
,
remote
))
<
0
)
return
error
;
if
((
error
=
git_remote_add_fetch
(
remote
,
"refs/tags/*:refs/tags/*"
))
<
0
)
return
error
;
...
...
@@ -378,9 +373,13 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_
cleanup:
git_remote_set_update_fetchhead
(
remote
,
old_fetchhead
);
/* Remove the tags refspec */
nspecs
=
git_remote_refspec_count
(
remote
);
git_remote_remove_refspec
(
remote
,
nspecs
);
/* Go back to the original refspecs */
if
(
git_remote_set_fetch_refspecs
(
remote
,
&
refspecs
)
<
0
)
{
git_strarray_free
(
&
refspecs
);
return
-
1
;
}
git_strarray_free
(
&
refspecs
);
return
error
;
}
...
...
src/fetch.c
View file @
6414fd33
...
...
@@ -19,55 +19,47 @@
#include "repository.h"
#include "refs.h"
struct
filter_payload
{
git_remote
*
remote
;
const
git_refspec
*
spec
,
*
tagspec
;
git_odb
*
odb
;
int
found_head
;
};
static
int
filter_ref__cb
(
git_remote_head
*
head
,
void
*
payload
)
static
int
maybe_want
(
git_remote
*
remote
,
git_remote_head
*
head
,
git_odb
*
odb
,
git_refspec
*
tagspec
)
{
struct
filter_payload
*
p
=
payload
;
int
match
=
0
;
if
(
!
git_reference_is_valid_name
(
head
->
name
))
return
0
;
if
(
!
p
->
found_head
&&
strcmp
(
head
->
name
,
GIT_HEAD_FILE
)
==
0
)
p
->
found_head
=
1
;
else
if
(
p
->
remote
->
download_tags
==
GIT_REMOTE_DOWNLOAD_TAGS_ALL
)
{
if
(
remote
->
download_tags
==
GIT_REMOTE_DOWNLOAD_TAGS_ALL
)
{
/*
* If tagopt is --tags, then we only use the default
* tags refspec and ignore the remote's
*/
if
(
git_refspec_src_matches
(
p
->
tagspec
,
head
->
name
))
if
(
git_refspec_src_matches
(
tagspec
,
head
->
name
))
match
=
1
;
else
return
0
;
}
else
if
(
git_remote__matching_refspec
(
p
->
remote
,
head
->
name
))
}
else
if
(
git_remote__matching_refspec
(
remote
,
head
->
name
))
match
=
1
;
if
(
!
match
)
return
0
;
/* If we have the object, mark it so we don't ask for it */
if
(
git_odb_exists
(
p
->
odb
,
&
head
->
oid
))
if
(
git_odb_exists
(
odb
,
&
head
->
oid
))
head
->
local
=
1
;
else
p
->
remote
->
need_pack
=
1
;
remote
->
need_pack
=
1
;
return
git_vector_insert
(
&
p
->
remote
->
refs
,
head
);
return
git_vector_insert
(
&
remote
->
refs
,
head
);
}
static
int
filter_wants
(
git_remote
*
remote
)
{
struct
filter_payload
p
;
git_refspec
tagspec
;
int
error
=
-
1
;
git_remote_head
**
heads
;
git_refspec
tagspec
,
head
;
int
error
=
0
;
git_odb
*
odb
;
size_t
i
,
heads_len
;
git_vector_clear
(
&
remote
->
refs
);
if
(
git_refspec__parse
(
&
tagspec
,
GIT_REFSPEC_TAGS
,
true
)
<
0
)
if
(
(
error
=
git_refspec__parse
(
&
tagspec
,
GIT_REFSPEC_TAGS
,
true
)
)
<
0
)
return
error
;
/*
...
...
@@ -76,14 +68,27 @@ static int filter_wants(git_remote *remote)
* not interested in any particular branch but just the remote's
* HEAD, which will be stored in FETCH_HEAD after the fetch.
*/
p
.
tagspec
=
&
tagspec
;
p
.
found_head
=
0
;
p
.
remote
=
remote
;
if
(
remote
->
active_refspecs
.
length
==
0
)
{
if
((
error
=
git_refspec__parse
(
&
head
,
"HEAD"
,
true
))
<
0
)
goto
cleanup
;
if
(
git_repository_odb__weakptr
(
&
p
.
odb
,
remote
->
repo
)
<
0
)
error
=
git_refspec__dwim_one
(
&
remote
->
active_refspecs
,
&
head
,
&
remote
->
refs
);
git_refspec__free
(
&
head
);
if
(
error
<
0
)
goto
cleanup
;
}
if
(
git_repository_odb__weakptr
(
&
odb
,
remote
->
repo
)
<
0
)
goto
cleanup
;
if
(
git_remote_ls
((
const
git_remote_head
***
)
&
heads
,
&
heads_len
,
remote
)
<
0
)
goto
cleanup
;
error
=
git_remote_ls
(
remote
,
filter_ref__cb
,
&
p
);
for
(
i
=
0
;
i
<
heads_len
;
i
++
)
{
if
((
error
=
maybe_want
(
remote
,
heads
[
i
],
odb
,
&
tagspec
))
<
0
)
break
;
}
cleanup:
git_refspec__free
(
&
tagspec
);
...
...
@@ -106,7 +111,7 @@ int git_fetch_negotiate(git_remote *remote)
}
/* Don't try to negotiate when we don't want anything */
if
(
remote
->
refs
.
length
==
0
||
!
remote
->
need_pack
)
if
(
!
remote
->
need_pack
)
return
0
;
/*
...
...
src/fetchhead.c
View file @
6414fd33
...
...
@@ -74,6 +74,7 @@ static int fetchhead_ref_write(
{
char
oid
[
GIT_OID_HEXSZ
+
1
];
const
char
*
type
,
*
name
;
int
head
=
0
;
assert
(
file
&&
fetchhead_ref
);
...
...
@@ -87,11 +88,16 @@ static int fetchhead_ref_write(
GIT_REFS_TAGS_DIR
)
==
0
)
{
type
=
"tag "
;
name
=
fetchhead_ref
->
ref_name
+
strlen
(
GIT_REFS_TAGS_DIR
);
}
else
if
(
!
git__strcmp
(
fetchhead_ref
->
ref_name
,
GIT_HEAD_FILE
))
{
head
=
1
;
}
else
{
type
=
""
;
name
=
fetchhead_ref
->
ref_name
;
}
if
(
head
)
return
git_filebuf_printf
(
file
,
"%s
\t\t
%s
\n
"
,
oid
,
fetchhead_ref
->
remote_url
);
return
git_filebuf_printf
(
file
,
"%s
\t
%s
\t
%s'%s' of %s
\n
"
,
oid
,
(
fetchhead_ref
->
is_merge
)
?
""
:
"not-for-merge"
,
...
...
src/push.c
View file @
6414fd33
...
...
@@ -616,16 +616,22 @@ on_error:
return
error
;
}
static
int
cb_filter_refs
(
git_remote_head
*
ref
,
void
*
data
)
{
git_remote
*
remote
=
(
git_remote
*
)
data
;
return
git_vector_insert
(
&
remote
->
refs
,
ref
);
}
static
int
filter_refs
(
git_remote
*
remote
)
{
const
git_remote_head
**
heads
;
size_t
heads_len
,
i
;
git_vector_clear
(
&
remote
->
refs
);
return
git_remote_ls
(
remote
,
cb_filter_refs
,
remote
);
if
(
git_remote_ls
(
&
heads
,
&
heads_len
,
remote
)
<
0
)
return
-
1
;
for
(
i
=
0
;
i
<
heads_len
;
i
++
)
{
if
(
git_vector_insert
(
&
remote
->
refs
,
heads
[
i
])
<
0
)
return
-
1
;
}
return
0
;
}
int
git_push_finish
(
git_push
*
push
)
...
...
src/refspec.c
View file @
6414fd33
...
...
@@ -12,6 +12,7 @@
#include "util.h"
#include "posix.h"
#include "refs.h"
#include "vector.h"
int
git_refspec__parse
(
git_refspec
*
refspec
,
const
char
*
input
,
bool
is_fetch
)
{
...
...
@@ -287,3 +288,70 @@ git_direction git_refspec_direction(const git_refspec *spec)
return
spec
->
push
;
}
int
git_refspec__dwim_one
(
git_vector
*
out
,
git_refspec
*
spec
,
git_vector
*
refs
)
{
git_buf
buf
=
GIT_BUF_INIT
;
size_t
j
,
pos
;
git_remote_head
key
;
const
char
*
formatters
[]
=
{
GIT_REFS_DIR
"%s"
,
GIT_REFS_TAGS_DIR
"%s"
,
GIT_REFS_HEADS_DIR
"%s"
,
NULL
};
git_refspec
*
cur
=
git__calloc
(
1
,
sizeof
(
git_refspec
));
GITERR_CHECK_ALLOC
(
cur
);
cur
->
force
=
spec
->
force
;
cur
->
push
=
spec
->
push
;
cur
->
pattern
=
spec
->
pattern
;
cur
->
matching
=
spec
->
matching
;
cur
->
string
=
git__strdup
(
spec
->
string
);
/* shorthand on the lhs */
if
(
git__prefixcmp
(
spec
->
src
,
GIT_REFS_DIR
))
{
for
(
j
=
0
;
formatters
[
j
];
j
++
)
{
git_buf_clear
(
&
buf
);
if
(
git_buf_printf
(
&
buf
,
formatters
[
j
],
spec
->
src
)
<
0
)
return
-
1
;
key
.
name
=
(
char
*
)
git_buf_cstr
(
&
buf
);
if
(
!
git_vector_search
(
&
pos
,
refs
,
&
key
))
{
/* we found something to match the shorthand, set src to that */
cur
->
src
=
git_buf_detach
(
&
buf
);
}
}
}
/* No shorthands found, copy over the name */
if
(
cur
->
src
==
NULL
&&
spec
->
src
!=
NULL
)
{
cur
->
src
=
git__strdup
(
spec
->
src
);
GITERR_CHECK_ALLOC
(
cur
->
src
);
}
if
(
spec
->
dst
&&
git__prefixcmp
(
spec
->
dst
,
GIT_REFS_DIR
))
{
/* if it starts with "remotes" then we just prepend "refs/" */
if
(
!
git__prefixcmp
(
spec
->
dst
,
"remotes/"
))
{
git_buf_puts
(
&
buf
,
GIT_REFS_DIR
);
}
else
{
git_buf_puts
(
&
buf
,
GIT_REFS_HEADS_DIR
);
}
if
(
git_buf_puts
(
&
buf
,
spec
->
dst
)
<
0
)
return
-
1
;
cur
->
dst
=
git_buf_detach
(
&
buf
);
}
git_buf_free
(
&
buf
);
if
(
cur
->
dst
==
NULL
&&
spec
->
dst
!=
NULL
)
{
cur
->
dst
=
git__strdup
(
spec
->
dst
);
GITERR_CHECK_ALLOC
(
cur
->
dst
);
}
return
git_vector_insert
(
out
,
cur
);
}
src/refspec.h
View file @
6414fd33
...
...
@@ -9,6 +9,7 @@
#include "git2/refspec.h"
#include "buffer.h"
#include "vector.h"
struct
git_refspec
{
char
*
string
;
...
...
@@ -17,7 +18,6 @@ struct git_refspec {
unsigned
int
force
:
1
,
push
:
1
,
pattern
:
1
,
dwim
:
1
,
matching
:
1
;
};
...
...
@@ -63,4 +63,10 @@ int git_refspec__serialize(git_buf *out, const git_refspec *refspec);
*/
int
git_refspec_is_wildcard
(
const
git_refspec
*
spec
);
/**
* DWIM `spec` with `refs` existing on the remote, append the dwim'ed
* result in `out`.
*/
int
git_refspec__dwim_one
(
git_vector
*
out
,
git_refspec
*
spec
,
git_vector
*
refs
);
#endif
src/remote.c
View file @
6414fd33
...
...
@@ -19,6 +19,8 @@
#include "refspec.h"
#include "fetchhead.h"
static
int
dwim_refspecs
(
git_vector
*
out
,
git_vector
*
refspecs
,
git_vector
*
refs
);
static
int
add_refspec
(
git_remote
*
remote
,
const
char
*
string
,
bool
is_fetch
)
{
git_refspec
*
spec
;
...
...
@@ -288,7 +290,8 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
GITERR_CHECK_ALLOC
(
remote
->
name
);
if
((
git_vector_init
(
&
remote
->
refs
,
32
,
NULL
)
<
0
)
||
(
git_vector_init
(
&
remote
->
refspecs
,
2
,
NULL
)))
{
(
git_vector_init
(
&
remote
->
refspecs
,
2
,
NULL
)
<
0
)
||
(
git_vector_init
(
&
remote
->
active_refspecs
,
2
,
NULL
)
<
0
))
{
error
=
-
1
;
goto
cleanup
;
}
...
...
@@ -347,6 +350,10 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
if
(
download_tags_value
(
remote
,
config
)
<
0
)
goto
cleanup
;
/* Move the data over to where the matching functions can find them */
if
(
dwim_refspecs
(
&
remote
->
active_refspecs
,
&
remote
->
refspecs
,
&
remote
->
refs
)
<
0
)
goto
cleanup
;
*
out
=
remote
;
cleanup:
...
...
@@ -613,11 +620,11 @@ on_error:
return
-
1
;
}
int
git_remote_ls
(
git_remote
*
remote
,
git_headlist_cb
list_cb
,
void
*
payload
)
int
git_remote_ls
(
const
git_remote_head
***
out
,
size_t
*
size
,
git_remote
*
remote
)
{
assert
(
remote
);
return
remote
->
transport
->
ls
(
remote
->
transport
,
list_cb
,
payload
);
return
remote
->
transport
->
ls
(
out
,
size
,
remote
->
transport
);
}
int
git_remote__get_http_proxy
(
git_remote
*
remote
,
bool
use_ssl
,
char
**
proxy_url
)
...
...
@@ -677,67 +684,31 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur
return
0
;
}
static
int
store_refs
(
git_remote_head
*
head
,
void
*
payload
)
{
git_vector
*
refs
=
(
git_vector
*
)
payload
;
return
git_vector_insert
(
refs
,
head
);
}
static
int
dwim_refspecs
(
git_vector
*
refspecs
,
git_vector
*
refs
)
/* DWIM `refspecs` based on `refs` and append the output to `out` */
static
int
dwim_refspecs
(
git_vector
*
out
,
git_vector
*
refspecs
,
git_vector
*
refs
)
{
git_buf
buf
=
GIT_BUF_INIT
;
size_t
i
;
git_refspec
*
spec
;
size_t
i
,
j
,
pos
;
git_remote_head
key
;
const
char
*
formatters
[]
=
{
GIT_REFS_DIR
"%s"
,
GIT_REFS_TAGS_DIR
"%s"
,
GIT_REFS_HEADS_DIR
"%s"
,
NULL
};
git_vector_foreach
(
refspecs
,
i
,
spec
)
{
if
(
spec
->
dwim
)
continue
;
/* shorthand on the lhs */
if
(
git__prefixcmp
(
spec
->
src
,
GIT_REFS_DIR
))
{
for
(
j
=
0
;
formatters
[
j
];
j
++
)
{
git_buf_clear
(
&
buf
);
if
(
git_buf_printf
(
&
buf
,
formatters
[
j
],
spec
->
src
)
<
0
)
return
-
1
;
key
.
name
=
(
char
*
)
git_buf_cstr
(
&
buf
);
if
(
!
git_vector_search
(
&
pos
,
refs
,
&
key
))
{
/* we found something to match the shorthand, set src to that */
git__free
(
spec
->
src
);
spec
->
src
=
git_buf_detach
(
&
buf
);
}
}
}
if
(
spec
->
dst
&&
git__prefixcmp
(
spec
->
dst
,
GIT_REFS_DIR
))
{
/* if it starts with "remotes" then we just prepend "refs/" */
if
(
!
git__prefixcmp
(
spec
->
dst
,
"remotes/"
))
{
git_buf_puts
(
&
buf
,
GIT_REFS_DIR
);
}
else
{
git_buf_puts
(
&
buf
,
GIT_REFS_HEADS_DIR
);
}
if
(
git_refspec__dwim_one
(
out
,
spec
,
refs
)
<
0
)
return
-
1
;
}
if
(
git_buf_puts
(
&
buf
,
spec
->
dst
)
<
0
)
return
-
1
;
return
0
;
}
git__free
(
spec
->
dst
);
spec
->
dst
=
git_buf_detach
(
&
buf
);
}
static
void
free_refspecs
(
git_vector
*
vec
)
{
size_t
i
;
git_refspec
*
spec
;
spec
->
dwim
=
1
;
git_vector_foreach
(
vec
,
i
,
spec
)
{
git_refspec__free
(
spec
);
git__free
(
spec
);
}
git_buf_free
(
&
buf
);
return
0
;
git_vector_clear
(
vec
);
}
static
int
remote_head_cmp
(
const
void
*
_a
,
const
void
*
_b
)
...
...
@@ -748,6 +719,25 @@ static int remote_head_cmp(const void *_a, const void *_b)
return
git__strcmp_cb
(
a
->
name
,
b
->
name
);
}
static
int
ls_to_vector
(
git_vector
*
out
,
git_remote
*
remote
)
{
git_remote_head
**
heads
;
size_t
heads_len
,
i
;
if
(
git_remote_ls
((
const
git_remote_head
***
)
&
heads
,
&
heads_len
,
remote
)
<
0
)
return
-
1
;
if
(
git_vector_init
(
out
,
heads_len
,
remote_head_cmp
)
<
0
)
return
-
1
;
for
(
i
=
0
;
i
<
heads_len
;
i
++
)
{
if
(
git_vector_insert
(
out
,
heads
[
i
])
<
0
)
return
-
1
;
}
return
0
;
}
int
git_remote_download
(
git_remote
*
remote
)
{
int
error
;
...
...
@@ -755,15 +745,14 @@ int git_remote_download(git_remote *remote)
assert
(
remote
);
if
(
git_vector_init
(
&
refs
,
16
,
remote_head_cmp
)
<
0
)
if
(
ls_to_vector
(
&
refs
,
remote
)
<
0
)
return
-
1
;
if
(
git_remote_ls
(
remote
,
store_refs
,
&
refs
)
<
0
)
{
return
-
1
;
}
free_refspecs
(
&
remote
->
active_refspecs
);
error
=
dwim_refspecs
(
&
remote
->
refspecs
,
&
refs
);
error
=
dwim_refspecs
(
&
remote
->
active_refspecs
,
&
remote
->
refspecs
,
&
refs
);
git_vector_free
(
&
refs
);
if
(
error
<
0
)
return
-
1
;
...
...
@@ -1013,10 +1002,8 @@ int git_remote_update_tips(git_remote *remote)
if
(
git_refspec__parse
(
&
tagspec
,
GIT_REFSPEC_TAGS
,
true
)
<
0
)
return
-
1
;
if
(
git_vector_init
(
&
refs
,
16
,
NULL
)
<
0
)
return
-
1
;
if
((
error
=
git_remote_ls
(
remote
,
store_refs
,
&
refs
))
<
0
)
if
((
error
=
ls_to_vector
(
&
refs
,
remote
))
<
0
)
goto
out
;
if
(
remote
->
download_tags
==
GIT_REMOTE_DOWNLOAD_TAGS_ALL
)
{
...
...
@@ -1024,7 +1011,7 @@ int git_remote_update_tips(git_remote *remote)
goto
out
;
}
git_vector_foreach
(
&
remote
->
refspecs
,
i
,
spec
)
{
git_vector_foreach
(
&
remote
->
active_
refspecs
,
i
,
spec
)
{
if
(
spec
->
push
)
continue
;
...
...
@@ -1033,8 +1020,8 @@ int git_remote_update_tips(git_remote *remote)
}
out:
git_refspec__free
(
&
tagspec
);
git_vector_free
(
&
refs
);
git_refspec__free
(
&
tagspec
);
return
error
;
}
...
...
@@ -1067,9 +1054,6 @@ void git_remote_disconnect(git_remote *remote)
void
git_remote_free
(
git_remote
*
remote
)
{
git_refspec
*
spec
;
size_t
i
;
if
(
remote
==
NULL
)
return
;
...
...
@@ -1082,12 +1066,12 @@ void git_remote_free(git_remote *remote)
git_vector_free
(
&
remote
->
refs
);
git_vector_foreach
(
&
remote
->
refspecs
,
i
,
spec
)
{
git_refspec__free
(
spec
);
git__free
(
spec
);
}
free_refspecs
(
&
remote
->
refspecs
);
git_vector_free
(
&
remote
->
refspecs
);
free_refspecs
(
&
remote
->
active_refspecs
);
git_vector_free
(
&
remote
->
active_refspecs
);
git__free
(
remote
->
url
);
git__free
(
remote
->
pushurl
);
git__free
(
remote
->
name
);
...
...
@@ -1496,7 +1480,7 @@ git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refnam
git_refspec
*
spec
;
size_t
i
;
git_vector_foreach
(
&
remote
->
refspecs
,
i
,
spec
)
{
git_vector_foreach
(
&
remote
->
active_
refspecs
,
i
,
spec
)
{
if
(
spec
->
push
)
continue
;
...
...
@@ -1512,7 +1496,7 @@ git_refspec *git_remote__matching_dst_refspec(git_remote *remote, const char *re
git_refspec
*
spec
;
size_t
i
;
git_vector_foreach
(
&
remote
->
refspecs
,
i
,
spec
)
{
git_vector_foreach
(
&
remote
->
active_
refspecs
,
i
,
spec
)
{
if
(
spec
->
push
)
continue
;
...
...
@@ -1535,14 +1519,68 @@ void git_remote_clear_refspecs(git_remote *remote)
git_vector_clear
(
&
remote
->
refspecs
);
}
static
int
add_and_dwim
(
git_remote
*
remote
,
const
char
*
str
,
int
push
)
{
git_refspec
*
spec
;
git_vector
*
vec
;
if
(
add_refspec
(
remote
,
str
,
!
push
)
<
0
)
return
-
1
;
vec
=
&
remote
->
refspecs
;
spec
=
git_vector_get
(
vec
,
vec
->
length
-
1
);
return
git_refspec__dwim_one
(
&
remote
->
active_refspecs
,
spec
,
&
remote
->
refs
);
}
int
git_remote_add_fetch
(
git_remote
*
remote
,
const
char
*
refspec
)
{
return
add_
refspec
(
remote
,
refspec
,
tru
e
);
return
add_
and_dwim
(
remote
,
refspec
,
fals
e
);
}
int
git_remote_add_push
(
git_remote
*
remote
,
const
char
*
refspec
)
{
return
add_refspec
(
remote
,
refspec
,
false
);
return
add_and_dwim
(
remote
,
refspec
,
true
);
}
static
int
set_refspecs
(
git_remote
*
remote
,
git_strarray
*
array
,
int
push
)
{
git_vector
*
vec
=
&
remote
->
refspecs
;
git_refspec
*
spec
;
size_t
i
;
/* Start by removing any refspecs of the same type */
for
(
i
=
0
;
i
<
vec
->
length
;
i
++
)
{
spec
=
git_vector_get
(
vec
,
i
);
if
(
spec
->
push
!=
push
)
continue
;
git_refspec__free
(
spec
);
git__free
(
spec
);
git_vector_remove
(
vec
,
i
);
i
--
;
}
/* And now we add the new ones */
for
(
i
=
0
;
i
<
array
->
count
;
i
++
)
{
if
(
add_refspec
(
remote
,
array
->
strings
[
i
],
!
push
)
<
0
)
return
-
1
;
}
free_refspecs
(
&
remote
->
active_refspecs
);
git_vector_clear
(
&
remote
->
active_refspecs
);
return
dwim_refspecs
(
&
remote
->
active_refspecs
,
&
remote
->
refspecs
,
&
remote
->
refs
);
}
int
git_remote_set_fetch_refspecs
(
git_remote
*
remote
,
git_strarray
*
array
)
{
return
set_refspecs
(
remote
,
array
,
false
);
}
int
git_remote_set_push_refspecs
(
git_remote
*
remote
,
git_strarray
*
array
)
{
return
set_refspecs
(
remote
,
array
,
true
);
}
static
int
copy_refspecs
(
git_strarray
*
array
,
git_remote
*
remote
,
unsigned
int
push
)
...
...
@@ -1600,18 +1638,3 @@ const git_refspec *git_remote_get_refspec(git_remote *remote, size_t n)
{
return
git_vector_get
(
&
remote
->
refspecs
,
n
);
}
int
git_remote_remove_refspec
(
git_remote
*
remote
,
size_t
n
)
{
git_refspec
*
spec
;
assert
(
remote
);
spec
=
git_vector_get
(
&
remote
->
refspecs
,
n
);
if
(
spec
)
{
git_refspec__free
(
spec
);
git__free
(
spec
);
}
return
git_vector_remove
(
&
remote
->
refspecs
,
n
);
}
src/remote.h
View file @
6414fd33
...
...
@@ -21,6 +21,7 @@ struct git_remote {
char
*
pushurl
;
git_vector
refs
;
git_vector
refspecs
;
git_vector
active_refspecs
;
git_transport
*
transport
;
git_repository
*
repo
;
git_remote_callbacks
callbacks
;
...
...
src/transports/local.c
View file @
6414fd33
...
...
@@ -213,21 +213,17 @@ static int local_connect(
return
0
;
}
static
int
local_ls
(
git_transport
*
transport
,
git_headlist_cb
list_cb
,
void
*
payload
)
static
int
local_ls
(
const
git_remote_head
***
out
,
size_t
*
size
,
git_transport
*
transport
)
{
transport_local
*
t
=
(
transport_local
*
)
transport
;
unsigned
int
i
;
git_remote_head
*
head
=
NULL
;
if
(
!
t
->
have_refs
)
{
giterr_set
(
GITERR_NET
,
"The transport has not yet loaded the refs"
);
return
-
1
;
}
git_vector_foreach
(
&
t
->
refs
,
i
,
head
)
{
if
(
list_cb
(
head
,
payload
))
return
GIT_EUSER
;
}
*
out
=
(
const
git_remote_head
**
)
t
->
refs
.
contents
;
*
size
=
t
->
refs
.
length
;
return
0
;
}
...
...
src/transports/smart.c
View file @
6414fd33
...
...
@@ -63,6 +63,24 @@ static int git_smart__set_callbacks(
return
0
;
}
int
git_smart__update_heads
(
transport_smart
*
t
)
{
size_t
i
;
git_pkt
*
pkt
;
git_vector_clear
(
&
t
->
heads
);
git_vector_foreach
(
&
t
->
refs
,
i
,
pkt
)
{
git_pkt_ref
*
ref
=
(
git_pkt_ref
*
)
pkt
;
if
(
pkt
->
type
!=
GIT_PKT_REF
)
continue
;
if
(
git_vector_insert
(
&
t
->
heads
,
&
ref
->
head
)
<
0
)
return
-
1
;
}
return
0
;
}
static
int
git_smart__connect
(
git_transport
*
transport
,
const
char
*
url
,
...
...
@@ -140,6 +158,9 @@ static int git_smart__connect(
git_pkt_free
((
git_pkt
*
)
first
);
}
/* Keep a list of heads for _ls */
git_smart__update_heads
(
t
);
if
(
t
->
rpc
&&
git_smart__reset_stream
(
t
,
false
)
<
0
)
return
-
1
;
...
...
@@ -149,28 +170,17 @@ static int git_smart__connect(
return
0
;
}
static
int
git_smart__ls
(
git_transport
*
transport
,
git_headlist_cb
list_cb
,
void
*
payload
)
static
int
git_smart__ls
(
const
git_remote_head
***
out
,
size_t
*
size
,
git_transport
*
transport
)
{
transport_smart
*
t
=
(
transport_smart
*
)
transport
;
unsigned
int
i
;
git_pkt
*
p
=
NULL
;
if
(
!
t
->
have_refs
)
{
giterr_set
(
GITERR_NET
,
"The transport has not yet loaded the refs"
);
return
-
1
;
}
git_vector_foreach
(
&
t
->
refs
,
i
,
p
)
{
git_pkt_ref
*
pkt
=
NULL
;
if
(
p
->
type
!=
GIT_PKT_REF
)
continue
;
pkt
=
(
git_pkt_ref
*
)
p
;
if
(
list_cb
(
&
pkt
->
head
,
payload
))
return
GIT_EUSER
;
}
*
out
=
(
const
git_remote_head
**
)
t
->
heads
.
contents
;
*
size
=
t
->
heads
.
length
;
return
0
;
}
...
...
@@ -293,6 +303,7 @@ static void git_smart__free(git_transport *transport)
/* Free the subtransport */
t
->
wrapped
->
free
(
t
->
wrapped
);
git_vector_free
(
&
t
->
heads
);
git_vector_foreach
(
refs
,
i
,
p
)
git_pkt_free
(
p
);
...
...
@@ -340,6 +351,11 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
return
-
1
;
}
if
(
git_vector_init
(
&
t
->
heads
,
16
,
ref_name_cmp
)
<
0
)
{
git__free
(
t
);
return
-
1
;
}
if
(
definition
->
callback
(
&
t
->
wrapped
,
&
t
->
parent
)
<
0
)
{
git__free
(
t
);
return
-
1
;
...
...
src/transports/smart.h
View file @
6414fd33
...
...
@@ -140,6 +140,7 @@ typedef struct {
git_smart_subtransport_stream
*
current_stream
;
transport_smart_caps
caps
;
git_vector
refs
;
git_vector
heads
;
git_vector
common
;
git_atomic
cancelled
;
packetsize_cb
packetsize_cb
;
...
...
@@ -173,6 +174,8 @@ int git_smart__download_pack(
int
git_smart__negotiation_step
(
git_transport
*
transport
,
void
*
data
,
size_t
len
);
int
git_smart__get_push_stream
(
transport_smart
*
t
,
git_smart_subtransport_stream
**
out
);
int
git_smart__update_heads
(
transport_smart
*
t
);
/* smart_pkt.c */
int
git_pkt_parse_line
(
git_pkt
**
head
,
const
char
*
line
,
const
char
**
out
,
size_t
len
);
int
git_pkt_buffer_flush
(
git_buf
*
buf
);
...
...
src/transports/smart_protocol.c
View file @
6414fd33
...
...
@@ -269,7 +269,7 @@ 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
*
ref
s
,
size_t
count
)
int
git_smart__negotiate_fetch
(
git_transport
*
transport
,
git_repository
*
repo
,
const
git_remote_head
*
const
*
want
s
,
size_t
count
)
{
transport_smart
*
t
=
(
transport_smart
*
)
transport
;
gitno_buffer
*
buf
=
&
t
->
buffer
;
...
...
@@ -279,19 +279,20 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
unsigned
int
i
;
git_oid
oid
;
/* No own logic, do our thing */
if
((
error
=
git_pkt_buffer_wants
(
refs
,
count
,
&
t
->
caps
,
&
data
))
<
0
)
if
((
error
=
git_pkt_buffer_wants
(
wants
,
count
,
&
t
->
caps
,
&
data
))
<
0
)
return
error
;
if
((
error
=
fetch_setup_walk
(
&
walk
,
repo
))
<
0
)
goto
on_error
;
/*
* We don't support any kind of ACK extensions, so the negotiation
* boils down to sending what we have and listening for an ACK
* every once in a while.
* Our support for ACK extensions is simply to parse them. On
* the first ACK we will accept that as enough common
* objects. We give up if we haven't found an answer in the
* first 256 we send.
*/
i
=
0
;
while
(
true
)
{
while
(
i
<
256
)
{
error
=
git_revwalk_next
(
&
oid
,
walk
);
if
(
error
<
0
)
{
...
...
@@ -349,7 +350,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
git_pkt_ack
*
pkt
;
unsigned
int
i
;
if
((
error
=
git_pkt_buffer_wants
(
ref
s
,
count
,
&
t
->
caps
,
&
data
))
<
0
)
if
((
error
=
git_pkt_buffer_wants
(
want
s
,
count
,
&
t
->
caps
,
&
data
))
<
0
)
goto
on_error
;
git_vector_foreach
(
&
t
->
common
,
i
,
pkt
)
{
...
...
@@ -369,7 +370,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
git_pkt_ack
*
pkt
;
unsigned
int
i
;
if
((
error
=
git_pkt_buffer_wants
(
ref
s
,
count
,
&
t
->
caps
,
&
data
))
<
0
)
if
((
error
=
git_pkt_buffer_wants
(
want
s
,
count
,
&
t
->
caps
,
&
data
))
<
0
)
goto
on_error
;
git_vector_foreach
(
&
t
->
common
,
i
,
pkt
)
{
...
...
@@ -943,8 +944,13 @@ int git_smart__push(git_transport *transport, git_push *push)
push
->
transfer_progress_cb
(
push
->
pb
->
nr_written
,
push
->
pb
->
nr_objects
,
packbuilder_payload
.
last_bytes
,
push
->
transfer_progress_cb_payload
);
}
if
(
push
->
status
.
length
)
if
(
push
->
status
.
length
)
{
error
=
update_refs_from_report
(
&
t
->
refs
,
&
push
->
specs
,
&
push
->
status
);
if
(
error
<
0
)
goto
done
;
error
=
git_smart__update_heads
(
t
);
}
done:
git_buf_free
(
&
pktline
);
...
...
tests-clar/network/remote/local.c
View file @
6414fd33
...
...
@@ -26,26 +26,6 @@ void test_network_remote_local__cleanup(void)
cl_fixture_cleanup
(
"remotelocal"
);
}
static
int
count_ref__cb
(
git_remote_head
*
head
,
void
*
payload
)
{
int
*
count
=
(
int
*
)
payload
;
(
void
)
head
;
(
*
count
)
++
;
return
0
;
}
static
int
ensure_peeled__cb
(
git_remote_head
*
head
,
void
*
payload
)
{
GIT_UNUSED
(
payload
);
if
(
strcmp
(
head
->
name
,
"refs/tags/test^{}"
)
!=
0
)
return
0
;
return
git_oid_streq
(
&
head
->
oid
,
"e90810b8df3e80c413d903f631643c716887138d"
);
}
static
void
connect_to_local_repository
(
const
char
*
local_repository
)
{
git_buf_sets
(
&
file_path_buf
,
cl_git_path_url
(
local_repository
));
...
...
@@ -65,39 +45,42 @@ void test_network_remote_local__connected(void)
void
test_network_remote_local__retrieve_advertised_references
(
void
)
{
int
how_many_refs
=
0
;
const
git_remote_head
**
refs
;
size_t
refs_len
;
connect_to_local_repository
(
cl_fixture
(
"testrepo.git"
));
cl_git_pass
(
git_remote_ls
(
remote
,
&
count_ref__cb
,
&
how_many_refs
));
cl_git_pass
(
git_remote_ls
(
&
refs
,
&
refs_len
,
remote
));
cl_assert_equal_i
(
how_many_refs
,
28
);
cl_assert_equal_i
(
refs_len
,
28
);
}
void
test_network_remote_local__retrieve_advertised_references_after_disconnect
(
void
)
{
int
how_many_refs
=
0
;
const
git_remote_head
**
refs
;
size_t
refs_len
;
connect_to_local_repository
(
cl_fixture
(
"testrepo.git"
));
git_remote_disconnect
(
remote
);
cl_git_pass
(
git_remote_ls
(
remote
,
&
count_ref__cb
,
&
how_many_refs
));
cl_git_pass
(
git_remote_ls
(
&
refs
,
&
refs_len
,
remote
));
cl_assert_equal_i
(
how_many_refs
,
28
);
cl_assert_equal_i
(
refs_len
,
28
);
}
void
test_network_remote_local__retrieve_advertised_references_from_spaced_repository
(
void
)
{
int
how_many_refs
=
0
;
const
git_remote_head
**
refs
;
size_t
refs_len
;
cl_fixture_sandbox
(
"testrepo.git"
);
cl_git_pass
(
p_rename
(
"testrepo.git"
,
"spaced testrepo.git"
));
connect_to_local_repository
(
"spaced testrepo.git"
);
cl_git_pass
(
git_remote_ls
(
remote
,
&
count_ref__cb
,
&
how_many_refs
));
cl_git_pass
(
git_remote_ls
(
&
refs
,
&
refs_len
,
remote
));
cl_assert_equal_i
(
how_many_refs
,
28
);
cl_assert_equal_i
(
refs_len
,
28
);
git_remote_free
(
remote
);
/* Disconnect from the "spaced repo" before the cleanup */
remote
=
NULL
;
...
...
@@ -107,9 +90,17 @@ void test_network_remote_local__retrieve_advertised_references_from_spaced_repos
void
test_network_remote_local__nested_tags_are_completely_peeled
(
void
)
{
const
git_remote_head
**
refs
;
size_t
refs_len
,
i
;
connect_to_local_repository
(
cl_fixture
(
"testrepo.git"
));
cl_git_pass
(
git_remote_ls
(
remote
,
&
ensure_peeled__cb
,
NULL
));
cl_git_pass
(
git_remote_ls
(
&
refs
,
&
refs_len
,
remote
));
for
(
i
=
0
;
i
<
refs_len
;
i
++
)
{
if
(
!
strcmp
(
refs
[
i
]
->
name
,
"refs/tags/test^{}"
))
cl_git_pass
(
git_oid_streq
(
&
refs
[
i
]
->
oid
,
"e90810b8df3e80c413d903f631643c716887138d"
));
}
}
void
test_network_remote_local__shorthand_fetch_refspec0
(
void
)
...
...
tests-clar/online/fetch.c
View file @
6414fd33
...
...
@@ -152,29 +152,20 @@ void test_online_fetch__can_cancel(void)
git_remote_free
(
remote
);
}
int
ls_cb
(
git_remote_head
*
rhead
,
void
*
payload
)
{
int
*
nr
=
payload
;
GIT_UNUSED
(
rhead
);
(
*
nr
)
++
;
return
0
;
}
void
test_online_fetch__ls_disconnected
(
void
)
{
const
git_remote_head
**
refs
;
size_t
refs_len_before
,
refs_len_after
;
git_remote
*
remote
;
int
nr_before
=
0
,
nr_after
=
0
;
cl_git_pass
(
git_remote_create
(
&
remote
,
_repo
,
"test"
,
"http://github.com/libgit2/TestGitRepository.git"
));
cl_git_pass
(
git_remote_connect
(
remote
,
GIT_DIRECTION_FETCH
));
cl_git_pass
(
git_remote_ls
(
remote
,
ls_cb
,
&
nr_befor
e
));
cl_git_pass
(
git_remote_ls
(
&
refs
,
&
refs_len_before
,
remot
e
));
git_remote_disconnect
(
remote
);
cl_git_pass
(
git_remote_ls
(
remote
,
ls_cb
,
&
nr_after
));
cl_git_pass
(
git_remote_ls
(
&
refs
,
&
refs_len_after
,
remote
));
cl_assert_equal_i
(
nr_before
,
nr
_after
);
cl_assert_equal_i
(
refs_len_before
,
refs_len
_after
);
git_remote_free
(
remote
);
}
tests-clar/online/push.c
View file @
6414fd33
...
...
@@ -155,12 +155,11 @@ static void do_verify_push_status(git_push *push, const push_status expected[],
*/
static
void
verify_refs
(
git_remote
*
remote
,
expected_ref
expected_refs
[],
size_t
expected_refs_len
)
{
git_vector
actual_refs
=
GIT_VECTOR_INIT
;
git_remote_ls
(
remote
,
record_ref_cb
,
&
actual_refs
);
verify_remote_refs
(
&
actual_refs
,
expected_refs
,
expected_refs_len
);
const
git_remote_head
**
actual_refs
;
size_t
actual_refs_len
;
git_vector_free
(
&
actual_refs
);
git_remote_ls
(
&
actual_refs
,
&
actual_refs_len
,
remote
);
verify_remote_refs
(
actual_refs
,
actual_refs_len
,
expected_refs
,
expected_refs_len
);
}
/**
...
...
@@ -257,7 +256,8 @@ failed:
void
test_online_push__initialize
(
void
)
{
git_vector
delete_specs
=
GIT_VECTOR_INIT
;
size_t
i
;
const
git_remote_head
**
heads
;
size_t
i
,
heads_len
;
char
*
curr_del_spec
;
_repo
=
cl_git_sandbox_init
(
"push_src"
);
...
...
@@ -314,7 +314,8 @@ void test_online_push__initialize(void)
* order to delete the remote branch pointed to by HEAD (usually master).
* See: https://raw.github.com/git/git/master/Documentation/RelNotes/1.7.0.txt
*/
cl_git_pass
(
git_remote_ls
(
_remote
,
delete_ref_cb
,
&
delete_specs
));
cl_git_pass
(
git_remote_ls
(
&
heads
,
&
heads_len
,
_remote
));
cl_git_pass
(
create_deletion_refspecs
(
&
delete_specs
,
heads
,
heads_len
));
if
(
delete_specs
.
length
)
{
git_push
*
push
;
...
...
tests-clar/online/push_util.c
View file @
6414fd33
...
...
@@ -44,20 +44,23 @@ int record_update_tips_cb(const char *refname, const git_oid *a, const git_oid *
return
0
;
}
int
delete_ref_cb
(
git_remote_head
*
head
,
void
*
payload
)
int
create_deletion_refspecs
(
git_vector
*
out
,
const
git_remote_head
**
heads
,
size_t
heads_len
)
{
git_vector
*
delete_specs
=
(
git_vector
*
)
payload
;
git_buf
del_spec
=
GIT_BUF_INIT
;
size_t
i
;
/* Ignore malformed ref names (which also saves us from tag^{} */
if
(
!
git_reference_is_valid_name
(
head
->
name
))
return
0
;
/* Create a refspec that deletes a branch in the remote */
if
(
strcmp
(
head
->
name
,
"refs/heads/master"
))
{
cl_git_pass
(
git_buf_putc
(
&
del_spec
,
':'
));
cl_git_pass
(
git_buf_puts
(
&
del_spec
,
head
->
name
));
cl_git_pass
(
git_vector_insert
(
delete_specs
,
git_buf_detach
(
&
del_spec
)));
for
(
i
=
0
;
i
<
heads_len
;
i
++
)
{
const
git_remote_head
*
head
=
heads
[
i
];
/* Ignore malformed ref names (which also saves us from tag^{} */
if
(
!
git_reference_is_valid_name
(
head
->
name
))
return
0
;
/* Create a refspec that deletes a branch in the remote */
if
(
strcmp
(
head
->
name
,
"refs/heads/master"
))
{
cl_git_pass
(
git_buf_putc
(
&
del_spec
,
':'
));
cl_git_pass
(
git_buf_puts
(
&
del_spec
,
head
->
name
));
cl_git_pass
(
git_vector_insert
(
out
,
git_buf_detach
(
&
del_spec
)));
}
}
return
0
;
...
...
@@ -69,26 +72,28 @@ int record_ref_cb(git_remote_head *head, void *payload)
return
git_vector_insert
(
refs
,
head
);
}
void
verify_remote_refs
(
git_vector
*
actual_refs
,
const
expected_ref
expected_refs
[],
size_t
expected_refs_len
)
void
verify_remote_refs
(
const
git_remote_head
*
actual_refs
[],
size_t
actual_refs_len
,
const
expected_ref
expected_refs
[],
size_t
expected_refs_len
)
{
size_t
i
,
j
=
0
;
git_buf
msg
=
GIT_BUF_INIT
;
git_remote_head
*
actual
;
const
git_remote_head
*
actual
;
char
*
oid_str
;
bool
master_present
=
false
;
/* We don't care whether "master" is present on the other end or not */
git_vector_foreach
(
actual_refs
,
i
,
actual
)
{
for
(
i
=
0
;
i
<
actual_refs_len
;
i
++
)
{
actual
=
actual_refs
[
i
];
if
(
!
strcmp
(
actual
->
name
,
"refs/heads/master"
))
{
master_present
=
true
;
break
;
}
}
if
(
expected_refs_len
+
(
master_present
?
1
:
0
)
!=
actual_refs
->
length
)
if
(
expected_refs_len
+
(
master_present
?
1
:
0
)
!=
actual_refs
_len
)
goto
failed
;
git_vector_foreach
(
actual_refs
,
i
,
actual
)
{
for
(
i
=
0
;
i
<
actual_refs_len
;
i
++
)
{
actual
=
actual_refs
[
i
];
if
(
master_present
&&
!
strcmp
(
actual
->
name
,
"refs/heads/master"
))
continue
;
...
...
@@ -111,7 +116,8 @@ failed:
}
git_buf_puts
(
&
msg
,
"
\n
ACTUAL:
\n
"
);
git_vector_foreach
(
actual_refs
,
i
,
actual
)
{
for
(
i
=
0
;
i
<
actual_refs_len
;
i
++
)
{
actual
=
actual_refs
[
i
];
if
(
master_present
&&
!
strcmp
(
actual
->
name
,
"refs/heads/master"
))
continue
;
...
...
tests-clar/online/push_util.h
View file @
6414fd33
...
...
@@ -41,12 +41,13 @@ void record_callbacks_data_clear(record_callbacks_data *data);
int
record_update_tips_cb
(
const
char
*
refname
,
const
git_oid
*
a
,
const
git_oid
*
b
,
void
*
data
);
/**
* C
allback for git_remote_list that adds refspecs to delete each ref
* C
reate a set of refspecs that deletes each of the inputs
*
* @param head a ref on the remote
* @param payload a git_push instance
* @param out the vector in which to store the refspecs
* @param heads the remote heads
* @param heads_len the size of the array
*/
int
delete_ref_cb
(
git_remote_head
*
head
,
void
*
payload
);
int
create_deletion_refspecs
(
git_vector
*
out
,
const
git_remote_head
**
heads
,
size_t
heads_len
);
/**
* Callback for git_remote_list that adds refspecs to vector
...
...
@@ -60,10 +61,11 @@ int record_ref_cb(git_remote_head *head, void *payload);
* Verifies that refs on remote stored by record_ref_cb match the expected
* names, oids, and order.
*
* @param actual_refs actual refs stored by record_ref_cb()
* @param actual_refs actual refs in the remote
* @param actual_refs_len length of actual_refs
* @param expected_refs expected remote refs
* @param expected_refs_len length of expected_refs
*/
void
verify_remote_refs
(
git_vector
*
actual_refs
,
const
expected_ref
expected_refs
[],
size_t
expected_refs_len
);
void
verify_remote_refs
(
const
git_remote_head
*
actual_refs
[],
size_t
actual_refs_len
,
const
expected_ref
expected_refs
[],
size_t
expected_refs_len
);
#endif
/* INCLUDE_cl_push_util_h__ */
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