rugged 0.17.0.b7 → 0.18.0.b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +1 -1
- data/README.md +88 -32
- data/ext/rugged/extconf.rb +4 -2
- data/ext/rugged/rugged.c +72 -10
- data/ext/rugged/rugged.h +14 -10
- data/ext/rugged/rugged_blob.c +8 -10
- data/ext/rugged/rugged_branch.c +11 -14
- data/ext/rugged/rugged_commit.c +31 -24
- data/ext/rugged/rugged_config.c +2 -2
- data/ext/rugged/rugged_index.c +133 -198
- data/ext/rugged/rugged_note.c +372 -0
- data/ext/rugged/rugged_object.c +50 -22
- data/ext/rugged/rugged_reference.c +122 -130
- data/ext/rugged/rugged_remote.c +72 -29
- data/ext/rugged/rugged_repo.c +402 -20
- data/ext/rugged/rugged_revwalk.c +7 -3
- data/ext/rugged/rugged_settings.c +110 -0
- data/ext/rugged/rugged_signature.c +23 -7
- data/ext/rugged/rugged_tag.c +32 -16
- data/ext/rugged/rugged_tree.c +44 -15
- data/lib/rugged.rb +1 -0
- data/lib/rugged/index.rb +8 -0
- data/lib/rugged/remote.rb +13 -0
- data/lib/rugged/repository.rb +3 -3
- data/lib/rugged/version.rb +1 -1
- data/test/blob_test.rb +13 -15
- data/test/branch_test.rb +32 -67
- data/test/commit_test.rb +50 -12
- data/test/config_test.rb +12 -11
- data/test/coverage/HEAD.json +1 -1
- data/test/coverage/cover.rb +40 -21
- data/test/errors_test.rb +34 -0
- data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
- data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
- data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
- data/test/fixtures/testrepo.git/logs/refs/notes/commits +1 -0
- data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +1 -0
- data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
- data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +1 -0
- data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
- data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
- data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +3 -0
- data/test/fixtures/testrepo.git/refs/notes/commits +1 -0
- data/test/index_test.rb +65 -69
- data/test/lib_test.rb +76 -11
- data/test/note_test.rb +158 -0
- data/test/object_test.rb +8 -11
- data/test/reference_test.rb +77 -85
- data/test/remote_test.rb +86 -8
- data/test/repo_pack_test.rb +9 -7
- data/test/repo_reset_test.rb +80 -0
- data/test/repo_test.rb +176 -53
- data/test/tag_test.rb +44 -7
- data/test/test_helper.rb +63 -35
- data/test/tree_test.rb +34 -13
- data/test/walker_test.rb +14 -14
- data/vendor/libgit2/Makefile.embed +1 -1
- data/vendor/libgit2/deps/http-parser/http_parser.c +974 -578
- data/vendor/libgit2/deps/http-parser/http_parser.h +106 -70
- data/vendor/libgit2/deps/regex/regcomp.c +7 -6
- data/vendor/libgit2/deps/regex/regex_internal.c +1 -1
- data/vendor/libgit2/deps/regex/regex_internal.h +12 -3
- data/vendor/libgit2/deps/regex/regexec.c +5 -5
- data/vendor/libgit2/include/git2.h +5 -1
- data/vendor/libgit2/include/git2/attr.h +4 -2
- data/vendor/libgit2/include/git2/blob.h +39 -12
- data/vendor/libgit2/include/git2/branch.h +123 -35
- data/vendor/libgit2/include/git2/checkout.h +206 -48
- data/vendor/libgit2/include/git2/clone.h +72 -27
- data/vendor/libgit2/include/git2/commit.h +20 -17
- data/vendor/libgit2/include/git2/common.h +67 -1
- data/vendor/libgit2/include/git2/config.h +81 -60
- data/vendor/libgit2/include/git2/cred_helpers.h +53 -0
- data/vendor/libgit2/include/git2/diff.h +459 -150
- data/vendor/libgit2/include/git2/errors.h +9 -1
- data/vendor/libgit2/include/git2/graph.h +41 -0
- data/vendor/libgit2/include/git2/ignore.h +7 -6
- data/vendor/libgit2/include/git2/index.h +323 -97
- data/vendor/libgit2/include/git2/indexer.h +27 -59
- data/vendor/libgit2/include/git2/inttypes.h +4 -0
- data/vendor/libgit2/include/git2/merge.h +13 -3
- data/vendor/libgit2/include/git2/message.h +14 -8
- data/vendor/libgit2/include/git2/net.h +9 -7
- data/vendor/libgit2/include/git2/notes.h +88 -29
- data/vendor/libgit2/include/git2/object.h +16 -6
- data/vendor/libgit2/include/git2/odb.h +80 -17
- data/vendor/libgit2/include/git2/odb_backend.h +47 -11
- data/vendor/libgit2/include/git2/oid.h +26 -17
- data/vendor/libgit2/include/git2/pack.h +62 -8
- data/vendor/libgit2/include/git2/push.h +131 -0
- data/vendor/libgit2/include/git2/refdb.h +103 -0
- data/vendor/libgit2/include/git2/refdb_backend.h +109 -0
- data/vendor/libgit2/include/git2/reflog.h +30 -21
- data/vendor/libgit2/include/git2/refs.h +215 -193
- data/vendor/libgit2/include/git2/refspec.h +22 -2
- data/vendor/libgit2/include/git2/remote.h +158 -37
- data/vendor/libgit2/include/git2/repository.h +150 -31
- data/vendor/libgit2/include/git2/reset.h +43 -9
- data/vendor/libgit2/include/git2/revparse.h +48 -4
- data/vendor/libgit2/include/git2/revwalk.h +25 -10
- data/vendor/libgit2/include/git2/signature.h +20 -12
- data/vendor/libgit2/include/git2/stash.h +121 -0
- data/vendor/libgit2/include/git2/status.h +122 -53
- data/vendor/libgit2/include/git2/strarray.h +17 -11
- data/vendor/libgit2/include/git2/submodule.h +42 -7
- data/vendor/libgit2/include/git2/tag.h +72 -59
- data/vendor/libgit2/include/git2/threads.h +4 -2
- data/vendor/libgit2/include/git2/trace.h +68 -0
- data/vendor/libgit2/include/git2/transport.h +328 -0
- data/vendor/libgit2/include/git2/tree.h +149 -120
- data/vendor/libgit2/include/git2/types.h +13 -12
- data/vendor/libgit2/include/git2/version.h +3 -3
- data/vendor/libgit2/src/amiga/map.c +2 -2
- data/vendor/libgit2/src/attr.c +58 -48
- data/vendor/libgit2/src/attr.h +4 -18
- data/vendor/libgit2/src/attr_file.c +30 -6
- data/vendor/libgit2/src/attr_file.h +6 -8
- data/vendor/libgit2/src/attrcache.h +24 -0
- data/vendor/libgit2/src/blob.c +30 -7
- data/vendor/libgit2/src/blob.h +1 -1
- data/vendor/libgit2/src/branch.c +361 -68
- data/vendor/libgit2/src/branch.h +17 -0
- data/vendor/libgit2/src/bswap.h +1 -1
- data/vendor/libgit2/src/buf_text.c +291 -0
- data/vendor/libgit2/src/buf_text.h +122 -0
- data/vendor/libgit2/src/buffer.c +27 -101
- data/vendor/libgit2/src/buffer.h +54 -39
- data/vendor/libgit2/src/cache.c +15 -6
- data/vendor/libgit2/src/cache.h +1 -1
- data/vendor/libgit2/src/cc-compat.h +3 -1
- data/vendor/libgit2/src/checkout.c +1165 -222
- data/vendor/libgit2/src/checkout.h +24 -0
- data/vendor/libgit2/src/clone.c +171 -86
- data/vendor/libgit2/src/commit.c +44 -45
- data/vendor/libgit2/src/commit.h +3 -3
- data/vendor/libgit2/src/commit_list.c +194 -0
- data/vendor/libgit2/src/commit_list.h +49 -0
- data/vendor/libgit2/src/common.h +44 -10
- data/vendor/libgit2/src/compress.c +1 -1
- data/vendor/libgit2/src/compress.h +1 -1
- data/vendor/libgit2/src/config.c +211 -124
- data/vendor/libgit2/src/config.h +23 -4
- data/vendor/libgit2/src/config_cache.c +2 -2
- data/vendor/libgit2/src/config_file.c +129 -53
- data/vendor/libgit2/src/config_file.h +10 -8
- data/vendor/libgit2/src/crlf.c +66 -67
- data/vendor/libgit2/src/date.c +12 -12
- data/vendor/libgit2/src/delta-apply.c +14 -1
- data/vendor/libgit2/src/delta-apply.h +18 -1
- data/vendor/libgit2/src/delta.c +40 -107
- data/vendor/libgit2/src/delta.h +19 -17
- data/vendor/libgit2/src/diff.c +347 -496
- data/vendor/libgit2/src/diff.h +27 -1
- data/vendor/libgit2/src/diff_output.c +564 -249
- data/vendor/libgit2/src/diff_output.h +15 -8
- data/vendor/libgit2/src/diff_tform.c +687 -0
- data/vendor/libgit2/src/errors.c +27 -36
- data/vendor/libgit2/src/fetch.c +13 -351
- data/vendor/libgit2/src/fetch.h +13 -3
- data/vendor/libgit2/src/fetchhead.c +295 -0
- data/vendor/libgit2/src/fetchhead.h +34 -0
- data/vendor/libgit2/src/filebuf.c +42 -15
- data/vendor/libgit2/src/filebuf.h +4 -2
- data/vendor/libgit2/src/fileops.c +466 -113
- data/vendor/libgit2/src/fileops.h +154 -28
- data/vendor/libgit2/src/filter.c +3 -75
- data/vendor/libgit2/src/filter.h +1 -29
- data/vendor/libgit2/src/fnmatch.c +1 -1
- data/vendor/libgit2/src/fnmatch.h +1 -1
- data/vendor/libgit2/src/global.c +54 -10
- data/vendor/libgit2/src/global.h +10 -1
- data/vendor/libgit2/src/graph.c +178 -0
- data/vendor/libgit2/src/hash.c +25 -52
- data/vendor/libgit2/src/hash.h +21 -9
- data/vendor/libgit2/src/{sha1/sha1.c → hash/hash_generic.c} +20 -12
- data/vendor/libgit2/src/hash/hash_generic.h +24 -0
- data/vendor/libgit2/src/hash/hash_openssl.h +45 -0
- data/vendor/libgit2/src/hash/hash_win32.c +291 -0
- data/vendor/libgit2/src/hash/hash_win32.h +140 -0
- data/vendor/libgit2/src/hashsig.c +368 -0
- data/vendor/libgit2/src/hashsig.h +72 -0
- data/vendor/libgit2/src/ignore.c +22 -15
- data/vendor/libgit2/src/ignore.h +6 -1
- data/vendor/libgit2/src/index.c +770 -171
- data/vendor/libgit2/src/index.h +13 -5
- data/vendor/libgit2/src/indexer.c +286 -431
- data/vendor/libgit2/src/iterator.c +854 -466
- data/vendor/libgit2/src/iterator.h +134 -109
- data/vendor/libgit2/src/map.h +1 -1
- data/vendor/libgit2/src/merge.c +296 -0
- data/vendor/libgit2/src/merge.h +22 -0
- data/vendor/libgit2/src/message.c +1 -1
- data/vendor/libgit2/src/message.h +1 -1
- data/vendor/libgit2/src/mwindow.c +35 -30
- data/vendor/libgit2/src/mwindow.h +2 -2
- data/vendor/libgit2/src/netops.c +162 -98
- data/vendor/libgit2/src/netops.h +50 -15
- data/vendor/libgit2/src/notes.c +109 -58
- data/vendor/libgit2/src/notes.h +2 -1
- data/vendor/libgit2/src/object.c +46 -57
- data/vendor/libgit2/src/object.h +1 -8
- data/vendor/libgit2/src/odb.c +151 -40
- data/vendor/libgit2/src/odb.h +5 -1
- data/vendor/libgit2/src/odb_loose.c +4 -5
- data/vendor/libgit2/src/odb_pack.c +122 -80
- data/vendor/libgit2/src/offmap.h +65 -0
- data/vendor/libgit2/src/oid.c +12 -4
- data/vendor/libgit2/src/oidmap.h +1 -1
- data/vendor/libgit2/src/pack-objects.c +88 -61
- data/vendor/libgit2/src/pack-objects.h +8 -8
- data/vendor/libgit2/src/pack.c +293 -28
- data/vendor/libgit2/src/pack.h +49 -4
- data/vendor/libgit2/src/path.c +103 -14
- data/vendor/libgit2/src/path.h +23 -7
- data/vendor/libgit2/src/pathspec.c +168 -0
- data/vendor/libgit2/src/pathspec.h +40 -0
- data/vendor/libgit2/src/pool.c +29 -4
- data/vendor/libgit2/src/pool.h +8 -1
- data/vendor/libgit2/src/posix.c +26 -27
- data/vendor/libgit2/src/posix.h +2 -3
- data/vendor/libgit2/src/pqueue.c +23 -1
- data/vendor/libgit2/src/pqueue.h +23 -1
- data/vendor/libgit2/src/push.c +653 -0
- data/vendor/libgit2/src/push.h +51 -0
- data/vendor/libgit2/src/refdb.c +185 -0
- data/vendor/libgit2/src/refdb.h +46 -0
- data/vendor/libgit2/src/refdb_fs.c +1024 -0
- data/vendor/libgit2/src/refdb_fs.h +15 -0
- data/vendor/libgit2/src/reflog.c +77 -45
- data/vendor/libgit2/src/reflog.h +1 -3
- data/vendor/libgit2/src/refs.c +366 -1326
- data/vendor/libgit2/src/refs.h +22 -13
- data/vendor/libgit2/src/refspec.c +46 -7
- data/vendor/libgit2/src/refspec.h +11 -1
- data/vendor/libgit2/src/remote.c +758 -120
- data/vendor/libgit2/src/remote.h +10 -5
- data/vendor/libgit2/src/repo_template.h +6 -6
- data/vendor/libgit2/src/repository.c +315 -96
- data/vendor/libgit2/src/repository.h +5 -3
- data/vendor/libgit2/src/reset.c +99 -81
- data/vendor/libgit2/src/revparse.c +157 -84
- data/vendor/libgit2/src/revwalk.c +68 -470
- data/vendor/libgit2/src/revwalk.h +44 -0
- data/vendor/libgit2/src/sha1_lookup.c +1 -1
- data/vendor/libgit2/src/sha1_lookup.h +1 -1
- data/vendor/libgit2/src/signature.c +68 -200
- data/vendor/libgit2/src/signature.h +1 -1
- data/vendor/libgit2/src/stash.c +663 -0
- data/vendor/libgit2/src/status.c +101 -79
- data/vendor/libgit2/src/strmap.h +1 -1
- data/vendor/libgit2/src/submodule.c +67 -51
- data/vendor/libgit2/src/submodule.h +1 -1
- data/vendor/libgit2/src/tag.c +35 -29
- data/vendor/libgit2/src/tag.h +1 -1
- data/vendor/libgit2/src/thread-utils.c +1 -1
- data/vendor/libgit2/src/thread-utils.h +2 -2
- data/vendor/libgit2/src/trace.c +39 -0
- data/vendor/libgit2/src/trace.h +56 -0
- data/vendor/libgit2/src/transport.c +81 -34
- data/vendor/libgit2/src/transports/cred.c +60 -0
- data/vendor/libgit2/src/transports/cred_helpers.c +49 -0
- data/vendor/libgit2/src/transports/git.c +234 -127
- data/vendor/libgit2/src/transports/http.c +761 -433
- data/vendor/libgit2/src/transports/local.c +460 -64
- data/vendor/libgit2/src/transports/smart.c +345 -0
- data/vendor/libgit2/src/transports/smart.h +179 -0
- data/vendor/libgit2/src/{pkt.c → transports/smart_pkt.c} +131 -12
- data/vendor/libgit2/src/transports/smart_protocol.c +856 -0
- data/vendor/libgit2/src/transports/winhttp.c +1136 -0
- data/vendor/libgit2/src/tree-cache.c +2 -2
- data/vendor/libgit2/src/tree-cache.h +1 -1
- data/vendor/libgit2/src/tree.c +239 -166
- data/vendor/libgit2/src/tree.h +11 -2
- data/vendor/libgit2/src/tsort.c +39 -23
- data/vendor/libgit2/src/unix/map.c +1 -1
- data/vendor/libgit2/src/unix/posix.h +12 -2
- data/vendor/libgit2/src/unix/realpath.c +30 -0
- data/vendor/libgit2/src/util.c +250 -13
- data/vendor/libgit2/src/util.h +71 -14
- data/vendor/libgit2/src/vector.c +123 -60
- data/vendor/libgit2/src/vector.h +24 -22
- data/vendor/libgit2/src/win32/dir.c +1 -1
- data/vendor/libgit2/src/win32/dir.h +1 -1
- data/vendor/libgit2/src/win32/error.c +77 -0
- data/vendor/libgit2/src/win32/error.h +13 -0
- data/vendor/libgit2/src/win32/findfile.c +143 -54
- data/vendor/libgit2/src/win32/findfile.h +10 -6
- data/vendor/libgit2/src/win32/map.c +1 -1
- data/vendor/libgit2/src/win32/mingw-compat.h +1 -1
- data/vendor/libgit2/src/win32/msvc-compat.h +10 -1
- data/vendor/libgit2/src/win32/posix.h +10 -1
- data/vendor/libgit2/src/win32/posix_w32.c +132 -63
- data/vendor/libgit2/src/win32/precompiled.c +1 -1
- data/vendor/libgit2/src/win32/pthread.c +1 -1
- data/vendor/libgit2/src/win32/pthread.h +1 -1
- data/vendor/libgit2/src/win32/utf-conv.c +5 -5
- data/vendor/libgit2/src/win32/utf-conv.h +3 -3
- data/vendor/libgit2/src/win32/version.h +20 -0
- metadata +308 -252
- data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
- data/test/fixtures/testrepo.git/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 +0 -0
- data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
- data/test/index_test.rb~ +0 -218
- data/vendor/libgit2/src/pkt.h +0 -91
- data/vendor/libgit2/src/ppc/sha1.c +0 -70
- data/vendor/libgit2/src/ppc/sha1.h +0 -26
- data/vendor/libgit2/src/protocol.c +0 -110
- data/vendor/libgit2/src/protocol.h +0 -21
- data/vendor/libgit2/src/sha1.h +0 -33
- data/vendor/libgit2/src/transport.h +0 -148
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (C)
|
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
|
3
3
|
*
|
|
4
4
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
5
5
|
* a Linking Exception. For full terms see the included COPYING file.
|
|
@@ -12,12 +12,11 @@
|
|
|
12
12
|
#include "git2/refs.h"
|
|
13
13
|
#include "git2/revwalk.h"
|
|
14
14
|
|
|
15
|
-
#include "
|
|
15
|
+
#include "smart.h"
|
|
16
16
|
#include "util.h"
|
|
17
17
|
#include "netops.h"
|
|
18
18
|
#include "posix.h"
|
|
19
19
|
#include "buffer.h"
|
|
20
|
-
#include "protocol.h"
|
|
21
20
|
|
|
22
21
|
#include <ctype.h>
|
|
23
22
|
|
|
@@ -123,6 +122,7 @@ static int err_pkt(git_pkt **out, const char *line, size_t len)
|
|
|
123
122
|
GITERR_CHECK_ALLOC(pkt);
|
|
124
123
|
|
|
125
124
|
pkt->type = GIT_PKT_ERR;
|
|
125
|
+
pkt->len = (int)len;
|
|
126
126
|
memcpy(pkt->error, line, len);
|
|
127
127
|
pkt->error[len] = '\0';
|
|
128
128
|
|
|
@@ -167,6 +167,25 @@ static int progress_pkt(git_pkt **out, const char *line, size_t len)
|
|
|
167
167
|
return 0;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
static int sideband_error_pkt(git_pkt **out, const char *line, size_t len)
|
|
171
|
+
{
|
|
172
|
+
git_pkt_err *pkt;
|
|
173
|
+
|
|
174
|
+
line++;
|
|
175
|
+
len--;
|
|
176
|
+
pkt = git__malloc(sizeof(git_pkt_err) + len + 1);
|
|
177
|
+
GITERR_CHECK_ALLOC(pkt);
|
|
178
|
+
|
|
179
|
+
pkt->type = GIT_PKT_ERR;
|
|
180
|
+
pkt->len = (int)len;
|
|
181
|
+
memcpy(pkt->error, line, len);
|
|
182
|
+
pkt->error[len] = '\0';
|
|
183
|
+
|
|
184
|
+
*out = (git_pkt *)pkt;
|
|
185
|
+
|
|
186
|
+
return 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
170
189
|
/*
|
|
171
190
|
* Parse an other-ref line.
|
|
172
191
|
*/
|
|
@@ -215,6 +234,83 @@ error_out:
|
|
|
215
234
|
return error;
|
|
216
235
|
}
|
|
217
236
|
|
|
237
|
+
static int ok_pkt(git_pkt **out, const char *line, size_t len)
|
|
238
|
+
{
|
|
239
|
+
git_pkt_ok *pkt;
|
|
240
|
+
const char *ptr;
|
|
241
|
+
|
|
242
|
+
pkt = git__malloc(sizeof(*pkt));
|
|
243
|
+
GITERR_CHECK_ALLOC(pkt);
|
|
244
|
+
|
|
245
|
+
pkt->type = GIT_PKT_OK;
|
|
246
|
+
|
|
247
|
+
line += 3; /* skip "ok " */
|
|
248
|
+
ptr = strchr(line, '\n');
|
|
249
|
+
len = ptr - line;
|
|
250
|
+
|
|
251
|
+
pkt->ref = git__malloc(len + 1);
|
|
252
|
+
GITERR_CHECK_ALLOC(pkt->ref);
|
|
253
|
+
|
|
254
|
+
memcpy(pkt->ref, line, len);
|
|
255
|
+
pkt->ref[len] = '\0';
|
|
256
|
+
|
|
257
|
+
*out = (git_pkt *)pkt;
|
|
258
|
+
return 0;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
static int ng_pkt(git_pkt **out, const char *line, size_t len)
|
|
262
|
+
{
|
|
263
|
+
git_pkt_ng *pkt;
|
|
264
|
+
const char *ptr;
|
|
265
|
+
|
|
266
|
+
pkt = git__malloc(sizeof(*pkt));
|
|
267
|
+
GITERR_CHECK_ALLOC(pkt);
|
|
268
|
+
|
|
269
|
+
pkt->type = GIT_PKT_NG;
|
|
270
|
+
|
|
271
|
+
line += 3; /* skip "ng " */
|
|
272
|
+
ptr = strchr(line, ' ');
|
|
273
|
+
len = ptr - line;
|
|
274
|
+
|
|
275
|
+
pkt->ref = git__malloc(len + 1);
|
|
276
|
+
GITERR_CHECK_ALLOC(pkt->ref);
|
|
277
|
+
|
|
278
|
+
memcpy(pkt->ref, line, len);
|
|
279
|
+
pkt->ref[len] = '\0';
|
|
280
|
+
|
|
281
|
+
line = ptr + 1;
|
|
282
|
+
ptr = strchr(line, '\n');
|
|
283
|
+
len = ptr - line;
|
|
284
|
+
|
|
285
|
+
pkt->msg = git__malloc(len + 1);
|
|
286
|
+
GITERR_CHECK_ALLOC(pkt->msg);
|
|
287
|
+
|
|
288
|
+
memcpy(pkt->msg, line, len);
|
|
289
|
+
pkt->msg[len] = '\0';
|
|
290
|
+
|
|
291
|
+
*out = (git_pkt *)pkt;
|
|
292
|
+
return 0;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
static int unpack_pkt(git_pkt **out, const char *line, size_t len)
|
|
296
|
+
{
|
|
297
|
+
git_pkt_unpack *pkt;
|
|
298
|
+
|
|
299
|
+
GIT_UNUSED(len);
|
|
300
|
+
|
|
301
|
+
pkt = git__malloc(sizeof(*pkt));
|
|
302
|
+
GITERR_CHECK_ALLOC(pkt);
|
|
303
|
+
|
|
304
|
+
pkt->type = GIT_PKT_UNPACK;
|
|
305
|
+
if (!git__prefixcmp(line, "unpack ok"))
|
|
306
|
+
pkt->unpack_ok = 1;
|
|
307
|
+
else
|
|
308
|
+
pkt->unpack_ok = 0;
|
|
309
|
+
|
|
310
|
+
*out = (git_pkt *)pkt;
|
|
311
|
+
return 0;
|
|
312
|
+
}
|
|
313
|
+
|
|
218
314
|
static int32_t parse_len(const char *line)
|
|
219
315
|
{
|
|
220
316
|
char num[PKT_LEN_SIZE + 1];
|
|
@@ -304,6 +400,8 @@ int git_pkt_parse_line(
|
|
|
304
400
|
ret = data_pkt(head, line, len);
|
|
305
401
|
else if (*line == GIT_SIDE_BAND_PROGRESS)
|
|
306
402
|
ret = progress_pkt(head, line, len);
|
|
403
|
+
else if (*line == GIT_SIDE_BAND_ERROR)
|
|
404
|
+
ret = sideband_error_pkt(head, line, len);
|
|
307
405
|
else if (!git__prefixcmp(line, "ACK"))
|
|
308
406
|
ret = ack_pkt(head, line, len);
|
|
309
407
|
else if (!git__prefixcmp(line, "NAK"))
|
|
@@ -312,6 +410,12 @@ int git_pkt_parse_line(
|
|
|
312
410
|
ret = err_pkt(head, line, len);
|
|
313
411
|
else if (*line == '#')
|
|
314
412
|
ret = comment_pkt(head, line, len);
|
|
413
|
+
else if (!git__prefixcmp(line, "ok"))
|
|
414
|
+
ret = ok_pkt(head, line, len);
|
|
415
|
+
else if (!git__prefixcmp(line, "ng"))
|
|
416
|
+
ret = ng_pkt(head, line, len);
|
|
417
|
+
else if (!git__prefixcmp(line, "unpack"))
|
|
418
|
+
ret = unpack_pkt(head, line, len);
|
|
315
419
|
else
|
|
316
420
|
ret = ref_pkt(head, line, len);
|
|
317
421
|
|
|
@@ -327,6 +431,17 @@ void git_pkt_free(git_pkt *pkt)
|
|
|
327
431
|
git__free(p->head.name);
|
|
328
432
|
}
|
|
329
433
|
|
|
434
|
+
if (pkt->type == GIT_PKT_OK) {
|
|
435
|
+
git_pkt_ok *p = (git_pkt_ok *) pkt;
|
|
436
|
+
git__free(p->ref);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (pkt->type == GIT_PKT_NG) {
|
|
440
|
+
git_pkt_ng *p = (git_pkt_ng *) pkt;
|
|
441
|
+
git__free(p->ref);
|
|
442
|
+
git__free(p->msg);
|
|
443
|
+
}
|
|
444
|
+
|
|
330
445
|
git__free(pkt);
|
|
331
446
|
}
|
|
332
447
|
|
|
@@ -335,7 +450,7 @@ int git_pkt_buffer_flush(git_buf *buf)
|
|
|
335
450
|
return git_buf_put(buf, pkt_flush_str, strlen(pkt_flush_str));
|
|
336
451
|
}
|
|
337
452
|
|
|
338
|
-
static int buffer_want_with_caps(git_remote_head *head,
|
|
453
|
+
static int buffer_want_with_caps(const git_remote_head *head, transport_smart_caps *caps, git_buf *buf)
|
|
339
454
|
{
|
|
340
455
|
git_buf str = GIT_BUF_INIT;
|
|
341
456
|
char oid[GIT_OID_HEXSZ +1] = {0};
|
|
@@ -376,28 +491,32 @@ static int buffer_want_with_caps(git_remote_head *head, git_transport_caps *caps
|
|
|
376
491
|
* is overwrite the OID each time.
|
|
377
492
|
*/
|
|
378
493
|
|
|
379
|
-
int git_pkt_buffer_wants(
|
|
494
|
+
int git_pkt_buffer_wants(
|
|
495
|
+
const git_remote_head * const *refs,
|
|
496
|
+
size_t count,
|
|
497
|
+
transport_smart_caps *caps,
|
|
498
|
+
git_buf *buf)
|
|
380
499
|
{
|
|
381
|
-
|
|
382
|
-
git_remote_head *head;
|
|
500
|
+
size_t i = 0;
|
|
501
|
+
const git_remote_head *head;
|
|
383
502
|
|
|
384
503
|
if (caps->common) {
|
|
385
|
-
for (; i <
|
|
386
|
-
head = refs
|
|
504
|
+
for (; i < count; ++i) {
|
|
505
|
+
head = refs[i];
|
|
387
506
|
if (!head->local)
|
|
388
507
|
break;
|
|
389
508
|
}
|
|
390
509
|
|
|
391
|
-
if (buffer_want_with_caps(refs
|
|
510
|
+
if (buffer_want_with_caps(refs[i], caps, buf) < 0)
|
|
392
511
|
return -1;
|
|
393
512
|
|
|
394
513
|
i++;
|
|
395
514
|
}
|
|
396
515
|
|
|
397
|
-
for (; i <
|
|
516
|
+
for (; i < count; ++i) {
|
|
398
517
|
char oid[GIT_OID_HEXSZ];
|
|
399
518
|
|
|
400
|
-
head = refs
|
|
519
|
+
head = refs[i];
|
|
401
520
|
if (head->local)
|
|
402
521
|
continue;
|
|
403
522
|
|
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
5
|
+
* a Linking Exception. For full terms see the included COPYING file.
|
|
6
|
+
*/
|
|
7
|
+
#include "git2.h"
|
|
8
|
+
|
|
9
|
+
#include "smart.h"
|
|
10
|
+
#include "refs.h"
|
|
11
|
+
#include "repository.h"
|
|
12
|
+
#include "push.h"
|
|
13
|
+
#include "pack-objects.h"
|
|
14
|
+
#include "remote.h"
|
|
15
|
+
|
|
16
|
+
#define NETWORK_XFER_THRESHOLD (100*1024)
|
|
17
|
+
|
|
18
|
+
int git_smart__store_refs(transport_smart *t, int flushes)
|
|
19
|
+
{
|
|
20
|
+
gitno_buffer *buf = &t->buffer;
|
|
21
|
+
git_vector *refs = &t->refs;
|
|
22
|
+
int error, flush = 0, recvd;
|
|
23
|
+
const char *line_end;
|
|
24
|
+
git_pkt *pkt;
|
|
25
|
+
|
|
26
|
+
/* Clear existing refs in case git_remote_connect() is called again
|
|
27
|
+
* after git_remote_disconnect().
|
|
28
|
+
*/
|
|
29
|
+
git_vector_clear(refs);
|
|
30
|
+
|
|
31
|
+
do {
|
|
32
|
+
if (buf->offset > 0)
|
|
33
|
+
error = git_pkt_parse_line(&pkt, buf->data, &line_end, buf->offset);
|
|
34
|
+
else
|
|
35
|
+
error = GIT_EBUFS;
|
|
36
|
+
|
|
37
|
+
if (error < 0 && error != GIT_EBUFS)
|
|
38
|
+
return -1;
|
|
39
|
+
|
|
40
|
+
if (error == GIT_EBUFS) {
|
|
41
|
+
if ((recvd = gitno_recv(buf)) < 0)
|
|
42
|
+
return -1;
|
|
43
|
+
|
|
44
|
+
if (recvd == 0 && !flush) {
|
|
45
|
+
giterr_set(GITERR_NET, "Early EOF");
|
|
46
|
+
return -1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
gitno_consume(buf, line_end);
|
|
53
|
+
if (pkt->type == GIT_PKT_ERR) {
|
|
54
|
+
giterr_set(GITERR_NET, "Remote error: %s", ((git_pkt_err *)pkt)->error);
|
|
55
|
+
git__free(pkt);
|
|
56
|
+
return -1;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (pkt->type != GIT_PKT_FLUSH && git_vector_insert(refs, pkt) < 0)
|
|
60
|
+
return -1;
|
|
61
|
+
|
|
62
|
+
if (pkt->type == GIT_PKT_FLUSH) {
|
|
63
|
+
flush++;
|
|
64
|
+
git_pkt_free(pkt);
|
|
65
|
+
}
|
|
66
|
+
} while (flush < flushes);
|
|
67
|
+
|
|
68
|
+
return flush;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps)
|
|
72
|
+
{
|
|
73
|
+
const char *ptr;
|
|
74
|
+
|
|
75
|
+
/* No refs or capabilites, odd but not a problem */
|
|
76
|
+
if (pkt == NULL || pkt->capabilities == NULL)
|
|
77
|
+
return 0;
|
|
78
|
+
|
|
79
|
+
ptr = pkt->capabilities;
|
|
80
|
+
while (ptr != NULL && *ptr != '\0') {
|
|
81
|
+
if (*ptr == ' ')
|
|
82
|
+
ptr++;
|
|
83
|
+
|
|
84
|
+
if (!git__prefixcmp(ptr, GIT_CAP_OFS_DELTA)) {
|
|
85
|
+
caps->common = caps->ofs_delta = 1;
|
|
86
|
+
ptr += strlen(GIT_CAP_OFS_DELTA);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!git__prefixcmp(ptr, GIT_CAP_MULTI_ACK)) {
|
|
91
|
+
caps->common = caps->multi_ack = 1;
|
|
92
|
+
ptr += strlen(GIT_CAP_MULTI_ACK);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!git__prefixcmp(ptr, GIT_CAP_INCLUDE_TAG)) {
|
|
97
|
+
caps->common = caps->include_tag = 1;
|
|
98
|
+
ptr += strlen(GIT_CAP_INCLUDE_TAG);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Keep side-band check after side-band-64k */
|
|
103
|
+
if (!git__prefixcmp(ptr, GIT_CAP_SIDE_BAND_64K)) {
|
|
104
|
+
caps->common = caps->side_band_64k = 1;
|
|
105
|
+
ptr += strlen(GIT_CAP_SIDE_BAND_64K);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (!git__prefixcmp(ptr, GIT_CAP_SIDE_BAND)) {
|
|
110
|
+
caps->common = caps->side_band = 1;
|
|
111
|
+
ptr += strlen(GIT_CAP_SIDE_BAND);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!git__prefixcmp(ptr, GIT_CAP_DELETE_REFS)) {
|
|
116
|
+
caps->common = caps->delete_refs = 1;
|
|
117
|
+
ptr += strlen(GIT_CAP_DELETE_REFS);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* We don't know this capability, so skip it */
|
|
122
|
+
ptr = strchr(ptr, ' ');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static int recv_pkt(git_pkt **out, gitno_buffer *buf)
|
|
129
|
+
{
|
|
130
|
+
const char *ptr = buf->data, *line_end = ptr;
|
|
131
|
+
git_pkt *pkt;
|
|
132
|
+
int pkt_type, error = 0, ret;
|
|
133
|
+
|
|
134
|
+
do {
|
|
135
|
+
if (buf->offset > 0)
|
|
136
|
+
error = git_pkt_parse_line(&pkt, ptr, &line_end, buf->offset);
|
|
137
|
+
else
|
|
138
|
+
error = GIT_EBUFS;
|
|
139
|
+
|
|
140
|
+
if (error == 0)
|
|
141
|
+
break; /* return the pkt */
|
|
142
|
+
|
|
143
|
+
if (error < 0 && error != GIT_EBUFS)
|
|
144
|
+
return -1;
|
|
145
|
+
|
|
146
|
+
if ((ret = gitno_recv(buf)) < 0)
|
|
147
|
+
return -1;
|
|
148
|
+
} while (error);
|
|
149
|
+
|
|
150
|
+
gitno_consume(buf, line_end);
|
|
151
|
+
pkt_type = pkt->type;
|
|
152
|
+
if (out != NULL)
|
|
153
|
+
*out = pkt;
|
|
154
|
+
else
|
|
155
|
+
git__free(pkt);
|
|
156
|
+
|
|
157
|
+
return pkt_type;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
static int store_common(transport_smart *t)
|
|
161
|
+
{
|
|
162
|
+
git_pkt *pkt = NULL;
|
|
163
|
+
gitno_buffer *buf = &t->buffer;
|
|
164
|
+
|
|
165
|
+
do {
|
|
166
|
+
if (recv_pkt(&pkt, buf) < 0)
|
|
167
|
+
return -1;
|
|
168
|
+
|
|
169
|
+
if (pkt->type == GIT_PKT_ACK) {
|
|
170
|
+
if (git_vector_insert(&t->common, pkt) < 0)
|
|
171
|
+
return -1;
|
|
172
|
+
} else {
|
|
173
|
+
git__free(pkt);
|
|
174
|
+
return 0;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
} while (1);
|
|
178
|
+
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
static int fetch_setup_walk(git_revwalk **out, git_repository *repo)
|
|
183
|
+
{
|
|
184
|
+
git_revwalk *walk;
|
|
185
|
+
git_strarray refs;
|
|
186
|
+
unsigned int i;
|
|
187
|
+
git_reference *ref;
|
|
188
|
+
|
|
189
|
+
if (git_reference_list(&refs, repo, GIT_REF_LISTALL) < 0)
|
|
190
|
+
return -1;
|
|
191
|
+
|
|
192
|
+
if (git_revwalk_new(&walk, repo) < 0)
|
|
193
|
+
return -1;
|
|
194
|
+
|
|
195
|
+
git_revwalk_sorting(walk, GIT_SORT_TIME);
|
|
196
|
+
|
|
197
|
+
for (i = 0; i < refs.count; ++i) {
|
|
198
|
+
/* No tags */
|
|
199
|
+
if (!git__prefixcmp(refs.strings[i], GIT_REFS_TAGS_DIR))
|
|
200
|
+
continue;
|
|
201
|
+
|
|
202
|
+
if (git_reference_lookup(&ref, repo, refs.strings[i]) < 0)
|
|
203
|
+
goto on_error;
|
|
204
|
+
|
|
205
|
+
if (git_reference_type(ref) == GIT_REF_SYMBOLIC)
|
|
206
|
+
continue;
|
|
207
|
+
if (git_revwalk_push(walk, git_reference_target(ref)) < 0)
|
|
208
|
+
goto on_error;
|
|
209
|
+
|
|
210
|
+
git_reference_free(ref);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
git_strarray_free(&refs);
|
|
214
|
+
*out = walk;
|
|
215
|
+
return 0;
|
|
216
|
+
|
|
217
|
+
on_error:
|
|
218
|
+
git_reference_free(ref);
|
|
219
|
+
git_strarray_free(&refs);
|
|
220
|
+
return -1;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *refs, size_t count)
|
|
224
|
+
{
|
|
225
|
+
transport_smart *t = (transport_smart *)transport;
|
|
226
|
+
gitno_buffer *buf = &t->buffer;
|
|
227
|
+
git_buf data = GIT_BUF_INIT;
|
|
228
|
+
git_revwalk *walk = NULL;
|
|
229
|
+
int error = -1, pkt_type;
|
|
230
|
+
unsigned int i;
|
|
231
|
+
git_oid oid;
|
|
232
|
+
|
|
233
|
+
/* No own logic, do our thing */
|
|
234
|
+
if ((error = git_pkt_buffer_wants(refs, count, &t->caps, &data)) < 0)
|
|
235
|
+
return error;
|
|
236
|
+
|
|
237
|
+
if ((error = fetch_setup_walk(&walk, repo)) < 0)
|
|
238
|
+
goto on_error;
|
|
239
|
+
/*
|
|
240
|
+
* We don't support any kind of ACK extensions, so the negotiation
|
|
241
|
+
* boils down to sending what we have and listening for an ACK
|
|
242
|
+
* every once in a while.
|
|
243
|
+
*/
|
|
244
|
+
i = 0;
|
|
245
|
+
while (true) {
|
|
246
|
+
error = git_revwalk_next(&oid, walk);
|
|
247
|
+
|
|
248
|
+
if (error < 0) {
|
|
249
|
+
if (GIT_ITEROVER == error)
|
|
250
|
+
break;
|
|
251
|
+
|
|
252
|
+
goto on_error;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
git_pkt_buffer_have(&oid, &data);
|
|
256
|
+
i++;
|
|
257
|
+
if (i % 20 == 0) {
|
|
258
|
+
if (t->cancelled.val) {
|
|
259
|
+
giterr_set(GITERR_NET, "The fetch was cancelled by the user");
|
|
260
|
+
error = GIT_EUSER;
|
|
261
|
+
goto on_error;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
git_pkt_buffer_flush(&data);
|
|
265
|
+
if (git_buf_oom(&data)) {
|
|
266
|
+
error = -1;
|
|
267
|
+
goto on_error;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0)
|
|
271
|
+
goto on_error;
|
|
272
|
+
|
|
273
|
+
git_buf_clear(&data);
|
|
274
|
+
if (t->caps.multi_ack) {
|
|
275
|
+
if ((error = store_common(t)) < 0)
|
|
276
|
+
goto on_error;
|
|
277
|
+
} else {
|
|
278
|
+
pkt_type = recv_pkt(NULL, buf);
|
|
279
|
+
|
|
280
|
+
if (pkt_type == GIT_PKT_ACK) {
|
|
281
|
+
break;
|
|
282
|
+
} else if (pkt_type == GIT_PKT_NAK) {
|
|
283
|
+
continue;
|
|
284
|
+
} else if (pkt_type < 0) {
|
|
285
|
+
/* recv_pkt returned an error */
|
|
286
|
+
error = pkt_type;
|
|
287
|
+
goto on_error;
|
|
288
|
+
} else {
|
|
289
|
+
giterr_set(GITERR_NET, "Unexpected pkt type");
|
|
290
|
+
error = -1;
|
|
291
|
+
goto on_error;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (t->common.length > 0)
|
|
297
|
+
break;
|
|
298
|
+
|
|
299
|
+
if (i % 20 == 0 && t->rpc) {
|
|
300
|
+
git_pkt_ack *pkt;
|
|
301
|
+
unsigned int i;
|
|
302
|
+
|
|
303
|
+
if ((error = git_pkt_buffer_wants(refs, count, &t->caps, &data)) < 0)
|
|
304
|
+
goto on_error;
|
|
305
|
+
|
|
306
|
+
git_vector_foreach(&t->common, i, pkt) {
|
|
307
|
+
if ((error = git_pkt_buffer_have(&pkt->oid, &data)) < 0)
|
|
308
|
+
goto on_error;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (git_buf_oom(&data)) {
|
|
312
|
+
error = -1;
|
|
313
|
+
goto on_error;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/* Tell the other end that we're done negotiating */
|
|
319
|
+
if (t->rpc && t->common.length > 0) {
|
|
320
|
+
git_pkt_ack *pkt;
|
|
321
|
+
unsigned int i;
|
|
322
|
+
|
|
323
|
+
if ((error = git_pkt_buffer_wants(refs, count, &t->caps, &data)) < 0)
|
|
324
|
+
goto on_error;
|
|
325
|
+
|
|
326
|
+
git_vector_foreach(&t->common, i, pkt) {
|
|
327
|
+
if ((error = git_pkt_buffer_have(&pkt->oid, &data)) < 0)
|
|
328
|
+
goto on_error;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (git_buf_oom(&data)) {
|
|
332
|
+
error = -1;
|
|
333
|
+
goto on_error;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if ((error = git_pkt_buffer_done(&data)) < 0)
|
|
338
|
+
goto on_error;
|
|
339
|
+
|
|
340
|
+
if (t->cancelled.val) {
|
|
341
|
+
giterr_set(GITERR_NET, "The fetch was cancelled by the user");
|
|
342
|
+
error = GIT_EUSER;
|
|
343
|
+
goto on_error;
|
|
344
|
+
}
|
|
345
|
+
if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0)
|
|
346
|
+
goto on_error;
|
|
347
|
+
|
|
348
|
+
git_buf_free(&data);
|
|
349
|
+
git_revwalk_free(walk);
|
|
350
|
+
|
|
351
|
+
/* Now let's eat up whatever the server gives us */
|
|
352
|
+
if (!t->caps.multi_ack) {
|
|
353
|
+
pkt_type = recv_pkt(NULL, buf);
|
|
354
|
+
|
|
355
|
+
if (pkt_type < 0) {
|
|
356
|
+
return pkt_type;
|
|
357
|
+
} else if (pkt_type != GIT_PKT_ACK && pkt_type != GIT_PKT_NAK) {
|
|
358
|
+
giterr_set(GITERR_NET, "Unexpected pkt type");
|
|
359
|
+
return -1;
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
git_pkt_ack *pkt;
|
|
363
|
+
do {
|
|
364
|
+
if ((error = recv_pkt((git_pkt **)&pkt, buf)) < 0)
|
|
365
|
+
return error;
|
|
366
|
+
|
|
367
|
+
if (pkt->type == GIT_PKT_NAK ||
|
|
368
|
+
(pkt->type == GIT_PKT_ACK && pkt->status != GIT_ACK_CONTINUE)) {
|
|
369
|
+
git__free(pkt);
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
git__free(pkt);
|
|
374
|
+
} while (1);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return 0;
|
|
378
|
+
|
|
379
|
+
on_error:
|
|
380
|
+
git_revwalk_free(walk);
|
|
381
|
+
git_buf_free(&data);
|
|
382
|
+
return error;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, gitno_buffer *buf, git_transfer_progress *stats)
|
|
386
|
+
{
|
|
387
|
+
int recvd;
|
|
388
|
+
|
|
389
|
+
do {
|
|
390
|
+
if (t->cancelled.val) {
|
|
391
|
+
giterr_set(GITERR_NET, "The fetch was cancelled by the user");
|
|
392
|
+
return GIT_EUSER;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (writepack->add(writepack, buf->data, buf->offset, stats) < 0)
|
|
396
|
+
return -1;
|
|
397
|
+
|
|
398
|
+
gitno_consume_n(buf, buf->offset);
|
|
399
|
+
|
|
400
|
+
if ((recvd = gitno_recv(buf)) < 0)
|
|
401
|
+
return -1;
|
|
402
|
+
} while(recvd > 0);
|
|
403
|
+
|
|
404
|
+
if (writepack->commit(writepack, stats))
|
|
405
|
+
return -1;
|
|
406
|
+
|
|
407
|
+
return 0;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
struct network_packetsize_payload
|
|
411
|
+
{
|
|
412
|
+
git_transfer_progress_callback callback;
|
|
413
|
+
void *payload;
|
|
414
|
+
git_transfer_progress *stats;
|
|
415
|
+
size_t last_fired_bytes;
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
static void network_packetsize(size_t received, void *payload)
|
|
419
|
+
{
|
|
420
|
+
struct network_packetsize_payload *npp = (struct network_packetsize_payload*)payload;
|
|
421
|
+
|
|
422
|
+
/* Accumulate bytes */
|
|
423
|
+
npp->stats->received_bytes += received;
|
|
424
|
+
|
|
425
|
+
/* Fire notification if the threshold is reached */
|
|
426
|
+
if ((npp->stats->received_bytes - npp->last_fired_bytes) > NETWORK_XFER_THRESHOLD) {
|
|
427
|
+
npp->last_fired_bytes = npp->stats->received_bytes;
|
|
428
|
+
npp->callback(npp->stats, npp->payload);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
int git_smart__download_pack(
|
|
433
|
+
git_transport *transport,
|
|
434
|
+
git_repository *repo,
|
|
435
|
+
git_transfer_progress *stats,
|
|
436
|
+
git_transfer_progress_callback progress_cb,
|
|
437
|
+
void *progress_payload)
|
|
438
|
+
{
|
|
439
|
+
transport_smart *t = (transport_smart *)transport;
|
|
440
|
+
gitno_buffer *buf = &t->buffer;
|
|
441
|
+
git_odb *odb;
|
|
442
|
+
struct git_odb_writepack *writepack = NULL;
|
|
443
|
+
int error = -1;
|
|
444
|
+
struct network_packetsize_payload npp = {0};
|
|
445
|
+
|
|
446
|
+
memset(stats, 0, sizeof(git_transfer_progress));
|
|
447
|
+
|
|
448
|
+
if (progress_cb) {
|
|
449
|
+
npp.callback = progress_cb;
|
|
450
|
+
npp.payload = progress_payload;
|
|
451
|
+
npp.stats = stats;
|
|
452
|
+
t->packetsize_cb = &network_packetsize;
|
|
453
|
+
t->packetsize_payload = &npp;
|
|
454
|
+
|
|
455
|
+
/* We might have something in the buffer already from negotiate_fetch */
|
|
456
|
+
if (t->buffer.offset > 0)
|
|
457
|
+
t->packetsize_cb(t->buffer.offset, t->packetsize_payload);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
|
|
461
|
+
((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0))
|
|
462
|
+
goto on_error;
|
|
463
|
+
|
|
464
|
+
/*
|
|
465
|
+
* If the remote doesn't support the side-band, we can feed
|
|
466
|
+
* the data directly to the pack writer. Otherwise, we need to
|
|
467
|
+
* check which one belongs there.
|
|
468
|
+
*/
|
|
469
|
+
if (!t->caps.side_band && !t->caps.side_band_64k) {
|
|
470
|
+
if (no_sideband(t, writepack, buf, stats) < 0)
|
|
471
|
+
goto on_error;
|
|
472
|
+
|
|
473
|
+
goto on_success;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
do {
|
|
477
|
+
git_pkt *pkt;
|
|
478
|
+
|
|
479
|
+
if (t->cancelled.val) {
|
|
480
|
+
giterr_set(GITERR_NET, "The fetch was cancelled by the user");
|
|
481
|
+
error = GIT_EUSER;
|
|
482
|
+
goto on_error;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (recv_pkt(&pkt, buf) < 0)
|
|
486
|
+
goto on_error;
|
|
487
|
+
|
|
488
|
+
if (pkt->type == GIT_PKT_PROGRESS) {
|
|
489
|
+
if (t->progress_cb) {
|
|
490
|
+
git_pkt_progress *p = (git_pkt_progress *) pkt;
|
|
491
|
+
t->progress_cb(p->data, p->len, t->message_cb_payload);
|
|
492
|
+
}
|
|
493
|
+
git__free(pkt);
|
|
494
|
+
} else if (pkt->type == GIT_PKT_DATA) {
|
|
495
|
+
git_pkt_data *p = (git_pkt_data *) pkt;
|
|
496
|
+
error = writepack->add(writepack, p->data, p->len, stats);
|
|
497
|
+
|
|
498
|
+
git__free(pkt);
|
|
499
|
+
if (error < 0)
|
|
500
|
+
goto on_error;
|
|
501
|
+
} else if (pkt->type == GIT_PKT_FLUSH) {
|
|
502
|
+
/* A flush indicates the end of the packfile */
|
|
503
|
+
git__free(pkt);
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
} while (1);
|
|
507
|
+
|
|
508
|
+
if (writepack->commit(writepack, stats) < 0)
|
|
509
|
+
goto on_error;
|
|
510
|
+
|
|
511
|
+
on_success:
|
|
512
|
+
error = 0;
|
|
513
|
+
|
|
514
|
+
on_error:
|
|
515
|
+
if (writepack)
|
|
516
|
+
writepack->free(writepack);
|
|
517
|
+
|
|
518
|
+
/* Trailing execution of progress_cb, if necessary */
|
|
519
|
+
if (npp.callback && npp.stats->received_bytes > npp.last_fired_bytes)
|
|
520
|
+
npp.callback(npp.stats, npp.payload);
|
|
521
|
+
|
|
522
|
+
return error;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
static int gen_pktline(git_buf *buf, git_push *push)
|
|
526
|
+
{
|
|
527
|
+
push_spec *spec;
|
|
528
|
+
size_t i, len;
|
|
529
|
+
char old_id[41], new_id[41];
|
|
530
|
+
|
|
531
|
+
old_id[40] = '\0'; new_id[40] = '\0';
|
|
532
|
+
|
|
533
|
+
git_vector_foreach(&push->specs, i, spec) {
|
|
534
|
+
len = 2*GIT_OID_HEXSZ + 7 + strlen(spec->rref);
|
|
535
|
+
|
|
536
|
+
if (i == 0) {
|
|
537
|
+
++len; /* '\0' */
|
|
538
|
+
if (push->report_status)
|
|
539
|
+
len += strlen(GIT_CAP_REPORT_STATUS) + 1;
|
|
540
|
+
len += strlen(GIT_CAP_SIDE_BAND_64K) + 1;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
git_oid_fmt(old_id, &spec->roid);
|
|
544
|
+
git_oid_fmt(new_id, &spec->loid);
|
|
545
|
+
|
|
546
|
+
git_buf_printf(buf, "%04"PRIxZ"%s %s %s", len, old_id, new_id, spec->rref);
|
|
547
|
+
|
|
548
|
+
if (i == 0) {
|
|
549
|
+
git_buf_putc(buf, '\0');
|
|
550
|
+
/* Core git always starts their capabilities string with a space */
|
|
551
|
+
if (push->report_status) {
|
|
552
|
+
git_buf_putc(buf, ' ');
|
|
553
|
+
git_buf_printf(buf, GIT_CAP_REPORT_STATUS);
|
|
554
|
+
}
|
|
555
|
+
git_buf_putc(buf, ' ');
|
|
556
|
+
git_buf_printf(buf, GIT_CAP_SIDE_BAND_64K);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
git_buf_putc(buf, '\n');
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
git_buf_puts(buf, "0000");
|
|
563
|
+
return git_buf_oom(buf) ? -1 : 0;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
static int add_push_report_pkt(git_push *push, git_pkt *pkt)
|
|
567
|
+
{
|
|
568
|
+
push_status *status;
|
|
569
|
+
|
|
570
|
+
switch (pkt->type) {
|
|
571
|
+
case GIT_PKT_OK:
|
|
572
|
+
status = git__malloc(sizeof(push_status));
|
|
573
|
+
GITERR_CHECK_ALLOC(status);
|
|
574
|
+
status->msg = NULL;
|
|
575
|
+
status->ref = git__strdup(((git_pkt_ok *)pkt)->ref);
|
|
576
|
+
if (!status->ref ||
|
|
577
|
+
git_vector_insert(&push->status, status) < 0) {
|
|
578
|
+
git_push_status_free(status);
|
|
579
|
+
return -1;
|
|
580
|
+
}
|
|
581
|
+
break;
|
|
582
|
+
case GIT_PKT_NG:
|
|
583
|
+
status = git__calloc(sizeof(push_status), 1);
|
|
584
|
+
GITERR_CHECK_ALLOC(status);
|
|
585
|
+
status->ref = git__strdup(((git_pkt_ng *)pkt)->ref);
|
|
586
|
+
status->msg = git__strdup(((git_pkt_ng *)pkt)->msg);
|
|
587
|
+
if (!status->ref || !status->msg ||
|
|
588
|
+
git_vector_insert(&push->status, status) < 0) {
|
|
589
|
+
git_push_status_free(status);
|
|
590
|
+
return -1;
|
|
591
|
+
}
|
|
592
|
+
break;
|
|
593
|
+
case GIT_PKT_UNPACK:
|
|
594
|
+
push->unpack_ok = ((git_pkt_unpack *)pkt)->unpack_ok;
|
|
595
|
+
break;
|
|
596
|
+
case GIT_PKT_FLUSH:
|
|
597
|
+
return GIT_ITEROVER;
|
|
598
|
+
default:
|
|
599
|
+
giterr_set(GITERR_NET, "report-status: protocol error");
|
|
600
|
+
return -1;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
return 0;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
|
|
607
|
+
{
|
|
608
|
+
git_pkt *pkt;
|
|
609
|
+
const char *line = data_pkt->data, *line_end;
|
|
610
|
+
size_t line_len = data_pkt->len;
|
|
611
|
+
int error;
|
|
612
|
+
|
|
613
|
+
while (line_len > 0) {
|
|
614
|
+
error = git_pkt_parse_line(&pkt, line, &line_end, line_len);
|
|
615
|
+
|
|
616
|
+
if (error < 0)
|
|
617
|
+
return error;
|
|
618
|
+
|
|
619
|
+
/* Advance in the buffer */
|
|
620
|
+
line_len -= (line_end - line);
|
|
621
|
+
line = line_end;
|
|
622
|
+
|
|
623
|
+
error = add_push_report_pkt(push, pkt);
|
|
624
|
+
|
|
625
|
+
git_pkt_free(pkt);
|
|
626
|
+
|
|
627
|
+
if (error < 0 && error != GIT_ITEROVER)
|
|
628
|
+
return error;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return 0;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
static int parse_report(gitno_buffer *buf, git_push *push)
|
|
635
|
+
{
|
|
636
|
+
git_pkt *pkt;
|
|
637
|
+
const char *line_end;
|
|
638
|
+
int error, recvd;
|
|
639
|
+
|
|
640
|
+
for (;;) {
|
|
641
|
+
if (buf->offset > 0)
|
|
642
|
+
error = git_pkt_parse_line(&pkt, buf->data,
|
|
643
|
+
&line_end, buf->offset);
|
|
644
|
+
else
|
|
645
|
+
error = GIT_EBUFS;
|
|
646
|
+
|
|
647
|
+
if (error < 0 && error != GIT_EBUFS)
|
|
648
|
+
return -1;
|
|
649
|
+
|
|
650
|
+
if (error == GIT_EBUFS) {
|
|
651
|
+
if ((recvd = gitno_recv(buf)) < 0)
|
|
652
|
+
return -1;
|
|
653
|
+
|
|
654
|
+
if (recvd == 0) {
|
|
655
|
+
giterr_set(GITERR_NET, "Early EOF");
|
|
656
|
+
return -1;
|
|
657
|
+
}
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
gitno_consume(buf, line_end);
|
|
662
|
+
|
|
663
|
+
error = 0;
|
|
664
|
+
|
|
665
|
+
switch (pkt->type) {
|
|
666
|
+
case GIT_PKT_DATA:
|
|
667
|
+
/* This is a sideband packet which contains other packets */
|
|
668
|
+
error = add_push_report_sideband_pkt(push, (git_pkt_data *)pkt);
|
|
669
|
+
break;
|
|
670
|
+
case GIT_PKT_ERR:
|
|
671
|
+
giterr_set(GITERR_NET, "report-status: Error reported: %s",
|
|
672
|
+
((git_pkt_err *)pkt)->error);
|
|
673
|
+
error = -1;
|
|
674
|
+
break;
|
|
675
|
+
case GIT_PKT_PROGRESS:
|
|
676
|
+
break;
|
|
677
|
+
default:
|
|
678
|
+
error = add_push_report_pkt(push, pkt);
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
git_pkt_free(pkt);
|
|
683
|
+
|
|
684
|
+
/* add_push_report_pkt returns GIT_ITEROVER when it receives a flush */
|
|
685
|
+
if (error == GIT_ITEROVER)
|
|
686
|
+
return 0;
|
|
687
|
+
|
|
688
|
+
if (error < 0)
|
|
689
|
+
return error;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
static int add_ref_from_push_spec(git_vector *refs, push_spec *push_spec)
|
|
694
|
+
{
|
|
695
|
+
git_pkt_ref *added = git__calloc(1, sizeof(git_pkt_ref));
|
|
696
|
+
GITERR_CHECK_ALLOC(added);
|
|
697
|
+
|
|
698
|
+
added->type = GIT_PKT_REF;
|
|
699
|
+
git_oid_cpy(&added->head.oid, &push_spec->loid);
|
|
700
|
+
added->head.name = git__strdup(push_spec->rref);
|
|
701
|
+
|
|
702
|
+
if (!added->head.name ||
|
|
703
|
+
git_vector_insert(refs, added) < 0) {
|
|
704
|
+
git_pkt_free((git_pkt *)added);
|
|
705
|
+
return -1;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
return 0;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
static int update_refs_from_report(
|
|
712
|
+
git_vector *refs,
|
|
713
|
+
git_vector *push_specs,
|
|
714
|
+
git_vector *push_report)
|
|
715
|
+
{
|
|
716
|
+
git_pkt_ref *ref;
|
|
717
|
+
push_spec *push_spec;
|
|
718
|
+
push_status *push_status;
|
|
719
|
+
size_t i, j, refs_len;
|
|
720
|
+
int cmp;
|
|
721
|
+
|
|
722
|
+
/* For each push spec we sent to the server, we should have
|
|
723
|
+
* gotten back a status packet in the push report */
|
|
724
|
+
if (push_specs->length != push_report->length) {
|
|
725
|
+
giterr_set(GITERR_NET, "report-status: protocol error");
|
|
726
|
+
return -1;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/* We require that push_specs be sorted with push_spec_rref_cmp,
|
|
730
|
+
* and that push_report be sorted with push_status_ref_cmp */
|
|
731
|
+
git_vector_sort(push_specs);
|
|
732
|
+
git_vector_sort(push_report);
|
|
733
|
+
|
|
734
|
+
git_vector_foreach(push_specs, i, push_spec) {
|
|
735
|
+
push_status = git_vector_get(push_report, i);
|
|
736
|
+
|
|
737
|
+
/* For each push spec we sent to the server, we should have
|
|
738
|
+
* gotten back a status packet in the push report which matches */
|
|
739
|
+
if (strcmp(push_spec->rref, push_status->ref)) {
|
|
740
|
+
giterr_set(GITERR_NET, "report-status: protocol error");
|
|
741
|
+
return -1;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/* We require that refs be sorted with ref_name_cmp */
|
|
746
|
+
git_vector_sort(refs);
|
|
747
|
+
i = j = 0;
|
|
748
|
+
refs_len = refs->length;
|
|
749
|
+
|
|
750
|
+
/* Merge join push_specs with refs */
|
|
751
|
+
while (i < push_specs->length && j < refs_len) {
|
|
752
|
+
push_spec = git_vector_get(push_specs, i);
|
|
753
|
+
push_status = git_vector_get(push_report, i);
|
|
754
|
+
ref = git_vector_get(refs, j);
|
|
755
|
+
|
|
756
|
+
cmp = strcmp(push_spec->rref, ref->head.name);
|
|
757
|
+
|
|
758
|
+
/* Iterate appropriately */
|
|
759
|
+
if (cmp <= 0) i++;
|
|
760
|
+
if (cmp >= 0) j++;
|
|
761
|
+
|
|
762
|
+
/* Add case */
|
|
763
|
+
if (cmp < 0 &&
|
|
764
|
+
!push_status->msg &&
|
|
765
|
+
add_ref_from_push_spec(refs, push_spec) < 0)
|
|
766
|
+
return -1;
|
|
767
|
+
|
|
768
|
+
/* Update case, delete case */
|
|
769
|
+
if (cmp == 0 &&
|
|
770
|
+
!push_status->msg)
|
|
771
|
+
git_oid_cpy(&ref->head.oid, &push_spec->loid);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
for (; i < push_specs->length; i++) {
|
|
775
|
+
push_spec = git_vector_get(push_specs, i);
|
|
776
|
+
push_status = git_vector_get(push_report, i);
|
|
777
|
+
|
|
778
|
+
/* Add case */
|
|
779
|
+
if (!push_status->msg &&
|
|
780
|
+
add_ref_from_push_spec(refs, push_spec) < 0)
|
|
781
|
+
return -1;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/* Remove any refs which we updated to have a zero OID. */
|
|
785
|
+
git_vector_rforeach(refs, i, ref) {
|
|
786
|
+
if (git_oid_iszero(&ref->head.oid)) {
|
|
787
|
+
git_vector_remove(refs, i);
|
|
788
|
+
git_pkt_free((git_pkt *)ref);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
git_vector_sort(refs);
|
|
793
|
+
|
|
794
|
+
return 0;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
static int stream_thunk(void *buf, size_t size, void *data)
|
|
798
|
+
{
|
|
799
|
+
git_smart_subtransport_stream *s = (git_smart_subtransport_stream *)data;
|
|
800
|
+
|
|
801
|
+
return s->write(s, (const char *)buf, size);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
int git_smart__push(git_transport *transport, git_push *push)
|
|
805
|
+
{
|
|
806
|
+
transport_smart *t = (transport_smart *)transport;
|
|
807
|
+
git_smart_subtransport_stream *s;
|
|
808
|
+
git_buf pktline = GIT_BUF_INIT;
|
|
809
|
+
int error = -1;
|
|
810
|
+
|
|
811
|
+
#ifdef PUSH_DEBUG
|
|
812
|
+
{
|
|
813
|
+
git_remote_head *head;
|
|
814
|
+
push_spec *spec;
|
|
815
|
+
unsigned int i;
|
|
816
|
+
char hex[41]; hex[40] = '\0';
|
|
817
|
+
|
|
818
|
+
git_vector_foreach(&push->remote->refs, i, head) {
|
|
819
|
+
git_oid_fmt(hex, &head->oid);
|
|
820
|
+
fprintf(stderr, "%s (%s)\n", hex, head->name);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
git_vector_foreach(&push->specs, i, spec) {
|
|
824
|
+
git_oid_fmt(hex, &spec->roid);
|
|
825
|
+
fprintf(stderr, "%s (%s) -> ", hex, spec->lref);
|
|
826
|
+
git_oid_fmt(hex, &spec->loid);
|
|
827
|
+
fprintf(stderr, "%s (%s)\n", hex, spec->rref ?
|
|
828
|
+
spec->rref : spec->lref);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
#endif
|
|
832
|
+
|
|
833
|
+
if (git_smart__get_push_stream(t, &s) < 0 ||
|
|
834
|
+
gen_pktline(&pktline, push) < 0 ||
|
|
835
|
+
s->write(s, git_buf_cstr(&pktline), git_buf_len(&pktline)) < 0 ||
|
|
836
|
+
git_packbuilder_foreach(push->pb, &stream_thunk, s) < 0)
|
|
837
|
+
goto on_error;
|
|
838
|
+
|
|
839
|
+
/* If we sent nothing or the server doesn't support report-status, then
|
|
840
|
+
* we consider the pack to have been unpacked successfully */
|
|
841
|
+
if (!push->specs.length || !push->report_status)
|
|
842
|
+
push->unpack_ok = 1;
|
|
843
|
+
else if (parse_report(&t->buffer, push) < 0)
|
|
844
|
+
goto on_error;
|
|
845
|
+
|
|
846
|
+
if (push->status.length &&
|
|
847
|
+
update_refs_from_report(&t->refs, &push->specs, &push->status) < 0)
|
|
848
|
+
goto on_error;
|
|
849
|
+
|
|
850
|
+
error = 0;
|
|
851
|
+
|
|
852
|
+
on_error:
|
|
853
|
+
git_buf_free(&pktline);
|
|
854
|
+
|
|
855
|
+
return error;
|
|
856
|
+
}
|