istagit-gopher.c - stagit-gopher - A git gopher frontend. (mirror) Err bitreich.org 70 hgit clone git://bitreich.org/stagit-gopher/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/stagit-gopher/ URL:git://bitreich.org/stagit-gopher/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/stagit-gopher/ bitreich.org 70 1Log /scm/stagit-gopher/log.gph bitreich.org 70 1Files /scm/stagit-gopher/files.gph bitreich.org 70 1Refs /scm/stagit-gopher/refs.gph bitreich.org 70 1Tags /scm/stagit-gopher/tag bitreich.org 70 1README /scm/stagit-gopher/file/README.gph bitreich.org 70 1LICENSE /scm/stagit-gopher/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 istagit-gopher.c (35494B) Err bitreich.org 70 i--- Err bitreich.org 70 i 1 #include Err bitreich.org 70 i 2 #include Err bitreich.org 70 i 3 Err bitreich.org 70 i 4 #include Err bitreich.org 70 i 5 #include Err bitreich.org 70 i 6 #include Err bitreich.org 70 i 7 #include Err bitreich.org 70 i 8 #include Err bitreich.org 70 i 9 #include Err bitreich.org 70 i 10 #include Err bitreich.org 70 i 11 #include Err bitreich.org 70 i 12 #include Err bitreich.org 70 i 13 #include Err bitreich.org 70 i 14 #include Err bitreich.org 70 i 15 #include Err bitreich.org 70 i 16 Err bitreich.org 70 i 17 #include Err bitreich.org 70 i 18 Err bitreich.org 70 i 19 #include "compat.h" Err bitreich.org 70 i 20 Err bitreich.org 70 i 21 #define LEN(s) (sizeof(s)/sizeof(*s)) Err bitreich.org 70 i 22 #define PAD_TRUNCATE_SYMBOL "\xe2\x80\xa6" /* symbol: "ellipsis" */ Err bitreich.org 70 i 23 #define UTF_INVALID_SYMBOL "\xef\xbf\xbd" /* symbol: "replacement" */ Err bitreich.org 70 i 24 Err bitreich.org 70 i 25 struct deltainfo { Err bitreich.org 70 i 26 git_patch *patch; Err bitreich.org 70 i 27 Err bitreich.org 70 i 28 size_t addcount; Err bitreich.org 70 i 29 size_t delcount; Err bitreich.org 70 i 30 }; Err bitreich.org 70 i 31 Err bitreich.org 70 i 32 struct commitinfo { Err bitreich.org 70 i 33 const git_oid *id; Err bitreich.org 70 i 34 Err bitreich.org 70 i 35 char oid[GIT_OID_HEXSZ + 1]; Err bitreich.org 70 i 36 char parentoid[GIT_OID_HEXSZ + 1]; Err bitreich.org 70 i 37 Err bitreich.org 70 i 38 const git_signature *author; Err bitreich.org 70 i 39 const git_signature *committer; Err bitreich.org 70 i 40 const char *summary; Err bitreich.org 70 i 41 const char *msg; Err bitreich.org 70 i 42 Err bitreich.org 70 i 43 git_diff *diff; Err bitreich.org 70 i 44 git_commit *commit; Err bitreich.org 70 i 45 git_commit *parent; Err bitreich.org 70 i 46 git_tree *commit_tree; Err bitreich.org 70 i 47 git_tree *parent_tree; Err bitreich.org 70 i 48 Err bitreich.org 70 i 49 size_t addcount; Err bitreich.org 70 i 50 size_t delcount; Err bitreich.org 70 i 51 size_t filecount; Err bitreich.org 70 i 52 Err bitreich.org 70 i 53 struct deltainfo **deltas; Err bitreich.org 70 i 54 size_t ndeltas; Err bitreich.org 70 i 55 }; Err bitreich.org 70 i 56 Err bitreich.org 70 i 57 /* reference and associated data for sorting */ Err bitreich.org 70 i 58 struct referenceinfo { Err bitreich.org 70 i 59 struct git_reference *ref; Err bitreich.org 70 i 60 struct commitinfo *ci; Err bitreich.org 70 i 61 }; Err bitreich.org 70 i 62 Err bitreich.org 70 i 63 static git_repository *repo; Err bitreich.org 70 i 64 Err bitreich.org 70 i 65 static const char *baseurl = ""; /* base URL to make absolute RSS/Atom URI */ Err bitreich.org 70 i 66 static const char *relpath = ""; Err bitreich.org 70 i 67 static const char *repodir; Err bitreich.org 70 i 68 Err bitreich.org 70 i 69 static char *name = ""; Err bitreich.org 70 i 70 static char *strippedname = ""; Err bitreich.org 70 i 71 static char description[255]; Err bitreich.org 70 i 72 static char cloneurl[1024]; Err bitreich.org 70 i 73 static char *submodules; Err bitreich.org 70 i 74 static char *licensefiles[] = { "HEAD:LICENSE", "HEAD:LICENSE.md", "HEAD:COPYING" }; Err bitreich.org 70 i 75 static char *license; Err bitreich.org 70 i 76 static char *readmefiles[] = { "HEAD:README", "HEAD:README.md" }; Err bitreich.org 70 i 77 static char *readme; Err bitreich.org 70 i 78 static long long nlogcommits = -1; /* -1 indicates not used */ Err bitreich.org 70 i 79 Err bitreich.org 70 i 80 /* cache */ Err bitreich.org 70 i 81 static git_oid lastoid; Err bitreich.org 70 i 82 static char lastoidstr[GIT_OID_HEXSZ + 2]; /* id + newline + NUL byte */ Err bitreich.org 70 i 83 static FILE *rcachefp, *wcachefp; Err bitreich.org 70 i 84 static const char *cachefile; Err bitreich.org 70 i 85 Err bitreich.org 70 i 86 /* Handle read or write errors for a FILE * stream */ Err bitreich.org 70 i 87 void Err bitreich.org 70 i 88 checkfileerror(FILE *fp, const char *name, int mode) Err bitreich.org 70 i 89 { Err bitreich.org 70 i 90 if (mode == 'r' && ferror(fp)) Err bitreich.org 70 i 91 errx(1, "read error: %s", name); Err bitreich.org 70 i 92 else if (mode == 'w' && (fflush(fp) || ferror(fp))) Err bitreich.org 70 i 93 errx(1, "write error: %s", name); Err bitreich.org 70 i 94 } Err bitreich.org 70 i 95 Err bitreich.org 70 i 96 /* Format `len' columns of characters. If string is shorter pad the rest Err bitreich.org 70 i 97 * with characters `pad`. */ Err bitreich.org 70 i 98 int Err bitreich.org 70 i 99 utf8pad(char *buf, size_t bufsiz, const char *s, size_t len, int pad) Err bitreich.org 70 i 100 { Err bitreich.org 70 i 101 wchar_t wc; Err bitreich.org 70 i 102 size_t col = 0, i, slen, siz = 0; Err bitreich.org 70 i 103 int inc, rl, w; Err bitreich.org 70 i 104 Err bitreich.org 70 i 105 if (!bufsiz) Err bitreich.org 70 i 106 return -1; Err bitreich.org 70 i 107 if (!len) { Err bitreich.org 70 i 108 buf[0] = '\0'; Err bitreich.org 70 i 109 return 0; Err bitreich.org 70 i 110 } Err bitreich.org 70 i 111 Err bitreich.org 70 i 112 slen = strlen(s); Err bitreich.org 70 i 113 for (i = 0; i < slen; i += inc) { Err bitreich.org 70 i 114 inc = 1; /* next byte */ Err bitreich.org 70 i 115 if ((unsigned char)s[i] < 32) Err bitreich.org 70 i 116 continue; Err bitreich.org 70 i 117 Err bitreich.org 70 i 118 rl = mbtowc(&wc, &s[i], slen - i < 4 ? slen - i : 4); Err bitreich.org 70 i 119 inc = rl; Err bitreich.org 70 i 120 if (rl < 0) { Err bitreich.org 70 i 121 mbtowc(NULL, NULL, 0); /* reset state */ Err bitreich.org 70 i 122 inc = 1; /* invalid, seek next byte */ Err bitreich.org 70 i 123 w = 1; /* replacement char is one width */ Err bitreich.org 70 i 124 } else if ((w = wcwidth(wc)) == -1) { Err bitreich.org 70 i 125 continue; Err bitreich.org 70 i 126 } Err bitreich.org 70 i 127 Err bitreich.org 70 i 128 if (col + w > len || (col + w == len && s[i + inc])) { Err bitreich.org 70 i 129 if (siz + 4 >= bufsiz) Err bitreich.org 70 i 130 return -1; Err bitreich.org 70 i 131 memcpy(&buf[siz], PAD_TRUNCATE_SYMBOL, sizeof(PAD_TRUNCATE_SYMBOL) - 1); Err bitreich.org 70 i 132 siz += sizeof(PAD_TRUNCATE_SYMBOL) - 1; Err bitreich.org 70 i 133 buf[siz] = '\0'; Err bitreich.org 70 i 134 col++; Err bitreich.org 70 i 135 break; Err bitreich.org 70 i 136 } else if (rl < 0) { Err bitreich.org 70 i 137 if (siz + 4 >= bufsiz) Err bitreich.org 70 i 138 return -1; Err bitreich.org 70 i 139 memcpy(&buf[siz], UTF_INVALID_SYMBOL, sizeof(UTF_INVALID_SYMBOL) - 1); Err bitreich.org 70 i 140 siz += sizeof(UTF_INVALID_SYMBOL) - 1; Err bitreich.org 70 i 141 buf[siz] = '\0'; Err bitreich.org 70 i 142 col++; Err bitreich.org 70 i 143 continue; Err bitreich.org 70 i 144 } Err bitreich.org 70 i 145 if (siz + inc + 1 >= bufsiz) Err bitreich.org 70 i 146 return -1; Err bitreich.org 70 i 147 memcpy(&buf[siz], &s[i], inc); Err bitreich.org 70 i 148 siz += inc; Err bitreich.org 70 i 149 buf[siz] = '\0'; Err bitreich.org 70 i 150 col += w; Err bitreich.org 70 i 151 } Err bitreich.org 70 i 152 Err bitreich.org 70 i 153 len -= col; Err bitreich.org 70 i 154 if (siz + len + 1 >= bufsiz) Err bitreich.org 70 i 155 return -1; Err bitreich.org 70 i 156 memset(&buf[siz], pad, len); Err bitreich.org 70 i 157 siz += len; Err bitreich.org 70 i 158 buf[siz] = '\0'; Err bitreich.org 70 i 159 Err bitreich.org 70 i 160 return 0; Err bitreich.org 70 i 161 } Err bitreich.org 70 i 162 Err bitreich.org 70 i 163 void Err bitreich.org 70 i 164 joinpath(char *buf, size_t bufsiz, const char *path, const char *path2) Err bitreich.org 70 i 165 { Err bitreich.org 70 i 166 int r; Err bitreich.org 70 i 167 Err bitreich.org 70 i 168 r = snprintf(buf, bufsiz, "%s%s%s", Err bitreich.org 70 i 169 path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "", path2); Err bitreich.org 70 i 170 if (r < 0 || (size_t)r >= bufsiz) Err bitreich.org 70 i 171 errx(1, "path truncated: '%s%s%s'", Err bitreich.org 70 i 172 path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "", path2); Err bitreich.org 70 i 173 } Err bitreich.org 70 i 174 Err bitreich.org 70 i 175 void Err bitreich.org 70 i 176 deltainfo_free(struct deltainfo *di) Err bitreich.org 70 i 177 { Err bitreich.org 70 i 178 if (!di) Err bitreich.org 70 i 179 return; Err bitreich.org 70 i 180 git_patch_free(di->patch); Err bitreich.org 70 i 181 memset(di, 0, sizeof(*di)); Err bitreich.org 70 i 182 free(di); Err bitreich.org 70 i 183 } Err bitreich.org 70 i 184 Err bitreich.org 70 i 185 int Err bitreich.org 70 i 186 commitinfo_getstats(struct commitinfo *ci) Err bitreich.org 70 i 187 { Err bitreich.org 70 i 188 struct deltainfo *di; Err bitreich.org 70 i 189 git_diff_options opts; Err bitreich.org 70 i 190 git_diff_find_options fopts; Err bitreich.org 70 i 191 const git_diff_delta *delta; Err bitreich.org 70 i 192 const git_diff_hunk *hunk; Err bitreich.org 70 i 193 const git_diff_line *line; Err bitreich.org 70 i 194 git_patch *patch = NULL; Err bitreich.org 70 i 195 size_t ndeltas, nhunks, nhunklines; Err bitreich.org 70 i 196 size_t i, j, k; Err bitreich.org 70 i 197 Err bitreich.org 70 i 198 if (git_tree_lookup(&(ci->commit_tree), repo, git_commit_tree_id(ci->commit))) Err bitreich.org 70 i 199 goto err; Err bitreich.org 70 i 200 if (!git_commit_parent(&(ci->parent), ci->commit, 0)) { Err bitreich.org 70 i 201 if (git_tree_lookup(&(ci->parent_tree), repo, git_commit_tree_id(ci->parent))) { Err bitreich.org 70 i 202 ci->parent = NULL; Err bitreich.org 70 i 203 ci->parent_tree = NULL; Err bitreich.org 70 i 204 } Err bitreich.org 70 i 205 } Err bitreich.org 70 i 206 Err bitreich.org 70 i 207 git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION); Err bitreich.org 70 i 208 opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH | Err bitreich.org 70 i 209 GIT_DIFF_IGNORE_SUBMODULES | Err bitreich.org 70 i 210 GIT_DIFF_INCLUDE_TYPECHANGE; Err bitreich.org 70 i 211 if (git_diff_tree_to_tree(&(ci->diff), repo, ci->parent_tree, ci->commit_tree, &opts)) Err bitreich.org 70 i 212 goto err; Err bitreich.org 70 i 213 Err bitreich.org 70 i 214 if (git_diff_find_init_options(&fopts, GIT_DIFF_FIND_OPTIONS_VERSION)) Err bitreich.org 70 i 215 goto err; Err bitreich.org 70 i 216 /* find renames and copies, exact matches (no heuristic) for renames. */ Err bitreich.org 70 i 217 fopts.flags |= GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES | Err bitreich.org 70 i 218 GIT_DIFF_FIND_EXACT_MATCH_ONLY; Err bitreich.org 70 i 219 if (git_diff_find_similar(ci->diff, &fopts)) Err bitreich.org 70 i 220 goto err; Err bitreich.org 70 i 221 Err bitreich.org 70 i 222 ndeltas = git_diff_num_deltas(ci->diff); Err bitreich.org 70 i 223 if (ndeltas && !(ci->deltas = calloc(ndeltas, sizeof(struct deltainfo *)))) Err bitreich.org 70 i 224 err(1, "calloc"); Err bitreich.org 70 i 225 Err bitreich.org 70 i 226 for (i = 0; i < ndeltas; i++) { Err bitreich.org 70 i 227 if (git_patch_from_diff(&patch, ci->diff, i)) Err bitreich.org 70 i 228 goto err; Err bitreich.org 70 i 229 Err bitreich.org 70 i 230 if (!(di = calloc(1, sizeof(struct deltainfo)))) Err bitreich.org 70 i 231 err(1, "calloc"); Err bitreich.org 70 i 232 di->patch = patch; Err bitreich.org 70 i 233 ci->deltas[i] = di; Err bitreich.org 70 i 234 Err bitreich.org 70 i 235 delta = git_patch_get_delta(patch); Err bitreich.org 70 i 236 Err bitreich.org 70 i 237 /* skip stats for binary data */ Err bitreich.org 70 i 238 if (delta->flags & GIT_DIFF_FLAG_BINARY) Err bitreich.org 70 i 239 continue; Err bitreich.org 70 i 240 Err bitreich.org 70 i 241 nhunks = git_patch_num_hunks(patch); Err bitreich.org 70 i 242 for (j = 0; j < nhunks; j++) { Err bitreich.org 70 i 243 if (git_patch_get_hunk(&hunk, &nhunklines, patch, j)) Err bitreich.org 70 i 244 break; Err bitreich.org 70 i 245 for (k = 0; ; k++) { Err bitreich.org 70 i 246 if (git_patch_get_line_in_hunk(&line, patch, j, k)) Err bitreich.org 70 i 247 break; Err bitreich.org 70 i 248 if (line->old_lineno == -1) { Err bitreich.org 70 i 249 di->addcount++; Err bitreich.org 70 i 250 ci->addcount++; Err bitreich.org 70 i 251 } else if (line->new_lineno == -1) { Err bitreich.org 70 i 252 di->delcount++; Err bitreich.org 70 i 253 ci->delcount++; Err bitreich.org 70 i 254 } Err bitreich.org 70 i 255 } Err bitreich.org 70 i 256 } Err bitreich.org 70 i 257 } Err bitreich.org 70 i 258 ci->ndeltas = i; Err bitreich.org 70 i 259 ci->filecount = i; Err bitreich.org 70 i 260 Err bitreich.org 70 i 261 return 0; Err bitreich.org 70 i 262 Err bitreich.org 70 i 263 err: Err bitreich.org 70 i 264 git_diff_free(ci->diff); Err bitreich.org 70 i 265 ci->diff = NULL; Err bitreich.org 70 i 266 git_tree_free(ci->commit_tree); Err bitreich.org 70 i 267 ci->commit_tree = NULL; Err bitreich.org 70 i 268 git_tree_free(ci->parent_tree); Err bitreich.org 70 i 269 ci->parent_tree = NULL; Err bitreich.org 70 i 270 git_commit_free(ci->parent); Err bitreich.org 70 i 271 ci->parent = NULL; Err bitreich.org 70 i 272 if (ci->deltas) Err bitreich.org 70 i 273 for (i = 0; i < ci->ndeltas; i++) Err bitreich.org 70 i 274 deltainfo_free(ci->deltas[i]); Err bitreich.org 70 i 275 free(ci->deltas); Err bitreich.org 70 i 276 ci->deltas = NULL; Err bitreich.org 70 i 277 ci->ndeltas = 0; Err bitreich.org 70 i 278 ci->addcount = 0; Err bitreich.org 70 i 279 ci->delcount = 0; Err bitreich.org 70 i 280 ci->filecount = 0; Err bitreich.org 70 i 281 Err bitreich.org 70 i 282 return -1; Err bitreich.org 70 i 283 } Err bitreich.org 70 i 284 Err bitreich.org 70 i 285 void Err bitreich.org 70 i 286 commitinfo_free(struct commitinfo *ci) Err bitreich.org 70 i 287 { Err bitreich.org 70 i 288 size_t i; Err bitreich.org 70 i 289 Err bitreich.org 70 i 290 if (!ci) Err bitreich.org 70 i 291 return; Err bitreich.org 70 i 292 if (ci->deltas) Err bitreich.org 70 i 293 for (i = 0; i < ci->ndeltas; i++) Err bitreich.org 70 i 294 deltainfo_free(ci->deltas[i]); Err bitreich.org 70 i 295 free(ci->deltas); Err bitreich.org 70 i 296 git_diff_free(ci->diff); Err bitreich.org 70 i 297 git_tree_free(ci->commit_tree); Err bitreich.org 70 i 298 git_tree_free(ci->parent_tree); Err bitreich.org 70 i 299 git_commit_free(ci->commit); Err bitreich.org 70 i 300 git_commit_free(ci->parent); Err bitreich.org 70 i 301 memset(ci, 0, sizeof(*ci)); Err bitreich.org 70 i 302 free(ci); Err bitreich.org 70 i 303 } Err bitreich.org 70 i 304 Err bitreich.org 70 i 305 struct commitinfo * Err bitreich.org 70 i 306 commitinfo_getbyoid(const git_oid *id) Err bitreich.org 70 i 307 { Err bitreich.org 70 i 308 struct commitinfo *ci; Err bitreich.org 70 i 309 Err bitreich.org 70 i 310 if (!(ci = calloc(1, sizeof(struct commitinfo)))) Err bitreich.org 70 i 311 err(1, "calloc"); Err bitreich.org 70 i 312 Err bitreich.org 70 i 313 if (git_commit_lookup(&(ci->commit), repo, id)) Err bitreich.org 70 i 314 goto err; Err bitreich.org 70 i 315 ci->id = id; Err bitreich.org 70 i 316 Err bitreich.org 70 i 317 git_oid_tostr(ci->oid, sizeof(ci->oid), git_commit_id(ci->commit)); Err bitreich.org 70 i 318 git_oid_tostr(ci->parentoid, sizeof(ci->parentoid), git_commit_parent_id(ci->commit, 0)); Err bitreich.org 70 i 319 Err bitreich.org 70 i 320 ci->author = git_commit_author(ci->commit); Err bitreich.org 70 i 321 ci->committer = git_commit_committer(ci->commit); Err bitreich.org 70 i 322 ci->summary = git_commit_summary(ci->commit); Err bitreich.org 70 i 323 ci->msg = git_commit_message(ci->commit); Err bitreich.org 70 i 324 Err bitreich.org 70 i 325 return ci; Err bitreich.org 70 i 326 Err bitreich.org 70 i 327 err: Err bitreich.org 70 i 328 commitinfo_free(ci); Err bitreich.org 70 i 329 Err bitreich.org 70 i 330 return NULL; Err bitreich.org 70 i 331 } Err bitreich.org 70 i 332 Err bitreich.org 70 i 333 int Err bitreich.org 70 i 334 refs_cmp(const void *v1, const void *v2) Err bitreich.org 70 i 335 { Err bitreich.org 70 i 336 const struct referenceinfo *r1 = v1, *r2 = v2; Err bitreich.org 70 i 337 time_t t1, t2; Err bitreich.org 70 i 338 int r; Err bitreich.org 70 i 339 Err bitreich.org 70 i 340 if ((r = git_reference_is_tag(r1->ref) - git_reference_is_tag(r2->ref))) Err bitreich.org 70 i 341 return r; Err bitreich.org 70 i 342 Err bitreich.org 70 i 343 t1 = r1->ci->author ? r1->ci->author->when.time : 0; Err bitreich.org 70 i 344 t2 = r2->ci->author ? r2->ci->author->when.time : 0; Err bitreich.org 70 i 345 if ((r = t1 > t2 ? -1 : (t1 == t2 ? 0 : 1))) Err bitreich.org 70 i 346 return r; Err bitreich.org 70 i 347 Err bitreich.org 70 i 348 return strcmp(git_reference_shorthand(r1->ref), Err bitreich.org 70 i 349 git_reference_shorthand(r2->ref)); Err bitreich.org 70 i 350 } Err bitreich.org 70 i 351 Err bitreich.org 70 i 352 int Err bitreich.org 70 i 353 getrefs(struct referenceinfo **pris, size_t *prefcount) Err bitreich.org 70 i 354 { Err bitreich.org 70 i 355 struct referenceinfo *ris = NULL; Err bitreich.org 70 i 356 struct commitinfo *ci = NULL; Err bitreich.org 70 i 357 git_reference_iterator *it = NULL; Err bitreich.org 70 i 358 const git_oid *id = NULL; Err bitreich.org 70 i 359 git_object *obj = NULL; Err bitreich.org 70 i 360 git_reference *dref = NULL, *r, *ref = NULL; Err bitreich.org 70 i 361 size_t i, refcount; Err bitreich.org 70 i 362 Err bitreich.org 70 i 363 *pris = NULL; Err bitreich.org 70 i 364 *prefcount = 0; Err bitreich.org 70 i 365 Err bitreich.org 70 i 366 if (git_reference_iterator_new(&it, repo)) Err bitreich.org 70 i 367 return -1; Err bitreich.org 70 i 368 Err bitreich.org 70 i 369 for (refcount = 0; !git_reference_next(&ref, it); ) { Err bitreich.org 70 i 370 if (!git_reference_is_branch(ref) && !git_reference_is_tag(ref)) { Err bitreich.org 70 i 371 git_reference_free(ref); Err bitreich.org 70 i 372 ref = NULL; Err bitreich.org 70 i 373 continue; Err bitreich.org 70 i 374 } Err bitreich.org 70 i 375 Err bitreich.org 70 i 376 switch (git_reference_type(ref)) { Err bitreich.org 70 i 377 case GIT_REF_SYMBOLIC: Err bitreich.org 70 i 378 if (git_reference_resolve(&dref, ref)) Err bitreich.org 70 i 379 goto err; Err bitreich.org 70 i 380 r = dref; Err bitreich.org 70 i 381 break; Err bitreich.org 70 i 382 case GIT_REF_OID: Err bitreich.org 70 i 383 r = ref; Err bitreich.org 70 i 384 break; Err bitreich.org 70 i 385 default: Err bitreich.org 70 i 386 continue; Err bitreich.org 70 i 387 } Err bitreich.org 70 i 388 if (!git_reference_target(r) || Err bitreich.org 70 i 389 git_reference_peel(&obj, r, GIT_OBJ_ANY)) Err bitreich.org 70 i 390 goto err; Err bitreich.org 70 i 391 if (!(id = git_object_id(obj))) Err bitreich.org 70 i 392 goto err; Err bitreich.org 70 i 393 if (!(ci = commitinfo_getbyoid(id))) Err bitreich.org 70 i 394 break; Err bitreich.org 70 i 395 Err bitreich.org 70 i 396 if (!(ris = reallocarray(ris, refcount + 1, sizeof(*ris)))) Err bitreich.org 70 i 397 err(1, "realloc"); Err bitreich.org 70 i 398 ris[refcount].ci = ci; Err bitreich.org 70 i 399 ris[refcount].ref = r; Err bitreich.org 70 i 400 refcount++; Err bitreich.org 70 i 401 Err bitreich.org 70 i 402 git_object_free(obj); Err bitreich.org 70 i 403 obj = NULL; Err bitreich.org 70 i 404 git_reference_free(dref); Err bitreich.org 70 i 405 dref = NULL; Err bitreich.org 70 i 406 } Err bitreich.org 70 i 407 git_reference_iterator_free(it); Err bitreich.org 70 i 408 Err bitreich.org 70 i 409 /* sort by type, date then shorthand name */ Err bitreich.org 70 i 410 qsort(ris, refcount, sizeof(*ris), refs_cmp); Err bitreich.org 70 i 411 Err bitreich.org 70 i 412 *pris = ris; Err bitreich.org 70 i 413 *prefcount = refcount; Err bitreich.org 70 i 414 Err bitreich.org 70 i 415 return 0; Err bitreich.org 70 i 416 Err bitreich.org 70 i 417 err: Err bitreich.org 70 i 418 git_object_free(obj); Err bitreich.org 70 i 419 git_reference_free(dref); Err bitreich.org 70 i 420 commitinfo_free(ci); Err bitreich.org 70 i 421 for (i = 0; i < refcount; i++) { Err bitreich.org 70 i 422 commitinfo_free(ris[i].ci); Err bitreich.org 70 i 423 git_reference_free(ris[i].ref); Err bitreich.org 70 i 424 } Err bitreich.org 70 i 425 free(ris); Err bitreich.org 70 i 426 Err bitreich.org 70 i 427 return -1; Err bitreich.org 70 i 428 } Err bitreich.org 70 i 429 Err bitreich.org 70 i 430 FILE * Err bitreich.org 70 i 431 efopen(const char *filename, const char *flags) Err bitreich.org 70 i 432 { Err bitreich.org 70 i 433 FILE *fp; Err bitreich.org 70 i 434 Err bitreich.org 70 i 435 if (!(fp = fopen(filename, flags))) Err bitreich.org 70 i 436 err(1, "fopen: '%s'", filename); Err bitreich.org 70 i 437 Err bitreich.org 70 i 438 return fp; Err bitreich.org 70 i 439 } Err bitreich.org 70 i 440 Err bitreich.org 70 i 441 /* Escape characters below as HTML 2.0 / XML 1.0. */ Err bitreich.org 70 i 442 void Err bitreich.org 70 i 443 xmlencode(FILE *fp, const char *s, size_t len) Err bitreich.org 70 i 444 { Err bitreich.org 70 i 445 size_t i; Err bitreich.org 70 i 446 Err bitreich.org 70 i 447 for (i = 0; *s && i < len; s++, i++) { Err bitreich.org 70 i 448 switch(*s) { Err bitreich.org 70 i 449 case '<': fputs("<", fp); break; Err bitreich.org 70 i 450 case '>': fputs(">", fp); break; Err bitreich.org 70 i 451 case '\'': fputs("'", fp); break; Err bitreich.org 70 i 452 case '&': fputs("&", fp); break; Err bitreich.org 70 i 453 case '"': fputs(""", fp); break; Err bitreich.org 70 i 454 default: putc(*s, fp); Err bitreich.org 70 i 455 } Err bitreich.org 70 i 456 } Err bitreich.org 70 i 457 } Err bitreich.org 70 i 458 Err bitreich.org 70 i 459 /* Escape characters in text in geomyidae .gph format, with newlines */ Err bitreich.org 70 i 460 void Err bitreich.org 70 i 461 gphtextnl(FILE *fp, const char *s, size_t len) Err bitreich.org 70 i 462 { Err bitreich.org 70 i 463 size_t i, n = 0; Err bitreich.org 70 i 464 Err bitreich.org 70 i 465 for (i = 0; s[i] && i < len; i++) { Err bitreich.org 70 i 466 /* escape '[' with "[|" at the start of a line */ Err bitreich.org 70 i 467 if (!n && s[i] == '[') Err bitreich.org 70 i 468 fputs("[|", fp); Err bitreich.org 70 i 469 Err bitreich.org 70 i 470 switch (s[i]) { Err bitreich.org 70 i 471 case '\t': fputs(" ", fp); Err bitreich.org 70 i 472 case '\r': break; Err bitreich.org 70 i 473 default: putc(s[i], fp); Err bitreich.org 70 i 474 } Err bitreich.org 70 i 475 n = (s[i] != '\n'); Err bitreich.org 70 i 476 } Err bitreich.org 70 i 477 } Err bitreich.org 70 i 478 Err bitreich.org 70 i 479 /* Escape characters in text in geomyidae .gph format, Err bitreich.org 70 i 480 newlines are ignored */ Err bitreich.org 70 i 481 void Err bitreich.org 70 i 482 gphtext(FILE *fp, const char *s, size_t len) Err bitreich.org 70 i 483 { Err bitreich.org 70 i 484 size_t i; Err bitreich.org 70 i 485 Err bitreich.org 70 i 486 for (i = 0; *s && i < len; s++, i++) { Err bitreich.org 70 i 487 switch (*s) { Err bitreich.org 70 i 488 case '\r': /* ignore CR */ Err bitreich.org 70 i 489 case '\n': /* ignore LF */ Err bitreich.org 70 i 490 break; Err bitreich.org 70 i 491 case '\t': Err bitreich.org 70 i 492 fputs(" ", fp); Err bitreich.org 70 i 493 break; Err bitreich.org 70 i 494 default: Err bitreich.org 70 i 495 putc(*s, fp); Err bitreich.org 70 i 496 break; Err bitreich.org 70 i 497 } Err bitreich.org 70 i 498 } Err bitreich.org 70 i 499 } Err bitreich.org 70 i 500 Err bitreich.org 70 i 501 /* Escape characters in links in geomyidae .gph format */ Err bitreich.org 70 i 502 void Err bitreich.org 70 i 503 gphlink(FILE *fp, const char *s, size_t len) Err bitreich.org 70 i 504 { Err bitreich.org 70 i 505 size_t i; Err bitreich.org 70 i 506 Err bitreich.org 70 i 507 for (i = 0; *s && i < len; s++, i++) { Err bitreich.org 70 i 508 switch (*s) { Err bitreich.org 70 i 509 case '\r': /* ignore CR */ Err bitreich.org 70 i 510 case '\n': /* ignore LF */ Err bitreich.org 70 i 511 break; Err bitreich.org 70 i 512 case '\t': Err bitreich.org 70 i 513 fputs(" ", fp); Err bitreich.org 70 i 514 break; Err bitreich.org 70 i 515 case '|': /* escape separators */ Err bitreich.org 70 i 516 fputs("\\|", fp); Err bitreich.org 70 i 517 break; Err bitreich.org 70 i 518 default: Err bitreich.org 70 i 519 putc(*s, fp); Err bitreich.org 70 i 520 break; Err bitreich.org 70 i 521 } Err bitreich.org 70 i 522 } Err bitreich.org 70 i 523 } Err bitreich.org 70 i 524 Err bitreich.org 70 i 525 int Err bitreich.org 70 i 526 mkdirp(const char *path) Err bitreich.org 70 i 527 { Err bitreich.org 70 i 528 char tmp[PATH_MAX], *p; Err bitreich.org 70 i 529 Err bitreich.org 70 i 530 if (strlcpy(tmp, path, sizeof(tmp)) >= sizeof(tmp)) Err bitreich.org 70 i 531 errx(1, "path truncated: '%s'", path); Err bitreich.org 70 i 532 for (p = tmp + (tmp[0] == '/'); *p; p++) { Err bitreich.org 70 i 533 if (*p != '/') Err bitreich.org 70 i 534 continue; Err bitreich.org 70 i 535 *p = '\0'; Err bitreich.org 70 i 536 if (mkdir(tmp, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST) Err bitreich.org 70 i 537 return -1; Err bitreich.org 70 i 538 *p = '/'; Err bitreich.org 70 i 539 } Err bitreich.org 70 i 540 if (mkdir(tmp, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST) Err bitreich.org 70 i 541 return -1; Err bitreich.org 70 i 542 return 0; Err bitreich.org 70 i 543 } Err bitreich.org 70 i 544 Err bitreich.org 70 i 545 void Err bitreich.org 70 i 546 printtimez(FILE *fp, const git_time *intime) Err bitreich.org 70 i 547 { Err bitreich.org 70 i 548 struct tm *intm; Err bitreich.org 70 i 549 time_t t; Err bitreich.org 70 i 550 char out[32]; Err bitreich.org 70 i 551 Err bitreich.org 70 i 552 t = (time_t)intime->time; Err bitreich.org 70 i 553 if (!(intm = gmtime(&t))) Err bitreich.org 70 i 554 return; Err bitreich.org 70 i 555 strftime(out, sizeof(out), "%Y-%m-%dT%H:%M:%SZ", intm); Err bitreich.org 70 i 556 fputs(out, fp); Err bitreich.org 70 i 557 } Err bitreich.org 70 i 558 Err bitreich.org 70 i 559 void Err bitreich.org 70 i 560 printtime(FILE *fp, const git_time *intime) Err bitreich.org 70 i 561 { Err bitreich.org 70 i 562 struct tm *intm; Err bitreich.org 70 i 563 time_t t; Err bitreich.org 70 i 564 char out[32]; Err bitreich.org 70 i 565 Err bitreich.org 70 i 566 t = (time_t)intime->time + (intime->offset * 60); Err bitreich.org 70 i 567 if (!(intm = gmtime(&t))) Err bitreich.org 70 i 568 return; Err bitreich.org 70 i 569 strftime(out, sizeof(out), "%a, %e %b %Y %H:%M:%S", intm); Err bitreich.org 70 i 570 if (intime->offset < 0) Err bitreich.org 70 i 571 fprintf(fp, "%s -%02d%02d", out, Err bitreich.org 70 i 572 -(intime->offset) / 60, -(intime->offset) % 60); Err bitreich.org 70 i 573 else Err bitreich.org 70 i 574 fprintf(fp, "%s +%02d%02d", out, Err bitreich.org 70 i 575 intime->offset / 60, intime->offset % 60); Err bitreich.org 70 i 576 } Err bitreich.org 70 i 577 Err bitreich.org 70 i 578 void Err bitreich.org 70 i 579 printtimeshort(FILE *fp, const git_time *intime) Err bitreich.org 70 i 580 { Err bitreich.org 70 i 581 struct tm *intm; Err bitreich.org 70 i 582 time_t t; Err bitreich.org 70 i 583 char out[32]; Err bitreich.org 70 i 584 Err bitreich.org 70 i 585 t = (time_t)intime->time; Err bitreich.org 70 i 586 if (!(intm = gmtime(&t))) Err bitreich.org 70 i 587 return; Err bitreich.org 70 i 588 strftime(out, sizeof(out), "%Y-%m-%d %H:%M", intm); Err bitreich.org 70 i 589 fputs(out, fp); Err bitreich.org 70 i 590 } Err bitreich.org 70 i 591 Err bitreich.org 70 i 592 void Err bitreich.org 70 i 593 writeheader(FILE *fp, const char *title) Err bitreich.org 70 i 594 { Err bitreich.org 70 i 595 if (title[0] == '[') Err bitreich.org 70 i 596 fputs("[|", fp); Err bitreich.org 70 i 597 gphtext(fp, title, strlen(title)); Err bitreich.org 70 i 598 if (title[0] && strippedname[0]) Err bitreich.org 70 i 599 fputs(" - ", fp); Err bitreich.org 70 i 600 gphtext(fp, strippedname, strlen(strippedname)); Err bitreich.org 70 i 601 if (description[0]) Err bitreich.org 70 i 602 fputs(" - ", fp); Err bitreich.org 70 i 603 gphtext(fp, description, strlen(description)); Err bitreich.org 70 i 604 fputs("\n", fp); Err bitreich.org 70 i 605 if (cloneurl[0]) { Err bitreich.org 70 i 606 fputs("[h|git clone ", fp); Err bitreich.org 70 i 607 gphlink(fp, cloneurl, strlen(cloneurl)); Err bitreich.org 70 i 608 fputs("|URL:", fp); Err bitreich.org 70 i 609 gphlink(fp, cloneurl, strlen(cloneurl)); Err bitreich.org 70 i 610 fputs("|server|port]\n", fp); Err bitreich.org 70 i 611 } Err bitreich.org 70 i 612 fprintf(fp, "[1|Log|%s/log.gph|server|port]\n", relpath); Err bitreich.org 70 i 613 fprintf(fp, "[1|Files|%s/files.gph|server|port]\n", relpath); Err bitreich.org 70 i 614 fprintf(fp, "[1|Refs|%s/refs.gph|server|port]\n", relpath); Err bitreich.org 70 i 615 if (submodules) Err bitreich.org 70 i 616 fprintf(fp, "[1|Submodules|%s/file/%s.gph|server|port]\n", Err bitreich.org 70 i 617 relpath, submodules); Err bitreich.org 70 i 618 if (readme) Err bitreich.org 70 i 619 fprintf(fp, "[1|README|%s/file/%s.gph|server|port]\n", Err bitreich.org 70 i 620 relpath, readme); Err bitreich.org 70 i 621 if (license) Err bitreich.org 70 i 622 fprintf(fp, "[1|LICENSE|%s/file/%s.gph|server|port]\n", Err bitreich.org 70 i 623 relpath, license); Err bitreich.org 70 i 624 fputs("---\n", fp); Err bitreich.org 70 i 625 } Err bitreich.org 70 i 626 Err bitreich.org 70 i 627 void Err bitreich.org 70 i 628 writefooter(FILE *fp) Err bitreich.org 70 i 629 { Err bitreich.org 70 i 630 } Err bitreich.org 70 i 631 Err bitreich.org 70 i 632 size_t Err bitreich.org 70 i 633 writeblobgph(FILE *fp, const git_blob *blob) Err bitreich.org 70 i 634 { Err bitreich.org 70 i 635 size_t n = 0, i, j, len, prev; Err bitreich.org 70 i 636 const char *nfmt = "%6zu "; Err bitreich.org 70 i 637 const char *s = git_blob_rawcontent(blob); Err bitreich.org 70 i 638 Err bitreich.org 70 i 639 len = git_blob_rawsize(blob); Err bitreich.org 70 i 640 if (len > 0) { Err bitreich.org 70 i 641 for (i = 0, prev = 0; i < len; i++) { Err bitreich.org 70 i 642 if (s[i] != '\n') Err bitreich.org 70 i 643 continue; Err bitreich.org 70 i 644 n++; Err bitreich.org 70 i 645 fprintf(fp, nfmt, n, n, n); Err bitreich.org 70 i 646 for (j = prev; j <= i && s[j]; j++) { Err bitreich.org 70 i 647 switch (s[j]) { Err bitreich.org 70 i 648 case '\r': break; Err bitreich.org 70 i 649 case '\t': fputs(" ", fp); break; Err bitreich.org 70 i 650 default: putc(s[j], fp); Err bitreich.org 70 i 651 } Err bitreich.org 70 i 652 } Err bitreich.org 70 i 653 prev = i + 1; Err bitreich.org 70 i 654 } Err bitreich.org 70 i 655 /* trailing data */ Err bitreich.org 70 i 656 if ((len - prev) > 0) { Err bitreich.org 70 i 657 n++; Err bitreich.org 70 i 658 fprintf(fp, nfmt, n, n, n); Err bitreich.org 70 i 659 for (j = prev; j < len - prev && s[j]; j++) { Err bitreich.org 70 i 660 switch (s[j]) { Err bitreich.org 70 i 661 case '\r': break; Err bitreich.org 70 i 662 case '\t': fputs(" ", fp); break; Err bitreich.org 70 i 663 default: putc(s[j], fp); Err bitreich.org 70 i 664 } Err bitreich.org 70 i 665 } Err bitreich.org 70 i 666 } Err bitreich.org 70 i 667 } Err bitreich.org 70 i 668 Err bitreich.org 70 i 669 return n; Err bitreich.org 70 i 670 } Err bitreich.org 70 i 671 Err bitreich.org 70 i 672 void Err bitreich.org 70 i 673 printcommit(FILE *fp, struct commitinfo *ci) Err bitreich.org 70 i 674 { Err bitreich.org 70 i 675 fprintf(fp, "[1|commit %s|%s/commit/%s.gph|server|port]\n", Err bitreich.org 70 i 676 ci->oid, relpath, ci->oid); Err bitreich.org 70 i 677 Err bitreich.org 70 i 678 if (ci->parentoid[0]) Err bitreich.org 70 i 679 fprintf(fp, "[1|parent %s|%s/commit/%s.gph|server|port]\n", Err bitreich.org 70 i 680 ci->parentoid, relpath, ci->parentoid); Err bitreich.org 70 i 681 Err bitreich.org 70 i 682 if (ci->author) { Err bitreich.org 70 i 683 fputs("[h|Author: ", fp); Err bitreich.org 70 i 684 gphlink(fp, ci->author->name, strlen(ci->author->name)); Err bitreich.org 70 i 685 fputs(" <", fp); Err bitreich.org 70 i 686 gphlink(fp, ci->author->email, strlen(ci->author->email)); Err bitreich.org 70 i 687 fputs(">|URL:mailto:", fp); Err bitreich.org 70 i 688 gphlink(fp, ci->author->email, strlen(ci->author->email)); Err bitreich.org 70 i 689 fputs("|server|port]\n", fp); Err bitreich.org 70 i 690 fputs("Date: ", fp); Err bitreich.org 70 i 691 printtime(fp, &(ci->author->when)); Err bitreich.org 70 i 692 putc('\n', fp); Err bitreich.org 70 i 693 } Err bitreich.org 70 i 694 if (ci->msg) { Err bitreich.org 70 i 695 putc('\n', fp); Err bitreich.org 70 i 696 gphtextnl(fp, ci->msg, strlen(ci->msg)); Err bitreich.org 70 i 697 putc('\n', fp); Err bitreich.org 70 i 698 } Err bitreich.org 70 i 699 } Err bitreich.org 70 i 700 Err bitreich.org 70 i 701 void Err bitreich.org 70 i 702 printshowfile(FILE *fp, struct commitinfo *ci) Err bitreich.org 70 i 703 { Err bitreich.org 70 i 704 const git_diff_delta *delta; Err bitreich.org 70 i 705 const git_diff_hunk *hunk; Err bitreich.org 70 i 706 const git_diff_line *line; Err bitreich.org 70 i 707 git_patch *patch; Err bitreich.org 70 i 708 size_t nhunks, nhunklines, changed, add, del, total, i, j, k; Err bitreich.org 70 i 709 char buf[256], filename[256], linestr[32]; Err bitreich.org 70 i 710 int c; Err bitreich.org 70 i 711 Err bitreich.org 70 i 712 printcommit(fp, ci); Err bitreich.org 70 i 713 Err bitreich.org 70 i 714 if (!ci->deltas) Err bitreich.org 70 i 715 return; Err bitreich.org 70 i 716 Err bitreich.org 70 i 717 if (ci->filecount > 1000 || Err bitreich.org 70 i 718 ci->ndeltas > 1000 || Err bitreich.org 70 i 719 ci->addcount > 100000 || Err bitreich.org 70 i 720 ci->delcount > 100000) { Err bitreich.org 70 i 721 fputs("\nDiff is too large, output suppressed.\n", fp); Err bitreich.org 70 i 722 return; Err bitreich.org 70 i 723 } Err bitreich.org 70 i 724 Err bitreich.org 70 i 725 /* diff stat */ Err bitreich.org 70 i 726 fputs("Diffstat:\n", fp); Err bitreich.org 70 i 727 for (i = 0; i < ci->ndeltas; i++) { Err bitreich.org 70 i 728 delta = git_patch_get_delta(ci->deltas[i]->patch); Err bitreich.org 70 i 729 Err bitreich.org 70 i 730 switch (delta->status) { Err bitreich.org 70 i 731 case GIT_DELTA_ADDED: c = 'A'; break; Err bitreich.org 70 i 732 case GIT_DELTA_COPIED: c = 'C'; break; Err bitreich.org 70 i 733 case GIT_DELTA_DELETED: c = 'D'; break; Err bitreich.org 70 i 734 case GIT_DELTA_MODIFIED: c = 'M'; break; Err bitreich.org 70 i 735 case GIT_DELTA_RENAMED: c = 'R'; break; Err bitreich.org 70 i 736 case GIT_DELTA_TYPECHANGE: c = 'T'; break; Err bitreich.org 70 i 737 default: c = ' '; break; Err bitreich.org 70 i 738 } Err bitreich.org 70 i 739 Err bitreich.org 70 i 740 if (strcmp(delta->old_file.path, delta->new_file.path)) { Err bitreich.org 70 i 741 snprintf(filename, sizeof(filename), "%s -> %s", Err bitreich.org 70 i 742 delta->old_file.path, delta->new_file.path); Err bitreich.org 70 i 743 utf8pad(buf, sizeof(buf), filename, 35, ' '); Err bitreich.org 70 i 744 } else { Err bitreich.org 70 i 745 utf8pad(buf, sizeof(buf), delta->old_file.path, 35, ' '); Err bitreich.org 70 i 746 } Err bitreich.org 70 i 747 fprintf(fp, " %c ", c); Err bitreich.org 70 i 748 gphtext(fp, buf, strlen(buf)); Err bitreich.org 70 i 749 Err bitreich.org 70 i 750 add = ci->deltas[i]->addcount; Err bitreich.org 70 i 751 del = ci->deltas[i]->delcount; Err bitreich.org 70 i 752 changed = add + del; Err bitreich.org 70 i 753 total = sizeof(linestr) - 2; Err bitreich.org 70 i 754 if (changed > total) { Err bitreich.org 70 i 755 if (add) Err bitreich.org 70 i 756 add = ((float)total / changed * add) + 1; Err bitreich.org 70 i 757 if (del) Err bitreich.org 70 i 758 del = ((float)total / changed * del) + 1; Err bitreich.org 70 i 759 } Err bitreich.org 70 i 760 memset(&linestr, '+', add); Err bitreich.org 70 i 761 memset(&linestr[add], '-', del); Err bitreich.org 70 i 762 Err bitreich.org 70 i 763 fprintf(fp, " | %7zu ", Err bitreich.org 70 i 764 ci->deltas[i]->addcount + ci->deltas[i]->delcount); Err bitreich.org 70 i 765 fwrite(&linestr, 1, add, fp); Err bitreich.org 70 i 766 fwrite(&linestr[add], 1, del, fp); Err bitreich.org 70 i 767 fputs("\n", fp); Err bitreich.org 70 i 768 } Err bitreich.org 70 i 769 fprintf(fp, "\n%zu file%s changed, %zu insertion%s(+), %zu deletion%s(-)\n", Err bitreich.org 70 i 770 ci->filecount, ci->filecount == 1 ? "" : "s", Err bitreich.org 70 i 771 ci->addcount, ci->addcount == 1 ? "" : "s", Err bitreich.org 70 i 772 ci->delcount, ci->delcount == 1 ? "" : "s"); Err bitreich.org 70 i 773 Err bitreich.org 70 i 774 fputs("---\n", fp); Err bitreich.org 70 i 775 Err bitreich.org 70 i 776 for (i = 0; i < ci->ndeltas; i++) { Err bitreich.org 70 i 777 patch = ci->deltas[i]->patch; Err bitreich.org 70 i 778 delta = git_patch_get_delta(patch); Err bitreich.org 70 i 779 /* NOTE: only links to new path */ Err bitreich.org 70 i 780 fputs("[1|diff --git a/", fp); Err bitreich.org 70 i 781 gphlink(fp, delta->old_file.path, strlen(delta->old_file.path)); Err bitreich.org 70 i 782 fputs(" b/", fp); Err bitreich.org 70 i 783 gphlink(fp, delta->new_file.path, strlen(delta->new_file.path)); Err bitreich.org 70 i 784 fprintf(fp, "|%s/file/", relpath); Err bitreich.org 70 i 785 gphlink(fp, delta->new_file.path, strlen(delta->new_file.path)); Err bitreich.org 70 i 786 fputs(".gph|server|port]\n", fp); Err bitreich.org 70 i 787 Err bitreich.org 70 i 788 /* check binary data */ Err bitreich.org 70 i 789 if (delta->flags & GIT_DIFF_FLAG_BINARY) { Err bitreich.org 70 i 790 fputs("Binary files differ.\n", fp); Err bitreich.org 70 i 791 continue; Err bitreich.org 70 i 792 } Err bitreich.org 70 i 793 Err bitreich.org 70 i 794 nhunks = git_patch_num_hunks(patch); Err bitreich.org 70 i 795 for (j = 0; j < nhunks; j++) { Err bitreich.org 70 i 796 if (git_patch_get_hunk(&hunk, &nhunklines, patch, j)) Err bitreich.org 70 i 797 break; Err bitreich.org 70 i 798 Err bitreich.org 70 i 799 if (hunk->header_len > 0 && hunk->header[0] == '[') Err bitreich.org 70 i 800 fputs("[|", fp); Err bitreich.org 70 i 801 gphtext(fp, hunk->header, hunk->header_len); Err bitreich.org 70 i 802 putc('\n', fp); Err bitreich.org 70 i 803 Err bitreich.org 70 i 804 for (k = 0; ; k++) { Err bitreich.org 70 i 805 if (git_patch_get_line_in_hunk(&line, patch, j, k)) Err bitreich.org 70 i 806 break; Err bitreich.org 70 i 807 if (line->old_lineno == -1) Err bitreich.org 70 i 808 fputs("+", fp); Err bitreich.org 70 i 809 else if (line->new_lineno == -1) Err bitreich.org 70 i 810 fputs("-", fp); Err bitreich.org 70 i 811 else Err bitreich.org 70 i 812 fputs(" ", fp); Err bitreich.org 70 i 813 gphtext(fp, line->content, line->content_len); Err bitreich.org 70 i 814 putc('\n', fp); Err bitreich.org 70 i 815 } Err bitreich.org 70 i 816 } Err bitreich.org 70 i 817 } Err bitreich.org 70 i 818 } Err bitreich.org 70 i 819 Err bitreich.org 70 i 820 void Err bitreich.org 70 i 821 writelogline(FILE *fp, struct commitinfo *ci) Err bitreich.org 70 i 822 { Err bitreich.org 70 i 823 char buf[256]; Err bitreich.org 70 i 824 Err bitreich.org 70 i 825 fputs("[1|", fp); Err bitreich.org 70 i 826 if (ci->author) Err bitreich.org 70 i 827 printtimeshort(fp, &(ci->author->when)); Err bitreich.org 70 i 828 else Err bitreich.org 70 i 829 fputs(" ", fp); Err bitreich.org 70 i 830 fputs(" ", fp); Err bitreich.org 70 i 831 utf8pad(buf, sizeof(buf), ci->summary ? ci->summary : "", 40, ' '); Err bitreich.org 70 i 832 gphlink(fp, buf, strlen(buf)); Err bitreich.org 70 i 833 fputs(" ", fp); Err bitreich.org 70 i 834 utf8pad(buf, sizeof(buf), ci->author ? ci->author->name : "", 19, '\0'); Err bitreich.org 70 i 835 gphlink(fp, buf, strlen(buf)); Err bitreich.org 70 i 836 fprintf(fp, "|%s/commit/%s.gph|server|port]\n", relpath, ci->oid); Err bitreich.org 70 i 837 } Err bitreich.org 70 i 838 Err bitreich.org 70 i 839 int Err bitreich.org 70 i 840 writelog(FILE *fp, const git_oid *oid) Err bitreich.org 70 i 841 { Err bitreich.org 70 i 842 struct commitinfo *ci; Err bitreich.org 70 i 843 git_revwalk *w = NULL; Err bitreich.org 70 i 844 git_oid id; Err bitreich.org 70 i 845 char path[PATH_MAX], oidstr[GIT_OID_HEXSZ + 1]; Err bitreich.org 70 i 846 FILE *fpfile; Err bitreich.org 70 i 847 size_t remcommits = 0; Err bitreich.org 70 i 848 int r; Err bitreich.org 70 i 849 Err bitreich.org 70 i 850 git_revwalk_new(&w, repo); Err bitreich.org 70 i 851 git_revwalk_push(w, oid); Err bitreich.org 70 i 852 Err bitreich.org 70 i 853 while (!git_revwalk_next(&id, w)) { Err bitreich.org 70 i 854 if (cachefile && !memcmp(&id, &lastoid, sizeof(id))) Err bitreich.org 70 i 855 break; Err bitreich.org 70 i 856 Err bitreich.org 70 i 857 git_oid_tostr(oidstr, sizeof(oidstr), &id); Err bitreich.org 70 i 858 r = snprintf(path, sizeof(path), "commit/%s.gph", oidstr); Err bitreich.org 70 i 859 if (r < 0 || (size_t)r >= sizeof(path)) Err bitreich.org 70 i 860 errx(1, "path truncated: 'commit/%s.gph'", oidstr); Err bitreich.org 70 i 861 r = access(path, F_OK); Err bitreich.org 70 i 862 Err bitreich.org 70 i 863 /* optimization: if there are no log lines to write and Err bitreich.org 70 i 864 the commit file already exists: skip the diffstat */ Err bitreich.org 70 i 865 if (!nlogcommits) { Err bitreich.org 70 i 866 remcommits++; Err bitreich.org 70 i 867 if (!r) Err bitreich.org 70 i 868 continue; Err bitreich.org 70 i 869 } Err bitreich.org 70 i 870 Err bitreich.org 70 i 871 if (!(ci = commitinfo_getbyoid(&id))) Err bitreich.org 70 i 872 break; Err bitreich.org 70 i 873 Err bitreich.org 70 i 874 if (nlogcommits != 0) { Err bitreich.org 70 i 875 writelogline(fp, ci); Err bitreich.org 70 i 876 if (nlogcommits > 0) Err bitreich.org 70 i 877 nlogcommits--; Err bitreich.org 70 i 878 } Err bitreich.org 70 i 879 Err bitreich.org 70 i 880 if (cachefile) Err bitreich.org 70 i 881 writelogline(wcachefp, ci); Err bitreich.org 70 i 882 Err bitreich.org 70 i 883 /* check if file exists if so skip it */ Err bitreich.org 70 i 884 if (r) { Err bitreich.org 70 i 885 /* lookup stats: only required here for gopher */ Err bitreich.org 70 i 886 if (commitinfo_getstats(ci) == -1) Err bitreich.org 70 i 887 goto err; Err bitreich.org 70 i 888 Err bitreich.org 70 i 889 fpfile = efopen(path, "w"); Err bitreich.org 70 i 890 writeheader(fpfile, ci->summary); Err bitreich.org 70 i 891 printshowfile(fpfile, ci); Err bitreich.org 70 i 892 writefooter(fpfile); Err bitreich.org 70 i 893 checkfileerror(fpfile, path, 'w'); Err bitreich.org 70 i 894 fclose(fpfile); Err bitreich.org 70 i 895 } Err bitreich.org 70 i 896 err: Err bitreich.org 70 i 897 commitinfo_free(ci); Err bitreich.org 70 i 898 } Err bitreich.org 70 i 899 git_revwalk_free(w); Err bitreich.org 70 i 900 Err bitreich.org 70 i 901 if (nlogcommits == 0 && remcommits != 0) { Err bitreich.org 70 i 902 fprintf(fp, "%16.16s " Err bitreich.org 70 i 903 "%zu more commits remaining, fetch the repository\n", Err bitreich.org 70 i 904 "", remcommits); Err bitreich.org 70 i 905 } Err bitreich.org 70 i 906 Err bitreich.org 70 i 907 return 0; Err bitreich.org 70 i 908 } Err bitreich.org 70 i 909 Err bitreich.org 70 i 910 void Err bitreich.org 70 i 911 printcommitatom(FILE *fp, struct commitinfo *ci, const char *tag) Err bitreich.org 70 i 912 { Err bitreich.org 70 i 913 fputs("\n", fp); Err bitreich.org 70 i 914 Err bitreich.org 70 i 915 fprintf(fp, "%s\n", ci->oid); Err bitreich.org 70 i 916 if (ci->author) { Err bitreich.org 70 i 917 fputs("", fp); Err bitreich.org 70 i 918 printtimez(fp, &(ci->author->when)); Err bitreich.org 70 i 919 fputs("\n", fp); Err bitreich.org 70 i 920 } Err bitreich.org 70 i 921 if (ci->committer) { Err bitreich.org 70 i 922 fputs("", fp); Err bitreich.org 70 i 923 printtimez(fp, &(ci->committer->when)); Err bitreich.org 70 i 924 fputs("\n", fp); Err bitreich.org 70 i 925 } Err bitreich.org 70 i 926 if (ci->summary) { Err bitreich.org 70 i 927 fputs("", fp); Err bitreich.org 70 i 928 if (tag && tag[0]) { Err bitreich.org 70 i 929 fputs("[", fp); Err bitreich.org 70 i 930 xmlencode(fp, tag, strlen(tag)); Err bitreich.org 70 i 931 fputs("] ", fp); Err bitreich.org 70 i 932 } Err bitreich.org 70 i 933 xmlencode(fp, ci->summary, strlen(ci->summary)); Err bitreich.org 70 i 934 fputs("\n", fp); Err bitreich.org 70 i 935 } Err bitreich.org 70 i 936 fprintf(fp, "\n", Err bitreich.org 70 i 937 baseurl, ci->oid); Err bitreich.org 70 i 938 Err bitreich.org 70 i 939 if (ci->author) { Err bitreich.org 70 i 940 fputs("\n", fp); Err bitreich.org 70 i 941 xmlencode(fp, ci->author->name, strlen(ci->author->name)); Err bitreich.org 70 i 942 fputs("\n", fp); Err bitreich.org 70 i 943 xmlencode(fp, ci->author->email, strlen(ci->author->email)); Err bitreich.org 70 i 944 fputs("\n\n", fp); Err bitreich.org 70 i 945 } Err bitreich.org 70 i 946 Err bitreich.org 70 i 947 fputs("", fp); Err bitreich.org 70 i 948 fprintf(fp, "commit %s\n", ci->oid); Err bitreich.org 70 i 949 if (ci->parentoid[0]) Err bitreich.org 70 i 950 fprintf(fp, "parent %s\n", ci->parentoid); Err bitreich.org 70 i 951 if (ci->author) { Err bitreich.org 70 i 952 fputs("Author: ", fp); Err bitreich.org 70 i 953 xmlencode(fp, ci->author->name, strlen(ci->author->name)); Err bitreich.org 70 i 954 fputs(" <", fp); Err bitreich.org 70 i 955 xmlencode(fp, ci->author->email, strlen(ci->author->email)); Err bitreich.org 70 i 956 fputs(">\nDate: ", fp); Err bitreich.org 70 i 957 printtime(fp, &(ci->author->when)); Err bitreich.org 70 i 958 putc('\n', fp); Err bitreich.org 70 i 959 } Err bitreich.org 70 i 960 if (ci->msg) { Err bitreich.org 70 i 961 putc('\n', fp); Err bitreich.org 70 i 962 xmlencode(fp, ci->msg, strlen(ci->msg)); Err bitreich.org 70 i 963 } Err bitreich.org 70 i 964 fputs("\n\n\n", fp); Err bitreich.org 70 i 965 } Err bitreich.org 70 i 966 Err bitreich.org 70 i 967 int Err bitreich.org 70 i 968 writeatom(FILE *fp, int all) Err bitreich.org 70 i 969 { Err bitreich.org 70 i 970 struct referenceinfo *ris = NULL; Err bitreich.org 70 i 971 size_t refcount = 0; Err bitreich.org 70 i 972 struct commitinfo *ci; Err bitreich.org 70 i 973 git_revwalk *w = NULL; Err bitreich.org 70 i 974 git_oid id; Err bitreich.org 70 i 975 size_t i, m = 100; /* last 'm' commits */ Err bitreich.org 70 i 976 Err bitreich.org 70 i 977 fputs("\n" Err bitreich.org 70 i 978 "\n", fp); Err bitreich.org 70 i 979 xmlencode(fp, strippedname, strlen(strippedname)); Err bitreich.org 70 i 980 fputs(", branch HEAD\n", fp); Err bitreich.org 70 i 981 xmlencode(fp, description, strlen(description)); Err bitreich.org 70 i 982 fputs("\n", fp); Err bitreich.org 70 i 983 Err bitreich.org 70 i 984 /* all commits or only tags? */ Err bitreich.org 70 i 985 if (all) { Err bitreich.org 70 i 986 git_revwalk_new(&w, repo); Err bitreich.org 70 i 987 git_revwalk_push_head(w); Err bitreich.org 70 i 988 for (i = 0; i < m && !git_revwalk_next(&id, w); i++) { Err bitreich.org 70 i 989 if (!(ci = commitinfo_getbyoid(&id))) Err bitreich.org 70 i 990 break; Err bitreich.org 70 i 991 printcommitatom(fp, ci, ""); Err bitreich.org 70 i 992 commitinfo_free(ci); Err bitreich.org 70 i 993 } Err bitreich.org 70 i 994 git_revwalk_free(w); Err bitreich.org 70 i 995 } else if (getrefs(&ris, &refcount) != -1) { Err bitreich.org 70 i 996 /* references: tags */ Err bitreich.org 70 i 997 for (i = 0; i < refcount; i++) { Err bitreich.org 70 i 998 if (git_reference_is_tag(ris[i].ref)) Err bitreich.org 70 i 999 printcommitatom(fp, ris[i].ci, Err bitreich.org 70 i 1000 git_reference_shorthand(ris[i].ref)); Err bitreich.org 70 i 1001 Err bitreich.org 70 i 1002 commitinfo_free(ris[i].ci); Err bitreich.org 70 i 1003 git_reference_free(ris[i].ref); Err bitreich.org 70 i 1004 } Err bitreich.org 70 i 1005 free(ris); Err bitreich.org 70 i 1006 } Err bitreich.org 70 i 1007 Err bitreich.org 70 i 1008 fputs("\n", fp); Err bitreich.org 70 i 1009 Err bitreich.org 70 i 1010 return 0; Err bitreich.org 70 i 1011 } Err bitreich.org 70 i 1012 Err bitreich.org 70 i 1013 size_t Err bitreich.org 70 i 1014 writeblob(git_object *obj, const char *fpath, const char *filename, size_t filesize) Err bitreich.org 70 i 1015 { Err bitreich.org 70 i 1016 char tmp[PATH_MAX] = "", *d; Err bitreich.org 70 i 1017 size_t lc = 0; Err bitreich.org 70 i 1018 FILE *fp; Err bitreich.org 70 i 1019 Err bitreich.org 70 i 1020 if (strlcpy(tmp, fpath, sizeof(tmp)) >= sizeof(tmp)) Err bitreich.org 70 i 1021 errx(1, "path truncated: '%s'", fpath); Err bitreich.org 70 i 1022 if (!(d = dirname(tmp))) Err bitreich.org 70 i 1023 err(1, "dirname"); Err bitreich.org 70 i 1024 if (mkdirp(d)) Err bitreich.org 70 i 1025 return -1; Err bitreich.org 70 i 1026 Err bitreich.org 70 i 1027 fp = efopen(fpath, "w"); Err bitreich.org 70 i 1028 writeheader(fp, filename); Err bitreich.org 70 i 1029 if (filename[0] == '[') Err bitreich.org 70 i 1030 fputs("[|", fp); Err bitreich.org 70 i 1031 gphtext(fp, filename, strlen(filename)); Err bitreich.org 70 i 1032 fprintf(fp, " (%zuB)\n", filesize); Err bitreich.org 70 i 1033 fputs("---\n", fp); Err bitreich.org 70 i 1034 Err bitreich.org 70 i 1035 if (git_blob_is_binary((git_blob *)obj)) Err bitreich.org 70 i 1036 fputs("Binary file.\n", fp); Err bitreich.org 70 i 1037 else Err bitreich.org 70 i 1038 lc = writeblobgph(fp, (git_blob *)obj); Err bitreich.org 70 i 1039 Err bitreich.org 70 i 1040 writefooter(fp); Err bitreich.org 70 i 1041 checkfileerror(fp, fpath, 'w'); Err bitreich.org 70 i 1042 fclose(fp); Err bitreich.org 70 i 1043 Err bitreich.org 70 i 1044 return lc; Err bitreich.org 70 i 1045 } Err bitreich.org 70 i 1046 Err bitreich.org 70 i 1047 const char * Err bitreich.org 70 i 1048 filemode(git_filemode_t m) Err bitreich.org 70 i 1049 { Err bitreich.org 70 i 1050 static char mode[11]; Err bitreich.org 70 i 1051 Err bitreich.org 70 i 1052 memset(mode, '-', sizeof(mode) - 1); Err bitreich.org 70 i 1053 mode[10] = '\0'; Err bitreich.org 70 i 1054 Err bitreich.org 70 i 1055 if (S_ISREG(m)) Err bitreich.org 70 i 1056 mode[0] = '-'; Err bitreich.org 70 i 1057 else if (S_ISBLK(m)) Err bitreich.org 70 i 1058 mode[0] = 'b'; Err bitreich.org 70 i 1059 else if (S_ISCHR(m)) Err bitreich.org 70 i 1060 mode[0] = 'c'; Err bitreich.org 70 i 1061 else if (S_ISDIR(m)) Err bitreich.org 70 i 1062 mode[0] = 'd'; Err bitreich.org 70 i 1063 else if (S_ISFIFO(m)) Err bitreich.org 70 i 1064 mode[0] = 'p'; Err bitreich.org 70 i 1065 else if (S_ISLNK(m)) Err bitreich.org 70 i 1066 mode[0] = 'l'; Err bitreich.org 70 i 1067 else if (S_ISSOCK(m)) Err bitreich.org 70 i 1068 mode[0] = 's'; Err bitreich.org 70 i 1069 else Err bitreich.org 70 i 1070 mode[0] = '?'; Err bitreich.org 70 i 1071 Err bitreich.org 70 i 1072 if (m & S_IRUSR) mode[1] = 'r'; Err bitreich.org 70 i 1073 if (m & S_IWUSR) mode[2] = 'w'; Err bitreich.org 70 i 1074 if (m & S_IXUSR) mode[3] = 'x'; Err bitreich.org 70 i 1075 if (m & S_IRGRP) mode[4] = 'r'; Err bitreich.org 70 i 1076 if (m & S_IWGRP) mode[5] = 'w'; Err bitreich.org 70 i 1077 if (m & S_IXGRP) mode[6] = 'x'; Err bitreich.org 70 i 1078 if (m & S_IROTH) mode[7] = 'r'; Err bitreich.org 70 i 1079 if (m & S_IWOTH) mode[8] = 'w'; Err bitreich.org 70 i 1080 if (m & S_IXOTH) mode[9] = 'x'; Err bitreich.org 70 i 1081 Err bitreich.org 70 i 1082 if (m & S_ISUID) mode[3] = (mode[3] == 'x') ? 's' : 'S'; Err bitreich.org 70 i 1083 if (m & S_ISGID) mode[6] = (mode[6] == 'x') ? 's' : 'S'; Err bitreich.org 70 i 1084 if (m & S_ISVTX) mode[9] = (mode[9] == 'x') ? 't' : 'T'; Err bitreich.org 70 i 1085 Err bitreich.org 70 i 1086 return mode; Err bitreich.org 70 i 1087 } Err bitreich.org 70 i 1088 Err bitreich.org 70 i 1089 int Err bitreich.org 70 i 1090 writefilestree(FILE *fp, git_tree *tree, const char *path) Err bitreich.org 70 i 1091 { Err bitreich.org 70 i 1092 const git_tree_entry *entry = NULL; Err bitreich.org 70 i 1093 git_object *obj = NULL; Err bitreich.org 70 i 1094 const char *entryname; Err bitreich.org 70 i 1095 char buf[256], filepath[PATH_MAX], entrypath[PATH_MAX], oid[8]; Err bitreich.org 70 i 1096 size_t count, i, lc, filesize; Err bitreich.org 70 i 1097 int r, ret; Err bitreich.org 70 i 1098 Err bitreich.org 70 i 1099 count = git_tree_entrycount(tree); Err bitreich.org 70 i 1100 for (i = 0; i < count; i++) { Err bitreich.org 70 i 1101 if (!(entry = git_tree_entry_byindex(tree, i)) || Err bitreich.org 70 i 1102 !(entryname = git_tree_entry_name(entry))) Err bitreich.org 70 i 1103 return -1; Err bitreich.org 70 i 1104 joinpath(entrypath, sizeof(entrypath), path, entryname); Err bitreich.org 70 i 1105 Err bitreich.org 70 i 1106 r = snprintf(filepath, sizeof(filepath), "file/%s.gph", Err bitreich.org 70 i 1107 entrypath); Err bitreich.org 70 i 1108 if (r < 0 || (size_t)r >= sizeof(filepath)) Err bitreich.org 70 i 1109 errx(1, "path truncated: 'file/%s.gph'", entrypath); Err bitreich.org 70 i 1110 Err bitreich.org 70 i 1111 if (!git_tree_entry_to_object(&obj, repo, entry)) { Err bitreich.org 70 i 1112 switch (git_object_type(obj)) { Err bitreich.org 70 i 1113 case GIT_OBJ_BLOB: Err bitreich.org 70 i 1114 break; Err bitreich.org 70 i 1115 case GIT_OBJ_TREE: Err bitreich.org 70 i 1116 /* NOTE: recurses */ Err bitreich.org 70 i 1117 ret = writefilestree(fp, (git_tree *)obj, Err bitreich.org 70 i 1118 entrypath); Err bitreich.org 70 i 1119 git_object_free(obj); Err bitreich.org 70 i 1120 if (ret) Err bitreich.org 70 i 1121 return ret; Err bitreich.org 70 i 1122 continue; Err bitreich.org 70 i 1123 default: Err bitreich.org 70 i 1124 git_object_free(obj); Err bitreich.org 70 i 1125 continue; Err bitreich.org 70 i 1126 } Err bitreich.org 70 i 1127 Err bitreich.org 70 i 1128 filesize = git_blob_rawsize((git_blob *)obj); Err bitreich.org 70 i 1129 lc = writeblob(obj, filepath, entryname, filesize); Err bitreich.org 70 i 1130 Err bitreich.org 70 i 1131 fputs("[1|", fp); Err bitreich.org 70 i 1132 fputs(filemode(git_tree_entry_filemode(entry)), fp); Err bitreich.org 70 i 1133 fputs(" ", fp); Err bitreich.org 70 i 1134 utf8pad(buf, sizeof(buf), entrypath, 50, ' '); Err bitreich.org 70 i 1135 gphlink(fp, buf, strlen(buf)); Err bitreich.org 70 i 1136 fputs(" ", fp); Err bitreich.org 70 i 1137 if (lc > 0) Err bitreich.org 70 i 1138 fprintf(fp, "%7zuL", lc); Err bitreich.org 70 i 1139 else Err bitreich.org 70 i 1140 fprintf(fp, "%7zuB", filesize); Err bitreich.org 70 i 1141 fprintf(fp, "|%s/", relpath); Err bitreich.org 70 i 1142 gphlink(fp, filepath, strlen(filepath)); Err bitreich.org 70 i 1143 fputs("|server|port]\n", fp); Err bitreich.org 70 i 1144 git_object_free(obj); Err bitreich.org 70 i 1145 } else if (git_tree_entry_type(entry) == GIT_OBJ_COMMIT) { Err bitreich.org 70 i 1146 /* commit object in tree is a submodule */ Err bitreich.org 70 i 1147 fputs("[1|m--------- ", fp); Err bitreich.org 70 i 1148 gphlink(fp, entrypath, strlen(entrypath)); Err bitreich.org 70 i 1149 fputs(" @ ", fp); Err bitreich.org 70 i 1150 git_oid_tostr(oid, sizeof(oid), git_tree_entry_id(entry)); Err bitreich.org 70 i 1151 gphlink(fp, oid, strlen(oid)); Err bitreich.org 70 i 1152 fprintf(fp, "|%s/file/.gitmodules.gph|server|port]\n", relpath); Err bitreich.org 70 i 1153 /* NOTE: linecount omitted */ Err bitreich.org 70 i 1154 } Err bitreich.org 70 i 1155 } Err bitreich.org 70 i 1156 Err bitreich.org 70 i 1157 return 0; Err bitreich.org 70 i 1158 } Err bitreich.org 70 i 1159 Err bitreich.org 70 i 1160 int Err bitreich.org 70 i 1161 writefiles(FILE *fp, const git_oid *id) Err bitreich.org 70 i 1162 { Err bitreich.org 70 i 1163 git_tree *tree = NULL; Err bitreich.org 70 i 1164 git_commit *commit = NULL; Err bitreich.org 70 i 1165 int ret = -1; Err bitreich.org 70 i 1166 Err bitreich.org 70 i 1167 fprintf(fp, "%-10.10s ", "Mode"); Err bitreich.org 70 i 1168 fprintf(fp, "%-50.50s ", "Name"); Err bitreich.org 70 i 1169 fprintf(fp, "%8.8s\n", "Size"); Err bitreich.org 70 i 1170 Err bitreich.org 70 i 1171 if (!git_commit_lookup(&commit, repo, id) && Err bitreich.org 70 i 1172 !git_commit_tree(&tree, commit)) Err bitreich.org 70 i 1173 ret = writefilestree(fp, tree, ""); Err bitreich.org 70 i 1174 Err bitreich.org 70 i 1175 git_commit_free(commit); Err bitreich.org 70 i 1176 git_tree_free(tree); Err bitreich.org 70 i 1177 Err bitreich.org 70 i 1178 return ret; Err bitreich.org 70 i 1179 } Err bitreich.org 70 i 1180 Err bitreich.org 70 i 1181 int Err bitreich.org 70 i 1182 writerefs(FILE *fp) Err bitreich.org 70 i 1183 { Err bitreich.org 70 i 1184 struct referenceinfo *ris = NULL; Err bitreich.org 70 i 1185 struct commitinfo *ci; Err bitreich.org 70 i 1186 size_t count, i, j, refcount; Err bitreich.org 70 i 1187 const char *titles[] = { "Branches", "Tags" }; Err bitreich.org 70 i 1188 const char *s; Err bitreich.org 70 i 1189 char buf[256]; Err bitreich.org 70 i 1190 Err bitreich.org 70 i 1191 if (getrefs(&ris, &refcount) == -1) Err bitreich.org 70 i 1192 return -1; Err bitreich.org 70 i 1193 Err bitreich.org 70 i 1194 for (i = 0, j = 0, count = 0; i < refcount; i++) { Err bitreich.org 70 i 1195 if (j == 0 && git_reference_is_tag(ris[i].ref)) { Err bitreich.org 70 i 1196 /* table footer */ Err bitreich.org 70 i 1197 if (count) Err bitreich.org 70 i 1198 fputs("\n", fp); Err bitreich.org 70 i 1199 count = 0; Err bitreich.org 70 i 1200 j = 1; Err bitreich.org 70 i 1201 } Err bitreich.org 70 i 1202 Err bitreich.org 70 i 1203 /* print header if it has an entry (first). */ Err bitreich.org 70 i 1204 if (++count == 1) { Err bitreich.org 70 i 1205 fprintf(fp, "%s\n", titles[j]); Err bitreich.org 70 i 1206 fprintf(fp, " %-32.32s", "Name"); Err bitreich.org 70 i 1207 fprintf(fp, " %-16.16s", "Last commit date"); Err bitreich.org 70 i 1208 fprintf(fp, " %s\n", "Author"); Err bitreich.org 70 i 1209 } Err bitreich.org 70 i 1210 Err bitreich.org 70 i 1211 ci = ris[i].ci; Err bitreich.org 70 i 1212 s = git_reference_shorthand(ris[i].ref); Err bitreich.org 70 i 1213 Err bitreich.org 70 i 1214 fputs(" ", fp); Err bitreich.org 70 i 1215 utf8pad(buf, sizeof(buf), s, 32, ' '); Err bitreich.org 70 i 1216 gphlink(fp, buf, strlen(buf)); Err bitreich.org 70 i 1217 fputs(" ", fp); Err bitreich.org 70 i 1218 if (ci->author) Err bitreich.org 70 i 1219 printtimeshort(fp, &(ci->author->when)); Err bitreich.org 70 i 1220 else Err bitreich.org 70 i 1221 fputs(" ", fp); Err bitreich.org 70 i 1222 fputs(" ", fp); Err bitreich.org 70 i 1223 if (ci->author) { Err bitreich.org 70 i 1224 utf8pad(buf, sizeof(buf), ci->author->name, 25, '\0'); Err bitreich.org 70 i 1225 gphlink(fp, buf, strlen(buf)); Err bitreich.org 70 i 1226 } Err bitreich.org 70 i 1227 fputs("\n", fp); Err bitreich.org 70 i 1228 } Err bitreich.org 70 i 1229 /* table footer */ Err bitreich.org 70 i 1230 if (count) Err bitreich.org 70 i 1231 fputs("\n", fp); Err bitreich.org 70 i 1232 Err bitreich.org 70 i 1233 for (i = 0; i < refcount; i++) { Err bitreich.org 70 i 1234 commitinfo_free(ris[i].ci); Err bitreich.org 70 i 1235 git_reference_free(ris[i].ref); Err bitreich.org 70 i 1236 } Err bitreich.org 70 i 1237 free(ris); Err bitreich.org 70 i 1238 Err bitreich.org 70 i 1239 return 0; Err bitreich.org 70 i 1240 } Err bitreich.org 70 i 1241 Err bitreich.org 70 i 1242 void Err bitreich.org 70 i 1243 usage(char *argv0) Err bitreich.org 70 i 1244 { Err bitreich.org 70 i 1245 fprintf(stderr, "usage: %s [-b baseprefix] [-c cachefile | -l commits] " Err bitreich.org 70 i 1246 "[-u baseurl] repodir\n", argv0); Err bitreich.org 70 i 1247 exit(1); Err bitreich.org 70 i 1248 } Err bitreich.org 70 i 1249 Err bitreich.org 70 i 1250 int Err bitreich.org 70 i 1251 main(int argc, char *argv[]) Err bitreich.org 70 i 1252 { Err bitreich.org 70 i 1253 git_object *obj = NULL; Err bitreich.org 70 i 1254 const git_oid *head = NULL; Err bitreich.org 70 i 1255 mode_t mask; Err bitreich.org 70 i 1256 FILE *fp, *fpread; Err bitreich.org 70 i 1257 char path[PATH_MAX], repodirabs[PATH_MAX + 1], *p; Err bitreich.org 70 i 1258 char tmppath[64] = "cache.XXXXXXXXXXXX", buf[BUFSIZ]; Err bitreich.org 70 i 1259 size_t n; Err bitreich.org 70 i 1260 int i, fd; Err bitreich.org 70 i 1261 Err bitreich.org 70 i 1262 setlocale(LC_CTYPE, ""); Err bitreich.org 70 i 1263 Err bitreich.org 70 i 1264 for (i = 1; i < argc; i++) { Err bitreich.org 70 i 1265 if (argv[i][0] != '-') { Err bitreich.org 70 i 1266 if (repodir) Err bitreich.org 70 i 1267 usage(argv[0]); Err bitreich.org 70 i 1268 repodir = argv[i]; Err bitreich.org 70 i 1269 } else if (argv[i][1] == 'b') { Err bitreich.org 70 i 1270 if (i + 1 >= argc) Err bitreich.org 70 i 1271 usage(argv[0]); Err bitreich.org 70 i 1272 relpath = argv[++i]; Err bitreich.org 70 i 1273 } else if (argv[i][1] == 'c') { Err bitreich.org 70 i 1274 if (nlogcommits > 0 || i + 1 >= argc) Err bitreich.org 70 i 1275 usage(argv[0]); Err bitreich.org 70 i 1276 cachefile = argv[++i]; Err bitreich.org 70 i 1277 } else if (argv[i][1] == 'l') { Err bitreich.org 70 i 1278 if (cachefile || i + 1 >= argc) Err bitreich.org 70 i 1279 usage(argv[0]); Err bitreich.org 70 i 1280 errno = 0; Err bitreich.org 70 i 1281 nlogcommits = strtoll(argv[++i], &p, 10); Err bitreich.org 70 i 1282 if (argv[i][0] == '\0' || *p != '\0' || Err bitreich.org 70 i 1283 nlogcommits <= 0 || errno) Err bitreich.org 70 i 1284 usage(argv[0]); Err bitreich.org 70 i 1285 } else if (argv[i][1] == 'u') { Err bitreich.org 70 i 1286 if (i + 1 >= argc) Err bitreich.org 70 i 1287 usage(argv[0]); Err bitreich.org 70 i 1288 baseurl = argv[++i]; Err bitreich.org 70 i 1289 } Err bitreich.org 70 i 1290 } Err bitreich.org 70 i 1291 if (!repodir) Err bitreich.org 70 i 1292 usage(argv[0]); Err bitreich.org 70 i 1293 Err bitreich.org 70 i 1294 if (!realpath(repodir, repodirabs)) Err bitreich.org 70 i 1295 err(1, "realpath"); Err bitreich.org 70 i 1296 Err bitreich.org 70 i 1297 /* do not search outside the git repository: Err bitreich.org 70 i 1298 GIT_CONFIG_LEVEL_APP is the highest level currently */ Err bitreich.org 70 i 1299 git_libgit2_init(); Err bitreich.org 70 i 1300 for (i = 1; i <= GIT_CONFIG_LEVEL_APP; i++) Err bitreich.org 70 i 1301 git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, i, ""); Err bitreich.org 70 i 1302 /* do not require the git repository to be owned by the current user */ Err bitreich.org 70 i 1303 git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 0); Err bitreich.org 70 i 1304 Err bitreich.org 70 i 1305 #ifdef __OpenBSD__ Err bitreich.org 70 i 1306 if (unveil(repodir, "r") == -1) Err bitreich.org 70 i 1307 err(1, "unveil: %s", repodir); Err bitreich.org 70 i 1308 if (unveil(".", "rwc") == -1) Err bitreich.org 70 i 1309 err(1, "unveil: ."); Err bitreich.org 70 i 1310 if (cachefile && unveil(cachefile, "rwc") == -1) Err bitreich.org 70 i 1311 err(1, "unveil: %s", cachefile); Err bitreich.org 70 i 1312 Err bitreich.org 70 i 1313 if (cachefile) { Err bitreich.org 70 i 1314 if (pledge("stdio rpath wpath cpath fattr", NULL) == -1) Err bitreich.org 70 i 1315 err(1, "pledge"); Err bitreich.org 70 i 1316 } else { Err bitreich.org 70 i 1317 if (pledge("stdio rpath wpath cpath", NULL) == -1) Err bitreich.org 70 i 1318 err(1, "pledge"); Err bitreich.org 70 i 1319 } Err bitreich.org 70 i 1320 #endif Err bitreich.org 70 i 1321 Err bitreich.org 70 i 1322 if (git_repository_open_ext(&repo, repodir, Err bitreich.org 70 i 1323 GIT_REPOSITORY_OPEN_NO_SEARCH, NULL) < 0) { Err bitreich.org 70 i 1324 fprintf(stderr, "%s: cannot open repository\n", argv[0]); Err bitreich.org 70 i 1325 return 1; Err bitreich.org 70 i 1326 } Err bitreich.org 70 i 1327 Err bitreich.org 70 i 1328 /* find HEAD */ Err bitreich.org 70 i 1329 if (!git_revparse_single(&obj, repo, "HEAD")) Err bitreich.org 70 i 1330 head = git_object_id(obj); Err bitreich.org 70 i 1331 git_object_free(obj); Err bitreich.org 70 i 1332 Err bitreich.org 70 i 1333 /* use directory name as name */ Err bitreich.org 70 i 1334 if ((name = strrchr(repodirabs, '/'))) Err bitreich.org 70 i 1335 name++; Err bitreich.org 70 i 1336 else Err bitreich.org 70 i 1337 name = ""; Err bitreich.org 70 i 1338 Err bitreich.org 70 i 1339 /* strip .git suffix */ Err bitreich.org 70 i 1340 if (!(strippedname = strdup(name))) Err bitreich.org 70 i 1341 err(1, "strdup"); Err bitreich.org 70 i 1342 if ((p = strrchr(strippedname, '.'))) Err bitreich.org 70 i 1343 if (!strcmp(p, ".git")) Err bitreich.org 70 i 1344 *p = '\0'; Err bitreich.org 70 i 1345 Err bitreich.org 70 i 1346 /* read description or .git/description */ Err bitreich.org 70 i 1347 joinpath(path, sizeof(path), repodir, "description"); Err bitreich.org 70 i 1348 if (!(fpread = fopen(path, "r"))) { Err bitreich.org 70 i 1349 joinpath(path, sizeof(path), repodir, ".git/description"); Err bitreich.org 70 i 1350 fpread = fopen(path, "r"); Err bitreich.org 70 i 1351 } Err bitreich.org 70 i 1352 if (fpread) { Err bitreich.org 70 i 1353 if (!fgets(description, sizeof(description), fpread)) Err bitreich.org 70 i 1354 description[0] = '\0'; Err bitreich.org 70 i 1355 checkfileerror(fpread, path, 'r'); Err bitreich.org 70 i 1356 fclose(fpread); Err bitreich.org 70 i 1357 } Err bitreich.org 70 i 1358 Err bitreich.org 70 i 1359 /* read url or .git/url */ Err bitreich.org 70 i 1360 joinpath(path, sizeof(path), repodir, "url"); Err bitreich.org 70 i 1361 if (!(fpread = fopen(path, "r"))) { Err bitreich.org 70 i 1362 joinpath(path, sizeof(path), repodir, ".git/url"); Err bitreich.org 70 i 1363 fpread = fopen(path, "r"); Err bitreich.org 70 i 1364 } Err bitreich.org 70 i 1365 if (fpread) { Err bitreich.org 70 i 1366 if (!fgets(cloneurl, sizeof(cloneurl), fpread)) Err bitreich.org 70 i 1367 cloneurl[0] = '\0'; Err bitreich.org 70 i 1368 checkfileerror(fpread, path, 'r'); Err bitreich.org 70 i 1369 fclose(fpread); Err bitreich.org 70 i 1370 cloneurl[strcspn(cloneurl, "\n")] = '\0'; Err bitreich.org 70 i 1371 } Err bitreich.org 70 i 1372 Err bitreich.org 70 i 1373 /* check LICENSE */ Err bitreich.org 70 i 1374 for (i = 0; i < LEN(licensefiles) && !license; i++) { Err bitreich.org 70 i 1375 if (!git_revparse_single(&obj, repo, licensefiles[i]) && Err bitreich.org 70 i 1376 git_object_type(obj) == GIT_OBJ_BLOB) Err bitreich.org 70 i 1377 license = licensefiles[i] + strlen("HEAD:"); Err bitreich.org 70 i 1378 git_object_free(obj); Err bitreich.org 70 i 1379 } Err bitreich.org 70 i 1380 Err bitreich.org 70 i 1381 /* check README */ Err bitreich.org 70 i 1382 for (i = 0; i < LEN(readmefiles) && !readme; i++) { Err bitreich.org 70 i 1383 if (!git_revparse_single(&obj, repo, readmefiles[i]) && Err bitreich.org 70 i 1384 git_object_type(obj) == GIT_OBJ_BLOB) Err bitreich.org 70 i 1385 readme = readmefiles[i] + strlen("HEAD:"); Err bitreich.org 70 i 1386 git_object_free(obj); Err bitreich.org 70 i 1387 } Err bitreich.org 70 i 1388 Err bitreich.org 70 i 1389 if (!git_revparse_single(&obj, repo, "HEAD:.gitmodules") && Err bitreich.org 70 i 1390 git_object_type(obj) == GIT_OBJ_BLOB) Err bitreich.org 70 i 1391 submodules = ".gitmodules"; Err bitreich.org 70 i 1392 git_object_free(obj); Err bitreich.org 70 i 1393 Err bitreich.org 70 i 1394 /* log for HEAD */ Err bitreich.org 70 i 1395 fp = efopen("log.gph", "w"); Err bitreich.org 70 i 1396 mkdir("commit", S_IRWXU | S_IRWXG | S_IRWXO); Err bitreich.org 70 i 1397 writeheader(fp, "Log"); Err bitreich.org 70 i 1398 Err bitreich.org 70 i 1399 fprintf(fp, "%-16.16s ", "Date"); Err bitreich.org 70 i 1400 fprintf(fp, "%-40.40s ", "Commit message"); Err bitreich.org 70 i 1401 fprintf(fp, "%s\n", "Author"); Err bitreich.org 70 i 1402 Err bitreich.org 70 i 1403 if (cachefile && head) { Err bitreich.org 70 i 1404 /* read from cache file (does not need to exist) */ Err bitreich.org 70 i 1405 if ((rcachefp = fopen(cachefile, "r"))) { Err bitreich.org 70 i 1406 if (!fgets(lastoidstr, sizeof(lastoidstr), rcachefp)) Err bitreich.org 70 i 1407 errx(1, "%s: no object id", cachefile); Err bitreich.org 70 i 1408 if (git_oid_fromstr(&lastoid, lastoidstr)) Err bitreich.org 70 i 1409 errx(1, "%s: invalid object id", cachefile); Err bitreich.org 70 i 1410 } Err bitreich.org 70 i 1411 Err bitreich.org 70 i 1412 /* write log to (temporary) cache */ Err bitreich.org 70 i 1413 if ((fd = mkstemp(tmppath)) == -1) Err bitreich.org 70 i 1414 err(1, "mkstemp"); Err bitreich.org 70 i 1415 if (!(wcachefp = fdopen(fd, "w"))) Err bitreich.org 70 i 1416 err(1, "fdopen: '%s'", tmppath); Err bitreich.org 70 i 1417 /* write last commit id (HEAD) */ Err bitreich.org 70 i 1418 git_oid_tostr(buf, sizeof(buf), head); Err bitreich.org 70 i 1419 fprintf(wcachefp, "%s\n", buf); Err bitreich.org 70 i 1420 Err bitreich.org 70 i 1421 writelog(fp, head); Err bitreich.org 70 i 1422 Err bitreich.org 70 i 1423 if (rcachefp) { Err bitreich.org 70 i 1424 /* append previous log to log.gph and the new cache */ Err bitreich.org 70 i 1425 while (!feof(rcachefp)) { Err bitreich.org 70 i 1426 n = fread(buf, 1, sizeof(buf), rcachefp); Err bitreich.org 70 i 1427 if (ferror(rcachefp)) Err bitreich.org 70 i 1428 break; Err bitreich.org 70 i 1429 if (fwrite(buf, 1, n, fp) != n || Err bitreich.org 70 i 1430 fwrite(buf, 1, n, wcachefp) != n) Err bitreich.org 70 i 1431 break; Err bitreich.org 70 i 1432 } Err bitreich.org 70 i 1433 checkfileerror(rcachefp, cachefile, 'r'); Err bitreich.org 70 i 1434 fclose(rcachefp); Err bitreich.org 70 i 1435 } Err bitreich.org 70 i 1436 checkfileerror(wcachefp, tmppath, 'w'); Err bitreich.org 70 i 1437 fclose(wcachefp); Err bitreich.org 70 i 1438 } else { Err bitreich.org 70 i 1439 if (head) Err bitreich.org 70 i 1440 writelog(fp, head); Err bitreich.org 70 i 1441 } Err bitreich.org 70 i 1442 fputs("\n", fp); Err bitreich.org 70 i 1443 fprintf(fp, "[0|Atom feed|%s/atom.xml|server|port]\n", relpath); Err bitreich.org 70 i 1444 fprintf(fp, "[0|Atom feed (tags)|%s/tags.xml|server|port]\n", relpath); Err bitreich.org 70 i 1445 writefooter(fp); Err bitreich.org 70 i 1446 checkfileerror(fp, "log.gph", 'w'); Err bitreich.org 70 i 1447 fclose(fp); Err bitreich.org 70 i 1448 Err bitreich.org 70 i 1449 /* files for HEAD */ Err bitreich.org 70 i 1450 fp = efopen("files.gph", "w"); Err bitreich.org 70 i 1451 writeheader(fp, "Files"); Err bitreich.org 70 i 1452 if (head) Err bitreich.org 70 i 1453 writefiles(fp, head); Err bitreich.org 70 i 1454 writefooter(fp); Err bitreich.org 70 i 1455 checkfileerror(fp, "files.gph", 'w'); Err bitreich.org 70 i 1456 fclose(fp); Err bitreich.org 70 i 1457 Err bitreich.org 70 i 1458 /* summary page with branches and tags */ Err bitreich.org 70 i 1459 fp = efopen("refs.gph", "w"); Err bitreich.org 70 i 1460 writeheader(fp, "Refs"); Err bitreich.org 70 i 1461 writerefs(fp); Err bitreich.org 70 i 1462 writefooter(fp); Err bitreich.org 70 i 1463 checkfileerror(fp, "refs.gph", 'w'); Err bitreich.org 70 i 1464 fclose(fp); Err bitreich.org 70 i 1465 Err bitreich.org 70 i 1466 /* Atom feed */ Err bitreich.org 70 i 1467 fp = efopen("atom.xml", "w"); Err bitreich.org 70 i 1468 writeatom(fp, 1); Err bitreich.org 70 i 1469 checkfileerror(fp, "atom.xml", 'w'); Err bitreich.org 70 i 1470 fclose(fp); Err bitreich.org 70 i 1471 Err bitreich.org 70 i 1472 /* Atom feed for tags / releases */ Err bitreich.org 70 i 1473 fp = efopen("tags.xml", "w"); Err bitreich.org 70 i 1474 writeatom(fp, 0); Err bitreich.org 70 i 1475 checkfileerror(fp, "tags.xml", 'w'); Err bitreich.org 70 i 1476 fclose(fp); Err bitreich.org 70 i 1477 Err bitreich.org 70 i 1478 /* rename new cache file on success */ Err bitreich.org 70 i 1479 if (cachefile && head) { Err bitreich.org 70 i 1480 if (rename(tmppath, cachefile)) Err bitreich.org 70 i 1481 err(1, "rename: '%s' to '%s'", tmppath, cachefile); Err bitreich.org 70 i 1482 umask((mask = umask(0))); Err bitreich.org 70 i 1483 if (chmod(cachefile, Err bitreich.org 70 i 1484 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) & ~mask)) Err bitreich.org 70 i 1485 err(1, "chmod: '%s'", cachefile); Err bitreich.org 70 i 1486 } Err bitreich.org 70 i 1487 Err bitreich.org 70 i 1488 /* cleanup */ Err bitreich.org 70 i 1489 git_repository_free(repo); Err bitreich.org 70 i 1490 git_libgit2_shutdown(); Err bitreich.org 70 i 1491 Err bitreich.org 70 i 1492 return 0; Err bitreich.org 70 i 1493 } Err bitreich.org 70 .