]> git.proxmox.com Git - libgit2.git/blame - src/fetch.c
Update Copyright header
[libgit2.git] / src / fetch.c
CommitLineData
e1f4a761 1/*
5e0de328 2 * Copyright (C) 2009-2012 the libgit2 contributors
e1f4a761 3 *
bb742ede
VM
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.
e1f4a761
CMN
6 */
7
8#include "git2/remote.h"
9#include "git2/oid.h"
10#include "git2/refs.h"
65fbc48a 11#include "git2/revwalk.h"
e1f4a761
CMN
12
13#include "common.h"
14#include "transport.h"
15#include "remote.h"
16#include "refspec.h"
01ad7b3a 17#include "pack.h"
e1d88030 18#include "fetch.h"
2c982daa 19#include "netops.h"
e1f4a761 20
d88d4311
VM
21struct filter_payload {
22 git_remote *remote;
e1f4a761 23 const git_refspec *spec;
d88d4311
VM
24 git_odb *odb;
25 int found_head;
26};
27
28static int filter_ref__cb(git_remote_head *head, void *payload)
29{
30 struct filter_payload *p = payload;
65fbc48a 31 int error;
e1f4a761 32
d88d4311
VM
33 if (!p->found_head && strcmp(head->name, GIT_HEAD_FILE) == 0) {
34 p->found_head = 1;
35 } else {
36 /* If it doesn't match the refpec, we don't want it */
37 error = git_refspec_src_match(p->spec, head->name);
e1f4a761 38
d88d4311
VM
39 if (error == GIT_ENOMATCH)
40 return GIT_SUCCESS;
41
42 if (error < GIT_SUCCESS)
43 return git__rethrow(error, "Error matching remote ref name");
e1f4a761
CMN
44 }
45
d88d4311
VM
46 /* If we have the object, mark it so we don't ask for it */
47 if (git_odb_exists(p->odb, &head->oid))
48 head->local = 1;
49 else
50 p->remote->need_pack = 1;
51
52 return git_vector_insert(&p->remote->refs, head);
53}
54
55static int filter_wants(git_remote *remote)
56{
57 int error;
58 struct filter_payload p;
59
60 git_vector_clear(&remote->refs);
9462c471 61
4a3b18a6
CMN
62 /*
63 * The fetch refspec can be NULL, and what this means is that the
64 * user didn't specify one. This is fine, as it means that we're
65 * not interested in any particular branch but just the remote's
66 * HEAD, which will be stored in FETCH_HEAD after the fetch.
67 */
d88d4311
VM
68 p.spec = git_remote_fetchspec(remote);
69 p.found_head = 0;
70 p.remote = remote;
e1f4a761 71
d88d4311
VM
72 error = git_repository_odb__weakptr(&p.odb, remote->repo);
73 if (error < GIT_SUCCESS)
74 return error;
e1f4a761 75
d88d4311 76 return remote->transport->ls(remote->transport, &filter_ref__cb, &p);
e1f4a761 77}
65fbc48a 78
65fbc48a
CMN
79/*
80 * In this first version, we push all our refs in and start sending
81 * them out. When we get an ACK we hide that commit and continue
82 * traversing until we're done
83 */
e1d88030 84int git_fetch_negotiate(git_remote *remote)
65fbc48a 85{
65fbc48a 86 int error;
b5a8aa94 87 git_transport *t = remote->transport;
65fbc48a 88
e1d88030
CMN
89 error = filter_wants(remote);
90 if (error < GIT_SUCCESS)
91 return git__rethrow(error, "Failed to filter the reference list for wants");
92
da290220 93 /* Don't try to negotiate when we don't want anything */
d88d4311 94 if (remote->refs.length == 0)
e1d88030 95 return GIT_SUCCESS;
d88d4311 96
427ca3d3
CMN
97 if (!remote->need_pack)
98 return GIT_SUCCESS;
99
7e1a94db
CMN
100 /*
101 * Now we have everything set up so we can start tell the server
102 * what we want and what we have.
103 */
b5a8aa94 104 return t->negotiate_fetch(t, remote->repo, &remote->refs);
65fbc48a
CMN
105}
106
9cf0f287 107int git_fetch_download_pack(char **out, git_remote *remote)
65fbc48a 108{
48a65a07
CMN
109 if(!remote->need_pack) {
110 *out = NULL;
111 return GIT_SUCCESS;
112 }
113
b5a8aa94 114 return remote->transport->download_pack(out, remote->transport, remote->repo);
65fbc48a 115}
2c982daa
CMN
116
117/* Receiving data from a socket and storing it is pretty much the same for git and HTTP */
97769280
RB
118int git_fetch__download_pack(
119 char **out,
120 const char *buffered,
121 size_t buffered_size,
122 GIT_SOCKET fd,
123 git_repository *repo)
2c982daa 124{
b762e576 125 git_filebuf file = GIT_FILEBUF_INIT;
2c982daa 126 int error;
97769280
RB
127 char buff[1024];
128 git_buf path = GIT_BUF_INIT;
2c982daa
CMN
129 static const char suff[] = "/objects/pack/pack-received";
130 gitno_buffer buf;
131
2c982daa
CMN
132 gitno_buffer_setup(&buf, buff, sizeof(buff), fd);
133
134 if (memcmp(buffered, "PACK", strlen("PACK"))) {
135 return git__throw(GIT_ERROR, "The pack doesn't start with the signature");
136 }
137
97769280
RB
138 error = git_buf_joinpath(&path, repo->path_repository, suff);
139 if (error < GIT_SUCCESS)
140 goto cleanup;
141
142 error = git_filebuf_open(&file, path.ptr, GIT_FILEBUF_TEMPORARY);
2c982daa
CMN
143 if (error < GIT_SUCCESS)
144 goto cleanup;
145
146 /* Part of the packfile has been received, don't loose it */
147 error = git_filebuf_write(&file, buffered, buffered_size);
148 if (error < GIT_SUCCESS)
149 goto cleanup;
150
151 while (1) {
152 error = git_filebuf_write(&file, buf.data, buf.offset);
153 if (error < GIT_SUCCESS)
154 goto cleanup;
155
156 gitno_consume_n(&buf, buf.offset);
157 error = gitno_recv(&buf);
158 if (error < GIT_SUCCESS)
159 goto cleanup;
160 if (error == 0) /* Orderly shutdown */
161 break;
162 }
163
164 *out = git__strdup(file.path_lock);
165 if (*out == NULL) {
166 error = GIT_ENOMEM;
167 goto cleanup;
168 }
169
170 /* A bit dodgy, but we need to keep the pack at the temporary path */
01ad7b3a 171 error = git_filebuf_commit_at(&file, file.path_lock, GIT_PACK_FILE_MODE);
2c982daa
CMN
172cleanup:
173 if (error < GIT_SUCCESS)
174 git_filebuf_cleanup(&file);
97769280 175 git_buf_free(&path);
2c982daa
CMN
176
177 return error;
2c982daa 178}