]>
Commit | Line | Data |
---|---|---|
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 | ||
e1f4a761 CMN |
8 | #include "git2/oid.h" |
9 | #include "git2/refs.h" | |
65fbc48a | 10 | #include "git2/revwalk.h" |
41fb1ca0 | 11 | #include "git2/transport.h" |
e1f4a761 CMN |
12 | |
13 | #include "common.h" | |
e1f4a761 CMN |
14 | #include "remote.h" |
15 | #include "refspec.h" | |
01ad7b3a | 16 | #include "pack.h" |
e1d88030 | 17 | #include "fetch.h" |
2c982daa | 18 | #include "netops.h" |
7bcd9e23 | 19 | |
d88d4311 VM |
20 | struct filter_payload { |
21 | git_remote *remote; | |
3230a44f | 22 | const git_refspec *spec, *tagspec; |
d88d4311 VM |
23 | git_odb *odb; |
24 | int found_head; | |
25 | }; | |
26 | ||
27 | static int filter_ref__cb(git_remote_head *head, void *payload) | |
28 | { | |
29 | struct filter_payload *p = payload; | |
3230a44f | 30 | int match = 0; |
e1f4a761 | 31 | |
3230a44f CMN |
32 | if (!git_reference_is_valid_name(head->name)) |
33 | return 0; | |
34 | ||
35 | if (!p->found_head && strcmp(head->name, GIT_HEAD_FILE) == 0) | |
d88d4311 | 36 | p->found_head = 1; |
3230a44f CMN |
37 | else if (git_refspec_src_matches(p->spec, head->name)) |
38 | match = 1; | |
39 | else if (p->remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL && | |
40 | git_refspec_src_matches(p->tagspec, head->name)) | |
41 | match = 1; | |
11678b37 | 42 | |
3230a44f CMN |
43 | if (!match) |
44 | return 0; | |
e1f4a761 | 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 | ||
55 | static int filter_wants(git_remote *remote) | |
56 | { | |
d88d4311 | 57 | struct filter_payload p; |
3230a44f | 58 | git_refspec tagspec; |
68206c54 | 59 | int error = -1; |
d88d4311 VM |
60 | |
61 | git_vector_clear(&remote->refs); | |
3230a44f | 62 | if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) |
68206c54 | 63 | return error; |
9462c471 | 64 | |
4a3b18a6 CMN |
65 | /* |
66 | * The fetch refspec can be NULL, and what this means is that the | |
67 | * user didn't specify one. This is fine, as it means that we're | |
68 | * not interested in any particular branch but just the remote's | |
69 | * HEAD, which will be stored in FETCH_HEAD after the fetch. | |
70 | */ | |
d88d4311 | 71 | p.spec = git_remote_fetchspec(remote); |
3230a44f | 72 | p.tagspec = &tagspec; |
d88d4311 VM |
73 | p.found_head = 0; |
74 | p.remote = remote; | |
e1f4a761 | 75 | |
5eb8affb | 76 | if (git_repository_odb__weakptr(&p.odb, remote->repo) < 0) |
68206c54 | 77 | goto cleanup; |
e1f4a761 | 78 | |
68206c54 | 79 | error = git_remote_ls(remote, filter_ref__cb, &p); |
80 | ||
81 | cleanup: | |
82 | git_refspec__free(&tagspec); | |
83 | ||
84 | return error; | |
e1f4a761 | 85 | } |
65fbc48a | 86 | |
65fbc48a CMN |
87 | /* |
88 | * In this first version, we push all our refs in and start sending | |
89 | * them out. When we get an ACK we hide that commit and continue | |
90 | * traversing until we're done | |
91 | */ | |
e1d88030 | 92 | int git_fetch_negotiate(git_remote *remote) |
65fbc48a | 93 | { |
b5a8aa94 | 94 | git_transport *t = remote->transport; |
41fb1ca0 | 95 | |
5eb8affb CMN |
96 | if (filter_wants(remote) < 0) { |
97 | giterr_set(GITERR_NET, "Failed to filter the reference list for wants"); | |
98 | return -1; | |
99 | } | |
e1d88030 | 100 | |
da290220 | 101 | /* Don't try to negotiate when we don't want anything */ |
5eb8affb CMN |
102 | if (remote->refs.length == 0 || !remote->need_pack) |
103 | return 0; | |
427ca3d3 | 104 | |
7e1a94db | 105 | /* |
64d01de8 | 106 | * Now we have everything set up so we can start tell the |
41fb1ca0 | 107 | * server what we want and what we have. |
64d01de8 | 108 | */ |
41fb1ca0 PK |
109 | return t->negotiate_fetch(t, |
110 | remote->repo, | |
111 | (const git_remote_head * const *)remote->refs.contents, | |
112 | remote->refs.length); | |
65fbc48a CMN |
113 | } |
114 | ||
216863c4 | 115 | int git_fetch_download_pack( |
41fb1ca0 | 116 | git_remote *remote, |
7d222e13 | 117 | git_transfer_progress_callback progress_cb, |
216863c4 | 118 | void *progress_payload) |
2c982daa | 119 | { |
41fb1ca0 | 120 | git_transport *t = remote->transport; |
2c982daa | 121 | |
41fb1ca0 | 122 | if(!remote->need_pack) |
e03e71da | 123 | return 0; |
dee5515a | 124 | |
41fb1ca0 | 125 | return t->download_pack(t, remote->repo, &remote->stats, progress_cb, progress_payload); |
dee5515a | 126 | } |