1 module fetch;
2 
3 import git.c;
4 
5 import core.thread;
6 import std.concurrency;
7 import std.string;
8 import std.stdio;
9 
10 import common;
11 
12 void download()
13 {
14     // Connect to the remote end specifying that we want to fetch
15     // information from it.
16     if (git_remote_connect(fetch_data.remote, GIT_DIR_FETCH) < 0)
17     {
18         fetch_data.ret = -1;
19         goto exit;
20     }
21 
22     // Download the packfile and index it. This function updates the
23     //~ // amount of received data and the indexer stats which lets you
24     //~ // inform the user about progress.
25     if (git_remote_download(fetch_data.remote, fetch_data.bytes, fetch_data.stats) < 0)
26     {
27         fetch_data.ret = -1;
28         goto exit;
29     }
30 
31     fetch_data.ret = 0;
32 
33 exit:
34     fetch_data.finished = 1;
35 }
36 
37 int update_cb(const(char)* refname, const git_oid* a, const git_oid* b)
38 {
39     const(char)* action;
40     char[GIT_OID_HEXSZ + 1] a_str = '\0';
41     char[GIT_OID_HEXSZ + 1] b_str = '\0';
42 
43     git_oid_fmt(b_str.ptr, b);
44     b_str[GIT_OID_HEXSZ] = '\0';
45 
46     if (git_oid_iszero(a))
47     {
48         printf("[new]     %.20s %s\n", b_str, refname);
49     }
50     else
51     {
52         git_oid_fmt(a_str.ptr, a);
53         a_str[GIT_OID_HEXSZ] = '\0';
54         printf("[updated] %.10s..%.10s %s\n", a_str, b_str, refname);
55     }
56 
57     return 0;
58 }
59 
60 int run_fetch(git_repository* repo, int argc, string[] argv)
61 {
62     git_remote* remote;
63     git_off_t bytes    = 0;
64     git_indexer_stats stats;
65 
66     // Figure out whether it's a named remote or a URL
67     writefln("Fetching %s\n", argv[1]);
68 
69     if (git_remote_load(&remote, repo, argv[1].toStringz) < 0)
70     {
71         if (git_remote_new(&remote, repo, null, argv[1].toStringz, null) < 0)
72             return -1;
73     }
74 
75     // Set up the information for the background worker thread
76     fetch_data.remote   = remote;
77     fetch_data.bytes    = &bytes;
78     fetch_data.stats    = &stats;
79     fetch_data.ret      = 0;
80     fetch_data.finished = 0;
81 
82     spawn(&download);
83 
84     // Loop while the worker thread is still running. Here we show processed
85     // and total objects in the pack and the amount of received
86     // data. Most frontends will probably want to show a percentage and
87     // the download rate.
88     do
89     {
90         Thread.sleep(dur!("msecs")(100));
91         writefln("\rReceived %s/%s objects in %s bytes", stats.processed, stats.total, bytes);
92     }
93     while (!fetch_data.finished);
94 
95     writefln("\rReceived %s/%s objects in %s bytes", stats.processed, stats.total, bytes);
96 
97     // Disconnect the underlying connection to prevent from idling.
98     git_remote_disconnect(remote);
99 
100     // Update the references in the remote's namespace to point to the
101     // right commits. This may be needed even if there was no packfile
102     // to download, which can happen e.g. when the branches have been
103     // changed but all the neede objects are available locally.
104     if (git_remote_update_tips(remote) < 0)
105         return -1;
106 
107     git_remote_free(remote);
108 
109     return 0;
110 
111 on_error:
112     git_remote_free(remote);
113     return -1;
114 }