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 
17 import git2.clone;
18 import git2.remote;
19 import git2.transport;
20 import git2.types;
21 
22 ///
23 struct GitCloneOptions
24 {
25     uint version_ = git_clone_options.init.version_;
26 
27     static assert(false, "TODO");
28     //GitCheckoutOptions checkoutOptions;
29     //git_remote_callbacks remote_callbacks;
30 
31     //bool ignoreCertErrors;
32     bool cloneBare;
33 
34     TransferCallbackDelegate fetchProgessCallback;
35 
36     string remoteName;
37     string pushURL;
38     string fetchSpec;
39     string pushSpec;
40 
41     GitCredAcquireDelegate credAcquireCallback;
42 
43     GitTransportFlags transportFlags;
44     // GitTransport transport; // TODO: translate
45     // GitRemoteCallback[] remoteCallbacks; // TODO: implement translation
46     GitRemoteAutotagOption remoteAutotag;
47     string checkoutBranch;
48 }
49 
50 
51 extern(C) int cFetchProgessCallback(
52     const(git_transfer_progress)* stats,
53     void* payload)
54 {
55     auto dg = (cast(GitCloneOptions*)payload).fetchProgessCallback;
56     if (dg)
57     {
58         GitTransferProgress tp;
59         tp.tupleof = stats.tupleof;
60         return dg(tp);
61     }
62     else
63     {
64         return 0;
65     }
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 GitRepo cloneRepo(in char[] url, in char[] localPath, GitCloneOptions options = GitCloneOptions.init)
89 {
90     git_clone_options cOpts;
91     with (options)
92     {
93         cOpts.version_ = version_;
94         checkoutOptions.toCCheckoutOpts(cOpts.checkout_opts);
95         cOpts.bare = cloneBare;
96         if (fetchProgessCallback)
97         {
98             cOpts.fetch_progress_cb = &cFetchProgessCallback;
99             cOpts.fetch_progress_payload = &cOpts;
100         }
101         cOpts.remote_name = remoteName.gitStr;
102         cOpts.pushurl = pushURL.gitStr;
103         cOpts.fetch_spec = fetchSpec.gitStr;
104         cOpts.push_spec = pushSpec.gitStr;
105         if (credAcquireCallback)
106         {
107             cOpts.cred_acquire_cb = &cCredAcquireCallback;
108             cOpts.cred_acquire_payload = &cOpts;
109         }
110         cOpts.transport_flags = transportFlags;
111         // cOpts.transport = // TODO: Translate.
112         cOpts.remote_autotag = cast(git_remote_autotag_option_t)remoteAutotag;
113         cOpts.checkout_branch = checkoutBranch.gitStr;
114     }
115 
116     git_repository* repo;
117     auto errc = git_clone(&repo, url.gitStr, localPath.gitStr, &cOpts);
118     require(errc == 0);
119     return GitRepo(repo);
120 }