1 module libgit2.example.fetch; 2 3 4 private static import core.stdc.stdio; 5 private static import core.stdc.stdlib; 6 private static import libgit2.example.common; 7 private static import libgit2.indexer; 8 private static import libgit2.oid; 9 private static import libgit2.remote; 10 private static import libgit2.types; 11 12 extern (C) 13 nothrow @nogc 14 private int progress_cb(const (char)* str, int len, void* data) 15 16 in 17 { 18 } 19 20 do 21 { 22 //cast(void)(data); 23 core.stdc.stdio.printf("remote: %.*s", len, str); 24 25 /* We don't have the \n to force the flush */ 26 core.stdc.stdio.fflush(core.stdc.stdio.stdout); 27 28 return 0; 29 } 30 31 /** 32 * This function gets called for each remote-tracking branch that gets 33 * updated. The message we output depends on whether it's a new one or 34 * an update. 35 */ 36 extern (C) 37 nothrow @nogc 38 private int update_cb(const (char)* refname, const (libgit2.oid.git_oid)* a, const (libgit2.oid.git_oid)* b, void* data) 39 40 in 41 { 42 } 43 44 do 45 { 46 //cast(void)(data); 47 48 char[libgit2.oid.GIT_OID_SHA1_HEXSIZE + 1] b_str; 49 libgit2.oid.git_oid_fmt(&(b_str[0]), b); 50 b_str[libgit2.oid.GIT_OID_SHA1_HEXSIZE] = '\0'; 51 52 if (libgit2.oid.git_oid_is_zero(a)) { 53 core.stdc.stdio.printf("[new] %.20s %s\n", &(b_str[0]), refname); 54 } else { 55 char[libgit2.oid.GIT_OID_SHA1_HEXSIZE + 1] a_str; 56 libgit2.oid.git_oid_fmt(&(a_str[0]), a); 57 a_str[libgit2.oid.GIT_OID_SHA1_HEXSIZE] = '\0'; 58 core.stdc.stdio.printf("[updated] %.10s..%.10s %s\n", &(a_str[0]), &(b_str[0]), refname); 59 } 60 61 return 0; 62 } 63 64 /** 65 * This gets called during the download and indexing. Here we show 66 * processed and total objects in the pack and the amount of received 67 * data. Most frontends will probably want to show a percentage and 68 * the download rate. 69 */ 70 extern (C) 71 nothrow @nogc 72 private int transfer_progress_cb(const (libgit2.indexer.git_indexer_progress)* stats, void* payload) 73 74 in 75 { 76 } 77 78 do 79 { 80 //cast(void)(payload); 81 82 if (stats.received_objects == stats.total_objects) { 83 core.stdc.stdio.printf("Resolving deltas %u/%u\r", stats.indexed_deltas, stats.total_deltas); 84 } else if (stats.total_objects > 0) { 85 core.stdc.stdio.printf("Received %u/%u objects (%u) in %" ~ libgit2.example.common.PRIuZ ~ " bytes\r", stats.received_objects, stats.total_objects, stats.indexed_objects, stats.received_bytes); 86 } 87 88 return 0; 89 } 90 91 /** 92 * Entry point for this command 93 */ 94 extern (C) 95 nothrow @nogc 96 public int lg2_fetch(libgit2.types.git_repository* repo, int argc, char** argv) 97 98 in 99 { 100 } 101 102 do 103 { 104 if (argc < 2) { 105 core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "usage: %s fetch <repo>\n", argv[-1]); 106 107 return core.stdc.stdlib.EXIT_FAILURE; 108 } 109 110 /* Figure out whether it's a named remote or a URL */ 111 core.stdc.stdio.printf("Fetching %s for repo %p\n", argv[1], repo); 112 113 libgit2.types.git_remote* remote = null; 114 115 scope (exit) { 116 libgit2.remote.git_remote_free(remote); 117 } 118 119 if (libgit2.remote.git_remote_lookup(&remote, repo, argv[1]) < 0) { 120 if (libgit2.remote.git_remote_create_anonymous(&remote, repo, argv[1]) < 0) { 121 return -1; 122 } 123 } 124 125 /* Set up the callbacks (only update_tips for now) */ 126 libgit2.remote.git_fetch_options fetch_opts = libgit2.remote.GIT_FETCH_OPTIONS_INIT(); 127 fetch_opts.callbacks.update_tips = &.update_cb; 128 fetch_opts.callbacks.sideband_progress = &.progress_cb; 129 fetch_opts.callbacks.transfer_progress = &.transfer_progress_cb; 130 fetch_opts.callbacks.credentials = &libgit2.example.common.cred_acquire_cb; 131 132 /** 133 * Perform the fetch with the configured refspecs from the 134 * config. Update the reflog for the updated references with 135 * "fetch". 136 */ 137 if (libgit2.remote.git_remote_fetch(remote, null, &fetch_opts, "fetch") < 0) { 138 return -1; 139 } 140 141 /** 142 * If there are local objects (we got a thin pack), then tell 143 * the user how many objects we saved from having to cross the 144 * network. 145 */ 146 const (libgit2.indexer.git_indexer_progress)* stats = libgit2.remote.git_remote_stats(remote); 147 148 if (stats.local_objects > 0) { 149 core.stdc.stdio.printf("\rReceived %u/%u objects in %" ~ libgit2.example.common.PRIuZ ~ " bytes (used %u local objects)\n", stats.indexed_objects, stats.total_objects, stats.received_bytes, stats.local_objects); 150 } else { 151 core.stdc.stdio.printf("\rReceived %u/%u objects in %" ~ libgit2.example.common.PRIuZ ~ "bytes\n", stats.indexed_objects, stats.total_objects, stats.received_bytes); 152 } 153 154 libgit2.remote.git_remote_free(remote); 155 156 return 0; 157 }