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
df93a681
Commit
df93a681
authored
Feb 08, 2013
by
Philip Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge the push report into the refs to avoid a 3rd network call
parent
ff9df883
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
130 additions
and
20 deletions
+130
-20
src/push.c
+16
-2
src/transports/smart.c
+8
-1
src/transports/smart_protocol.c
+105
-16
src/vector.h
+1
-1
No files found.
src/push.c
View file @
df93a681
...
...
@@ -14,6 +14,20 @@
#include "vector.h"
#include "push.h"
static
int
push_spec_rref_cmp
(
const
void
*
a
,
const
void
*
b
)
{
const
push_spec
*
push_spec_a
=
a
,
*
push_spec_b
=
b
;
return
strcmp
(
push_spec_a
->
rref
,
push_spec_b
->
rref
);
}
static
int
push_status_ref_cmp
(
const
void
*
a
,
const
void
*
b
)
{
const
push_status
*
push_status_a
=
a
,
*
push_status_b
=
b
;
return
strcmp
(
push_status_a
->
ref
,
push_status_b
->
ref
);
}
int
git_push_new
(
git_push
**
out
,
git_remote
*
remote
)
{
git_push
*
p
;
...
...
@@ -27,12 +41,12 @@ int git_push_new(git_push **out, git_remote *remote)
p
->
remote
=
remote
;
p
->
report_status
=
1
;
if
(
git_vector_init
(
&
p
->
specs
,
0
,
NULL
)
<
0
)
{
if
(
git_vector_init
(
&
p
->
specs
,
0
,
push_spec_rref_cmp
)
<
0
)
{
git__free
(
p
);
return
-
1
;
}
if
(
git_vector_init
(
&
p
->
status
,
0
,
NULL
)
<
0
)
{
if
(
git_vector_init
(
&
p
->
status
,
0
,
push_status_ref_cmp
)
<
0
)
{
git_vector_free
(
&
p
->
specs
);
git__free
(
p
);
return
-
1
;
...
...
src/transports/smart.c
View file @
df93a681
...
...
@@ -294,6 +294,13 @@ static void git_smart__free(git_transport *transport)
git__free
(
t
);
}
static
int
ref_name_cmp
(
const
void
*
a
,
const
void
*
b
)
{
const
git_pkt_ref
*
ref_a
=
a
,
*
ref_b
=
b
;
return
strcmp
(
ref_a
->
head
.
name
,
ref_b
->
head
.
name
);
}
int
git_transport_smart
(
git_transport
**
out
,
git_remote
*
owner
,
void
*
param
)
{
transport_smart
*
t
;
...
...
@@ -321,7 +328,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
t
->
owner
=
owner
;
t
->
rpc
=
definition
->
rpc
;
if
(
git_vector_init
(
&
t
->
refs
,
16
,
NULL
)
<
0
)
{
if
(
git_vector_init
(
&
t
->
refs
,
16
,
ref_name_cmp
)
<
0
)
{
git__free
(
t
);
return
-
1
;
}
...
...
src/transports/smart_protocol.c
View file @
df93a681
...
...
@@ -628,6 +628,108 @@ static int parse_report(gitno_buffer *buf, git_push *push)
}
}
static
int
add_ref_from_push_spec
(
git_vector
*
refs
,
push_spec
*
push_spec
)
{
git_pkt_ref
*
added
=
git__calloc
(
1
,
sizeof
(
git_pkt_ref
));
GITERR_CHECK_ALLOC
(
added
);
added
->
type
=
GIT_PKT_REF
;
git_oid_cpy
(
&
added
->
head
.
oid
,
&
push_spec
->
loid
);
added
->
head
.
name
=
git__strdup
(
push_spec
->
rref
);
if
(
!
added
->
head
.
name
||
git_vector_insert
(
refs
,
added
)
<
0
)
{
git_pkt_free
((
git_pkt
*
)
added
);
return
-
1
;
}
return
0
;
}
static
int
update_refs_from_report
(
git_vector
*
refs
,
git_vector
*
push_specs
,
git_vector
*
push_report
)
{
git_pkt_ref
*
ref
;
push_spec
*
push_spec
;
push_status
*
push_status
;
size_t
i
,
j
,
refs_len
;
int
cmp
;
/* For each push spec we sent to the server, we should have
* gotten back a status packet in the push report */
if
(
push_specs
->
length
!=
push_report
->
length
)
{
giterr_set
(
GITERR_NET
,
"report-status: protocol error"
);
return
-
1
;
}
/* We require that push_specs be sorted with push_spec_rref_cmp,
* and that push_report be sorted with push_status_ref_cmp */
git_vector_sort
(
push_specs
);
git_vector_sort
(
push_report
);
git_vector_foreach
(
push_specs
,
i
,
push_spec
)
{
push_status
=
git_vector_get
(
push_report
,
i
);
/* For each push spec we sent to the server, we should have
* gotten back a status packet in the push report which matches */
if
(
strcmp
(
push_spec
->
rref
,
push_status
->
ref
))
{
giterr_set
(
GITERR_NET
,
"report-status: protocol error"
);
return
-
1
;
}
}
/* We require that refs be sorted with ref_name_cmp */
git_vector_sort
(
refs
);
i
=
j
=
0
;
refs_len
=
refs
->
length
;
/* Merge join push_specs with refs */
while
(
i
<
push_specs
->
length
&&
j
<
refs_len
)
{
push_spec
=
git_vector_get
(
push_specs
,
i
);
ref
=
git_vector_get
(
refs
,
j
);
cmp
=
strcmp
(
push_spec
->
rref
,
ref
->
head
.
name
);
/* Iterate appropriately */
if
(
cmp
<=
0
)
i
++
;
if
(
cmp
>=
0
)
j
++
;
/* Add case */
if
(
cmp
<
0
&&
!
push_status
->
msg
&&
add_ref_from_push_spec
(
refs
,
push_spec
)
<
0
)
return
-
1
;
/* Update case, delete case */
if
(
cmp
==
0
&&
!
push_status
->
msg
)
git_oid_cpy
(
&
ref
->
head
.
oid
,
&
push_spec
->
loid
);
}
for
(;
i
<
push_specs
->
length
;
i
++
)
{
push_spec
=
git_vector_get
(
push_specs
,
i
);
/* Add case */
if
(
!
push_status
->
msg
&&
add_ref_from_push_spec
(
refs
,
push_spec
)
<
0
)
return
-
1
;
}
/* Remove any refs which we updated to have a zero OID. */
git_vector_rforeach
(
refs
,
i
,
ref
)
{
if
(
git_oid_iszero
(
&
ref
->
head
.
oid
))
{
git_vector_remove
(
refs
,
i
);
git_pkt_free
((
git_pkt
*
)
ref
);
}
}
git_vector_sort
(
refs
);
return
0
;
}
static
int
stream_thunk
(
void
*
buf
,
size_t
size
,
void
*
data
)
{
git_smart_subtransport_stream
*
s
=
(
git_smart_subtransport_stream
*
)
data
;
...
...
@@ -640,7 +742,6 @@ int git_smart__push(git_transport *transport, git_push *push)
transport_smart
*
t
=
(
transport_smart
*
)
transport
;
git_smart_subtransport_stream
*
s
;
git_buf
pktline
=
GIT_BUF_INIT
;
char
*
url
=
NULL
;
int
error
=
-
1
;
#ifdef PUSH_DEBUG
...
...
@@ -678,25 +779,13 @@ int git_smart__push(git_transport *transport, git_push *push)
else
if
(
parse_report
(
&
t
->
buffer
,
push
)
<
0
)
goto
on_error
;
/* If we updated at least one ref, then we need to re-acquire the list of
* refs so the caller can call git_remote_update_tips afterward. TODO: Use
* the data from the push report to do this without another network call */
if
(
push
->
specs
.
length
)
{
git_cred_acquire_cb
cred_cb
=
t
->
cred_acquire_cb
;
void
*
cred_payload
=
t
->
cred_acquire_payload
;
int
flags
=
t
->
flags
;
url
=
git__strdup
(
t
->
url
);
if
(
!
url
||
t
->
parent
.
close
(
&
t
->
parent
)
<
0
||
t
->
parent
.
connect
(
&
t
->
parent
,
url
,
cred_cb
,
cred_payload
,
GIT_DIRECTION_PUSH
,
flags
))
goto
on_error
;
}
if
(
push
->
status
.
length
&&
update_refs_from_report
(
&
t
->
refs
,
&
push
->
specs
,
&
push
->
status
)
<
0
)
goto
on_error
;
error
=
0
;
on_error:
git__free
(
url
);
git_buf_free
(
&
pktline
);
return
error
;
...
...
src/vector.h
View file @
df93a681
...
...
@@ -64,7 +64,7 @@ GIT_INLINE(void *) git_vector_last(const git_vector *v)
for ((iter) = 0; (iter) < (v)->length && ((elem) = (v)->contents[(iter)], 1); (iter)++ )
#define git_vector_rforeach(v, iter, elem) \
for ((iter) = (v)->length
; (iter) > 0 && ((elem) = (v)->contents[(iter)-1
], 1); (iter)-- )
for ((iter) = (v)->length
- 1; (iter) < SIZE_MAX && ((elem) = (v)->contents[(iter)
], 1); (iter)-- )
int
git_vector_insert
(
git_vector
*
v
,
void
*
element
);
int
git_vector_insert_sorted
(
git_vector
*
v
,
void
*
element
,
...
...
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