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.clone;
8
9 import git.checkout;
10 import git.credentials;
11 import git.remote;
12 import git.repository;
13 import git.transport;
14 import git.types;
15 import git.util;
16 import git.version_;
17
18 import deimos.git2.clone;
19 import deimos.git2.remote;
20 import deimos.git2.transport;
21 import deimos.git2.types;
22
23 ///
24 struct GitCloneOptions
25 {
26 uint version_ = git_clone_options.init.version_;
27
28 GitCheckoutOptions checkoutOptions;
29
30 bool cloneBare;
31
32 static if (targetLibGitVersion == VersionInfo(0, 19, 0)) TransferCallbackDelegate fetchProgessCallback;
33
34 string remoteName;
35 static if (targetLibGitVersion == VersionInfo(0, 19, 0)) {
36 string pushURL;
37 string fetchSpec;
38 string pushSpec;
39
40 GitCredAcquireDelegate credAcquireCallback;
41
42 GitTransportFlags transportFlags;
43 // GitTransport transport; // TODO: translate
44 // GitRemoteCallback[] remoteCallbacks; // TODO: implement translation
45 GitRemoteAutotagOption remoteAutotag;
46 }
47 string checkoutBranch;
48 }
49
50
51 static if (targetLibGitVersion == VersionInfo(0, 19, 0)) {
52 extern(C) nothrow int cFetchProgessCallback(
53 const(git_transfer_progress)* stats,
54 void* payload)
55 {
56 auto dg = (cast(GitCloneOptions*)payload).fetchProgessCallback;
57 if (dg) {
58 try {
59 auto tp = GitTransferProgress(stats);
60 dg(tp);
61 } catch (Exception e) {
62 return -1;
63 }
64 }
65 return 0;
66 }
67
68 extern(C) int cCredAcquireCallback(
69 git_cred** cred,
70 const(char)* url,
71 const(char)* username_from_url,
72 uint allowed_types,
73 void* payload)
74 {
75 auto dg = (cast(GitCloneOptions*)payload).credAcquireCallback;
76 if (dg)
77 {
78 auto dCred = dg(toSlice(url), toSlice(username_from_url), allowed_types);
79 // FIXME: cred will probably be immediately freed.
80 *cred = dCred.cHandle;
81 return 0;
82 }
83
84 // FIXME: Use real error code here.
85 return 1;
86 }
87 }
88
89 GitRepo cloneRepo(in char[] url, in char[] localPath, GitCloneOptions options = GitCloneOptions.init)
90 {
91 git_clone_options cOpts;
92 with (options)
93 {
94 cOpts.version_ = version_;
95 checkoutOptions.toCCheckoutOpts(cOpts.checkout_opts);
96 cOpts.bare = cloneBare;
97 static if (targetLibGitVersion == VersionInfo(0, 19, 0)) {
98 if (fetchProgessCallback)
99 {
100 cOpts.fetch_progress_cb = &cFetchProgessCallback;
101 cOpts.fetch_progress_payload = &cOpts;
102 }
103 }
104 cOpts.remote_name = remoteName.gitStr;
105 static if (targetLibGitVersion == VersionInfo(0, 19, 0)) {
106 cOpts.pushurl = pushURL.gitStr;
107 cOpts.fetch_spec = fetchSpec.gitStr;
108 cOpts.push_spec = pushSpec.gitStr;
109 if (credAcquireCallback)
110 {
111 cOpts.cred_acquire_cb = &cCredAcquireCallback;
112 cOpts.cred_acquire_payload = &cOpts;
113 }
114 cOpts.transport_flags = transportFlags;
115 // cOpts.transport = // TODO: Translate.
116 cOpts.remote_autotag = cast(git_remote_autotag_option_t)remoteAutotag;
117 }
118 cOpts.checkout_branch = checkoutBranch.gitStr;
119 }
120
121 git_repository* repo;
122 auto errc = git_clone(&repo, url.gitStr, localPath.gitStr, &cOpts);
123 require(errc == 0);
124 return GitRepo(repo);
125 }