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 }