1 /*
2   *             Copyright David Nadlinger 2014.
3  *  Distributed under the Boost Software License, Version 1.0.
4  *     (See accompanying file LICENSE_1_0.txt or copy at
5  *           http://www.boost.org/LICENSE_1_0.txt)
6  */
7 module git.remote;
8 
9 import git.repository;
10 import git.types;
11 import git.util;
12 
13 import git2.net;
14 import git2.remote;
15 import git2.types;
16 
17 import std.conv : to;
18 
19 ///
20 enum GitDirection
21 {
22     ///
23     fetch = GIT_DIRECTION_FETCH,
24 
25     ///
26     push = GIT_DIRECTION_PUSH
27 }
28 
29 ///
30 enum GitRemoteAutotagOption
31 {
32     ///
33     automatic = 0,
34 
35     ///
36     none = 1,
37 
38     ///
39     all = 2
40 }
41 
42 
43 ///
44 struct GitRemote
45 {
46     // Internal, see free-standing constructor functions below.
47     private this(GitRepo repo, git_remote* remote)
48     {
49         _repo = repo;
50         _data = Data(remote);
51     }
52 
53     ///
54     void save()
55     {
56         require(git_remote_save(_data._payload) == 0);
57     }
58 
59     ///
60     @property string name() const
61     {
62         return to!string(git_remote_name(_data._payload));
63     }
64 
65     ///
66     @property string url() const
67     {
68         return to!string(git_remote_url(_data._payload));
69     }
70 
71     ///
72     @property void name(in char[] url)
73     {
74         require(git_remote_set_url(_data._payload, url.gitStr) == 0);
75     }
76 
77     ///
78     @property string pushURL() const
79     {
80         return to!string(git_remote_pushurl(_data._payload));
81     }
82 
83     ///
84     @property void pushURL(in char[] url)
85     {
86         require(git_remote_set_pushurl(_data._payload, url.gitStr) == 0);
87     }
88 
89     ///
90     void connect(GitDirection direction)
91     {
92         require(git_remote_connect(_data._payload, cast(git_direction)direction) == 0);
93     }
94 
95     ///
96     @property bool connected()
97     {
98         return git_remote_connected(_data._payload) != 0;
99     }
100 
101     ///
102     void stop()
103     {
104         git_remote_stop(_data._payload);
105     }
106 
107     ///
108     void disconnect()
109     {
110         git_remote_disconnect(_data._payload);
111     }
112 
113     ///
114     void download(TransferCallbackDelegate progressCallback = null)
115     {
116         static struct Ctx { TransferCallbackDelegate dg; }
117         extern(C) static int cCallback(const(git_transfer_progress)* stats, void* payload)
118         {
119             auto dg = (cast(Ctx*)payload).dg;
120             if (dg)
121             {
122                 GitTransferProgress tp;
123                 tp.tupleof = stats.tupleof;
124                 return dg(tp);
125             }
126             else
127             {
128                 return 0;
129             }
130         }
131 
132         assert(connected, "Must connect(GitDirection.push) before invoking download().");
133 
134         immutable ctx = Ctx(progressCallback);
135         if (progressCallback)
136         {
137             require(git_remote_download(_data._payload, &cCallback, cast(void*)&ctx) == 0);
138         }
139         else
140         {
141             require(git_remote_download(_data._payload, null, null) == 0);
142         }
143     }
144 
145 private:
146     struct Payload
147     {
148         this(git_remote* payload)
149         {
150             _payload = payload;
151         }
152 
153         ~this()
154         {
155             if (_payload !is null)
156             {
157                 git_remote_free(_payload);
158                 _payload = null;
159             }
160         }
161 
162         /// Should never perform copy
163         @disable this(this);
164 
165         /// Should never perform assign
166         @disable void opAssign(typeof(this));
167 
168         git_remote* _payload;
169     }
170 
171     // Reference to the parent repository to keep it alive.
172     GitRepo _repo;
173 
174     import std.typecons : RefCounted, RefCountedAutoInitialize;
175     alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data;
176     Data _data;
177 }
178 
179 ///
180 GitRemote createRemote(GitRepo repo, in char[] name, in char[] url)
181 {
182     git_remote* result;
183     require(git_remote_create(&result, repo.cHandle, name.gitStr, url.gitStr) == 0);
184     return GitRemote(repo, result);
185 }
186 
187 ///
188 GitRemote createRemoteInMemory(GitRepo repo, in char[] fetch, in char[] url)
189 {
190     git_remote* result;
191     require(git_remote_create_inmemory(&result, repo.cHandle, fetch.gitStr, url.gitStr) == 0);
192     return GitRemote(repo, result);
193 }
194 
195 ///
196 GitRemote loadRemote(GitRepo repo, in char[] name)
197 {
198     git_remote* result;
199     require(git_remote_load(&result, repo.cHandle, name.gitStr) == 0);
200     return GitRemote(repo, result);
201 }
202 
203 
204 /+ TODO: Port these.
205 
206 extern (C):
207 
208 alias git_remote_rename_problem_cb = int function(const(char)* problematic_refspec, void *payload);
209 
210 int git_remote_add_fetch(git_remote *remote, const(char)* refspec);
211 
212 int git_remote_get_fetch_refspecs(git_strarray *array, git_remote *remote);
213 
214 int git_remote_add_push(git_remote *remote, const(char)* refspec);
215 
216 int git_remote_get_push_refspecs(git_strarray *array, git_remote *remote);
217 
218 void git_remote_clear_refspecs(git_remote *remote);
219 
220 size_t git_remote_refspec_count(git_remote *remote);
221 
222 const(git_refspec)* git_remote_get_refspec(git_remote *remote, size_t n);
223 
224 int git_remote_remove_refspec(git_remote *remote, size_t n);
225 
226 int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload);
227 
228 int git_remote_update_tips(git_remote *remote);
229 
230 int git_remote_valid_url(const(char)* url);
231 
232 int git_remote_supported_url(const(char)* url);
233 
234 int git_remote_list(git_strarray *out_, git_repository *repo);
235 
236 void git_remote_check_cert(git_remote *remote, int check);
237 
238 void git_remote_set_cred_acquire_cb(
239     git_remote *remote,
240     git_cred_acquire_cb cred_acquire_cb,
241     void *payload);
242 
243 int git_remote_set_transport(
244     git_remote *remote,
245     git_transport *transport);
246 
247 enum git_remote_completion_type {
248     GIT_REMOTE_COMPLETION_DOWNLOAD,
249     GIT_REMOTE_COMPLETION_INDEXING,
250     GIT_REMOTE_COMPLETION_ERROR,
251 } ;
252 
253 mixin _ExportEnumMembers!git_remote_completion_type;
254 
255 struct git_remote_callbacks {
256     uint version_ = GIT_REMOTE_CALLBACKS_VERSION;
257     void function(const(char)* str, int len, void *data) progress;
258     int function(git_remote_completion_type type, void *data) completion;
259     int function(const(char)* refname, const(git_oid)* a, const(git_oid)* b, void *data) update_tips;
260     void *payload;
261 }
262 
263 enum GIT_REMOTE_CALLBACKS_VERSION = 1;
264 enum git_remote_callbacks GIT_REMOTE_CALLBACKS_INIT = { GIT_REMOTE_CALLBACKS_VERSION };
265 
266 int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks);
267 
268 const(git_transfer_progress)*  git_remote_stats(git_remote *remote);
269 
270 enum git_remote_autotag_option_t {
271     GIT_REMOTE_DOWNLOAD_TAGS_AUTO = 0,
272     GIT_REMOTE_DOWNLOAD_TAGS_NONE = 1,
273     GIT_REMOTE_DOWNLOAD_TAGS_ALL = 2
274 } ;
275 
276 mixin _ExportEnumMembers!git_remote_autotag_option_t;
277 
278 git_remote_autotag_option_t git_remote_autotag(git_remote *remote);
279 
280 void git_remote_set_autotag(
281     git_remote *remote,
282     git_remote_autotag_option_t value);
283 
284 int git_remote_rename(
285     git_remote *remote,
286     const(char)* new_name,
287     git_remote_rename_problem_cb callback,
288     void *payload);
289 
290 int git_remote_update_fetchhead(git_remote *remote);
291 
292 void git_remote_set_update_fetchhead(git_remote *remote, int value);
293 
294 int git_remote_is_valid_name(const(char)* remote_name);
295 
296 +/