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