/* * Utilities library for libgit2 examples * * Written by the libgit2 contributors * * To the extent possible under law, the author(s) have dedicated all copyright * and related and neighboring rights to this software to the public domain * worldwide. This software is distributed without any warranty. * * You should have received a copy of the CC0 Public Domain Dedication along * with this software. If not, see * . */ #include #include "common.h" void check_lg2(int error, const char *message, const char *extra) { const git_error *lg2err; const char *lg2msg = "", *lg2spacer = ""; if (!error) return; if ((lg2err = git_error_last()) != NULL && lg2err->message != NULL) { lg2msg = lg2err->message; lg2spacer = " - "; } if (extra) fprintf(stderr, "%s '%s' [%d]%s%s\n", message, extra, error, lg2spacer, lg2msg); else fprintf(stderr, "%s [%d]%s%s\n", message, error, lg2spacer, lg2msg); exit(1); } void fatal(const char *message, const char *extra) { if (extra) fprintf(stderr, "%s %s\n", message, extra); else fprintf(stderr, "%s\n", message); exit(1); } size_t is_prefixed(const char *str, const char *pfx) { size_t len = strlen(pfx); return strncmp(str, pfx, len) ? 0 : len; } int optional_str_arg( const char **out, struct args_info *args, const char *opt, const char *def) { const char *found = args->argv[args->pos]; size_t len = is_prefixed(found, opt); if (!len) return 0; if (!found[len]) { if (args->pos + 1 == args->argc) { *out = def; return 1; } args->pos += 1; *out = args->argv[args->pos]; return 1; } if (found[len] == '=') { *out = found + len + 1; return 1; } return 0; } int match_str_arg( const char **out, struct args_info *args, const char *opt) { const char *found = args->argv[args->pos]; size_t len = is_prefixed(found, opt); if (!len) return 0; if (!found[len]) { if (args->pos + 1 == args->argc) fatal("expected value following argument", opt); args->pos += 1; *out = args->argv[args->pos]; return 1; } if (found[len] == '=') { *out = found + len + 1; return 1; } return 0; } static const char *match_numeric_arg(struct args_info *args, const char *opt) { const char *found = args->argv[args->pos]; size_t len = is_prefixed(found, opt); if (!len) return NULL; if (!found[len]) { if (args->pos + 1 == args->argc) fatal("expected numeric value following argument", opt); args->pos += 1; found = args->argv[args->pos]; } else { found = found + len; if (*found == '=') found++; } return found; } int match_uint16_arg( uint16_t *out, struct args_info *args, const char *opt) { const char *found = match_numeric_arg(args, opt); uint16_t val; char *endptr = NULL; if (!found) return 0; val = (uint16_t)strtoul(found, &endptr, 0); if (!endptr || *endptr != '\0') fatal("expected number after argument", opt); if (out) *out = val; return 1; } int match_uint32_arg( uint32_t *out, struct args_info *args, const char *opt) { const char *found = match_numeric_arg(args, opt); uint16_t val; char *endptr = NULL; if (!found) return 0; val = (uint32_t)strtoul(found, &endptr, 0); if (!endptr || *endptr != '\0') fatal("expected number after argument", opt); if (out) *out = val; return 1; } static int match_int_internal( int *out, const char *str, int allow_negative, const char *opt) { char *endptr = NULL; int val = (int)strtol(str, &endptr, 10); if (!endptr || *endptr != '\0') fatal("expected number", opt); else if (val < 0 && !allow_negative) fatal("negative values are not allowed", opt); if (out) *out = val; return 1; } int match_bool_arg(int *out, struct args_info *args, const char *opt) { const char *found = args->argv[args->pos]; if (!strcmp(found, opt)) { *out = 1; return 1; } if (!strncmp(found, "--no-", strlen("--no-")) && !strcmp(found + strlen("--no-"), opt + 2)) { *out = 0; return 1; } *out = -1; return 0; } int is_integer(int *out, const char *str, int allow_negative) { return match_int_internal(out, str, allow_negative, NULL); } int match_int_arg( int *out, struct args_info *args, const char *opt, int allow_negative) { const char *found = match_numeric_arg(args, opt); if (!found) return 0; return match_int_internal(out, found, allow_negative, opt); } int diff_output( const git_diff_delta *d, const git_diff_hunk *h, const git_diff_line *l, void *p) { FILE *fp = (FILE*)p; (void)d; (void)h; if (!fp) fp = stdout; if (l->origin == GIT_DIFF_LINE_CONTEXT || l->origin == GIT_DIFF_LINE_ADDITION || l->origin == GIT_DIFF_LINE_DELETION) fputc(l->origin, fp); fwrite(l->content, 1, l->content_len, fp); return 0; } void treeish_to_tree( git_tree **out, git_repository *repo, const char *treeish) { git_object *obj = NULL; check_lg2( git_revparse_single(&obj, repo, treeish), "looking up object", treeish); check_lg2( git_object_peel((git_object **)out, obj, GIT_OBJECT_TREE), "resolving object to tree", treeish); git_object_free(obj); } void *xrealloc(void *oldp, size_t newsz) { void *p = realloc(oldp, newsz); if (p == NULL) { fprintf(stderr, "Cannot allocate memory, exiting.\n"); exit(1); } return p; } int resolve_refish(git_annotated_commit **commit, git_repository *repo, const char *refish) { git_reference *ref; git_object *obj; int err = 0; assert(commit != NULL); err = git_reference_dwim(&ref, repo, refish); if (err == GIT_OK) { git_annotated_commit_from_ref(commit, repo, ref); git_reference_free(ref); return 0; } err = git_revparse_single(&obj, repo, refish); if (err == GIT_OK) { err = git_annotated_commit_lookup(commit, repo, git_object_id(obj)); git_object_free(obj); } return err; }