1 /* 2 * libgit2 "rev-list" example - shows how to transform a rev-spec into a list 3 * of commit ids 4 * 5 * Written by the libgit2 contributors 6 * 7 * To the extent possible under law, the author(s) have dedicated all copyright 8 * and related and neighboring rights to this software to the public domain 9 * worldwide. This software is distributed without any warranty. 10 * 11 * You should have received a copy of the CC0 Public Domain Dedication along 12 * with this software. If not, see 13 * <https://creativecommons.org/publicdomain/zero/1.0/>. 14 */ 15 /** 16 * License: $(LINK2 https://creativecommons.org/publicdomain/zero/1.0/, CC0 1.0 Universal) 17 */ 18 module libgit2.example.rev_list; 19 20 21 private static import core.stdc.stdio; 22 private static import core.stdc.stdlib; 23 private static import core.stdc.string; 24 private static import libgit2.errors; 25 private static import libgit2.example.args; 26 private static import libgit2.example.common; 27 private static import libgit2.object; 28 private static import libgit2.oid; 29 private static import libgit2.revparse; 30 private static import libgit2.revwalk; 31 private static import libgit2.types; 32 33 extern (C) 34 nothrow @nogc 35 public int lg2_rev_list(libgit2.types.git_repository* repo, int argc, char** argv) 36 37 in 38 { 39 } 40 41 do 42 { 43 libgit2.example.args.args_info args = libgit2.example.args.ARGS_INFO_INIT(argc, argv); 44 libgit2.types.git_revwalk* walk; 45 libgit2.revwalk.git_sort_t sort; 46 47 libgit2.example.common.check_lg2(.revwalk_parse_options(&sort, &args), "parsing options", null); 48 49 libgit2.example.common.check_lg2(libgit2.revwalk.git_revwalk_new(&walk, repo), "allocating revwalk", null); 50 libgit2.revwalk.git_revwalk_sorting(walk, sort); 51 libgit2.example.common.check_lg2(.revwalk_parse_revs(repo, walk, &args), "parsing revs", null); 52 53 libgit2.oid.git_oid oid; 54 char[libgit2.oid.GIT_OID_SHA1_HEXSIZE + 1] buf; 55 56 while (!libgit2.revwalk.git_revwalk_next(&oid, walk)) { 57 libgit2.oid.git_oid_fmt(&(buf[0]), &oid); 58 buf[libgit2.oid.GIT_OID_SHA1_HEXSIZE] = '\0'; 59 core.stdc.stdio.printf("%s\n", &(buf[0])); 60 } 61 62 libgit2.revwalk.git_revwalk_free(walk); 63 64 return 0; 65 } 66 67 nothrow @nogc 68 private int push_commit(libgit2.types.git_revwalk* walk, const (libgit2.oid.git_oid)* oid, int hide) 69 70 in 71 { 72 } 73 74 do 75 { 76 if (hide) { 77 return libgit2.revwalk.git_revwalk_hide(walk, oid); 78 } else { 79 return libgit2.revwalk.git_revwalk_push(walk, oid); 80 } 81 } 82 83 nothrow @nogc 84 private int push_spec(libgit2.types.git_repository* repo, libgit2.types.git_revwalk* walk, const (char)* spec, int hide) 85 86 in 87 { 88 } 89 90 do 91 { 92 libgit2.types.git_object* obj; 93 int error = libgit2.revparse.git_revparse_single(&obj, repo, spec); 94 95 if (error < 0) { 96 return error; 97 } 98 99 error = .push_commit(walk, libgit2.object.git_object_id(obj), hide); 100 libgit2.object.git_object_free(obj); 101 102 return error; 103 } 104 105 nothrow @nogc 106 private int push_range(libgit2.types.git_repository* repo, libgit2.types.git_revwalk* walk, const (char)* range, int hide) 107 108 in 109 { 110 } 111 112 do 113 { 114 libgit2.revparse.git_revspec revspec; 115 int error = libgit2.revparse.git_revparse(&revspec, repo, range); 116 117 if (error) { 118 return error; 119 } 120 121 scope (exit) { 122 libgit2.object.git_object_free(revspec.from); 123 libgit2.object.git_object_free(revspec.to); 124 } 125 126 if (revspec.flags & libgit2.revparse.git_revspec_t.GIT_REVSPEC_MERGE_BASE) { 127 /* TODO: support "<commit>...<commit>" */ 128 return libgit2.errors.git_error_code.GIT_EINVALIDSPEC; 129 } 130 131 error = .push_commit(walk, libgit2.object.git_object_id(revspec.from), !hide); 132 133 if (error) { 134 return error; 135 } 136 137 error = .push_commit(walk, libgit2.object.git_object_id(revspec.to), hide); 138 139 return error; 140 } 141 142 nothrow @nogc 143 private void print_usage() 144 145 do 146 { 147 core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "rev-list [--git-dir=dir] [--topo-order|--date-order] [--reverse] <revspec>\n"); 148 core.stdc.stdlib.exit(-1); 149 } 150 151 nothrow @nogc 152 private int revwalk_parse_options(libgit2.revwalk.git_sort_t* sort, libgit2.example.args.args_info* args) 153 154 in 155 { 156 assert((sort) && (args)); 157 } 158 159 do 160 { 161 *sort = libgit2.revwalk.git_sort_t.GIT_SORT_NONE; 162 163 if (args.argc < 1) { 164 .print_usage(); 165 } 166 167 for (args.pos = 1; args.pos < args.argc; ++args.pos) { 168 const (char)* curr = args.argv[args.pos]; 169 170 if (!core.stdc..string.strcmp(curr, "--topo-order")) { 171 *sort |= libgit2.revwalk.git_sort_t.GIT_SORT_TOPOLOGICAL; 172 } else if (!core.stdc..string.strcmp(curr, "--date-order")) { 173 *sort |= libgit2.revwalk.git_sort_t.GIT_SORT_TIME; 174 } else if (!core.stdc..string.strcmp(curr, "--reverse")) { 175 *sort |= (*sort & ~libgit2.revwalk.git_sort_t.GIT_SORT_REVERSE) ^ libgit2.revwalk.git_sort_t.GIT_SORT_REVERSE; 176 } else { 177 break; 178 } 179 } 180 181 return 0; 182 } 183 184 nothrow @nogc 185 private int revwalk_parse_revs(libgit2.types.git_repository* repo, libgit2.types.git_revwalk* walk, libgit2.example.args.args_info* args) 186 187 in 188 { 189 } 190 191 do 192 { 193 int hide = 0; 194 int error; 195 libgit2.oid.git_oid oid; 196 197 for (; args.pos < args.argc; ++args.pos) { 198 const (char)* curr = args.argv[args.pos]; 199 200 if (!core.stdc..string.strcmp(curr, "--not")) { 201 hide = !hide; 202 } else if (curr[0] == '^') { 203 error = .push_spec(repo, walk, curr + 1, !hide); 204 205 if (error) { 206 return error; 207 } 208 } else if (core.stdc..string.strstr(curr, "..")) { 209 error = .push_range(repo, walk, curr, hide); 210 211 if (error) { 212 return error; 213 } 214 } else { 215 if (.push_spec(repo, walk, curr, hide) == 0) { 216 continue; 217 } 218 219 version (GIT_EXPERIMENTAL_SHA256) { 220 error = libgit2.oid.git_oid_fromstr(&oid, curr, libgit2.oid.git_oid_t.GIT_OID_SHA1); 221 222 if (error) { 223 return error; 224 } 225 } else { 226 error = libgit2.oid.git_oid_fromstr(&oid, curr); 227 228 if (error) { 229 return error; 230 } 231 } 232 233 error = .push_commit(walk, &oid, hide); 234 235 if (error) { 236 return error; 237 } 238 } 239 } 240 241 return 0; 242 }