From 7c026a9686543d3102fdd1cdcfb2645d6a3bddd6 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 29 Mar 2015 11:58:58 +0300 Subject: [PATCH 001/171] update to libgit2 0.22, examples/diff disabled --- CMakeLists.txt | 2 + examples/add.cpp | 4 +- examples/branch.cpp | 2 +- examples/cat-file.cpp | 4 +- examples/diff.cpp | 267 +++--------- examples/init.cpp | 4 +- examples/log.cpp | 592 +++++++++++++------------- examples/rev-parse.cpp | 4 +- examples/showindex.cpp | 84 ++-- include/git2cpp/commit.h | 65 +-- include/git2cpp/diff.h | 61 +++ include/git2cpp/diff_list.h | 66 --- include/git2cpp/initializer.h | 13 + include/git2cpp/object.h | 43 +- include/git2cpp/repo.h | 9 +- include/git2cpp/revspec.h | 49 +-- include/git2cpp/tag.h | 31 +- include/git2cpp/threads_initializer.h | 13 - include/git2cpp/tree.h | 1 - src/commit.cpp | 103 +++-- src/diff.cpp | 74 ++++ src/diff_list.cpp | 78 ---- src/index.cpp | 2 +- src/initializer.cpp | 20 + src/object.cpp | 6 +- src/repo.cpp | 72 +++- src/revspec.cpp | 10 +- src/tag.cpp | 8 +- src/threads_initializer.cpp | 20 - 29 files changed, 804 insertions(+), 903 deletions(-) create mode 100644 include/git2cpp/diff.h delete mode 100644 include/git2cpp/diff_list.h create mode 100644 include/git2cpp/initializer.h delete mode 100644 include/git2cpp/threads_initializer.h create mode 100644 src/diff.cpp delete mode 100644 src/diff_list.cpp create mode 100644 src/initializer.cpp delete mode 100644 src/threads_initializer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 20e434c..93bbbe8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ file(GLOB lib_sources add_library(git2cpp ${lib_sources}) target_link_libraries(git2cpp git2) +install_targets(/lib git2cpp) + set(examples add branch diff --git a/examples/add.cpp b/examples/add.cpp index f491114..48cecbe 100644 --- a/examples/add.cpp +++ b/examples/add.cpp @@ -4,7 +4,7 @@ #include #include "git2cpp/repo.h" -#include "git2cpp/threads_initializer.h" +#include "git2cpp/initializer.h" enum print_options { SKIP = 1, @@ -98,7 +98,7 @@ int main (int argc, char** argv) init_array(&array, argc-i, argv+i); - git::ThreadsInitializer threads_initializer; + git::Initializer threads_initializer; git::Repository repo("."); diff --git a/examples/branch.cpp b/examples/branch.cpp index 0c3f0fa..3e139d0 100644 --- a/examples/branch.cpp +++ b/examples/branch.cpp @@ -5,7 +5,7 @@ int main() { git::Repository repo("."); - auto branches = repo.branches(); + auto branches = repo.branches(git::branch_type::LOCAL); for (auto b : branches) std::cout << b << std::endl; } diff --git a/examples/cat-file.cpp b/examples/cat-file.cpp index 723d68f..b973c11 100644 --- a/examples/cat-file.cpp +++ b/examples/cat-file.cpp @@ -5,7 +5,7 @@ #include -#include "git2cpp/threads_initializer.h" +#include "git2cpp/initializer.h" #include "git2cpp/repo.h" #include "git2cpp/id_to_str.h" @@ -163,7 +163,7 @@ int main(int argc, char *argv[]) if (!action || !rev) usage(NULL, NULL); - git::ThreadsInitializer threads_initializer; + git::Initializer threads_initializer; git::Repository repo(dir); git::Object obj = revparse_single(repo, rev); diff --git a/examples/diff.cpp b/examples/diff.cpp index 2cd3119..5d8658f 100644 --- a/examples/diff.cpp +++ b/examples/diff.cpp @@ -5,115 +5,68 @@ #include -#include "git2cpp/threads_initializer.h" +#include "git2cpp/initializer.h" #include "git2cpp/repo.h" +#include "git2cpp/diff.h" using namespace git; Tree resolve_to_tree(Repository const & repo, const char *identifier) { - Object obj = revparse_single(repo, identifier); - - switch (obj.type()) - { - case GIT_OBJ_TREE: - return obj.to_tree(); - break; - case GIT_OBJ_COMMIT: - return obj.to_commit().tree(); - break; - } - - std::ostringstream ss; - ss - << "object corresponding to identifier " - << identifier - << " is neither commit or tree"; - - throw std::logic_error(ss.str()); + Object obj = revparse_single(repo, identifier); + + switch (obj.type()) + { + case GIT_OBJ_TREE: + return obj.to_tree(); + break; + case GIT_OBJ_COMMIT: + return obj.to_commit().tree(); + break; + } + + std::ostringstream ss; + ss + << "object corresponding to identifier " + << identifier + << " is neither commit or tree"; + + throw std::logic_error(ss.str()); } const char *colors[] = { - "\033[m", /* reset */ - "\033[1m", /* bold */ - "\033[31m", /* red */ - "\033[32m", /* green */ - "\033[36m" /* cyan */ + "\033[m", /* reset */ + "\033[1m", /* bold */ + "\033[31m", /* red */ + "\033[32m", /* green */ + "\033[36m" /* cyan */ }; -static int printer( - const git_diff_delta *, - const git_diff_range *, - char usage, - const char *line, - size_t, - int & last_color) -{ - int color = 0; - - if (last_color >= 0) { - switch (usage) { - case GIT_DIFF_LINE_ADDITION: color = 3; break; - case GIT_DIFF_LINE_DELETION: color = 2; break; - case GIT_DIFF_LINE_ADD_EOFNL: color = 3; break; - case GIT_DIFF_LINE_DEL_EOFNL: color = 2; break; - case GIT_DIFF_LINE_FILE_HDR: color = 1; break; - case GIT_DIFF_LINE_HUNK_HDR: color = 4; break; - default: color = 0; - } - if (color != last_color) { - if (last_color == 1 || color == 1) - fputs(colors[0], stdout); - fputs(colors[color], stdout); - last_color = color; - } - } - - fputs(line, stdout); - return 0; -} - -static int check_uint16_param(const char *arg, const char *pattern, uint16_t *val) -{ - size_t len = strlen(pattern); - uint16_t strval; - char *endptr = NULL; - if (strncmp(arg, pattern, len)) - return 0; - if (arg[len] == '\0' && pattern[len - 1] != '=') - return 1; - if (arg[len] == '=') - len++; - strval = strtoul(arg + len, &endptr, 0); - if (endptr == arg) - return 0; - *val = strval; - return 1; -} +int diff_output(const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); static int check_str_param(const char *arg, const char *pattern, const char **val) { - size_t len = strlen(pattern); - if (strncmp(arg, pattern, len)) - return 0; - *val = (const char *)(arg + len); - return 1; + size_t len = strlen(pattern); + if (strncmp(arg, pattern, len)) + return 0; + *val = (const char *)(arg + len); + return 1; } static void usage(const char *message, const char *arg) { - if (message && arg) - fprintf(stderr, "%s: %s\n", message, arg); - else if (message) - fprintf(stderr, "%s\n", message); - fprintf(stderr, "usage: diff [ []]\n"); - exit(1); + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: diff [ []]\n"); + exit(1); } enum { - FORMAT_PATCH = 0, - FORMAT_COMPACT = 1, - FORMAT_RAW = 2 + FORMAT_PATCH = 0, + FORMAT_COMPACT = 1, + FORMAT_RAW = 2 }; /* */ @@ -122,134 +75,24 @@ enum { /* --cached */ /* nothing */ -DiffList diff(Repository & repo, Tree & t1, Tree & t2, bool cached, git_diff_options const & opts) +Diff calc_diff(Repository & repo, Tree & t1, Tree & t2, bool cached, git_diff_options const & opts) { - auto r_ptr = repo.ptr(); - - if (t1 && t2) - return diff(r_ptr, t1, t2, opts); - else if (t1 && cached) - return diff_to_index(r_ptr, t1, opts); - else if (t1) - return std::move(diff_to_index(r_ptr, t1, opts).merge(diff_index_to_workdir(r_ptr, opts))); - else if (cached) - { - auto tree = resolve_to_tree(repo, "HEAD"); - return diff_to_index(r_ptr, tree, opts); - } - else - return diff_index_to_workdir(r_ptr, opts); + if (t1 && t2) + return git::diff(repo, t1, t2, opts); + else if (t1 && cached) + return diff_to_index(repo, t1, opts); + else if (t1) + return std::move(diff_to_index(repo, t1, opts).merge(diff_index_to_workdir(repo, opts))); + else if (cached) + { + auto tree = resolve_to_tree(repo, "HEAD"); + return diff_to_index(repo, tree, opts); + } + else + return diff_index_to_workdir(repo, opts); } int main(int argc, char *argv[]) { - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; - int i, color = -1, format = FORMAT_PATCH, cached = 0; - char *a, *treeish1 = NULL, *treeish2 = NULL; - const char *dir = "."; - - git::ThreadsInitializer threads_initializer; - - /* parse arguments as copied from git-diff */ - - for (i = 1; i < argc; ++i) { - a = argv[i]; - - if (a[0] != '-') { - if (treeish1 == NULL) - treeish1 = a; - else if (treeish2 == NULL) - treeish2 = a; - else - usage("Only one or two tree identifiers can be provided", NULL); - } - else if (!strcmp(a, "-p") || !strcmp(a, "-u") || - !strcmp(a, "--patch")) - format = FORMAT_PATCH; - else if (!strcmp(a, "--cached")) - cached = 1; - else if (!strcmp(a, "--name-status")) - format = FORMAT_COMPACT; - else if (!strcmp(a, "--raw")) - format = FORMAT_RAW; - else if (!strcmp(a, "--color")) - color = 0; - else if (!strcmp(a, "--no-color")) - color = -1; - else if (!strcmp(a, "-R")) - opts.flags |= GIT_DIFF_REVERSE; - else if (!strcmp(a, "-a") || !strcmp(a, "--text")) - opts.flags |= GIT_DIFF_FORCE_TEXT; - else if (!strcmp(a, "--ignore-space-at-eol")) - opts.flags |= GIT_DIFF_IGNORE_WHITESPACE_EOL; - else if (!strcmp(a, "-b") || !strcmp(a, "--ignore-space-change")) - opts.flags |= GIT_DIFF_IGNORE_WHITESPACE_CHANGE; - else if (!strcmp(a, "-w") || !strcmp(a, "--ignore-all-space")) - opts.flags |= GIT_DIFF_IGNORE_WHITESPACE; - else if (!strcmp(a, "--ignored")) - opts.flags |= GIT_DIFF_INCLUDE_IGNORED; - else if (!strcmp(a, "--untracked")) - opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; - else if (check_uint16_param(a, "-M", &findopts.rename_threshold) || - check_uint16_param(a, "--find-renames", - &findopts.rename_threshold)) - findopts.flags |= GIT_DIFF_FIND_RENAMES; - else if (check_uint16_param(a, "-C", &findopts.copy_threshold) || - check_uint16_param(a, "--find-copies", - &findopts.copy_threshold)) - findopts.flags |= GIT_DIFF_FIND_COPIES; - else if (!strcmp(a, "--find-copies-harder")) - findopts.flags |= GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; - else if (!strncmp(a, "-B", 2) || !strncmp(a, "--break-rewrites", 16)) { - /* TODO: parse thresholds */ - findopts.flags |= GIT_DIFF_FIND_REWRITES; - } - else if (!check_uint16_param(a, "-U", &opts.context_lines) && - !check_uint16_param(a, "--unified=", &opts.context_lines) && - !check_uint16_param(a, "--inter-hunk-context=", - &opts.interhunk_lines) && - !check_str_param(a, "--src-prefix=", &opts.old_prefix) && - !check_str_param(a, "--dst-prefix=", &opts.new_prefix) && - !check_str_param(a, "--git-dir=", &dir)) - usage("Unknown arg", a); - } - - git::Repository repo(dir); - - git::Tree t1, t2; - - if (treeish1) - t1 = resolve_to_tree(repo, treeish1); - if (treeish2) - t2 = resolve_to_tree(repo, treeish2); - - DiffList diff_list = diff(repo, t1, t2, cached, opts); - - if ((findopts.flags & GIT_DIFF_FIND_ALL) != 0) - diff_list.find_similar(findopts); - - if (color >= 0) - fputs(colors[0], stdout); - - using namespace std::placeholders; - auto print_cb = std::bind(&printer, _1, _2, _3, _4, _5, std::ref(color)); - - switch (format) { - case FORMAT_PATCH: - diff_list.print_patch(print_cb); - break; - case FORMAT_COMPACT: - diff_list.print_compact(print_cb); - break; - case FORMAT_RAW: - diff_list.print_raw(print_cb); - break; - } - - if (color >= 0) - fputs(colors[0], stdout); - - return 0; } diff --git a/examples/init.cpp b/examples/init.cpp index e0dc2e7..24e627f 100644 --- a/examples/init.cpp +++ b/examples/init.cpp @@ -20,7 +20,7 @@ #include #include -#include "git2cpp/threads_initializer.h" +#include "git2cpp/initializer.h" #include "git2cpp/repo.h" static void usage(const char *error, const char *arg) @@ -108,7 +108,7 @@ int main(int argc, char *argv[]) const char *templ = NULL, *gitdir = NULL, *dir = NULL; size_t pfxlen; - ThreadsInitializer threads_initializer; + Initializer threads_initializer; /* Process arguments */ diff --git a/examples/log.cpp b/examples/log.cpp index 829c828..d1ac6dc 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -9,373 +9,367 @@ #include "git2cpp/repo.h" #include "git2cpp/pathspec.h" -#include "git2cpp/threads_initializer.h" +#include "git2cpp/initializer.h" #include "git2cpp/id_to_str.h" #include "git2cpp/revspec.h" #include "git2cpp/revwalker.h" +#include "git2cpp/diff.h" static void usage(const char *message, const char *arg) { - if (message && arg) - fprintf(stderr, "%s: %s\n", message, arg); - else if (message) - fprintf(stderr, "%s\n", message); - fprintf(stderr, "usage: log []\n"); - exit(1); + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: log []\n"); + exit(1); } struct log_state { - std::string repodir = "."; - boost::optional repo; - std::unique_ptr walker; - int hide = 0; - int sorting = GIT_SORT_TIME; + std::string repodir = "."; + boost::optional repo; + std::unique_ptr walker; + int hide = 0; + int sorting = GIT_SORT_TIME; }; static void set_sorting(struct log_state *s, unsigned int sort_mode) { - if (!s->repo) { - s->repo = boost::in_place(s->repodir); - } + if (!s->repo) { + s->repo = boost::in_place(s->repodir); + } - if (!s->walker) - s->walker.reset(new git::RevWalker(s->repo->rev_walker())); + if (!s->walker) + s->walker.reset(new git::RevWalker(s->repo->rev_walker())); - if (sort_mode == GIT_SORT_REVERSE) - s->sorting = s->sorting ^ GIT_SORT_REVERSE; - else - s->sorting = sort_mode | (s->sorting & GIT_SORT_REVERSE); + if (sort_mode == GIT_SORT_REVERSE) + s->sorting = s->sorting ^ GIT_SORT_REVERSE; + else + s->sorting = sort_mode | (s->sorting & GIT_SORT_REVERSE); - s->walker->sort(s->sorting); + s->walker->sort(s->sorting); } void push_rev(log_state * s, git::Commit const & commit, int hide) { - hide = s->hide ^ hide; - - if (!s->walker) { - s->walker.reset(new git::RevWalker(s->repo->rev_walker())); - s->walker->sort(s->sorting); - } - - if (!commit) - s->walker->push_head(); - else if (hide) - s->walker->hide(commit.id()); - else - s->walker->push(commit.id()); + hide = s->hide ^ hide; + + if (!s->walker) { + s->walker.reset(new git::RevWalker(s->repo->rev_walker())); + s->walker->sort(s->sorting); + } + + if (!commit) + s->walker->push_head(); + else if (hide) + s->walker->hide(commit.id()); + else + s->walker->push(commit.id()); } void push_rev(struct log_state *s, git::Object const & obj, int hide) { - hide = s->hide ^ hide; - - if (!s->walker) { - s->walker.reset(new git::RevWalker(s->repo->rev_walker())); - s->walker->sort(s->sorting); - } - - if (!obj) - s->walker->push_head(); - else if (hide) - s->walker->hide(obj.id()); - else - s->walker->push(obj.id()); + hide = s->hide ^ hide; + + if (!s->walker) { + s->walker.reset(new git::RevWalker(s->repo->rev_walker())); + s->walker->sort(s->sorting); + } + + if (!obj) + s->walker->push_head(); + else if (hide) + s->walker->hide(obj.id()); + else + s->walker->push(obj.id()); } void add_revision(struct log_state *s, const char *revstr) { - int hide = 0; - - if (!s->repo) { - s->repo = boost::in_place(s->repodir); - } - - if (!revstr) { - push_rev(s, git::Commit(nullptr), hide); - return; - } - - if (*revstr == '^') - hide = !hide; - - git::Revspec revs = (*revstr == '^') - ? s->repo->revparse_single(revstr + 1) - : s->repo->revparse(revstr); - - if (auto obj = revs.single()) - { - push_rev(s, *obj, hide); - } - else - { - git::Revspec::Range const & range = *revs.range(); - push_rev(s, range.to, hide); - - if ((revs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) { - git_oid base = s->repo->merge_base(range); - push_rev(s, s->repo->commit_lookup(&base), hide); - } - - push_rev(s, range.from, !hide); - } + int hide = 0; + + if (!s->repo) { + s->repo = boost::in_place(s->repodir); + } + + if (!revstr) { + push_rev(s, git::Commit(), hide); + return; + } + + if (*revstr == '^') + hide = !hide; + + git::Revspec revs = (*revstr == '^') + ? s->repo->revparse_single(revstr + 1) + : s->repo->revparse(revstr); + + if (auto obj = revs.single()) + { + push_rev(s, *obj, hide); + } + else + { + git::Revspec::Range const & range = *revs.range(); + push_rev(s, range.to, hide); + + if ((revs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) { + git_oid base = s->repo->merge_base(range); + push_rev(s, s->repo->commit_lookup(&base), hide); + } + + push_rev(s, range.from, !hide); + } } static void print_time(const git_time *intime, const char *prefix) { - char sign, out[32]; - struct tm intm; - int offset, hours, minutes; - time_t t; + char sign, out[32]; + struct tm intm; + int offset, hours, minutes; + time_t t; - offset = intime->offset; - if (offset < 0) { - sign = '-'; - offset = -offset; - } else { - sign = '+'; - } + offset = intime->offset; + if (offset < 0) { + sign = '-'; + offset = -offset; + } else { + sign = '+'; + } - hours = offset / 60; - minutes = offset % 60; + hours = offset / 60; + minutes = offset % 60; - t = (time_t)intime->time + (intime->offset * 60); + t = (time_t)intime->time + (intime->offset * 60); - gmtime_r(&t, &intm); - strftime(out, sizeof(out), "%a %b %e %T %Y", &intm); + gmtime_r(&t, &intm); + strftime(out, sizeof(out), "%a %b %e %T %Y", &intm); - printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); + printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); } static void print_commit(git::Commit const & commit) { - int i, count; - const git_signature *sig; - const char *scan, *eol; - - printf("commit %s\n", git::id_to_str(commit.id()).c_str()); - - if ((count = (int)commit.parents_num()) > 1) { - printf("Merge:"); - for (i = 0; i < count; ++i) { - printf(" %s", git::id_to_str(commit.parent_id(i), 7).c_str()); - } - printf("\n"); - } - - if ((sig = commit.author()) != NULL) { - printf("Author: %s <%s>\n", sig->name, sig->email); - print_time(&sig->when, "Date: "); - } - printf("\n"); - - for (scan = commit.message(); scan && *scan; ) { - for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */; - - printf(" %.*s\n", (int)(eol - scan), scan); - scan = *eol ? eol + 1 : NULL; - } - printf("\n"); + int i, count; + const git_signature *sig; + const char *scan, *eol; + + printf("commit %s\n", git::id_to_str(commit.id()).c_str()); + + if ((count = (int)commit.parents_num()) > 1) { + printf("Merge:"); + for (i = 0; i < count; ++i) { + printf(" %s", git::id_to_str(commit.parent_id(i), 7).c_str()); + } + printf("\n"); + } + + if ((sig = commit.author()) != NULL) { + printf("Author: %s <%s>\n", sig->name, sig->email); + print_time(&sig->when, "Date: "); + } + printf("\n"); + + for (scan = commit.message(); scan && *scan; ) { + for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */; + + printf(" %.*s\n", (int)(eol - scan), scan); + scan = *eol ? eol + 1 : NULL; + } + printf("\n"); } -int print_diff( - const git_diff_delta *, - const git_diff_range *, - char , - const char *line, - size_t - ) +void print_diff(git_diff_delta const &, git_diff_hunk const &, git_diff_line const & line) { - fputs(line, stdout); - return 0; + fwrite(line.content, 1, line.content_len, stdout); } static int match_int(int *value, const char *arg, int allow_negative) { - char *found; - *value = (int)strtol(arg, &found, 10); - return (found && *found == '\0' && (allow_negative || *value >= 0)); + char *found; + *value = (int)strtol(arg, &found, 10); + return (found && *found == '\0' && (allow_negative || *value >= 0)); } static int match_int_arg( - int *value, const char *arg, const char *pfx, int allow_negative) + int *value, const char *arg, const char *pfx, int allow_negative) { - size_t pfxlen = strlen(pfx); - if (strncmp(arg, pfx, pfxlen) != 0) - return 0; - if (!match_int(value, arg + pfxlen, allow_negative)) - usage("Invalid value after argument", arg); - return 1; + size_t pfxlen = strlen(pfx); + if (strncmp(arg, pfx, pfxlen) != 0) + return 0; + if (!match_int(value, arg + pfxlen, allow_negative)) + usage("Invalid value after argument", arg); + return 1; } static int match_with_parent(git::Commit const & commit, int i, git_diff_options const & opts) { - auto parent = commit.parent(i); - auto c_tree = commit.tree(); - auto p_tree = parent.tree(); - auto diff = git::diff(commit.owner(), p_tree, c_tree, opts); + auto parent = commit.parent(i); + auto c_tree = commit.tree(); + auto p_tree = parent.tree(); + auto diff = git::diff(commit.owner(), p_tree, c_tree, opts); - return diff.deltas_num() > 0; + return diff.deltas_num() > 0; } struct log_options { - int show_diff; - int skip, limit; - int min_parents, max_parents; - git_time_t before; - git_time_t after; - char *author; - char *committer; + int show_diff; + int skip, limit; + int min_parents, max_parents; + git_time_t before; + git_time_t after; + char *author; + char *committer; }; int parse_options ( int argc, char *argv[] - , log_state & s - , log_options & opt - , int count - ) + , log_state & s + , log_options & opt + , int count + ) { - int i = 1; - for (; i < argc; ++i) { - char* a = argv[i]; - - if (a[0] != '-') { - try - { - add_revision(&s, a); - ++count; - } - catch (...) /* try failed revision parse as filename */ - { - break; - } - } else if (!strcmp(a, "--")) { - ++i; - break; - } - else if (!strcmp(a, "--date-order")) - set_sorting(&s, GIT_SORT_TIME); - else if (!strcmp(a, "--topo-order")) - set_sorting(&s, GIT_SORT_TOPOLOGICAL); - else if (!strcmp(a, "--reverse")) - set_sorting(&s, GIT_SORT_REVERSE); - else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) - s.repodir = a + strlen("--git-dir="); - else if (match_int_arg(&opt.skip, a, "--skip=", 0)) - /* found valid --skip */; - else if (match_int_arg(&opt.limit, a, "--max-count=", 0)) - /* found valid --max-count */; - else if (a[1] >= '0' && a[1] <= '9') { - if (!match_int(&opt.limit, a + 1, 0)) - usage("Invalid limit on number of commits", a); - } else if (!strcmp(a, "-n")) { - if (i + 1 == argc || !match_int(&opt.limit, argv[i + 1], 0)) - usage("Argument -n not followed by valid count", argv[i + 1]); - else - ++i; - } - else if (!strcmp(a, "--merges")) - opt.min_parents = 2; - else if (!strcmp(a, "--no-merges")) - opt.max_parents = 1; - else if (!strcmp(a, "--no-min-parents")) - opt.min_parents = 0; - else if (!strcmp(a, "--no-max-parents")) - opt.max_parents = -1; - else if (match_int_arg(&opt.max_parents, a, "--max-parents=", 1)) - /* found valid --max-parents */; - else if (match_int_arg(&opt.min_parents, a, "--min-parents=", 0)) - /* found valid --min_parents */; - else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) - opt.show_diff = 1; - else - usage("Unsupported argument", a); - } - - return i; + int i = 1; + for (; i < argc; ++i) { + char* a = argv[i]; + + if (a[0] != '-') { + try + { + add_revision(&s, a); + ++count; + } + catch (...) /* try failed revision parse as filename */ + { + break; + } + } else if (!strcmp(a, "--")) { + ++i; + break; + } + else if (!strcmp(a, "--date-order")) + set_sorting(&s, GIT_SORT_TIME); + else if (!strcmp(a, "--topo-order")) + set_sorting(&s, GIT_SORT_TOPOLOGICAL); + else if (!strcmp(a, "--reverse")) + set_sorting(&s, GIT_SORT_REVERSE); + else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) + s.repodir = a + strlen("--git-dir="); + else if (match_int_arg(&opt.skip, a, "--skip=", 0)) + /* found valid --skip */; + else if (match_int_arg(&opt.limit, a, "--max-count=", 0)) + /* found valid --max-count */; + else if (a[1] >= '0' && a[1] <= '9') { + if (!match_int(&opt.limit, a + 1, 0)) + usage("Invalid limit on number of commits", a); + } else if (!strcmp(a, "-n")) { + if (i + 1 == argc || !match_int(&opt.limit, argv[i + 1], 0)) + usage("Argument -n not followed by valid count", argv[i + 1]); + else + ++i; + } + else if (!strcmp(a, "--merges")) + opt.min_parents = 2; + else if (!strcmp(a, "--no-merges")) + opt.max_parents = 1; + else if (!strcmp(a, "--no-min-parents")) + opt.min_parents = 0; + else if (!strcmp(a, "--no-max-parents")) + opt.max_parents = -1; + else if (match_int_arg(&opt.max_parents, a, "--max-parents=", 1)) + /* found valid --max-parents */; + else if (match_int_arg(&opt.min_parents, a, "--min-parents=", 0)) + /* found valid --min_parents */; + else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) + opt.show_diff = 1; + else + usage("Unsupported argument", a); + } + + return i; } int main(int argc, char *argv[]) { - log_options opt; - memset(&opt, 0, sizeof(opt)); - opt.max_parents = -1; - opt.limit = -1; - - log_state s; - - int count = 0; - int parsed_options_num = parse_options(argc, argv, s, opt, count); - - git::ThreadsInitializer threads_initializer; - - if (!count) - add_revision(&s, NULL); - - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - diffopts.pathspec.strings = &argv[parsed_options_num]; - diffopts.pathspec.count = argc - parsed_options_num; - git::Pathspec ps(diffopts.pathspec); - - count = 0; - int printed = 0; - - while (auto commit = s.walker->next(*s.repo)) - { - int parents = commit.parents_num(); - if (parents < opt.min_parents) - continue; - if (opt.max_parents > 0 && parents > opt.max_parents) - continue; - - if (diffopts.pathspec.count > 0) - { - int unmatched = parents; - - if (parents == 0) - { - if (commit.tree().pathspec_match(GIT_PATHSPEC_NO_MATCH_ERROR, ps) != 0) - unmatched = 1; - } - else if (parents == 1) + log_options opt; + memset(&opt, 0, sizeof(opt)); + opt.max_parents = -1; + opt.limit = -1; + + log_state s; + + int count = 0; + int parsed_options_num = parse_options(argc, argv, s, opt, count); + + git::Initializer threads_initializer; + + if (!count) + add_revision(&s, NULL); + + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + diffopts.pathspec.strings = &argv[parsed_options_num]; + diffopts.pathspec.count = argc - parsed_options_num; + git::Pathspec ps(diffopts.pathspec); + + count = 0; + int printed = 0; + + while (git::Commit commit = s.walker->next(*s.repo)) + { + int parents = commit.parents_num(); + if (parents < opt.min_parents) + continue; + if (opt.max_parents > 0 && parents > opt.max_parents) + continue; + + if (diffopts.pathspec.count > 0) + { + int unmatched = parents; + + if (parents == 0) + { + if (commit.tree().pathspec_match(GIT_PATHSPEC_NO_MATCH_ERROR, ps) != 0) + unmatched = 1; + } + else if (parents == 1) + { + unmatched = match_with_parent(commit, 0, diffopts) ? 0 : 1; + } + else + { + for (int i = 0; i < parents; ++i) { - unmatched = match_with_parent(commit, 0, diffopts) ? 0 : 1; - } - else - { - for (int i = 0; i < parents; ++i) - { - if (match_with_parent(commit, i, diffopts)) - unmatched--; - } - } - - if (unmatched > 0) - continue; - } - - if (count++ < opt.skip) - continue; - if (opt.limit != -1 && printed++ >= opt.limit) { - break; - } - - print_commit(commit); - - if (opt.show_diff) - { - if (parents > 1) - continue; - git::Tree b = commit.tree(); - git::Tree a; - if (parents == 1) - { - a = commit.parent(0).tree(); - } - - git::diff(commit.owner(), a, b, diffopts).print_patch(print_diff); - } - } - - return 0; + if (match_with_parent(commit, i, diffopts)) + unmatched--; + } + } + + if (unmatched > 0) + continue; + } + + if (count++ < opt.skip) + continue; + if (opt.limit != -1 && printed++ >= opt.limit) { + break; + } + + print_commit(commit); + + if (opt.show_diff) + { + if (parents > 1) + continue; + git::Tree b = commit.tree(); + git::Tree a; + if (parents == 1) + { + a = commit.parent(0).tree(); + } + + git::diff(commit.owner(), a, b, diffopts).print(git::Diff::format::patch, print_diff); + } + } + + return 0; } diff --git a/examples/rev-parse.cpp b/examples/rev-parse.cpp index f3306d4..3c47e16 100644 --- a/examples/rev-parse.cpp +++ b/examples/rev-parse.cpp @@ -5,7 +5,7 @@ #include #include -#include "git2cpp/threads_initializer.h" +#include "git2cpp/initializer.h" #include "git2cpp/repo.h" using namespace git; @@ -54,7 +54,7 @@ int main(int argc, char *argv[]) { parse_state ps; - ThreadsInitializer threads_initalizer; + Initializer threads_initalizer; for (int i = 1; i < argc; ++i) { const char * a = argv[i]; diff --git a/examples/showindex.cpp b/examples/showindex.cpp index b259e18..3dd68a8 100644 --- a/examples/showindex.cpp +++ b/examples/showindex.cpp @@ -6,53 +6,53 @@ extern "C" #include } -#include "git2cpp/threads_initializer.h" +#include "git2cpp/initializer.h" #include "git2cpp/repo.h" using namespace git; int main (int argc, char** argv) { - const char * dir = "."; - - ThreadsInitializer threads_initalizer; - - if (argc > 1) - dir = argv[1]; - if (!dir || argc > 2) { - fprintf(stderr, "usage: showindex []\n"); - return 1; - } - - size_t dirlen = strlen(dir); - Index index = (dirlen > 5 && strcmp(dir + dirlen - 5, "index") == 0) - ? Index(dir) - : Repository(dir).index(); - - size_t ecount = index.entrycount(); - if (!ecount) - printf("Empty index\n"); - - for (size_t i = 0; i < ecount; ++i) - { - auto e = index[i]; - - char out[41]; - out[40] = '\0'; - git_oid_fmt(out, &e->oid); - - printf("File Path: %s\n", e->path); - printf(" Stage: %d\n", git_index_entry_stage(e)); - printf(" Blob SHA: %s\n", out); - printf("File Mode: %07o\n", e->mode); - printf("File Size: %d bytes\n", (int)e->file_size); - printf("Dev/Inode: %d/%d\n", (int)e->dev, (int)e->ino); - printf(" UID/GID: %d/%d\n", (int)e->uid, (int)e->gid); - printf(" ctime: %d\n", (int)e->ctime.seconds); - printf(" mtime: %d\n", (int)e->mtime.seconds); - printf("\n"); - } - - return 0; + const char * dir = "."; + + Initializer threads_initalizer; + + if (argc > 1) + dir = argv[1]; + if (!dir || argc > 2) { + fprintf(stderr, "usage: showindex []\n"); + return 1; + } + + size_t dirlen = strlen(dir); + Index index = (dirlen > 5 && strcmp(dir + dirlen - 5, "index") == 0) + ? Index(dir) + : Repository(dir).index(); + + size_t ecount = index.entrycount(); + if (!ecount) + printf("Empty index\n"); + + for (size_t i = 0; i < ecount; ++i) + { + auto e = index[i]; + + char out[41]; + out[40] = '\0'; + git_oid_fmt(out, &e->id); + + printf("File Path: %s\n", e->path); + printf(" Stage: %d\n", git_index_entry_stage(e)); + printf(" Blob SHA: %s\n", out); + printf("File Mode: %07o\n", e->mode); + printf("File Size: %d bytes\n", (int)e->file_size); + printf("Dev/Inode: %d/%d\n", (int)e->dev, (int)e->ino); + printf(" UID/GID: %d/%d\n", (int)e->uid, (int)e->gid); + printf(" ctime: %d\n", (int)e->ctime.seconds); + printf(" mtime: %d\n", (int)e->mtime.seconds); + printf("\n"); + } + + return 0; } diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 47e9375..3498c37 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -8,47 +8,54 @@ struct git_repository; namespace git { - struct Commit - { - git_commit const * ptr() const { return commit_; } + struct Repository; - size_t parents_num() const; - Commit parent(size_t i) const; - git_oid const * parent_id(size_t i) const; + struct Commit + { + git_commit const * ptr() const { return commit_; } - Tree tree() const; + size_t parents_num() const; + Commit parent(size_t i) const; + git_oid const * parent_id(size_t i) const; - git_repository * owner() const; + Tree tree() const; - explicit operator bool () const { return commit_; } + Repository const & owner() const { return *repo_; } - git_oid const * id() const; + explicit operator bool () const { return commit_; } - git_signature const * author() const; - git_signature const * commiter() const; + git_oid const * id() const; - const char * message() const; - git_time_t time() const; + git_signature const * author() const; + git_signature const * commiter() const; - Commit(git_oid const * oid, git_repository * repo); + const char * message() const; + git_time_t time() const; - explicit Commit(git_commit * commit = nullptr) - : commit_(commit) - {} + Commit(git_oid const * oid, Repository const & repo); - Commit(Commit && other) - : commit_(other.commit_) - { - other.commit_ = nullptr; - } + Commit(git_commit * commit, Repository const & repo) + : commit_(commit) + , repo_(&repo) + {} - Commit (Commit const &) = delete; - Commit& operator = (Commit const &) = delete; + Commit() {} - ~Commit(); + Commit(Commit && other) + : commit_(other.commit_) + , repo_(other.repo_) + { + other.commit_ = nullptr; + } - private: - git_commit * commit_; - }; + Commit (Commit const &) = delete; + Commit& operator = (Commit const &) = delete; + + ~Commit(); + + private: + git_commit * commit_ = nullptr; + Repository const * repo_ = nullptr; + }; } diff --git a/include/git2cpp/diff.h b/include/git2cpp/diff.h new file mode 100644 index 0000000..f8cdd82 --- /dev/null +++ b/include/git2cpp/diff.h @@ -0,0 +1,61 @@ +#pragma once + +#include + +extern "C" +{ +#include +} + +namespace git +{ + struct Repository; + + struct Diff + { + size_t deltas_num() const; + + void find_similar(git_diff_find_options & findopts) + { + git_diff_find_similar(diff_, &findopts); + } + + Diff& merge(Diff const & other); + + enum class format + { + patch, patch_header, raw, name_only, name_status + }; + + typedef + std::function + print_callback_t; + + void print(format, print_callback_t print_callback) const; + + explicit Diff(git_diff * diff) + : diff_(diff) + {} + + ~Diff() { git_diff_free(diff_); } + + Diff (Diff const &) = delete; + Diff& operator = (Diff const &) = delete; + + Diff(Diff && other) + : diff_(other.diff_) + { + other.diff_ = nullptr; + } + + private: + git_diff * diff_; + }; + + struct Tree; + + Diff diff (Repository const &, Tree & a, Tree & b, git_diff_options const &); + Diff diff_to_index (Repository const &, Tree &, git_diff_options const &); + Diff diff_index_to_workdir (Repository const &, git_diff_options const &); +} + diff --git a/include/git2cpp/diff_list.h b/include/git2cpp/diff_list.h deleted file mode 100644 index c4ca783..0000000 --- a/include/git2cpp/diff_list.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include - -extern "C" -{ -#include -} - -namespace git -{ - struct DiffList - { - size_t deltas_num() const; - - typedef std::function data_callback_t; - - void print_patch (data_callback_t cb) const; - void print_compact (data_callback_t cb) const; - void print_raw (data_callback_t cb) const; - - void find_similar(git_diff_find_options & findopts) - { - git_diff_find_similar(diff_list_, &findopts); - } - - DiffList& merge(DiffList const & other); - - explicit DiffList(git_diff_list * diff_list) - : diff_list_(diff_list) - {} - - ~DiffList() { git_diff_list_free(diff_list_); } - - DiffList (DiffList const &) = delete; - DiffList& operator = (DiffList const &) = delete; - - DiffList(DiffList && other) - : diff_list_(other.diff_list_) - { - other.diff_list_ = nullptr; - } - - private: - git_diff_list * diff_list_; - }; - - struct Tree; - - DiffList diff ( git_repository * repo - , Tree & a, Tree & b - , git_diff_options const & opts - ); - DiffList diff_to_index ( git_repository * repo - , Tree & - , git_diff_options const & opts - ); - - DiffList diff_index_to_workdir(git_repository * repo, git_diff_options const & opts); -} - diff --git a/include/git2cpp/initializer.h b/include/git2cpp/initializer.h new file mode 100644 index 0000000..2d83b02 --- /dev/null +++ b/include/git2cpp/initializer.h @@ -0,0 +1,13 @@ +#pragma once + +namespace git +{ + struct Initializer + { + Initializer(); + ~Initializer(); + + Initializer (Initializer const &) = delete; + Initializer& operator = (Initializer const &) = delete; + }; +} diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index f928733..88c5dc9 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -12,31 +12,36 @@ struct git_oid; namespace git { - struct Object - { - explicit Object(git_object * obj); - ~Object(); + struct Repository; - explicit operator bool() const { return obj_; } + struct Object + { + Object() {} - git_otype type() const; - git_oid const * id() const; + Object(git_object * obj, Repository const &); + ~Object(); - git_blob const * as_blob() const; - git_commit const * as_commit() const; - git_tree const * as_tree() const; - git_tag const * as_tag() const; + explicit operator bool() const { return obj_; } - Commit to_commit(); - Tree to_tree(); + git_otype type() const; + git_oid const * id() const; - Object (Object const &) = delete; - Object& operator = (Object const &) = delete; + git_blob const * as_blob() const; + git_commit const * as_commit() const; + git_tree const * as_tree() const; + git_tag const * as_tag() const; - Object(Object && other); + Commit to_commit(); + Tree to_tree(); - private: - git_object * obj_; - }; + Object (Object const &) = delete; + Object& operator = (Object const &) = delete; + + Object(Object && other); + + private: + git_object * obj_ = nullptr; + Repository const * repo_ = nullptr; + }; } diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 70516fd..a71ed2b 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -25,9 +25,14 @@ namespace git struct non_existing_branch_error {}; struct missing_head_error {}; + enum class branch_type + { + LOCAL, REMOTE, ALL + }; + struct Repository { - git_repository * ptr() { return repo_; } + git_repository * ptr() const { return repo_; } Commit commit_lookup(git_oid const * oid) const; Tree tree_lookup (git_oid const * oid) const; @@ -54,7 +59,7 @@ namespace git StrArray reference_list() const; - std::vector branches() const; + std::vector branches(branch_type) const; bool is_bare() const; diff --git a/include/git2cpp/revspec.h b/include/git2cpp/revspec.h index 4245130..245341b 100644 --- a/include/git2cpp/revspec.h +++ b/include/git2cpp/revspec.h @@ -9,35 +9,36 @@ extern "C" namespace git { - struct Revspec - { - struct Range - { - Object from, to; + struct Repository; - explicit Range(git_object * single) - : from (single) - , to (nullptr) - {} + struct Revspec + { + struct Range + { + Object from, to; - explicit Range(git_revspec const & revspec) - : from (revspec.from) - , to (revspec.to) - {} - }; + Range(git_object * single, Repository const & repo) + : from(single, repo) + {} - Object const * single() const; - Range const * range() const; + explicit Range(git_revspec const & revspec, Repository const & repo) + : from (revspec.from, repo) + , to (revspec.to, repo) + {} + }; - Object * single(); + Object const * single() const; + Range const * range() const; - unsigned int flags() const; + Object * single(); - Revspec(git_object * single); - Revspec(git_revspec const &); + unsigned int flags() const; - private: - unsigned int flags_ = 0; - Range revspec_; - }; + Revspec(git_object * single, Repository const &); + Revspec(git_revspec const &, Repository const &); + + private: + unsigned int flags_ = 0; + Range revspec_; + }; } diff --git a/include/git2cpp/tag.h b/include/git2cpp/tag.h index 7464a8e..0fd8d85 100644 --- a/include/git2cpp/tag.h +++ b/include/git2cpp/tag.h @@ -6,22 +6,25 @@ struct git_tag; namespace git { - struct Tag - { - Tag(git_oid const * oid, git_repository * repo); - ~Tag(); + struct Repository; - Tag& operator = (Tag const &) = delete; - Tag (Tag const &) = delete; + struct Tag + { + Tag(git_oid const * oid, Repository const &); + ~Tag(); - Tag(Tag &&); + Tag& operator = (Tag const &) = delete; + Tag (Tag const &) = delete; - Object target() const; - git_otype target_type() const; - const char * name() const; - const char * message() const; + Tag(Tag &&); - private: - git_tag * tag_; - }; + Object target() const; + git_otype target_type() const; + const char * name() const; + const char * message() const; + + private: + git_tag * tag_; + Repository const & repo_; + }; } diff --git a/include/git2cpp/threads_initializer.h b/include/git2cpp/threads_initializer.h deleted file mode 100644 index b97c4e1..0000000 --- a/include/git2cpp/threads_initializer.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -namespace git -{ - struct ThreadsInitializer - { - ThreadsInitializer(); - ~ThreadsInitializer(); - - ThreadsInitializer (ThreadsInitializer const &) = delete; - ThreadsInitializer& operator = (ThreadsInitializer const &) = delete; - }; -} diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index 3c801f7..f220991 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -1,6 +1,5 @@ #pragma once -#include "diff_list.h" #include "pathspec.h" namespace git diff --git a/src/commit.cpp b/src/commit.cpp index 0ef8a11..04c0fb5 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -1,4 +1,5 @@ #include "git2cpp/commit.h" +#include "git2cpp/repo.h" extern "C" { @@ -7,67 +8,63 @@ extern "C" namespace git { - Commit Commit::parent(size_t i) const - { - git_commit * parent; - if (git_commit_parent(&parent, commit_, i)); - throw commit_parent_error(id()); - return Commit(parent); - } + Commit Commit::parent(size_t i) const + { + git_commit * parent; + if (git_commit_parent(&parent, commit_, i)); + throw commit_parent_error(id()); + return Commit(parent, *repo_); + } - Tree Commit::tree() const - { - git_tree * tree; - if (git_commit_tree(&tree, commit_)) - throw commit_tree_error(id()); - return Tree(tree); - } + Tree Commit::tree() const + { + git_tree * tree; + if (git_commit_tree(&tree, commit_)) + throw commit_tree_error(id()); + return Tree(tree); + } - git_repository * Commit::owner() const - { - return git_commit_owner(commit_); - } + size_t Commit::parents_num() const + { + return git_commit_parentcount(commit_); + } - size_t Commit::parents_num() const - { - return git_commit_parentcount(commit_); - } + git_oid const * Commit::id() const + { + return git_commit_id(commit_); + } - git_oid const * Commit::id() const - { - return git_commit_id(commit_); - } + git_oid const * Commit::parent_id(size_t i) const + { + return git_commit_parent_id(commit_, i); + } - git_oid const * Commit::parent_id(size_t i) const - { - return git_commit_parent_id(commit_, i); - } + git_signature const * Commit::author() const + { + return git_commit_author(commit_); + } - git_signature const * Commit::author() const - { - return git_commit_author(commit_); - } + git_signature const * Commit::commiter() const + { + return git_commit_committer(commit_); + } - git_signature const * Commit::commiter() const - { - return git_commit_committer(commit_); - } + const char * Commit::message() const + { + return git_commit_message(commit_); + } - const char * Commit::message() const - { - return git_commit_message(commit_); - } + git_time_t Commit::time() const + { + return git_commit_time(commit_); + } - git_time_t Commit::time() const - { - return git_commit_time(commit_); - } + Commit::Commit(git_oid const * oid, Repository const & repo) + : repo_(&repo) + { + if (git_commit_lookup(&commit_, repo.ptr(), oid)) + throw commit_lookup_error(oid); + } - Commit::Commit(git_oid const * oid, git_repository * repo) - { - if (git_commit_lookup(&commit_, repo, oid)) - throw commit_lookup_error(oid); - } - - Commit::~Commit() { git_commit_free(commit_); } + Commit::~Commit() { git_commit_free(commit_); } } diff --git a/src/diff.cpp b/src/diff.cpp new file mode 100644 index 0000000..c7658fd --- /dev/null +++ b/src/diff.cpp @@ -0,0 +1,74 @@ +#include + +#include "git2cpp/diff.h" +#include "git2cpp/tree.h" +#include "git2cpp/repo.h" + +namespace git +{ + Diff diff(Repository const & repo, Tree & a, Tree & b, git_diff_options const & opts) + { + git_diff * diff; + auto op_res = git_diff_tree_to_tree(&diff, repo.ptr(), a.ptr(), b.ptr(), &opts); + assert(op_res == 0); + return Diff(diff); + } + + Diff diff_to_index(Repository const & repo, Tree & t, git_diff_options const & opts) + { + git_diff * diff; + auto op_res = git_diff_tree_to_index(&diff, repo.ptr(), t.ptr(), nullptr, &opts); + assert(op_res == 0); + return Diff(diff); + } + + Diff diff_index_to_workdir(Repository const & repo, git_diff_options const & opts) + { + git_diff * diff; + auto op_res = git_diff_index_to_workdir(&diff, repo.ptr(), nullptr, &opts); + assert(op_res == 0); + return Diff(diff); + } + + namespace + { + int apply_callback ( git_diff_delta const * delta + , git_diff_hunk const * hunk + , git_diff_line const * line + , void * payload ) + { + auto cb = reinterpret_cast(payload); + (*cb)(*delta, *hunk, *line); + return 0; + } + + git_diff_format_t convert(Diff::format f) + { + switch (f) + { + case Diff::format::name_only: return GIT_DIFF_FORMAT_NAME_ONLY; + case Diff::format::name_status: return GIT_DIFF_FORMAT_NAME_STATUS; + case Diff::format::patch: return GIT_DIFF_FORMAT_PATCH; + case Diff::format::patch_header: return GIT_DIFF_FORMAT_PATCH_HEADER; + case Diff::format::raw: return GIT_DIFF_FORMAT_RAW; + } + } + } + + Diff& Diff::merge(Diff const & other) + { + git_diff_merge(diff_, other.diff_); + return *this; + } + + size_t Diff::deltas_num() const + { + return git_diff_num_deltas(diff_); + } + + void Diff::print(format f, print_callback_t print_callback) const + { + git_diff_print(diff_, convert(f), &apply_callback, &print_callback); + } +} + diff --git a/src/diff_list.cpp b/src/diff_list.cpp deleted file mode 100644 index 9d608b3..0000000 --- a/src/diff_list.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "git2cpp/diff_list.h" -#include "git2cpp/tree.h" - -namespace git -{ - DiffList diff (git_repository * repo - , Tree & a, Tree & b - , git_diff_options const & opts - ) - { - git_diff_list * diff_list; - auto op_res = git_diff_tree_to_tree(&diff_list, repo, a.ptr(), b.ptr(), &opts); - assert(op_res == 0); - return DiffList(diff_list); - } - - DiffList diff_to_index ( git_repository * repo - , Tree & t - , git_diff_options const & opts - ) - { - git_diff_list * diff_list; - auto op_res = git_diff_tree_to_index(&diff_list, repo, t.ptr(), nullptr, &opts); - assert(op_res == 0); - return DiffList(diff_list); - } - - DiffList diff_index_to_workdir(git_repository * repo, git_diff_options const & opts) - { - git_diff_list * diff_list; - auto op_res = git_diff_index_to_workdir(&diff_list, repo, nullptr, &opts); - assert(op_res == 0); - return DiffList(diff_list); - } - - namespace - { - int apply_callback ( git_diff_delta const * delta - , git_diff_range const * range - , char usage - , const char * line - , size_t line_len - , void * payload ) - { - auto cb = reinterpret_cast(payload); - return (*cb)(delta, range, usage, line, line_len); - } - } - - void DiffList::print_patch(data_callback_t cb) const - { - git_diff_print_patch(diff_list_, &apply_callback, &cb); - } - - void DiffList::print_compact(data_callback_t cb) const - { - git_diff_print_compact(diff_list_, &apply_callback, &cb); - } - - void DiffList::print_raw(data_callback_t cb) const - { - git_diff_print_raw(diff_list_, &apply_callback, &cb); - } - - DiffList& DiffList::merge(DiffList const & other) - { - git_diff_merge(diff_list_, other.diff_list_); - return *this; - } - - size_t DiffList::deltas_num() const - { - return git_diff_num_deltas(diff_list_); - } -} - diff --git a/src/index.cpp b/src/index.cpp index c31dae9..9ce5335 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -21,7 +21,7 @@ namespace git { if (git_index_open(&index_, dir)) throw index_open_error(); - git_index_read(index_); + git_index_read(index_, true); } Index::~Index() diff --git a/src/initializer.cpp b/src/initializer.cpp new file mode 100644 index 0000000..4e18894 --- /dev/null +++ b/src/initializer.cpp @@ -0,0 +1,20 @@ +#include "git2cpp/initializer.h" + +extern "C" +{ +#include +} + +namespace git +{ + Initializer::Initializer() + { + git_libgit2_init(); + } + + Initializer::~Initializer() + { + git_libgit2_shutdown(); + } +} + diff --git a/src/object.cpp b/src/object.cpp index c30bf79..cabe63e 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -9,8 +9,9 @@ extern "C" namespace git { - Object::Object(git_object * obj) + Object::Object(git_object * obj, Repository const & repo) : obj_(obj) + , repo_(&repo) {} Object::~Object() @@ -20,6 +21,7 @@ namespace git Object::Object(Object && other) : obj_(other.obj_) + , repo_(other.repo_) { other.obj_ = nullptr; } @@ -59,7 +61,7 @@ namespace git Commit Object::to_commit() { assert(type() == GIT_OBJ_COMMIT); - Commit res(reinterpret_cast(obj_)); + Commit res(reinterpret_cast(obj_), *repo_); obj_ = nullptr; return res; } diff --git a/src/repo.cpp b/src/repo.cpp index bd76b71..6f20b64 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -8,6 +8,8 @@ extern "C" #include } +#include + #include "git2cpp/repo.h" #include "git2cpp/error.h" @@ -59,7 +61,7 @@ namespace git Commit Repository::commit_lookup(git_oid const * oid) const { - return Commit(oid, repo_); + return Commit(oid, *this); } Tree Repository::tree_lookup(git_oid const * oid) const @@ -69,7 +71,7 @@ namespace git Tag Repository::tag_lookup(git_oid const * oid) const { - return Tag(oid, repo_); + return Tag(oid, *this); } Blob Repository::blob_lookup(git_oid const * oid) const @@ -82,7 +84,7 @@ namespace git git_revspec revspec; if (git_revparse(&revspec, repo_, spec)) throw revparse_error(spec); - return Revspec(revspec); + return Revspec(revspec, *this); } Revspec Repository::revparse_single(const char * spec) const @@ -90,7 +92,7 @@ namespace git git_object * obj; if (git_revparse_single(&obj, repo_, spec) < 0) throw revparse_error(spec); - return Revspec(obj); + return Revspec(obj, *this); } Index Repository::index() const @@ -119,14 +121,62 @@ namespace git return res; } - std::vector Repository::branches() const + struct branch_iterator + { + branch_iterator(Repository const & repo, branch_type type) + : type_(convert(type)) + { + git_branch_iterator_new(&base_, repo.ptr(), type_); + ++(*this); + } + + ~branch_iterator() + { + git_branch_iterator_free(base_); + } + + explicit operator bool () const { return ref_.is_initialized(); } + + void operator ++ () + { + git_branch_t type; + git_reference * ref; + if (git_branch_next(&ref, &type, base_) == 0) + { + assert(type == type_); + ref_ = boost::in_place(ref); + } + } + + Reference const * operator -> () const + { + return ref_.get_ptr(); + } + + private: + git_branch_t convert(branch_type t) const + { + switch (t) + { + case branch_type::LOCAL : return GIT_BRANCH_LOCAL; + case branch_type::REMOTE: return GIT_BRANCH_REMOTE; + case branch_type::ALL: return GIT_BRANCH_REMOTE; + default: + throw std::logic_error("invalid branch type"); + } + } + + private: + git_branch_t type_; + git_branch_iterator * base_; + boost::optional ref_; + }; + + std::vector Repository::branches(branch_type type) const { std::vector res; - git_branch_foreach ( repo_ - , GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE - , write_branch_name - , &res - ); + for (branch_iterator it(*this, type); it; ++it) + it->name(); return res; } @@ -232,7 +282,7 @@ namespace git { git_object * obj; git_tree_entry_to_object(&obj, repo_, entry); - return Object(obj); + return Object(obj, *this); } Object revparse_single(Repository const & repo, const char * spec) diff --git a/src/revspec.cpp b/src/revspec.cpp index 15b0808..f93f564 100644 --- a/src/revspec.cpp +++ b/src/revspec.cpp @@ -2,16 +2,16 @@ namespace git { - Revspec::Revspec(git_object * single) + Revspec::Revspec(git_object * single, Repository const & repo) : flags_(GIT_REVPARSE_SINGLE) - , revspec_(single) + , revspec_(single, repo) {} - Revspec::Revspec(git_revspec const & revspec) + Revspec::Revspec(git_revspec const & revspec, Repository const & repo) : flags_(revspec.flags) , revspec_((revspec.flags & GIT_REVPARSE_SINGLE) - ? Range(revspec.from) - : Range(revspec)) + ? Range(revspec.from, repo) + : Range(revspec, repo)) {} Object * Revspec::single() diff --git a/src/tag.cpp b/src/tag.cpp index 3e6b0f5..793bc36 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -2,12 +2,14 @@ #include "git2cpp/tag.h" #include "git2cpp/error.h" +#include "git2cpp/repo.h" namespace git { - Tag::Tag(git_oid const * oid, git_repository * repo) + Tag::Tag(git_oid const * oid, Repository const & repo) + : repo_(repo) { - if (git_tag_lookup(&tag_, repo, oid)) + if (git_tag_lookup(&tag_, repo.ptr(), oid)) throw tag_lookup_error(oid); } @@ -20,7 +22,7 @@ namespace git { git_object * obj; git_tag_target(&obj, tag_); - return Object(obj); + return Object(obj, repo_); } git_otype Tag::target_type() const diff --git a/src/threads_initializer.cpp b/src/threads_initializer.cpp deleted file mode 100644 index a670b0d..0000000 --- a/src/threads_initializer.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "git2cpp/threads_initializer.h" - -extern "C" -{ -#include -} - -namespace git -{ - ThreadsInitializer::ThreadsInitializer() - { - git_threads_init(); - } - - ThreadsInitializer::~ThreadsInitializer() - { - git_threads_shutdown(); - } -} - From ab30147fe8ae785ec2902db9be11cb4c99da05c9 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 29 Mar 2015 17:56:57 +0300 Subject: [PATCH 002/171] typo fix --- src/commit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commit.cpp b/src/commit.cpp index 04c0fb5..8e06e8d 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -11,8 +11,8 @@ namespace git Commit Commit::parent(size_t i) const { git_commit * parent; - if (git_commit_parent(&parent, commit_, i)); - throw commit_parent_error(id()); + if (git_commit_parent(&parent, commit_, i)) + throw commit_parent_error(id()); return Commit(parent, *repo_); } From 7a5e3585027240161f002df6a2eb9c81d0acddce Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 29 Mar 2015 17:57:18 +0300 Subject: [PATCH 003/171] + commit graph generator (dot format) --- CMakeLists.txt | 1 + examples/commit-graph-generator.cpp | 76 +++++ examples/general.cpp | 28 +- examples/init.cpp | 2 +- examples/log.cpp | 20 +- examples/rev-list.cpp | 13 +- examples/rev-parse.cpp | 2 +- include/git2cpp/blob.h | 2 +- include/git2cpp/commit.h | 13 +- include/git2cpp/error.h | 489 ++++++++++------------------ include/git2cpp/id_to_str.h | 4 +- include/git2cpp/initializer.h | 2 + include/git2cpp/object.h | 2 +- include/git2cpp/odb.h | 2 +- include/git2cpp/reference.h | 2 +- include/git2cpp/repo.h | 8 +- include/git2cpp/revwalker.h | 72 ++-- include/git2cpp/tag.h | 2 +- include/git2cpp/tree.h | 2 +- src/blob.cpp | 4 +- src/commit.cpp | 27 +- src/id_to_str.cpp | 6 +- src/object.cpp | 4 +- src/odb.cpp | 4 +- src/reference.cpp | 4 +- src/repo.cpp | 31 +- src/revwalker.cpp | 54 ++- src/tag.cpp | 4 +- src/tree.cpp | 4 +- 29 files changed, 446 insertions(+), 438 deletions(-) create mode 100644 examples/commit-graph-generator.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 93bbbe8..4db6315 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ set(examples init rev-parse general + commit-graph-generator ) foreach (example ${examples}) diff --git a/examples/commit-graph-generator.cpp b/examples/commit-graph-generator.cpp new file mode 100644 index 0000000..db4ae72 --- /dev/null +++ b/examples/commit-graph-generator.cpp @@ -0,0 +1,76 @@ +#include + +#include +#include + +namespace +{ + struct visitor_t + { + void operator() (git::RevWalker & walker) + { + walker.sort(git::RevWalker::sorting::topological); + walker.simplify_first_parent(); + + while (git::Commit commit = walker.next()) + { + output_commit(commit); + + for (size_t i = 0; i != commit.parents_num(); ++i) + { + output_hash(commit.id()) << " -> "; + output_hash(commit.parent_id(i)) << "\n"; + } + + for (size_t i = 1; i < commit.parents_num(); ++i) + { + auto branch_walker = repo_.rev_walker(); + branch_walker.push(commit.parent_id(i)); + branch_walker.hide(commit.merge_base(0, i)); + (*this)(branch_walker); + } + } + } + + visitor_t(git::Repository const & repo, std::ostream & out) + : repo_(repo) + , out_(out) + {} + + private: + std::ostream& output_hash(git_oid const & id) const + { + out_ << "C" << git::id_to_str(id, 6); + return out_; + } + + void output_commit(git::Commit const & commit) const + { + output_hash(commit.id()) << " [label=\"" << commit.summary() << "\"];" << "\n"; + } + + private: + git::Repository const & repo_; + std::ostream & out_; + }; + + void visit(git::Repository const & repo, std::ostream & out) + { + visitor_t visitor(repo, out); + + git::RevWalker walker = repo.rev_walker(); + walker.push_head(); + visitor(walker); + } +} + +int main(int argc, char * argv[]) +{ + auto_git_initializer; + git::Repository repo (argc >= 2 ? argv[1] : "."); + std::ofstream out (argc >= 3 ? argv[2] : "commit-graph.dot"); + + out << "digraph {\n"; + visit(repo, out); + out << "}\n"; +} diff --git a/examples/general.cpp b/examples/general.cpp index 7e14770..a221382 100644 --- a/examples/general.cpp +++ b/examples/general.cpp @@ -89,7 +89,7 @@ int main (int argc, char** argv) printf("\n*Raw to Hex*\n"); // If you have a oid, you can easily get the hex value of the SHA as well. - std::cout << "SHA hex string: " << id_to_str(&oid) << std::endl; + std::cout << "SHA hex string: " << id_to_str(oid) << std::endl; // ### Working with the Object Database @@ -109,7 +109,7 @@ int main (int argc, char** argv) // We can read raw objects directly from the object database if we have // the oid (SHA) of the object. This allows us to access objects without // knowing thier type and inspect the raw bytes unparsed. - OdbObject obj = odb.read(&oid); + OdbObject obj = odb.read(oid); // A raw object only has three properties - the type (commit, blob, tree // or tag), the size of the raw data and the raw, unparsed data itself. @@ -141,7 +141,7 @@ int main (int argc, char** argv) // Now that we've written the object, we can check out what SHA1 was // generated when the object was written to our database. - std::cout << "Written Object: " << id_to_str(&oid) << std::endl; + std::cout << "Written Object: " << id_to_str(oid) << std::endl; } // ### Object Parsing @@ -163,7 +163,7 @@ int main (int argc, char** argv) oid = str_to_id("8496071c1b46c854b31185ea97743be6a8774479"); - Commit commit = repo.commit_lookup(&oid); + Commit commit = repo.commit_lookup(oid); // Each of the properties of the commit object are accessible via methods, // including commonly needed variations, such as `git_commit_time` which @@ -184,7 +184,7 @@ int main (int argc, char** argv) // based on) and merge commits will have two or more. Commits can // technically have any number, though it's rare to have more than two. for (size_t p = 0, parents = commit.parents_num(); p != parents; ++p) - std::cout << "Parent: " << id_to_str(commit.parent(p).id()) << std::endl; + std::cout << "Parent: " << id_to_str(commit.parent_id(p)) << std::endl; } { @@ -211,9 +211,9 @@ int main (int argc, char** argv) // parents. Here we're creating oid objects to create the commit with, // but you can also use git_oid tree_id = str_to_id("f60079018b664e4e79329a7ef9559c8d9e0378d1"); - Tree tree = repo.tree_lookup(&tree_id); + Tree tree = repo.tree_lookup(tree_id); git_oid parent_id = str_to_id("5b5b025afb0b4c913b4c338a42934a3863bf3644"); - Commit parent = repo.commit_lookup(&parent_id); + Commit parent = repo.commit_lookup(parent_id); // Here we actually create the commit object with a single call with all // the values we need to create the commit. The SHA key is written to the @@ -228,7 +228,7 @@ int main (int argc, char** argv) parent); // Now we can take a look at the commit SHA we've generated. - std::cout << "New Commit: " << id_to_str(&commit_id) << std::endl; + std::cout << "New Commit: " << id_to_str(commit_id) << std::endl; } { @@ -244,7 +244,7 @@ int main (int argc, char** argv) // We create an oid for the tag object if we know the SHA and look it up // the same way that we would a commit (or any other object). oid = str_to_id("b25fa35b38051e4ae45d4222e795f9df2e43f1d1"); - Tag tag = repo.tag_lookup(&oid); + Tag tag = repo.tag_lookup(oid); // Now that we have the tag object, we can extract the information it // generally contains: the target (usually a commit object), the type of @@ -274,7 +274,7 @@ int main (int argc, char** argv) try { - Tree tree = repo.tree_lookup(&oid); + Tree tree = repo.tree_lookup(oid); // Getting the count of entries in the tree so you can iterate over them // if you want to. @@ -316,7 +316,7 @@ int main (int argc, char** argv) printf("\n*Blob Parsing*\n"); git_oid oid = str_to_id("1385f264afb75a56a5bec74243be9b367ba4ca08"); - Blob blob = repo.blob_lookup(&oid); + Blob blob = repo.blob_lookup(oid); // You can access a buffer with the raw contents of the blob directly. // Note that this buffer may not be contain ASCII data for certain blobs @@ -351,15 +351,15 @@ int main (int argc, char** argv) // branch1..branch2`, you would push the oid of `branch2` and hide the oid // of `branch1`. RevWalker walk = repo.rev_walker(); - walk.sort(GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE); - walk.push(&oid); + walk.sort(RevWalker::sorting::topological | RevWalker::sorting::reverse); + walk.push(oid); // Now that we have the starting point pushed onto the walker, we start // asking for ancestors. It will return them in the sorting order we asked // for as commit oids. We can then lookup and parse the commited pointed // at by the returned OID; note that this operation is specially fast // since the raw contents of the commit object will be cached in memory - while (auto commit = walk.next(repo)) + while (auto commit = walk.next()) { char const * cmsg = commit.message(); git_signature const * cauth = commit.author(); diff --git a/examples/init.cpp b/examples/init.cpp index 24e627f..700eade 100644 --- a/examples/init.cpp +++ b/examples/init.cpp @@ -190,7 +190,7 @@ static void create_initial_commit(Repository & repo) */ git_oid tree_id = index.write_tree(); - Tree tree = repo.tree_lookup(&tree_id); + Tree tree = repo.tree_lookup(tree_id); /* Ready to create the initial commit * diff --git a/examples/log.cpp b/examples/log.cpp index d1ac6dc..c3c7b0a 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -31,10 +31,10 @@ struct log_state boost::optional repo; std::unique_ptr walker; int hide = 0; - int sorting = GIT_SORT_TIME; + git::RevWalker::sorting sorting = git::RevWalker::sorting::time; }; -static void set_sorting(struct log_state *s, unsigned int sort_mode) +static void set_sorting(struct log_state *s, git::RevWalker::sorting sort_mode) { if (!s->repo) { s->repo = boost::in_place(s->repodir); @@ -43,10 +43,10 @@ static void set_sorting(struct log_state *s, unsigned int sort_mode) if (!s->walker) s->walker.reset(new git::RevWalker(s->repo->rev_walker())); - if (sort_mode == GIT_SORT_REVERSE) - s->sorting = s->sorting ^ GIT_SORT_REVERSE; + if (sort_mode == git::RevWalker::sorting::reverse) + s->sorting = s->sorting ^ git::RevWalker::sorting::reverse; else - s->sorting = sort_mode | (s->sorting & GIT_SORT_REVERSE); + s->sorting = sort_mode | (s->sorting & git::RevWalker::sorting::reverse); s->walker->sort(s->sorting); } @@ -116,7 +116,7 @@ void add_revision(struct log_state *s, const char *revstr) if ((revs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) { git_oid base = s->repo->merge_base(range); - push_rev(s, s->repo->commit_lookup(&base), hide); + push_rev(s, s->repo->commit_lookup(base), hide); } push_rev(s, range.from, !hide); @@ -248,11 +248,11 @@ int parse_options ( int argc, char *argv[] break; } else if (!strcmp(a, "--date-order")) - set_sorting(&s, GIT_SORT_TIME); + set_sorting(&s, git::RevWalker::sorting::time); else if (!strcmp(a, "--topo-order")) - set_sorting(&s, GIT_SORT_TOPOLOGICAL); + set_sorting(&s, git::RevWalker::sorting::topological); else if (!strcmp(a, "--reverse")) - set_sorting(&s, GIT_SORT_REVERSE); + set_sorting(&s, git::RevWalker::sorting::reverse); else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) s.repodir = a + strlen("--git-dir="); else if (match_int_arg(&opt.skip, a, "--skip=", 0)) @@ -314,7 +314,7 @@ int main(int argc, char *argv[]) count = 0; int printed = 0; - while (git::Commit commit = s.walker->next(*s.repo)) + while (git::Commit commit = s.walker->next()) { int parents = commit.parents_num(); if (parents < opt.min_parents) diff --git a/examples/rev-list.cpp b/examples/rev-list.cpp index 8d9a599..0331ec3 100644 --- a/examples/rev-list.cpp +++ b/examples/rev-list.cpp @@ -14,7 +14,7 @@ extern "C" using namespace git; -void push_commit(RevWalker const & walk, const git_oid *oid, int hide) +void push_commit(RevWalker const & walk, git_oid const & oid, int hide) { if (hide) return walk.hide(oid); @@ -44,19 +44,20 @@ void push_range(Repository const & repo, RevWalker const & walk, const char *ran void revwalk_parseopts(Repository const & repo, RevWalker & walk, int nopts, char **opts) { - unsigned int sorting = GIT_SORT_NONE; + typedef RevWalker::sorting sort; + auto sorting = sort::none; int hide = 0; for (int i = 0; i < nopts; i++) { if (!strcmp(opts[i], "--topo-order")) { - sorting = GIT_SORT_TOPOLOGICAL | (sorting & GIT_SORT_REVERSE); + sorting = sort::topological | (sorting & sort::reverse); walk.sort(sorting); } else if (!strcmp(opts[i], "--date-order")) { - sorting = GIT_SORT_TIME | (sorting & GIT_SORT_REVERSE); + sorting = sort::time | (sorting & sort::reverse); walk.sort(sorting); } else if (!strcmp(opts[i], "--reverse")) { - sorting = (sorting & ~GIT_SORT_REVERSE) - | ((sorting & GIT_SORT_REVERSE) ? 0 : GIT_SORT_REVERSE); + if ((sorting & sort::reverse) != sort::none) + sorting = sorting & ~sort::reverse; walk.sort(sorting); } else if (!strcmp(opts[i], "--not")) { hide = !hide; diff --git a/examples/rev-parse.cpp b/examples/rev-parse.cpp index 3c47e16..c161577 100644 --- a/examples/rev-parse.cpp +++ b/examples/rev-parse.cpp @@ -43,7 +43,7 @@ void parse_revision(parse_state & ps, const char *revstr) if ((rs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) { git_oid base = ps.repo->merge_base(range); - std::cout << id_to_str(&base) << std::endl; + std::cout << id_to_str(base) << std::endl; } std::cout << "^" << id_to_str(range.from.id()) << std::endl; diff --git a/include/git2cpp/blob.h b/include/git2cpp/blob.h index 374e5c4..c2656bf 100644 --- a/include/git2cpp/blob.h +++ b/include/git2cpp/blob.h @@ -13,7 +13,7 @@ namespace git { struct Blob { - explicit Blob(git_oid const * oid, git_repository * repo); + Blob(git_oid const & oid, git_repository * repo); ~Blob(); git_off_t size() const; diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 3498c37..660071f 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -16,7 +16,7 @@ namespace git size_t parents_num() const; Commit parent(size_t i) const; - git_oid const * parent_id(size_t i) const; + git_oid const & parent_id(size_t i) const; Tree tree() const; @@ -24,15 +24,18 @@ namespace git explicit operator bool () const { return commit_; } - git_oid const * id() const; + git_oid const & id() const; git_signature const * author() const; git_signature const * commiter() const; - const char * message() const; - git_time_t time() const; + const char * message() const; + const char * summary() const; + git_time_t time() const; - Commit(git_oid const * oid, Repository const & repo); + git_oid merge_base(size_t p1, size_t p2) const; + + Commit(git_oid const & oid, Repository const & repo); Commit(git_commit * commit, Repository const & repo) : commit_(commit) diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 85ae7c6..7f94710 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -1,326 +1,183 @@ #pragma once #include -#include + +#include #include "id_to_str.h" namespace git { - struct repository_open_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not open repository"; - } - }; - - struct repository_init_error : std::exception - { - explicit repository_init_error(std::string const & dir) - : message_("Could not initialize repository on path " + dir) - {} - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct index_open_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not open repository index"; - } - }; - - struct odb_open_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not open ODB"; - } - }; - - struct commit_lookup_error : std::exception - { - explicit commit_lookup_error(git_oid const * id) - : message_("Could not lookup commit " + id_to_str(id)) - {} - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct tree_lookup_error : std::exception - { - explicit tree_lookup_error(git_oid const * id) - : message_("Could not lookup tree " + id_to_str(id)) - {} - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct tag_lookup_error : std::exception - { - explicit tag_lookup_error(git_oid const * id) - : message_("Could not lookup tag " + id_to_str(id)) - {} - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct commit_parent_error : std::exception - { - explicit commit_parent_error(git_oid const * id) - : message_("Could not get parent for commit " + id_to_str(id)) - {} - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct commit_tree_error : std::exception - { - explicit commit_tree_error(git_oid const * id) - : message_("Could not get tree for commit " + id_to_str(id)) - {} - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct revparse_error : std::exception - { - explicit revparse_error(const char * spec) - { - std::ostringstream ss; - ss << "Could not resolve " << spec; - message_ = ss.str(); - } - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct odb_read_error : std::exception - { - explicit odb_read_error(git_oid const * id) - : message_("Could not find obj " + id_to_str(id)) - {} - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct odb_write_error : std::exception - { - virtual const char * what() const noexcept override - { - return "odb write error"; - } - }; - - struct file_not_found_error : std::exception - { - explicit file_not_found_error(const char * filepath) - { - std::ostringstream ss; - ss << "file path \"" << filepath << "\" not found"; - message_ = ss.str(); - } - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct ambiguous_path_error : std::exception - { - explicit ambiguous_path_error(const char * filepath) - { - std::ostringstream ss; - ss << "file path \"" << filepath << "\" is ambiguous"; - message_ = ss.str(); - } - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct unknown_file_status_error : std::exception - { - explicit unknown_file_status_error(const char * filepath) - { - std::ostringstream ss; - ss << "unknown error during getting status for file \"" << filepath; - message_ = ss.str(); - } - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct pathspec_new_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not build pathspec"; - } - }; - - struct revwalk_new_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not create revision walker"; - } - }; - - struct invalid_head_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not find repository HEAD"; - } - }; - - struct non_commit_object_error : std::exception - { - explicit non_commit_object_error(git_oid const * id) - { - std::ostringstream ss; - ss << "object " << id_to_str(id) << " is not a commit"; - message_ = ss.str(); - } - - virtual const char * what() const noexcept override - { - return message_.c_str(); - } - - private: - std::string message_; - }; - - struct unknown_get_current_branch_error : std::exception - { - virtual const char * what() const noexcept override - { - return "failed to get current branch"; - } - }; - - struct get_status_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not get status"; - } - }; - - struct signature_create_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Unable to create a commit signature." - " Perhaps 'user.name' and 'user.email' are not set"; - } - }; - - struct index_write_tree_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Unable to write tree from index"; - } - }; - - struct index_write_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Unable to write index"; - } - }; - - struct commit_create_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not create commit"; - } - }; - - struct merge_base_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not find merge base"; - } - }; - - struct config_open_error : std::exception - { - virtual const char * what() const noexcept override - { - return "Could not open config"; - } - }; + struct error_t : std::runtime_error + { + explicit error_t(std::string const & message) : std::runtime_error(message) {} + explicit error_t(boost::format const & message) : error_t(str(message)) {} + }; + + struct repository_open_error : error_t + { + repository_open_error() : error_t("Could not open repository") {} + }; + + struct repository_init_error : error_t + { + explicit repository_init_error(std::string const & dir) + : error_t("Could not initialize repository on path " + dir) + {} + }; + + struct index_open_error : error_t + { + index_open_error() : error_t("Could not open repository index") {} + }; + + struct odb_open_error : error_t + { + odb_open_error() : error_t("Could not open ODB") {} + }; + + struct commit_lookup_error : error_t + { + explicit commit_lookup_error(git_oid const & id) + : error_t("Could not lookup commit " + id_to_str(id)) + {} + }; + + struct tree_lookup_error : error_t + { + explicit tree_lookup_error(git_oid const & id) + : error_t("Could not lookup tree " + id_to_str(id)) + {} + }; + + struct tag_lookup_error : error_t + { + explicit tag_lookup_error(git_oid const & id) + : error_t("Could not lookup tag " + id_to_str(id)) + {} + }; + + struct commit_parent_error : error_t + { + explicit commit_parent_error(git_oid const & id) + : error_t("Could not get parent for commit " + id_to_str(id)) + {} + }; + + struct commit_tree_error : error_t + { + explicit commit_tree_error(git_oid const & id) + : error_t("Could not get tree for commit " + id_to_str(id)) + {} + }; + + struct revparse_error : error_t + { + explicit revparse_error(const char * spec) + : error_t(boost::format("Could not resolve %1%") % spec) + {} + }; + + struct odb_read_error : error_t + { + explicit odb_read_error(git_oid const & id) + : error_t("Could not find obj " + id_to_str(id)) + {} + }; + + struct odb_write_error : error_t + { + odb_write_error() : error_t("odb write error") {} + }; + + struct file_not_found_error : error_t + { + explicit file_not_found_error(const char * filepath) + : error_t(boost::format("file path \"%1%\" not found") % filepath) + {} + }; + + struct ambiguous_path_error : error_t + { + explicit ambiguous_path_error(const char * filepath) + : error_t(boost::format("file path \"%1%\" is ambiguous") % filepath) + {} + }; + + struct unknown_file_status_error : error_t + { + explicit unknown_file_status_error(const char * filepath) + : error_t(boost::format("unknown error during getting status for file \"%1%\"") % filepath) + {} + }; + + struct pathspec_new_error : error_t + { + pathspec_new_error() : error_t("Could not build pathspec") {} + }; + + struct revwalk_new_error : error_t + { + revwalk_new_error() : error_t("Could not create revision walker") {} + }; + + struct invalid_head_error : error_t + { + invalid_head_error() : error_t("Could not find repository HEAD") {} + }; + + struct non_commit_object_error : error_t + { + explicit non_commit_object_error(git_oid const & id) + : error_t(str(boost::format("object %1% is not a commit") % id_to_str(id))) + {} + }; + + struct unknown_get_current_branch_error : error_t + { + unknown_get_current_branch_error() : error_t("failed to get current branch") {} + }; + + struct get_status_error : error_t + { + get_status_error() : error_t("Could not get status") {} + }; + + struct signature_create_error : error_t + { + signature_create_error() + : error_t("Unable to create a commit signature." + " Perhaps 'user.name' and 'user.email' are not set") + {} + }; + + struct index_write_tree_error : error_t + { + index_write_tree_error() : error_t("Unable to write tree from index") {} + }; + + struct index_write_error : error_t + { + index_write_error() : error_t("Unable to write index") {} + }; + + struct commit_create_error : error_t + { + commit_create_error() : error_t("Could not create commit") {} + }; + + struct merge_base_error : error_t + { + merge_base_error(git_oid const & c1, git_oid const & c2) + : error_t(boost::format("Could not find merge base for commits %1% and % 2%") + % id_to_str(c1, 8) + % id_to_str(c2, 8)) + {} + }; + + struct config_open_error : error_t + { + config_open_error() : error_t("Could not open config") {} + }; } diff --git a/include/git2cpp/id_to_str.h b/include/git2cpp/id_to_str.h index cde6d25..84e94fb 100644 --- a/include/git2cpp/id_to_str.h +++ b/include/git2cpp/id_to_str.h @@ -9,9 +9,9 @@ extern "C" namespace git { - std::string id_to_str(git_oid const * oid); + std::string id_to_str(git_oid const & oid); - std::string id_to_str(git_oid const * oid, size_t digits_num); + std::string id_to_str(git_oid const & oid, size_t digits_num); git_oid str_to_id(const char * str); } diff --git a/include/git2cpp/initializer.h b/include/git2cpp/initializer.h index 2d83b02..5ffdcd1 100644 --- a/include/git2cpp/initializer.h +++ b/include/git2cpp/initializer.h @@ -11,3 +11,5 @@ namespace git Initializer& operator = (Initializer const &) = delete; }; } + +#define auto_git_initializer ::git::Initializer git_initializer; (void) git_initializer diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index 88c5dc9..624bfff 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -24,7 +24,7 @@ namespace git explicit operator bool() const { return obj_; } git_otype type() const; - git_oid const * id() const; + git_oid const & id() const; git_blob const * as_blob() const; git_commit const * as_commit() const; diff --git a/include/git2cpp/odb.h b/include/git2cpp/odb.h index 4d93fb3..b6b58e4 100644 --- a/include/git2cpp/odb.h +++ b/include/git2cpp/odb.h @@ -16,7 +16,7 @@ namespace git explicit Odb(git_repository * repo); ~Odb(); - OdbObject read(git_oid const * oid) const; + OdbObject read(git_oid const & oid) const; git_oid write(const void * data, size_t len, git_otype type); Odb (Odb const &) = delete; diff --git a/include/git2cpp/reference.h b/include/git2cpp/reference.h index 0cb2628..6858b2e 100644 --- a/include/git2cpp/reference.h +++ b/include/git2cpp/reference.h @@ -17,7 +17,7 @@ namespace git const char * name() const; git_ref_t type() const; - git_oid const * target() const; + git_oid const & target() const; const char * symbolic_target() const; Reference& operator = (Reference const &) = delete; diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index a71ed2b..f8e645b 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -34,10 +34,10 @@ namespace git { git_repository * ptr() const { return repo_; } - Commit commit_lookup(git_oid const * oid) const; - Tree tree_lookup (git_oid const * oid) const; - Tag tag_lookup (git_oid const * oid) const; - Blob blob_lookup (git_oid const * oid) const; + Commit commit_lookup(git_oid const & oid) const; + Tree tree_lookup (git_oid const & oid) const; + Tag tag_lookup (git_oid const & oid) const; + Blob blob_lookup (git_oid const & oid) const; git_oid merge_base(Revspec::Range const & range) const; diff --git a/include/git2cpp/revwalker.h b/include/git2cpp/revwalker.h index 6b05674..f9d5149 100644 --- a/include/git2cpp/revwalker.h +++ b/include/git2cpp/revwalker.h @@ -7,32 +7,48 @@ struct git_revwalk; namespace git { - struct Repository; - - struct RevWalker - { - explicit RevWalker(git_repository * repo); - ~RevWalker(); - - void sort(int sorting); - - void push_head() const; - void hide(git_oid const * obj) const; - void push(git_oid const * obj) const; - - Commit next(Repository const & repo) const; - bool next(char * id_buffer) const; - - RevWalker (RevWalker const &) = delete; - RevWalker& operator = (RevWalker const &) = delete; - - RevWalker(RevWalker && other) - : walker_(other.walker_) - { - other.walker_ = nullptr; - } - - private: - git_revwalk * walker_; - }; + struct Repository; + + struct RevWalker + { + explicit RevWalker(Repository const & repo); + ~RevWalker(); + + enum class sorting : unsigned int + { + none = 0, + topological = 1 << 0, + time = 1 << 1, + reverse = 1 << 2 + }; + + friend sorting operator ~ (sorting); + friend sorting operator | (sorting, sorting); + friend sorting operator & (sorting, sorting); + friend sorting operator ^ (sorting, sorting); + + void sort(sorting); + void simplify_first_parent(); + + void push_head() const; + void hide(git_oid const &) const; + void push(git_oid const &) const; + + Commit next() const; + bool next(char * id_buffer) const; + + RevWalker (RevWalker const &) = delete; + RevWalker& operator = (RevWalker const &) = delete; + + RevWalker(RevWalker && other) + : walker_(other.walker_) + , repo_(other.repo_) + { + other.walker_ = nullptr; + } + + private: + git_revwalk * walker_; + Repository const & repo_; + }; } diff --git a/include/git2cpp/tag.h b/include/git2cpp/tag.h index 0fd8d85..055a94f 100644 --- a/include/git2cpp/tag.h +++ b/include/git2cpp/tag.h @@ -10,7 +10,7 @@ namespace git struct Tag { - Tag(git_oid const * oid, Repository const &); + Tag(git_oid const & oid, Repository const &); ~Tag(); Tag& operator = (Tag const &) = delete; diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index f220991..5ec8a80 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -29,7 +29,7 @@ namespace git return git_tree_entry_byname(tree_, filename.c_str()); } - Tree(git_oid const * oid, git_repository * repo); + Tree(git_oid const & oid, git_repository * repo); explicit Tree(git_tree * tree = nullptr) : tree_(tree) diff --git a/src/blob.cpp b/src/blob.cpp index 2a75625..e7d1927 100644 --- a/src/blob.cpp +++ b/src/blob.cpp @@ -7,9 +7,9 @@ extern "C" namespace git { - Blob::Blob(const git_oid *oid, git_repository *repo) + Blob::Blob(git_oid const & oid, git_repository *repo) { - git_blob_lookup(&blob_, repo, oid); + git_blob_lookup(&blob_, repo, &oid); } Blob::~Blob() diff --git a/src/commit.cpp b/src/commit.cpp index 8e06e8d..4d73771 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -1,9 +1,11 @@ #include "git2cpp/commit.h" #include "git2cpp/repo.h" +#include "git2cpp/error.h" extern "C" { #include +#include } namespace git @@ -29,14 +31,14 @@ namespace git return git_commit_parentcount(commit_); } - git_oid const * Commit::id() const + git_oid const & Commit::id() const { - return git_commit_id(commit_); + return *git_commit_id(commit_); } - git_oid const * Commit::parent_id(size_t i) const + git_oid const & Commit::parent_id(size_t i) const { - return git_commit_parent_id(commit_, i); + return *git_commit_parent_id(commit_, i); } git_signature const * Commit::author() const @@ -54,15 +56,28 @@ namespace git return git_commit_message(commit_); } + const char * Commit::summary() const + { + return git_commit_summary(commit_); + } + git_time_t Commit::time() const { return git_commit_time(commit_); } - Commit::Commit(git_oid const * oid, Repository const & repo) + git_oid Commit::merge_base(size_t p1, size_t p2) const + { + git_oid res; + if (git_merge_base(&res, repo_->ptr(), &parent_id(p1), &parent_id(p2))) + throw merge_base_error(parent_id(p1), parent_id(p2)); + return res; + } + + Commit::Commit(git_oid const & oid, Repository const & repo) : repo_(&repo) { - if (git_commit_lookup(&commit_, repo.ptr(), oid)) + if (git_commit_lookup(&commit_, repo.ptr(), &oid)) throw commit_lookup_error(oid); } diff --git a/src/id_to_str.cpp b/src/id_to_str.cpp index 8e36ffb..9bcdd97 100644 --- a/src/id_to_str.cpp +++ b/src/id_to_str.cpp @@ -7,15 +7,15 @@ extern "C" namespace git { - std::string id_to_str(git_oid const * oid) + std::string id_to_str(git_oid const & oid) { return id_to_str(oid, GIT_OID_HEXSZ); } - std::string id_to_str(git_oid const * oid, size_t digits_num) + std::string id_to_str(git_oid const & oid, size_t digits_num) { char buf[digits_num + 1]; - git_oid_tostr(buf, sizeof(buf), oid); + git_oid_tostr(buf, sizeof(buf), &oid); return std::string(buf); } diff --git a/src/object.cpp b/src/object.cpp index cabe63e..6b2c80d 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -31,9 +31,9 @@ namespace git return git_object_type(obj_); } - git_oid const * Object::id() const + git_oid const & Object::id() const { - return git_object_id(obj_); + return *git_object_id(obj_); } #define DEFINE_METHOD_AS(type_name, enum_element) \ diff --git a/src/odb.cpp b/src/odb.cpp index 03da994..e28fb2e 100644 --- a/src/odb.cpp +++ b/src/odb.cpp @@ -21,10 +21,10 @@ namespace git git_odb_free(odb_); } - OdbObject Odb::read(git_oid const * oid) const + OdbObject Odb::read(git_oid const & oid) const { git_odb_object * obj; - if (git_odb_read(&obj, odb_, oid)) + if (git_odb_read(&obj, odb_, &oid)) throw odb_read_error(oid); return OdbObject(obj); } diff --git a/src/reference.cpp b/src/reference.cpp index 42df965..d0769db 100644 --- a/src/reference.cpp +++ b/src/reference.cpp @@ -26,9 +26,9 @@ namespace git return git_reference_type(ref_); } - git_oid const * Reference::target() const + git_oid const & Reference::target() const { - return git_reference_target(ref_); + return *git_reference_target(ref_); } const char * Reference::symbolic_target() const diff --git a/src/repo.cpp b/src/repo.cpp index 6f20b64..6b53955 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -59,22 +59,22 @@ namespace git return Signature(repo_); } - Commit Repository::commit_lookup(git_oid const * oid) const + Commit Repository::commit_lookup(git_oid const & oid) const { return Commit(oid, *this); } - Tree Repository::tree_lookup(git_oid const * oid) const + Tree Repository::tree_lookup(git_oid const & oid) const { return Tree(oid, repo_); } - Tag Repository::tag_lookup(git_oid const * oid) const + Tag Repository::tag_lookup(git_oid const & oid) const { return Tag(oid, *this); } - Blob Repository::blob_lookup(git_oid const * oid) const + Blob Repository::blob_lookup(git_oid const & oid) const { return Blob(oid, repo_); } @@ -182,29 +182,32 @@ namespace git RevWalker Repository::rev_walker() const { - return RevWalker(repo_); + return RevWalker(*this); } git_oid Repository::merge_base(Revspec::Range const & range) const { git_oid res; - if (git_merge_base(&res, repo_, range.from.id(), range.to.id())) - throw merge_base_error(); + if (git_merge_base(&res, repo_, &range.from.id(), &range.to.id())) + throw merge_base_error(range.from.id(), range.to.id()); return res; } Reference Repository::head() const { git_reference * head; - auto error = git_repository_head(&head, repo_); - if (error == GIT_EUNBORNBRANCH) + switch (auto error = git_repository_head(&head, repo_)) + { + case GIT_EUNBORNBRANCH: throw non_existing_branch_error(); - else if (error == GIT_ENOTFOUND) + case GIT_ENOTFOUND: throw missing_head_error(); - else if (error) - throw unknown_get_current_branch_error(); - else - return Reference(head); + default: + if (error == 0) + return Reference(head); + else + throw unknown_get_current_branch_error(); + } } Reference Repository::ref(const char * name) const diff --git a/src/revwalker.cpp b/src/revwalker.cpp index fa584ee..42e7add 100644 --- a/src/revwalker.cpp +++ b/src/revwalker.cpp @@ -9,9 +9,10 @@ extern "C" namespace git { - RevWalker::RevWalker(git_repository * repo) + RevWalker::RevWalker(Repository const & repo) + : repo_(repo) { - if (git_revwalk_new(&walker_, repo)) + if (git_revwalk_new(&walker_, repo.ptr())) throw revwalk_new_error(); } @@ -20,9 +21,42 @@ namespace git git_revwalk_free(walker_); } - void RevWalker::sort(int sorting) + namespace { - git_revwalk_sorting(walker_, sorting); + unsigned int raw(RevWalker::sorting s) + { + return static_cast(s); + } + } + + RevWalker::sorting operator ~ (RevWalker::sorting s) + { + return RevWalker::sorting(~raw(s)); + } + + RevWalker::sorting operator | (RevWalker::sorting a, RevWalker::sorting b) + { + return RevWalker::sorting(raw(a) | raw(b)); + } + + RevWalker::sorting operator ^ (RevWalker::sorting a, RevWalker::sorting b) + { + return RevWalker::sorting(raw(a) ^ raw(b)); + } + + RevWalker::sorting operator & (RevWalker::sorting a, RevWalker::sorting b) + { + return RevWalker::sorting(raw(a) & raw(b)); + } + + void RevWalker::sort(sorting s) + { + git_revwalk_sorting(walker_, raw(s)); + } + + void RevWalker::simplify_first_parent() + { + git_revwalk_simplify_first_parent(walker_); } void RevWalker::push_head() const @@ -31,23 +65,23 @@ namespace git throw invalid_head_error(); } - void RevWalker::hide(git_oid const * obj) const + void RevWalker::hide(git_oid const & obj) const { - if (git_revwalk_hide(walker_, obj)) + if (git_revwalk_hide(walker_, &obj)) throw non_commit_object_error(obj); } - void RevWalker::push(git_oid const * obj) const + void RevWalker::push(git_oid const & obj) const { - if (git_revwalk_push(walker_, obj)) + if (git_revwalk_push(walker_, &obj)) throw non_commit_object_error(obj); } - Commit RevWalker::next(Repository const & repo) const + Commit RevWalker::next() const { git_oid oid; if (git_revwalk_next(&oid, walker_) == 0) - return repo.commit_lookup(&oid); + return repo_.commit_lookup(oid); else return Commit(); } diff --git a/src/tag.cpp b/src/tag.cpp index 793bc36..cd56f99 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -6,10 +6,10 @@ namespace git { - Tag::Tag(git_oid const * oid, Repository const & repo) + Tag::Tag(git_oid const & oid, Repository const & repo) : repo_(repo) { - if (git_tag_lookup(&tag_, repo.ptr(), oid)) + if (git_tag_lookup(&tag_, repo.ptr(), &oid)) throw tag_lookup_error(oid); } diff --git a/src/tree.cpp b/src/tree.cpp index 2ec2f36..3a22e07 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -3,9 +3,9 @@ namespace git { - Tree::Tree(git_oid const * oid, git_repository *repo) + Tree::Tree(git_oid const & oid, git_repository *repo) { - if (git_tree_lookup(&tree_, repo, oid)) + if (git_tree_lookup(&tree_, repo, &oid)) throw tree_lookup_error(oid); } } From 33e50c64dfd959f33fea4f1803e49b2f22f685e5 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 23 Nov 2015 21:01:34 +0300 Subject: [PATCH 004/171] + missing return --- include/git2cpp/tree.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index 5ec8a80..c851506 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -45,6 +45,7 @@ namespace git { tree_ = other.tree_; other.tree_ = nullptr; + return *this; } Tree (Tree const &) = delete; From f50c3d909cdb86a15414b8cc9b0731eb5ed3854d Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 23 Nov 2015 21:01:53 +0300 Subject: [PATCH 005/171] CMake: include_directories -> target_include_directories --- CMakeLists.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4db6315..deee557 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,6 @@ project (libgit2cpp) cmake_minimum_required(VERSION 2.8) -include_directories(include) - set(CMAKE_CXX_FLAGS -std=c++11) file(GLOB lib_sources @@ -11,6 +9,14 @@ file(GLOB lib_sources ) add_library(git2cpp ${lib_sources}) + +target_include_directories(git2cpp + PRIVATE + src + PUBLIC + $ +) + target_link_libraries(git2cpp git2) install_targets(/lib git2cpp) From 084b4e680a93aab5bb15b326b91706bf6cab4d7e Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 03:06:13 +0100 Subject: [PATCH 006/171] updated git_submodule_status --- examples/status.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/status.cpp b/examples/status.cpp index 496aee1..b69a5f2 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -270,7 +270,7 @@ void print_short(Repository const & repo, Status const & status) unsigned int smstatus = 0; if (!repo.submodule_lookup(sm, s->index_to_workdir->new_file.path) && - !git_submodule_status(&smstatus, sm)) + !git_submodule_status(&smstatus, repo.ptr(), git_submodule_name(sm), git_submodule_ignore(sm))) { if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED) extra = " (new commits)"; From 1550c1e1c49b9eb7b10b676654f9c8f89e334939 Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 03:14:15 +0100 Subject: [PATCH 007/171] added initializer --- examples/status.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/status.cpp b/examples/status.cpp index b69a5f2..0b41c71 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -15,6 +15,7 @@ extern "C" #include } +#include "git2cpp/initializer.h" #include "git2cpp/repo.h" using namespace git; @@ -318,6 +319,8 @@ void print_short(Repository const & repo, Status const & status) int main(int argc, char *argv[]) { + auto_git_initializer; + int i, npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0; git_status_options opt = GIT_STATUS_OPTIONS_INIT; const char *repodir = "."; From 964321a72fb69e9c7a0d6c678c41b9da00f5c301 Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 03:45:16 +0100 Subject: [PATCH 008/171] fixed testrepo path added initializer --- examples/general.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/general.cpp b/examples/general.cpp index a221382..489fd68 100644 --- a/examples/general.cpp +++ b/examples/general.cpp @@ -31,8 +31,10 @@ #include #include +#include "git2cpp/initializer.h" #include "git2cpp/repo.h" #include "git2cpp/config.h" + using namespace git; // Almost all libgit2 functions return 0 on success or negative on error. @@ -59,7 +61,7 @@ int main (int argc, char** argv) // simplest. There are also [methods][me] for specifying the index file // and work tree locations, here we assume they are in the normal places. // - // (Try running this program against tests-clar/resources/testrepo.git.) + // (Try running this program against libgit2/tests/resources/testrepo.git/) // // [me]: http://libgit2.github.com/libgit2/#HEAD/group/repository assert(argc >= 2); @@ -67,7 +69,9 @@ int main (int argc, char** argv) try { - Repository repo(repo_path); + git::Initializer threads_initializer; + + Repository repo(repo_path); // ### SHA-1 Value Conversions From f2109e56c6eaba6fe00a72b403abbf469f259ecc Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 03:45:30 +0100 Subject: [PATCH 009/171] cosmetics --- examples/status.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/status.cpp b/examples/status.cpp index 0b41c71..4d16888 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -319,7 +319,7 @@ void print_short(Repository const & repo, Status const & status) int main(int argc, char *argv[]) { - auto_git_initializer; + git::Initializer threads_initializer; int i, npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0; git_status_options opt = GIT_STATUS_OPTIONS_INIT; From 733b0cf802a45727603cf2f5e4142f7c04caf327 Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 04:00:05 +0100 Subject: [PATCH 010/171] initializer dtor must be after log_state dtor --- examples/log.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/log.cpp b/examples/log.cpp index c3c7b0a..c2e871f 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -296,13 +296,13 @@ int main(int argc, char *argv[]) opt.max_parents = -1; opt.limit = -1; + git::Initializer threads_initializer; + log_state s; int count = 0; int parsed_options_num = parse_options(argc, argv, s, opt, count); - git::Initializer threads_initializer; - if (!count) add_revision(&s, NULL); From 978fa61ed1155b22dd639be92f6e9a7df6af778d Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 04:03:16 +0100 Subject: [PATCH 011/171] initializer must be upstream from parse_state --- examples/rev-parse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/rev-parse.cpp b/examples/rev-parse.cpp index c161577..c707d28 100644 --- a/examples/rev-parse.cpp +++ b/examples/rev-parse.cpp @@ -52,10 +52,10 @@ void parse_revision(parse_state & ps, const char *revstr) int main(int argc, char *argv[]) { - parse_state ps; - Initializer threads_initalizer; + parse_state ps; + for (int i = 1; i < argc; ++i) { const char * a = argv[i]; From 27e1f30ab3aee482a2fd44d3d5cbcda25d294c3f Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 04:30:47 +0100 Subject: [PATCH 012/171] added initializer --- examples/rev-list.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/rev-list.cpp b/examples/rev-list.cpp index 0331ec3..f51d8bc 100644 --- a/examples/rev-list.cpp +++ b/examples/rev-list.cpp @@ -3,6 +3,7 @@ #include +#include "git2cpp/initializer.h" #include "git2cpp/repo.h" #include "git2cpp/revwalker.h" @@ -75,7 +76,9 @@ int main (int argc, char **argv) { try { - Repository repo("."); + git::Initializer threads_initializer; + + Repository repo("."); auto walker = repo.rev_walker(); revwalk_parseopts(repo, walker, argc-1, argv+1); From 1756355d4bb408e1bdaa10bf63b8f26fac0e28ce Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 04:46:50 +0100 Subject: [PATCH 013/171] fix branch iterator --- src/repo.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/repo.cpp b/src/repo.cpp index 6b53955..516d5b5 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -124,7 +124,8 @@ namespace git struct branch_iterator { branch_iterator(Repository const & repo, branch_type type) - : type_(convert(type)) + : type_(convert(type)), + m_DoneFlag(false) { git_branch_iterator_new(&base_, repo.ptr(), type_); ++(*this); @@ -135,17 +136,26 @@ namespace git git_branch_iterator_free(base_); } - explicit operator bool () const { return ref_.is_initialized(); } + explicit operator bool () const { return ref_.is_initialized() && !m_DoneFlag; } void operator ++ () { git_branch_t type; git_reference * ref; - if (git_branch_next(&ref, &type, base_) == 0) + const int err = git_branch_next(&ref, &type, base_); + if (err == 0) { assert(type == type_); ref_ = boost::in_place(ref); } + else if (err == GIT_ITEROVER) + { + m_DoneFlag = true; + } + else + { + throw std::logic_error("unknown git_branch_next error"); + } } Reference const * operator -> () const @@ -170,13 +180,14 @@ namespace git git_branch_t type_; git_branch_iterator * base_; boost::optional ref_; + bool m_DoneFlag; }; std::vector Repository::branches(branch_type type) const { std::vector res; for (branch_iterator it(*this, type); it; ++it) - it->name(); + res.push_back(it->name()); return res; } From 7566733feb9896a1f4f7c9e50eecb799aa87992c Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 04:47:08 +0100 Subject: [PATCH 014/171] add initializer --- examples/branch.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/branch.cpp b/examples/branch.cpp index 3e139d0..dd3eb03 100644 --- a/examples/branch.cpp +++ b/examples/branch.cpp @@ -1,11 +1,14 @@ #include +#include "git2cpp/initializer.h" #include "git2cpp/repo.h" int main() { + git::Initializer threads_initializer; + git::Repository repo("."); - auto branches = repo.branches(git::branch_type::LOCAL); + auto branches = repo.branches(git::branch_type::ALL); for (auto b : branches) std::cout << b << std::endl; } From 09b2477f81a1a4b732ae6028c3ee9b9d2a39c313 Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 05:33:11 +0100 Subject: [PATCH 015/171] fix compile- vs run-time sizeof() --- src/id_to_str.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/id_to_str.cpp b/src/id_to_str.cpp index 9bcdd97..15d189b 100644 --- a/src/id_to_str.cpp +++ b/src/id_to_str.cpp @@ -14,9 +14,9 @@ namespace git std::string id_to_str(git_oid const & oid, size_t digits_num) { - char buf[digits_num + 1]; + char buf[GIT_OID_HEXSZ + 1]; git_oid_tostr(buf, sizeof(buf), &oid); - return std::string(buf); + return std::string(buf, buf + digits_num); } git_oid str_to_id(const char *str) From 739059990e83046a3211cc489dba56ba929ede16 Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 08:28:55 +0100 Subject: [PATCH 016/171] initializer must be outside try/catch block --- examples/general.cpp | 6 +++--- examples/rev-list.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/general.cpp b/examples/general.cpp index 489fd68..da6f16b 100644 --- a/examples/general.cpp +++ b/examples/general.cpp @@ -67,11 +67,11 @@ int main (int argc, char** argv) assert(argc >= 2); const char *repo_path = argv[1]; + git::Initializer threads_initializer; + try { - git::Initializer threads_initializer; - - Repository repo(repo_path); + Repository repo(repo_path); // ### SHA-1 Value Conversions diff --git a/examples/rev-list.cpp b/examples/rev-list.cpp index f51d8bc..d1c8f70 100644 --- a/examples/rev-list.cpp +++ b/examples/rev-list.cpp @@ -74,10 +74,10 @@ void revwalk_parseopts(Repository const & repo, RevWalker & walk, int nopts, cha int main (int argc, char **argv) { + git::Initializer threads_initializer; + try { - git::Initializer threads_initializer; - Repository repo("."); auto walker = repo.rev_walker(); From 20ea43a1092bd8d05f786d907ca713bd3fb3d37b Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 09:49:49 +0100 Subject: [PATCH 017/171] assert callback pointers --- src/diff.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/diff.cpp b/src/diff.cpp index c7658fd..8fffa8b 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -37,6 +37,8 @@ namespace git , git_diff_line const * line , void * payload ) { + assert(delta); + assert(line); auto cb = reinterpret_cast(payload); (*cb)(*delta, *hunk, *line); return 0; From 801d1ba825f06fd30acf570ce7bc2ae54b637b1c Mon Sep 17 00:00:00 2001 From: petah Date: Fri, 6 Nov 2015 09:54:17 +0100 Subject: [PATCH 018/171] use rev walker sort flags directly from libgit2 --- include/git2cpp/revwalker.h | 14 +++++++++----- src/revwalker.cpp | 4 ---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/git2cpp/revwalker.h b/include/git2cpp/revwalker.h index f9d5149..f1b03ed 100644 --- a/include/git2cpp/revwalker.h +++ b/include/git2cpp/revwalker.h @@ -1,9 +1,13 @@ #pragma once +extern "C" +{ +#include +} + #include "commit.h" struct git_repository; -struct git_revwalk; namespace git { @@ -16,10 +20,10 @@ namespace git enum class sorting : unsigned int { - none = 0, - topological = 1 << 0, - time = 1 << 1, - reverse = 1 << 2 + none = GIT_SORT_NONE, + topological = GIT_SORT_TOPOLOGICAL, + time = GIT_SORT_TIME, + reverse = GIT_SORT_REVERSE }; friend sorting operator ~ (sorting); diff --git a/src/revwalker.cpp b/src/revwalker.cpp index 42e7add..a25255f 100644 --- a/src/revwalker.cpp +++ b/src/revwalker.cpp @@ -1,7 +1,3 @@ -extern "C" -{ -#include -} #include "git2cpp/error.h" #include "git2cpp/revwalker.h" From 3cf4fac45c50cfe6099c66a2f70dce0b36e24e42 Mon Sep 17 00:00:00 2001 From: petah Date: Tue, 24 Nov 2015 02:07:33 +0100 Subject: [PATCH 019/171] raw test script --- CMakeLists.txt | 2 ++ README.md | 14 +++++++++++ test.sh | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100755 test.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index deee557..c2b1653 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,3 +40,5 @@ foreach (example ${examples}) add_executable(${example} examples/${example}.cpp) target_link_libraries(${example} git2cpp) endforeach(example) + +file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) \ No newline at end of file diff --git a/README.md b/README.md index 1033be6..d5e295a 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,17 @@ Building libgit2cpp - Using CMake $ mkdir build && cd build $ cmake .. $ make + +Testing +======= + + $ cd build + $ ./test.sh [path_to_libgit2_testrepo] + +e.g. + + $ mkdir build && cd build + $ cmake .. + $ make + $ ./test.sh .. ../../libgit2/tests/resources/testrepo.git + diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..fe0b161 --- /dev/null +++ b/test.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +#trace +# set -x +#verbose outputs each input line as is read +# set -v + +if [ $# -eq 0 ] ; then + echo "usage: test.sh read_only_repo [writable_repo]" 1>&2 + return 1 +fi + +REPO=$1 + +if [ ! -d $REPO ]; then + echo "repo $REPO not a directory" 1>&2 + exit 1 +fi + +CWD=${PWD} + +function test() +{ + local test_name="$1" + echo -e "**** test $test_name *********************************\n\n" + local bin="$CWD/$test_name" + + shift + + $bin "$@" + + local exit_status + + exit_status=$? + + echo -e "\nexit status $exit_status \n\n" +} + +# read-only tests (repo shouldn't be bare) +pushd $REPO + +test branch +test commit-graph-generator . "$CWD/commit-graph.dot" +test log +test rev-list --topo-order HEAD +test rev-parse HEAD +test showindex +test status + +popd + +# write test (use libgit2/tests/resources/testrepo.git) + +RW_REPO=$2 + +if [ -z $RW_REPO ]; then + echo "no writable repo specified" + exit 0 +fi + +pushd $RW_REPO + +test cat-file -t a8233120f6ad708f843d861ce2b7228ec4e3dec6 +test cat-file -p a8233120f6ad708f843d861ce2b7228ec4e3dec6 +test general . + +popd From f41db8db43a851fc574e8d6eb7e9c7b1410a6e0f Mon Sep 17 00:00:00 2001 From: petah Date: Tue, 24 Nov 2015 02:28:39 +0100 Subject: [PATCH 020/171] 1st TODO --- README.md | 4 ++-- TODO.md | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 TODO.md diff --git a/README.md b/README.md index d5e295a..679bf19 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ libgit2cpp -======= +========== C++ wrapper for libgit2 Building libgit2cpp - Using CMake -============================== +================================= $ mkdir build && cd build $ cmake .. diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..21a793c --- /dev/null +++ b/TODO.md @@ -0,0 +1,7 @@ +libgit2cpp TODO +=============== + +* restore diff +* standardize command-line processing (esp. --git-dir) +* unit tests +* embed test repo (remove dep on libgit2/tests/resources/testrepo.git) From 335a916476358ac48865c6ffba4ce61172eaa43f Mon Sep 17 00:00:00 2001 From: petah Date: Tue, 24 Nov 2015 02:31:20 +0100 Subject: [PATCH 021/171] cosmetics --- TODO.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 21a793c..21dcfe9 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,8 @@ libgit2cpp TODO =============== * restore diff -* standardize command-line processing (esp. --git-dir) +* standardize command-line processing for all examples + * most importantly --git-dir * unit tests -* embed test repo (remove dep on libgit2/tests/resources/testrepo.git) +* embed test repo + * remove dep on libgit2/tests/resources/testrepo.git From b570e4033f4b933668bf776ce54f3c3dd6970b78 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 24 Nov 2015 14:41:28 +0300 Subject: [PATCH 022/171] git::Blob::size return type: git_off_t -> std::size_t --- include/git2cpp/blob.h | 8 +++----- src/blob.cpp | 6 +++++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/git2cpp/blob.h b/include/git2cpp/blob.h index c2656bf..d87f9b2 100644 --- a/include/git2cpp/blob.h +++ b/include/git2cpp/blob.h @@ -1,9 +1,6 @@ #pragma once -extern "C" -{ -#include -} +#include struct git_blob; struct git_repository; @@ -13,10 +10,11 @@ namespace git { struct Blob { + explicit Blob(git_blob *); Blob(git_oid const & oid, git_repository * repo); ~Blob(); - git_off_t size() const; + std::size_t size() const; const void * content() const; Blob& operator = (Blob const &) = delete; diff --git a/src/blob.cpp b/src/blob.cpp index e7d1927..2be0b01 100644 --- a/src/blob.cpp +++ b/src/blob.cpp @@ -7,6 +7,10 @@ extern "C" namespace git { + Blob::Blob(git_blob * blob) + : blob_(blob) + {} + Blob::Blob(git_oid const & oid, git_repository *repo) { git_blob_lookup(&blob_, repo, &oid); @@ -17,7 +21,7 @@ namespace git git_blob_free(blob_); } - git_off_t Blob::size() const + std::size_t Blob::size() const { return git_blob_rawsize(blob_); } From 155e667f7a1ac58d7c64f3ced46778449ca470e6 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 24 Nov 2015 14:42:13 +0300 Subject: [PATCH 023/171] [+ some functions] (*) Object::to_blob (*) Tree: Borrowed and Owned entries --- include/git2cpp/object.h | 11 ++--- include/git2cpp/tree.h | 77 +++++++++++++++++------------------ src/commit.cpp | 2 +- src/object.cpp | 14 +++++-- src/repo.cpp | 2 +- src/tree.cpp | 87 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 141 insertions(+), 52 deletions(-) diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index 624bfff..ccface7 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -1,11 +1,7 @@ #pragma once -extern "C" -{ -#include -} - #include "commit.h" +#include "blob.h" struct git_object; struct git_oid; @@ -31,8 +27,9 @@ namespace git git_tree const * as_tree() const; git_tag const * as_tag() const; - Commit to_commit(); - Tree to_tree(); + Commit to_commit() /*&&*/; + Tree to_tree() /*&&*/; + Blob to_blob() /*&&*/; Object (Object const &) = delete; Object& operator = (Object const &) = delete; diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index c851506..4e9b158 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -4,62 +4,63 @@ namespace git { + struct Repository; + struct Tree { - git_tree const * ptr() const { return tree_; } - git_tree * ptr() { return tree_; } + typedef git_tree_entry const * BorrowedEntry; - int pathspec_match(uint32_t flags, Pathspec const & ps) + struct OwnedEntry { - return git_pathspec_match_tree(NULL, tree_, flags, ps.ptr()); - } + ~OwnedEntry(); - size_t entrycount() const - { - return git_tree_entrycount(tree_); - } + OwnedEntry (OwnedEntry const &) = delete; + OwnedEntry& operator = (OwnedEntry const &) = delete; - git_tree_entry const * operator[] (size_t i) const - { - return git_tree_entry_byindex(tree_, i); - } + OwnedEntry (OwnedEntry &&); + OwnedEntry& operator = (OwnedEntry &&); - git_tree_entry const * operator[] (std::string const & filename) const - { - return git_tree_entry_byname(tree_, filename.c_str()); - } + Tree as_tree() /*&&*/; - Tree(git_oid const & oid, git_repository * repo); + private: + friend struct Tree; - explicit Tree(git_tree * tree = nullptr) - : tree_(tree) - {} + OwnedEntry(git_tree_entry * entry, Repository const & repo); - Tree(Tree && other) - : tree_(other.tree_) - { - other.tree_ = nullptr; - } + private: + git_tree_entry * entry_; + Repository const * repo_; + }; - Tree& operator =(Tree && other) - { - tree_ = other.tree_; - other.tree_ = nullptr; - return *this; - } + git_tree const * ptr() const { return tree_; } + git_tree * ptr() { return tree_; } - Tree (Tree const &) = delete; - Tree& operator = (Tree const &) = delete; + int pathspec_match(uint32_t flags, Pathspec const & ps); - ~Tree() - { - git_tree_free(tree_); - } + size_t entrycount() const; + + BorrowedEntry operator[] (size_t) const; + + BorrowedEntry operator[] (std::string const & filename) const; + + OwnedEntry find(const char * path) const; + + Tree(git_oid const &, Repository const &); + Tree(git_tree *, Repository const &); + + ~Tree(); + + Tree (Tree &&); + Tree& operator =(Tree &&); + + Tree (Tree const &) = delete; + Tree& operator =(Tree const &) = delete; explicit operator bool() const { return tree_; } private: git_tree * tree_; + Repository const * repo_; }; } diff --git a/src/commit.cpp b/src/commit.cpp index 4d73771..1627ea8 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -23,7 +23,7 @@ namespace git git_tree * tree; if (git_commit_tree(&tree, commit_)) throw commit_tree_error(id()); - return Tree(tree); + return Tree(tree, *repo_); } size_t Commit::parents_num() const diff --git a/src/object.cpp b/src/object.cpp index 6b2c80d..6a82aaa 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -50,20 +50,28 @@ namespace git #undef DEFINE_METHOD_AS - Tree Object::to_tree() + Tree Object::to_tree() /*&&*/ { assert(type() == GIT_OBJ_TREE); - Tree res(reinterpret_cast(obj_)); + Tree res(reinterpret_cast(obj_), *repo_); obj_ = nullptr; return res; } - Commit Object::to_commit() + Commit Object::to_commit() /*&&*/ { assert(type() == GIT_OBJ_COMMIT); Commit res(reinterpret_cast(obj_), *repo_); obj_ = nullptr; return res; } + + Blob Object::to_blob() /*&&*/ + { + assert(type() == GIT_OBJ_COMMIT); + Blob res(reinterpret_cast(obj_)); + obj_ = nullptr; + return res; + } } diff --git a/src/repo.cpp b/src/repo.cpp index 516d5b5..b915024 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -66,7 +66,7 @@ namespace git Tree Repository::tree_lookup(git_oid const & oid) const { - return Tree(oid, repo_); + return Tree(oid, *this); } Tag Repository::tag_lookup(git_oid const & oid) const diff --git a/src/tree.cpp b/src/tree.cpp index 3a22e07..eb403a3 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -1,11 +1,94 @@ #include "git2cpp/tree.h" #include "git2cpp/error.h" +#include "git2cpp/repo.h" + +#include namespace git { - Tree::Tree(git_oid const & oid, git_repository *repo) + Tree::Tree(git_oid const & oid, Repository const & repo) + : repo_(&repo) { - if (git_tree_lookup(&tree_, repo, &oid)) + if (git_tree_lookup(&tree_, repo.ptr(), &oid)) throw tree_lookup_error(oid); } + + Tree::Tree(git_tree * tree, Repository const & repo) + : tree_(tree) + , repo_(&repo) + {} + + Tree::Tree(Tree && other) + : tree_(other.tree_) + , repo_(other.repo_) + { + other.tree_ = nullptr; + other.repo_ = nullptr; + } + + Tree& Tree::operator =(Tree && other) + { + tree_ = other.tree_; + repo_ = other.repo_; + other.tree_ = nullptr; + other.repo_ = nullptr; + return *this; + } + + Tree::~Tree() + { + git_tree_free(tree_); + } + + int Tree::pathspec_match(uint32_t flags, Pathspec const & ps) + { + return git_pathspec_match_tree(NULL, tree_, flags, ps.ptr()); + } + + size_t Tree::entrycount() const + { + return git_tree_entrycount(tree_); + } + + Tree::BorrowedEntry Tree::operator[] (size_t i) const + { + return git_tree_entry_byindex(tree_, i); + } + + Tree::BorrowedEntry Tree::operator[] (std::string const & filename) const + { + return git_tree_entry_byname(tree_, filename.c_str()); + } + + Tree::OwnedEntry Tree::find(const char * path) const + { + git_tree_entry * res; + const auto status = git_tree_entry_bypath(&res, tree_, path); + switch (status) + { + case GIT_OK: + return OwnedEntry(res, *repo_); + case GIT_ENOTFOUND: + throw file_not_found_error(path); + default: + throw error_t(boost::format("unknown error inside function: 'git_tree_entry_bypath': %1%") % status); + } + } + + Tree::OwnedEntry::OwnedEntry(git_tree_entry * entry, Repository const & repo) + : entry_(entry) + , repo_(&repo) + {} + + Tree::OwnedEntry::~OwnedEntry() + { + git_tree_entry_free(entry_); + } + + Tree Tree::OwnedEntry::as_tree() + { + git_object * obj; + git_tree_entry_to_object(&obj, repo_->ptr(), entry_); + return Object(obj, *repo_).to_tree(); + } } From 7220571e2fd67773611399d7274aa3d0f709affc Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 24 Nov 2015 15:43:37 +0300 Subject: [PATCH 024/171] copypaste fix --- src/object.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object.cpp b/src/object.cpp index 6a82aaa..e26be81 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -68,7 +68,7 @@ namespace git Blob Object::to_blob() /*&&*/ { - assert(type() == GIT_OBJ_COMMIT); + assert(type() == GIT_OBJ_BLOB); Blob res(reinterpret_cast(obj_)); obj_ = nullptr; return res; From ec5e90522ebd27a7823ef4de675a76c4ca28d585 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 24 Nov 2015 16:02:40 +0300 Subject: [PATCH 025/171] + move ctor implementation for Blob --- src/blob.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/blob.cpp b/src/blob.cpp index 2be0b01..07864f5 100644 --- a/src/blob.cpp +++ b/src/blob.cpp @@ -16,6 +16,12 @@ namespace git git_blob_lookup(&blob_, repo, &oid); } + Blob::Blob(Blob && other) + : blob_(other.blob_) + { + other.blob_ = nullptr; + } + Blob::~Blob() { git_blob_free(blob_); From 4c38b7e07fdf95a57c5b73f2fccce3b29a410ea0 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 24 Nov 2015 22:20:36 +0300 Subject: [PATCH 026/171] Tree::BorrowedEntry: typedef -> struct --- examples/general.cpp | 6 +++--- include/git2cpp/repo.h | 2 +- include/git2cpp/tree.h | 18 +++++++++++++++++- src/repo.cpp | 4 ++-- src/tree.cpp | 14 ++++++++++++-- 5 files changed, 35 insertions(+), 9 deletions(-) diff --git a/examples/general.cpp b/examples/general.cpp index da6f16b..16be78a 100644 --- a/examples/general.cpp +++ b/examples/general.cpp @@ -285,13 +285,13 @@ int main (int argc, char** argv) size_t cnt = tree.entrycount(); // 3 printf("tree entries: %d\n", (int)cnt); - git_tree_entry const * entry = tree[0]; - printf("Entry name: %s\n", git_tree_entry_name(entry)); // "hello.c" + auto entry = tree[0]; + printf("Entry name: %s\n", entry.name()); // "hello.c" // You can also access tree entries by name if you know the name of the // entry you're looking for. entry = tree["README"]; - git_tree_entry_name(entry); // "hello.c" + entry.name(); // "hello.c" // Once you have the entry object, you can access the content or subtree // (or commit, in the case of submodules) that it points to. You can also diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index f8e645b..f626e0c 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -48,7 +48,7 @@ namespace git git_status_t file_status(const char * filepath) const; - Object entry_to_object(git_tree_entry const * entry) const; + Object entry_to_object(Tree::BorrowedEntry) const; Index index() const; Odb odb() const; diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index 4e9b158..dcca204 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -8,7 +8,22 @@ namespace git struct Tree { - typedef git_tree_entry const * BorrowedEntry; + struct BorrowedEntry + { + const char * name() const; + + git_tree_entry const * ptr() const { return entry_; } + + private: + friend struct Tree; + + explicit BorrowedEntry(git_tree_entry const * entry) + : entry_(entry) + {} + + private: + git_tree_entry const * entry_; + }; struct OwnedEntry { @@ -48,6 +63,7 @@ namespace git Tree(git_oid const &, Repository const &); Tree(git_tree *, Repository const &); + Tree(); ~Tree(); Tree (Tree &&); diff --git a/src/repo.cpp b/src/repo.cpp index b915024..cd190ab 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -292,10 +292,10 @@ namespace git return res; } - Object Repository::entry_to_object(git_tree_entry const * entry) const + Object Repository::entry_to_object(Tree::BorrowedEntry entry) const { git_object * obj; - git_tree_entry_to_object(&obj, repo_, entry); + git_tree_entry_to_object(&obj, repo_, entry.ptr()); return Object(obj, *this); } diff --git a/src/tree.cpp b/src/tree.cpp index eb403a3..1fd3cab 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -18,6 +18,11 @@ namespace git , repo_(&repo) {} + Tree::Tree() + : tree_(nullptr) + , repo_(nullptr) + {} + Tree::Tree(Tree && other) : tree_(other.tree_) , repo_(other.repo_) @@ -52,12 +57,12 @@ namespace git Tree::BorrowedEntry Tree::operator[] (size_t i) const { - return git_tree_entry_byindex(tree_, i); + return BorrowedEntry(git_tree_entry_byindex(tree_, i)); } Tree::BorrowedEntry Tree::operator[] (std::string const & filename) const { - return git_tree_entry_byname(tree_, filename.c_str()); + return BorrowedEntry(git_tree_entry_byname(tree_, filename.c_str())); } Tree::OwnedEntry Tree::find(const char * path) const @@ -91,4 +96,9 @@ namespace git git_tree_entry_to_object(&obj, repo_->ptr(), entry_); return Object(obj, *repo_).to_tree(); } + + const char * Tree::BorrowedEntry::name() const + { + return git_tree_entry_name(entry_); + } } From 0d96924cc7cd78ac5c6679a0875babe91a169ad4 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 25 Nov 2015 17:26:11 +0300 Subject: [PATCH 027/171] + method Tree::BorrowedEntry::id() --- include/git2cpp/tree.h | 3 ++- src/tree.cpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index dcca204..172c4a4 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -10,7 +10,8 @@ namespace git { struct BorrowedEntry { - const char * name() const; + const char * name() const; + git_oid const & id() const; git_tree_entry const * ptr() const { return entry_; } diff --git a/src/tree.cpp b/src/tree.cpp index 1fd3cab..c17abc3 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -101,4 +101,9 @@ namespace git { return git_tree_entry_name(entry_); } + + git_oid const & Tree::BorrowedEntry::id() const + { + return *git_tree_entry_id(entry_); + } } From 9836328e37b9883c2e34dd7546a3d8609868d1b5 Mon Sep 17 00:00:00 2001 From: Ivan Gromakovsky Date: Wed, 25 Nov 2015 20:19:49 +0300 Subject: [PATCH 028/171] Fix compilation with Boost 1.59 --- src/repo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/repo.cpp b/src/repo.cpp index cd190ab..6bdc7a9 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -9,6 +9,7 @@ extern "C" } #include +#include #include "git2cpp/repo.h" #include "git2cpp/error.h" From da3f5a90bc971386698a5820d135e23fe3288c14 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 4 Dec 2015 16:03:39 +0300 Subject: [PATCH 029/171] boost 1.59 compilation fix --- examples/log.cpp | 1 + examples/rev-parse.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/log.cpp b/examples/log.cpp index c2e871f..36009c7 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -4,6 +4,7 @@ #include #include +#include #include diff --git a/examples/rev-parse.cpp b/examples/rev-parse.cpp index c707d28..257f040 100644 --- a/examples/rev-parse.cpp +++ b/examples/rev-parse.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "git2cpp/initializer.h" #include "git2cpp/repo.h" From 8a1f6d40b1577d405eaca298f270e07a50044507 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 4 Dec 2015 16:47:22 +0300 Subject: [PATCH 030/171] remove method 'Repository::ptr()' (*) + struct Submodule (*) lookup methods (git_{tree, commit, tag, blob, submodule, ...}_lookup) moved from classes 'Tree', 'Commit', 'Tag', 'Blob', ... to class 'Repository' implemenetation (*) 'diff' methods moved to class 'Repositry' implementation --- examples/diff.cpp | 12 +-- examples/log.cpp | 4 +- examples/status.cpp | 35 ++++----- include/git2cpp/blob.h | 1 - include/git2cpp/commit.h | 9 ++- include/git2cpp/diff.h | 68 +++++++---------- include/git2cpp/error.h | 14 ++++ include/git2cpp/repo.h | 22 +++--- include/git2cpp/revwalker.h | 11 ++- include/git2cpp/submodule.h | 47 ++++++++++++ include/git2cpp/tag.h | 4 +- include/git2cpp/tree.h | 13 ++-- src/blob.cpp | 8 -- src/commit.cpp | 15 +--- src/diff.cpp | 37 +++------- src/repo.cpp | 142 ++++++++++++++++++++++++++---------- src/revwalker.cpp | 10 +-- src/submodule.cpp | 40 ++++++++++ src/tag.cpp | 10 +-- src/tree.cpp | 21 +++--- 20 files changed, 309 insertions(+), 214 deletions(-) create mode 100644 include/git2cpp/submodule.h create mode 100644 src/submodule.cpp diff --git a/examples/diff.cpp b/examples/diff.cpp index 5d8658f..237cfe9 100644 --- a/examples/diff.cpp +++ b/examples/diff.cpp @@ -75,21 +75,21 @@ enum { /* --cached */ /* nothing */ -Diff calc_diff(Repository & repo, Tree & t1, Tree & t2, bool cached, git_diff_options const & opts) +Diff calc_diff(Repository const & repo, Tree & t1, Tree & t2, bool cached, git_diff_options const & opts) { if (t1 && t2) - return git::diff(repo, t1, t2, opts); + return repo.diff(t1, t2, opts); else if (t1 && cached) - return diff_to_index(repo, t1, opts); + return repo.diff_to_index(t1, opts); else if (t1) - return std::move(diff_to_index(repo, t1, opts).merge(diff_index_to_workdir(repo, opts))); + return std::move(repo.diff_to_index(t1, opts).merge(repo.diff_index_to_workdir(opts))); else if (cached) { auto tree = resolve_to_tree(repo, "HEAD"); - return diff_to_index(repo, tree, opts); + return repo.diff_to_index(tree, opts); } else - return diff_index_to_workdir(repo, opts); + return repo.diff_index_to_workdir(opts); } int main(int argc, char *argv[]) diff --git a/examples/log.cpp b/examples/log.cpp index 36009c7..2e8d370 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -209,7 +209,7 @@ static int match_with_parent(git::Commit const & commit, int i, git_diff_options auto parent = commit.parent(i); auto c_tree = commit.tree(); auto p_tree = parent.tree(); - auto diff = git::diff(commit.owner(), p_tree, c_tree, opts); + auto diff = commit.owner().diff(p_tree, c_tree, opts); return diff.deltas_num() > 0; } @@ -368,7 +368,7 @@ int main(int argc, char *argv[]) a = commit.parent(0).tree(); } - git::diff(commit.owner(), a, b, diffopts).print(git::Diff::format::patch, print_diff); + s.repo->diff(a, b, diffopts).print(git::Diff::format::patch, print_diff); } } diff --git a/examples/status.cpp b/examples/status.cpp index 4d16888..4235636 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -264,25 +264,22 @@ void print_short(Repository const & repo, Status const & status) if (istatus == '?' && wstatus == '?') continue; - if (s->index_to_workdir && - s->index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT) - { - git_submodule *sm = NULL; - unsigned int smstatus = 0; - - if (!repo.submodule_lookup(sm, s->index_to_workdir->new_file.path) && - !git_submodule_status(&smstatus, repo.ptr(), git_submodule_name(sm), git_submodule_ignore(sm))) - { - if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED) - extra = " (new commits)"; - else if (smstatus & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) - extra = " (modified content)"; - else if (smstatus & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) - extra = " (modified content)"; - else if (smstatus & GIT_SUBMODULE_STATUS_WD_UNTRACKED) - extra = " (untracked content)"; - } - } + if (s->index_to_workdir && s->index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT) + { + auto sm = repo.submodule_lookup(s->index_to_workdir->new_file.path); + auto smstatus = sm.get_status(); + + typedef Submodule::status status; + + if (contains(smstatus, status::wd_modified)) + extra = " (new commits)"; + else if (contains(smstatus, status::wd_index_modified)) + extra = " (modified content)"; + else if (contains(smstatus, status::wd_wd_modified)) + extra = " (modified content)"; + else if (contains(smstatus, status::wd_untracked)) + extra = " (untracked content)"; + } if (s->head_to_index) { a = s->head_to_index->old_file.path; diff --git a/include/git2cpp/blob.h b/include/git2cpp/blob.h index d87f9b2..171d62d 100644 --- a/include/git2cpp/blob.h +++ b/include/git2cpp/blob.h @@ -11,7 +11,6 @@ namespace git struct Blob { explicit Blob(git_blob *); - Blob(git_oid const & oid, git_repository * repo); ~Blob(); std::size_t size() const; diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 660071f..2a3f614 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -12,8 +12,6 @@ namespace git struct Commit { - git_commit const * ptr() const { return commit_; } - size_t parents_num() const; Commit parent(size_t i) const; git_oid const & parent_id(size_t i) const; @@ -35,8 +33,6 @@ namespace git git_oid merge_base(size_t p1, size_t p2) const; - Commit(git_oid const & oid, Repository const & repo); - Commit(git_commit * commit, Repository const & repo) : commit_(commit) , repo_(&repo) @@ -56,6 +52,11 @@ namespace git ~Commit(); + private: + friend struct Repository; + + git_commit const * ptr() const { return commit_; } + private: git_commit * commit_ = nullptr; Repository const * repo_ = nullptr; diff --git a/include/git2cpp/diff.h b/include/git2cpp/diff.h index f8cdd82..1751980 100644 --- a/include/git2cpp/diff.h +++ b/include/git2cpp/diff.h @@ -2,60 +2,46 @@ #include -extern "C" -{ #include -} namespace git { - struct Repository; - - struct Diff - { - size_t deltas_num() const; - - void find_similar(git_diff_find_options & findopts) - { - git_diff_find_similar(diff_, &findopts); - } - - Diff& merge(Diff const & other); + struct Diff + { + size_t deltas_num() const; - enum class format - { - patch, patch_header, raw, name_only, name_status - }; + void find_similar(git_diff_find_options &); - typedef - std::function - print_callback_t; + Diff& merge(Diff const & other); - void print(format, print_callback_t print_callback) const; + enum class format + { + patch, patch_header, raw, name_only, name_status + }; - explicit Diff(git_diff * diff) - : diff_(diff) - {} + typedef + std::function + print_callback_t; - ~Diff() { git_diff_free(diff_); } + void print(format, print_callback_t print_callback) const; - Diff (Diff const &) = delete; - Diff& operator = (Diff const &) = delete; + explicit Diff(git_diff * diff) + : diff_(diff) + {} - Diff(Diff && other) - : diff_(other.diff_) - { - other.diff_ = nullptr; - } + ~Diff(); - private: - git_diff * diff_; - }; + Diff (Diff const &) = delete; + Diff& operator = (Diff const &) = delete; - struct Tree; + Diff(Diff && other) + : diff_(other.diff_) + { + other.diff_ = nullptr; + } - Diff diff (Repository const &, Tree & a, Tree & b, git_diff_options const &); - Diff diff_to_index (Repository const &, Tree &, git_diff_options const &); - Diff diff_index_to_workdir (Repository const &, git_diff_options const &); + private: + git_diff * diff_; + }; } diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 7f94710..623b3f5 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -57,6 +57,20 @@ namespace git {} }; + struct blob_lookup_error : error_t + { + explicit blob_lookup_error(git_oid const & id) + : error_t("Could not lookup blob " + id_to_str(id)) + {} + }; + + struct submodule_lookup_error : error_t + { + explicit submodule_lookup_error(std::string const & name) + : error_t("Counld not lookup submodule " + name) + {} + }; + struct commit_parent_error : error_t { explicit commit_parent_error(git_oid const & id) diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index f626e0c..f3d2934 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -3,11 +3,6 @@ #include #include -extern "C" -{ -#include -} - #include "commit.h" #include "index.h" #include "odb.h" @@ -19,6 +14,8 @@ extern "C" #include "tag.h" #include "blob.h" #include "str_array.h" +#include "diff.h" +#include "submodule.h" namespace git { @@ -32,14 +29,13 @@ namespace git struct Repository { - git_repository * ptr() const { return repo_; } - Commit commit_lookup(git_oid const & oid) const; Tree tree_lookup (git_oid const & oid) const; Tag tag_lookup (git_oid const & oid) const; Blob blob_lookup (git_oid const & oid) const; - git_oid merge_base(Revspec::Range const & range) const; + git_oid merge_base(Revspec::Range const & range) const; + git_oid merge_base(git_oid const &, git_oid const &) const; Revspec revparse (const char * spec) const; Revspec revparse_single (const char * spec) const; @@ -48,11 +44,16 @@ namespace git git_status_t file_status(const char * filepath) const; + Object entry_to_object(Tree::OwnedEntry) const; Object entry_to_object(Tree::BorrowedEntry) const; Index index() const; Odb odb() const; + Diff diff (Tree &, Tree &, git_diff_options const &) const; + Diff diff_to_index (Tree &, git_diff_options const &) const; + Diff diff_index_to_workdir ( git_diff_options const &) const; + Signature signature() const; Status status(git_status_options const &) const; @@ -66,7 +67,7 @@ namespace git Reference head() const; Reference ref(const char * name) const; - int submodule_lookup(git_submodule *&, const char * name) const; + Submodule submodule_lookup(const char * name) const; const char * path() const; const char * workdir() const; @@ -91,8 +92,7 @@ namespace git struct init_tag {}; static init_tag init; Repository(std::string const & dir, init_tag); - Repository(std::string const & dir, init_tag, - git_repository_init_options opts); + Repository(std::string const & dir, init_tag, git_repository_init_options opts); Repository (Repository const &) = delete; Repository& operator = (Repository const &) = delete; diff --git a/include/git2cpp/revwalker.h b/include/git2cpp/revwalker.h index f1b03ed..5b74b46 100644 --- a/include/git2cpp/revwalker.h +++ b/include/git2cpp/revwalker.h @@ -1,21 +1,20 @@ #pragma once -extern "C" -{ #include -} #include "commit.h" -struct git_repository; - namespace git { struct Repository; struct RevWalker { - explicit RevWalker(Repository const & repo); + RevWalker(git_revwalk * walker, Repository const & repo) + : walker_(walker) + , repo_(repo) + {} + ~RevWalker(); enum class sorting : unsigned int diff --git a/include/git2cpp/submodule.h b/include/git2cpp/submodule.h new file mode 100644 index 0000000..f79536b --- /dev/null +++ b/include/git2cpp/submodule.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +struct git_submodule; +struct git_repository; + +namespace git +{ + struct Submodule + { + Submodule(git_submodule *, git_repository *); + ~Submodule(); + + Submodule (Submodule const &) = delete; + Submodule& operator = (Submodule const &) = delete; + + Submodule (Submodule &&); + Submodule& operator = (Submodule &&); + + enum class status : unsigned int + { + in_head = GIT_SUBMODULE_STATUS_IN_HEAD, + in_index = GIT_SUBMODULE_STATUS_IN_INDEX, + in_config = GIT_SUBMODULE_STATUS_IN_CONFIG, + in_wd = GIT_SUBMODULE_STATUS_IN_WD, + index_added = GIT_SUBMODULE_STATUS_INDEX_ADDED, + index_deleted = GIT_SUBMODULE_STATUS_INDEX_DELETED, + index_modified = GIT_SUBMODULE_STATUS_INDEX_MODIFIED, + wd_uninitialized = GIT_SUBMODULE_STATUS_WD_UNINITIALIZED, + wd_added = GIT_SUBMODULE_STATUS_WD_ADDED, + wd_deleted = GIT_SUBMODULE_STATUS_WD_DELETED, + wd_modified = GIT_SUBMODULE_STATUS_WD_MODIFIED, + wd_index_modified = GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED, + wd_wd_modified = GIT_SUBMODULE_STATUS_WD_WD_MODIFIED, + wd_untracked = GIT_SUBMODULE_STATUS_WD_UNTRACKED, + }; + + friend bool contains (status set, status element); + + status get_status() const; + + private: + git_submodule * sm_; + git_repository * repo_; + }; +} diff --git a/include/git2cpp/tag.h b/include/git2cpp/tag.h index 055a94f..def4dd2 100644 --- a/include/git2cpp/tag.h +++ b/include/git2cpp/tag.h @@ -6,11 +6,9 @@ struct git_tag; namespace git { - struct Repository; - struct Tag { - Tag(git_oid const & oid, Repository const &); + Tag(git_tag *, Repository const &); ~Tag(); Tag& operator = (Tag const &) = delete; diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index 172c4a4..633c765 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -13,15 +13,16 @@ namespace git const char * name() const; git_oid const & id() const; - git_tree_entry const * ptr() const { return entry_; } - private: friend struct Tree; + friend struct Repository; explicit BorrowedEntry(git_tree_entry const * entry) : entry_(entry) {} + git_tree_entry const * ptr() const { return entry_; } + private: git_tree_entry const * entry_; }; @@ -36,13 +37,16 @@ namespace git OwnedEntry (OwnedEntry &&); OwnedEntry& operator = (OwnedEntry &&); - Tree as_tree() /*&&*/; + Tree to_tree() /*&&*/; private: friend struct Tree; + friend struct Repository; OwnedEntry(git_tree_entry * entry, Repository const & repo); + git_tree_entry const * ptr() const { return entry_; } + private: git_tree_entry * entry_; Repository const * repo_; @@ -61,8 +65,7 @@ namespace git OwnedEntry find(const char * path) const; - Tree(git_oid const &, Repository const &); - Tree(git_tree *, Repository const &); + Tree(git_tree *, Repository const &); Tree(); ~Tree(); diff --git a/src/blob.cpp b/src/blob.cpp index 07864f5..118c4a7 100644 --- a/src/blob.cpp +++ b/src/blob.cpp @@ -1,9 +1,6 @@ #include "git2cpp/blob.h" -extern "C" -{ #include -} namespace git { @@ -11,11 +8,6 @@ namespace git : blob_(blob) {} - Blob::Blob(git_oid const & oid, git_repository *repo) - { - git_blob_lookup(&blob_, repo, &oid); - } - Blob::Blob(Blob && other) : blob_(other.blob_) { diff --git a/src/commit.cpp b/src/commit.cpp index 1627ea8..633a328 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -2,11 +2,8 @@ #include "git2cpp/repo.h" #include "git2cpp/error.h" -extern "C" -{ #include #include -} namespace git { @@ -68,17 +65,7 @@ namespace git git_oid Commit::merge_base(size_t p1, size_t p2) const { - git_oid res; - if (git_merge_base(&res, repo_->ptr(), &parent_id(p1), &parent_id(p2))) - throw merge_base_error(parent_id(p1), parent_id(p2)); - return res; - } - - Commit::Commit(git_oid const & oid, Repository const & repo) - : repo_(&repo) - { - if (git_commit_lookup(&commit_, repo.ptr(), &oid)) - throw commit_lookup_error(oid); + return repo_->merge_base(parent_id(p1), parent_id(p2)); } Commit::~Commit() { git_commit_free(commit_); } diff --git a/src/diff.cpp b/src/diff.cpp index 8fffa8b..d9245f4 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -1,35 +1,9 @@ -#include - #include "git2cpp/diff.h" -#include "git2cpp/tree.h" -#include "git2cpp/repo.h" + +#include namespace git { - Diff diff(Repository const & repo, Tree & a, Tree & b, git_diff_options const & opts) - { - git_diff * diff; - auto op_res = git_diff_tree_to_tree(&diff, repo.ptr(), a.ptr(), b.ptr(), &opts); - assert(op_res == 0); - return Diff(diff); - } - - Diff diff_to_index(Repository const & repo, Tree & t, git_diff_options const & opts) - { - git_diff * diff; - auto op_res = git_diff_tree_to_index(&diff, repo.ptr(), t.ptr(), nullptr, &opts); - assert(op_res == 0); - return Diff(diff); - } - - Diff diff_index_to_workdir(Repository const & repo, git_diff_options const & opts) - { - git_diff * diff; - auto op_res = git_diff_index_to_workdir(&diff, repo.ptr(), nullptr, &opts); - assert(op_res == 0); - return Diff(diff); - } - namespace { int apply_callback ( git_diff_delta const * delta @@ -57,6 +31,13 @@ namespace git } } + Diff::~Diff() { git_diff_free(diff_); } + + void Diff::find_similar(git_diff_find_options & findopts) + { + git_diff_find_similar(diff_, &findopts); + } + Diff& Diff::merge(Diff const & other) { git_diff_merge(diff_, other.diff_); diff --git a/src/repo.cpp b/src/repo.cpp index 6bdc7a9..f286237 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -1,12 +1,12 @@ -extern "C" -{ #include #include #include #include #include #include -} +#include +#include +#include #include #include @@ -38,8 +38,7 @@ namespace git throw repository_init_error(dir); } - Repository::Repository(std::string const & dir, init_tag, - git_repository_init_options opts) + Repository::Repository(std::string const & dir, init_tag, git_repository_init_options opts) { if (git_repository_init_ext(&repo_, dir.c_str(), &opts) < 0) throw repository_init_error(dir); @@ -62,22 +61,38 @@ namespace git Commit Repository::commit_lookup(git_oid const & oid) const { - return Commit(oid, *this); + git_commit * commit; + if (git_commit_lookup(&commit, repo_, &oid)) + throw commit_lookup_error(oid); + else + return { commit, *this }; } Tree Repository::tree_lookup(git_oid const & oid) const { - return Tree(oid, *this); + git_tree * tree; + if (git_tree_lookup(&tree, repo_, &oid)) + throw tree_lookup_error(oid); + else + return { tree, *this }; } Tag Repository::tag_lookup(git_oid const & oid) const { - return Tag(oid, *this); + git_tag * tag; + if (git_tag_lookup(&tag, repo_, &oid)) + throw tag_lookup_error(oid); + else + return { tag, *this }; } Blob Repository::blob_lookup(git_oid const & oid) const { - return Blob(oid, repo_); + git_blob * blob; + if (git_blob_lookup(&blob, repo_, &oid)) + throw blob_lookup_error(oid); + else + return Blob(blob); } Revspec Repository::revparse(const char * spec) const @@ -85,7 +100,8 @@ namespace git git_revspec revspec; if (git_revparse(&revspec, repo_, spec)) throw revparse_error(spec); - return Revspec(revspec, *this); + else + return { revspec, *this }; } Revspec Repository::revparse_single(const char * spec) const @@ -124,11 +140,10 @@ namespace git struct branch_iterator { - branch_iterator(Repository const & repo, branch_type type) - : type_(convert(type)), - m_DoneFlag(false) + branch_iterator(git_repository * repo, branch_type type) + : type_(convert(type)) { - git_branch_iterator_new(&base_, repo.ptr(), type_); + git_branch_iterator_new(&base_, repo, type_); ++(*this); } @@ -137,24 +152,23 @@ namespace git git_branch_iterator_free(base_); } - explicit operator bool () const { return ref_.is_initialized() && !m_DoneFlag; } + explicit operator bool () const { return ref_.is_initialized(); } void operator ++ () { git_branch_t type; git_reference * ref; - const int err = git_branch_next(&ref, &type, base_); - if (err == 0) + switch (git_branch_next(&ref, &type, base_)) { + case GIT_OK: assert(type == type_); ref_ = boost::in_place(ref); - } - else if (err == GIT_ITEROVER) - { - m_DoneFlag = true; - } - else - { + break; + case GIT_ITEROVER: + ref_ = boost::none; + break; + default: + ref_ = boost::none; throw std::logic_error("unknown git_branch_next error"); } } @@ -181,44 +195,51 @@ namespace git git_branch_t type_; git_branch_iterator * base_; boost::optional ref_; - bool m_DoneFlag; }; std::vector Repository::branches(branch_type type) const { std::vector res; - for (branch_iterator it(*this, type); it; ++it) + for (branch_iterator it(repo_, type); it; ++it) res.push_back(it->name()); return res; } RevWalker Repository::rev_walker() const { - return RevWalker(*this); + git_revwalk * walker; + if (git_revwalk_new(&walker, repo_)) + throw revwalk_new_error(); + else + return { walker, *this }; } - git_oid Repository::merge_base(Revspec::Range const & range) const + git_oid Repository::merge_base(git_oid const & a, git_oid const & b) const { git_oid res; - if (git_merge_base(&res, repo_, &range.from.id(), &range.to.id())) - throw merge_base_error(range.from.id(), range.to.id()); + if (git_merge_base(&res, repo_, &a, &b)) + throw merge_base_error(a, b); return res; } + git_oid Repository::merge_base(Revspec::Range const & range) const + { + return merge_base(range.from.id(), range.to.id()); + } + Reference Repository::head() const { git_reference * head; - switch (auto error = git_repository_head(&head, repo_)) + switch (git_repository_head(&head, repo_)) { + case GIT_OK: + return Reference(head); case GIT_EUNBORNBRANCH: throw non_existing_branch_error(); case GIT_ENOTFOUND: throw missing_head_error(); default: - if (error == 0) - return Reference(head); - else - throw unknown_get_current_branch_error(); + throw unknown_get_current_branch_error(); } } @@ -241,9 +262,13 @@ namespace git return StrArray(str_array); } - int Repository::submodule_lookup(git_submodule *& sm, const char * name) const + Submodule Repository::submodule_lookup(const char * name) const { - return git_submodule_lookup(&sm, repo_, name); + git_submodule * sm; + if (git_submodule_lookup(&sm, repo_, name)) + throw submodule_lookup_error(name); + else + return { sm, repo_ }; } const char * Repository::path() const @@ -293,15 +318,52 @@ namespace git return res; } + namespace + { + Object tree_entry_to_object(git_tree_entry const * entry, Repository const & repo, git_repository * repo_ptr) + { + git_object * obj; + git_tree_entry_to_object(&obj, repo_ptr, entry); + return Object(obj, repo); + } + } + Object Repository::entry_to_object(Tree::BorrowedEntry entry) const { - git_object * obj; - git_tree_entry_to_object(&obj, repo_, entry.ptr()); - return Object(obj, *this); + return tree_entry_to_object(entry.ptr(), *this, repo_); + } + + Object Repository::entry_to_object(Tree::OwnedEntry entry) const + { + return tree_entry_to_object(entry.ptr(), *this, repo_); } Object revparse_single(Repository const & repo, const char * spec) { return std::move(*repo.revparse_single(spec).single()); } + + Diff Repository::diff(Tree & a, Tree & b, git_diff_options const & opts) const + { + git_diff * diff; + auto op_res = git_diff_tree_to_tree(&diff, repo_, a.ptr(), b.ptr(), &opts); + assert(op_res == 0); + return Diff(diff); + } + + Diff Repository::diff_to_index(Tree & t, git_diff_options const & opts) const + { + git_diff * diff; + auto op_res = git_diff_tree_to_index(&diff, repo_, t.ptr(), nullptr, &opts); + assert(op_res == 0); + return Diff(diff); + } + + Diff Repository::diff_index_to_workdir(git_diff_options const & opts) const + { + git_diff * diff; + auto op_res = git_diff_index_to_workdir(&diff, repo_, nullptr, &opts); + assert(op_res == 0); + return Diff(diff); + } } diff --git a/src/revwalker.cpp b/src/revwalker.cpp index a25255f..e12d565 100644 --- a/src/revwalker.cpp +++ b/src/revwalker.cpp @@ -1,17 +1,9 @@ - -#include "git2cpp/error.h" #include "git2cpp/revwalker.h" +#include "git2cpp/error.h" #include "git2cpp/repo.h" namespace git { - RevWalker::RevWalker(Repository const & repo) - : repo_(repo) - { - if (git_revwalk_new(&walker_, repo.ptr())) - throw revwalk_new_error(); - } - RevWalker::~RevWalker() { git_revwalk_free(walker_); diff --git a/src/submodule.cpp b/src/submodule.cpp new file mode 100644 index 0000000..190c16a --- /dev/null +++ b/src/submodule.cpp @@ -0,0 +1,40 @@ +#include "git2cpp/submodule.h" + +#include + +#include "git2cpp/error.h" + +namespace git +{ + Submodule::Submodule(git_submodule * sm, git_repository * repo) + : sm_(sm) + , repo_(repo) + {} + + Submodule::~Submodule() + { + git_submodule_free(sm_); + } + + Submodule::status Submodule::get_status() const + { + unsigned int res; + if (auto err = git_submodule_status(&res, repo_, git_submodule_name(sm_), git_submodule_ignore(sm_))) + throw error_t("git_submodule_status failed with error code " + std::to_string(err)); + else + return static_cast(res); + } + + namespace + { + unsigned int to_raw(Submodule::status s) + { + return static_cast(s); + } + } + + bool contains(Submodule::status set, Submodule::status element) + { + return to_raw(set) & to_raw(element); + } +} diff --git a/src/tag.cpp b/src/tag.cpp index cd56f99..4e029e9 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -6,12 +6,10 @@ namespace git { - Tag::Tag(git_oid const & oid, Repository const & repo) - : repo_(repo) - { - if (git_tag_lookup(&tag_, repo.ptr(), &oid)) - throw tag_lookup_error(oid); - } + Tag::Tag(git_tag * tag, Repository const & repo) + : tag_(tag) + , repo_(repo) + {} Tag::~Tag() { diff --git a/src/tree.cpp b/src/tree.cpp index c17abc3..a3ca65f 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -6,13 +6,6 @@ namespace git { - Tree::Tree(git_oid const & oid, Repository const & repo) - : repo_(&repo) - { - if (git_tree_lookup(&tree_, repo.ptr(), &oid)) - throw tree_lookup_error(oid); - } - Tree::Tree(git_tree * tree, Repository const & repo) : tree_(tree) , repo_(&repo) @@ -90,11 +83,17 @@ namespace git git_tree_entry_free(entry_); } - Tree Tree::OwnedEntry::as_tree() + Tree::OwnedEntry::OwnedEntry(OwnedEntry && other) + : entry_(other.entry_) + , repo_(other.repo_) + { + other.entry_ = nullptr; + other.repo_ = nullptr; + } + + Tree Tree::OwnedEntry::to_tree() /* && */ { - git_object * obj; - git_tree_entry_to_object(&obj, repo_->ptr(), entry_); - return Object(obj, *repo_).to_tree(); + return repo_->entry_to_object(std::move(*this)).to_tree(); } const char * Tree::BorrowedEntry::name() const From b683bd0e5d7ea436a22e57866de321026a4b5dd1 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 7 Dec 2015 16:53:46 +0300 Subject: [PATCH 031/171] lifetime bug fix --- src/tree.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tree.cpp b/src/tree.cpp index a3ca65f..b67684f 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -93,7 +93,8 @@ namespace git Tree Tree::OwnedEntry::to_tree() /* && */ { - return repo_->entry_to_object(std::move(*this)).to_tree(); + auto const & repo = *repo_; + return repo.entry_to_object(std::move(*this)).to_tree(); } const char * Tree::BorrowedEntry::name() const From 8b65ea864b30e7b7a111879ed815cc1ba1cfad9b Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 25 Dec 2015 19:14:37 +0300 Subject: [PATCH 032/171] Add one more check --- src/tree.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tree.cpp b/src/tree.cpp index b67684f..4eee6f0 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -55,7 +55,10 @@ namespace git Tree::BorrowedEntry Tree::operator[] (std::string const & filename) const { - return BorrowedEntry(git_tree_entry_byname(tree_, filename.c_str())); + if (auto entry = git_tree_entry_byname(tree_, filename.c_str())) + return BorrowedEntry(entry); + else + throw file_not_found_error(filename.c_str()); } Tree::OwnedEntry Tree::find(const char * path) const From 61c5c221c919b05729f65c6c81d6317270eeb51f Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 9 Jan 2016 19:47:08 +0300 Subject: [PATCH 033/171] code format --- include/git2cpp/revwalker.h | 96 ++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/include/git2cpp/revwalker.h b/include/git2cpp/revwalker.h index 5b74b46..a000420 100644 --- a/include/git2cpp/revwalker.h +++ b/include/git2cpp/revwalker.h @@ -6,52 +6,52 @@ namespace git { - struct Repository; - - struct RevWalker - { - RevWalker(git_revwalk * walker, Repository const & repo) - : walker_(walker) - , repo_(repo) - {} - - ~RevWalker(); - - enum class sorting : unsigned int - { - none = GIT_SORT_NONE, - topological = GIT_SORT_TOPOLOGICAL, - time = GIT_SORT_TIME, - reverse = GIT_SORT_REVERSE - }; - - friend sorting operator ~ (sorting); - friend sorting operator | (sorting, sorting); - friend sorting operator & (sorting, sorting); - friend sorting operator ^ (sorting, sorting); - - void sort(sorting); - void simplify_first_parent(); - - void push_head() const; - void hide(git_oid const &) const; - void push(git_oid const &) const; - - Commit next() const; - bool next(char * id_buffer) const; - - RevWalker (RevWalker const &) = delete; - RevWalker& operator = (RevWalker const &) = delete; - - RevWalker(RevWalker && other) - : walker_(other.walker_) - , repo_(other.repo_) - { - other.walker_ = nullptr; - } - - private: - git_revwalk * walker_; - Repository const & repo_; - }; + struct Repository; + + struct RevWalker + { + RevWalker(git_revwalk * walker, Repository const & repo) + : walker_(walker) + , repo_(repo) + {} + + ~RevWalker(); + + enum class sorting : unsigned int + { + none = GIT_SORT_NONE, + topological = GIT_SORT_TOPOLOGICAL, + time = GIT_SORT_TIME, + reverse = GIT_SORT_REVERSE + }; + + friend sorting operator ~ (sorting); + friend sorting operator | (sorting, sorting); + friend sorting operator & (sorting, sorting); + friend sorting operator ^ (sorting, sorting); + + void sort(sorting); + void simplify_first_parent(); + + void push_head() const; + void hide(git_oid const &) const; + void push(git_oid const &) const; + + Commit next() const; + bool next(char * id_buffer) const; + + RevWalker (RevWalker const &) = delete; + RevWalker& operator = (RevWalker const &) = delete; + + RevWalker(RevWalker && other) + : walker_(other.walker_) + , repo_(other.repo_) + { + other.walker_ = nullptr; + } + + private: + git_revwalk * walker_; + Repository const & repo_; + }; } From 08179d66c863a5d0da09ea44c96f39db49978002 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 9 Jan 2016 23:55:22 +0300 Subject: [PATCH 034/171] + struct 'tagged_mask_t' --- include/git2cpp/tagged_mask.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 include/git2cpp/tagged_mask.h diff --git a/include/git2cpp/tagged_mask.h b/include/git2cpp/tagged_mask.h new file mode 100644 index 0000000..5ee7ea4 --- /dev/null +++ b/include/git2cpp/tagged_mask.h @@ -0,0 +1,27 @@ +#pragma once + +namespace git +{ + template + struct tagged_mask_t + { + typedef tagged_mask_t self_t; + + explicit tagged_mask_t(RawType value) + : value_(value) + {} + + RawType value() const { return value_; } + + operator bool() const { return value_; } + + friend self_t operator ~ (self_t x) { return self_t(~x.value_); } + + friend self_t operator | (self_t x, self_t y) { return self_t(x.value_ | y.value_); } + friend self_t operator & (self_t x, self_t y) { return self_t(x.value_ & y.value_); } + friend self_t operator ^ (self_t x, self_t y) { return self_t(x.value_ ^ y.value_); } + + private: + RawType value_; + }; +} From 8fce56184f145fc30f70815baaf0b340d739e6a5 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 00:01:18 +0300 Subject: [PATCH 035/171] remove #include from public includes --- examples/commit-graph-generator.cpp | 2 +- examples/general.cpp | 2 +- examples/log.cpp | 16 +++++------ examples/rev-list.cpp | 2 +- include/git2cpp/revwalker.h | 29 +++++++++---------- src/revwalker.cpp | 43 +++++++++-------------------- 6 files changed, 37 insertions(+), 57 deletions(-) diff --git a/examples/commit-graph-generator.cpp b/examples/commit-graph-generator.cpp index db4ae72..d7ef2df 100644 --- a/examples/commit-graph-generator.cpp +++ b/examples/commit-graph-generator.cpp @@ -9,7 +9,7 @@ namespace { void operator() (git::RevWalker & walker) { - walker.sort(git::RevWalker::sorting::topological); + walker.sort(git::revwalker::sorting::topological); walker.simplify_first_parent(); while (git::Commit commit = walker.next()) diff --git a/examples/general.cpp b/examples/general.cpp index 16be78a..d4aac54 100644 --- a/examples/general.cpp +++ b/examples/general.cpp @@ -355,7 +355,7 @@ int main (int argc, char** argv) // branch1..branch2`, you would push the oid of `branch2` and hide the oid // of `branch1`. RevWalker walk = repo.rev_walker(); - walk.sort(RevWalker::sorting::topological | RevWalker::sorting::reverse); + walk.sort(revwalker::sorting::topological | revwalker::sorting::reverse); walk.push(oid); // Now that we have the starting point pushed onto the walker, we start diff --git a/examples/log.cpp b/examples/log.cpp index 2e8d370..b06c9cc 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -32,10 +32,10 @@ struct log_state boost::optional repo; std::unique_ptr walker; int hide = 0; - git::RevWalker::sorting sorting = git::RevWalker::sorting::time; + git::revwalker::sorting::type sorting = git::revwalker::sorting::time; }; -static void set_sorting(struct log_state *s, git::RevWalker::sorting sort_mode) +static void set_sorting(struct log_state *s, git::revwalker::sorting::type sort_mode) { if (!s->repo) { s->repo = boost::in_place(s->repodir); @@ -44,10 +44,10 @@ static void set_sorting(struct log_state *s, git::RevWalker::sorting sort_mode) if (!s->walker) s->walker.reset(new git::RevWalker(s->repo->rev_walker())); - if (sort_mode == git::RevWalker::sorting::reverse) - s->sorting = s->sorting ^ git::RevWalker::sorting::reverse; + if (sort_mode == git::revwalker::sorting::reverse) + s->sorting = s->sorting ^ git::revwalker::sorting::reverse; else - s->sorting = sort_mode | (s->sorting & git::RevWalker::sorting::reverse); + s->sorting = sort_mode | (s->sorting & git::revwalker::sorting::reverse); s->walker->sort(s->sorting); } @@ -249,11 +249,11 @@ int parse_options ( int argc, char *argv[] break; } else if (!strcmp(a, "--date-order")) - set_sorting(&s, git::RevWalker::sorting::time); + set_sorting(&s, git::revwalker::sorting::time); else if (!strcmp(a, "--topo-order")) - set_sorting(&s, git::RevWalker::sorting::topological); + set_sorting(&s, git::revwalker::sorting::topological); else if (!strcmp(a, "--reverse")) - set_sorting(&s, git::RevWalker::sorting::reverse); + set_sorting(&s, git::revwalker::sorting::reverse); else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) s.repodir = a + strlen("--git-dir="); else if (match_int_arg(&opt.skip, a, "--skip=", 0)) diff --git a/examples/rev-list.cpp b/examples/rev-list.cpp index d1c8f70..253c40b 100644 --- a/examples/rev-list.cpp +++ b/examples/rev-list.cpp @@ -45,7 +45,7 @@ void push_range(Repository const & repo, RevWalker const & walk, const char *ran void revwalk_parseopts(Repository const & repo, RevWalker & walk, int nopts, char **opts) { - typedef RevWalker::sorting sort; + namespace sort = revwalker::sorting; auto sorting = sort::none; int hide = 0; diff --git a/include/git2cpp/revwalker.h b/include/git2cpp/revwalker.h index a000420..56377b2 100644 --- a/include/git2cpp/revwalker.h +++ b/include/git2cpp/revwalker.h @@ -1,13 +1,23 @@ #pragma once -#include - +#include "tagged_mask.h" #include "commit.h" namespace git { struct Repository; + namespace revwalker { + namespace sorting + { + typedef tagged_mask_t type; + + extern const type none; + extern const type topological; + extern const type time; + extern const type reverse; + }} + struct RevWalker { RevWalker(git_revwalk * walker, Repository const & repo) @@ -17,20 +27,7 @@ namespace git ~RevWalker(); - enum class sorting : unsigned int - { - none = GIT_SORT_NONE, - topological = GIT_SORT_TOPOLOGICAL, - time = GIT_SORT_TIME, - reverse = GIT_SORT_REVERSE - }; - - friend sorting operator ~ (sorting); - friend sorting operator | (sorting, sorting); - friend sorting operator & (sorting, sorting); - friend sorting operator ^ (sorting, sorting); - - void sort(sorting); + void sort(revwalker::sorting::type); void simplify_first_parent(); void push_head() const; diff --git a/src/revwalker.cpp b/src/revwalker.cpp index e12d565..9965d9d 100644 --- a/src/revwalker.cpp +++ b/src/revwalker.cpp @@ -2,44 +2,27 @@ #include "git2cpp/error.h" #include "git2cpp/repo.h" +#include + namespace git { - RevWalker::~RevWalker() - { - git_revwalk_free(walker_); - } - - namespace - { - unsigned int raw(RevWalker::sorting s) - { - return static_cast(s); - } - } - - RevWalker::sorting operator ~ (RevWalker::sorting s) + namespace revwalker { + namespace sorting { - return RevWalker::sorting(~raw(s)); - } + const type none (GIT_SORT_NONE); + const type topological (GIT_SORT_TOPOLOGICAL); + const type time (GIT_SORT_TIME); + const type reverse (GIT_SORT_REVERSE); + }} - RevWalker::sorting operator | (RevWalker::sorting a, RevWalker::sorting b) - { - return RevWalker::sorting(raw(a) | raw(b)); - } - - RevWalker::sorting operator ^ (RevWalker::sorting a, RevWalker::sorting b) - { - return RevWalker::sorting(raw(a) ^ raw(b)); - } - - RevWalker::sorting operator & (RevWalker::sorting a, RevWalker::sorting b) + RevWalker::~RevWalker() { - return RevWalker::sorting(raw(a) & raw(b)); + git_revwalk_free(walker_); } - void RevWalker::sort(sorting s) + void RevWalker::sort(revwalker::sorting::type s) { - git_revwalk_sorting(walker_, raw(s)); + git_revwalk_sorting(walker_, s.value()); } void RevWalker::simplify_first_parent() From c762eca9fb7b196d8017fd88cd982e23a029e79d Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 00:02:35 +0300 Subject: [PATCH 036/171] RevWalker: + operator = (Revwalker &&) --- include/git2cpp/revwalker.h | 12 ++++++++++-- src/revwalker.cpp | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/git2cpp/revwalker.h b/include/git2cpp/revwalker.h index 56377b2..fe783f4 100644 --- a/include/git2cpp/revwalker.h +++ b/include/git2cpp/revwalker.h @@ -22,7 +22,7 @@ namespace git { RevWalker(git_revwalk * walker, Repository const & repo) : walker_(walker) - , repo_(repo) + , repo_(&repo) {} ~RevWalker(); @@ -47,8 +47,16 @@ namespace git other.walker_ = nullptr; } + RevWalker& operator = (RevWalker && other) + { + walker_ = other.walker_; + repo_ = other.repo_; + other.walker_ = nullptr; + return *this; + } + private: git_revwalk * walker_; - Repository const & repo_; + Repository const * repo_; }; } diff --git a/src/revwalker.cpp b/src/revwalker.cpp index 9965d9d..fdd9b89 100644 --- a/src/revwalker.cpp +++ b/src/revwalker.cpp @@ -52,7 +52,7 @@ namespace git { git_oid oid; if (git_revwalk_next(&oid, walker_) == 0) - return repo_.commit_lookup(oid); + return repo_->commit_lookup(oid); else return Commit(); } From 2621ae84ca69ef3ee010e4eea59c5596ca9cec23 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 00:03:09 +0300 Subject: [PATCH 037/171] code porn removed --- examples/log.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/log.cpp b/examples/log.cpp index b06c9cc..c6a8d2a 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -30,7 +30,7 @@ struct log_state { std::string repodir = "."; boost::optional repo; - std::unique_ptr walker; + boost::optional walker; int hide = 0; git::revwalker::sorting::type sorting = git::revwalker::sorting::time; }; @@ -42,7 +42,7 @@ static void set_sorting(struct log_state *s, git::revwalker::sorting::type sort_ } if (!s->walker) - s->walker.reset(new git::RevWalker(s->repo->rev_walker())); + s->walker = s->repo->rev_walker(); if (sort_mode == git::revwalker::sorting::reverse) s->sorting = s->sorting ^ git::revwalker::sorting::reverse; @@ -57,7 +57,7 @@ void push_rev(log_state * s, git::Commit const & commit, int hide) hide = s->hide ^ hide; if (!s->walker) { - s->walker.reset(new git::RevWalker(s->repo->rev_walker())); + s->walker = s->repo->rev_walker(); s->walker->sort(s->sorting); } @@ -74,7 +74,7 @@ void push_rev(struct log_state *s, git::Object const & obj, int hide) hide = s->hide ^ hide; if (!s->walker) { - s->walker.reset(new git::RevWalker(s->repo->rev_walker())); + s->walker = s->repo->rev_walker(); s->walker->sort(s->sorting); } From d824fa30aa8963394150fe027927a964cbe24d7e Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 01:54:43 +0300 Subject: [PATCH 038/171] + wrapper around 'git_buf' --- include/git2cpp/buffer.h | 25 +++++++++++++++++++++++++ src/buffer.cpp | 9 +++++++++ 2 files changed, 34 insertions(+) create mode 100644 include/git2cpp/buffer.h create mode 100644 src/buffer.cpp diff --git a/include/git2cpp/buffer.h b/include/git2cpp/buffer.h new file mode 100644 index 0000000..f9331d7 --- /dev/null +++ b/include/git2cpp/buffer.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace git +{ + struct Buffer + { + Buffer (Buffer const &) = delete; + Buffer& operator = (Buffer const &) = delete; + + Buffer(Buffer &&); + + explicit Buffer(git_buf buf) + : buf_(buf) + {} + + ~Buffer(); + + const char * ptr() const { return buf_.ptr; } + + private: + git_buf buf_; + }; +} diff --git a/src/buffer.cpp b/src/buffer.cpp new file mode 100644 index 0000000..5b49529 --- /dev/null +++ b/src/buffer.cpp @@ -0,0 +1,9 @@ +#include "git2cpp/buffer.h" + +namespace git +{ + Buffer::~Buffer() + { + git_buf_free(&buf_); + } +} From 2152b059789cd84677e98657ba7fbf6e5a87413f Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 01:57:28 +0300 Subject: [PATCH 039/171] tagged_mask_t: + default ctor and operator |= --- include/git2cpp/tagged_mask.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/git2cpp/tagged_mask.h b/include/git2cpp/tagged_mask.h index 5ee7ea4..85cb21c 100644 --- a/include/git2cpp/tagged_mask.h +++ b/include/git2cpp/tagged_mask.h @@ -7,7 +7,7 @@ namespace git { typedef tagged_mask_t self_t; - explicit tagged_mask_t(RawType value) + explicit tagged_mask_t(RawType value = RawType()) : value_(value) {} @@ -15,6 +15,8 @@ namespace git operator bool() const { return value_; } + self_t& operator |= (self_t other) { value_ |= other.value_; return *this; } + friend self_t operator ~ (self_t x) { return self_t(~x.value_); } friend self_t operator | (self_t x, self_t y) { return self_t(x.value_ | y.value_); } From 1e7860a9443cab667533d03a1eee0100b843a862 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 02:58:49 +0300 Subject: [PATCH 040/171] tagged_mask_t: make operator bool() explicit --- include/git2cpp/tagged_mask.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2cpp/tagged_mask.h b/include/git2cpp/tagged_mask.h index 85cb21c..793b3e2 100644 --- a/include/git2cpp/tagged_mask.h +++ b/include/git2cpp/tagged_mask.h @@ -13,7 +13,7 @@ namespace git RawType value() const { return value_; } - operator bool() const { return value_; } + explicit operator bool() const { return value_; } self_t& operator |= (self_t other) { value_ |= other.value_; return *this; } From 23c4c6804e7317c8a04d7bfaabc79fcd9619d063 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 03:00:54 +0300 Subject: [PATCH 041/171] + tagged_mask_t: + operators ==, != --- include/git2cpp/tagged_mask.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/git2cpp/tagged_mask.h b/include/git2cpp/tagged_mask.h index 793b3e2..1be5616 100644 --- a/include/git2cpp/tagged_mask.h +++ b/include/git2cpp/tagged_mask.h @@ -23,6 +23,9 @@ namespace git friend self_t operator & (self_t x, self_t y) { return self_t(x.value_ & y.value_); } friend self_t operator ^ (self_t x, self_t y) { return self_t(x.value_ ^ y.value_); } + friend bool operator == (self_t x, self_t y) { return x.value_ == y.value_; } + friend bool operator != (self_t x, self_t y) { return x.value_ != y.value_; } + private: RawType value_; }; From 39569c1ae3e0e53911df6d810648595ac3aed72a Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 03:12:40 +0300 Subject: [PATCH 042/171] buffer: + operator bool() --- include/git2cpp/buffer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/git2cpp/buffer.h b/include/git2cpp/buffer.h index f9331d7..f5f69a4 100644 --- a/include/git2cpp/buffer.h +++ b/include/git2cpp/buffer.h @@ -17,6 +17,8 @@ namespace git ~Buffer(); + explicit operator bool() const { return ptr(); } + const char * ptr() const { return buf_.ptr; } private: From 49c315476a860374b3f1083bd18d92f68d22c8c9 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 03:13:51 +0300 Subject: [PATCH 043/171] + Repository: + 2 overloads for 'diff' --- include/git2cpp/repo.h | 8 +++++--- src/repo.cpp | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index f3d2934..0da5969 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -50,9 +50,11 @@ namespace git Index index() const; Odb odb() const; - Diff diff (Tree &, Tree &, git_diff_options const &) const; - Diff diff_to_index (Tree &, git_diff_options const &) const; - Diff diff_index_to_workdir ( git_diff_options const &) const; + Diff diff (Tree &, Tree &, git_diff_options const &) const; + Diff diff_to_index (Tree &, git_diff_options const &) const; + Diff diff_to_workdir (Tree &, git_diff_options const &) const; + Diff diff_to_workdir_with_index (Tree &, git_diff_options const &) const; + Diff diff_index_to_workdir ( git_diff_options const &) const; Signature signature() const; diff --git a/src/repo.cpp b/src/repo.cpp index f286237..7a5b7c2 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -359,6 +359,22 @@ namespace git return Diff(diff); } + Diff Repository::diff_to_workdir(Tree & t, git_diff_options const & opts) const + { + git_diff * diff; + auto op_res = git_diff_tree_to_workdir(&diff, repo_, t.ptr(), &opts); + assert(op_res == 0); + return Diff(diff); + } + + Diff Repository::diff_to_workdir_with_index(Tree & t, git_diff_options const & opts) const + { + git_diff * diff; + auto op_res = git_diff_tree_to_workdir_with_index(&diff, repo_, t.ptr(), &opts); + assert(op_res == 0); + return Diff(diff); + } + Diff Repository::diff_index_to_workdir(git_diff_options const & opts) const { git_diff * diff; From d7b889677bb4c4caeb2ad1be77dad224f458d8ce Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 03:15:04 +0300 Subject: [PATCH 044/171] Diff: + method 'stats()' --- include/git2cpp/diff.h | 42 ++++++++++++++++++++++++++++++++++++++++++ src/diff.cpp | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/include/git2cpp/diff.h b/include/git2cpp/diff.h index 1751980..f9efc63 100644 --- a/include/git2cpp/diff.h +++ b/include/git2cpp/diff.h @@ -4,16 +4,58 @@ #include +#include "tagged_mask.h" +#include "buffer.h" + namespace git { + namespace diff + { + namespace stats { + namespace format + { + typedef tagged_mask_t type; + + extern const type none; + extern const type full; + extern const type _short; + extern const type number; + extern const type include_summary; + }} + } + struct Diff { + struct Stats + { + ~Stats(); + + Stats (Stats const &) = delete; + Stats& operator = (Stats const &) = delete; + + Stats(Stats &&); + + Buffer to_buf(diff::stats::format::type, size_t width) const; + + private: + friend struct Diff; + + explicit Stats(git_diff_stats * stats) + : stats_(stats) + {} + + private: + git_diff_stats * stats_; + }; + size_t deltas_num() const; void find_similar(git_diff_find_options &); Diff& merge(Diff const & other); + Stats stats() const; + enum class format { patch, patch_header, raw, name_only, name_status diff --git a/src/diff.cpp b/src/diff.cpp index d9245f4..9ca77fb 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -1,4 +1,5 @@ #include "git2cpp/diff.h" +#include "git2cpp/error.h" #include @@ -53,5 +54,41 @@ namespace git { git_diff_print(diff_, convert(f), &apply_callback, &print_callback); } + + Diff::Stats Diff::stats() const + { + git_diff_stats * stats; + if (git_diff_get_stats(&stats, diff_)) + throw error_t("git_diff_get_stats fail"); + else + return Stats(stats); + } + + Diff::Stats::~Stats() + { + git_diff_stats_free(stats_); + } + + Buffer Diff::Stats::to_buf(diff::stats::format::type format, size_t width) const + { + git_buf buf = GIT_BUF_INIT_CONST(nullptr, 0); + if (git_diff_stats_to_buf(&buf, stats_, git_diff_stats_format_t(format.value()), width)) + throw error_t("git_diff_stats_to_buf fail"); + else + return Buffer(buf); + } + + namespace diff + { + namespace stats { + namespace format + { + const type none (GIT_DIFF_STATS_NONE); + const type full (GIT_DIFF_STATS_FULL); + const type _short (GIT_DIFF_STATS_SHORT); + const type number (GIT_DIFF_STATS_NUMBER); + const type include_summary (GIT_DIFF_STATS_INCLUDE_SUMMARY); + }} + } } From 0300b26bd2a083ac361dc6ab38063760033c9d11 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 03:30:54 +0300 Subject: [PATCH 045/171] Diff: unused now function 'merge' removed --- include/git2cpp/diff.h | 2 -- src/diff.cpp | 6 ------ 2 files changed, 8 deletions(-) diff --git a/include/git2cpp/diff.h b/include/git2cpp/diff.h index f9efc63..b7d14fe 100644 --- a/include/git2cpp/diff.h +++ b/include/git2cpp/diff.h @@ -52,8 +52,6 @@ namespace git void find_similar(git_diff_find_options &); - Diff& merge(Diff const & other); - Stats stats() const; enum class format diff --git a/src/diff.cpp b/src/diff.cpp index 9ca77fb..da9251b 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -39,12 +39,6 @@ namespace git git_diff_find_similar(diff_, &findopts); } - Diff& Diff::merge(Diff const & other) - { - git_diff_merge(diff_, other.diff_); - return *this; - } - size_t Diff::deltas_num() const { return git_diff_num_deltas(diff_); From 20816a13809a84b5ee505c48a58309ea6bf1c834 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 03:31:33 +0300 Subject: [PATCH 046/171] example 'diff' reexported from libgit2 examples --- examples/diff.cpp | 379 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 343 insertions(+), 36 deletions(-) diff --git a/examples/diff.cpp b/examples/diff.cpp index 237cfe9..6b69c72 100644 --- a/examples/diff.cpp +++ b/examples/diff.cpp @@ -42,17 +42,6 @@ const char *colors[] = { "\033[36m" /* cyan */ }; -int diff_output(const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); - -static int check_str_param(const char *arg, const char *pattern, const char **val) -{ - size_t len = strlen(pattern); - if (strncmp(arg, pattern, len)) - return 0; - *val = (const char *)(arg + len); - return 1; -} - static void usage(const char *message, const char *arg) { if (message && arg) @@ -63,36 +52,354 @@ static void usage(const char *message, const char *arg) exit(1); } -enum { - FORMAT_PATCH = 0, - FORMAT_COMPACT = 1, - FORMAT_RAW = 2 +namespace output +{ + typedef tagged_mask_t type; + + const type diff (1 << 0); + const type stat (1 << 1); + const type shortstat(1 << 2); + const type numstat (1 << 3); + const type summary (1 << 4); +} + +enum class cache_t +{ + normal, + only, + none }; -/* */ -/* --cached */ -/* */ -/* --cached */ -/* nothing */ - -Diff calc_diff(Repository const & repo, Tree & t1, Tree & t2, bool cached, git_diff_options const & opts) -{ - if (t1 && t2) - return repo.diff(t1, t2, opts); - else if (t1 && cached) - return repo.diff_to_index(t1, opts); - else if (t1) - return std::move(repo.diff_to_index(t1, opts).merge(repo.diff_index_to_workdir(opts))); - else if (cached) - { - auto tree = resolve_to_tree(repo, "HEAD"); - return repo.diff_to_index(tree, opts); - } - else - return repo.diff_index_to_workdir(opts); +/** The 'opts' struct captures all the various parsed command line options. */ +struct opts_t { + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + int color = -1; + cache_t cache = cache_t::normal; + output::type output; + Diff::format format = Diff::format::patch; + const char *treeish1 = nullptr; + const char *treeish2 = nullptr; + const char *dir = "."; + + opts_t(int argc, char *argv[]); +}; + +size_t is_prefixed(const char *str, const char *pfx) +{ + size_t len = strlen(pfx); + return strncmp(str, pfx, len) ? 0 : len; +} + +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); +} + +struct args_info +{ +private: + int argc; + char **argv; + +public: + int pos; + + args_info(int argc, char ** argv) + : argc(argc) + , argv(argv) + , pos(0) + {} + + int match_str(const char **out, const char *opt); + int match_uint16(uint16_t *out, const char *opt); + +private: + const char * match_numeric(const char *opt); +}; + +int args_info::match_str(const char **out, const char *opt) +{ + const char *found = argv[pos]; + size_t len = is_prefixed(found, opt); + + if (!len) + return 0; + + if (!found[len]) { + if (pos + 1 == argc) + fatal("expected value following argument", opt); + ++pos; + *out = argv[pos]; + return 1; + } + + if (found[len] == '=') { + *out = found + len + 1; + return 1; + } + + return 0; +} + +const char * args_info::match_numeric(const char *opt) +{ + const char *found = argv[pos]; + size_t len = is_prefixed(found, opt); + + if (!len) + return NULL; + + if (!found[len]) { + if (pos + 1 == argc) + fatal("expected numeric value following argument", opt); + pos += 1; + found = argv[pos]; + } else { + found = found + len; + if (*found == '=') + found++; + } + + return found; +} + +int args_info::match_uint16(uint16_t *out, const char *opt) +{ + const char *found = match_numeric(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_uint16_arg(uint32_t *out, args_info & args, const char *opt) +{ + uint16_t tmp; + const int res = args.match_uint16(&tmp, opt); + *out = tmp; + return res; +} + +/** Parse arguments as copied from git-diff. */ +opts_t::opts_t(int argc, char *argv[]) +{ + args_info args(argc, argv); + + for (args.pos = 1; args.pos < argc; ++args.pos) + { + const char *a = argv[args.pos]; + + if (a[0] != '-') { + if (treeish1 == NULL) + treeish1 = a; + else if (treeish2 == NULL) + treeish2 = a; + else + usage("Only one or two tree identifiers can be provided", NULL); + } + else if (!strcmp(a, "-p") || !strcmp(a, "-u") || + !strcmp(a, "--patch")) { + output |= output::diff; + format = Diff::format::patch; + } + else if (!strcmp(a, "--cached")) + cache = cache_t::only; + else if (!strcmp(a, "--nocache")) + cache = cache_t::none; + else if (!strcmp(a, "--name-only") || !strcmp(a, "--format=name")) + format = Diff::format::name_only; + else if (!strcmp(a, "--name-status") || + !strcmp(a, "--format=name-status")) + format = Diff::format::name_status; + else if (!strcmp(a, "--raw") || !strcmp(a, "--format=raw")) + format = Diff::format::raw; + else if (!strcmp(a, "--format=diff-index")) { + format = Diff::format::raw; + diffopts.id_abbrev = 40; + } + else if (!strcmp(a, "--color")) + color = 0; + else if (!strcmp(a, "--no-color")) + color = -1; + else if (!strcmp(a, "-R")) + diffopts.flags |= GIT_DIFF_REVERSE; + else if (!strcmp(a, "-a") || !strcmp(a, "--text")) + diffopts.flags |= GIT_DIFF_FORCE_TEXT; + else if (!strcmp(a, "--ignore-space-at-eol")) + diffopts.flags |= GIT_DIFF_IGNORE_WHITESPACE_EOL; + else if (!strcmp(a, "-b") || !strcmp(a, "--ignore-space-change")) + diffopts.flags |= GIT_DIFF_IGNORE_WHITESPACE_CHANGE; + else if (!strcmp(a, "-w") || !strcmp(a, "--ignore-all-space")) + diffopts.flags |= GIT_DIFF_IGNORE_WHITESPACE; + else if (!strcmp(a, "--ignored")) + diffopts.flags |= GIT_DIFF_INCLUDE_IGNORED; + else if (!strcmp(a, "--untracked")) + diffopts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; + else if (!strcmp(a, "--patience")) + diffopts.flags |= GIT_DIFF_PATIENCE; + else if (!strcmp(a, "--minimal")) + diffopts.flags |= GIT_DIFF_MINIMAL; + else if (!strcmp(a, "--stat")) + output |= output::stat; + else if (!strcmp(a, "--numstat")) + output |= output::numstat; + else if (!strcmp(a, "--shortstat")) + output |= output::shortstat; + else if (!strcmp(a, "--summary")) + output |= output::summary; + else if (args.match_uint16( + &findopts.rename_threshold, "-M") || + args.match_uint16( + &findopts.rename_threshold, "--find-renames")) + findopts.flags |= GIT_DIFF_FIND_RENAMES; + else if (args.match_uint16( + &findopts.copy_threshold, "-C") || + args.match_uint16( + &findopts.copy_threshold, "--find-copies")) + findopts.flags |= GIT_DIFF_FIND_COPIES; + else if (!strcmp(a, "--find-copies-harder")) + findopts.flags |= GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; + else if (is_prefixed(a, "-B") || is_prefixed(a, "--break-rewrites")) + /* TODO: parse thresholds */ + findopts.flags |= GIT_DIFF_FIND_REWRITES; + else if (!match_uint16_arg( + &diffopts.context_lines, args, "-U") && + !match_uint16_arg( + &diffopts.context_lines, args, "--unified") && + !match_uint16_arg( + &diffopts.interhunk_lines, args, "--inter-hunk-context") && + !args.match_uint16( + &diffopts.id_abbrev, "--abbrev") && + !args.match_str(&diffopts.old_prefix, "--src-prefix") && + !args.match_str(&diffopts.new_prefix, "--dst-prefix") && + !args.match_str(&dir, "--git-dir")) + usage("Unknown command line argument", a); + } +} + +Diff find_diff(Repository const & repo, Tree & t1, Tree & t2, cache_t cache, git_diff_options const & opts) +{ + if (t1 && t2) + { + return repo.diff(t1, t2, opts); + } + else if (cache == cache_t::normal) + { + if (t1) + return repo.diff_to_workdir_with_index(t1, opts); + else + return repo.diff_index_to_workdir(opts); + } + else + { + if (!t1) + t1 = resolve_to_tree(repo, "HEAD"); + + if (cache == cache_t::none) + return repo.diff_to_workdir(t1, opts); + else + return repo.diff_to_index(t1, opts); + } +} + +int color_printer(git_diff_delta const &, git_diff_hunk const &, git_diff_line const & l, int & last_color) +{ + int color = 0; + + if (last_color >= 0) { + switch (l.origin) { + case GIT_DIFF_LINE_ADDITION: color = 3; break; + case GIT_DIFF_LINE_DELETION: color = 2; break; + case GIT_DIFF_LINE_ADD_EOFNL: color = 3; break; + case GIT_DIFF_LINE_DEL_EOFNL: color = 2; break; + case GIT_DIFF_LINE_FILE_HDR: color = 1; break; + case GIT_DIFF_LINE_HUNK_HDR: color = 4; break; + default: break; + } + + if (color != last_color) { + if (last_color == 1 || color == 1) + fputs(colors[0], stdout); + fputs(colors[color], stdout); + last_color = color; + } + } + + if (l.origin == GIT_DIFF_LINE_CONTEXT || + l.origin == GIT_DIFF_LINE_ADDITION || + l.origin == GIT_DIFF_LINE_DELETION) + fputc(l.origin, stdout); + + fwrite(l.content, 1, l.content_len, stdout); + + return 0; +} + +void diff_print_stats(Diff const & diff, output::type output) +{ + namespace fmt = diff::stats::format; + fmt::type format = fmt::none; + if (output & output::stat) + format |= fmt::full; + if (output & output::shortstat) + format |= fmt::_short; + if (output & output::numstat) + format |= fmt::number; + if (output & output::summary) + format |= fmt::include_summary; + + auto stats = diff.stats(); + if (Buffer buf = stats.to_buf(format, 80)) + fputs(buf.ptr(), stdout); } int main(int argc, char *argv[]) { + auto_git_initializer; + opts_t opts(argc, argv); + Repository repo(opts.dir); + Tree t1, t2; + if (opts.treeish1) + t1 = resolve_to_tree(repo, opts.treeish1); + if (opts.treeish2) + t2 = resolve_to_tree(repo, opts.treeish2); + + Diff diff = find_diff(repo, t1, t2, opts.cache, opts.diffopts); + + if (opts.findopts.flags & GIT_DIFF_FIND_ALL) + diff.find_similar(opts.findopts); + + if (!opts.output) + opts.output = output::diff; + + if (opts.output != output::diff) + diff_print_stats(diff, opts.output); + + if (opts.output & output::diff) + { + if (opts.color >= 0) + fputs(colors[0], stdout); + + using namespace std::placeholders; + diff.print(opts.format, std::bind(&color_printer, _1, _2, _3, std::ref(opts.color))); + + if (opts.color >= 0) + fputs(colors[0], stdout); + } } From e64f9215721dbb913b258656955959312260ee03 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 10 Jan 2016 15:08:56 +0300 Subject: [PATCH 047/171] enum format moved from struct 'Diff' to namespace 'diff' --- examples/diff.cpp | 12 +++++----- examples/log.cpp | 2 +- include/git2cpp/diff.h | 12 +++++----- src/diff.cpp | 54 ++++++++++++++++++++++-------------------- 4 files changed, 41 insertions(+), 39 deletions(-) diff --git a/examples/diff.cpp b/examples/diff.cpp index 6b69c72..858d911 100644 --- a/examples/diff.cpp +++ b/examples/diff.cpp @@ -77,7 +77,7 @@ struct opts_t { int color = -1; cache_t cache = cache_t::normal; output::type output; - Diff::format format = Diff::format::patch; + diff::format format = diff::format::patch; const char *treeish1 = nullptr; const char *treeish2 = nullptr; const char *dir = "."; @@ -215,21 +215,21 @@ opts_t::opts_t(int argc, char *argv[]) else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) { output |= output::diff; - format = Diff::format::patch; + format = diff::format::patch; } else if (!strcmp(a, "--cached")) cache = cache_t::only; else if (!strcmp(a, "--nocache")) cache = cache_t::none; else if (!strcmp(a, "--name-only") || !strcmp(a, "--format=name")) - format = Diff::format::name_only; + format = diff::format::name_only; else if (!strcmp(a, "--name-status") || !strcmp(a, "--format=name-status")) - format = Diff::format::name_status; + format = diff::format::name_status; else if (!strcmp(a, "--raw") || !strcmp(a, "--format=raw")) - format = Diff::format::raw; + format = diff::format::raw; else if (!strcmp(a, "--format=diff-index")) { - format = Diff::format::raw; + format = diff::format::raw; diffopts.id_abbrev = 40; } else if (!strcmp(a, "--color")) diff --git a/examples/log.cpp b/examples/log.cpp index c6a8d2a..76a5084 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -368,7 +368,7 @@ int main(int argc, char *argv[]) a = commit.parent(0).tree(); } - s.repo->diff(a, b, diffopts).print(git::Diff::format::patch, print_diff); + s.repo->diff(a, b, diffopts).print(git::diff::format::patch, print_diff); } } diff --git a/include/git2cpp/diff.h b/include/git2cpp/diff.h index b7d14fe..25640f7 100644 --- a/include/git2cpp/diff.h +++ b/include/git2cpp/diff.h @@ -22,6 +22,11 @@ namespace git extern const type number; extern const type include_summary; }} + + enum class format + { + patch, patch_header, raw, name_only, name_status + }; } struct Diff @@ -54,16 +59,11 @@ namespace git Stats stats() const; - enum class format - { - patch, patch_header, raw, name_only, name_status - }; - typedef std::function print_callback_t; - void print(format, print_callback_t print_callback) const; + void print(diff::format, print_callback_t print_callback) const; explicit Diff(git_diff * diff) : diff_(diff) diff --git a/src/diff.cpp b/src/diff.cpp index da9251b..fba1956 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -3,8 +3,35 @@ #include +#include + namespace git { + namespace diff + { + namespace stats { + namespace format + { + const type none (GIT_DIFF_STATS_NONE); + const type full (GIT_DIFF_STATS_FULL); + const type _short (GIT_DIFF_STATS_SHORT); + const type number (GIT_DIFF_STATS_NUMBER); + const type include_summary (GIT_DIFF_STATS_INCLUDE_SUMMARY); + }} + + git_diff_format_t convert(format f) + { + static const boost::container::flat_map converter = { + { format::patch, GIT_DIFF_FORMAT_PATCH }, + { format::patch_header, GIT_DIFF_FORMAT_PATCH_HEADER }, + { format::raw, GIT_DIFF_FORMAT_RAW }, + { format::name_only, GIT_DIFF_FORMAT_NAME_ONLY }, + { format::name_status, GIT_DIFF_FORMAT_NAME_STATUS }, + }; + return converter.at(f); + } + } + namespace { int apply_callback ( git_diff_delta const * delta @@ -18,18 +45,6 @@ namespace git (*cb)(*delta, *hunk, *line); return 0; } - - git_diff_format_t convert(Diff::format f) - { - switch (f) - { - case Diff::format::name_only: return GIT_DIFF_FORMAT_NAME_ONLY; - case Diff::format::name_status: return GIT_DIFF_FORMAT_NAME_STATUS; - case Diff::format::patch: return GIT_DIFF_FORMAT_PATCH; - case Diff::format::patch_header: return GIT_DIFF_FORMAT_PATCH_HEADER; - case Diff::format::raw: return GIT_DIFF_FORMAT_RAW; - } - } } Diff::~Diff() { git_diff_free(diff_); } @@ -44,7 +59,7 @@ namespace git return git_diff_num_deltas(diff_); } - void Diff::print(format f, print_callback_t print_callback) const + void Diff::print(diff::format f, print_callback_t print_callback) const { git_diff_print(diff_, convert(f), &apply_callback, &print_callback); } @@ -71,18 +86,5 @@ namespace git else return Buffer(buf); } - - namespace diff - { - namespace stats { - namespace format - { - const type none (GIT_DIFF_STATS_NONE); - const type full (GIT_DIFF_STATS_FULL); - const type _short (GIT_DIFF_STATS_SHORT); - const type number (GIT_DIFF_STATS_NUMBER); - const type include_summary (GIT_DIFF_STATS_INCLUDE_SUMMARY); - }} - } } From 123f2374227685e02f4ffe6c4d8a022a5b2deac8 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 11 Jan 2016 14:52:31 +0300 Subject: [PATCH 048/171] initializer list -> boost::assign::list_of --- src/diff.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/diff.cpp b/src/diff.cpp index fba1956..e731422 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace git { @@ -21,13 +22,14 @@ namespace git git_diff_format_t convert(format f) { - static const boost::container::flat_map converter = { - { format::patch, GIT_DIFF_FORMAT_PATCH }, - { format::patch_header, GIT_DIFF_FORMAT_PATCH_HEADER }, - { format::raw, GIT_DIFF_FORMAT_RAW }, - { format::name_only, GIT_DIFF_FORMAT_NAME_ONLY }, - { format::name_status, GIT_DIFF_FORMAT_NAME_STATUS }, - }; + static const boost::container::flat_map converter + = boost::assign::list_of> + ( format::patch, GIT_DIFF_FORMAT_PATCH ) + ( format::patch_header, GIT_DIFF_FORMAT_PATCH_HEADER ) + ( format::raw, GIT_DIFF_FORMAT_RAW ) + ( format::name_only, GIT_DIFF_FORMAT_NAME_ONLY ) + ( format::name_status, GIT_DIFF_FORMAT_NAME_STATUS ) + ; return converter.at(f); } } From e477d835c46286ea32af69ce0c6535a6f4d81c4d Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 22 Mar 2016 11:43:49 +0300 Subject: [PATCH 049/171] Status: return entry by reference --- examples/status.cpp | 103 +++++++++++++++++++-------------------- include/git2cpp/status.h | 2 +- src/status.cpp | 7 ++- 3 files changed, 55 insertions(+), 57 deletions(-) diff --git a/examples/status.cpp b/examples/status.cpp index 4235636..469134f 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -10,11 +10,6 @@ #include -extern "C" -{ -#include -} - #include "git2cpp/initializer.h" #include "git2cpp/repo.h" @@ -79,25 +74,25 @@ void print_long(Status const & status) /* print index changes */ for (size_t i = 0; i < maxi; ++i) { - auto s = status[i]; + auto const & s = status[i]; - if (s->status == GIT_STATUS_CURRENT) + if (s.status == GIT_STATUS_CURRENT) continue; - if (s->status & GIT_STATUS_WT_DELETED) + if (s.status & GIT_STATUS_WT_DELETED) rm_in_workdir = 1; const char *istatus = nullptr; - if (s->status & GIT_STATUS_INDEX_NEW) + if (s.status & GIT_STATUS_INDEX_NEW) istatus = "new file: "; - if (s->status & GIT_STATUS_INDEX_MODIFIED) + if (s.status & GIT_STATUS_INDEX_MODIFIED) istatus = "modified: "; - if (s->status & GIT_STATUS_INDEX_DELETED) + if (s.status & GIT_STATUS_INDEX_DELETED) istatus = "deleted: "; - if (s->status & GIT_STATUS_INDEX_RENAMED) + if (s.status & GIT_STATUS_INDEX_RENAMED) istatus = "renamed: "; - if (s->status & GIT_STATUS_INDEX_TYPECHANGE) + if (s.status & GIT_STATUS_INDEX_TYPECHANGE) istatus = "typechange:"; if (istatus == NULL) @@ -110,8 +105,8 @@ void print_long(Status const & status) header = 1; } - old_path = s->head_to_index->old_file.path; - new_path = s->head_to_index->new_file.path; + old_path = s.head_to_index->old_file.path; + new_path = s.head_to_index->new_file.path; if (old_path && new_path && strcmp(old_path, new_path)) printf("#\t%s %s -> %s\n", istatus, old_path, new_path); @@ -128,20 +123,20 @@ void print_long(Status const & status) /* print workdir changes to tracked files */ for (size_t i = 0; i < maxi; ++i) { - auto s = status[i]; + auto const & s = status[i]; - if (s->status == GIT_STATUS_CURRENT || !s->index_to_workdir) + if (s.status == GIT_STATUS_CURRENT || !s.index_to_workdir) continue; const char *wstatus = nullptr; - if (s->status & GIT_STATUS_WT_MODIFIED) + if (s.status & GIT_STATUS_WT_MODIFIED) wstatus = "modified: "; - if (s->status & GIT_STATUS_WT_DELETED) + if (s.status & GIT_STATUS_WT_DELETED) wstatus = "deleted: "; - if (s->status & GIT_STATUS_WT_RENAMED) + if (s.status & GIT_STATUS_WT_RENAMED) wstatus = "renamed: "; - if (s->status & GIT_STATUS_WT_TYPECHANGE) + if (s.status & GIT_STATUS_WT_TYPECHANGE) wstatus = "typechange:"; if (wstatus == NULL) @@ -155,8 +150,8 @@ void print_long(Status const & status) header = 1; } - old_path = s->index_to_workdir->old_file.path; - new_path = s->index_to_workdir->new_file.path; + old_path = s.index_to_workdir->old_file.path; + new_path = s.index_to_workdir->new_file.path; if (old_path && new_path && strcmp(old_path, new_path)) printf("#\t%s %s -> %s\n", wstatus, old_path, new_path); @@ -175,9 +170,9 @@ void print_long(Status const & status) header = 0; for (size_t i = 0; i < maxi; ++i) { - auto s = status[i]; + auto const & s = status[i]; - if (s->status == GIT_STATUS_WT_NEW) { + if (s.status == GIT_STATUS_WT_NEW) { if (!header) { printf("# Untracked files:\n"); @@ -186,7 +181,7 @@ void print_long(Status const & status) header = 1; } - printf("#\t%s\n", s->index_to_workdir->old_file.path); + printf("#\t%s\n", s.index_to_workdir->old_file.path); } } @@ -195,9 +190,9 @@ void print_long(Status const & status) /* print ignored files */ for (size_t i = 0; i < maxi; ++i) { - auto s = status[i]; + auto const & s = status[i]; - if (s->status == GIT_STATUS_IGNORED) { + if (s.status == GIT_STATUS_IGNORED) { if (!header) { printf("# Ignored files:\n"); @@ -206,7 +201,7 @@ void print_long(Status const & status) header = 1; } - printf("#\t%s\n", s->index_to_workdir->old_file.path); + printf("#\t%s\n", s.index_to_workdir->old_file.path); } } @@ -222,41 +217,41 @@ void print_short(Repository const & repo, Status const & status) for (size_t i = 0; i < maxi; ++i) { - auto s = status[i]; + auto const & s = status[i]; - if (s->status == GIT_STATUS_CURRENT) + if (s.status == GIT_STATUS_CURRENT) continue; a = b = c = NULL; istatus = wstatus = ' '; extra = ""; - if (s->status & GIT_STATUS_INDEX_NEW) + if (s.status & GIT_STATUS_INDEX_NEW) istatus = 'A'; - if (s->status & GIT_STATUS_INDEX_MODIFIED) + if (s.status & GIT_STATUS_INDEX_MODIFIED) istatus = 'M'; - if (s->status & GIT_STATUS_INDEX_DELETED) + if (s.status & GIT_STATUS_INDEX_DELETED) istatus = 'D'; - if (s->status & GIT_STATUS_INDEX_RENAMED) + if (s.status & GIT_STATUS_INDEX_RENAMED) istatus = 'R'; - if (s->status & GIT_STATUS_INDEX_TYPECHANGE) + if (s.status & GIT_STATUS_INDEX_TYPECHANGE) istatus = 'T'; - if (s->status & GIT_STATUS_WT_NEW) { + if (s.status & GIT_STATUS_WT_NEW) { if (istatus == ' ') istatus = '?'; wstatus = '?'; } - if (s->status & GIT_STATUS_WT_MODIFIED) + if (s.status & GIT_STATUS_WT_MODIFIED) wstatus = 'M'; - if (s->status & GIT_STATUS_WT_DELETED) + if (s.status & GIT_STATUS_WT_DELETED) wstatus = 'D'; - if (s->status & GIT_STATUS_WT_RENAMED) + if (s.status & GIT_STATUS_WT_RENAMED) wstatus = 'R'; - if (s->status & GIT_STATUS_WT_TYPECHANGE) + if (s.status & GIT_STATUS_WT_TYPECHANGE) wstatus = 'T'; - if (s->status & GIT_STATUS_IGNORED) { + if (s.status & GIT_STATUS_IGNORED) { istatus = '!'; wstatus = '!'; } @@ -264,9 +259,9 @@ void print_short(Repository const & repo, Status const & status) if (istatus == '?' && wstatus == '?') continue; - if (s->index_to_workdir && s->index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT) + if (s.index_to_workdir && s.index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT) { - auto sm = repo.submodule_lookup(s->index_to_workdir->new_file.path); + auto sm = repo.submodule_lookup(s.index_to_workdir->new_file.path); auto smstatus = sm.get_status(); typedef Submodule::status status; @@ -281,16 +276,16 @@ void print_short(Repository const & repo, Status const & status) extra = " (untracked content)"; } - if (s->head_to_index) { - a = s->head_to_index->old_file.path; - b = s->head_to_index->new_file.path; + if (s.head_to_index) { + a = s.head_to_index->old_file.path; + b = s.head_to_index->new_file.path; } - if (s->index_to_workdir) { + if (s.index_to_workdir) { if (!a) - a = s->index_to_workdir->old_file.path; + a = s.index_to_workdir->old_file.path; if (!b) - b = s->index_to_workdir->old_file.path; - c = s->index_to_workdir->new_file.path; + b = s.index_to_workdir->old_file.path; + c = s.index_to_workdir->new_file.path; } if (istatus == 'R') { @@ -307,10 +302,10 @@ void print_short(Repository const & repo, Status const & status) } for (size_t i = 0; i < maxi; ++i) { - auto s = status[i]; + auto const & s = status[i]; - if (s->status == GIT_STATUS_WT_NEW) - printf("?? %s\n", s->index_to_workdir->old_file.path); + if (s.status == GIT_STATUS_WT_NEW) + printf("?? %s\n", s.index_to_workdir->old_file.path); } } diff --git a/include/git2cpp/status.h b/include/git2cpp/status.h index 9092c47..90cb406 100644 --- a/include/git2cpp/status.h +++ b/include/git2cpp/status.h @@ -17,7 +17,7 @@ namespace git ~Status(); size_t entrycount() const; - git_status_entry const * operator[] (size_t i) const; + git_status_entry const & operator[] (size_t i) const; Status (Status const &) = delete; Status& operator = (Status const &) = delete; diff --git a/src/status.cpp b/src/status.cpp index 9dcee88..d6956a6 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -8,9 +8,12 @@ namespace git return git_status_list_entrycount(status_); } - git_status_entry const * Status::operator[] (size_t i) const + git_status_entry const & Status::operator[] (size_t i) const { - return git_status_byindex(status_, i); + if (auto res = git_status_byindex(status_, i)) + return *res; + else + throw error_t("status entry index out of bounds: " + std::to_string(i)); } Status::Status(git_repository * repo, git_status_options const & opts) From e35cc3510df805c78d2b2445fd99d9700f51e9e5 Mon Sep 17 00:00:00 2001 From: Paulo Brizolara Date: Sun, 9 Oct 2016 18:53:35 -0300 Subject: [PATCH 050/171] Turning boost dependence optional. * Included in CMakeLists option to enable/disable use of boost (and check if it is found on system). * Modified 'error.h' to use a custom 'format' (using variadic template) instead of boost::format. * Created 'internal/optional.h' to wrap 'boost/optional' (when using boost) or using custom optional (without boost). * Changed 'repo.cpp' to use it * Modified 'diff.cpp' to allow alternate between 'boost::flatmap'(when available) or 'std::unordered_map' * Modified examples (log.cpp and rev-parse.cpp) to align with the changes. --- CMakeLists.txt | 14 ++- examples/log.cpp | 14 +-- examples/rev-parse.cpp | 12 +-- include/git2cpp/error.h | 25 +++-- include/git2cpp/internal/format.h | 43 ++++++++ include/git2cpp/internal/optional.h | 158 ++++++++++++++++++++++++++++ src/diff.cpp | 34 ++++-- src/repo.cpp | 13 +-- src/tree.cpp | 2 +- 9 files changed, 273 insertions(+), 42 deletions(-) create mode 100644 include/git2cpp/internal/format.h create mode 100644 include/git2cpp/internal/optional.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c2b1653..3225050 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,23 @@ project (libgit2cpp) cmake_minimum_required(VERSION 2.8) +# Build options +OPTION( USE_BOOST "Enable use of boost header libraries" OFF ) + + set(CMAKE_CXX_FLAGS -std=c++11) -file(GLOB lib_sources +file(GLOB_RECURSE lib_sources src/*.cpp include/git2cpp/*.h ) +IF(USE_BOOST) + add_definitions(-DUSE_BOOST=1) + find_package(Boost REQUIRED) + include_directories(${BOOST_INCLUDEDIR}) +ENDIF() + add_library(git2cpp ${lib_sources}) target_include_directories(git2cpp @@ -41,4 +51,4 @@ foreach (example ${examples}) target_link_libraries(${example} git2cpp) endforeach(example) -file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) \ No newline at end of file +file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) diff --git a/examples/log.cpp b/examples/log.cpp index 76a5084..3b814c3 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -3,8 +3,6 @@ #include #include -#include -#include #include @@ -16,6 +14,8 @@ #include "git2cpp/revwalker.h" #include "git2cpp/diff.h" +#include "git2cpp/internal/optional.h" + static void usage(const char *message, const char *arg) { if (message && arg) @@ -26,11 +26,11 @@ static void usage(const char *message, const char *arg) exit(1); } -struct log_state +struct log_state { std::string repodir = "."; - boost::optional repo; - boost::optional walker; + git::internal::optional repo; + git::internal::optional walker; int hide = 0; git::revwalker::sorting::type sorting = git::revwalker::sorting::time; }; @@ -38,7 +38,7 @@ struct log_state static void set_sorting(struct log_state *s, git::revwalker::sorting::type sort_mode) { if (!s->repo) { - s->repo = boost::in_place(s->repodir); + git::internal::emplace(s->repo, s->repodir); } if (!s->walker) @@ -91,7 +91,7 @@ void add_revision(struct log_state *s, const char *revstr) int hide = 0; if (!s->repo) { - s->repo = boost::in_place(s->repodir); + git::internal::emplace(s->repo, s->repodir); } if (!revstr) { diff --git a/examples/rev-parse.cpp b/examples/rev-parse.cpp index 257f040..7ff1335 100644 --- a/examples/rev-parse.cpp +++ b/examples/rev-parse.cpp @@ -3,11 +3,11 @@ #include #include -#include -#include +#include #include "git2cpp/initializer.h" #include "git2cpp/repo.h" +#include "git2cpp/internal/optional.h" using namespace git; @@ -22,14 +22,14 @@ static void usage(const char *message, const char *arg) } struct parse_state { - boost::optional repo; - std::string repodir = "."; + internal::optional repo; + std::string repodir = "."; }; void parse_revision(parse_state & ps, const char *revstr) { - if (!ps.repo) - ps.repo = boost::in_place(ps.repodir); + if (!ps.repo) + internal::emplace(ps.repo, ps.repodir); Revspec rs = ps.repo->revparse(revstr); diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 623b3f5..1d9f0a2 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -2,16 +2,15 @@ #include -#include - #include "id_to_str.h" +#include "internal/format.h" namespace git { + struct error_t : std::runtime_error { explicit error_t(std::string const & message) : std::runtime_error(message) {} - explicit error_t(boost::format const & message) : error_t(str(message)) {} }; struct repository_open_error : error_t @@ -88,7 +87,7 @@ namespace git struct revparse_error : error_t { explicit revparse_error(const char * spec) - : error_t(boost::format("Could not resolve %1%") % spec) + : error_t(internal::format("Could not resolve %s", spec)) {} }; @@ -107,21 +106,21 @@ namespace git struct file_not_found_error : error_t { explicit file_not_found_error(const char * filepath) - : error_t(boost::format("file path \"%1%\" not found") % filepath) + : error_t(internal::format("file path \"%s\" not found", filepath)) {} }; struct ambiguous_path_error : error_t { explicit ambiguous_path_error(const char * filepath) - : error_t(boost::format("file path \"%1%\" is ambiguous") % filepath) + : error_t(internal::format("file path \"%s\" is ambiguous", filepath)) {} }; struct unknown_file_status_error : error_t { explicit unknown_file_status_error(const char * filepath) - : error_t(boost::format("unknown error during getting status for file \"%1%\"") % filepath) + : error_t(internal::format("unknown error during getting status for file \"%s\"", filepath)) {} }; @@ -143,7 +142,7 @@ namespace git struct non_commit_object_error : error_t { explicit non_commit_object_error(git_oid const & id) - : error_t(str(boost::format("object %1% is not a commit") % id_to_str(id))) + : error_t(internal::format("object %s is not a commit", id_to_str(id))) {} }; @@ -182,11 +181,11 @@ namespace git struct merge_base_error : error_t { - merge_base_error(git_oid const & c1, git_oid const & c2) - : error_t(boost::format("Could not find merge base for commits %1% and % 2%") - % id_to_str(c1, 8) - % id_to_str(c2, 8)) - {} + merge_base_error(git_oid const & c1, git_oid const & c2) + : error_t(internal::format( + "Could not find merge base for commits %s and %s", id_to_str(c1, 8), id_to_str(c2, 8) + )) + {} }; struct config_open_error : error_t diff --git a/include/git2cpp/internal/format.h b/include/git2cpp/internal/format.h new file mode 100644 index 0000000..651d729 --- /dev/null +++ b/include/git2cpp/internal/format.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +#ifdef USE_BOOST +#include +#endif + +namespace git { +namespace internal +{ + +#ifndef USE_BOOST + template + inline std::string format(const char * fmt, Args&& ... args) + { + auto size = std::snprintf(nullptr, 0, fmt, args...); + std::string result(size, 0); + std::snprintf(&result[0], size + 1, fmt, args...); + return result; + } +#else + inline boost::format & format_apply(boost::format & fmt) + { + return fmt; + } + + template + boost::format & format_apply(boost::format & fmt, T && data, Args&& ... args) + { + return format_apply(fmt % data, std::forward(args)...); + } + + template + std::string format(const char * fmt_str, Args&& ... args) + { + boost::format fmt(fmt_str); + str(format_apply(fmt, std::forward(args)...)); + } +#endif + +}} diff --git a/include/git2cpp/internal/optional.h b/include/git2cpp/internal/optional.h new file mode 100644 index 0000000..a20d440 --- /dev/null +++ b/include/git2cpp/internal/optional.h @@ -0,0 +1,158 @@ +#pragma once + +#ifdef USE_BOOST + #include + #include +#else + #include + #include +#endif + +namespace git { +namespace internal +{ +#ifdef USE_BOOST + using boost::optional; + using boost::in_place; + using boost::none_t; + using boost::none; + + template + optional & emplace(optional & opt, Args&&... args){ + opt = in_place(std::forward(args)...); + return opt; + } +#else + typedef nullptr_t none_t; + const constexpr none_t none = nullptr; + + //Simple (and incomplete) optional implementations + template + class optional + { + private: //type alias + typedef typename std::aligned_storage::type StorageT; + + public: //type traits + enum non_movable_t{}; + enum non_copyable_t{}; + + static const constexpr bool movable = std::is_move_constructible::value && std::is_move_assignable::value; + static const constexpr bool copyable = std::is_copy_constructible::value && std::is_copy_assignable::value; + typedef typename std::conditional::type MovableT; + typedef typename std::conditional::type CopyableT; + + public: //initializing and attribution + constexpr optional(none_t t = none) + : initialized(false) + {} + + optional(T const & v) { assign(v);} + optional(T && v) { assign(std::move(v));} + + optional(optional const & other) { assign(other);} + optional(optional && other) { assign(std::move(other));} + + optional & operator=(none_t none) { reset(); return *this;} + optional & operator=(T && v) { return assign(std::move(v));} + optional & operator=(const T & v) { return assign(v);} + + optional & operator=(optional const & other){ return assign(other);} + optional & operator=(optional && other){ return assign(std::move(other));} + + ~optional() { reset(); } + + public: //getting value + T const* get_ptr() const { return reinterpret_cast(&storage);} + T* get_ptr() { return reinterpret_cast(&storage);} + + const + T& value() const { return *get_ptr(); } + T& value() { return *get_ptr(); } + + T const & operator* () const { return value(); } + T & operator * () { return value(); } + + T const * operator -> () const { return get_ptr(); } + T * operator -> () { return get_ptr(); } + + public: //querying state + bool is_initialized() const { return initialized; } + + explicit operator bool() const { return is_initialized(); } + + public: //change state + void reset() + { + if (is_initialized()) + { + get_ptr()->~T(); + initialized = false; + } + } + + template + void emplace(Args&&... args){ + if (is_initialized()) + reset(); + init(std::forward(args)...); + } + + private: //assign + optional & assign(MovableT && value) { + return set_from_value(std::move(value)); + } + optional & assign(CopyableT const & value) { + return set_from_value(value); + } + optional & assign(optional const & other) { + return set_or_reset(other.value(), other.is_initialized()); + } + optional & assign(optional && other) { + return set_or_reset(std::move(other.value()), other.is_initialized()); + } + + protected: + template + optional & set_or_reset(U&& u, bool isValid) + { + if (isValid) + set_from_value(std::forward(u)); + else + reset(); + + return *this; + } + + template + optional & set_from_value(U&& u) + { + if(is_initialized()){ + reinterpret_cast(storage) = std::forward(u); + } + else{ + init(std::forward(u)); + } + + return *this; + } + + template + void init(Args&& ... args){ + new (&storage) T(std::forward(args)...); + initialized = true; + } + + protected: + StorageT storage; + bool initialized; + }; + + template + optional & emplace(optional & opt, Args&&... args){ + opt.emplace(std::forward(args)...); + return opt; + } +#endif + +}}//namespace git diff --git a/src/diff.cpp b/src/diff.cpp index e731422..3f9cc08 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -3,8 +3,12 @@ #include +#ifdef USE_BOOST #include #include +#else +#include +#endif namespace git { @@ -20,15 +24,31 @@ namespace git const type include_summary (GIT_DIFF_STATS_INCLUDE_SUMMARY); }} +#ifdef USE_BOOST + template + using map_container = boost::container::flat_map; +#else + struct EnumHash{ + template + std::size_t operator()(T t) const{ + return static_cast(t); + } + }; + + template + using map_container = std::unordered_map; +#endif + git_diff_format_t convert(format f) { - static const boost::container::flat_map converter - = boost::assign::list_of> - ( format::patch, GIT_DIFF_FORMAT_PATCH ) - ( format::patch_header, GIT_DIFF_FORMAT_PATCH_HEADER ) - ( format::raw, GIT_DIFF_FORMAT_RAW ) - ( format::name_only, GIT_DIFF_FORMAT_NAME_ONLY ) - ( format::name_status, GIT_DIFF_FORMAT_NAME_STATUS ) + static const map_container converter + = { + { format::patch, GIT_DIFF_FORMAT_PATCH }, + { format::patch_header, GIT_DIFF_FORMAT_PATCH_HEADER }, + { format::raw, GIT_DIFF_FORMAT_RAW }, + { format::name_only, GIT_DIFF_FORMAT_NAME_ONLY }, + { format::name_status, GIT_DIFF_FORMAT_NAME_STATUS } + } ; return converter.at(f); } diff --git a/src/repo.cpp b/src/repo.cpp index 7a5b7c2..945a11c 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -8,12 +8,13 @@ #include #include -#include -#include +#include #include "git2cpp/repo.h" #include "git2cpp/error.h" +#include "git2cpp/internal/optional.h" + namespace git { namespace @@ -162,13 +163,13 @@ namespace git { case GIT_OK: assert(type == type_); - ref_ = boost::in_place(ref); + internal::emplace(ref_, ref); break; case GIT_ITEROVER: - ref_ = boost::none; + ref_ = internal::none; break; default: - ref_ = boost::none; + ref_ = internal::none; throw std::logic_error("unknown git_branch_next error"); } } @@ -194,7 +195,7 @@ namespace git private: git_branch_t type_; git_branch_iterator * base_; - boost::optional ref_; + internal::optional ref_; }; std::vector Repository::branches(branch_type type) const diff --git a/src/tree.cpp b/src/tree.cpp index 4eee6f0..5b31de8 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -72,7 +72,7 @@ namespace git case GIT_ENOTFOUND: throw file_not_found_error(path); default: - throw error_t(boost::format("unknown error inside function: 'git_tree_entry_bypath': %1%") % status); + throw error_t(internal::format("unknown error inside function: 'git_tree_entry_bypath': %d", status)); } } From e04adb8da4b0ad96b35581815ddb43a246a3d116 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 15 Jun 2017 08:19:27 +0300 Subject: [PATCH 051/171] if possible use std::optional or std::experimental::optional --- CMakeLists.txt | 5 +- include/git2cpp/internal/optional.h | 108 +++++++++++++++++++++------- src/repo.cpp | 4 +- 3 files changed, 86 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3225050..82d78da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,6 @@ cmake_minimum_required(VERSION 2.8) # Build options OPTION( USE_BOOST "Enable use of boost header libraries" OFF ) - -set(CMAKE_CXX_FLAGS -std=c++11) - file(GLOB_RECURSE lib_sources src/*.cpp include/git2cpp/*.h @@ -29,6 +26,8 @@ target_include_directories(git2cpp target_link_libraries(git2cpp git2) +target_compile_features(git2cpp PUBLIC cxx_std_17) + install_targets(/lib git2cpp) set(examples diff --git a/include/git2cpp/internal/optional.h b/include/git2cpp/internal/optional.h index a20d440..5413a0f 100644 --- a/include/git2cpp/internal/optional.h +++ b/include/git2cpp/internal/optional.h @@ -3,6 +3,16 @@ #ifdef USE_BOOST #include #include + #define GIT_USE_BOOST_OPTIONAL + +#elif defined(__has_include) && __has_include() + #include + #define GIT_USE_STD_OPTIONAL + +#elif defined(__has_include) && __has_include() + #include + #define GIT_USE_STD_EXPERIMENTAL_OPTIONAL + #else #include #include @@ -11,20 +21,66 @@ namespace git { namespace internal { -#ifdef USE_BOOST +#if defined(GIT_USE_BOOST_OPTIONAL) + #undef GIT_USE_BOOST_OPTIONAL using boost::optional; - using boost::in_place; using boost::none_t; using boost::none; template - optional & emplace(optional & opt, Args&&... args){ - opt = in_place(std::forward(args)...); + optional & emplace(optional & opt, Args&&... args) + { + opt = boost::in_place(std::forward(args)...); + return opt; + } + + template + bool has_value(optional const & opt) + { + return opt.is_initialized(); + } + +#elif defined(GIT_USE_STD_OPTIONAL) + #undef GIT_USE_STD_OPTIONAL + using std::optional; + using none_t = std::nullopt_t; + const none_t none = std::nullopt; + + template + optional & emplace(optional & opt, Args&&... args) + { + opt.emplace(std::forward(args)...); + return opt; + } + + template + bool has_value(optional const & opt) + { + return opt.has_value(); + } + +#elif defined(GIT_USE_STD_EXPERIMENTAL_OPTIONAL) + #undef GIT_USE_STD_EXPERIMENTAL_OPTIONAL + using std::experimental::optional; + using none_t = std::experimental::nullopt_t; + const none_t none = std::experimental::nullopt; + + template + optional & emplace(optional & opt, Args&&... args) + { + opt.emplace(std::forward(args)...); return opt; } + + template + bool has_value(optional const & opt) + { + return static_cast(opt); + } + #else - typedef nullptr_t none_t; - const constexpr none_t none = nullptr; + typedef std::nullptr_t none_t; + const none_t none = nullptr; //Simple (and incomplete) optional implementations template @@ -37,8 +93,8 @@ namespace internal enum non_movable_t{}; enum non_copyable_t{}; - static const constexpr bool movable = std::is_move_constructible::value && std::is_move_assignable::value; - static const constexpr bool copyable = std::is_copy_constructible::value && std::is_copy_assignable::value; + static const bool movable = std::is_move_constructible::value && std::is_move_assignable::value; + static const bool copyable = std::is_copy_constructible::value && std::is_copy_assignable::value; typedef typename std::conditional::type MovableT; typedef typename std::conditional::type CopyableT; @@ -63,37 +119,33 @@ namespace internal ~optional() { reset(); } public: //getting value - T const* get_ptr() const { return reinterpret_cast(&storage);} - T* get_ptr() { return reinterpret_cast(&storage);} - const - T& value() const { return *get_ptr(); } - T& value() { return *get_ptr(); } + T const & value() const { return reinterpret_cast(storage); } + T & value() { return reinterpret_cast(storage); } T const & operator* () const { return value(); } T & operator * () { return value(); } - T const * operator -> () const { return get_ptr(); } - T * operator -> () { return get_ptr(); } + T const * operator -> () const { return &value(); } + T * operator -> () { return &value(); } public: //querying state - bool is_initialized() const { return initialized; } - explicit operator bool() const { return is_initialized(); } + explicit operator bool() const { return initialized; } public: //change state void reset() { - if (is_initialized()) + if (initialized) { - get_ptr()->~T(); + value().~T(); initialized = false; } } template void emplace(Args&&... args){ - if (is_initialized()) + if (initialized) reset(); init(std::forward(args)...); } @@ -106,10 +158,10 @@ namespace internal return set_from_value(value); } optional & assign(optional const & other) { - return set_or_reset(other.value(), other.is_initialized()); + return set_or_reset(other.value(), other.initialized); } optional & assign(optional && other) { - return set_or_reset(std::move(other.value()), other.is_initialized()); + return set_or_reset(std::move(other.value()), other.initialized); } protected: @@ -127,12 +179,10 @@ namespace internal template optional & set_from_value(U&& u) { - if(is_initialized()){ + if (initialized) reinterpret_cast(storage) = std::forward(u); - } - else{ + else init(std::forward(u)); - } return *this; } @@ -153,6 +203,12 @@ namespace internal opt.emplace(std::forward(args)...); return opt; } + + template + bool has_value(optional const & opt) + { + return static_cast(opt); + } #endif }}//namespace git diff --git a/src/repo.cpp b/src/repo.cpp index 945a11c..d043194 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -153,7 +153,7 @@ namespace git git_branch_iterator_free(base_); } - explicit operator bool () const { return ref_.is_initialized(); } + explicit operator bool () const { return internal::has_value(ref_); } void operator ++ () { @@ -176,7 +176,7 @@ namespace git Reference const * operator -> () const { - return ref_.get_ptr(); + return &ref_.value(); } private: From 0ff67f2f09012c447f565f0954a2bc0e87511025 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 15 Jun 2017 08:46:09 +0300 Subject: [PATCH 052/171] code cosmetics --- examples/add.cpp | 2 +- examples/log.cpp | 2 +- examples/rev-parse.cpp | 4 ++-- examples/status.cpp | 36 +++++++++++++++++++++--------------- include/git2cpp/error.h | 4 +++- include/git2cpp/repo.h | 5 +++-- include/git2cpp/status.h | 5 ----- src/repo.cpp | 16 +++++++++++----- 8 files changed, 42 insertions(+), 32 deletions(-) diff --git a/examples/add.cpp b/examples/add.cpp index 48cecbe..7eeee6e 100644 --- a/examples/add.cpp +++ b/examples/add.cpp @@ -98,7 +98,7 @@ int main (int argc, char** argv) init_array(&array, argc-i, argv+i); - git::Initializer threads_initializer; + auto_git_initializer; git::Repository repo("."); diff --git a/examples/log.cpp b/examples/log.cpp index 3b814c3..336f6ed 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -28,7 +28,7 @@ static void usage(const char *message, const char *arg) struct log_state { - std::string repodir = "."; + const char * repodir = "."; git::internal::optional repo; git::internal::optional walker; int hide = 0; diff --git a/examples/rev-parse.cpp b/examples/rev-parse.cpp index 7ff1335..d9c310d 100644 --- a/examples/rev-parse.cpp +++ b/examples/rev-parse.cpp @@ -23,7 +23,7 @@ static void usage(const char *message, const char *arg) struct parse_state { internal::optional repo; - std::string repodir = "."; + const char * repodir = "."; }; void parse_revision(parse_state & ps, const char *revstr) @@ -53,7 +53,7 @@ void parse_revision(parse_state & ps, const char *revstr) int main(int argc, char *argv[]) { - Initializer threads_initalizer; + auto_git_initializer; parse_state ps; diff --git a/examples/status.cpp b/examples/status.cpp index 469134f..7e884df 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -9,6 +9,8 @@ #include #include +#include +#include #include "git2cpp/initializer.h" #include "git2cpp/repo.h" @@ -40,15 +42,20 @@ enum { * - A sample status formatter that matches the "short" format */ +bool starts_with(std::string_view str, std::string_view prefix) +{ + return str.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), str.begin()); +} + void show_branch(Repository const & repo, int format) { - const char * branch = nullptr; + std::optional branch; try - { - Reference head = repo.head(); - branch = head.name(); - if (!strncmp(branch, "refs/heads/", strlen("refs/heads/"))) - branch += strlen("refs/heads/"); + { + branch = repo.head().name(); + static const std::string_view refs_heads = "refs/heads/"; + if (starts_with(*branch, refs_heads)) + branch->remove_prefix(refs_heads.length()); } catch (non_existing_branch_error const &) {} catch (missing_head_error const &) {} @@ -57,11 +64,10 @@ void show_branch(Repository const & repo, int format) throw e; } - if (format == FORMAT_LONG) - printf("# On branch %s\n", - branch ? branch : "Not currently on any branch."); - else - printf("## %s\n", branch ? branch : "HEAD (no branch)"); + if (format == FORMAT_LONG) + printf("# On branch %s\n", branch.value_or("Not currently on any branch.")); + else + printf("## %s\n", branch.value_or("HEAD (no branch)")); } void print_long(Status const & status) @@ -95,7 +101,7 @@ void print_long(Status const & status) if (s.status & GIT_STATUS_INDEX_TYPECHANGE) istatus = "typechange:"; - if (istatus == NULL) + if (!istatus) continue; if (!header) { @@ -311,9 +317,9 @@ void print_short(Repository const & repo, Status const & status) int main(int argc, char *argv[]) { - git::Initializer threads_initializer; + auto_git_initializer; - int i, npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0; + int npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0; git_status_options opt = GIT_STATUS_OPTIONS_INIT; const char *repodir = "."; @@ -325,7 +331,7 @@ int main(int argc, char *argv[]) GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | GIT_STATUS_OPT_SORT_CASE_SENSITIVELY; - for (i = 1; i < argc; ++i) { + for (int i = 1; i < argc; ++i) { if (argv[i][0] != '-') { if (npaths < MAX_PATHSPEC) { diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 1d9f0a2..9e71f05 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -15,7 +15,9 @@ namespace git struct repository_open_error : error_t { - repository_open_error() : error_t("Could not open repository") {} + repository_open_error(std::string const & dir) + : error_t("Could not open repository on path " + dir) + {} }; struct repository_init_error : error_t diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 0da5969..16d62d2 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -89,12 +89,13 @@ namespace git Tree const & tree, Commit const & parent); + explicit Repository(const char * dir); explicit Repository(std::string const & dir); struct init_tag {}; static init_tag init; - Repository(std::string const & dir, init_tag); - Repository(std::string const & dir, init_tag, git_repository_init_options opts); + Repository(const char * dir, init_tag); + Repository(const char * dir, init_tag, git_repository_init_options opts); Repository (Repository const &) = delete; Repository& operator = (Repository const &) = delete; diff --git a/include/git2cpp/status.h b/include/git2cpp/status.h index 90cb406..e1a2245 100644 --- a/include/git2cpp/status.h +++ b/include/git2cpp/status.h @@ -1,13 +1,8 @@ #pragma once -extern "C" -{ #include #include #include -} - -struct git_status_list; namespace git { diff --git a/src/repo.cpp b/src/repo.cpp index d043194..7c44d6d 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -27,21 +27,27 @@ namespace git } } + Repository::Repository(const char * dir) + { + if (git_repository_open_ext(&repo_, dir, 0, NULL)) + throw repository_open_error(dir); + } + Repository::Repository(std::string const & dir) { if (git_repository_open_ext(&repo_, dir.c_str(), 0, NULL)) - throw repository_open_error(); + throw repository_open_error(dir); } - Repository::Repository(std::string const & dir, init_tag) + Repository::Repository(const char * dir, init_tag) { - if (git_repository_init(&repo_, dir.c_str(), 0) < 0) + if (git_repository_init(&repo_, dir, 0) < 0) throw repository_init_error(dir); } - Repository::Repository(std::string const & dir, init_tag, git_repository_init_options opts) + Repository::Repository(const char * dir, init_tag, git_repository_init_options opts) { - if (git_repository_init_ext(&repo_, dir.c_str(), &opts) < 0) + if (git_repository_init_ext(&repo_, dir, &opts) < 0) throw repository_init_error(dir); } From 758b8963956934456a211e01c44b5716e0210781 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 19 Jun 2017 08:39:54 +0300 Subject: [PATCH 053/171] wrap status options --- examples/status.cpp | 24 +++++-------- include/git2cpp/repo.h | 2 +- include/git2cpp/status.h | 34 +++++++++++++++++- src/repo.cpp | 12 +++---- src/status.cpp | 76 ++++++++++++++++++++++++++++++++++++++-- 5 files changed, 123 insertions(+), 25 deletions(-) diff --git a/examples/status.cpp b/examples/status.cpp index 7e884df..f9c7a09 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -320,16 +320,13 @@ int main(int argc, char *argv[]) auto_git_initializer; int npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0; - git_status_options opt = GIT_STATUS_OPTIONS_INIT; + Status::Options opt; const char *repodir = "."; const size_t MAX_PATHSPEC = 8; char * pathspec[MAX_PATHSPEC]; - opt.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; - opt.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | - GIT_STATUS_OPT_SORT_CASE_SENSITIVELY; + opt.include_untracked().renames_head_to_index(); for (int i = 1; i < argc; ++i) { if (argv[i][0] != '-') { @@ -357,19 +354,18 @@ int main(int argc, char *argv[]) format = FORMAT_PORCELAIN; } else if (!strcmp(argv[i], "--ignored")) - opt.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED; + opt.include_ignored(); else if (!strcmp(argv[i], "-uno") || !strcmp(argv[i], "--untracked-files=no")) - opt.flags &= ~GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opt.exclude_untracked(); else if (!strcmp(argv[i], "-unormal") || !strcmp(argv[i], "--untracked-files=normal")) - opt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opt.include_untracked(); else if (!strcmp(argv[i], "-uall") || !strcmp(argv[i], "--untracked-files=all")) - opt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; + opt.include_untracked().recurse_untracked_dirs(); else if (!strcmp(argv[i], "--ignore-submodules=all")) - opt.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES; + opt.exclude_submodules(); else if (!strncmp(argv[i], "--git-dir=", strlen("--git-dir="))) repodir = argv[i] + strlen("--git-dir="); else @@ -383,10 +379,8 @@ int main(int argc, char *argv[]) format = FORMAT_LONG; if (format == FORMAT_LONG) showbranch = 1; - if (npaths > 0) { - opt.pathspec.strings = pathspec; - opt.pathspec.count = npaths; - } + if (npaths > 0) + opt.set_pathspec(pathspec, npaths); Repository repo(repodir); diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 16d62d2..c891b27 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -58,7 +58,7 @@ namespace git Signature signature() const; - Status status(git_status_options const &) const; + Status status(Status::Options const &) const; StrArray reference_list() const; diff --git a/include/git2cpp/status.h b/include/git2cpp/status.h index e1a2245..4b949f6 100644 --- a/include/git2cpp/status.h +++ b/include/git2cpp/status.h @@ -8,7 +8,39 @@ namespace git { struct Status { - Status(git_repository * repo, git_status_options const & opts); + struct Options + { + enum class Show + { + IndexOnly, + WorkdirOnly, + IndexAndWorkdir + }; + + enum class Sort + { + CaseSensitively, + CaseInsensitively, + }; + + Options(Show = Show::IndexAndWorkdir, Sort = Sort::CaseSensitively); + + Options& include_untracked(); + Options& exclude_untracked(); + Options& renames_head_to_index(); + Options& include_ignored(); + Options& recurse_untracked_dirs(); + Options& exclude_submodules(); + + void set_pathspec(char ** ptr, size_t size); + + git_status_options const * raw() const { return &opts_; } + + private: + git_status_options opts_; + }; + + Status(git_repository * repo, Options const & opts); ~Status(); size_t entrycount() const; diff --git a/src/repo.cpp b/src/repo.cpp index 7c44d6d..3dd52b4 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -1,3 +1,8 @@ +#include "git2cpp/repo.h" + +#include "git2cpp/error.h" +#include "git2cpp/internal/optional.h" + #include #include #include @@ -10,11 +15,6 @@ #include -#include "git2cpp/repo.h" -#include "git2cpp/error.h" - -#include "git2cpp/internal/optional.h" - namespace git { namespace @@ -257,7 +257,7 @@ namespace git return Reference(ref); } - Status Repository::status(git_status_options const & opts) const + Status Repository::status(Status::Options const & opts) const { return Status(repo_, opts); } diff --git a/src/status.cpp b/src/status.cpp index d6956a6..abf72b4 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -16,9 +16,81 @@ namespace git throw error_t("status entry index out of bounds: " + std::to_string(i)); } - Status::Status(git_repository * repo, git_status_options const & opts) + namespace { - if (git_status_list_new(&status_, repo, &opts)) + git_status_show_t convert(Status::Options::Show show) + { + switch (show) + { + case Status::Options::Show::IndexOnly: return GIT_STATUS_SHOW_INDEX_ONLY; + case Status::Options::Show::WorkdirOnly: return GIT_STATUS_SHOW_INDEX_ONLY; + default: + return GIT_STATUS_SHOW_INDEX_AND_WORKDIR; + } + } + } + + Status::Options::Options(Show show, Sort sort) + : opts_(GIT_STATUS_OPTIONS_INIT) + { + opts_.show = convert(show); + + switch (sort) + { + case Sort::CaseSensitively: + opts_.flags |= GIT_STATUS_OPT_SORT_CASE_SENSITIVELY; + break; + case Sort::CaseInsensitively: + opts_.flags |= GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY; + break; + } + } + + void Status::Options::set_pathspec(char ** ptr, size_t size) + { + opts_.pathspec.strings = ptr; + opts_.pathspec.count = size; + } + + Status::Options& Status::Options::include_untracked() + { + opts_.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + return *this; + } + + Status::Options& Status::Options::exclude_untracked() + { + opts_.flags &= ~GIT_STATUS_OPT_INCLUDE_UNTRACKED; + return *this; + } + + Status::Options& Status::Options::recurse_untracked_dirs() + { + opts_.flags |= GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; + return *this; + } + + Status::Options& Status::Options::exclude_submodules() + { + opts_.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES; + return *this; + } + + Status::Options& Status::Options::include_ignored() + { + opts_.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED; + return *this; + } + + Status::Options& Status::Options::renames_head_to_index() + { + opts_.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + return *this; + } + + Status::Status(git_repository * repo, Options const & opts) + { + if (git_status_list_new(&status_, repo, opts.raw())) throw get_status_error(); } From 191bf529db57d7f3c196082b4d640ef9a3253467 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 19 Jun 2017 08:40:14 +0300 Subject: [PATCH 054/171] + Index::add(path) --- include/git2cpp/index.h | 5 +++++ src/index.cpp | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/git2cpp/index.h b/include/git2cpp/index.h index 361ebe8..3fd5889 100644 --- a/include/git2cpp/index.h +++ b/include/git2cpp/index.h @@ -1,5 +1,7 @@ #pragma once +#include + #include struct git_index; @@ -24,6 +26,9 @@ namespace git void update_all (git_strarray const & pathspec, matched_path_callback_t cb); void add_all (git_strarray const & pathspec, matched_path_callback_t cb, unsigned int flags = 0); + void add_path(const char *); + void add_path(std::string const &); + git_oid write_tree() const; void write() const; diff --git a/src/index.cpp b/src/index.cpp index 9ce5335..e17c14b 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -71,6 +71,17 @@ namespace git assert(res == 0); } + void Index::add_path(const char * path) + { + int res = git_index_add_bypath(index_, path); + assert(res == 0); + } + + void Index::add_path(std::string const & path) + { + add_path(path.c_str()); + } + void Index::write() const { if (git_index_write(index_)) From e36ecf4f0ae1da54504f0c39e2b764f22cdfd1b7 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 20 Jun 2017 14:02:08 -0700 Subject: [PATCH 055/171] examples/status: printf -> std::cout --- examples/status.cpp | 192 ++++++++++++++++++++++---------------------- 1 file changed, 98 insertions(+), 94 deletions(-) diff --git a/examples/status.cpp b/examples/status.cpp index f9c7a09..e01320c 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -4,8 +4,6 @@ * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ -#include -#include #include #include @@ -65,20 +63,22 @@ void show_branch(Repository const & repo, int format) } if (format == FORMAT_LONG) - printf("# On branch %s\n", branch.value_or("Not currently on any branch.")); + std::cout << "# On branch " << branch.value_or("Not currently on any branch."); else - printf("## %s\n", branch.value_or("HEAD (no branch)")); + std::cout<< "## ", branch.value_or("HEAD (no branch)"); + std::cout << "\n"; } void print_long(Status const & status) { size_t maxi = status.entrycount(); - int header = 0, changes_in_index = 0; - int changed_in_workdir = 0, rm_in_workdir = 0; + int rm_in_workdir = 0; const char *old_path, *new_path; /* print index changes */ + bool changes_in_index = false; + for (size_t i = 0; i < maxi; ++i) { auto const & s = status[i]; @@ -104,27 +104,32 @@ void print_long(Status const & status) if (!istatus) continue; - if (!header) { - printf("# Changes to be committed:\n"); - printf("# (use \"git reset HEAD ...\" to unstage)\n"); - printf("#\n"); - header = 1; - } + if (!changes_in_index) { + std::cout << "# Changes to be committed:\n" + << "# (use \"git reset HEAD ...\" to unstage)\n" + << "#\n"; + changes_in_index = true; + } + + std::cout << "#\t" << istatus << " "; old_path = s.head_to_index->old_file.path; new_path = s.head_to_index->new_file.path; if (old_path && new_path && strcmp(old_path, new_path)) - printf("#\t%s %s -> %s\n", istatus, old_path, new_path); + std::cout << old_path << " -> " << new_path; + else if (old_path) + std::cout << old_path; else - printf("#\t%s %s\n", istatus, old_path ? old_path : new_path); - } + std::cout << new_path; - if (header) { - changes_in_index = 1; - printf("#\n"); + std::cout << "\n"; } - header = 0; + + if (changes_in_index) + std::cout << "#\n"; + + bool changed_in_workdir = false; /* print workdir changes to tracked files */ @@ -145,92 +150,95 @@ void print_long(Status const & status) if (s.status & GIT_STATUS_WT_TYPECHANGE) wstatus = "typechange:"; - if (wstatus == NULL) - continue; + if (!wstatus) + continue; - if (!header) { - printf("# Changes not staged for commit:\n"); - printf("# (use \"git add%s ...\" to update what will be committed)\n", rm_in_workdir ? "/rm" : ""); - printf("# (use \"git checkout -- ...\" to discard changes in working directory)\n"); - printf("#\n"); - header = 1; - } + if (!changed_in_workdir) { + std::cout << "# Changes not staged for commit:\n" + << "# (use \"git add" << (rm_in_workdir ? "/rm" : "") << "...\" to update what will be committed)\n" + << "# (use \"git checkout -- ...\" to discard changes in working directory)\n" + << "#\n"; + changed_in_workdir = true; + } + + std::cout << "#\t" << wstatus << " "; old_path = s.index_to_workdir->old_file.path; new_path = s.index_to_workdir->new_file.path; - if (old_path && new_path && strcmp(old_path, new_path)) - printf("#\t%s %s -> %s\n", wstatus, old_path, new_path); - else - printf("#\t%s %s\n", wstatus, old_path ? old_path : new_path); - } - - if (header) { - changed_in_workdir = 1; - printf("#\n"); - } - header = 0; - - /* print untracked files */ + if (old_path && new_path && strcmp(old_path, new_path)) + std::cout << old_path << " -> " << new_path; + else if (old_path) + std::cout << old_path; + else + std::cout << new_path; + std::cout << "\n"; + } - header = 0; + if (changed_in_workdir) + std::cout << "#\n"; - for (size_t i = 0; i < maxi; ++i) { + /* print untracked files */ + bool were_untracked_files = false; + for (size_t i = 0; i < maxi; ++i) + { auto const & s = status[i]; - if (s.status == GIT_STATUS_WT_NEW) { - - if (!header) { - printf("# Untracked files:\n"); - printf("# (use \"git add ...\" to include in what will be committed)\n"); - printf("#\n"); - header = 1; - } - - printf("#\t%s\n", s.index_to_workdir->old_file.path); - } - } + if (s.status == GIT_STATUS_WT_NEW) + { + if (!were_untracked_files) + { + std::cout << "# Untracked files:\n" + << "# (use \"git add ...\" to include in what will be committed)\n" + << "#\n"; + were_untracked_files = true; + } - header = 0; + std::cout << "#\t" << s.index_to_workdir->old_file.path << "\n"; + } + } - /* print ignored files */ + /* print ignored files */ + bool were_ignored_files = false; - for (size_t i = 0; i < maxi; ++i) { + for (size_t i = 0; i < maxi; ++i) { auto const & s = status[i]; - if (s.status == GIT_STATUS_IGNORED) { - - if (!header) { - printf("# Ignored files:\n"); - printf("# (use \"git add -f ...\" to include in what will be committed)\n"); - printf("#\n"); - header = 1; - } + if (s.status == GIT_STATUS_IGNORED) + { + if (!were_ignored_files) + { + std::cout << "# Ignored files:\n" + << "# (use \"git add -f ...\" to include in what will be committed)\n" + << "#\n"; + were_ignored_files = true; + } - printf("#\t%s\n", s.index_to_workdir->old_file.path); - } - } + std::cout << "#\t" << s.index_to_workdir->old_file.path << "\n"; + } + } - if (!changes_in_index && changed_in_workdir) - printf("no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"); + if (!changes_in_index && changed_in_workdir) + std::cout << "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"; } void print_short(Repository const & repo, Status const & status) { - size_t maxi = status.entrycount(); - char istatus, wstatus; - const char *extra, *a, *b, *c; + size_t maxi = status.entrycount(); - for (size_t i = 0; i < maxi; ++i) + for (size_t i = 0; i < maxi; ++i) { auto const & s = status[i]; if (s.status == GIT_STATUS_CURRENT) - continue; + continue; - a = b = c = NULL; - istatus = wstatus = ' '; - extra = ""; + const char *a = nullptr; + const char *b = nullptr; + const char *c = nullptr; + char istatus = ' '; + char wstatus = ' '; + const char *extra = ""; if (s.status & GIT_STATUS_INDEX_NEW) istatus = 'A'; @@ -294,25 +302,21 @@ void print_short(Repository const & repo, Status const & status) c = s.index_to_workdir->new_file.path; } - if (istatus == 'R') { - if (wstatus == 'R') - printf("%c%c %s %s %s%s\n", istatus, wstatus, a, b, c, extra); - else - printf("%c%c %s %s%s\n", istatus, wstatus, a, b, extra); - } else { - if (wstatus == 'R') - printf("%c%c %s %s%s\n", istatus, wstatus, a, c, extra); - else - printf("%c%c %s%s\n", istatus, wstatus, a, extra); - } - } + std::cout << istatus << wstatus << ' ' << a; + if (istatus == 'R') + std::cout << ' ' << b; + if (wstatus == 'R') + std::cout << ' ' << c; + std::cout << extra << "\n"; + } - for (size_t i = 0; i < maxi; ++i) { + for (size_t i = 0; i < maxi; ++i) + { auto const & s = status[i]; if (s.status == GIT_STATUS_WT_NEW) - printf("?? %s\n", s.index_to_workdir->old_file.path); - } + std::cout << "?? " << s.index_to_workdir->old_file.path << "\n"; + } } int main(int argc, char *argv[]) From e4a624b575e4affc055ec98d237fbb02b92857b2 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 20 Jun 2017 14:06:38 -0700 Subject: [PATCH 056/171] Bundle libgit2 and CMake fixes for MSVC --- .gitmodules | 3 +++ CMakeLists.txt | 68 +++++++++++++++++++++++++++++++------------------- libs/libgit2 | 1 + 3 files changed, 46 insertions(+), 26 deletions(-) create mode 100644 .gitmodules create mode 160000 libs/libgit2 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..102276c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libs/libgit2"] + path = libs/libgit2 + url = git@github.com:AndreyG/libgit2.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 82d78da..8f87c8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,20 +2,30 @@ project (libgit2cpp) cmake_minimum_required(VERSION 2.8) # Build options -OPTION( USE_BOOST "Enable use of boost header libraries" OFF ) - -file(GLOB_RECURSE lib_sources - src/*.cpp - include/git2cpp/*.h -) +OPTION(USE_BOOST "Enable use of boost header libraries" OFF) IF(USE_BOOST) - add_definitions(-DUSE_BOOST=1) - find_package(Boost REQUIRED) - include_directories(${BOOST_INCLUDEDIR}) + add_definitions(-DUSE_BOOST=1) + find_package(Boost REQUIRED) + include_directories(${BOOST_INCLUDEDIR}) ENDIF() -add_library(git2cpp ${lib_sources}) +if (MSVC) + OPTION(BUNDLE_LIBGIT2 "use bundled libgit2" ON) +else() + OPTION(BUNDLE_LIBGIT2 "use bundled libgit2" OFF) +endif() + +if (BUNDLE_LIBGIT2) + add_subdirectory(libs/libgit2) +endif() + +file(GLOB_RECURSE lib_sources + src/*.cpp + include/git2cpp/*.h +) + +add_library(git2cpp STATIC ${lib_sources}) target_include_directories(git2cpp PRIVATE @@ -26,28 +36,34 @@ target_include_directories(git2cpp target_link_libraries(git2cpp git2) -target_compile_features(git2cpp PUBLIC cxx_std_17) +set_target_properties(git2cpp PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED YES + INTERFACE_COMPILE_FEATURES cxx_std_17 +) -install_targets(/lib git2cpp) +if (MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") +endif() set(examples - add - branch - cat-file - diff - log - rev-list - showindex - status - init - rev-parse - general - commit-graph-generator + add + branch + cat-file + diff + log + rev-list + showindex + status + init + rev-parse + general + commit-graph-generator ) foreach (example ${examples}) - add_executable(${example} examples/${example}.cpp) - target_link_libraries(${example} git2cpp) + add_executable("${example}-cpp" examples/${example}.cpp) + target_link_libraries("${example}-cpp" git2cpp) endforeach(example) file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) diff --git a/libs/libgit2 b/libs/libgit2 new file mode 160000 index 0000000..eb1b844 --- /dev/null +++ b/libs/libgit2 @@ -0,0 +1 @@ +Subproject commit eb1b844b8f54c331a2b62651ab5a8e4708a9ed09 From 0d146e2e4e593eff41a2c8d0620a678bac8d96e4 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 20 Jun 2017 14:08:45 -0700 Subject: [PATCH 057/171] fix msvc compilation errors and warnings --- examples/cat-file.cpp | 2 +- examples/init.cpp | 2 +- examples/log.cpp | 15 ++++++--------- include/git2cpp/repo.h | 4 ++-- src/blob.cpp | 2 +- src/repo.cpp | 8 ++++++++ 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/examples/cat-file.cpp b/examples/cat-file.cpp index b973c11..6dadc7f 100644 --- a/examples/cat-file.cpp +++ b/examples/cat-file.cpp @@ -64,7 +64,7 @@ static void print_signature(const char *header, const git_signature *sig) static void show_blob(const git_blob *blob) { /* ? Does this need crlf filtering? */ - fwrite(git_blob_rawcontent(blob), git_blob_rawsize(blob), 1, stdout); + fwrite(git_blob_rawcontent(blob), static_cast(git_blob_rawsize(blob)), 1, stdout); } static void show_tree(const git_tree *tree) diff --git a/examples/init.cpp b/examples/init.cpp index 700eade..c5ee1a5 100644 --- a/examples/init.cpp +++ b/examples/init.cpp @@ -108,7 +108,7 @@ int main(int argc, char *argv[]) const char *templ = NULL, *gitdir = NULL, *dir = NULL; size_t pfxlen; - Initializer threads_initializer; + auto_git_initializer; /* Process arguments */ diff --git a/examples/log.cpp b/examples/log.cpp index 336f6ed..922cb4f 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -127,11 +127,8 @@ void add_revision(struct log_state *s, const char *revstr) static void print_time(const git_time *intime, const char *prefix) { char sign, out[32]; - struct tm intm; - int offset, hours, minutes; - time_t t; - offset = intime->offset; + int offset = intime->offset; if (offset < 0) { sign = '-'; offset = -offset; @@ -139,13 +136,13 @@ static void print_time(const git_time *intime, const char *prefix) sign = '+'; } - hours = offset / 60; - minutes = offset % 60; + int hours = offset / 60; + int minutes = offset % 60; - t = (time_t)intime->time + (intime->offset * 60); + time_t t = static_cast(intime->time) + (intime->offset * 60); - gmtime_r(&t, &intm); - strftime(out, sizeof(out), "%a %b %e %T %Y", &intm); + auto intm = gmtime(&t); + strftime(out, sizeof(out), "%a %b %e %T %Y", intm); printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); } diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index c891b27..120b9b4 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -93,14 +93,14 @@ namespace git explicit Repository(std::string const & dir); struct init_tag {}; - static init_tag init; + static const init_tag init; Repository(const char * dir, init_tag); Repository(const char * dir, init_tag, git_repository_init_options opts); Repository (Repository const &) = delete; Repository& operator = (Repository const &) = delete; - Repository(Repository &&); + Repository(Repository &&) noexcept; ~Repository(); diff --git a/src/blob.cpp b/src/blob.cpp index 118c4a7..0d044de 100644 --- a/src/blob.cpp +++ b/src/blob.cpp @@ -21,7 +21,7 @@ namespace git std::size_t Blob::size() const { - return git_blob_rawsize(blob_); + return static_cast(git_blob_rawsize(blob_)); } const void * Blob::content() const diff --git a/src/repo.cpp b/src/repo.cpp index 3dd52b4..2988583 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -27,6 +27,8 @@ namespace git } } + const Repository::init_tag Repository::init; + Repository::Repository(const char * dir) { if (git_repository_open_ext(&repo_, dir, 0, NULL)) @@ -51,6 +53,12 @@ namespace git throw repository_init_error(dir); } + Repository::Repository(Repository&& other) noexcept + : repo_(other.repo_) + { + other.repo_ = nullptr; + } + Repository::~Repository() { git_repository_free(repo_); From c47199f5a890996ec996c0015e446f7c0fdfae13 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 26 Jun 2017 09:15:05 +0300 Subject: [PATCH 058/171] code cosmetics --- examples/log.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/log.cpp b/examples/log.cpp index 922cb4f..88f17d2 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -294,7 +294,7 @@ int main(int argc, char *argv[]) opt.max_parents = -1; opt.limit = -1; - git::Initializer threads_initializer; + auto_git_initializer; log_state s; @@ -302,7 +302,7 @@ int main(int argc, char *argv[]) int parsed_options_num = parse_options(argc, argv, s, opt, count); if (!count) - add_revision(&s, NULL); + add_revision(&s, nullptr); git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; diffopts.pathspec.strings = &argv[parsed_options_num]; From 47bca58f48d90ee4cac6dcd4f8ff6b66bec34e62 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 26 Jun 2017 09:15:17 +0300 Subject: [PATCH 059/171] warninig fixes for 64-bit --- src/commit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commit.cpp b/src/commit.cpp index 633a328..0a6a6a7 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -10,7 +10,7 @@ namespace git Commit Commit::parent(size_t i) const { git_commit * parent; - if (git_commit_parent(&parent, commit_, i)) + if (git_commit_parent(&parent, commit_, static_cast(i))) throw commit_parent_error(id()); return Commit(parent, *repo_); } @@ -35,7 +35,7 @@ namespace git git_oid const & Commit::parent_id(size_t i) const { - return *git_commit_parent_id(commit_, i); + return *git_commit_parent_id(commit_, static_cast(i)); } git_signature const * Commit::author() const From e975242c4766068dd22335c451d2e531f03355c4 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 28 Jun 2017 14:53:50 +0300 Subject: [PATCH 060/171] switch submodule libs/libgit2 to upstream --- .gitmodules | 2 +- libs/libgit2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 102276c..4acd4b3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "libs/libgit2"] path = libs/libgit2 - url = git@github.com:AndreyG/libgit2.git + url = https://github.com/libgit2/libgit2.git diff --git a/libs/libgit2 b/libs/libgit2 index eb1b844..c26ce78 160000 --- a/libs/libgit2 +++ b/libs/libgit2 @@ -1 +1 @@ -Subproject commit eb1b844b8f54c331a2b62651ab5a8e4708a9ed09 +Subproject commit c26ce78404b7fc7356c56bd2c57611fd60a3705b From 4a9db3b63e86b6f1db6e57adec7c6cfd48217762 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 28 Jun 2017 23:56:39 +0300 Subject: [PATCH 061/171] code cosmetics --- examples/log.cpp | 6 ++---- include/git2cpp/id_to_str.h | 3 --- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/examples/log.cpp b/examples/log.cpp index 88f17d2..37d7497 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -4,8 +4,6 @@ #include -#include - #include "git2cpp/repo.h" #include "git2cpp/pathspec.h" #include "git2cpp/initializer.h" @@ -294,7 +292,7 @@ int main(int argc, char *argv[]) opt.max_parents = -1; opt.limit = -1; - auto_git_initializer; + git::Initializer threads_initializer; log_state s; @@ -302,7 +300,7 @@ int main(int argc, char *argv[]) int parsed_options_num = parse_options(argc, argv, s, opt, count); if (!count) - add_revision(&s, nullptr); + add_revision(&s, NULL); git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; diffopts.pathspec.strings = &argv[parsed_options_num]; diff --git a/include/git2cpp/id_to_str.h b/include/git2cpp/id_to_str.h index 84e94fb..0866bfd 100644 --- a/include/git2cpp/id_to_str.h +++ b/include/git2cpp/id_to_str.h @@ -2,10 +2,7 @@ #include -extern "C" -{ #include -} namespace git { From 9157305070f3803700bc660aca208abb252dda8e Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 29 Jun 2017 00:04:25 +0300 Subject: [PATCH 062/171] bug fix: missing return --- include/git2cpp/internal/format.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2cpp/internal/format.h b/include/git2cpp/internal/format.h index 651d729..2dbb7c9 100644 --- a/include/git2cpp/internal/format.h +++ b/include/git2cpp/internal/format.h @@ -36,7 +36,7 @@ namespace internal std::string format(const char * fmt_str, Args&& ... args) { boost::format fmt(fmt_str); - str(format_apply(fmt, std::forward(args)...)); + return str(format_apply(fmt, std::forward(args)...)); } #endif From b305a0af024453a8e3ac7038db9267401c887119 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 29 Jun 2017 00:05:55 +0300 Subject: [PATCH 063/171] warning fixes --- include/git2cpp/buffer.h | 2 +- include/git2cpp/commit.h | 2 +- include/git2cpp/object.h | 2 +- include/git2cpp/tree.h | 2 +- src/repo.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/git2cpp/buffer.h b/include/git2cpp/buffer.h index f5f69a4..91dc8b6 100644 --- a/include/git2cpp/buffer.h +++ b/include/git2cpp/buffer.h @@ -17,7 +17,7 @@ namespace git ~Buffer(); - explicit operator bool() const { return ptr(); } + explicit operator bool() const { return ptr() != nullptr; } const char * ptr() const { return buf_.ptr; } diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 2a3f614..7f52dd9 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -20,7 +20,7 @@ namespace git Repository const & owner() const { return *repo_; } - explicit operator bool () const { return commit_; } + explicit operator bool () const { return commit_ != nullptr; } git_oid const & id() const; diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index ccface7..b939212 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -17,7 +17,7 @@ namespace git Object(git_object * obj, Repository const &); ~Object(); - explicit operator bool() const { return obj_; } + explicit operator bool() const { return obj_ != nullptr; } git_otype type() const; git_oid const & id() const; diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index 633c765..f569397 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -76,7 +76,7 @@ namespace git Tree (Tree const &) = delete; Tree& operator =(Tree const &) = delete; - explicit operator bool() const { return tree_; } + explicit operator bool() const { return tree_ != nullptr; } private: git_tree * tree_; diff --git a/src/repo.cpp b/src/repo.cpp index 2988583..af42222 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -66,7 +66,7 @@ namespace git bool Repository::is_bare() const { - return git_repository_is_bare(repo_); + return git_repository_is_bare(repo_) != 0; } Signature Repository::signature() const From fd48644a3dfbac742141a179e9dddee5558f7396 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 29 Jun 2017 00:06:17 +0300 Subject: [PATCH 064/171] missing #include and forward declarations --- include/git2cpp/commit.h | 2 ++ include/git2cpp/object.h | 4 ++++ include/git2cpp/pathspec.h | 5 +---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 7f52dd9..a0363ce 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -2,6 +2,8 @@ #include "tree.h" +#include + struct git_commit; struct git_oid; struct git_repository; diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index b939212..6e95c98 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -3,8 +3,12 @@ #include "commit.h" #include "blob.h" +#include + struct git_object; struct git_oid; +struct git_tree; +struct git_tag; namespace git { diff --git a/include/git2cpp/pathspec.h b/include/git2cpp/pathspec.h index 0bc22d3..ada9b05 100644 --- a/include/git2cpp/pathspec.h +++ b/include/git2cpp/pathspec.h @@ -2,10 +2,7 @@ #include "error.h" -extern "C" -{ - #include -} +#include namespace git { From d934fa7ab7387c60a907dc51240db36f0c5d61da Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 29 Jun 2017 00:07:07 +0300 Subject: [PATCH 065/171] missing noexcept --- include/git2cpp/object.h | 2 +- src/object.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index 6e95c98..6b8b6c6 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -38,7 +38,7 @@ namespace git Object (Object const &) = delete; Object& operator = (Object const &) = delete; - Object(Object && other); + Object(Object && other) noexcept; private: git_object * obj_ = nullptr; diff --git a/src/object.cpp b/src/object.cpp index e26be81..58ee1d5 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -19,7 +19,7 @@ namespace git git_object_free(obj_); } - Object::Object(Object && other) + Object::Object(Object && other) noexcept : obj_(other.obj_) , repo_(other.repo_) { From b4fb7e72555e0fbb4cd70a2a1f7fa09a5a1b8cd3 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 29 Jun 2017 00:08:09 +0300 Subject: [PATCH 066/171] implement Repository::operator=(Repository &&) --- include/git2cpp/repo.h | 3 ++- src/repo.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 120b9b4..b97cf13 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -100,7 +100,8 @@ namespace git Repository (Repository const &) = delete; Repository& operator = (Repository const &) = delete; - Repository(Repository &&) noexcept; + Repository (Repository &&) noexcept; + Repository& operator = (Repository &&) noexcept; ~Repository(); diff --git a/src/repo.cpp b/src/repo.cpp index af42222..24345a5 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -59,6 +59,12 @@ namespace git other.repo_ = nullptr; } + Repository& Repository::operator=(Repository&& other) noexcept + { + std::swap(repo_, other.repo_); + return *this; + } + Repository::~Repository() { git_repository_free(repo_); From c7c2d5808d291687c7a061643edcdac8637dc079 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 29 Jun 2017 00:09:03 +0300 Subject: [PATCH 067/171] examples/status: if USE_BOOST defined use types from Boost --- examples/status.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/examples/status.cpp b/examples/status.cpp index e01320c..a5b0a95 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -7,12 +7,28 @@ #include #include -#include -#include #include "git2cpp/initializer.h" #include "git2cpp/repo.h" +#ifdef USE_BOOST + #include +#include + + template + using Optional = boost::optional; + + using StringView = boost::string_view; +#else + #include + #include + + template + using Optional = std::optional; + + using StringView = std::string_view; +#endif + using namespace git; enum { @@ -40,18 +56,18 @@ enum { * - A sample status formatter that matches the "short" format */ -bool starts_with(std::string_view str, std::string_view prefix) +bool starts_with(StringView str, StringView prefix) { return str.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), str.begin()); } void show_branch(Repository const & repo, int format) { - std::optional branch; + Optional branch; try { branch = repo.head().name(); - static const std::string_view refs_heads = "refs/heads/"; + static const StringView refs_heads = "refs/heads/"; if (starts_with(*branch, refs_heads)) branch->remove_prefix(refs_heads.length()); } From 79146d0e13c080d5c729111f599cd79b15d8f6e2 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 29 Jun 2017 00:10:45 +0300 Subject: [PATCH 068/171] CMake: set /std:c++17 only when MSVC_VERSION > 1900 --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f87c8f..07d135a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,10 @@ file(GLOB_RECURSE lib_sources include/git2cpp/*.h ) +if (MSVC AND ($MSVC_VERSION VERSION_GREATER 1900)) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") +endif() + add_library(git2cpp STATIC ${lib_sources}) target_include_directories(git2cpp @@ -42,10 +46,6 @@ set_target_properties(git2cpp PROPERTIES INTERFACE_COMPILE_FEATURES cxx_std_17 ) -if (MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") -endif() - set(examples add branch From 166852f20dec015c362d5dab9911ce1cbdbf920f Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 29 Jun 2017 00:11:26 +0300 Subject: [PATCH 069/171] When Boost used add Boost_INCLUDE_DIR to public includes --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07d135a..b6e1088 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,10 @@ target_include_directories(git2cpp $ ) +if (USE_BOOST) + target_include_directories(git2cpp PUBLIC ${Boost_INCLUDE_DIRS}) +endif() + target_link_libraries(git2cpp git2) set_target_properties(git2cpp PROPERTIES From 0c06317e04e89cc6ec1aa28183de3c758c2e324c Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 30 Jun 2017 08:16:45 +0300 Subject: [PATCH 070/171] code cosmetics --- include/git2cpp/commit.h | 9 ++++++--- include/git2cpp/str_array.h | 3 --- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index a0363ce..aeba5a2 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -40,7 +40,10 @@ namespace git , repo_(&repo) {} - Commit() {} + Commit() + : commit_(nullptr) + , repo_(nullptr) + {} Commit(Commit && other) : commit_(other.commit_) @@ -60,8 +63,8 @@ namespace git git_commit const * ptr() const { return commit_; } private: - git_commit * commit_ = nullptr; - Repository const * repo_ = nullptr; + git_commit * commit_; + Repository const * repo_; }; } diff --git a/include/git2cpp/str_array.h b/include/git2cpp/str_array.h index 069ef03..743ce20 100644 --- a/include/git2cpp/str_array.h +++ b/include/git2cpp/str_array.h @@ -1,9 +1,6 @@ #pragma once -extern "C" -{ #include -} namespace git { From 83ac61c5636a191ef483a4146e1adb53834aa270 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 30 Jun 2017 08:17:26 +0300 Subject: [PATCH 071/171] + Index::remove(path) --- include/git2cpp/index.h | 3 +++ src/index.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/git2cpp/index.h b/include/git2cpp/index.h index 3fd5889..5931447 100644 --- a/include/git2cpp/index.h +++ b/include/git2cpp/index.h @@ -29,6 +29,9 @@ namespace git void add_path(const char *); void add_path(std::string const &); + void remove_path(const char *); + void remove_path(std::string const &); + git_oid write_tree() const; void write() const; diff --git a/src/index.cpp b/src/index.cpp index e17c14b..331cdae 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -82,6 +82,17 @@ namespace git add_path(path.c_str()); } + void Index::remove_path(const char * path) + { + int res = git_index_remove_bypath(index_, path); + assert(res == 0); + } + + void Index::remove_path(std::string const & path) + { + remove_path(path.c_str()); + } + void Index::write() const { if (git_index_write(index_)) From 699eeba11cb3e793848179339458e80235b69359 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 30 Jun 2017 11:09:42 +0300 Subject: [PATCH 072/171] + Repository::reset_default --- include/git2cpp/repo.h | 2 ++ src/repo.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index b97cf13..653a44c 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -89,6 +89,8 @@ namespace git Tree const & tree, Commit const & parent); + void reset_default(Commit const &, git_strarray const & pathspecs); + explicit Repository(const char * dir); explicit Repository(std::string const & dir); diff --git a/src/repo.cpp b/src/repo.cpp index 24345a5..00438bf 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -403,4 +404,11 @@ namespace git assert(op_res == 0); return Diff(diff); } + + void Repository::reset_default(Commit const& commit, git_strarray const& pathspecs) + { + auto op_res = git_reset_default(repo_, reinterpret_cast(const_cast(commit.ptr())), const_cast(&pathspecs)); + assert(op_res == GIT_OK); + } + } From 1d669d78da884141fe2c29c8631f4829371903c4 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 2 Jul 2017 12:07:14 +0300 Subject: [PATCH 073/171] + missing `noexcept` --- include/git2cpp/blob.h | 2 +- include/git2cpp/diff.h | 4 ++-- src/blob.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/git2cpp/blob.h b/include/git2cpp/blob.h index 171d62d..4e5fbf0 100644 --- a/include/git2cpp/blob.h +++ b/include/git2cpp/blob.h @@ -19,7 +19,7 @@ namespace git Blob& operator = (Blob const &) = delete; Blob (Blob const &) = delete; - Blob(Blob &&); + Blob(Blob &&) noexcept; private: git_blob * blob_; diff --git a/include/git2cpp/diff.h b/include/git2cpp/diff.h index 25640f7..21b0ef9 100644 --- a/include/git2cpp/diff.h +++ b/include/git2cpp/diff.h @@ -38,7 +38,7 @@ namespace git Stats (Stats const &) = delete; Stats& operator = (Stats const &) = delete; - Stats(Stats &&); + Stats(Stats &&) noexcept; Buffer to_buf(diff::stats::format::type, size_t width) const; @@ -74,7 +74,7 @@ namespace git Diff (Diff const &) = delete; Diff& operator = (Diff const &) = delete; - Diff(Diff && other) + Diff(Diff && other) noexcept : diff_(other.diff_) { other.diff_ = nullptr; diff --git a/src/blob.cpp b/src/blob.cpp index 0d044de..ac7fda8 100644 --- a/src/blob.cpp +++ b/src/blob.cpp @@ -8,8 +8,8 @@ namespace git : blob_(blob) {} - Blob::Blob(Blob && other) - : blob_(other.blob_) + Blob::Blob(Blob && other) noexcept + : blob_(other.blob_) { other.blob_ = nullptr; } From 80897fc6bd6d7aa4b633ae6645090f74e87f1276 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 2 Jul 2017 12:07:42 +0300 Subject: [PATCH 074/171] implement Index::operator=(Index &&) --- include/git2cpp/index.h | 3 ++- src/index.cpp | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/git2cpp/index.h b/include/git2cpp/index.h index 5931447..5ff302c 100644 --- a/include/git2cpp/index.h +++ b/include/git2cpp/index.h @@ -39,7 +39,8 @@ namespace git Index (Index const &) = delete; Index& operator = (Index const &) = delete; - Index(Index && other); + Index (Index &&) noexcept; + Index& operator = (Index &&) noexcept; private: git_index * index_; diff --git a/src/index.cpp b/src/index.cpp index 331cdae..6d49ae9 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -26,16 +26,21 @@ namespace git Index::~Index() { - if (index_) - git_index_free(index_); + git_index_free(index_); } - Index::Index(Index && other) + Index::Index(Index && other) noexcept : index_(other.index_) { other.index_ = nullptr; } + Index& Index::operator =(Index && other) noexcept + { + std::swap(index_, other.index_); + return *this; + } + size_t Index::entrycount() const { return git_index_entrycount(index_); From fe4b6ab6ffa95371c77fd5fe98bf0ad1493a4c36 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 2 Jul 2017 12:09:28 +0300 Subject: [PATCH 075/171] + Repository::file_diff --- include/git2cpp/blob.h | 5 +++++ include/git2cpp/repo.h | 11 +++++++++++ src/repo.cpp | 16 ++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/include/git2cpp/blob.h b/include/git2cpp/blob.h index 4e5fbf0..5d61100 100644 --- a/include/git2cpp/blob.h +++ b/include/git2cpp/blob.h @@ -21,6 +21,11 @@ namespace git Blob(Blob &&) noexcept; + private: + friend struct Repository; + + git_blob const * ptr() const { return blob_; } + private: git_blob * blob_; }; diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 653a44c..cb72d43 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -27,6 +27,14 @@ namespace git LOCAL, REMOTE, ALL }; + struct FileDiffHandler + { + virtual void line(git_diff_line const &) = 0; + + protected: + ~FileDiffHandler() = default; + }; + struct Repository { Commit commit_lookup(git_oid const & oid) const; @@ -91,6 +99,9 @@ namespace git void reset_default(Commit const &, git_strarray const & pathspecs); + void file_diff(std::string const & old_path, git_oid const & old_id, + std::string const & new_path, git_oid const & new_id, FileDiffHandler &) const; + explicit Repository(const char * dir); explicit Repository(std::string const & dir); diff --git a/src/repo.cpp b/src/repo.cpp index 00438bf..bac77a1 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -411,4 +411,20 @@ namespace git assert(op_res == GIT_OK); } + void Repository::file_diff(std::string const& old_path, git_oid const& old_id, + std::string const& new_path, git_oid const& new_id, + FileDiffHandler & diff_handler) const + { + auto old_file = blob_lookup(old_id); + auto new_file = blob_lookup(new_id); + git_diff_options options = GIT_DIFF_OPTIONS_INIT; + auto data_callback = [] (git_diff_delta const *, git_diff_hunk const *, git_diff_line const * line, void * payload) { + auto handler = reinterpret_cast(payload); + handler->line(*line); + return 0; + }; + auto op_res = git_diff_blobs(old_file.ptr(), old_path.c_str(), new_file.ptr(), new_path.c_str(), + &options, nullptr, nullptr, nullptr, data_callback, &diff_handler); + assert(op_res == GIT_OK); + } } From 1df7beda85a3518f7af39bc0b4bf780f3d4f1310 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 3 Jul 2017 07:47:42 +0300 Subject: [PATCH 076/171] + Repostiory(std::string const & dir, init_tag) --- include/git2cpp/repo.h | 1 + src/repo.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index cb72d43..157f586 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -109,6 +109,7 @@ namespace git static const init_tag init; Repository(const char * dir, init_tag); Repository(const char * dir, init_tag, git_repository_init_options opts); + Repository(std::string const & dir, init_tag); Repository (Repository const &) = delete; Repository& operator = (Repository const &) = delete; diff --git a/src/repo.cpp b/src/repo.cpp index bac77a1..1140555 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -44,7 +44,13 @@ namespace git Repository::Repository(const char * dir, init_tag) { - if (git_repository_init(&repo_, dir, 0) < 0) + if (git_repository_init(&repo_, dir, false) < 0) + throw repository_init_error(dir); + } + + Repository::Repository(std::string const & dir, init_tag tag) + { + if (git_repository_init(&repo_, dir.c_str(), false) < 0) throw repository_init_error(dir); } From c9446f34512baeeb86a90f35b6f62d7188feaf32 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 4 Jul 2017 07:50:37 +0300 Subject: [PATCH 077/171] commit-graph-generator: don't add suffix `-cpp` --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6e1088..03a070a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,7 +62,6 @@ set(examples init rev-parse general - commit-graph-generator ) foreach (example ${examples}) @@ -70,4 +69,7 @@ foreach (example ${examples}) target_link_libraries("${example}-cpp" git2cpp) endforeach(example) +add_executable(commit-graph-generator examples/commit-graph-generator.cpp) +target_link_libraries(commit-graph-generator git2cpp) + file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) From c0ac66f74999fa9b27f749887de6ade07d40158a Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 4 Jul 2017 07:57:47 +0300 Subject: [PATCH 078/171] test.sh: add suffix `-cpp` for executables --- test.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test.sh b/test.sh index fe0b161..6aefbdf 100755 --- a/test.sh +++ b/test.sh @@ -39,13 +39,13 @@ function test() # read-only tests (repo shouldn't be bare) pushd $REPO -test branch +test branch-cpp test commit-graph-generator . "$CWD/commit-graph.dot" -test log -test rev-list --topo-order HEAD -test rev-parse HEAD -test showindex -test status +test log-cpp +test rev-list-cpp --topo-order HEAD +test rev-parse-cpp HEAD +test showindex-cpp +test status-cpp popd @@ -60,8 +60,8 @@ fi pushd $RW_REPO -test cat-file -t a8233120f6ad708f843d861ce2b7228ec4e3dec6 -test cat-file -p a8233120f6ad708f843d861ce2b7228ec4e3dec6 -test general . +test cat-file-cpp -t a8233120f6ad708f843d861ce2b7228ec4e3dec6 +test cat-file-cpp -p a8233120f6ad708f843d861ce2b7228ec4e3dec6 +test general-cpp . popd From 4ffc28c47602817db688ec2c46a15d09b48c1526 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 4 Jul 2017 07:58:45 +0300 Subject: [PATCH 079/171] test.sh: + 'diff' --- TODO.md | 1 - test.sh | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 21dcfe9..432fc7b 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,6 @@ libgit2cpp TODO =============== -* restore diff * standardize command-line processing for all examples * most importantly --git-dir * unit tests diff --git a/test.sh b/test.sh index 6aefbdf..3f1f276 100755 --- a/test.sh +++ b/test.sh @@ -40,6 +40,7 @@ function test() pushd $REPO test branch-cpp +test diff-cpp test commit-graph-generator . "$CWD/commit-graph.dot" test log-cpp test rev-list-cpp --topo-order HEAD From d4cc36ff7ef19e7dd4cf4ba6766290dafa500c53 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 4 Jul 2017 08:03:00 +0300 Subject: [PATCH 080/171] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 679bf19..9d95c65 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ libgit2cpp ========== -C++ wrapper for libgit2 +C++ wrapper for libgit2. It contains libgit2 as submodule (libs/libgit2). Building libgit2cpp - Using CMake ================================= @@ -9,6 +9,8 @@ Building libgit2cpp - Using CMake $ mkdir build && cd build $ cmake .. $ make + +Supporting CMake options: `USE_BOOST`, `BUNDLE_LIBGIT2`. Testing ======= @@ -21,5 +23,4 @@ e.g. $ mkdir build && cd build $ cmake .. $ make - $ ./test.sh .. ../../libgit2/tests/resources/testrepo.git - + $ ./test.sh .. ../libs/libgit2/tests/resources/testrepo.git From 5666e6a9470c433d94d61e914a2ca3ed53b33081 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 4 Jul 2017 10:18:41 +0300 Subject: [PATCH 081/171] + repo_fwd.h --- include/git2cpp/repo.h | 6 ++++-- include/git2cpp/repo_fwd.h | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 include/git2cpp/repo_fwd.h diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 157f586..683432e 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -1,7 +1,6 @@ #pragma once -#include -#include +#include "repo_fwd.h" #include "commit.h" #include "index.h" @@ -17,6 +16,9 @@ #include "diff.h" #include "submodule.h" +#include +#include + namespace git { struct non_existing_branch_error {}; diff --git a/include/git2cpp/repo_fwd.h b/include/git2cpp/repo_fwd.h new file mode 100644 index 0000000..47b942a --- /dev/null +++ b/include/git2cpp/repo_fwd.h @@ -0,0 +1,6 @@ +#pragma once + +namespace git +{ + struct Repository; +} From 3bcf2a28e28e3deb815f1bd09bce956148238af0 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 4 Jul 2017 10:54:47 +0300 Subject: [PATCH 082/171] + very initial support of remote repositories --- include/git2cpp/error.h | 7 +++++++ include/git2cpp/remote.h | 20 ++++++++++++++++++++ include/git2cpp/repo.h | 4 ++++ src/remote.cpp | 11 +++++++++++ src/repo.cpp | 17 +++++++++++++++++ 5 files changed, 59 insertions(+) create mode 100644 include/git2cpp/remote.h create mode 100644 src/remote.cpp diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 9e71f05..93afda1 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -72,6 +72,13 @@ namespace git {} }; + struct remote_lookup_error : error_t + { + explicit remote_lookup_error(std::string const & name) + : error_t("Could not lookup remote " + name) + {} + }; + struct commit_parent_error : error_t { explicit commit_parent_error(git_oid const & id) diff --git a/include/git2cpp/remote.h b/include/git2cpp/remote.h new file mode 100644 index 0000000..bb2b31a --- /dev/null +++ b/include/git2cpp/remote.h @@ -0,0 +1,20 @@ +#pragma once + +struct git_remote; + +namespace git +{ + struct Remote + { + const char * url() const; + + private: + friend struct Repository; + + explicit Remote(git_remote * remote) + : remote_(remote) + {} + + git_remote * remote_; + }; +} diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 683432e..e9d802c 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -15,6 +15,7 @@ #include "str_array.h" #include "diff.h" #include "submodule.h" +#include "remote.h" #include #include @@ -104,6 +105,9 @@ namespace git void file_diff(std::string const & old_path, git_oid const & old_id, std::string const & new_path, git_oid const & new_id, FileDiffHandler &) const; + StrArray remotes() const; + Remote remote(const char * name) const; + explicit Repository(const char * dir); explicit Repository(std::string const & dir); diff --git a/src/remote.cpp b/src/remote.cpp new file mode 100644 index 0000000..bd700c6 --- /dev/null +++ b/src/remote.cpp @@ -0,0 +1,11 @@ +#include "git2cpp/remote.h" + +#include + +namespace git +{ + const char * Remote::url() const + { + return git_remote_url(remote_); + } +} diff --git a/src/repo.cpp b/src/repo.cpp index 1140555..35bd85b 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -433,4 +433,21 @@ namespace git &options, nullptr, nullptr, nullptr, data_callback, &diff_handler); assert(op_res == GIT_OK); } + + StrArray Repository::remotes() const + { + git_strarray result; + auto op_res = git_remote_list(&result, repo_); + assert(op_res == GIT_OK); + return StrArray(result); + } + + Remote Repository::remote(const char * name) const + { + git_remote * remote; + if (git_remote_lookup(&remote, repo_, name)) + throw remote_lookup_error(name); + else + return Remote(remote); + } } From c7ace8e62e4cad97a795fbed04938c451292f560 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 6 Jul 2017 06:42:37 +0300 Subject: [PATCH 083/171] examples: + missing `free` --- examples/add.cpp | 53 ++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/examples/add.cpp b/examples/add.cpp index 7eeee6e..565a2ab 100644 --- a/examples/add.cpp +++ b/examples/add.cpp @@ -12,19 +12,11 @@ enum print_options { UPDATE = 4, }; -void init_array(git_strarray *array, int argc, char **argv) +void init_array(git_strarray & arr, int argc, char **argv) { - unsigned int i; - - array->count = argc; - array->strings = reinterpret_cast(malloc(sizeof(char*) * array->count)); - assert(array->strings!=NULL); - - for(i=0; icount; i++) { - array->strings[i]=argv[i]; - } - - return; + arr.count = argc; + arr.strings = reinterpret_cast(malloc(sizeof(char*) * argc)); + std::copy_n(argv, argc, arr.strings); } int print_matched_cb( const char *path, const char * /*matched_pathspec*/, @@ -60,8 +52,6 @@ int main (int argc, char** argv) { using namespace std::placeholders; - git_strarray array = {0}; - int i = 1, options = 0; for (; i < argc; ++i) { if (argv[i][0] != '-') { @@ -91,30 +81,31 @@ int main (int argc, char** argv) } } - if (argc<=i) { - print_usage(); - return 1; - } + if (argc <= i) + { + print_usage(); + return EXIT_FAILURE; + } - init_array(&array, argc-i, argv+i); + git_strarray arr; + init_array(arr, argc - i, argv + i); auto_git_initializer; - git::Repository repo("."); + git::Repository repo("."); git::Index::matched_path_callback_t cb; - if (options&VERBOSE || options&SKIP) { - cb = std::bind(&print_matched_cb, _1, _2, std::cref(repo), static_cast(options)); - } + if (options & VERBOSE || options & SKIP) + cb = std::bind(&print_matched_cb, _1, _2, std::cref(repo), static_cast(options)); - git::Index index = repo.index(); - if (options&UPDATE) { - index.update_all(array, cb); - } else { - index.add_all(array, cb); - } + git::Index index = repo.index(); + if (options & UPDATE) + index.update_all(arr, cb); + else + index.add_all(arr, cb); - index.write(); + index.write(); + free(arr.strings); - return 0; + return 0; } From 274caf52eef886053e82fd527cf13a6f0ac69546 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 11 Jul 2017 07:52:07 +0300 Subject: [PATCH 084/171] Status: + move constructor and assignment --- include/git2cpp/status.h | 3 ++- src/status.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/git2cpp/status.h b/include/git2cpp/status.h index 4b949f6..4815c3d 100644 --- a/include/git2cpp/status.h +++ b/include/git2cpp/status.h @@ -49,7 +49,8 @@ namespace git Status (Status const &) = delete; Status& operator = (Status const &) = delete; - Status(Status &&); + Status (Status &&) noexcept; + Status& operator = (Status &&) noexcept; private: git_status_list * status_; diff --git a/src/status.cpp b/src/status.cpp index abf72b4..5707692 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -94,6 +94,18 @@ namespace git throw get_status_error(); } + Status::Status(Status && other) noexcept + : status_(other.status_) + { + other.status_ = nullptr; + } + + Status& Status::operator =(Status && other) noexcept + { + std::swap(status_, other.status_); + return *this; + } + Status::~Status() { git_status_list_free(status_); From 7fa0591b22495d86d63220034611287ee3364e4b Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 11 Jul 2017 07:52:53 +0300 Subject: [PATCH 085/171] Repository::create_commit: set default value `nullptr` for `message_enconding` --- examples/general.cpp | 1 - examples/init.cpp | 2 +- include/git2cpp/repo.h | 8 ++++---- src/repo.cpp | 8 ++++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/examples/general.cpp b/examples/general.cpp index d4aac54..f07541c 100644 --- a/examples/general.cpp +++ b/examples/general.cpp @@ -226,7 +226,6 @@ int main (int argc, char** argv) nullptr, /* do not update the HEAD */ author, cmtter, - nullptr, /* use default message encoding */ "example commit", tree, parent); diff --git a/examples/init.cpp b/examples/init.cpp index c5ee1a5..e6dc89a 100644 --- a/examples/init.cpp +++ b/examples/init.cpp @@ -198,5 +198,5 @@ static void create_initial_commit(Repository & repo) * HEAD commit and making that be the parent of the initial commit, * but here this is the first commit so there will be no parent. */ - repo.create_commit("HEAD", sig, sig, NULL, "Initial commit", tree); + repo.create_commit("HEAD", sig, sig, "Initial commit", tree); } diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index e9d802c..12d12af 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -88,17 +88,17 @@ namespace git git_oid create_commit(const char * update_ref, Signature const & author, Signature const & commiter, - const char * message_encoding, const char * message, - Tree const & tree); + Tree const & tree, + const char * message_encoding = nullptr); git_oid create_commit(const char * update_ref, Signature const & author, Signature const & commiter, - const char * message_encoding, const char * message, Tree const & tree, - Commit const & parent); + Commit const & parent, + const char * message_encoding = nullptr); void reset_default(Commit const &, git_strarray const & pathspecs); diff --git a/src/repo.cpp b/src/repo.cpp index 35bd85b..c2d4bcc 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -312,9 +312,9 @@ namespace git git_oid Repository::create_commit(const char * update_ref, Signature const & author, Signature const & commiter, - const char * message_encoding, const char * message, - Tree const & tree) + Tree const & tree, + const char * message_encoding) { git_oid res; if (git_commit_create_v(&res, repo_, update_ref, @@ -330,10 +330,10 @@ namespace git git_oid Repository::create_commit(const char * update_ref, Signature const & author, Signature const & commiter, - const char * message_encoding, const char * message, Tree const & tree, - Commit const & parent) + Commit const & parent, + const char * message_encoding) { git_oid res; if (git_commit_create_v(&res, repo_, update_ref, From 87b12b8b0128b3b996e0f471cc11d79e9af2ddad Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 12 Jul 2017 08:05:48 +0300 Subject: [PATCH 086/171] code cosmetics --- include/git2cpp/commit.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index aeba5a2..ad481e7 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -1,6 +1,7 @@ #pragma once #include "tree.h" +#include "repo_fwd.h" #include @@ -10,8 +11,6 @@ struct git_repository; namespace git { - struct Repository; - struct Commit { size_t parents_num() const; From 11306aaac46c319b1f81e590afba2361650ab3d8 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 12 Jul 2017 08:06:14 +0300 Subject: [PATCH 087/171] + Index::clear() --- include/git2cpp/index.h | 1 + src/index.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/git2cpp/index.h b/include/git2cpp/index.h index 5ff302c..7a315bf 100644 --- a/include/git2cpp/index.h +++ b/include/git2cpp/index.h @@ -25,6 +25,7 @@ namespace git void update_all (git_strarray const & pathspec, matched_path_callback_t cb); void add_all (git_strarray const & pathspec, matched_path_callback_t cb, unsigned int flags = 0); + void clear(); void add_path(const char *); void add_path(std::string const &); diff --git a/src/index.cpp b/src/index.cpp index 6d49ae9..96fa9e9 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -76,6 +76,12 @@ namespace git assert(res == 0); } + void Index::clear() + { + int res = git_index_clear(index_); + assert(res == 0); + } + void Index::add_path(const char * path) { int res = git_index_add_bypath(index_, path); From 20c8281536d72f575fbe8bf014098a33fd7f4e63 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 3 Jan 2018 17:09:53 +0200 Subject: [PATCH 088/171] Create appveyor.yml --- README.md | 2 ++ appveyor.yml | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 appveyor.yml diff --git a/README.md b/README.md index 9d95c65..74e4613 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ libgit2cpp ========== +[![AppVeryor Build Status](https://ci.appveyor.com/api/projects/status/ps6e0s4nfnw5afh4/branch/master?svg=true)](https://ci.appveyor.com/project/AndreyG/libgit2cpp/branch/master) + C++ wrapper for libgit2. It contains libgit2 as submodule (libs/libgit2). Building libgit2cpp - Using CMake diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..04d7e6d --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,27 @@ +version: '{build}' + +branches: + only: + - master + +environment: + matrix: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + GENERATOR: "Visual Studio 14 2015" + ARCH: 32 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + GENERATOR: "Visual Studio 15 2017" + ARCH: 32 + +clone_script: +- cmd: git clone --branch=%APPVEYOR_REPO_BRANCH% https://github.com/%APPVEYOR_REPO_NAME%.git %APPVEYOR_BUILD_FOLDER% +- cmd: cd %APPVEYOR_BUILD_FOLDER% +- cmd: git checkout -q %APPVEYOR_REPO_COMMIT% +- cmd: git submodule update --init + +build_script: +- ps: | + mkdir build + cd build + cmake -D BUILD_CLAR=OFF -D BUILD_EXAMPLES=OFF -D USE_BOOST=ON -D BOOST_ROOT=C:\Libraries\boost_1_65_1 .. -G"$env:GENERATOR" + cmake --build . --config Debug From 0345a15242ddb8cb7013f4e01d1988c5a04a4750 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 5 Jan 2018 14:21:45 +0200 Subject: [PATCH 089/171] Boost: [VS 2015 -> 1.63.0]; [VS 2017 -> 1.65.1] --- appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 04d7e6d..3e95f73 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,9 +9,11 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 GENERATOR: "Visual Studio 14 2015" ARCH: 32 + BOOST: 1_63_0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 GENERATOR: "Visual Studio 15 2017" ARCH: 32 + BOOST: 1_65_1 clone_script: - cmd: git clone --branch=%APPVEYOR_REPO_BRANCH% https://github.com/%APPVEYOR_REPO_NAME%.git %APPVEYOR_BUILD_FOLDER% @@ -23,5 +25,5 @@ build_script: - ps: | mkdir build cd build - cmake -D BUILD_CLAR=OFF -D BUILD_EXAMPLES=OFF -D USE_BOOST=ON -D BOOST_ROOT=C:\Libraries\boost_1_65_1 .. -G"$env:GENERATOR" + cmake -D BUILD_CLAR=OFF -D BUILD_EXAMPLES=OFF -D USE_BOOST=ON -D BOOST_ROOT="C:\Libraries\boost_$env:BOOST" .. -G"$env:GENERATOR" cmake --build . --config Debug From c269324c0f73b3ec54642c09228053c497684956 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 6 Jan 2018 12:30:09 +0300 Subject: [PATCH 090/171] Update submodule libgit2 --- libs/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/libgit2 b/libs/libgit2 index c26ce78..70db57d 160000 --- a/libs/libgit2 +++ b/libs/libgit2 @@ -1 +1 @@ -Subproject commit c26ce78404b7fc7356c56bd2c57611fd60a3705b +Subproject commit 70db57d4a431dae2edcf19e92a84db8d6cf4f935 From 86b69421c567e206e0a7bf3eb4197a25616ac567 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 24 Jul 2018 08:44:15 +0300 Subject: [PATCH 091/171] typo fix --- src/repo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.cpp b/src/repo.cpp index c2d4bcc..210db38 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -213,7 +213,7 @@ namespace git { case branch_type::LOCAL : return GIT_BRANCH_LOCAL; case branch_type::REMOTE: return GIT_BRANCH_REMOTE; - case branch_type::ALL: return GIT_BRANCH_REMOTE; + case branch_type::ALL: return GIT_BRANCH_ALL; default: throw std::logic_error("invalid branch type"); } From 431a28637bf4c4d6964f1ac94807a2362faefc12 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 19 Sep 2018 08:55:55 +0300 Subject: [PATCH 092/171] code cleanup --- include/git2cpp/reference.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/git2cpp/reference.h b/include/git2cpp/reference.h index 6858b2e..d1ef7d1 100644 --- a/include/git2cpp/reference.h +++ b/include/git2cpp/reference.h @@ -1,9 +1,6 @@ #pragma once -extern "C" -{ #include -} struct git_reference; struct git_oid; @@ -23,7 +20,7 @@ namespace git Reference& operator = (Reference const &) = delete; Reference (Reference const &) = delete; - Reference(Reference &&); + Reference(Reference &&) noexcept; private: git_reference * ref_; From 63d2c51550a05faccc7b42d2e44956b68bb2ec1a Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 19 Sep 2018 08:56:20 +0300 Subject: [PATCH 093/171] CMake: workaround of incorrectly configured module libgit2 --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03a070a..d5044ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,12 @@ if (USE_BOOST) target_include_directories(git2cpp PUBLIC ${Boost_INCLUDE_DIRS}) endif() +if (BUNDLE_LIBGIT2) + target_include_directories(git2cpp + PUBLIC libs/libgit2/include + ) +endif() + target_link_libraries(git2cpp git2) set_target_properties(git2cpp PROPERTIES From 172d858f9b6bce6057fef99d5fb1b8e60e740a85 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 19 Sep 2018 08:57:31 +0300 Subject: [PATCH 094/171] Update submodule libgit2 --- libs/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/libgit2 b/libs/libgit2 index 70db57d..a3e53c1 160000 --- a/libs/libgit2 +++ b/libs/libgit2 @@ -1 +1 @@ -Subproject commit 70db57d4a431dae2edcf19e92a84db8d6cf4f935 +Subproject commit a3e53c166c742da5913f776944be2c7fa94db838 From 7d903338acdf805e9ac67e121896a94cb9c5af73 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 19 Sep 2018 10:16:36 +0300 Subject: [PATCH 095/171] Reference::target: check that reference is not symbolic --- src/reference.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/reference.cpp b/src/reference.cpp index d0769db..4a172c9 100644 --- a/src/reference.cpp +++ b/src/reference.cpp @@ -1,9 +1,8 @@ #include "git2cpp/reference.h" -extern "C" -{ - #include -} +#include + +#include namespace git { @@ -28,6 +27,7 @@ namespace git git_oid const & Reference::target() const { + assert(type() != GIT_REF_SYMBOLIC); return *git_reference_target(ref_); } From 069f082a84e0b39ad06ac90abefde0e8ffd07928 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 19 Sep 2018 10:17:54 +0300 Subject: [PATCH 096/171] branch_iterator bug fix --- src/repo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.cpp b/src/repo.cpp index 210db38..9d7f807 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -189,7 +189,7 @@ namespace git switch (git_branch_next(&ref, &type, base_)) { case GIT_OK: - assert(type == type_); + assert(type & type_); internal::emplace(ref_, ref); break; case GIT_ITEROVER: From 381f10e279f98c5c9dc668faae08c633811060e6 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 19 Sep 2018 10:18:35 +0300 Subject: [PATCH 097/171] micro optimization --- src/repo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.cpp b/src/repo.cpp index 9d7f807..cb06460 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -229,7 +229,7 @@ namespace git { std::vector res; for (branch_iterator it(repo_, type); it; ++it) - res.push_back(it->name()); + res.emplace_back(it->name()); return res; } From 3be834255d59fbec736586a30ba659b2a6a914e9 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 17 Oct 2018 08:22:59 +0300 Subject: [PATCH 098/171] code cleanup --- include/git2cpp/commit.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index ad481e7..38ffeeb 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -44,12 +44,10 @@ namespace git , repo_(nullptr) {} - Commit(Commit && other) - : commit_(other.commit_) + Commit(Commit && other) noexcept + : commit_(std::exchange(other.commit_, nullptr)) , repo_(other.repo_) - { - other.commit_ = nullptr; - } + {} Commit (Commit const &) = delete; Commit& operator = (Commit const &) = delete; From db3f23cb5d2acb26a6570e8c9a0a879be830f41b Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 17 Oct 2018 09:45:59 +0300 Subject: [PATCH 099/171] Commit: owner() -> repo() --- examples/log.cpp | 2 +- include/git2cpp/commit.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/log.cpp b/examples/log.cpp index 37d7497..4c977ca 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -204,7 +204,7 @@ static int match_with_parent(git::Commit const & commit, int i, git_diff_options auto parent = commit.parent(i); auto c_tree = commit.tree(); auto p_tree = parent.tree(); - auto diff = commit.owner().diff(p_tree, c_tree, opts); + auto diff = commit.repo().diff(p_tree, c_tree, opts); return diff.deltas_num() > 0; } diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 38ffeeb..05a6091 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -19,8 +19,6 @@ namespace git Tree tree() const; - Repository const & owner() const { return *repo_; } - explicit operator bool () const { return commit_ != nullptr; } git_oid const & id() const; @@ -34,6 +32,8 @@ namespace git git_oid merge_base(size_t p1, size_t p2) const; + Repository const & repo() const { return *repo_; } + Commit(git_commit * commit, Repository const & repo) : commit_(commit) , repo_(&repo) From 340a1f80fd12965cf84ca66daa8c4b2662414000 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 1 Nov 2018 12:46:16 +0300 Subject: [PATCH 100/171] make class `Reference` nullable --- include/git2cpp/reference.h | 7 +++++++ src/reference.cpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/include/git2cpp/reference.h b/include/git2cpp/reference.h index d1ef7d1..4d77056 100644 --- a/include/git2cpp/reference.h +++ b/include/git2cpp/reference.h @@ -9,9 +9,15 @@ namespace git { struct Reference { + Reference() + : ref_(nullptr) + {} + explicit Reference(git_reference * ref); ~Reference(); + explicit operator bool() const { return ref_ != nullptr; } + const char * name() const; git_ref_t type() const; git_oid const & target() const; @@ -21,6 +27,7 @@ namespace git Reference (Reference const &) = delete; Reference(Reference &&) noexcept; + Reference& operator =(Reference && other) noexcept; private: git_reference * ref_; diff --git a/src/reference.cpp b/src/reference.cpp index 4a172c9..c73d0a7 100644 --- a/src/reference.cpp +++ b/src/reference.cpp @@ -3,6 +3,7 @@ #include #include +#include namespace git { @@ -35,4 +36,10 @@ namespace git { return git_reference_symbolic_target(ref_); } + + Reference& Reference::operator=(Reference&& other) noexcept + { + std::swap(ref_, other.ref_); + return *this; + } } From 11a1a6c8701184bc296d48e3ad2df960b35e4f32 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 1 Nov 2018 12:47:03 +0300 Subject: [PATCH 101/171] implement Commit::operator=(Commit &&) --- include/git2cpp/commit.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 05a6091..8e55c26 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -45,10 +45,17 @@ namespace git {} Commit(Commit && other) noexcept - : commit_(std::exchange(other.commit_, nullptr)) + : commit_(std::exchange(other.commit_, nullptr)) , repo_(other.repo_) {} + Commit& operator = (Commit && other) noexcept + { + std::swap(commit_, other.commit_); + std::swap(repo_, other.repo_); + return *this; + } + Commit (Commit const &) = delete; Commit& operator = (Commit const &) = delete; From f8eb99a0542d28249acec3f15a9ebb9a6cd67a12 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 7 Nov 2018 07:16:40 +0300 Subject: [PATCH 102/171] implement Reference(Reference &&) --- src/reference.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/reference.cpp b/src/reference.cpp index c73d0a7..762e040 100644 --- a/src/reference.cpp +++ b/src/reference.cpp @@ -37,6 +37,11 @@ namespace git return git_reference_symbolic_target(ref_); } + Reference::Reference(Reference&& other) noexcept + : ref_(std::exchange(other.ref_, nullptr)) + { + } + Reference& Reference::operator=(Reference&& other) noexcept { std::swap(ref_, other.ref_); From 9ec887515113aa950a2694d32ae7240753a06b6f Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Wed, 7 Nov 2018 07:17:24 +0300 Subject: [PATCH 103/171] Repository::branches(): vector -> vector --- examples/branch.cpp | 4 ++-- include/git2cpp/repo.h | 2 +- src/repo.cpp | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/branch.cpp b/examples/branch.cpp index dd3eb03..2880e47 100644 --- a/examples/branch.cpp +++ b/examples/branch.cpp @@ -9,6 +9,6 @@ int main() git::Repository repo("."); auto branches = repo.branches(git::branch_type::ALL); - for (auto b : branches) - std::cout << b << std::endl; + for (auto const & b : branches) + std::cout << b.name() << std::endl; } diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 12d12af..c7c8c58 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -73,7 +73,7 @@ namespace git StrArray reference_list() const; - std::vector branches(branch_type) const; + std::vector branches(branch_type) const; bool is_bare() const; diff --git a/src/repo.cpp b/src/repo.cpp index cb06460..aced1b3 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -201,9 +201,9 @@ namespace git } } - Reference const * operator -> () const + Reference& operator * () { - return &ref_.value(); + return *ref_; } private: @@ -225,11 +225,11 @@ namespace git internal::optional ref_; }; - std::vector Repository::branches(branch_type type) const + std::vector Repository::branches(branch_type type) const { - std::vector res; + std::vector res; for (branch_iterator it(repo_, type); it; ++it) - res.emplace_back(it->name()); + res.emplace_back(std::move(*it)); return res; } From 3889aa1ffbc4953882d3804d05f8749dac60122a Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 5 Jan 2019 09:47:07 +0300 Subject: [PATCH 104/171] fix non-MSVC comilation (missing #include) --- include/git2cpp/commit.h | 25 ++++--------------------- src/commit.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 8e55c26..1eccfec 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -34,28 +34,11 @@ namespace git Repository const & repo() const { return *repo_; } - Commit(git_commit * commit, Repository const & repo) - : commit_(commit) - , repo_(&repo) - {} - - Commit() - : commit_(nullptr) - , repo_(nullptr) - {} - - Commit(Commit && other) noexcept - : commit_(std::exchange(other.commit_, nullptr)) - , repo_(other.repo_) - {} - - Commit& operator = (Commit && other) noexcept - { - std::swap(commit_, other.commit_); - std::swap(repo_, other.repo_); - return *this; - } + Commit(git_commit *, Repository const &); + Commit(); + Commit (Commit &&) noexcept; + Commit& operator = (Commit &&) noexcept; Commit (Commit const &) = delete; Commit& operator = (Commit const &) = delete; diff --git a/src/commit.cpp b/src/commit.cpp index 0a6a6a7..0167bae 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -5,8 +5,32 @@ #include #include +#include + namespace git { + Commit::Commit(git_commit * commit, Repository const & repo) + : commit_(commit) + , repo_(&repo) + {} + + Commit::Commit() + : commit_(nullptr) + , repo_(nullptr) + {} + + Commit::Commit(Commit && other) noexcept + : commit_(std::exchange(other.commit_, nullptr)) + , repo_(other.repo_) + {} + + Commit& Commit::operator = (Commit && other) noexcept + { + std::swap(commit_, other.commit_); + std::swap(repo_, other.repo_); + return *this; + } + Commit Commit::parent(size_t i) const { git_commit * parent; From 40aab7d0c6befed14b366028c7e317761fdb226d Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 5 Jan 2019 10:56:54 +0300 Subject: [PATCH 105/171] fix formatting --- .clang-format | 37 ++ examples/add.cpp | 131 +++--- examples/branch.cpp | 2 +- examples/cat-file.cpp | 343 ++++++++-------- examples/commit-graph-generator.cpp | 110 ++--- examples/diff.cpp | 223 +++++----- examples/general.cpp | 67 ++- examples/init.cpp | 207 +++++----- examples/log.cpp | 605 ++++++++++++++-------------- examples/rev-list.cpp | 105 ++--- examples/rev-parse.cpp | 59 +-- examples/showindex.cpp | 89 ++-- examples/status.cpp | 318 ++++++++------- include/git2cpp/blob.h | 8 +- include/git2cpp/buffer.h | 4 +- include/git2cpp/commit.h | 61 ++- include/git2cpp/config.h | 6 +- include/git2cpp/diff.h | 42 +- include/git2cpp/error.h | 406 ++++++++++--------- include/git2cpp/index.h | 18 +- include/git2cpp/initializer.h | 8 +- include/git2cpp/object.h | 49 ++- include/git2cpp/odb.h | 12 +- include/git2cpp/odb_object.h | 14 +- include/git2cpp/pathspec.h | 6 +- include/git2cpp/reference.h | 15 +- include/git2cpp/repo.h | 80 ++-- include/git2cpp/revspec.h | 51 ++- include/git2cpp/revwalker.h | 32 +- include/git2cpp/signature.h | 1 - include/git2cpp/status.h | 25 +- include/git2cpp/str_array.h | 2 +- include/git2cpp/submodule.h | 38 +- include/git2cpp/tag.h | 30 +- include/git2cpp/tagged_mask.h | 20 +- include/git2cpp/tree.h | 47 ++- src/blob.cpp | 7 +- src/commit.cpp | 173 ++++---- src/config.cpp | 5 +- src/diff.cpp | 53 ++- src/id_to_str.cpp | 9 +- src/index.cpp | 23 +- src/initializer.cpp | 4 +- src/object.cpp | 35 +- src/odb.cpp | 10 +- src/odb_object.cpp | 4 +- src/reference.cpp | 7 +- src/repo.cpp | 81 ++-- src/revspec.cpp | 15 +- src/revwalker.cpp | 19 +- src/signature.cpp | 5 +- src/status.cpp | 27 +- src/submodule.cpp | 3 +- src/tag.cpp | 9 +- src/tree.cpp | 55 +-- 55 files changed, 1994 insertions(+), 1821 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..c94340e --- /dev/null +++ b/.clang-format @@ -0,0 +1,37 @@ +--- +Language: Cpp +ColumnLimit: 0 +BreakBeforeBraces: Custom +BraceWrapping: + AfterNamespace: true + AfterClass: true + AfterStruct: true + AfterEnum: true + AfterFunction: true + AfterControlStatement: true + BeforeElse: true + BeforeCatch: true + SplitEmptyFunction: false + SplitEmptyRecord: false +NamespaceIndentation: All +AccessModifierOffset: -4 +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +PointerAlignment: Middle +BreakConstructorInitializers: BeforeComma +BreakBeforeTernaryOperators: true +CompactNamespaces: true +FixNamespaceComments: false +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"git2cpp/' + Priority: 2 + - Regex: '^' + Priority: 4 + - Regex: '.*' + Priority: 1 +... + diff --git a/examples/add.cpp b/examples/add.cpp index 565a2ab..c24721e 100644 --- a/examples/add.cpp +++ b/examples/add.cpp @@ -1,85 +1,98 @@ #include +#include #include #include -#include -#include "git2cpp/repo.h" #include "git2cpp/initializer.h" +#include "git2cpp/repo.h" -enum print_options { - SKIP = 1, - VERBOSE = 2, - UPDATE = 4, +enum print_options +{ + SKIP = 1, + VERBOSE = 2, + UPDATE = 4, }; -void init_array(git_strarray & arr, int argc, char **argv) +void init_array(git_strarray & arr, int argc, char ** argv) { arr.count = argc; - arr.strings = reinterpret_cast(malloc(sizeof(char*) * argc)); + arr.strings = reinterpret_cast(malloc(sizeof(char *) * argc)); std::copy_n(argv, argc, arr.strings); } -int print_matched_cb( const char *path, const char * /*matched_pathspec*/, - git::Repository const & repo, print_options options ) +int print_matched_cb(const char * path, const char * /*matched_pathspec*/, + git::Repository const & repo, print_options options) { - git_status_t status = repo.file_status(path); - - int ret; - if (status & GIT_STATUS_WT_MODIFIED || - status & GIT_STATUS_WT_NEW) { - printf("add '%s'\n", path); - ret = 0; - } else { - ret = 1; - } - - if (options & SKIP) { - ret = 1; - } - - return ret; + git_status_t status = repo.file_status(path); + + int ret; + if (status & GIT_STATUS_WT_MODIFIED || + status & GIT_STATUS_WT_NEW) + { + printf("add '%s'\n", path); + ret = 0; + } + else + { + ret = 1; + } + + if (options & SKIP) + { + ret = 1; + } + + return ret; } void print_usage(void) { - fprintf(stderr, "usage: add [options] [--] file-spec [file-spec] [...]\n\n"); - fprintf(stderr, "\t-n, --dry-run dry run\n"); - fprintf(stderr, "\t-v, --verbose be verbose\n"); - fprintf(stderr, "\t-u, --update update tracked files\n"); + fprintf(stderr, "usage: add [options] [--] file-spec [file-spec] [...]\n\n"); + fprintf(stderr, "\t-n, --dry-run dry run\n"); + fprintf(stderr, "\t-v, --verbose be verbose\n"); + fprintf(stderr, "\t-u, --update update tracked files\n"); } -int main (int argc, char** argv) +int main(int argc, char ** argv) { using namespace std::placeholders; - int i = 1, options = 0; - for (; i < argc; ++i) { - if (argv[i][0] != '-') { - break; - } - else if(!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-v")) { - options |= VERBOSE; - } - else if(!strcmp(argv[i], "--dry-run") || !strcmp(argv[i], "-n")) { - options |= SKIP; - } - else if(!strcmp(argv[i], "--update") || !strcmp(argv[i], "-u")) { - options |= UPDATE; - } - else if(!strcmp(argv[i], "-h")) { - print_usage(); - break; - } - else if(!strcmp(argv[i], "--")) { - i++; - break; - } - else { - fprintf(stderr, "Unsupported option %s.\n", argv[i]); - print_usage(); - return 1; - } - } + int i = 1, options = 0; + for (; i < argc; ++i) + { + if (argv[i][0] != '-') + { + break; + } + else if (!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-v")) + { + options |= VERBOSE; + } + else if (!strcmp(argv[i], "--dry-run") || !strcmp(argv[i], "-n")) + { + options |= SKIP; + } + else if (!strcmp(argv[i], "--update") || !strcmp(argv[i], "-u")) + { + options |= UPDATE; + } + else if (!strcmp(argv[i], "-h")) + { + print_usage(); + break; + } + else if (!strcmp(argv[i], "--")) + { + i++; + break; + } + else + { + fprintf(stderr, "Unsupported option %s.\n", argv[i]); + print_usage(); + return 1; + } + } if (argc <= i) { diff --git a/examples/branch.cpp b/examples/branch.cpp index 2880e47..9df894c 100644 --- a/examples/branch.cpp +++ b/examples/branch.cpp @@ -6,7 +6,7 @@ int main() { git::Initializer threads_initializer; - + git::Repository repo("."); auto branches = repo.branches(git::branch_type::ALL); for (auto const & b : branches) diff --git a/examples/cat-file.cpp b/examples/cat-file.cpp index 6dadc7f..8f1d23a 100644 --- a/examples/cat-file.cpp +++ b/examples/cat-file.cpp @@ -1,217 +1,230 @@ -#include #include +#include #include #include #include +#include "git2cpp/id_to_str.h" #include "git2cpp/initializer.h" #include "git2cpp/repo.h" -#include "git2cpp/id_to_str.h" -static void check(int error, const char *message) +static void check(int error, const char * message) { - if (error) { - fprintf(stderr, "%s (%d)\n", message, error); - exit(1); - } + if (error) + { + fprintf(stderr, "%s (%d)\n", message, error); + exit(1); + } } -static void usage(const char *message, const char *arg) +static void usage(const char * message, const char * arg) { - if (message && arg) - fprintf(stderr, "%s: %s\n", message, arg); - else if (message) - fprintf(stderr, "%s\n", message); - fprintf(stderr, "usage: cat-file (-t | -s | -e | -p) [] \n"); - exit(1); + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: cat-file (-t | -s | -e | -p) [] \n"); + exit(1); } static int check_str_param( - const char *arg, const char *pattern, const char **val) + const char * arg, const char * pattern, const char ** val) { - size_t len = strlen(pattern); - if (strncmp(arg, pattern, len)) - return 0; - *val = (const char *)(arg + len); - return 1; + size_t len = strlen(pattern); + if (strncmp(arg, pattern, len)) + return 0; + *val = (const char *)(arg + len); + return 1; } -static void print_signature(const char *header, const git_signature *sig) +static void print_signature(const char * header, const git_signature * sig) { - char sign; - int offset, hours, minutes; - - if (!sig) - return; - - offset = sig->when.offset; - if (offset < 0) { - sign = '-'; - offset = -offset; - } else { - sign = '+'; - } - - hours = offset / 60; - minutes = offset % 60; - - printf("%s %s <%s> %ld %c%02d%02d\n", - header, sig->name, sig->email, (long)sig->when.time, - sign, hours, minutes); + char sign; + int offset, hours, minutes; + + if (!sig) + return; + + offset = sig->when.offset; + if (offset < 0) + { + sign = '-'; + offset = -offset; + } + else + { + sign = '+'; + } + + hours = offset / 60; + minutes = offset % 60; + + printf("%s %s <%s> %ld %c%02d%02d\n", + header, sig->name, sig->email, (long)sig->when.time, + sign, hours, minutes); } -static void show_blob(const git_blob *blob) +static void show_blob(const git_blob * blob) { - /* ? Does this need crlf filtering? */ - fwrite(git_blob_rawcontent(blob), static_cast(git_blob_rawsize(blob)), 1, stdout); + /* ? Does this need crlf filtering? */ + fwrite(git_blob_rawcontent(blob), static_cast(git_blob_rawsize(blob)), 1, stdout); } -static void show_tree(const git_tree *tree) +static void show_tree(const git_tree * tree) { - size_t i, max_i = (int)git_tree_entrycount(tree); - char oidstr[GIT_OID_HEXSZ + 1]; - const git_tree_entry *te; + size_t i, max_i = (int)git_tree_entrycount(tree); + char oidstr[GIT_OID_HEXSZ + 1]; + const git_tree_entry * te; - for (i = 0; i < max_i; ++i) { - te = git_tree_entry_byindex(tree, i); + for (i = 0; i < max_i; ++i) + { + te = git_tree_entry_byindex(tree, i); - git_oid_tostr(oidstr, sizeof(oidstr), git_tree_entry_id(te)); + git_oid_tostr(oidstr, sizeof(oidstr), git_tree_entry_id(te)); - printf("%06o %s %s\t%s\n", - git_tree_entry_filemode(te), - git_object_type2string(git_tree_entry_type(te)), - oidstr, git_tree_entry_name(te)); - } + printf("%06o %s %s\t%s\n", + git_tree_entry_filemode(te), + git_object_type2string(git_tree_entry_type(te)), + oidstr, git_tree_entry_name(te)); + } } -static void show_commit(const git_commit *commit) +static void show_commit(const git_commit * commit) { - unsigned int i, max_i; - char oidstr[GIT_OID_HEXSZ + 1]; + unsigned int i, max_i; + char oidstr[GIT_OID_HEXSZ + 1]; - git_oid_tostr(oidstr, sizeof(oidstr), git_commit_tree_id(commit)); - printf("tree %s\n", oidstr); + git_oid_tostr(oidstr, sizeof(oidstr), git_commit_tree_id(commit)); + printf("tree %s\n", oidstr); - max_i = (unsigned int)git_commit_parentcount(commit); - for (i = 0; i < max_i; ++i) { - git_oid_tostr(oidstr, sizeof(oidstr), git_commit_parent_id(commit, i)); - printf("parent %s\n", oidstr); - } + max_i = (unsigned int)git_commit_parentcount(commit); + for (i = 0; i < max_i; ++i) + { + git_oid_tostr(oidstr, sizeof(oidstr), git_commit_parent_id(commit, i)); + printf("parent %s\n", oidstr); + } - print_signature("author", git_commit_author(commit)); - print_signature("committer", git_commit_committer(commit)); + print_signature("author", git_commit_author(commit)); + print_signature("committer", git_commit_committer(commit)); - if (git_commit_message(commit)) - printf("\n%s\n", git_commit_message(commit)); + if (git_commit_message(commit)) + printf("\n%s\n", git_commit_message(commit)); } -static void show_tag(const git_tag *tag) +static void show_tag(const git_tag * tag) { - char oidstr[GIT_OID_HEXSZ + 1]; + char oidstr[GIT_OID_HEXSZ + 1]; - git_oid_tostr(oidstr, sizeof(oidstr), git_tag_target_id(tag));; - printf("object %s\n", oidstr); - printf("type %s\n", git_object_type2string(git_tag_target_type(tag))); - printf("tag %s\n", git_tag_name(tag)); - print_signature("tagger", git_tag_tagger(tag)); + git_oid_tostr(oidstr, sizeof(oidstr), git_tag_target_id(tag)); + ; + printf("object %s\n", oidstr); + printf("type %s\n", git_object_type2string(git_tag_target_type(tag))); + printf("tag %s\n", git_tag_name(tag)); + print_signature("tagger", git_tag_tagger(tag)); - if (git_tag_message(tag)) - printf("\n%s\n", git_tag_message(tag)); + if (git_tag_message(tag)) + printf("\n%s\n", git_tag_message(tag)); } -enum { - SHOW_TYPE = 1, - SHOW_SIZE = 2, - SHOW_NONE = 3, - SHOW_PRETTY = 4 +enum +{ + SHOW_TYPE = 1, + SHOW_SIZE = 2, + SHOW_NONE = 3, + SHOW_PRETTY = 4 }; -int main(int argc, char *argv[]) +int main(int argc, char * argv[]) { - const char *dir = ".", *rev = NULL; - int i, action = 0, verbose = 0; - char oidstr[GIT_OID_HEXSZ + 1]; - - for (i = 1; i < argc; ++i) { - char *a = argv[i]; - - if (a[0] != '-') { - if (rev != NULL) - usage("Only one rev should be provided", NULL); - else - rev = a; - } - else if (!strcmp(a, "-t")) - action = SHOW_TYPE; - else if (!strcmp(a, "-s")) - action = SHOW_SIZE; - else if (!strcmp(a, "-e")) - action = SHOW_NONE; - else if (!strcmp(a, "-p")) - action = SHOW_PRETTY; - else if (!strcmp(a, "-q")) - verbose = 0; - else if (!strcmp(a, "-v")) - verbose = 1; - else if (!strcmp(a, "--help") || !strcmp(a, "-h")) - usage(NULL, NULL); - else if (!check_str_param(a, "--git-dir=", &dir)) - usage("Unknown option", a); - } - - if (!action || !rev) - usage(NULL, NULL); + const char *dir = ".", *rev = NULL; + int i, action = 0, verbose = 0; + char oidstr[GIT_OID_HEXSZ + 1]; + + for (i = 1; i < argc; ++i) + { + char * a = argv[i]; + + if (a[0] != '-') + { + if (rev != NULL) + usage("Only one rev should be provided", NULL); + else + rev = a; + } + else if (!strcmp(a, "-t")) + action = SHOW_TYPE; + else if (!strcmp(a, "-s")) + action = SHOW_SIZE; + else if (!strcmp(a, "-e")) + action = SHOW_NONE; + else if (!strcmp(a, "-p")) + action = SHOW_PRETTY; + else if (!strcmp(a, "-q")) + verbose = 0; + else if (!strcmp(a, "-v")) + verbose = 1; + else if (!strcmp(a, "--help") || !strcmp(a, "-h")) + usage(NULL, NULL); + else if (!check_str_param(a, "--git-dir=", &dir)) + usage("Unknown option", a); + } + + if (!action || !rev) + usage(NULL, NULL); git::Initializer threads_initializer; git::Repository repo(dir); - git::Object obj = revparse_single(repo, rev); - - if (verbose) { - std::cout - << git_object_type2string(obj.type()) - << " " - << git::id_to_str(obj.id()) - << "\n--\n"; - } - - switch (action) { - case SHOW_TYPE: - printf("%s\n", git_object_type2string(obj.type())); - break; - case SHOW_SIZE: + git::Object obj = revparse_single(repo, rev); + + if (verbose) + { + std::cout + << git_object_type2string(obj.type()) + << " " + << git::id_to_str(obj.id()) + << "\n--\n"; + } + + switch (action) + { + case SHOW_TYPE: + printf("%s\n", git_object_type2string(obj.type())); + break; + case SHOW_SIZE: + { + git::Odb odb = repo.odb(); + git::OdbObject odbobj = odb.read(obj.id()); + + printf("%ld\n", (long)odbobj.size()); + } + break; + case SHOW_NONE: + /* just want return result */ + break; + case SHOW_PRETTY: + + switch (obj.type()) { - git::Odb odb = repo.odb(); - git::OdbObject odbobj = odb.read(obj.id()); - - printf("%ld\n", (long)odbobj.size()); - } - break; - case SHOW_NONE: - /* just want return result */ - break; - case SHOW_PRETTY: - - switch (obj.type()) { - case GIT_OBJ_BLOB: - show_blob(obj.as_blob()); - break; - case GIT_OBJ_COMMIT: - show_commit(obj.as_commit()); - break; - case GIT_OBJ_TREE: - show_tree(obj.as_tree()); - break; - case GIT_OBJ_TAG: - show_tag(obj.as_tag()); - break; - default: - printf("unknown %s\n", oidstr); - break; - } - break; - } - - return 0; + case GIT_OBJ_BLOB: + show_blob(obj.as_blob()); + break; + case GIT_OBJ_COMMIT: + show_commit(obj.as_commit()); + break; + case GIT_OBJ_TREE: + show_tree(obj.as_tree()); + break; + case GIT_OBJ_TAG: + show_tag(obj.as_tag()); + break; + default: + printf("unknown %s\n", oidstr); + break; + } + break; + } + + return 0; } diff --git a/examples/commit-graph-generator.cpp b/examples/commit-graph-generator.cpp index d7ef2df..0d07945 100644 --- a/examples/commit-graph-generator.cpp +++ b/examples/commit-graph-generator.cpp @@ -1,76 +1,78 @@ #include -#include #include +#include namespace { - struct visitor_t - { - void operator() (git::RevWalker & walker) - { - walker.sort(git::revwalker::sorting::topological); - walker.simplify_first_parent(); - - while (git::Commit commit = walker.next()) - { - output_commit(commit); + struct visitor_t + { + void operator()(git::RevWalker & walker) + { + walker.sort(git::revwalker::sorting::topological); + walker.simplify_first_parent(); - for (size_t i = 0; i != commit.parents_num(); ++i) + while (git::Commit commit = walker.next()) { - output_hash(commit.id()) << " -> "; - output_hash(commit.parent_id(i)) << "\n"; - } + output_commit(commit); - for (size_t i = 1; i < commit.parents_num(); ++i) - { - auto branch_walker = repo_.rev_walker(); - branch_walker.push(commit.parent_id(i)); - branch_walker.hide(commit.merge_base(0, i)); - (*this)(branch_walker); + for (size_t i = 0; i != commit.parents_num(); ++i) + { + output_hash(commit.id()) << " -> "; + output_hash(commit.parent_id(i)) << "\n"; + } + + for (size_t i = 1; i < commit.parents_num(); ++i) + { + auto branch_walker = repo_.rev_walker(); + branch_walker.push(commit.parent_id(i)); + branch_walker.hide(commit.merge_base(0, i)); + (*this)(branch_walker); + } } - } - } + } - visitor_t(git::Repository const & repo, std::ostream & out) - : repo_(repo) - , out_(out) - {} + visitor_t(git::Repository const & repo, std::ostream & out) + : repo_(repo) + , out_(out) + { + } - private: - std::ostream& output_hash(git_oid const & id) const - { - out_ << "C" << git::id_to_str(id, 6); - return out_; - } + private: + std::ostream & output_hash(git_oid const & id) const + { + out_ << "C" << git::id_to_str(id, 6); + return out_; + } - void output_commit(git::Commit const & commit) const - { - output_hash(commit.id()) << " [label=\"" << commit.summary() << "\"];" << "\n"; - } + void output_commit(git::Commit const & commit) const + { + output_hash(commit.id()) << " [label=\"" << commit.summary() << "\"];" + << "\n"; + } - private: - git::Repository const & repo_; - std::ostream & out_; - }; + private: + git::Repository const & repo_; + std::ostream & out_; + }; - void visit(git::Repository const & repo, std::ostream & out) - { - visitor_t visitor(repo, out); + void visit(git::Repository const & repo, std::ostream & out) + { + visitor_t visitor(repo, out); - git::RevWalker walker = repo.rev_walker(); - walker.push_head(); - visitor(walker); - } + git::RevWalker walker = repo.rev_walker(); + walker.push_head(); + visitor(walker); + } } int main(int argc, char * argv[]) { - auto_git_initializer; - git::Repository repo (argc >= 2 ? argv[1] : "."); - std::ofstream out (argc >= 3 ? argv[2] : "commit-graph.dot"); + auto_git_initializer; + git::Repository repo(argc >= 2 ? argv[1] : "."); + std::ofstream out(argc >= 3 ? argv[2] : "commit-graph.dot"); - out << "digraph {\n"; - visit(repo, out); - out << "}\n"; + out << "digraph {\n"; + visit(repo, out); + out << "}\n"; } diff --git a/examples/diff.cpp b/examples/diff.cpp index 858d911..ef8efca 100644 --- a/examples/diff.cpp +++ b/examples/diff.cpp @@ -1,66 +1,66 @@ -#include #include +#include #include #include #include +#include "git2cpp/diff.h" #include "git2cpp/initializer.h" #include "git2cpp/repo.h" -#include "git2cpp/diff.h" using namespace git; -Tree resolve_to_tree(Repository const & repo, const char *identifier) +Tree resolve_to_tree(Repository const & repo, const char * identifier) { - Object obj = revparse_single(repo, identifier); - - switch (obj.type()) - { - case GIT_OBJ_TREE: - return obj.to_tree(); - break; - case GIT_OBJ_COMMIT: - return obj.to_commit().tree(); - break; - } - - std::ostringstream ss; - ss - << "object corresponding to identifier " - << identifier - << " is neither commit or tree"; - - throw std::logic_error(ss.str()); + Object obj = revparse_single(repo, identifier); + + switch (obj.type()) + { + case GIT_OBJ_TREE: + return obj.to_tree(); + break; + case GIT_OBJ_COMMIT: + return obj.to_commit().tree(); + break; + } + + std::ostringstream ss; + ss + << "object corresponding to identifier " + << identifier + << " is neither commit or tree"; + + throw std::logic_error(ss.str()); } -const char *colors[] = { - "\033[m", /* reset */ - "\033[1m", /* bold */ - "\033[31m", /* red */ - "\033[32m", /* green */ - "\033[36m" /* cyan */ +const char * colors[] = { + "\033[m", /* reset */ + "\033[1m", /* bold */ + "\033[31m", /* red */ + "\033[32m", /* green */ + "\033[36m" /* cyan */ }; -static void usage(const char *message, const char *arg) +static void usage(const char * message, const char * arg) { - if (message && arg) - fprintf(stderr, "%s: %s\n", message, arg); - else if (message) - fprintf(stderr, "%s\n", message); - fprintf(stderr, "usage: diff [ []]\n"); - exit(1); + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: diff [ []]\n"); + exit(1); } namespace output { typedef tagged_mask_t type; - const type diff (1 << 0); - const type stat (1 << 1); + const type diff(1 << 0); + const type stat(1 << 1); const type shortstat(1 << 2); - const type numstat (1 << 3); - const type summary (1 << 4); + const type numstat(1 << 3); + const type summary(1 << 4); } enum class cache_t @@ -71,27 +71,28 @@ enum class cache_t }; /** The 'opts' struct captures all the various parsed command line options. */ -struct opts_t { +struct opts_t +{ git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; int color = -1; cache_t cache = cache_t::normal; output::type output; diff::format format = diff::format::patch; - const char *treeish1 = nullptr; - const char *treeish2 = nullptr; - const char *dir = "."; + const char * treeish1 = nullptr; + const char * treeish2 = nullptr; + const char * dir = "."; - opts_t(int argc, char *argv[]); + opts_t(int argc, char * argv[]); }; -size_t is_prefixed(const char *str, const char *pfx) +size_t is_prefixed(const char * str, const char * pfx) { size_t len = strlen(pfx); return strncmp(str, pfx, len) ? 0 : len; } -void fatal(const char *message, const char *extra) +void fatal(const char * message, const char * extra) { if (extra) fprintf(stderr, "%s %s\n", message, extra); @@ -104,34 +105,36 @@ void fatal(const char *message, const char *extra) struct args_info { private: - int argc; - char **argv; + int argc; + char ** argv; public: - int pos; + int pos; args_info(int argc, char ** argv) : argc(argc) , argv(argv) , pos(0) - {} + { + } - int match_str(const char **out, const char *opt); - int match_uint16(uint16_t *out, const char *opt); + int match_str(const char ** out, const char * opt); + int match_uint16(uint16_t * out, const char * opt); private: - const char * match_numeric(const char *opt); + const char * match_numeric(const char * opt); }; -int args_info::match_str(const char **out, const char *opt) +int args_info::match_str(const char ** out, const char * opt) { - const char *found = argv[pos]; + const char * found = argv[pos]; size_t len = is_prefixed(found, opt); if (!len) return 0; - if (!found[len]) { + if (!found[len]) + { if (pos + 1 == argc) fatal("expected value following argument", opt); ++pos; @@ -139,7 +142,8 @@ int args_info::match_str(const char **out, const char *opt) return 1; } - if (found[len] == '=') { + if (found[len] == '=') + { *out = found + len + 1; return 1; } @@ -147,20 +151,23 @@ int args_info::match_str(const char **out, const char *opt) return 0; } -const char * args_info::match_numeric(const char *opt) +const char * args_info::match_numeric(const char * opt) { - const char *found = argv[pos]; + const char * found = argv[pos]; size_t len = is_prefixed(found, opt); if (!len) return NULL; - if (!found[len]) { + if (!found[len]) + { if (pos + 1 == argc) fatal("expected numeric value following argument", opt); pos += 1; found = argv[pos]; - } else { + } + else + { found = found + len; if (*found == '=') found++; @@ -169,11 +176,11 @@ const char * args_info::match_numeric(const char *opt) return found; } -int args_info::match_uint16(uint16_t *out, const char *opt) +int args_info::match_uint16(uint16_t * out, const char * opt) { - const char *found = match_numeric(opt); + const char * found = match_numeric(opt); uint16_t val; - char *endptr = NULL; + char * endptr = NULL; if (!found) return 0; @@ -187,7 +194,7 @@ int args_info::match_uint16(uint16_t *out, const char *opt) return 1; } -int match_uint16_arg(uint32_t *out, args_info & args, const char *opt) +int match_uint16_arg(uint32_t * out, args_info & args, const char * opt) { uint16_t tmp; const int res = args.match_uint16(&tmp, opt); @@ -196,15 +203,16 @@ int match_uint16_arg(uint32_t *out, args_info & args, const char *opt) } /** Parse arguments as copied from git-diff. */ -opts_t::opts_t(int argc, char *argv[]) +opts_t::opts_t(int argc, char * argv[]) { args_info args(argc, argv); for (args.pos = 1; args.pos < argc; ++args.pos) { - const char *a = argv[args.pos]; + const char * a = argv[args.pos]; - if (a[0] != '-') { + if (a[0] != '-') + { if (treeish1 == NULL) treeish1 = a; else if (treeish2 == NULL) @@ -213,7 +221,8 @@ opts_t::opts_t(int argc, char *argv[]) usage("Only one or two tree identifiers can be provided", NULL); } else if (!strcmp(a, "-p") || !strcmp(a, "-u") || - !strcmp(a, "--patch")) { + !strcmp(a, "--patch")) + { output |= output::diff; format = diff::format::patch; } @@ -224,11 +233,12 @@ opts_t::opts_t(int argc, char *argv[]) else if (!strcmp(a, "--name-only") || !strcmp(a, "--format=name")) format = diff::format::name_only; else if (!strcmp(a, "--name-status") || - !strcmp(a, "--format=name-status")) + !strcmp(a, "--format=name-status")) format = diff::format::name_status; else if (!strcmp(a, "--raw") || !strcmp(a, "--format=raw")) format = diff::format::raw; - else if (!strcmp(a, "--format=diff-index")) { + else if (!strcmp(a, "--format=diff-index")) + { format = diff::format::raw; diffopts.id_abbrev = 40; } @@ -263,14 +273,14 @@ opts_t::opts_t(int argc, char *argv[]) else if (!strcmp(a, "--summary")) output |= output::summary; else if (args.match_uint16( - &findopts.rename_threshold, "-M") || - args.match_uint16( - &findopts.rename_threshold, "--find-renames")) + &findopts.rename_threshold, "-M") || + args.match_uint16( + &findopts.rename_threshold, "--find-renames")) findopts.flags |= GIT_DIFF_FIND_RENAMES; else if (args.match_uint16( - &findopts.copy_threshold, "-C") || - args.match_uint16( - &findopts.copy_threshold, "--find-copies")) + &findopts.copy_threshold, "-C") || + args.match_uint16( + &findopts.copy_threshold, "--find-copies")) findopts.flags |= GIT_DIFF_FIND_COPIES; else if (!strcmp(a, "--find-copies-harder")) findopts.flags |= GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; @@ -278,16 +288,16 @@ opts_t::opts_t(int argc, char *argv[]) /* TODO: parse thresholds */ findopts.flags |= GIT_DIFF_FIND_REWRITES; else if (!match_uint16_arg( - &diffopts.context_lines, args, "-U") && - !match_uint16_arg( - &diffopts.context_lines, args, "--unified") && - !match_uint16_arg( - &diffopts.interhunk_lines, args, "--inter-hunk-context") && - !args.match_uint16( - &diffopts.id_abbrev, "--abbrev") && - !args.match_str(&diffopts.old_prefix, "--src-prefix") && - !args.match_str(&diffopts.new_prefix, "--dst-prefix") && - !args.match_str(&dir, "--git-dir")) + &diffopts.context_lines, args, "-U") && + !match_uint16_arg( + &diffopts.context_lines, args, "--unified") && + !match_uint16_arg( + &diffopts.interhunk_lines, args, "--inter-hunk-context") && + !args.match_uint16( + &diffopts.id_abbrev, "--abbrev") && + !args.match_str(&diffopts.old_prefix, "--src-prefix") && + !args.match_str(&diffopts.new_prefix, "--dst-prefix") && + !args.match_str(&dir, "--git-dir")) usage("Unknown command line argument", a); } } @@ -321,18 +331,34 @@ int color_printer(git_diff_delta const &, git_diff_hunk const &, git_diff_line c { int color = 0; - if (last_color >= 0) { - switch (l.origin) { - case GIT_DIFF_LINE_ADDITION: color = 3; break; - case GIT_DIFF_LINE_DELETION: color = 2; break; - case GIT_DIFF_LINE_ADD_EOFNL: color = 3; break; - case GIT_DIFF_LINE_DEL_EOFNL: color = 2; break; - case GIT_DIFF_LINE_FILE_HDR: color = 1; break; - case GIT_DIFF_LINE_HUNK_HDR: color = 4; break; - default: break; + if (last_color >= 0) + { + switch (l.origin) + { + case GIT_DIFF_LINE_ADDITION: + color = 3; + break; + case GIT_DIFF_LINE_DELETION: + color = 2; + break; + case GIT_DIFF_LINE_ADD_EOFNL: + color = 3; + break; + case GIT_DIFF_LINE_DEL_EOFNL: + color = 2; + break; + case GIT_DIFF_LINE_FILE_HDR: + color = 1; + break; + case GIT_DIFF_LINE_HUNK_HDR: + color = 4; + break; + default: + break; } - if (color != last_color) { + if (color != last_color) + { if (last_color == 1 || color == 1) fputs(colors[0], stdout); fputs(colors[color], stdout); @@ -368,7 +394,7 @@ void diff_print_stats(Diff const & diff, output::type output) fputs(buf.ptr(), stdout); } -int main(int argc, char *argv[]) +int main(int argc, char * argv[]) { auto_git_initializer; opts_t opts(argc, argv); @@ -402,4 +428,3 @@ int main(int argc, char *argv[]) fputs(colors[0], stdout); } } - diff --git a/examples/general.cpp b/examples/general.cpp index f07541c..e5d6a23 100644 --- a/examples/general.cpp +++ b/examples/general.cpp @@ -28,47 +28,47 @@ #include #include -#include #include +#include +#include "git2cpp/config.h" #include "git2cpp/initializer.h" #include "git2cpp/repo.h" -#include "git2cpp/config.h" using namespace git; // Almost all libgit2 functions return 0 on success or negative on error. // This is not production quality error checking, but should be sufficient // as an example. -static void check_error(int error_code, const char *action) +static void check_error(int error_code, const char * action) { - if (!error_code) - return; + if (!error_code) + return; - const git_error *error = giterr_last(); + const git_error * error = giterr_last(); - printf("Error %d %s - %s\n", error_code, action, - (error && error->message) ? error->message : "???"); + printf("Error %d %s - %s\n", error_code, action, + (error && error->message) ? error->message : "???"); - exit(1); + exit(1); } -int main (int argc, char** argv) +int main(int argc, char ** argv) { - // ### Opening the Repository - - // There are a couple of methods for opening a repository, this being the - // simplest. There are also [methods][me] for specifying the index file - // and work tree locations, here we assume they are in the normal places. - // - // (Try running this program against libgit2/tests/resources/testrepo.git/) - // - // [me]: http://libgit2.github.com/libgit2/#HEAD/group/repository + // ### Opening the Repository + + // There are a couple of methods for opening a repository, this being the + // simplest. There are also [methods][me] for specifying the index file + // and work tree locations, here we assume they are in the normal places. + // + // (Try running this program against libgit2/tests/resources/testrepo.git/) + // + // [me]: http://libgit2.github.com/libgit2/#HEAD/group/repository assert(argc >= 2); - const char *repo_path = argv[1]; + const char * repo_path = argv[1]; git::Initializer threads_initializer; - + try { Repository repo(repo_path); @@ -223,12 +223,12 @@ int main (int argc, char** argv) // the values we need to create the commit. The SHA key is written to the // `commit_id` variable here. git_oid commit_id = repo.create_commit( - nullptr, /* do not update the HEAD */ - author, - cmtter, - "example commit", - tree, - parent); + nullptr, /* do not update the HEAD */ + author, + cmtter, + "example commit", + tree, + parent); // Now we can take a look at the commit SHA we've generated. std::cout << "New Commit: " << id_to_str(commit_id) << std::endl; @@ -254,9 +254,9 @@ int main (int argc, char** argv) // the target object (usually 'commit'), the name ('v1.0'), the tagger (a // git_signature - name, email, timestamp), and the tag message. Object commit = tag.target(); - const char * tname = tag.name(); // "test" - git_otype ttype = tag.target_type(); // GIT_OBJ_COMMIT (otype enum) - const char * tmessage = tag.message();// "tag message\n" + const char * tname = tag.name(); // "test" + git_otype ttype = tag.target_type(); // GIT_OBJ_COMMIT (otype enum) + const char * tmessage = tag.message(); // "tag message\n" std::cout << "Tag Message: " << tmessage << std::endl; } @@ -327,7 +327,7 @@ int main (int argc, char** argv) // string, and use the `git_blob_rawsize` attribute to find out its exact // size in bytes printf("Blob Size: %ld\n", (long)blob.size()); // 8 - blob.content(); // "content" + blob.content(); // "content" } { @@ -364,7 +364,7 @@ int main (int argc, char** argv) // since the raw contents of the commit object will be cached in memory while (auto commit = walk.next()) { - char const * cmsg = commit.message(); + char const * cmsg = commit.message(); git_signature const * cauth = commit.author(); printf("%s (%s)\n", cmsg, cauth->email); } @@ -394,7 +394,7 @@ int main (int argc, char** argv) // the `git_index_entry` struct for (size_t i = 0, ecount = index.entrycount(); i < ecount; ++i) { - const git_index_entry *e = index[i]; + const git_index_entry * e = index[i]; printf("path: %s\n", e->path); printf("mtime: %d\n", (int)e->mtime.seconds); @@ -483,4 +483,3 @@ int main (int argc, char** argv) return 1; } } - diff --git a/examples/init.cpp b/examples/init.cpp index e6dc89a..34fa080 100644 --- a/examples/init.cpp +++ b/examples/init.cpp @@ -23,47 +23,48 @@ #include "git2cpp/initializer.h" #include "git2cpp/repo.h" -static void usage(const char *error, const char *arg) +static void usage(const char * error, const char * arg) { - fprintf(stderr, "error: %s '%s'\n", error, arg); - fprintf(stderr, "usage: init [-q | --quiet] [--bare] " - "[--template=] [--shared[=perms]] \n"); - exit(1); + fprintf(stderr, "error: %s '%s'\n", error, arg); + fprintf(stderr, "usage: init [-q | --quiet] [--bare] " + "[--template=] [--shared[=perms]] \n"); + exit(1); } /* simple string prefix test used in argument parsing */ -static size_t is_prefixed(const char *arg, const char *pfx) +static size_t is_prefixed(const char * arg, const char * pfx) { - size_t len = strlen(pfx); - return !strncmp(arg, pfx, len) ? len : 0; + size_t len = strlen(pfx); + return !strncmp(arg, pfx, len) ? len : 0; } /* parse the tail of the --shared= argument */ -static uint32_t parse_shared(const char *shared) +static uint32_t parse_shared(const char * shared) { - if (!strcmp(shared, "false") || !strcmp(shared, "umask")) - return GIT_REPOSITORY_INIT_SHARED_UMASK; - - else if (!strcmp(shared, "true") || !strcmp(shared, "group")) - return GIT_REPOSITORY_INIT_SHARED_GROUP; - - else if (!strcmp(shared, "all") || !strcmp(shared, "world") || - !strcmp(shared, "everybody")) - return GIT_REPOSITORY_INIT_SHARED_ALL; - - else if (shared[0] == '0') { - long val; - char *end = NULL; - val = strtol(shared + 1, &end, 8); - if (end == shared + 1 || *end != 0) - usage("invalid octal value for --shared", shared); - return (uint32_t)val; - } + if (!strcmp(shared, "false") || !strcmp(shared, "umask")) + return GIT_REPOSITORY_INIT_SHARED_UMASK; + + else if (!strcmp(shared, "true") || !strcmp(shared, "group")) + return GIT_REPOSITORY_INIT_SHARED_GROUP; + + else if (!strcmp(shared, "all") || !strcmp(shared, "world") || + !strcmp(shared, "everybody")) + return GIT_REPOSITORY_INIT_SHARED_ALL; + + else if (shared[0] == '0') + { + long val; + char * end = NULL; + val = strtol(shared + 1, &end, 8); + if (end == shared + 1 || *end != 0) + usage("invalid octal value for --shared", shared); + return (uint32_t)val; + } - else - usage("unknown value for --shared", shared); + else + usage("unknown value for --shared", shared); - return 0; + return 0; } using namespace git; @@ -71,22 +72,24 @@ using namespace git; /* forward declaration of helper to make an empty parent-less commit */ static void create_initial_commit(Repository & repo); -git_repository_init_options make_opts( bool bare, const char * templ, - uint32_t shared, - const char * gitdir, - const char * dir ) +git_repository_init_options make_opts(bool bare, const char * templ, + uint32_t shared, + const char * gitdir, + const char * dir) { git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; if (bare) opts.flags |= GIT_REPOSITORY_INIT_BARE; - if (templ) { + if (templ) + { opts.flags |= GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; opts.template_path = templ; } - if (gitdir) { + if (gitdir) + { /* if you specified a separate git directory, then initialize * the repository at that path and use the second path as the * working directory of the repository (with a git-link file) @@ -101,75 +104,79 @@ git_repository_init_options make_opts( bool bare, const char * templ, return opts; } -int main(int argc, char *argv[]) +int main(int argc, char * argv[]) { - int no_options = 1, quiet = 0, bare = 0, initial_commit = 0, i; - uint32_t shared = GIT_REPOSITORY_INIT_SHARED_UMASK; - const char *templ = NULL, *gitdir = NULL, *dir = NULL; - size_t pfxlen; + int no_options = 1, quiet = 0, bare = 0, initial_commit = 0, i; + uint32_t shared = GIT_REPOSITORY_INIT_SHARED_UMASK; + const char *templ = NULL, *gitdir = NULL, *dir = NULL; + size_t pfxlen; auto_git_initializer; - /* Process arguments */ - - for (i = 1; i < argc; ++i) { - char *a = argv[i]; - - if (a[0] == '-') - no_options = 0; - - if (a[0] != '-') { - if (dir != NULL) - usage("extra argument", a); - dir = a; - } - else if (!strcmp(a, "-q") || !strcmp(a, "--quiet")) - quiet = 1; - else if (!strcmp(a, "--bare")) - bare = 1; - else if ((pfxlen = is_prefixed(a, "--template=")) > 0) - templ = a + pfxlen; - else if (!strcmp(a, "--separate-git-dir")) - gitdir = argv[++i]; - else if ((pfxlen = is_prefixed(a, "--separate-git-dir=")) > 0) - gitdir = a + pfxlen; - else if (!strcmp(a, "--shared")) - shared = GIT_REPOSITORY_INIT_SHARED_GROUP; - else if ((pfxlen = is_prefixed(a, "--shared=")) > 0) - shared = parse_shared(a + pfxlen); - else if (!strcmp(a, "--initial-commit")) - initial_commit = 1; - else - usage("unknown option", a); - } - - if (!dir) - usage("must specify directory to init", NULL); - - /* Initialize repository */ - - Repository repo = no_options - ? Repository(dir, Repository::init) - : Repository(dir, Repository::init, make_opts(bare, templ, shared, gitdir, dir)); - - /* Print a message to stdout like "git init" does */ - - if (!quiet) { - printf("Initialized empty Git repository in %s\n", + /* Process arguments */ + + for (i = 1; i < argc; ++i) + { + char * a = argv[i]; + + if (a[0] == '-') + no_options = 0; + + if (a[0] != '-') + { + if (dir != NULL) + usage("extra argument", a); + dir = a; + } + else if (!strcmp(a, "-q") || !strcmp(a, "--quiet")) + quiet = 1; + else if (!strcmp(a, "--bare")) + bare = 1; + else if ((pfxlen = is_prefixed(a, "--template=")) > 0) + templ = a + pfxlen; + else if (!strcmp(a, "--separate-git-dir")) + gitdir = argv[++i]; + else if ((pfxlen = is_prefixed(a, "--separate-git-dir=")) > 0) + gitdir = a + pfxlen; + else if (!strcmp(a, "--shared")) + shared = GIT_REPOSITORY_INIT_SHARED_GROUP; + else if ((pfxlen = is_prefixed(a, "--shared=")) > 0) + shared = parse_shared(a + pfxlen); + else if (!strcmp(a, "--initial-commit")) + initial_commit = 1; + else + usage("unknown option", a); + } + + if (!dir) + usage("must specify directory to init", NULL); + + /* Initialize repository */ + + Repository repo = no_options + ? Repository(dir, Repository::init) + : Repository(dir, Repository::init, make_opts(bare, templ, shared, gitdir, dir)); + + /* Print a message to stdout like "git init" does */ + + if (!quiet) + { + printf("Initialized empty Git repository in %s\n", (bare || gitdir) ? repo.path() : repo.workdir()); - } + } - /* As an extension to the basic "git init" command, this example + /* As an extension to the basic "git init" command, this example * gives the option to create an empty initial commit. This is * mostly to demonstrate what it takes to do that, but also some * people like to have that empty base commit in their repo. */ - if (initial_commit) { - create_initial_commit(repo); - printf("Created empty initial commit\n"); - } + if (initial_commit) + { + create_initial_commit(repo); + printf("Created empty initial commit\n"); + } - return 0; + return 0; } /* Unlike regular "git init", this example shows how to create an initial @@ -178,13 +185,13 @@ int main(int argc, char *argv[]) */ static void create_initial_commit(Repository & repo) { - /* First use the config to initialize a commit signature for the user */ - Signature sig = repo.signature(); + /* First use the config to initialize a commit signature for the user */ + Signature sig = repo.signature(); - /* Now let's create an empty tree for this commit */ - Index index = repo.index(); + /* Now let's create an empty tree for this commit */ + Index index = repo.index(); - /* Outside of this example, you could call git_index_add_bypath() + /* Outside of this example, you could call git_index_add_bypath() * here to put actual files into the index. For our purposes, we'll * leave it empty for now. */ @@ -192,7 +199,7 @@ static void create_initial_commit(Repository & repo) git_oid tree_id = index.write_tree(); Tree tree = repo.tree_lookup(tree_id); - /* Ready to create the initial commit + /* Ready to create the initial commit * * Normally creating a commit would involve looking up the current * HEAD commit and making that be the parent of the initial commit, diff --git a/examples/log.cpp b/examples/log.cpp index 4c977ca..50dd947 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -4,368 +4,387 @@ #include -#include "git2cpp/repo.h" -#include "git2cpp/pathspec.h" -#include "git2cpp/initializer.h" +#include "git2cpp/diff.h" #include "git2cpp/id_to_str.h" +#include "git2cpp/initializer.h" +#include "git2cpp/pathspec.h" +#include "git2cpp/repo.h" #include "git2cpp/revspec.h" #include "git2cpp/revwalker.h" -#include "git2cpp/diff.h" #include "git2cpp/internal/optional.h" -static void usage(const char *message, const char *arg) +static void usage(const char * message, const char * arg) { - if (message && arg) - fprintf(stderr, "%s: %s\n", message, arg); - else if (message) - fprintf(stderr, "%s\n", message); - fprintf(stderr, "usage: log []\n"); - exit(1); + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: log []\n"); + exit(1); } struct log_state { - const char * repodir = "."; - git::internal::optional repo; - git::internal::optional walker; - int hide = 0; - git::revwalker::sorting::type sorting = git::revwalker::sorting::time; + const char * repodir = "."; + git::internal::optional repo; + git::internal::optional walker; + int hide = 0; + git::revwalker::sorting::type sorting = git::revwalker::sorting::time; }; -static void set_sorting(struct log_state *s, git::revwalker::sorting::type sort_mode) +static void set_sorting(struct log_state * s, git::revwalker::sorting::type sort_mode) { - if (!s->repo) { - git::internal::emplace(s->repo, s->repodir); - } + if (!s->repo) + { + git::internal::emplace(s->repo, s->repodir); + } - if (!s->walker) - s->walker = s->repo->rev_walker(); + if (!s->walker) + s->walker = s->repo->rev_walker(); - if (sort_mode == git::revwalker::sorting::reverse) - s->sorting = s->sorting ^ git::revwalker::sorting::reverse; - else - s->sorting = sort_mode | (s->sorting & git::revwalker::sorting::reverse); + if (sort_mode == git::revwalker::sorting::reverse) + s->sorting = s->sorting ^ git::revwalker::sorting::reverse; + else + s->sorting = sort_mode | (s->sorting & git::revwalker::sorting::reverse); - s->walker->sort(s->sorting); + s->walker->sort(s->sorting); } void push_rev(log_state * s, git::Commit const & commit, int hide) { - hide = s->hide ^ hide; - - if (!s->walker) { - s->walker = s->repo->rev_walker(); - s->walker->sort(s->sorting); - } - - if (!commit) - s->walker->push_head(); - else if (hide) - s->walker->hide(commit.id()); - else - s->walker->push(commit.id()); + hide = s->hide ^ hide; + + if (!s->walker) + { + s->walker = s->repo->rev_walker(); + s->walker->sort(s->sorting); + } + + if (!commit) + s->walker->push_head(); + else if (hide) + s->walker->hide(commit.id()); + else + s->walker->push(commit.id()); } -void push_rev(struct log_state *s, git::Object const & obj, int hide) +void push_rev(struct log_state * s, git::Object const & obj, int hide) { - hide = s->hide ^ hide; - - if (!s->walker) { - s->walker = s->repo->rev_walker(); - s->walker->sort(s->sorting); - } - - if (!obj) - s->walker->push_head(); - else if (hide) - s->walker->hide(obj.id()); - else - s->walker->push(obj.id()); + hide = s->hide ^ hide; + + if (!s->walker) + { + s->walker = s->repo->rev_walker(); + s->walker->sort(s->sorting); + } + + if (!obj) + s->walker->push_head(); + else if (hide) + s->walker->hide(obj.id()); + else + s->walker->push(obj.id()); } -void add_revision(struct log_state *s, const char *revstr) +void add_revision(struct log_state * s, const char * revstr) { - int hide = 0; - - if (!s->repo) { - git::internal::emplace(s->repo, s->repodir); - } - - if (!revstr) { - push_rev(s, git::Commit(), hide); - return; - } - - if (*revstr == '^') - hide = !hide; - - git::Revspec revs = (*revstr == '^') - ? s->repo->revparse_single(revstr + 1) - : s->repo->revparse(revstr); - - if (auto obj = revs.single()) - { - push_rev(s, *obj, hide); - } - else - { - git::Revspec::Range const & range = *revs.range(); - push_rev(s, range.to, hide); - - if ((revs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) { - git_oid base = s->repo->merge_base(range); - push_rev(s, s->repo->commit_lookup(base), hide); - } - - push_rev(s, range.from, !hide); - } + int hide = 0; + + if (!s->repo) + { + git::internal::emplace(s->repo, s->repodir); + } + + if (!revstr) + { + push_rev(s, git::Commit(), hide); + return; + } + + if (*revstr == '^') + hide = !hide; + + git::Revspec revs = (*revstr == '^') + ? s->repo->revparse_single(revstr + 1) + : s->repo->revparse(revstr); + + if (auto obj = revs.single()) + { + push_rev(s, *obj, hide); + } + else + { + git::Revspec::Range const & range = *revs.range(); + push_rev(s, range.to, hide); + + if ((revs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) + { + git_oid base = s->repo->merge_base(range); + push_rev(s, s->repo->commit_lookup(base), hide); + } + + push_rev(s, range.from, !hide); + } } -static void print_time(const git_time *intime, const char *prefix) +static void print_time(const git_time * intime, const char * prefix) { - char sign, out[32]; + char sign, out[32]; - int offset = intime->offset; - if (offset < 0) { - sign = '-'; - offset = -offset; - } else { - sign = '+'; - } + int offset = intime->offset; + if (offset < 0) + { + sign = '-'; + offset = -offset; + } + else + { + sign = '+'; + } - int hours = offset / 60; - int minutes = offset % 60; + int hours = offset / 60; + int minutes = offset % 60; - time_t t = static_cast(intime->time) + (intime->offset * 60); + time_t t = static_cast(intime->time) + (intime->offset * 60); - auto intm = gmtime(&t); - strftime(out, sizeof(out), "%a %b %e %T %Y", intm); + auto intm = gmtime(&t); + strftime(out, sizeof(out), "%a %b %e %T %Y", intm); - printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); + printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); } static void print_commit(git::Commit const & commit) { - int i, count; - const git_signature *sig; - const char *scan, *eol; - - printf("commit %s\n", git::id_to_str(commit.id()).c_str()); - - if ((count = (int)commit.parents_num()) > 1) { - printf("Merge:"); - for (i = 0; i < count; ++i) { - printf(" %s", git::id_to_str(commit.parent_id(i), 7).c_str()); - } - printf("\n"); - } - - if ((sig = commit.author()) != NULL) { - printf("Author: %s <%s>\n", sig->name, sig->email); - print_time(&sig->when, "Date: "); - } - printf("\n"); - - for (scan = commit.message(); scan && *scan; ) { - for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */; - - printf(" %.*s\n", (int)(eol - scan), scan); - scan = *eol ? eol + 1 : NULL; - } - printf("\n"); + int i, count; + const git_signature * sig; + const char *scan, *eol; + + printf("commit %s\n", git::id_to_str(commit.id()).c_str()); + + if ((count = (int)commit.parents_num()) > 1) + { + printf("Merge:"); + for (i = 0; i < count; ++i) + { + printf(" %s", git::id_to_str(commit.parent_id(i), 7).c_str()); + } + printf("\n"); + } + + if ((sig = commit.author()) != NULL) + { + printf("Author: %s <%s>\n", sig->name, sig->email); + print_time(&sig->when, "Date: "); + } + printf("\n"); + + for (scan = commit.message(); scan && *scan;) + { + for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */ + ; + + printf(" %.*s\n", (int)(eol - scan), scan); + scan = *eol ? eol + 1 : NULL; + } + printf("\n"); } void print_diff(git_diff_delta const &, git_diff_hunk const &, git_diff_line const & line) { - fwrite(line.content, 1, line.content_len, stdout); + fwrite(line.content, 1, line.content_len, stdout); } -static int match_int(int *value, const char *arg, int allow_negative) +static int match_int(int * value, const char * arg, int allow_negative) { - char *found; - *value = (int)strtol(arg, &found, 10); - return (found && *found == '\0' && (allow_negative || *value >= 0)); + char * found; + *value = (int)strtol(arg, &found, 10); + return (found && *found == '\0' && (allow_negative || *value >= 0)); } static int match_int_arg( - int *value, const char *arg, const char *pfx, int allow_negative) + int * value, const char * arg, const char * pfx, int allow_negative) { - size_t pfxlen = strlen(pfx); - if (strncmp(arg, pfx, pfxlen) != 0) - return 0; - if (!match_int(value, arg + pfxlen, allow_negative)) - usage("Invalid value after argument", arg); - return 1; + size_t pfxlen = strlen(pfx); + if (strncmp(arg, pfx, pfxlen) != 0) + return 0; + if (!match_int(value, arg + pfxlen, allow_negative)) + usage("Invalid value after argument", arg); + return 1; } static int match_with_parent(git::Commit const & commit, int i, git_diff_options const & opts) { - auto parent = commit.parent(i); - auto c_tree = commit.tree(); - auto p_tree = parent.tree(); - auto diff = commit.repo().diff(p_tree, c_tree, opts); + auto parent = commit.parent(i); + auto c_tree = commit.tree(); + auto p_tree = parent.tree(); + auto diff = commit.repo().diff(p_tree, c_tree, opts); - return diff.deltas_num() > 0; + return diff.deltas_num() > 0; } -struct log_options { - int show_diff; - int skip, limit; - int min_parents, max_parents; - git_time_t before; - git_time_t after; - char *author; - char *committer; +struct log_options +{ + int show_diff; + int skip, limit; + int min_parents, max_parents; + git_time_t before; + git_time_t after; + char * author; + char * committer; }; -int parse_options ( int argc, char *argv[] - , log_state & s - , log_options & opt - , int count - ) +int parse_options(int argc, char * argv[], log_state & s, log_options & opt, int count) { - int i = 1; - for (; i < argc; ++i) { - char* a = argv[i]; - - if (a[0] != '-') { - try - { - add_revision(&s, a); - ++count; - } - catch (...) /* try failed revision parse as filename */ - { - break; - } - } else if (!strcmp(a, "--")) { - ++i; - break; - } - else if (!strcmp(a, "--date-order")) - set_sorting(&s, git::revwalker::sorting::time); - else if (!strcmp(a, "--topo-order")) - set_sorting(&s, git::revwalker::sorting::topological); - else if (!strcmp(a, "--reverse")) - set_sorting(&s, git::revwalker::sorting::reverse); - else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) - s.repodir = a + strlen("--git-dir="); - else if (match_int_arg(&opt.skip, a, "--skip=", 0)) - /* found valid --skip */; - else if (match_int_arg(&opt.limit, a, "--max-count=", 0)) - /* found valid --max-count */; - else if (a[1] >= '0' && a[1] <= '9') { - if (!match_int(&opt.limit, a + 1, 0)) - usage("Invalid limit on number of commits", a); - } else if (!strcmp(a, "-n")) { - if (i + 1 == argc || !match_int(&opt.limit, argv[i + 1], 0)) - usage("Argument -n not followed by valid count", argv[i + 1]); - else + int i = 1; + for (; i < argc; ++i) + { + char * a = argv[i]; + + if (a[0] != '-') + { + try + { + add_revision(&s, a); + ++count; + } + catch (...) /* try failed revision parse as filename */ + { + break; + } + } + else if (!strcmp(a, "--")) + { ++i; - } - else if (!strcmp(a, "--merges")) - opt.min_parents = 2; - else if (!strcmp(a, "--no-merges")) - opt.max_parents = 1; - else if (!strcmp(a, "--no-min-parents")) - opt.min_parents = 0; - else if (!strcmp(a, "--no-max-parents")) - opt.max_parents = -1; - else if (match_int_arg(&opt.max_parents, a, "--max-parents=", 1)) - /* found valid --max-parents */; - else if (match_int_arg(&opt.min_parents, a, "--min-parents=", 0)) - /* found valid --min_parents */; - else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) - opt.show_diff = 1; - else - usage("Unsupported argument", a); - } - - return i; + break; + } + else if (!strcmp(a, "--date-order")) + set_sorting(&s, git::revwalker::sorting::time); + else if (!strcmp(a, "--topo-order")) + set_sorting(&s, git::revwalker::sorting::topological); + else if (!strcmp(a, "--reverse")) + set_sorting(&s, git::revwalker::sorting::reverse); + else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) + s.repodir = a + strlen("--git-dir="); + else if (match_int_arg(&opt.skip, a, "--skip=", 0)) + /* found valid --skip */; + else if (match_int_arg(&opt.limit, a, "--max-count=", 0)) + /* found valid --max-count */; + else if (a[1] >= '0' && a[1] <= '9') + { + if (!match_int(&opt.limit, a + 1, 0)) + usage("Invalid limit on number of commits", a); + } + else if (!strcmp(a, "-n")) + { + if (i + 1 == argc || !match_int(&opt.limit, argv[i + 1], 0)) + usage("Argument -n not followed by valid count", argv[i + 1]); + else + ++i; + } + else if (!strcmp(a, "--merges")) + opt.min_parents = 2; + else if (!strcmp(a, "--no-merges")) + opt.max_parents = 1; + else if (!strcmp(a, "--no-min-parents")) + opt.min_parents = 0; + else if (!strcmp(a, "--no-max-parents")) + opt.max_parents = -1; + else if (match_int_arg(&opt.max_parents, a, "--max-parents=", 1)) + /* found valid --max-parents */; + else if (match_int_arg(&opt.min_parents, a, "--min-parents=", 0)) + /* found valid --min_parents */; + else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) + opt.show_diff = 1; + else + usage("Unsupported argument", a); + } + + return i; } -int main(int argc, char *argv[]) +int main(int argc, char * argv[]) { - log_options opt; - memset(&opt, 0, sizeof(opt)); - opt.max_parents = -1; - opt.limit = -1; - - git::Initializer threads_initializer; - - log_state s; - - int count = 0; - int parsed_options_num = parse_options(argc, argv, s, opt, count); - - if (!count) - add_revision(&s, NULL); - - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - diffopts.pathspec.strings = &argv[parsed_options_num]; - diffopts.pathspec.count = argc - parsed_options_num; - git::Pathspec ps(diffopts.pathspec); - - count = 0; - int printed = 0; - - while (git::Commit commit = s.walker->next()) - { - int parents = commit.parents_num(); - if (parents < opt.min_parents) - continue; - if (opt.max_parents > 0 && parents > opt.max_parents) - continue; - - if (diffopts.pathspec.count > 0) - { - int unmatched = parents; - - if (parents == 0) - { - if (commit.tree().pathspec_match(GIT_PATHSPEC_NO_MATCH_ERROR, ps) != 0) - unmatched = 1; - } - else if (parents == 1) - { - unmatched = match_with_parent(commit, 0, diffopts) ? 0 : 1; - } - else - { - for (int i = 0; i < parents; ++i) + log_options opt; + memset(&opt, 0, sizeof(opt)); + opt.max_parents = -1; + opt.limit = -1; + + git::Initializer threads_initializer; + + log_state s; + + int count = 0; + int parsed_options_num = parse_options(argc, argv, s, opt, count); + + if (!count) + add_revision(&s, NULL); + + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + diffopts.pathspec.strings = &argv[parsed_options_num]; + diffopts.pathspec.count = argc - parsed_options_num; + git::Pathspec ps(diffopts.pathspec); + + count = 0; + int printed = 0; + + while (git::Commit commit = s.walker->next()) + { + int parents = commit.parents_num(); + if (parents < opt.min_parents) + continue; + if (opt.max_parents > 0 && parents > opt.max_parents) + continue; + + if (diffopts.pathspec.count > 0) + { + int unmatched = parents; + + if (parents == 0) + { + if (commit.tree().pathspec_match(GIT_PATHSPEC_NO_MATCH_ERROR, ps) != 0) + unmatched = 1; + } + else if (parents == 1) + { + unmatched = match_with_parent(commit, 0, diffopts) ? 0 : 1; + } + else { - if (match_with_parent(commit, i, diffopts)) - unmatched--; + for (int i = 0; i < parents; ++i) + { + if (match_with_parent(commit, i, diffopts)) + unmatched--; + } } - } - if (unmatched > 0) + if (unmatched > 0) + continue; + } + + if (count++ < opt.skip) continue; - } + if (opt.limit != -1 && printed++ >= opt.limit) + { + break; + } - if (count++ < opt.skip) - continue; - if (opt.limit != -1 && printed++ >= opt.limit) { - break; - } + print_commit(commit); - print_commit(commit); + if (opt.show_diff) + { + if (parents > 1) + continue; + git::Tree b = commit.tree(); + git::Tree a; + if (parents == 1) + { + a = commit.parent(0).tree(); + } - if (opt.show_diff) - { - if (parents > 1) - continue; - git::Tree b = commit.tree(); - git::Tree a; - if (parents == 1) - { - a = commit.parent(0).tree(); - } - - s.repo->diff(a, b, diffopts).print(git::diff::format::patch, print_diff); - } - } - - return 0; + s.repo->diff(a, b, diffopts).print(git::diff::format::patch, print_diff); + } + } + + return 0; } diff --git a/examples/rev-list.cpp b/examples/rev-list.cpp index 253c40b..6b2fbfb 100644 --- a/examples/rev-list.cpp +++ b/examples/rev-list.cpp @@ -7,91 +7,105 @@ #include "git2cpp/repo.h" #include "git2cpp/revwalker.h" -extern "C" -{ -#include +extern "C" { #include +#include } using namespace git; void push_commit(RevWalker const & walk, git_oid const & oid, int hide) { - if (hide) - return walk.hide(oid); - else - return walk.push(oid); + if (hide) + return walk.hide(oid); + else + return walk.push(oid); } -void push_spec(Repository const & repo, RevWalker const & walk, const char *spec, int hide) +void push_spec(Repository const & repo, RevWalker const & walk, const char * spec, int hide) { - push_commit(walk, revparse_single(repo, spec).id(), hide); + push_commit(walk, revparse_single(repo, spec).id(), hide); } -void push_range(Repository const & repo, RevWalker const & walk, const char *range, int hide) +void push_range(Repository const & repo, RevWalker const & walk, const char * range, int hide) { auto revspec = repo.revparse(range); - if (revspec.flags() & GIT_REVPARSE_MERGE_BASE) { - /* TODO: support "..." */ + if (revspec.flags() & GIT_REVPARSE_MERGE_BASE) + { + /* TODO: support "..." */ throw std::runtime_error("unsupported operation"); - } + } auto const & r = *revspec.range(); - push_commit(walk, r.to.id(), !hide); + push_commit(walk, r.to.id(), !hide); push_commit(walk, r.from.id(), hide); } -void revwalk_parseopts(Repository const & repo, RevWalker & walk, int nopts, char **opts) +void revwalk_parseopts(Repository const & repo, RevWalker & walk, int nopts, char ** opts) { - namespace sort = revwalker::sorting; - auto sorting = sort::none; - - int hide = 0; - for (int i = 0; i < nopts; i++) { - if (!strcmp(opts[i], "--topo-order")) { - sorting = sort::topological | (sorting & sort::reverse); - walk.sort(sorting); - } else if (!strcmp(opts[i], "--date-order")) { - sorting = sort::time | (sorting & sort::reverse); - walk.sort(sorting); - } else if (!strcmp(opts[i], "--reverse")) { - if ((sorting & sort::reverse) != sort::none) - sorting = sorting & ~sort::reverse; - walk.sort(sorting); - } else if (!strcmp(opts[i], "--not")) { - hide = !hide; - } else if (opts[i][0] == '^') { - push_spec(repo, walk, opts[i] + 1, !hide); - } else if (strstr(opts[i], "..")) { - push_range(repo, walk, opts[i], hide); - } else { - push_spec(repo, walk, opts[i], hide); - } - } + namespace sort = revwalker::sorting; + auto sorting = sort::none; + + int hide = 0; + for (int i = 0; i < nopts; i++) + { + if (!strcmp(opts[i], "--topo-order")) + { + sorting = sort::topological | (sorting & sort::reverse); + walk.sort(sorting); + } + else if (!strcmp(opts[i], "--date-order")) + { + sorting = sort::time | (sorting & sort::reverse); + walk.sort(sorting); + } + else if (!strcmp(opts[i], "--reverse")) + { + if ((sorting & sort::reverse) != sort::none) + sorting = sorting & ~sort::reverse; + walk.sort(sorting); + } + else if (!strcmp(opts[i], "--not")) + { + hide = !hide; + } + else if (opts[i][0] == '^') + { + push_spec(repo, walk, opts[i] + 1, !hide); + } + else if (strstr(opts[i], "..")) + { + push_range(repo, walk, opts[i], hide); + } + else + { + push_spec(repo, walk, opts[i], hide); + } + } } -int main (int argc, char **argv) +int main(int argc, char ** argv) { git::Initializer threads_initializer; try { - Repository repo("."); + Repository repo("."); auto walker = repo.rev_walker(); - revwalk_parseopts(repo, walker, argc-1, argv+1); + revwalk_parseopts(repo, walker, argc - 1, argv + 1); char buf[41]; - while (walker.next(buf)) + while (walker.next(buf)) { buf[40] = '\0'; printf("%s\n", buf); } - return 0; + return 0; } catch (std::exception const & e) { @@ -103,4 +117,3 @@ int main (int argc, char **argv) } } } - diff --git a/examples/rev-parse.cpp b/examples/rev-parse.cpp index d9c310d..37bf368 100644 --- a/examples/rev-parse.cpp +++ b/examples/rev-parse.cpp @@ -6,27 +6,28 @@ #include #include "git2cpp/initializer.h" -#include "git2cpp/repo.h" #include "git2cpp/internal/optional.h" +#include "git2cpp/repo.h" using namespace git; -static void usage(const char *message, const char *arg) +static void usage(const char * message, const char * arg) { - if (message && arg) - fprintf(stderr, "%s: %s\n", message, arg); - else if (message) - fprintf(stderr, "%s\n", message); - fprintf(stderr, "usage: rev-parse [ --option ] ...\n"); - exit(1); + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: rev-parse [ --option ] ...\n"); + exit(1); } -struct parse_state { +struct parse_state +{ internal::optional repo; const char * repodir = "."; }; -void parse_revision(parse_state & ps, const char *revstr) +void parse_revision(parse_state & ps, const char * revstr) { if (!ps.repo) internal::emplace(ps.repo, ps.repodir); @@ -35,38 +36,40 @@ void parse_revision(parse_state & ps, const char *revstr) if (auto commit = rs.single()) { - std::cout << id_to_str(commit->id()) << std::endl; - } - else + std::cout << id_to_str(commit->id()) << std::endl; + } + else { auto const & range = *rs.range(); std::cout << id_to_str(range.to.id()) << std::endl; - if ((rs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) { - git_oid base = ps.repo->merge_base(range); + if ((rs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) + { + git_oid base = ps.repo->merge_base(range); std::cout << id_to_str(base) << std::endl; - } + } std::cout << "^" << id_to_str(range.from.id()) << std::endl; - } + } } -int main(int argc, char *argv[]) +int main(int argc, char * argv[]) { auto_git_initializer; - parse_state ps; + parse_state ps; - for (int i = 1; i < argc; ++i) { - const char * a = argv[i]; + for (int i = 1; i < argc; ++i) + { + const char * a = argv[i]; - if (a[0] != '-') - parse_revision(ps, a); + if (a[0] != '-') + parse_revision(ps, a); else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) - ps.repodir = a + strlen("--git-dir="); - else - usage("Cannot handle argument", a); - } + ps.repodir = a + strlen("--git-dir="); + else + usage("Cannot handle argument", a); + } - return 0; + return 0; } diff --git a/examples/showindex.cpp b/examples/showindex.cpp index 3dd68a8..1927ef0 100644 --- a/examples/showindex.cpp +++ b/examples/showindex.cpp @@ -1,58 +1,55 @@ #include #include -extern "C" -{ #include -} #include "git2cpp/initializer.h" #include "git2cpp/repo.h" using namespace git; -int main (int argc, char** argv) +int main(int argc, char ** argv) { - const char * dir = "."; - - Initializer threads_initalizer; - - if (argc > 1) - dir = argv[1]; - if (!dir || argc > 2) { - fprintf(stderr, "usage: showindex []\n"); - return 1; - } - - size_t dirlen = strlen(dir); - Index index = (dirlen > 5 && strcmp(dir + dirlen - 5, "index") == 0) - ? Index(dir) - : Repository(dir).index(); - - size_t ecount = index.entrycount(); - if (!ecount) - printf("Empty index\n"); - - for (size_t i = 0; i < ecount; ++i) - { - auto e = index[i]; - - char out[41]; - out[40] = '\0'; - git_oid_fmt(out, &e->id); - - printf("File Path: %s\n", e->path); - printf(" Stage: %d\n", git_index_entry_stage(e)); - printf(" Blob SHA: %s\n", out); - printf("File Mode: %07o\n", e->mode); - printf("File Size: %d bytes\n", (int)e->file_size); - printf("Dev/Inode: %d/%d\n", (int)e->dev, (int)e->ino); - printf(" UID/GID: %d/%d\n", (int)e->uid, (int)e->gid); - printf(" ctime: %d\n", (int)e->ctime.seconds); - printf(" mtime: %d\n", (int)e->mtime.seconds); - printf("\n"); - } - - return 0; + const char * dir = "."; + + Initializer threads_initalizer; + + if (argc > 1) + dir = argv[1]; + if (!dir || argc > 2) + { + fprintf(stderr, "usage: showindex []\n"); + return 1; + } + + size_t dirlen = strlen(dir); + Index index = (dirlen > 5 && strcmp(dir + dirlen - 5, "index") == 0) + ? Index(dir) + : Repository(dir).index(); + + size_t ecount = index.entrycount(); + if (!ecount) + printf("Empty index\n"); + + for (size_t i = 0; i < ecount; ++i) + { + auto e = index[i]; + + char out[41]; + out[40] = '\0'; + git_oid_fmt(out, &e->id); + + printf("File Path: %s\n", e->path); + printf(" Stage: %d\n", git_index_entry_stage(e)); + printf(" Blob SHA: %s\n", out); + printf("File Mode: %07o\n", e->mode); + printf("File Size: %d bytes\n", (int)e->file_size); + printf("Dev/Inode: %d/%d\n", (int)e->dev, (int)e->ino); + printf(" UID/GID: %d/%d\n", (int)e->uid, (int)e->gid); + printf(" ctime: %d\n", (int)e->ctime.seconds); + printf(" mtime: %d\n", (int)e->mtime.seconds); + printf("\n"); + } + + return 0; } - diff --git a/examples/status.cpp b/examples/status.cpp index a5b0a95..8a6ff7f 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -12,30 +12,31 @@ #include "git2cpp/repo.h" #ifdef USE_BOOST - #include +#include #include - template - using Optional = boost::optional; +template +using Optional = boost::optional; - using StringView = boost::string_view; +using StringView = boost::string_view; #else - #include - #include +#include +#include - template - using Optional = std::optional; +template +using Optional = std::optional; - using StringView = std::string_view; +using StringView = std::string_view; #endif using namespace git; -enum { - FORMAT_DEFAULT = 0, - FORMAT_LONG = 1, - FORMAT_SHORT = 2, - FORMAT_PORCELAIN = 3, +enum +{ + FORMAT_DEFAULT = 0, + FORMAT_LONG = 1, + FORMAT_SHORT = 2, + FORMAT_PORCELAIN = 3, }; /* @@ -71,8 +72,12 @@ void show_branch(Repository const & repo, int format) if (starts_with(*branch, refs_heads)) branch->remove_prefix(refs_heads.length()); } - catch (non_existing_branch_error const &) {} - catch (missing_head_error const &) {} + catch (non_existing_branch_error const &) + { + } + catch (missing_head_error const &) + { + } catch (std::exception const & e) { throw e; @@ -81,49 +86,51 @@ void show_branch(Repository const & repo, int format) if (format == FORMAT_LONG) std::cout << "# On branch " << branch.value_or("Not currently on any branch."); else - std::cout<< "## ", branch.value_or("HEAD (no branch)"); + std::cout << "## ", branch.value_or("HEAD (no branch)"); std::cout << "\n"; } void print_long(Status const & status) { - size_t maxi = status.entrycount(); - int rm_in_workdir = 0; - const char *old_path, *new_path; + size_t maxi = status.entrycount(); + int rm_in_workdir = 0; + const char *old_path, *new_path; - /* print index changes */ + /* print index changes */ bool changes_in_index = false; - for (size_t i = 0; i < maxi; ++i) { + for (size_t i = 0; i < maxi; ++i) + { auto const & s = status[i]; if (s.status == GIT_STATUS_CURRENT) - continue; + continue; if (s.status & GIT_STATUS_WT_DELETED) - rm_in_workdir = 1; + rm_in_workdir = 1; - const char *istatus = nullptr; + const char * istatus = nullptr; if (s.status & GIT_STATUS_INDEX_NEW) - istatus = "new file: "; + istatus = "new file: "; if (s.status & GIT_STATUS_INDEX_MODIFIED) - istatus = "modified: "; + istatus = "modified: "; if (s.status & GIT_STATUS_INDEX_DELETED) - istatus = "deleted: "; + istatus = "deleted: "; if (s.status & GIT_STATUS_INDEX_RENAMED) - istatus = "renamed: "; + istatus = "renamed: "; if (s.status & GIT_STATUS_INDEX_TYPECHANGE) - istatus = "typechange:"; + istatus = "typechange:"; - if (!istatus) - continue; + if (!istatus) + continue; - if (!changes_in_index) { - std::cout << "# Changes to be committed:\n" - << "# (use \"git reset HEAD ...\" to unstage)\n" - << "#\n"; + if (!changes_in_index) + { + std::cout << "# Changes to be committed:\n" + << "# (use \"git reset HEAD ...\" to unstage)\n" + << "#\n"; changes_in_index = true; } @@ -132,48 +139,50 @@ void print_long(Status const & status) old_path = s.head_to_index->old_file.path; new_path = s.head_to_index->new_file.path; - if (old_path && new_path && strcmp(old_path, new_path)) - std::cout << old_path << " -> " << new_path; - else if (old_path) - std::cout << old_path; - else - std::cout << new_path; + if (old_path && new_path && strcmp(old_path, new_path)) + std::cout << old_path << " -> " << new_path; + else if (old_path) + std::cout << old_path; + else + std::cout << new_path; - std::cout << "\n"; - } + std::cout << "\n"; + } if (changes_in_index) std::cout << "#\n"; bool changed_in_workdir = false; - /* print workdir changes to tracked files */ + /* print workdir changes to tracked files */ - for (size_t i = 0; i < maxi; ++i) { + for (size_t i = 0; i < maxi; ++i) + { auto const & s = status[i]; if (s.status == GIT_STATUS_CURRENT || !s.index_to_workdir) - continue; + continue; - const char *wstatus = nullptr; + const char * wstatus = nullptr; if (s.status & GIT_STATUS_WT_MODIFIED) - wstatus = "modified: "; + wstatus = "modified: "; if (s.status & GIT_STATUS_WT_DELETED) - wstatus = "deleted: "; + wstatus = "deleted: "; if (s.status & GIT_STATUS_WT_RENAMED) - wstatus = "renamed: "; + wstatus = "renamed: "; if (s.status & GIT_STATUS_WT_TYPECHANGE) - wstatus = "typechange:"; + wstatus = "typechange:"; if (!wstatus) continue; - if (!changed_in_workdir) { - std::cout << "# Changes not staged for commit:\n" - << "# (use \"git add" << (rm_in_workdir ? "/rm" : "") << "...\" to update what will be committed)\n" - << "# (use \"git checkout -- ...\" to discard changes in working directory)\n" - << "#\n"; + if (!changed_in_workdir) + { + std::cout << "# Changes not staged for commit:\n" + << "# (use \"git add" << (rm_in_workdir ? "/rm" : "") << "...\" to update what will be committed)\n" + << "# (use \"git checkout -- ...\" to discard changes in working directory)\n" + << "#\n"; changed_in_workdir = true; } @@ -196,7 +205,7 @@ void print_long(Status const & status) /* print untracked files */ bool were_untracked_files = false; - for (size_t i = 0; i < maxi; ++i) + for (size_t i = 0; i < maxi; ++i) { auto const & s = status[i]; @@ -204,9 +213,9 @@ void print_long(Status const & status) { if (!were_untracked_files) { - std::cout << "# Untracked files:\n" - << "# (use \"git add ...\" to include in what will be committed)\n" - << "#\n"; + std::cout << "# Untracked files:\n" + << "# (use \"git add ...\" to include in what will be committed)\n" + << "#\n"; were_untracked_files = true; } @@ -217,16 +226,17 @@ void print_long(Status const & status) /* print ignored files */ bool were_ignored_files = false; - for (size_t i = 0; i < maxi; ++i) { + for (size_t i = 0; i < maxi; ++i) + { auto const & s = status[i]; - if (s.status == GIT_STATUS_IGNORED) + if (s.status == GIT_STATUS_IGNORED) { if (!were_ignored_files) { - std::cout << "# Ignored files:\n" - << "# (use \"git add -f ...\" to include in what will be committed)\n" - << "#\n"; + std::cout << "# Ignored files:\n" + << "# (use \"git add -f ...\" to include in what will be committed)\n" + << "#\n"; were_ignored_files = true; } @@ -242,52 +252,54 @@ void print_short(Repository const & repo, Status const & status) { size_t maxi = status.entrycount(); - for (size_t i = 0; i < maxi; ++i) + for (size_t i = 0; i < maxi; ++i) { auto const & s = status[i]; if (s.status == GIT_STATUS_CURRENT) continue; - const char *a = nullptr; - const char *b = nullptr; - const char *c = nullptr; + const char * a = nullptr; + const char * b = nullptr; + const char * c = nullptr; char istatus = ' '; char wstatus = ' '; - const char *extra = ""; + const char * extra = ""; if (s.status & GIT_STATUS_INDEX_NEW) - istatus = 'A'; + istatus = 'A'; if (s.status & GIT_STATUS_INDEX_MODIFIED) - istatus = 'M'; + istatus = 'M'; if (s.status & GIT_STATUS_INDEX_DELETED) - istatus = 'D'; + istatus = 'D'; if (s.status & GIT_STATUS_INDEX_RENAMED) - istatus = 'R'; + istatus = 'R'; if (s.status & GIT_STATUS_INDEX_TYPECHANGE) - istatus = 'T'; + istatus = 'T'; - if (s.status & GIT_STATUS_WT_NEW) { - if (istatus == ' ') - istatus = '?'; - wstatus = '?'; - } + if (s.status & GIT_STATUS_WT_NEW) + { + if (istatus == ' ') + istatus = '?'; + wstatus = '?'; + } if (s.status & GIT_STATUS_WT_MODIFIED) - wstatus = 'M'; + wstatus = 'M'; if (s.status & GIT_STATUS_WT_DELETED) - wstatus = 'D'; + wstatus = 'D'; if (s.status & GIT_STATUS_WT_RENAMED) - wstatus = 'R'; + wstatus = 'R'; if (s.status & GIT_STATUS_WT_TYPECHANGE) - wstatus = 'T'; + wstatus = 'T'; - if (s.status & GIT_STATUS_IGNORED) { - istatus = '!'; - wstatus = '!'; - } + if (s.status & GIT_STATUS_IGNORED) + { + istatus = '!'; + wstatus = '!'; + } - if (istatus == '?' && wstatus == '?') - continue; + if (istatus == '?' && wstatus == '?') + continue; if (s.index_to_workdir && s.index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT) { @@ -306,17 +318,19 @@ void print_short(Repository const & repo, Status const & status) extra = " (untracked content)"; } - if (s.head_to_index) { + if (s.head_to_index) + { a = s.head_to_index->old_file.path; b = s.head_to_index->new_file.path; - } - if (s.index_to_workdir) { - if (!a) + } + if (s.index_to_workdir) + { + if (!a) a = s.index_to_workdir->old_file.path; - if (!b) + if (!b) b = s.index_to_workdir->old_file.path; c = s.index_to_workdir->new_file.path; - } + } std::cout << istatus << wstatus << ' ' << a; if (istatus == 'R') @@ -335,82 +349,85 @@ void print_short(Repository const & repo, Status const & status) } } -int main(int argc, char *argv[]) +int main(int argc, char * argv[]) { - auto_git_initializer; - - int npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0; + auto_git_initializer; + + int npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0; Status::Options opt; - const char *repodir = "."; + const char * repodir = "."; const size_t MAX_PATHSPEC = 8; char * pathspec[MAX_PATHSPEC]; opt.include_untracked().renames_head_to_index(); - for (int i = 1; i < argc; ++i) { - if (argv[i][0] != '-') { - if (npaths < MAX_PATHSPEC) + for (int i = 1; i < argc; ++i) + { + if (argv[i][0] != '-') + { + if (npaths < MAX_PATHSPEC) { - pathspec[npaths++] = argv[i]; + pathspec[npaths++] = argv[i]; } - else + else { - std::cerr << "Example only supports a limited pathspec\n"; + std::cerr << "Example only supports a limited pathspec\n"; return 1; } - } - else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--short")) - format = FORMAT_SHORT; - else if (!strcmp(argv[i], "--long")) - format = FORMAT_LONG; - else if (!strcmp(argv[i], "--porcelain")) - format = FORMAT_PORCELAIN; - else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--branch")) - showbranch = 1; - else if (!strcmp(argv[i], "-z")) { - zterm = 1; - if (format == FORMAT_DEFAULT) - format = FORMAT_PORCELAIN; - } - else if (!strcmp(argv[i], "--ignored")) + } + else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--short")) + format = FORMAT_SHORT; + else if (!strcmp(argv[i], "--long")) + format = FORMAT_LONG; + else if (!strcmp(argv[i], "--porcelain")) + format = FORMAT_PORCELAIN; + else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--branch")) + showbranch = 1; + else if (!strcmp(argv[i], "-z")) + { + zterm = 1; + if (format == FORMAT_DEFAULT) + format = FORMAT_PORCELAIN; + } + else if (!strcmp(argv[i], "--ignored")) opt.include_ignored(); - else if (!strcmp(argv[i], "-uno") || - !strcmp(argv[i], "--untracked-files=no")) + else if (!strcmp(argv[i], "-uno") || + !strcmp(argv[i], "--untracked-files=no")) opt.exclude_untracked(); - else if (!strcmp(argv[i], "-unormal") || - !strcmp(argv[i], "--untracked-files=normal")) + else if (!strcmp(argv[i], "-unormal") || + !strcmp(argv[i], "--untracked-files=normal")) opt.include_untracked(); - else if (!strcmp(argv[i], "-uall") || - !strcmp(argv[i], "--untracked-files=all")) + else if (!strcmp(argv[i], "-uall") || + !strcmp(argv[i], "--untracked-files=all")) opt.include_untracked().recurse_untracked_dirs(); - else if (!strcmp(argv[i], "--ignore-submodules=all")) + else if (!strcmp(argv[i], "--ignore-submodules=all")) opt.exclude_submodules(); - else if (!strncmp(argv[i], "--git-dir=", strlen("--git-dir="))) - repodir = argv[i] + strlen("--git-dir="); - else + else if (!strncmp(argv[i], "--git-dir=", strlen("--git-dir="))) + repodir = argv[i] + strlen("--git-dir="); + else { std::cerr << "Unsupported option '" << argv[i] << "'\n"; return 1; } - } + } - if (format == FORMAT_DEFAULT) - format = FORMAT_LONG; - if (format == FORMAT_LONG) - showbranch = 1; + if (format == FORMAT_DEFAULT) + format = FORMAT_LONG; + if (format == FORMAT_LONG) + showbranch = 1; if (npaths > 0) opt.set_pathspec(pathspec, npaths); - Repository repo(repodir); + Repository repo(repodir); - if (repo.is_bare()) + if (repo.is_bare()) { - std::cerr << "Cannot report status on bare repository\n"; + std::cerr << "Cannot report status on bare repository\n"; return 1; } - /* + /* * Run status on the repository * * Because we want to simluate a full "git status" run and want to @@ -421,16 +438,15 @@ int main(int argc, char *argv[]) * enumerate files that are modified) then you probably don't need the * extended API. */ - Status status = repo.status(opt); + Status status = repo.status(opt); - if (showbranch) - show_branch(repo, format); + if (showbranch) + show_branch(repo, format); - if (format == FORMAT_LONG) - print_long(status); - else - print_short(repo, status); + if (format == FORMAT_LONG) + print_long(status); + else + print_short(repo, status); - return 0; + return 0; } - diff --git a/include/git2cpp/blob.h b/include/git2cpp/blob.h index 5d61100..61d8bd5 100644 --- a/include/git2cpp/blob.h +++ b/include/git2cpp/blob.h @@ -13,11 +13,11 @@ namespace git explicit Blob(git_blob *); ~Blob(); - std::size_t size() const; - const void * content() const; + std::size_t size() const; + const void * content() const; - Blob& operator = (Blob const &) = delete; - Blob (Blob const &) = delete; + Blob & operator=(Blob const &) = delete; + Blob(Blob const &) = delete; Blob(Blob &&) noexcept; diff --git a/include/git2cpp/buffer.h b/include/git2cpp/buffer.h index 91dc8b6..7c3f69b 100644 --- a/include/git2cpp/buffer.h +++ b/include/git2cpp/buffer.h @@ -6,8 +6,8 @@ namespace git { struct Buffer { - Buffer (Buffer const &) = delete; - Buffer& operator = (Buffer const &) = delete; + Buffer(Buffer const &) = delete; + Buffer & operator=(Buffer const &) = delete; Buffer(Buffer &&); diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 1eccfec..042a158 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -1,7 +1,7 @@ #pragma once -#include "tree.h" #include "repo_fwd.h" +#include "tree.h" #include @@ -11,47 +11,46 @@ struct git_repository; namespace git { - struct Commit - { - size_t parents_num() const; - Commit parent(size_t i) const; - git_oid const & parent_id(size_t i) const; + struct Commit + { + size_t parents_num() const; + Commit parent(size_t i) const; + git_oid const & parent_id(size_t i) const; - Tree tree() const; + Tree tree() const; - explicit operator bool () const { return commit_ != nullptr; } + explicit operator bool() const { return commit_ != nullptr; } - git_oid const & id() const; + git_oid const & id() const; - git_signature const * author() const; - git_signature const * commiter() const; + git_signature const * author() const; + git_signature const * commiter() const; - const char * message() const; - const char * summary() const; - git_time_t time() const; + const char * message() const; + const char * summary() const; + git_time_t time() const; - git_oid merge_base(size_t p1, size_t p2) const; + git_oid merge_base(size_t p1, size_t p2) const; - Repository const & repo() const { return *repo_; } + Repository const & repo() const { return *repo_; } - Commit(git_commit *, Repository const &); + Commit(git_commit *, Repository const &); - Commit(); - Commit (Commit &&) noexcept; - Commit& operator = (Commit &&) noexcept; - Commit (Commit const &) = delete; - Commit& operator = (Commit const &) = delete; + Commit(); + Commit(Commit &&) noexcept; + Commit & operator=(Commit &&) noexcept; + Commit(Commit const &) = delete; + Commit & operator=(Commit const &) = delete; - ~Commit(); + ~Commit(); - private: - friend struct Repository; + private: + friend struct Repository; - git_commit const * ptr() const { return commit_; } + git_commit const * ptr() const { return commit_; } - private: - git_commit * commit_; - Repository const * repo_; - }; + private: + git_commit * commit_; + Repository const * repo_; + }; } - diff --git a/include/git2cpp/config.h b/include/git2cpp/config.h index 59b16bd..97e6705 100644 --- a/include/git2cpp/config.h +++ b/include/git2cpp/config.h @@ -28,12 +28,12 @@ namespace git std::string key_; }; - std::string operator[] (const char * key) const; + std::string operator[](const char * key) const; int get_int(const char * key) const; - Config (Config const &) = delete; - Config& operator = (Config const &) = delete; + Config(Config const &) = delete; + Config & operator=(Config const &) = delete; private: git_config * cfg_; diff --git a/include/git2cpp/diff.h b/include/git2cpp/diff.h index 21b0ef9..e6a4e81 100644 --- a/include/git2cpp/diff.h +++ b/include/git2cpp/diff.h @@ -4,28 +4,34 @@ #include -#include "tagged_mask.h" #include "buffer.h" +#include "tagged_mask.h" namespace git { namespace diff { - namespace stats { - namespace format + namespace stats { - typedef tagged_mask_t type; - - extern const type none; - extern const type full; - extern const type _short; - extern const type number; - extern const type include_summary; - }} + namespace format + { + typedef tagged_mask_t type; + + extern const type none; + extern const type full; + extern const type _short; + extern const type number; + extern const type include_summary; + } + } enum class format { - patch, patch_header, raw, name_only, name_status + patch, + patch_header, + raw, + name_only, + name_status }; } @@ -35,8 +41,8 @@ namespace git { ~Stats(); - Stats (Stats const &) = delete; - Stats& operator = (Stats const &) = delete; + Stats(Stats const &) = delete; + Stats & operator=(Stats const &) = delete; Stats(Stats &&) noexcept; @@ -59,8 +65,7 @@ namespace git Stats stats() const; - typedef - std::function + typedef std::function print_callback_t; void print(diff::format, print_callback_t print_callback) const; @@ -71,8 +76,8 @@ namespace git ~Diff(); - Diff (Diff const &) = delete; - Diff& operator = (Diff const &) = delete; + Diff(Diff const &) = delete; + Diff & operator=(Diff const &) = delete; Diff(Diff && other) noexcept : diff_(other.diff_) @@ -84,4 +89,3 @@ namespace git git_diff * diff_; }; } - diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 93afda1..696c9ff 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -8,198 +8,222 @@ namespace git { - struct error_t : std::runtime_error - { - explicit error_t(std::string const & message) : std::runtime_error(message) {} - }; - - struct repository_open_error : error_t - { - repository_open_error(std::string const & dir) - : error_t("Could not open repository on path " + dir) - {} - }; - - struct repository_init_error : error_t - { - explicit repository_init_error(std::string const & dir) - : error_t("Could not initialize repository on path " + dir) - {} - }; - - struct index_open_error : error_t - { - index_open_error() : error_t("Could not open repository index") {} - }; - - struct odb_open_error : error_t - { - odb_open_error() : error_t("Could not open ODB") {} - }; - - struct commit_lookup_error : error_t - { - explicit commit_lookup_error(git_oid const & id) - : error_t("Could not lookup commit " + id_to_str(id)) - {} - }; - - struct tree_lookup_error : error_t - { - explicit tree_lookup_error(git_oid const & id) - : error_t("Could not lookup tree " + id_to_str(id)) - {} - }; - - struct tag_lookup_error : error_t - { - explicit tag_lookup_error(git_oid const & id) - : error_t("Could not lookup tag " + id_to_str(id)) - {} - }; - - struct blob_lookup_error : error_t - { - explicit blob_lookup_error(git_oid const & id) - : error_t("Could not lookup blob " + id_to_str(id)) - {} - }; - - struct submodule_lookup_error : error_t - { - explicit submodule_lookup_error(std::string const & name) - : error_t("Counld not lookup submodule " + name) - {} - }; - - struct remote_lookup_error : error_t - { - explicit remote_lookup_error(std::string const & name) - : error_t("Could not lookup remote " + name) - {} - }; - - struct commit_parent_error : error_t - { - explicit commit_parent_error(git_oid const & id) - : error_t("Could not get parent for commit " + id_to_str(id)) - {} - }; - - struct commit_tree_error : error_t - { - explicit commit_tree_error(git_oid const & id) - : error_t("Could not get tree for commit " + id_to_str(id)) - {} - }; - - struct revparse_error : error_t - { - explicit revparse_error(const char * spec) - : error_t(internal::format("Could not resolve %s", spec)) - {} - }; - - struct odb_read_error : error_t - { - explicit odb_read_error(git_oid const & id) - : error_t("Could not find obj " + id_to_str(id)) - {} - }; - - struct odb_write_error : error_t - { - odb_write_error() : error_t("odb write error") {} - }; - - struct file_not_found_error : error_t - { - explicit file_not_found_error(const char * filepath) - : error_t(internal::format("file path \"%s\" not found", filepath)) - {} - }; - - struct ambiguous_path_error : error_t - { - explicit ambiguous_path_error(const char * filepath) - : error_t(internal::format("file path \"%s\" is ambiguous", filepath)) - {} - }; - - struct unknown_file_status_error : error_t - { - explicit unknown_file_status_error(const char * filepath) - : error_t(internal::format("unknown error during getting status for file \"%s\"", filepath)) - {} - }; - - struct pathspec_new_error : error_t - { - pathspec_new_error() : error_t("Could not build pathspec") {} - }; - - struct revwalk_new_error : error_t - { - revwalk_new_error() : error_t("Could not create revision walker") {} - }; - - struct invalid_head_error : error_t - { - invalid_head_error() : error_t("Could not find repository HEAD") {} - }; - - struct non_commit_object_error : error_t - { - explicit non_commit_object_error(git_oid const & id) - : error_t(internal::format("object %s is not a commit", id_to_str(id))) - {} - }; - - struct unknown_get_current_branch_error : error_t - { - unknown_get_current_branch_error() : error_t("failed to get current branch") {} - }; - - struct get_status_error : error_t - { - get_status_error() : error_t("Could not get status") {} - }; - - struct signature_create_error : error_t - { - signature_create_error() - : error_t("Unable to create a commit signature." - " Perhaps 'user.name' and 'user.email' are not set") - {} - }; - - struct index_write_tree_error : error_t - { - index_write_tree_error() : error_t("Unable to write tree from index") {} - }; - - struct index_write_error : error_t - { - index_write_error() : error_t("Unable to write index") {} - }; - - struct commit_create_error : error_t - { - commit_create_error() : error_t("Could not create commit") {} - }; - - struct merge_base_error : error_t - { + struct error_t : std::runtime_error + { + explicit error_t(std::string const & message) + : std::runtime_error(message) + {} + }; + + struct repository_open_error : error_t + { + repository_open_error(std::string const & dir) + : error_t("Could not open repository on path " + dir) + {} + }; + + struct repository_init_error : error_t + { + explicit repository_init_error(std::string const & dir) + : error_t("Could not initialize repository on path " + dir) + {} + }; + + struct index_open_error : error_t + { + index_open_error() + : error_t("Could not open repository index") + {} + }; + + struct odb_open_error : error_t + { + odb_open_error() + : error_t("Could not open ODB") + {} + }; + + struct commit_lookup_error : error_t + { + explicit commit_lookup_error(git_oid const & id) + : error_t("Could not lookup commit " + id_to_str(id)) + {} + }; + + struct tree_lookup_error : error_t + { + explicit tree_lookup_error(git_oid const & id) + : error_t("Could not lookup tree " + id_to_str(id)) + {} + }; + + struct tag_lookup_error : error_t + { + explicit tag_lookup_error(git_oid const & id) + : error_t("Could not lookup tag " + id_to_str(id)) + {} + }; + + struct blob_lookup_error : error_t + { + explicit blob_lookup_error(git_oid const & id) + : error_t("Could not lookup blob " + id_to_str(id)) + {} + }; + + struct submodule_lookup_error : error_t + { + explicit submodule_lookup_error(std::string const & name) + : error_t("Counld not lookup submodule " + name) + {} + }; + + struct remote_lookup_error : error_t + { + explicit remote_lookup_error(std::string const & name) + : error_t("Could not lookup remote " + name) + {} + }; + + struct commit_parent_error : error_t + { + explicit commit_parent_error(git_oid const & id) + : error_t("Could not get parent for commit " + id_to_str(id)) + {} + }; + + struct commit_tree_error : error_t + { + explicit commit_tree_error(git_oid const & id) + : error_t("Could not get tree for commit " + id_to_str(id)) + {} + }; + + struct revparse_error : error_t + { + explicit revparse_error(const char * spec) + : error_t(internal::format("Could not resolve %s", spec)) + {} + }; + + struct odb_read_error : error_t + { + explicit odb_read_error(git_oid const & id) + : error_t("Could not find obj " + id_to_str(id)) + {} + }; + + struct odb_write_error : error_t + { + odb_write_error() + : error_t("odb write error") + {} + }; + + struct file_not_found_error : error_t + { + explicit file_not_found_error(const char * filepath) + : error_t(internal::format("file path \"%s\" not found", filepath)) + {} + }; + + struct ambiguous_path_error : error_t + { + explicit ambiguous_path_error(const char * filepath) + : error_t(internal::format("file path \"%s\" is ambiguous", filepath)) + {} + }; + + struct unknown_file_status_error : error_t + { + explicit unknown_file_status_error(const char * filepath) + : error_t(internal::format("unknown error during getting status for file \"%s\"", filepath)) + {} + }; + + struct pathspec_new_error : error_t + { + pathspec_new_error() + : error_t("Could not build pathspec") + {} + }; + + struct revwalk_new_error : error_t + { + revwalk_new_error() + : error_t("Could not create revision walker") + {} + }; + + struct invalid_head_error : error_t + { + invalid_head_error() + : error_t("Could not find repository HEAD") + {} + }; + + struct non_commit_object_error : error_t + { + explicit non_commit_object_error(git_oid const & id) + : error_t(internal::format("object %s is not a commit", id_to_str(id))) + {} + }; + + struct unknown_get_current_branch_error : error_t + { + unknown_get_current_branch_error() + : error_t("failed to get current branch") + {} + }; + + struct get_status_error : error_t + { + get_status_error() + : error_t("Could not get status") + {} + }; + + struct signature_create_error : error_t + { + signature_create_error() + : error_t("Unable to create a commit signature." + " Perhaps 'user.name' and 'user.email' are not set") + {} + }; + + struct index_write_tree_error : error_t + { + index_write_tree_error() + : error_t("Unable to write tree from index") + {} + }; + + struct index_write_error : error_t + { + index_write_error() + : error_t("Unable to write index") + {} + }; + + struct commit_create_error : error_t + { + commit_create_error() + : error_t("Could not create commit") + {} + }; + + struct merge_base_error : error_t + { merge_base_error(git_oid const & c1, git_oid const & c2) - : error_t(internal::format( - "Could not find merge base for commits %s and %s", id_to_str(c1, 8), id_to_str(c2, 8) - )) + : error_t(internal::format( + "Could not find merge base for commits %s and %s", id_to_str(c1, 8), id_to_str(c2, 8))) {} - }; + }; - struct config_open_error : error_t - { - config_open_error() : error_t("Could not open config") {} - }; + struct config_open_error : error_t + { + config_open_error() + : error_t("Could not open config") + {} + }; } - diff --git a/include/git2cpp/index.h b/include/git2cpp/index.h index 7a315bf..8bee61b 100644 --- a/include/git2cpp/index.h +++ b/include/git2cpp/index.h @@ -19,12 +19,12 @@ namespace git ~Index(); size_t entrycount() const; - git_index_entry const * operator[] (size_t i) const; + git_index_entry const * operator[](size_t i) const; - typedef std::function matched_path_callback_t; - - void update_all (git_strarray const & pathspec, matched_path_callback_t cb); - void add_all (git_strarray const & pathspec, matched_path_callback_t cb, unsigned int flags = 0); + typedef std::function matched_path_callback_t; + + void update_all(git_strarray const & pathspec, matched_path_callback_t cb); + void add_all(git_strarray const & pathspec, matched_path_callback_t cb, unsigned int flags = 0); void clear(); void add_path(const char *); @@ -37,11 +37,11 @@ namespace git void write() const; - Index (Index const &) = delete; - Index& operator = (Index const &) = delete; + Index(Index const &) = delete; + Index & operator=(Index const &) = delete; - Index (Index &&) noexcept; - Index& operator = (Index &&) noexcept; + Index(Index &&) noexcept; + Index & operator=(Index &&) noexcept; private: git_index * index_; diff --git a/include/git2cpp/initializer.h b/include/git2cpp/initializer.h index 5ffdcd1..86a9f2f 100644 --- a/include/git2cpp/initializer.h +++ b/include/git2cpp/initializer.h @@ -7,9 +7,11 @@ namespace git Initializer(); ~Initializer(); - Initializer (Initializer const &) = delete; - Initializer& operator = (Initializer const &) = delete; + Initializer(Initializer const &) = delete; + Initializer & operator=(Initializer const &) = delete; }; } -#define auto_git_initializer ::git::Initializer git_initializer; (void) git_initializer +#define auto_git_initializer \ + ::git::Initializer git_initializer; \ + (void)git_initializer diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index 6b8b6c6..47d071d 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -1,7 +1,7 @@ #pragma once -#include "commit.h" #include "blob.h" +#include "commit.h" #include @@ -12,37 +12,36 @@ struct git_tag; namespace git { - struct Repository; + struct Repository; - struct Object - { - Object() {} + struct Object + { + Object() {} - Object(git_object * obj, Repository const &); - ~Object(); + Object(git_object * obj, Repository const &); + ~Object(); - explicit operator bool() const { return obj_ != nullptr; } + explicit operator bool() const { return obj_ != nullptr; } - git_otype type() const; - git_oid const & id() const; + git_otype type() const; + git_oid const & id() const; - git_blob const * as_blob() const; - git_commit const * as_commit() const; - git_tree const * as_tree() const; - git_tag const * as_tag() const; + git_blob const * as_blob() const; + git_commit const * as_commit() const; + git_tree const * as_tree() const; + git_tag const * as_tag() const; - Commit to_commit() /*&&*/; - Tree to_tree() /*&&*/; - Blob to_blob() /*&&*/; + Commit to_commit() /*&&*/; + Tree to_tree() /*&&*/; + Blob to_blob() /*&&*/; - Object (Object const &) = delete; - Object& operator = (Object const &) = delete; + Object(Object const &) = delete; + Object & operator=(Object const &) = delete; - Object(Object && other) noexcept; + Object(Object && other) noexcept; - private: - git_object * obj_ = nullptr; - Repository const * repo_ = nullptr; - }; + private: + git_object * obj_ = nullptr; + Repository const * repo_ = nullptr; + }; } - diff --git a/include/git2cpp/odb.h b/include/git2cpp/odb.h index b6b58e4..a427bff 100644 --- a/include/git2cpp/odb.h +++ b/include/git2cpp/odb.h @@ -2,10 +2,7 @@ #include "odb_object.h" -extern "C" -{ #include -} struct git_odb; @@ -16,11 +13,11 @@ namespace git explicit Odb(git_repository * repo); ~Odb(); - OdbObject read(git_oid const & oid) const; - git_oid write(const void * data, size_t len, git_otype type); + OdbObject read(git_oid const & oid) const; + git_oid write(const void * data, size_t len, git_otype type); - Odb (Odb const &) = delete; - Odb& operator = (Odb const &) = delete; + Odb(Odb const &) = delete; + Odb & operator=(Odb const &) = delete; Odb(Odb && other); @@ -28,4 +25,3 @@ namespace git git_odb * odb_; }; } - diff --git a/include/git2cpp/odb_object.h b/include/git2cpp/odb_object.h index 1e45abf..5eee662 100644 --- a/include/git2cpp/odb_object.h +++ b/include/git2cpp/odb_object.h @@ -2,8 +2,7 @@ #include -extern "C" -{ +extern "C" { #include } @@ -17,12 +16,12 @@ namespace git ~OdbObject(); - git_otype type() const; - unsigned char const * data() const; - size_t size() const; + git_otype type() const; + unsigned char const * data() const; + size_t size() const; - OdbObject (OdbObject const &) = delete; - OdbObject& operator = (OdbObject const &) = delete; + OdbObject(OdbObject const &) = delete; + OdbObject & operator=(OdbObject const &) = delete; OdbObject(OdbObject && other); @@ -30,4 +29,3 @@ namespace git git_odb_object * obj_; }; } - diff --git a/include/git2cpp/pathspec.h b/include/git2cpp/pathspec.h index ada9b05..56a5336 100644 --- a/include/git2cpp/pathspec.h +++ b/include/git2cpp/pathspec.h @@ -21,10 +21,10 @@ namespace git git_pathspec_free(ps_); } - Pathspec (Pathspec const &) = delete; - Pathspec& operator = (Pathspec const &) = delete; + Pathspec(Pathspec const &) = delete; + Pathspec & operator=(Pathspec const &) = delete; private: - git_pathspec * ps_; + git_pathspec * ps_; }; } diff --git a/include/git2cpp/reference.h b/include/git2cpp/reference.h index 4d77056..bd09360 100644 --- a/include/git2cpp/reference.h +++ b/include/git2cpp/reference.h @@ -18,19 +18,18 @@ namespace git explicit operator bool() const { return ref_ != nullptr; } - const char * name() const; - git_ref_t type() const; - git_oid const & target() const; - const char * symbolic_target() const; + const char * name() const; + git_ref_t type() const; + git_oid const & target() const; + const char * symbolic_target() const; - Reference& operator = (Reference const &) = delete; - Reference (Reference const &) = delete; + Reference & operator=(Reference const &) = delete; + Reference(Reference const &) = delete; Reference(Reference &&) noexcept; - Reference& operator =(Reference && other) noexcept; + Reference & operator=(Reference && other) noexcept; private: git_reference * ref_; }; } - diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index c7c8c58..b96ea44 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -2,32 +2,36 @@ #include "repo_fwd.h" +#include "blob.h" #include "commit.h" +#include "diff.h" #include "index.h" #include "odb.h" -#include "revspec.h" -#include "status.h" #include "reference.h" -#include "signature.h" +#include "remote.h" +#include "revspec.h" #include "revwalker.h" -#include "tag.h" -#include "blob.h" +#include "signature.h" +#include "status.h" #include "str_array.h" -#include "diff.h" #include "submodule.h" -#include "remote.h" +#include "tag.h" #include #include namespace git { - struct non_existing_branch_error {}; - struct missing_head_error {}; + struct non_existing_branch_error + {}; + struct missing_head_error + {}; enum class branch_type { - LOCAL, REMOTE, ALL + LOCAL, + REMOTE, + ALL }; struct FileDiffHandler @@ -41,31 +45,31 @@ namespace git struct Repository { Commit commit_lookup(git_oid const & oid) const; - Tree tree_lookup (git_oid const & oid) const; - Tag tag_lookup (git_oid const & oid) const; - Blob blob_lookup (git_oid const & oid) const; + Tree tree_lookup(git_oid const & oid) const; + Tag tag_lookup(git_oid const & oid) const; + Blob blob_lookup(git_oid const & oid) const; - git_oid merge_base(Revspec::Range const & range) const; - git_oid merge_base(git_oid const &, git_oid const &) const; + git_oid merge_base(Revspec::Range const & range) const; + git_oid merge_base(git_oid const &, git_oid const &) const; - Revspec revparse (const char * spec) const; - Revspec revparse_single (const char * spec) const; + Revspec revparse(const char * spec) const; + Revspec revparse_single(const char * spec) const; RevWalker rev_walker() const; git_status_t file_status(const char * filepath) const; - Object entry_to_object(Tree::OwnedEntry) const; + Object entry_to_object(Tree::OwnedEntry) const; Object entry_to_object(Tree::BorrowedEntry) const; - Index index() const; - Odb odb() const; + Index index() const; + Odb odb() const; - Diff diff (Tree &, Tree &, git_diff_options const &) const; - Diff diff_to_index (Tree &, git_diff_options const &) const; - Diff diff_to_workdir (Tree &, git_diff_options const &) const; - Diff diff_to_workdir_with_index (Tree &, git_diff_options const &) const; - Diff diff_index_to_workdir ( git_diff_options const &) const; + Diff diff(Tree &, Tree &, git_diff_options const &) const; + Diff diff_to_index(Tree &, git_diff_options const &) const; + Diff diff_to_workdir(Tree &, git_diff_options const &) const; + Diff diff_to_workdir_with_index(Tree &, git_diff_options const &) const; + Diff diff_index_to_workdir(git_diff_options const &) const; Signature signature() const; @@ -77,13 +81,13 @@ namespace git bool is_bare() const; - Reference head() const; - Reference ref(const char * name) const; + Reference head() const; + Reference ref(const char * name) const; Submodule submodule_lookup(const char * name) const; - - const char * path() const; - const char * workdir() const; + + const char * path() const; + const char * workdir() const; git_oid create_commit(const char * update_ref, Signature const & author, @@ -105,23 +109,24 @@ namespace git void file_diff(std::string const & old_path, git_oid const & old_id, std::string const & new_path, git_oid const & new_id, FileDiffHandler &) const; - StrArray remotes() const; - Remote remote(const char * name) const; + StrArray remotes() const; + Remote remote(const char * name) const; explicit Repository(const char * dir); explicit Repository(std::string const & dir); - struct init_tag {}; + struct init_tag + {}; static const init_tag init; Repository(const char * dir, init_tag); Repository(const char * dir, init_tag, git_repository_init_options opts); Repository(std::string const & dir, init_tag); - Repository (Repository const &) = delete; - Repository& operator = (Repository const &) = delete; + Repository(Repository const &) = delete; + Repository & operator=(Repository const &) = delete; - Repository (Repository &&) noexcept; - Repository& operator = (Repository &&) noexcept; + Repository(Repository &&) noexcept; + Repository & operator=(Repository &&) noexcept; ~Repository(); @@ -131,4 +136,3 @@ namespace git Object revparse_single(Repository const & repo, const char * spec); } - diff --git a/include/git2cpp/revspec.h b/include/git2cpp/revspec.h index 245341b..0fbfd81 100644 --- a/include/git2cpp/revspec.h +++ b/include/git2cpp/revspec.h @@ -2,43 +2,42 @@ #include "object.h" -extern "C" -{ +extern "C" { #include } namespace git { - struct Repository; + struct Repository; - struct Revspec - { - struct Range - { - Object from, to; + struct Revspec + { + struct Range + { + Object from, to; - Range(git_object * single, Repository const & repo) - : from(single, repo) - {} + Range(git_object * single, Repository const & repo) + : from(single, repo) + {} - explicit Range(git_revspec const & revspec, Repository const & repo) - : from (revspec.from, repo) - , to (revspec.to, repo) - {} - }; + explicit Range(git_revspec const & revspec, Repository const & repo) + : from(revspec.from, repo) + , to(revspec.to, repo) + {} + }; - Object const * single() const; - Range const * range() const; + Object const * single() const; + Range const * range() const; - Object * single(); + Object * single(); - unsigned int flags() const; + unsigned int flags() const; - Revspec(git_object * single, Repository const &); - Revspec(git_revspec const &, Repository const &); + Revspec(git_object * single, Repository const &); + Revspec(git_revspec const &, Repository const &); - private: - unsigned int flags_ = 0; - Range revspec_; - }; + private: + unsigned int flags_ = 0; + Range revspec_; + }; } diff --git a/include/git2cpp/revwalker.h b/include/git2cpp/revwalker.h index fe783f4..7ed2240 100644 --- a/include/git2cpp/revwalker.h +++ b/include/git2cpp/revwalker.h @@ -1,22 +1,24 @@ #pragma once -#include "tagged_mask.h" #include "commit.h" +#include "tagged_mask.h" namespace git { struct Repository; - namespace revwalker { - namespace sorting + namespace revwalker { - typedef tagged_mask_t type; + namespace sorting + { + typedef tagged_mask_t type; - extern const type none; - extern const type topological; - extern const type time; - extern const type reverse; - }} + extern const type none; + extern const type topological; + extern const type time; + extern const type reverse; + } + } struct RevWalker { @@ -34,11 +36,11 @@ namespace git void hide(git_oid const &) const; void push(git_oid const &) const; - Commit next() const; - bool next(char * id_buffer) const; + Commit next() const; + bool next(char * id_buffer) const; - RevWalker (RevWalker const &) = delete; - RevWalker& operator = (RevWalker const &) = delete; + RevWalker(RevWalker const &) = delete; + RevWalker & operator=(RevWalker const &) = delete; RevWalker(RevWalker && other) : walker_(other.walker_) @@ -47,10 +49,10 @@ namespace git other.walker_ = nullptr; } - RevWalker& operator = (RevWalker && other) + RevWalker & operator=(RevWalker && other) { walker_ = other.walker_; - repo_ = other.repo_; + repo_ = other.repo_; other.walker_ = nullptr; return *this; } diff --git a/include/git2cpp/signature.h b/include/git2cpp/signature.h index 743322d..4992cac 100644 --- a/include/git2cpp/signature.h +++ b/include/git2cpp/signature.h @@ -18,4 +18,3 @@ namespace git git_signature * sig_; }; } - diff --git a/include/git2cpp/status.h b/include/git2cpp/status.h index 4815c3d..d5c4a39 100644 --- a/include/git2cpp/status.h +++ b/include/git2cpp/status.h @@ -1,8 +1,8 @@ #pragma once -#include #include #include +#include namespace git { @@ -25,12 +25,12 @@ namespace git Options(Show = Show::IndexAndWorkdir, Sort = Sort::CaseSensitively); - Options& include_untracked(); - Options& exclude_untracked(); - Options& renames_head_to_index(); - Options& include_ignored(); - Options& recurse_untracked_dirs(); - Options& exclude_submodules(); + Options & include_untracked(); + Options & exclude_untracked(); + Options & renames_head_to_index(); + Options & include_ignored(); + Options & recurse_untracked_dirs(); + Options & exclude_submodules(); void set_pathspec(char ** ptr, size_t size); @@ -44,16 +44,15 @@ namespace git ~Status(); size_t entrycount() const; - git_status_entry const & operator[] (size_t i) const; + git_status_entry const & operator[](size_t i) const; - Status (Status const &) = delete; - Status& operator = (Status const &) = delete; + Status(Status const &) = delete; + Status & operator=(Status const &) = delete; - Status (Status &&) noexcept; - Status& operator = (Status &&) noexcept; + Status(Status &&) noexcept; + Status & operator=(Status &&) noexcept; private: git_status_list * status_; }; } - diff --git a/include/git2cpp/str_array.h b/include/git2cpp/str_array.h index 743ce20..fd37a2f 100644 --- a/include/git2cpp/str_array.h +++ b/include/git2cpp/str_array.h @@ -12,7 +12,7 @@ namespace git size_t count() const { return str_array_.count; } - const char * operator [] (size_t i) const + const char * operator[](size_t i) const { return str_array_.strings[i]; } diff --git a/include/git2cpp/submodule.h b/include/git2cpp/submodule.h index f79536b..e801409 100644 --- a/include/git2cpp/submodule.h +++ b/include/git2cpp/submodule.h @@ -12,31 +12,31 @@ namespace git Submodule(git_submodule *, git_repository *); ~Submodule(); - Submodule (Submodule const &) = delete; - Submodule& operator = (Submodule const &) = delete; + Submodule(Submodule const &) = delete; + Submodule & operator=(Submodule const &) = delete; - Submodule (Submodule &&); - Submodule& operator = (Submodule &&); + Submodule(Submodule &&); + Submodule & operator=(Submodule &&); enum class status : unsigned int { - in_head = GIT_SUBMODULE_STATUS_IN_HEAD, - in_index = GIT_SUBMODULE_STATUS_IN_INDEX, - in_config = GIT_SUBMODULE_STATUS_IN_CONFIG, - in_wd = GIT_SUBMODULE_STATUS_IN_WD, - index_added = GIT_SUBMODULE_STATUS_INDEX_ADDED, - index_deleted = GIT_SUBMODULE_STATUS_INDEX_DELETED, - index_modified = GIT_SUBMODULE_STATUS_INDEX_MODIFIED, - wd_uninitialized = GIT_SUBMODULE_STATUS_WD_UNINITIALIZED, - wd_added = GIT_SUBMODULE_STATUS_WD_ADDED, - wd_deleted = GIT_SUBMODULE_STATUS_WD_DELETED, - wd_modified = GIT_SUBMODULE_STATUS_WD_MODIFIED, - wd_index_modified = GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED, - wd_wd_modified = GIT_SUBMODULE_STATUS_WD_WD_MODIFIED, - wd_untracked = GIT_SUBMODULE_STATUS_WD_UNTRACKED, + in_head = GIT_SUBMODULE_STATUS_IN_HEAD, + in_index = GIT_SUBMODULE_STATUS_IN_INDEX, + in_config = GIT_SUBMODULE_STATUS_IN_CONFIG, + in_wd = GIT_SUBMODULE_STATUS_IN_WD, + index_added = GIT_SUBMODULE_STATUS_INDEX_ADDED, + index_deleted = GIT_SUBMODULE_STATUS_INDEX_DELETED, + index_modified = GIT_SUBMODULE_STATUS_INDEX_MODIFIED, + wd_uninitialized = GIT_SUBMODULE_STATUS_WD_UNINITIALIZED, + wd_added = GIT_SUBMODULE_STATUS_WD_ADDED, + wd_deleted = GIT_SUBMODULE_STATUS_WD_DELETED, + wd_modified = GIT_SUBMODULE_STATUS_WD_MODIFIED, + wd_index_modified = GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED, + wd_wd_modified = GIT_SUBMODULE_STATUS_WD_WD_MODIFIED, + wd_untracked = GIT_SUBMODULE_STATUS_WD_UNTRACKED, }; - friend bool contains (status set, status element); + friend bool contains(status set, status element); status get_status() const; diff --git a/include/git2cpp/tag.h b/include/git2cpp/tag.h index def4dd2..26d9c9d 100644 --- a/include/git2cpp/tag.h +++ b/include/git2cpp/tag.h @@ -6,23 +6,23 @@ struct git_tag; namespace git { - struct Tag - { - Tag(git_tag *, Repository const &); - ~Tag(); + struct Tag + { + Tag(git_tag *, Repository const &); + ~Tag(); - Tag& operator = (Tag const &) = delete; - Tag (Tag const &) = delete; + Tag & operator=(Tag const &) = delete; + Tag(Tag const &) = delete; - Tag(Tag &&); + Tag(Tag &&); - Object target() const; - git_otype target_type() const; - const char * name() const; - const char * message() const; + Object target() const; + git_otype target_type() const; + const char * name() const; + const char * message() const; - private: - git_tag * tag_; - Repository const & repo_; - }; + private: + git_tag * tag_; + Repository const & repo_; + }; } diff --git a/include/git2cpp/tagged_mask.h b/include/git2cpp/tagged_mask.h index 1be5616..80082ca 100644 --- a/include/git2cpp/tagged_mask.h +++ b/include/git2cpp/tagged_mask.h @@ -2,7 +2,7 @@ namespace git { - template + template struct tagged_mask_t { typedef tagged_mask_t self_t; @@ -15,16 +15,20 @@ namespace git explicit operator bool() const { return value_; } - self_t& operator |= (self_t other) { value_ |= other.value_; return *this; } + self_t & operator|=(self_t other) + { + value_ |= other.value_; + return *this; + } - friend self_t operator ~ (self_t x) { return self_t(~x.value_); } + friend self_t operator~(self_t x) { return self_t(~x.value_); } - friend self_t operator | (self_t x, self_t y) { return self_t(x.value_ | y.value_); } - friend self_t operator & (self_t x, self_t y) { return self_t(x.value_ & y.value_); } - friend self_t operator ^ (self_t x, self_t y) { return self_t(x.value_ ^ y.value_); } + friend self_t operator|(self_t x, self_t y) { return self_t(x.value_ | y.value_); } + friend self_t operator&(self_t x, self_t y) { return self_t(x.value_ & y.value_); } + friend self_t operator^(self_t x, self_t y) { return self_t(x.value_ ^ y.value_); } - friend bool operator == (self_t x, self_t y) { return x.value_ == y.value_; } - friend bool operator != (self_t x, self_t y) { return x.value_ != y.value_; } + friend bool operator==(self_t x, self_t y) { return x.value_ == y.value_; } + friend bool operator!=(self_t x, self_t y) { return x.value_ != y.value_; } private: RawType value_; diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index f569397..21285f7 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -10,34 +10,34 @@ namespace git { struct BorrowedEntry { - const char * name() const; - git_oid const & id() const; + const char * name() const; + git_oid const & id() const; private: - friend struct Tree; - friend struct Repository; + friend struct Tree; + friend struct Repository; - explicit BorrowedEntry(git_tree_entry const * entry) - : entry_(entry) - {} + explicit BorrowedEntry(git_tree_entry const * entry) + : entry_(entry) + {} - git_tree_entry const * ptr() const { return entry_; } + git_tree_entry const * ptr() const { return entry_; } private: - git_tree_entry const * entry_; + git_tree_entry const * entry_; }; struct OwnedEntry { - ~OwnedEntry(); + ~OwnedEntry(); - OwnedEntry (OwnedEntry const &) = delete; - OwnedEntry& operator = (OwnedEntry const &) = delete; + OwnedEntry(OwnedEntry const &) = delete; + OwnedEntry & operator=(OwnedEntry const &) = delete; - OwnedEntry (OwnedEntry &&); - OwnedEntry& operator = (OwnedEntry &&); + OwnedEntry(OwnedEntry &&); + OwnedEntry & operator=(OwnedEntry &&); - Tree to_tree() /*&&*/; + Tree to_tree() /*&&*/; private: friend struct Tree; @@ -52,16 +52,16 @@ namespace git Repository const * repo_; }; - git_tree const * ptr() const { return tree_; } - git_tree * ptr() { return tree_; } + git_tree const * ptr() const { return tree_; } + git_tree * ptr() { return tree_; } int pathspec_match(uint32_t flags, Pathspec const & ps); size_t entrycount() const; - BorrowedEntry operator[] (size_t) const; + BorrowedEntry operator[](size_t) const; - BorrowedEntry operator[] (std::string const & filename) const; + BorrowedEntry operator[](std::string const & filename) const; OwnedEntry find(const char * path) const; @@ -70,11 +70,11 @@ namespace git Tree(); ~Tree(); - Tree (Tree &&); - Tree& operator =(Tree &&); + Tree(Tree &&); + Tree & operator=(Tree &&); - Tree (Tree const &) = delete; - Tree& operator =(Tree const &) = delete; + Tree(Tree const &) = delete; + Tree & operator=(Tree const &) = delete; explicit operator bool() const { return tree_ != nullptr; } @@ -83,4 +83,3 @@ namespace git Repository const * repo_; }; } - diff --git a/src/blob.cpp b/src/blob.cpp index ac7fda8..38c799b 100644 --- a/src/blob.cpp +++ b/src/blob.cpp @@ -5,13 +5,14 @@ namespace git { Blob::Blob(git_blob * blob) - : blob_(blob) - {} + : blob_(blob) + { + } Blob::Blob(Blob && other) noexcept : blob_(other.blob_) { - other.blob_ = nullptr; + other.blob_ = nullptr; } Blob::~Blob() diff --git a/src/commit.cpp b/src/commit.cpp index 0167bae..58b7fcc 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -1,6 +1,6 @@ #include "git2cpp/commit.h" -#include "git2cpp/repo.h" #include "git2cpp/error.h" +#include "git2cpp/repo.h" #include #include @@ -9,88 +9,91 @@ namespace git { - Commit::Commit(git_commit * commit, Repository const & repo) - : commit_(commit) - , repo_(&repo) - {} - - Commit::Commit() - : commit_(nullptr) - , repo_(nullptr) - {} - - Commit::Commit(Commit && other) noexcept - : commit_(std::exchange(other.commit_, nullptr)) - , repo_(other.repo_) - {} - - Commit& Commit::operator = (Commit && other) noexcept - { - std::swap(commit_, other.commit_); - std::swap(repo_, other.repo_); - return *this; - } - - Commit Commit::parent(size_t i) const - { - git_commit * parent; - if (git_commit_parent(&parent, commit_, static_cast(i))) - throw commit_parent_error(id()); - return Commit(parent, *repo_); - } - - Tree Commit::tree() const - { - git_tree * tree; - if (git_commit_tree(&tree, commit_)) - throw commit_tree_error(id()); - return Tree(tree, *repo_); - } - - size_t Commit::parents_num() const - { - return git_commit_parentcount(commit_); - } - - git_oid const & Commit::id() const - { - return *git_commit_id(commit_); - } - - git_oid const & Commit::parent_id(size_t i) const - { - return *git_commit_parent_id(commit_, static_cast(i)); - } - - git_signature const * Commit::author() const - { - return git_commit_author(commit_); - } - - git_signature const * Commit::commiter() const - { - return git_commit_committer(commit_); - } - - const char * Commit::message() const - { - return git_commit_message(commit_); - } - - const char * Commit::summary() const - { - return git_commit_summary(commit_); - } - - git_time_t Commit::time() const - { - return git_commit_time(commit_); - } - - git_oid Commit::merge_base(size_t p1, size_t p2) const - { - return repo_->merge_base(parent_id(p1), parent_id(p2)); - } - - Commit::~Commit() { git_commit_free(commit_); } + Commit::Commit(git_commit * commit, Repository const & repo) + : commit_(commit) + , repo_(&repo) + { + } + + Commit::Commit() + : commit_(nullptr) + , repo_(nullptr) + { + } + + Commit::Commit(Commit && other) noexcept + : commit_(std::exchange(other.commit_, nullptr)) + , repo_(other.repo_) + { + } + + Commit & Commit::operator=(Commit && other) noexcept + { + std::swap(commit_, other.commit_); + std::swap(repo_, other.repo_); + return *this; + } + + Commit Commit::parent(size_t i) const + { + git_commit * parent; + if (git_commit_parent(&parent, commit_, static_cast(i))) + throw commit_parent_error(id()); + return Commit(parent, *repo_); + } + + Tree Commit::tree() const + { + git_tree * tree; + if (git_commit_tree(&tree, commit_)) + throw commit_tree_error(id()); + return Tree(tree, *repo_); + } + + size_t Commit::parents_num() const + { + return git_commit_parentcount(commit_); + } + + git_oid const & Commit::id() const + { + return *git_commit_id(commit_); + } + + git_oid const & Commit::parent_id(size_t i) const + { + return *git_commit_parent_id(commit_, static_cast(i)); + } + + git_signature const * Commit::author() const + { + return git_commit_author(commit_); + } + + git_signature const * Commit::commiter() const + { + return git_commit_committer(commit_); + } + + const char * Commit::message() const + { + return git_commit_message(commit_); + } + + const char * Commit::summary() const + { + return git_commit_summary(commit_); + } + + git_time_t Commit::time() const + { + return git_commit_time(commit_); + } + + git_oid Commit::merge_base(size_t p1, size_t p2) const + { + return repo_->merge_base(parent_id(p1), parent_id(p2)); + } + + Commit::~Commit() { git_commit_free(commit_); } } diff --git a/src/config.cpp b/src/config.cpp index 562a8cb..b588725 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,8 +1,7 @@ #include "git2cpp/config.h" #include "git2cpp/error.h" -extern "C" -{ +extern "C" { #include } @@ -19,7 +18,7 @@ namespace git git_config_free(cfg_); } - std::string Config::operator [] (const char * key) const + std::string Config::operator[](const char * key) const { const char * res; if (git_config_get_string(&res, cfg_, key)) diff --git a/src/diff.cpp b/src/diff.cpp index 3f9cc08..dccb1ae 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -4,8 +4,8 @@ #include #ifdef USE_BOOST -#include #include +#include #else #include #endif @@ -14,52 +14,50 @@ namespace git { namespace diff { - namespace stats { - namespace format + namespace stats { - const type none (GIT_DIFF_STATS_NONE); - const type full (GIT_DIFF_STATS_FULL); - const type _short (GIT_DIFF_STATS_SHORT); - const type number (GIT_DIFF_STATS_NUMBER); - const type include_summary (GIT_DIFF_STATS_INCLUDE_SUMMARY); - }} + namespace format + { + const type none(GIT_DIFF_STATS_NONE); + const type full(GIT_DIFF_STATS_FULL); + const type _short(GIT_DIFF_STATS_SHORT); + const type number(GIT_DIFF_STATS_NUMBER); + const type include_summary(GIT_DIFF_STATS_INCLUDE_SUMMARY); + } + } #ifdef USE_BOOST - template + template using map_container = boost::container::flat_map; #else - struct EnumHash{ + struct EnumHash + { template - std::size_t operator()(T t) const{ + std::size_t operator()(T t) const + { return static_cast(t); } }; - template + template using map_container = std::unordered_map; #endif git_diff_format_t convert(format f) { - static const map_container converter - = { - { format::patch, GIT_DIFF_FORMAT_PATCH }, - { format::patch_header, GIT_DIFF_FORMAT_PATCH_HEADER }, - { format::raw, GIT_DIFF_FORMAT_RAW }, - { format::name_only, GIT_DIFF_FORMAT_NAME_ONLY }, - { format::name_status, GIT_DIFF_FORMAT_NAME_STATUS } - } - ; + static const map_container converter = { + {format::patch, GIT_DIFF_FORMAT_PATCH}, + {format::patch_header, GIT_DIFF_FORMAT_PATCH_HEADER}, + {format::raw, GIT_DIFF_FORMAT_RAW}, + {format::name_only, GIT_DIFF_FORMAT_NAME_ONLY}, + {format::name_status, GIT_DIFF_FORMAT_NAME_STATUS}}; return converter.at(f); } } namespace { - int apply_callback ( git_diff_delta const * delta - , git_diff_hunk const * hunk - , git_diff_line const * line - , void * payload ) + int apply_callback(git_diff_delta const * delta, git_diff_hunk const * hunk, git_diff_line const * line, void * payload) { assert(delta); assert(line); @@ -83,7 +81,7 @@ namespace git void Diff::print(diff::format f, print_callback_t print_callback) const { - git_diff_print(diff_, convert(f), &apply_callback, &print_callback); + git_diff_print(diff_, convert(f), &apply_callback, &print_callback); } Diff::Stats Diff::stats() const @@ -109,4 +107,3 @@ namespace git return Buffer(buf); } } - diff --git a/src/id_to_str.cpp b/src/id_to_str.cpp index 15d189b..b286ea7 100644 --- a/src/id_to_str.cpp +++ b/src/id_to_str.cpp @@ -1,15 +1,14 @@ #include "git2cpp/id_to_str.h" -extern "C" -{ +extern "C" { #include -} +} namespace git { std::string id_to_str(git_oid const & oid) { - return id_to_str(oid, GIT_OID_HEXSZ); + return id_to_str(oid, GIT_OID_HEXSZ); } std::string id_to_str(git_oid const & oid, size_t digits_num) @@ -19,7 +18,7 @@ namespace git return std::string(buf, buf + digits_num); } - git_oid str_to_id(const char *str) + git_oid str_to_id(const char * str) { git_oid res; git_oid_fromstr(&res, str); diff --git a/src/index.cpp b/src/index.cpp index 96fa9e9..e84fa2d 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -1,13 +1,12 @@ #include -extern "C" -{ -#include +extern "C" { #include +#include } -#include "git2cpp/index.h" #include "git2cpp/error.h" +#include "git2cpp/index.h" namespace git { @@ -35,7 +34,7 @@ namespace git other.index_ = nullptr; } - Index& Index::operator =(Index && other) noexcept + Index & Index::operator=(Index && other) noexcept { std::swap(index_, other.index_); return *this; @@ -46,7 +45,7 @@ namespace git return git_index_entrycount(index_); } - git_index_entry const * Index::operator[] (size_t i) const + git_index_entry const * Index::operator[](size_t i) const { return git_index_get_byindex(index_, i); } @@ -62,17 +61,17 @@ namespace git void Index::update_all(git_strarray const & pathspec, matched_path_callback_t cb) { - int res = cb - ? git_index_update_all(index_, &pathspec, &apply_callback, &cb) - : git_index_update_all(index_, &pathspec, nullptr, nullptr); + int res = cb + ? git_index_update_all(index_, &pathspec, &apply_callback, &cb) + : git_index_update_all(index_, &pathspec, nullptr, nullptr); assert(res == 0); } void Index::add_all(git_strarray const & pathspec, matched_path_callback_t cb, unsigned int flags) { - int res = cb - ? git_index_add_all(index_, &pathspec, flags, &apply_callback, &cb) - : git_index_add_all(index_, &pathspec, flags, nullptr, nullptr); + int res = cb + ? git_index_add_all(index_, &pathspec, flags, &apply_callback, &cb) + : git_index_add_all(index_, &pathspec, flags, nullptr, nullptr); assert(res == 0); } diff --git a/src/initializer.cpp b/src/initializer.cpp index 4e18894..9f42d3c 100644 --- a/src/initializer.cpp +++ b/src/initializer.cpp @@ -1,7 +1,6 @@ #include "git2cpp/initializer.h" -extern "C" -{ +extern "C" { #include } @@ -17,4 +16,3 @@ namespace git git_libgit2_shutdown(); } } - diff --git a/src/object.cpp b/src/object.cpp index 58ee1d5..fe7c166 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -2,8 +2,7 @@ #include -extern "C" -{ +extern "C" { #include } @@ -12,7 +11,8 @@ namespace git Object::Object(git_object * obj, Repository const & repo) : obj_(obj) , repo_(&repo) - {} + { + } Object::~Object() { @@ -36,17 +36,17 @@ namespace git return *git_object_id(obj_); } -#define DEFINE_METHOD_AS(type_name, enum_element) \ - git_##type_name const * Object::as_##type_name() const \ - { \ - assert(type() == GIT_OBJ_##enum_element); \ - return reinterpret_cast(obj_); \ - } \ +#define DEFINE_METHOD_AS(type_name, enum_element) \ + git_##type_name const * Object::as_##type_name() const \ + { \ + assert(type() == GIT_OBJ_##enum_element); \ + return reinterpret_cast(obj_); \ + } - DEFINE_METHOD_AS(blob, BLOB) - DEFINE_METHOD_AS(commit, COMMIT) - DEFINE_METHOD_AS(tree, TREE) - DEFINE_METHOD_AS(tag, TAG) + DEFINE_METHOD_AS(blob, BLOB) + DEFINE_METHOD_AS(commit, COMMIT) + DEFINE_METHOD_AS(tree, TREE) + DEFINE_METHOD_AS(tag, TAG) #undef DEFINE_METHOD_AS @@ -68,10 +68,9 @@ namespace git Blob Object::to_blob() /*&&*/ { - assert(type() == GIT_OBJ_BLOB); - Blob res(reinterpret_cast(obj_)); - obj_ = nullptr; - return res; + assert(type() == GIT_OBJ_BLOB); + Blob res(reinterpret_cast(obj_)); + obj_ = nullptr; + return res; } } - diff --git a/src/odb.cpp b/src/odb.cpp index e28fb2e..f9060d6 100644 --- a/src/odb.cpp +++ b/src/odb.cpp @@ -1,11 +1,10 @@ -extern "C" -{ -#include +extern "C" { #include +#include } -#include "git2cpp/odb.h" #include "git2cpp/error.h" +#include "git2cpp/odb.h" namespace git { @@ -29,7 +28,7 @@ namespace git return OdbObject(obj); } - git_oid Odb::write(const void *data, size_t len, git_otype type) + git_oid Odb::write(const void * data, size_t len, git_otype type) { git_oid res; if (git_odb_write(&res, odb_, data, len, type)) @@ -37,4 +36,3 @@ namespace git return res; } } - diff --git a/src/odb_object.cpp b/src/odb_object.cpp index 2e99ade..5f2f5f8 100644 --- a/src/odb_object.cpp +++ b/src/odb_object.cpp @@ -1,7 +1,6 @@ #include "git2cpp/odb_object.h" -extern "C" -{ +extern "C" { #include } @@ -28,4 +27,3 @@ namespace git return git_odb_object_size(obj_); } } - diff --git a/src/reference.cpp b/src/reference.cpp index 762e040..f64a293 100644 --- a/src/reference.cpp +++ b/src/reference.cpp @@ -14,7 +14,8 @@ namespace git Reference::Reference(git_reference * ref) : ref_(ref) - {} + { + } const char * Reference::name() const { @@ -37,12 +38,12 @@ namespace git return git_reference_symbolic_target(ref_); } - Reference::Reference(Reference&& other) noexcept + Reference::Reference(Reference && other) noexcept : ref_(std::exchange(other.ref_, nullptr)) { } - Reference& Reference::operator=(Reference&& other) noexcept + Reference & Reference::operator=(Reference && other) noexcept { std::swap(ref_, other.ref_); return *this; diff --git a/src/repo.cpp b/src/repo.cpp index aced1b3..e84085d 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -3,16 +3,16 @@ #include "git2cpp/error.h" #include "git2cpp/internal/optional.h" -#include +#include #include -#include +#include +#include #include +#include +#include #include -#include #include -#include -#include -#include +#include #include @@ -60,13 +60,13 @@ namespace git throw repository_init_error(dir); } - Repository::Repository(Repository&& other) noexcept + Repository::Repository(Repository && other) noexcept : repo_(other.repo_) { other.repo_ = nullptr; } - Repository& Repository::operator=(Repository&& other) noexcept + Repository & Repository::operator=(Repository && other) noexcept { std::swap(repo_, other.repo_); return *this; @@ -89,11 +89,11 @@ namespace git Commit Repository::commit_lookup(git_oid const & oid) const { - git_commit * commit; - if (git_commit_lookup(&commit, repo_, &oid)) - throw commit_lookup_error(oid); - else - return { commit, *this }; + git_commit * commit; + if (git_commit_lookup(&commit, repo_, &oid)) + throw commit_lookup_error(oid); + else + return {commit, *this}; } Tree Repository::tree_lookup(git_oid const & oid) const @@ -102,16 +102,16 @@ namespace git if (git_tree_lookup(&tree, repo_, &oid)) throw tree_lookup_error(oid); else - return { tree, *this }; + return {tree, *this}; } Tag Repository::tag_lookup(git_oid const & oid) const { - git_tag * tag; - if (git_tag_lookup(&tag, repo_, &oid)) - throw tag_lookup_error(oid); - else - return { tag, *this }; + git_tag * tag; + if (git_tag_lookup(&tag, repo_, &oid)) + throw tag_lookup_error(oid); + else + return {tag, *this}; } Blob Repository::blob_lookup(git_oid const & oid) const @@ -129,7 +129,7 @@ namespace git if (git_revparse(&revspec, repo_, spec)) throw revparse_error(spec); else - return { revspec, *this }; + return {revspec, *this}; } Revspec Repository::revparse_single(const char * spec) const @@ -180,9 +180,9 @@ namespace git git_branch_iterator_free(base_); } - explicit operator bool () const { return internal::has_value(ref_); } + explicit operator bool() const { return internal::has_value(ref_); } - void operator ++ () + void operator++() { git_branch_t type; git_reference * ref; @@ -201,7 +201,7 @@ namespace git } } - Reference& operator * () + Reference & operator*() { return *ref_; } @@ -211,9 +211,12 @@ namespace git { switch (t) { - case branch_type::LOCAL : return GIT_BRANCH_LOCAL; - case branch_type::REMOTE: return GIT_BRANCH_REMOTE; - case branch_type::ALL: return GIT_BRANCH_ALL; + case branch_type::LOCAL: + return GIT_BRANCH_LOCAL; + case branch_type::REMOTE: + return GIT_BRANCH_REMOTE; + case branch_type::ALL: + return GIT_BRANCH_ALL; default: throw std::logic_error("invalid branch type"); } @@ -239,7 +242,7 @@ namespace git if (git_revwalk_new(&walker, repo_)) throw revwalk_new_error(); else - return { walker, *this }; + return {walker, *this}; } git_oid Repository::merge_base(git_oid const & a, git_oid const & b) const @@ -296,7 +299,7 @@ namespace git if (git_submodule_lookup(&sm, repo_, name)) throw submodule_lookup_error(name); else - return { sm, repo_ }; + return {sm, repo_}; } const char * Repository::path() const @@ -317,7 +320,7 @@ namespace git const char * message_encoding) { git_oid res; - if (git_commit_create_v(&res, repo_, update_ref, + if (git_commit_create_v(&res, repo_, update_ref, author.ptr(), commiter.ptr(), message_encoding, message, tree.ptr(), 0)) @@ -411,20 +414,20 @@ namespace git return Diff(diff); } - void Repository::reset_default(Commit const& commit, git_strarray const& pathspecs) + void Repository::reset_default(Commit const & commit, git_strarray const & pathspecs) { - auto op_res = git_reset_default(repo_, reinterpret_cast(const_cast(commit.ptr())), const_cast(&pathspecs)); + auto op_res = git_reset_default(repo_, reinterpret_cast(const_cast(commit.ptr())), const_cast(&pathspecs)); assert(op_res == GIT_OK); } - void Repository::file_diff(std::string const& old_path, git_oid const& old_id, - std::string const& new_path, git_oid const& new_id, + void Repository::file_diff(std::string const & old_path, git_oid const & old_id, + std::string const & new_path, git_oid const & new_id, FileDiffHandler & diff_handler) const { auto old_file = blob_lookup(old_id); auto new_file = blob_lookup(new_id); git_diff_options options = GIT_DIFF_OPTIONS_INIT; - auto data_callback = [] (git_diff_delta const *, git_diff_hunk const *, git_diff_line const * line, void * payload) { + auto data_callback = [](git_diff_delta const *, git_diff_hunk const *, git_diff_line const * line, void * payload) { auto handler = reinterpret_cast(payload); handler->line(*line); return 0; @@ -444,10 +447,10 @@ namespace git Remote Repository::remote(const char * name) const { - git_remote * remote; - if (git_remote_lookup(&remote, repo_, name)) - throw remote_lookup_error(name); - else - return Remote(remote); + git_remote * remote; + if (git_remote_lookup(&remote, repo_, name)) + throw remote_lookup_error(name); + else + return Remote(remote); } } diff --git a/src/revspec.cpp b/src/revspec.cpp index f93f564..0de9d5a 100644 --- a/src/revspec.cpp +++ b/src/revspec.cpp @@ -3,16 +3,18 @@ namespace git { Revspec::Revspec(git_object * single, Repository const & repo) - : flags_(GIT_REVPARSE_SINGLE) + : flags_(GIT_REVPARSE_SINGLE) , revspec_(single, repo) - {} + { + } Revspec::Revspec(git_revspec const & revspec, Repository const & repo) : flags_(revspec.flags) - , revspec_((revspec.flags & GIT_REVPARSE_SINGLE) - ? Range(revspec.from, repo) - : Range(revspec, repo)) - {} + , revspec_((revspec.flags & GIT_REVPARSE_SINGLE) + ? Range(revspec.from, repo) + : Range(revspec, repo)) + { + } Object * Revspec::single() { @@ -35,4 +37,3 @@ namespace git return flags_; } } - diff --git a/src/revwalker.cpp b/src/revwalker.cpp index fdd9b89..b1c2ba5 100644 --- a/src/revwalker.cpp +++ b/src/revwalker.cpp @@ -6,14 +6,16 @@ namespace git { - namespace revwalker { - namespace sorting + namespace revwalker { - const type none (GIT_SORT_NONE); - const type topological (GIT_SORT_TOPOLOGICAL); - const type time (GIT_SORT_TIME); - const type reverse (GIT_SORT_REVERSE); - }} + namespace sorting + { + const type none(GIT_SORT_NONE); + const type topological(GIT_SORT_TOPOLOGICAL); + const type time(GIT_SORT_TIME); + const type reverse(GIT_SORT_REVERSE); + } + } RevWalker::~RevWalker() { @@ -27,7 +29,7 @@ namespace git void RevWalker::simplify_first_parent() { - git_revwalk_simplify_first_parent(walker_); + git_revwalk_simplify_first_parent(walker_); } void RevWalker::push_head() const @@ -66,4 +68,3 @@ namespace git return valid; } } - diff --git a/src/signature.cpp b/src/signature.cpp index b72daac..4c0ca65 100644 --- a/src/signature.cpp +++ b/src/signature.cpp @@ -1,10 +1,9 @@ -extern "C" -{ +extern "C" { #include } -#include "git2cpp/signature.h" #include "git2cpp/error.h" +#include "git2cpp/signature.h" namespace git { diff --git a/src/status.cpp b/src/status.cpp index 5707692..12ffa7b 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -6,9 +6,9 @@ namespace git size_t Status::entrycount() const { return git_status_list_entrycount(status_); - } + } - git_status_entry const & Status::operator[] (size_t i) const + git_status_entry const & Status::operator[](size_t i) const { if (auto res = git_status_byindex(status_, i)) return *res; @@ -22,8 +22,10 @@ namespace git { switch (show) { - case Status::Options::Show::IndexOnly: return GIT_STATUS_SHOW_INDEX_ONLY; - case Status::Options::Show::WorkdirOnly: return GIT_STATUS_SHOW_INDEX_ONLY; + case Status::Options::Show::IndexOnly: + return GIT_STATUS_SHOW_INDEX_ONLY; + case Status::Options::Show::WorkdirOnly: + return GIT_STATUS_SHOW_INDEX_ONLY; default: return GIT_STATUS_SHOW_INDEX_AND_WORKDIR; } @@ -52,40 +54,40 @@ namespace git opts_.pathspec.count = size; } - Status::Options& Status::Options::include_untracked() + Status::Options & Status::Options::include_untracked() { opts_.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; return *this; } - Status::Options& Status::Options::exclude_untracked() + Status::Options & Status::Options::exclude_untracked() { opts_.flags &= ~GIT_STATUS_OPT_INCLUDE_UNTRACKED; return *this; } - Status::Options& Status::Options::recurse_untracked_dirs() + Status::Options & Status::Options::recurse_untracked_dirs() { opts_.flags |= GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; return *this; } - Status::Options& Status::Options::exclude_submodules() + Status::Options & Status::Options::exclude_submodules() { opts_.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES; return *this; } - Status::Options& Status::Options::include_ignored() + Status::Options & Status::Options::include_ignored() { opts_.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED; return *this; } - Status::Options& Status::Options::renames_head_to_index() + Status::Options & Status::Options::renames_head_to_index() { opts_.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - return *this; + return *this; } Status::Status(git_repository * repo, Options const & opts) @@ -100,7 +102,7 @@ namespace git other.status_ = nullptr; } - Status& Status::operator =(Status && other) noexcept + Status & Status::operator=(Status && other) noexcept { std::swap(status_, other.status_); return *this; @@ -111,4 +113,3 @@ namespace git git_status_list_free(status_); } } - diff --git a/src/submodule.cpp b/src/submodule.cpp index 190c16a..30b917a 100644 --- a/src/submodule.cpp +++ b/src/submodule.cpp @@ -9,7 +9,8 @@ namespace git Submodule::Submodule(git_submodule * sm, git_repository * repo) : sm_(sm) , repo_(repo) - {} + { + } Submodule::~Submodule() { diff --git a/src/tag.cpp b/src/tag.cpp index 4e029e9..a7be2dd 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -1,15 +1,16 @@ #include -#include "git2cpp/tag.h" #include "git2cpp/error.h" #include "git2cpp/repo.h" +#include "git2cpp/tag.h" namespace git { Tag::Tag(git_tag * tag, Repository const & repo) - : tag_(tag) - , repo_(repo) - {} + : tag_(tag) + , repo_(repo) + { + } Tag::~Tag() { diff --git a/src/tree.cpp b/src/tree.cpp index 5b31de8..f40d185 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -9,12 +9,14 @@ namespace git Tree::Tree(git_tree * tree, Repository const & repo) : tree_(tree) , repo_(&repo) - {} + { + } Tree::Tree() - : tree_(nullptr) - , repo_(nullptr) - {} + : tree_(nullptr) + , repo_(nullptr) + { + } Tree::Tree(Tree && other) : tree_(other.tree_) @@ -24,7 +26,7 @@ namespace git other.repo_ = nullptr; } - Tree& Tree::operator =(Tree && other) + Tree & Tree::operator=(Tree && other) { tree_ = other.tree_; repo_ = other.repo_; @@ -48,12 +50,12 @@ namespace git return git_tree_entrycount(tree_); } - Tree::BorrowedEntry Tree::operator[] (size_t i) const + Tree::BorrowedEntry Tree::operator[](size_t i) const { return BorrowedEntry(git_tree_entry_byindex(tree_, i)); } - Tree::BorrowedEntry Tree::operator[] (std::string const & filename) const + Tree::BorrowedEntry Tree::operator[](std::string const & filename) const { if (auto entry = git_tree_entry_byname(tree_, filename.c_str())) return BorrowedEntry(entry); @@ -63,35 +65,36 @@ namespace git Tree::OwnedEntry Tree::find(const char * path) const { - git_tree_entry * res; - const auto status = git_tree_entry_bypath(&res, tree_, path); - switch (status) - { - case GIT_OK: - return OwnedEntry(res, *repo_); - case GIT_ENOTFOUND: - throw file_not_found_error(path); - default: - throw error_t(internal::format("unknown error inside function: 'git_tree_entry_bypath': %d", status)); - } + git_tree_entry * res; + const auto status = git_tree_entry_bypath(&res, tree_, path); + switch (status) + { + case GIT_OK: + return OwnedEntry(res, *repo_); + case GIT_ENOTFOUND: + throw file_not_found_error(path); + default: + throw error_t(internal::format("unknown error inside function: 'git_tree_entry_bypath': %d", status)); + } } Tree::OwnedEntry::OwnedEntry(git_tree_entry * entry, Repository const & repo) - : entry_(entry) - , repo_(&repo) - {} + : entry_(entry) + , repo_(&repo) + { + } Tree::OwnedEntry::~OwnedEntry() { - git_tree_entry_free(entry_); + git_tree_entry_free(entry_); } Tree::OwnedEntry::OwnedEntry(OwnedEntry && other) : entry_(other.entry_) , repo_(other.repo_) { - other.entry_ = nullptr; - other.repo_ = nullptr; + other.entry_ = nullptr; + other.repo_ = nullptr; } Tree Tree::OwnedEntry::to_tree() /* && */ @@ -102,11 +105,11 @@ namespace git const char * Tree::BorrowedEntry::name() const { - return git_tree_entry_name(entry_); + return git_tree_entry_name(entry_); } git_oid const & Tree::BorrowedEntry::id() const { - return *git_tree_entry_id(entry_); + return *git_tree_entry_id(entry_); } } From 5c444957e0d971a37e6b3b685d1819db198cd815 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 5 Jan 2019 11:24:54 +0300 Subject: [PATCH 106/171] redundant extern "C" blocks removed --- src/config.cpp | 2 -- src/id_to_str.cpp | 2 -- src/index.cpp | 2 -- src/initializer.cpp | 2 -- src/object.cpp | 2 -- src/odb.cpp | 2 -- src/odb_object.cpp | 2 -- src/signature.cpp | 2 -- 8 files changed, 16 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index b588725..25db76d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,9 +1,7 @@ #include "git2cpp/config.h" #include "git2cpp/error.h" -extern "C" { #include -} namespace git { diff --git a/src/id_to_str.cpp b/src/id_to_str.cpp index b286ea7..48c48c9 100644 --- a/src/id_to_str.cpp +++ b/src/id_to_str.cpp @@ -1,8 +1,6 @@ #include "git2cpp/id_to_str.h" -extern "C" { #include -} namespace git { diff --git a/src/index.cpp b/src/index.cpp index e84fa2d..cfa82af 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -1,9 +1,7 @@ #include -extern "C" { #include #include -} #include "git2cpp/error.h" #include "git2cpp/index.h" diff --git a/src/initializer.cpp b/src/initializer.cpp index 9f42d3c..e9728e8 100644 --- a/src/initializer.cpp +++ b/src/initializer.cpp @@ -1,8 +1,6 @@ #include "git2cpp/initializer.h" -extern "C" { #include -} namespace git { diff --git a/src/object.cpp b/src/object.cpp index fe7c166..3b65142 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -2,9 +2,7 @@ #include -extern "C" { #include -} namespace git { diff --git a/src/odb.cpp b/src/odb.cpp index f9060d6..61230cc 100644 --- a/src/odb.cpp +++ b/src/odb.cpp @@ -1,7 +1,5 @@ -extern "C" { #include #include -} #include "git2cpp/error.h" #include "git2cpp/odb.h" diff --git a/src/odb_object.cpp b/src/odb_object.cpp index 5f2f5f8..13d367c 100644 --- a/src/odb_object.cpp +++ b/src/odb_object.cpp @@ -1,8 +1,6 @@ #include "git2cpp/odb_object.h" -extern "C" { #include -} namespace git { diff --git a/src/signature.cpp b/src/signature.cpp index 4c0ca65..7b41910 100644 --- a/src/signature.cpp +++ b/src/signature.cpp @@ -1,6 +1,4 @@ -extern "C" { #include -} #include "git2cpp/error.h" #include "git2cpp/signature.h" From d6560620037f73c60d1fe0e887559087df6ba328 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 18:41:33 +0300 Subject: [PATCH 107/171] fix typo --- examples/status.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/status.cpp b/examples/status.cpp index 8a6ff7f..b6790b0 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -86,7 +86,7 @@ void show_branch(Repository const & repo, int format) if (format == FORMAT_LONG) std::cout << "# On branch " << branch.value_or("Not currently on any branch."); else - std::cout << "## ", branch.value_or("HEAD (no branch)"); + std::cout << "## " << branch.value_or("HEAD (no branch)"); std::cout << "\n"; } From 611f7583c87fc2c162de60337c575b646e96e7ba Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 18:51:24 +0300 Subject: [PATCH 108/171] code cleanup --- examples/status.cpp | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/examples/status.cpp b/examples/status.cpp index b6790b0..68d9126 100644 --- a/examples/status.cpp +++ b/examples/status.cpp @@ -31,12 +31,14 @@ using StringView = std::string_view; using namespace git; -enum +namespace { + +enum class Format { - FORMAT_DEFAULT = 0, - FORMAT_LONG = 1, - FORMAT_SHORT = 2, - FORMAT_PORCELAIN = 3, + DEFAULT, + LONG, + SHORT, + PORCELAIN, }; /* @@ -62,7 +64,7 @@ bool starts_with(StringView str, StringView prefix) return str.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), str.begin()); } -void show_branch(Repository const & repo, int format) +void show_branch(Repository const & repo, Format format) { Optional branch; try @@ -83,7 +85,7 @@ void show_branch(Repository const & repo, int format) throw e; } - if (format == FORMAT_LONG) + if (format == Format::LONG) std::cout << "# On branch " << branch.value_or("Not currently on any branch."); else std::cout << "## " << branch.value_or("HEAD (no branch)"); @@ -349,11 +351,15 @@ void print_short(Repository const & repo, Status const & status) } } +} + int main(int argc, char * argv[]) { auto_git_initializer; - int npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0; + size_t npaths = 0; + Format format = Format::DEFAULT; + bool showbranch = false; Status::Options opt; const char * repodir = "."; @@ -377,18 +383,17 @@ int main(int argc, char * argv[]) } } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--short")) - format = FORMAT_SHORT; + format = Format::SHORT; else if (!strcmp(argv[i], "--long")) - format = FORMAT_LONG; + format = Format::LONG; else if (!strcmp(argv[i], "--porcelain")) - format = FORMAT_PORCELAIN; + format = Format::PORCELAIN; else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--branch")) showbranch = 1; else if (!strcmp(argv[i], "-z")) { - zterm = 1; - if (format == FORMAT_DEFAULT) - format = FORMAT_PORCELAIN; + if (format == Format::DEFAULT) + format = Format::PORCELAIN; } else if (!strcmp(argv[i], "--ignored")) opt.include_ignored(); @@ -412,10 +417,10 @@ int main(int argc, char * argv[]) } } - if (format == FORMAT_DEFAULT) - format = FORMAT_LONG; - if (format == FORMAT_LONG) - showbranch = 1; + if (format == Format::DEFAULT) + format = Format::LONG; + if (format == Format::LONG) + showbranch = true; if (npaths > 0) opt.set_pathspec(pathspec, npaths); @@ -443,7 +448,7 @@ int main(int argc, char * argv[]) if (showbranch) show_branch(repo, format); - if (format == FORMAT_LONG) + if (format == Format::LONG) print_long(status); else print_short(repo, status); From bb0a643604956047e9e74ecb3b99ba3f37122d9c Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 19:19:16 +0300 Subject: [PATCH 109/171] missing `noexcept` + code cleanup --- include/git2cpp/tree.h | 8 ++++---- src/tree.cpp | 26 ++++++++++---------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index 21285f7..f117baf 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -34,8 +34,8 @@ namespace git OwnedEntry(OwnedEntry const &) = delete; OwnedEntry & operator=(OwnedEntry const &) = delete; - OwnedEntry(OwnedEntry &&); - OwnedEntry & operator=(OwnedEntry &&); + OwnedEntry(OwnedEntry &&) noexcept; + OwnedEntry & operator=(OwnedEntry &&) noexcept; Tree to_tree() /*&&*/; @@ -70,8 +70,8 @@ namespace git Tree(); ~Tree(); - Tree(Tree &&); - Tree & operator=(Tree &&); + Tree(Tree &&) noexcept; + Tree & operator=(Tree &&) noexcept; Tree(Tree const &) = delete; Tree & operator=(Tree const &) = delete; diff --git a/src/tree.cpp b/src/tree.cpp index f40d185..03f6e97 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -18,20 +18,16 @@ namespace git { } - Tree::Tree(Tree && other) - : tree_(other.tree_) - , repo_(other.repo_) + Tree::Tree(Tree && other) noexcept + : tree_(std::exchange(other.tree_, nullptr)) + , repo_(std::exchange(other.repo_, nullptr)) { - other.tree_ = nullptr; - other.repo_ = nullptr; } - Tree & Tree::operator=(Tree && other) + Tree & Tree::operator=(Tree && other) noexcept { - tree_ = other.tree_; - repo_ = other.repo_; - other.tree_ = nullptr; - other.repo_ = nullptr; + std::swap(tree_, other.tree_); + std::swap(repo_, other.repo_); return *this; } @@ -42,7 +38,7 @@ namespace git int Tree::pathspec_match(uint32_t flags, Pathspec const & ps) { - return git_pathspec_match_tree(NULL, tree_, flags, ps.ptr()); + return git_pathspec_match_tree(nullptr, tree_, flags, ps.ptr()); } size_t Tree::entrycount() const @@ -89,12 +85,10 @@ namespace git git_tree_entry_free(entry_); } - Tree::OwnedEntry::OwnedEntry(OwnedEntry && other) - : entry_(other.entry_) - , repo_(other.repo_) + Tree::OwnedEntry::OwnedEntry(OwnedEntry && other) noexcept + : entry_(std::exchange(other.entry_, nullptr)) + , repo_(std::exchange(other.repo_, nullptr)) { - other.entry_ = nullptr; - other.repo_ = nullptr; } Tree Tree::OwnedEntry::to_tree() /* && */ From 93dfacb1053be813e4abbc47a7eb304bddd35dbf Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 20:13:33 +0300 Subject: [PATCH 110/171] Tag: don't store ref to repo, + some getters --- examples/general.cpp | 2 +- include/git2cpp/tag.h | 19 +++++++++++++------ src/repo.cpp | 2 +- src/tag.cpp | 24 ++++++++++++++++-------- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/examples/general.cpp b/examples/general.cpp index e5d6a23..2a32565 100644 --- a/examples/general.cpp +++ b/examples/general.cpp @@ -253,7 +253,7 @@ int main(int argc, char ** argv) // generally contains: the target (usually a commit object), the type of // the target object (usually 'commit'), the name ('v1.0'), the tagger (a // git_signature - name, email, timestamp), and the tag message. - Object commit = tag.target(); + Object commit = tag.target(repo); const char * tname = tag.name(); // "test" git_otype ttype = tag.target_type(); // GIT_OBJ_COMMIT (otype enum) const char * tmessage = tag.message(); // "tag message\n" diff --git a/include/git2cpp/tag.h b/include/git2cpp/tag.h index 26d9c9d..6f9a893 100644 --- a/include/git2cpp/tag.h +++ b/include/git2cpp/tag.h @@ -1,28 +1,35 @@ #pragma once -#include "object.h" +#include struct git_tag; +struct git_oid; namespace git { + struct Repository; + struct Object; + struct Tag { - Tag(git_tag *, Repository const &); + Tag(git_tag *); ~Tag(); Tag & operator=(Tag const &) = delete; Tag(Tag const &) = delete; - Tag(Tag &&); + Tag(Tag &&) noexcept; + + Object target(Repository const &) const; + + git_oid const & target_id() const; + git_otype target_type() const; - Object target() const; - git_otype target_type() const; const char * name() const; const char * message() const; + git_signature const * tagger() const; private: git_tag * tag_; - Repository const & repo_; }; } diff --git a/src/repo.cpp b/src/repo.cpp index e84085d..8f83057 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -111,7 +111,7 @@ namespace git if (git_tag_lookup(&tag, repo_, &oid)) throw tag_lookup_error(oid); else - return {tag, *this}; + return { tag }; } Blob Repository::blob_lookup(git_oid const & oid) const diff --git a/src/tag.cpp b/src/tag.cpp index a7be2dd..d53e055 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -1,14 +1,12 @@ -#include - -#include "git2cpp/error.h" -#include "git2cpp/repo.h" #include "git2cpp/tag.h" +#include "git2cpp/object.h" + +#include namespace git { - Tag::Tag(git_tag * tag, Repository const & repo) + Tag::Tag(git_tag * tag) : tag_(tag) - , repo_(repo) { } @@ -17,11 +15,16 @@ namespace git git_tag_free(tag_); } - Object Tag::target() const + Object Tag::target(Repository const & repo) const { git_object * obj; git_tag_target(&obj, tag_); - return Object(obj, repo_); + return Object(obj, repo); + } + + git_oid const & Tag::target_id() const + { + return *git_tag_target_id(tag_); } git_otype Tag::target_type() const @@ -38,4 +41,9 @@ namespace git { return git_tag_message(tag_); } + + git_signature const * Tag::tagger() const + { + return git_tag_tagger(tag_); + } } From 2409b804a9cd218e5ed16fa7a6c46210cb36c2cf Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 20:08:33 +0300 Subject: [PATCH 111/171] replace #includes to fwd declarations --- include/git2cpp/object.h | 9 ++++++--- src/object.cpp | 12 ++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index 47d071d..de4c5b3 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -1,8 +1,5 @@ #pragma once -#include "blob.h" -#include "commit.h" - #include struct git_object; @@ -14,6 +11,11 @@ namespace git { struct Repository; + struct Blob; + struct Commit; + struct Tree; + struct Tag; + struct Object { Object() {} @@ -34,6 +36,7 @@ namespace git Commit to_commit() /*&&*/; Tree to_tree() /*&&*/; Blob to_blob() /*&&*/; + Tag to_tag() /*&&*/; Object(Object const &) = delete; Object & operator=(Object const &) = delete; diff --git a/src/object.cpp b/src/object.cpp index 3b65142..0ad0121 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -1,4 +1,8 @@ #include "git2cpp/object.h" +#include "git2cpp/blob.h" +#include "git2cpp/commit.h" +#include "git2cpp/tree.h" +#include "git2cpp/tag.h" #include @@ -71,4 +75,12 @@ namespace git obj_ = nullptr; return res; } + + Tag Object::to_tag() /*&&*/ + { + assert(type() == GIT_OBJ_TAG); + Tag res(reinterpret_cast(obj_)); + obj_ = nullptr; + return res; + } } From d9df5c4ad48c6db1a584110990317dcd00d066e6 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 20:17:07 +0300 Subject: [PATCH 112/171] + Commit::tree_id() --- include/git2cpp/commit.h | 1 + src/commit.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 042a158..242c415 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -22,6 +22,7 @@ namespace git explicit operator bool() const { return commit_ != nullptr; } git_oid const & id() const; + git_oid const & tree_id() const; git_signature const * author() const; git_signature const * commiter() const; diff --git a/src/commit.cpp b/src/commit.cpp index 58b7fcc..ca72e88 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -60,6 +60,11 @@ namespace git return *git_commit_id(commit_); } + git_oid const & Commit::tree_id() const + { + return *git_commit_tree_id(commit_); + } + git_oid const & Commit::parent_id(size_t i) const { return *git_commit_parent_id(commit_, static_cast(i)); From f387ca57acd06f9c92e6a616256ffe1275e5252b Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 20:18:08 +0300 Subject: [PATCH 113/171] + Tree::BorrowedEntry::{type(), filemode()} --- include/git2cpp/tree.h | 2 ++ src/tree.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index f117baf..7b1509e 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -12,6 +12,8 @@ namespace git { const char * name() const; git_oid const & id() const; + git_otype type() const; + git_filemode_t filemode() const; private: friend struct Tree; diff --git a/src/tree.cpp b/src/tree.cpp index 03f6e97..cbb0417 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -106,4 +106,14 @@ namespace git { return *git_tree_entry_id(entry_); } + + git_otype Tree::BorrowedEntry::type() const + { + return git_tree_entry_type(entry_); + } + + git_filemode_t Tree::BorrowedEntry::filemode() const + { + return git_tree_entry_filemode(entry_); + } } From 7d76d519a70122e0678df642740829efa7b0b88c Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 20:19:00 +0300 Subject: [PATCH 114/171] code cleanup --- examples/cat-file.cpp | 150 ++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 80 deletions(-) diff --git a/examples/cat-file.cpp b/examples/cat-file.cpp index 8f1d23a..c27b80c 100644 --- a/examples/cat-file.cpp +++ b/examples/cat-file.cpp @@ -1,24 +1,18 @@ +#include "git2cpp/id_to_str.h" +#include "git2cpp/initializer.h" +#include "git2cpp/repo.h" + #include #include #include #include +#include #include -#include "git2cpp/id_to_str.h" -#include "git2cpp/initializer.h" -#include "git2cpp/repo.h" +namespace { -static void check(int error, const char * message) -{ - if (error) - { - fprintf(stderr, "%s (%d)\n", message, error); - exit(1); - } -} - -static void usage(const char * message, const char * arg) +[[noreturn]] void usage(const char * message, const char * arg) { if (message && arg) fprintf(stderr, "%s: %s\n", message, arg); @@ -28,25 +22,22 @@ static void usage(const char * message, const char * arg) exit(1); } -static int check_str_param( - const char * arg, const char * pattern, const char ** val) +bool check_str_param(const char * arg, const char * pattern, const char ** val) { size_t len = strlen(pattern); if (strncmp(arg, pattern, len)) - return 0; - *val = (const char *)(arg + len); - return 1; + return false; + *val = arg + len; + return true; } -static void print_signature(const char * header, const git_signature * sig) +void print_signature(const char * header, const git_signature * sig) { - char sign; - int offset, hours, minutes; - if (!sig) return; - offset = sig->when.offset; + int offset = sig->when.offset; + char sign; if (offset < 0) { sign = '-'; @@ -57,88 +48,85 @@ static void print_signature(const char * header, const git_signature * sig) sign = '+'; } - hours = offset / 60; - minutes = offset % 60; + const int hours = offset / 60; + const int minutes = offset % 60; printf("%s %s <%s> %ld %c%02d%02d\n", header, sig->name, sig->email, (long)sig->when.time, sign, hours, minutes); } -static void show_blob(const git_blob * blob) +void show_blob(git::Blob const & blob) { /* ? Does this need crlf filtering? */ - fwrite(git_blob_rawcontent(blob), static_cast(git_blob_rawsize(blob)), 1, stdout); + fwrite(blob.content(), blob.size(), 1, stdout); } -static void show_tree(const git_tree * tree) +void show_tree(git::Tree const & tree) { - size_t i, max_i = (int)git_tree_entrycount(tree); char oidstr[GIT_OID_HEXSZ + 1]; - const git_tree_entry * te; - for (i = 0; i < max_i; ++i) + for (size_t i = 0, n = tree.entrycount(); i < n; ++i) { - te = git_tree_entry_byindex(tree, i); + auto te = tree[i]; - git_oid_tostr(oidstr, sizeof(oidstr), git_tree_entry_id(te)); + git_oid_tostr(oidstr, sizeof(oidstr), &te.id()); printf("%06o %s %s\t%s\n", - git_tree_entry_filemode(te), - git_object_type2string(git_tree_entry_type(te)), - oidstr, git_tree_entry_name(te)); + te.filemode(), + git_object_type2string(te.type()), + oidstr, te.name()); } } -static void show_commit(const git_commit * commit) +void show_commit(git::Commit const & commit) { - unsigned int i, max_i; char oidstr[GIT_OID_HEXSZ + 1]; - git_oid_tostr(oidstr, sizeof(oidstr), git_commit_tree_id(commit)); + git_oid_tostr(oidstr, sizeof(oidstr), &commit.tree_id()); printf("tree %s\n", oidstr); - max_i = (unsigned int)git_commit_parentcount(commit); - for (i = 0; i < max_i; ++i) + for (size_t i = 0, n = commit.parents_num(); i != n; ++i) { - git_oid_tostr(oidstr, sizeof(oidstr), git_commit_parent_id(commit, i)); + git_oid_tostr(oidstr, sizeof(oidstr), &commit.parent_id(i)); printf("parent %s\n", oidstr); } - print_signature("author", git_commit_author(commit)); - print_signature("committer", git_commit_committer(commit)); + print_signature("author", commit.author()); + print_signature("committer", commit.commiter()); - if (git_commit_message(commit)) - printf("\n%s\n", git_commit_message(commit)); + if (auto message = commit.message()) + printf("\n%s\n", message); } -static void show_tag(const git_tag * tag) +void show_tag(git::Tag const & tag) { - char oidstr[GIT_OID_HEXSZ + 1]; - - git_oid_tostr(oidstr, sizeof(oidstr), git_tag_target_id(tag)); - ; - printf("object %s\n", oidstr); - printf("type %s\n", git_object_type2string(git_tag_target_type(tag))); - printf("tag %s\n", git_tag_name(tag)); - print_signature("tagger", git_tag_tagger(tag)); - - if (git_tag_message(tag)) - printf("\n%s\n", git_tag_message(tag)); + std::cout << "object " << git::id_to_str(tag.target_id()) << "\n" + << "\ntype " << git_object_type2string(tag.target_type()) + << "\ntag " << tag.name() + << std::endl; + print_signature("tagger", tag.tagger()); + + if (auto message = tag.message()) + printf("\n%s\n", message); } -enum +enum class Action { + NONE = 0, SHOW_TYPE = 1, SHOW_SIZE = 2, SHOW_NONE = 3, SHOW_PRETTY = 4 }; +} + int main(int argc, char * argv[]) { - const char *dir = ".", *rev = NULL; - int i, action = 0, verbose = 0; + const char *dir = ".", *rev = nullptr; + int i, verbose = 0; + Action action = Action::NONE; char oidstr[GIT_OID_HEXSZ + 1]; for (i = 1; i < argc; ++i) @@ -147,31 +135,31 @@ int main(int argc, char * argv[]) if (a[0] != '-') { - if (rev != NULL) - usage("Only one rev should be provided", NULL); + if (rev) + usage("Only one rev should be provided", nullptr); else rev = a; } else if (!strcmp(a, "-t")) - action = SHOW_TYPE; + action = Action::SHOW_TYPE; else if (!strcmp(a, "-s")) - action = SHOW_SIZE; + action = Action::SHOW_SIZE; else if (!strcmp(a, "-e")) - action = SHOW_NONE; + action = Action::SHOW_NONE; else if (!strcmp(a, "-p")) - action = SHOW_PRETTY; + action = Action::SHOW_PRETTY; else if (!strcmp(a, "-q")) verbose = 0; else if (!strcmp(a, "-v")) verbose = 1; else if (!strcmp(a, "--help") || !strcmp(a, "-h")) - usage(NULL, NULL); + usage(nullptr, nullptr); else if (!check_str_param(a, "--git-dir=", &dir)) usage("Unknown option", a); } - if (!action || !rev) - usage(NULL, NULL); + if (action == Action::NONE || !rev) + usage(nullptr, nullptr); git::Initializer threads_initializer; @@ -189,41 +177,43 @@ int main(int argc, char * argv[]) switch (action) { - case SHOW_TYPE: + case Action::SHOW_TYPE: printf("%s\n", git_object_type2string(obj.type())); break; - case SHOW_SIZE: + case Action::SHOW_SIZE: { git::Odb odb = repo.odb(); git::OdbObject odbobj = odb.read(obj.id()); - printf("%ld\n", (long)odbobj.size()); + printf("%zu\n", odbobj.size()); + break; } - break; - case SHOW_NONE: + case Action::SHOW_NONE: /* just want return result */ break; - case SHOW_PRETTY: + case Action::SHOW_PRETTY: switch (obj.type()) { case GIT_OBJ_BLOB: - show_blob(obj.as_blob()); + show_blob(obj.to_blob()); break; case GIT_OBJ_COMMIT: - show_commit(obj.as_commit()); + show_commit(obj.to_commit()); break; case GIT_OBJ_TREE: - show_tree(obj.as_tree()); + show_tree(obj.to_tree()); break; case GIT_OBJ_TAG: - show_tag(obj.as_tag()); + show_tag(obj.to_tag()); break; default: printf("unknown %s\n", oidstr); break; } break; + default: + assert("unexpected action" && static_cast(action)); } return 0; From 96ad2b588fb5d93486afc653990209050651bbfe Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 20:41:12 +0300 Subject: [PATCH 115/171] implement Tag move constructor --- src/tag.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tag.cpp b/src/tag.cpp index d53e055..c65b56b 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -3,6 +3,8 @@ #include +#include + namespace git { Tag::Tag(git_tag * tag) @@ -10,6 +12,11 @@ namespace git { } + Tag::Tag(Tag && other) noexcept + : tag_(std::exchange(other.tag_, nullptr)) + { + } + Tag::~Tag() { git_tag_free(tag_); From ea3c1822e308db5f5f785833b9cbf8767dc6dadf Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 20:44:08 +0300 Subject: [PATCH 116/171] code cleanup --- examples/diff.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/diff.cpp b/examples/diff.cpp index ef8efca..d49402d 100644 --- a/examples/diff.cpp +++ b/examples/diff.cpp @@ -11,6 +11,8 @@ using namespace git; +namespace { + Tree resolve_to_tree(Repository const & repo, const char * identifier) { Object obj = revparse_single(repo, identifier); @@ -19,10 +21,8 @@ Tree resolve_to_tree(Repository const & repo, const char * identifier) { case GIT_OBJ_TREE: return obj.to_tree(); - break; case GIT_OBJ_COMMIT: return obj.to_commit().tree(); - break; } std::ostringstream ss; @@ -42,7 +42,7 @@ const char * colors[] = { "\033[36m" /* cyan */ }; -static void usage(const char * message, const char * arg) +[[noreturn]] void usage(const char * message, const char * arg) { if (message && arg) fprintf(stderr, "%s: %s\n", message, arg); @@ -394,6 +394,8 @@ void diff_print_stats(Diff const & diff, output::type output) fputs(buf.ptr(), stdout); } +} + int main(int argc, char * argv[]) { auto_git_initializer; From b0cfe4a25c2201eed31484b95c1b83f6e365c237 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 20:58:38 +0300 Subject: [PATCH 117/171] code cleanup --- include/git2cpp/str_array.h | 3 +++ src/repo.cpp | 22 +++++----------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/include/git2cpp/str_array.h b/include/git2cpp/str_array.h index fd37a2f..1ffb12f 100644 --- a/include/git2cpp/str_array.h +++ b/include/git2cpp/str_array.h @@ -10,6 +10,9 @@ namespace git : str_array_(str_array) {} + StrArray(StrArray const &) = delete; + StrArray& operator =(StrArray const &) = delete; + size_t count() const { return str_array_.count; } const char * operator[](size_t i) const diff --git a/src/repo.cpp b/src/repo.cpp index 8f83057..b3c4253 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -18,27 +18,17 @@ namespace git { - namespace - { - int write_branch_name(const char * name, git_branch_t, void * payload) - { - std::vector * out = reinterpret_cast *>(payload); - out->emplace_back(name); - return 0; - } - } - const Repository::init_tag Repository::init; Repository::Repository(const char * dir) { - if (git_repository_open_ext(&repo_, dir, 0, NULL)) + if (git_repository_open_ext(&repo_, dir, 0, nullptr)) throw repository_open_error(dir); } Repository::Repository(std::string const & dir) { - if (git_repository_open_ext(&repo_, dir.c_str(), 0, NULL)) + if (git_repository_open_ext(&repo_, dir.c_str(), 0, nullptr)) throw repository_open_error(dir); } @@ -48,7 +38,7 @@ namespace git throw repository_init_error(dir); } - Repository::Repository(std::string const & dir, init_tag tag) + Repository::Repository(std::string const & dir, init_tag) { if (git_repository_init(&repo_, dir.c_str(), false) < 0) throw repository_init_error(dir); @@ -61,9 +51,8 @@ namespace git } Repository::Repository(Repository && other) noexcept - : repo_(other.repo_) + : repo_(std::exchange(other.repo_, nullptr)) { - other.repo_ = nullptr; } Repository & Repository::operator=(Repository && other) noexcept @@ -217,9 +206,8 @@ namespace git return GIT_BRANCH_REMOTE; case branch_type::ALL: return GIT_BRANCH_ALL; - default: - throw std::logic_error("invalid branch type"); } + throw std::logic_error("invalid branch type"); } private: From fca56d95cc5ba5f8a7fc0f8b3a22e14fdb50a996 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 21:30:52 +0300 Subject: [PATCH 118/171] code cleanup --- examples/init.cpp | 143 ++++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 68 deletions(-) diff --git a/examples/init.cpp b/examples/init.cpp index 34fa080..a80a86a 100644 --- a/examples/init.cpp +++ b/examples/init.cpp @@ -23,7 +23,19 @@ #include "git2cpp/initializer.h" #include "git2cpp/repo.h" -static void usage(const char * error, const char * arg) +#ifdef USE_BOOST +#include + +using StringView = boost::string_view; +#else +#include + +using StringView = std::string_view; +#endif + +namespace { + +[[noreturn]] void usage(const char * error, const char * arg) { fprintf(stderr, "error: %s '%s'\n", error, arg); fprintf(stderr, "usage: init [-q | --quiet] [--bare] " @@ -32,14 +44,13 @@ static void usage(const char * error, const char * arg) } /* simple string prefix test used in argument parsing */ -static size_t is_prefixed(const char * arg, const char * pfx) +size_t is_prefixed(StringView arg, StringView pfx) { - size_t len = strlen(pfx); - return !strncmp(arg, pfx, len) ? len : 0; + return arg == pfx ? pfx.size() : 0; } /* parse the tail of the --shared= argument */ -static uint32_t parse_shared(const char * shared) +uint32_t parse_shared(const char * shared) { if (!strcmp(shared, "false") || !strcmp(shared, "umask")) return GIT_REPOSITORY_INIT_SHARED_UMASK; @@ -53,9 +64,8 @@ static uint32_t parse_shared(const char * shared) else if (shared[0] == '0') { - long val; - char * end = NULL; - val = strtol(shared + 1, &end, 8); + char * end = nullptr; + long val = strtol(shared + 1, &end, 8); if (end == shared + 1 || *end != 0) usage("invalid octal value for --shared", shared); return (uint32_t)val; @@ -63,14 +73,38 @@ static uint32_t parse_shared(const char * shared) else usage("unknown value for --shared", shared); - - return 0; } using namespace git; -/* forward declaration of helper to make an empty parent-less commit */ -static void create_initial_commit(Repository & repo); +/* Unlike regular "git init", this example shows how to create an initial + * empty commit in the repository. This is the helper function that does + * that. + */ +static void create_initial_commit(Repository & repo) +{ + /* First use the config to initialize a commit signature for the user */ + Signature sig = repo.signature(); + + /* Now let's create an empty tree for this commit */ + Index index = repo.index(); + + /* Outside of this example, you could call git_index_add_bypath() + * here to put actual files into the index. For our purposes, we'll + * leave it empty for now. + */ + + git_oid tree_id = index.write_tree(); + Tree tree = repo.tree_lookup(tree_id); + + /* Ready to create the initial commit + * + * Normally creating a commit would involve looking up the current + * HEAD commit and making that be the parent of the initial commit, + * but here this is the first commit so there will be no parent. + */ + repo.create_commit("HEAD", sig, sig, "Initial commit", tree); +} git_repository_init_options make_opts(bool bare, const char * templ, uint32_t shared, @@ -104,52 +138,54 @@ git_repository_init_options make_opts(bool bare, const char * templ, return opts; } +} + int main(int argc, char * argv[]) { - int no_options = 1, quiet = 0, bare = 0, initial_commit = 0, i; + bool no_options = true, quiet = false, bare = false, initial_commit = false; uint32_t shared = GIT_REPOSITORY_INIT_SHARED_UMASK; - const char *templ = NULL, *gitdir = NULL, *dir = NULL; - size_t pfxlen; + const char *templ = nullptr, *gitdir = nullptr, *dir = nullptr; auto_git_initializer; /* Process arguments */ - for (i = 1; i < argc; ++i) + for (int i = 1; i < argc; ++i) { - char * a = argv[i]; + auto arg = argv[i]; + StringView a = arg; - if (a[0] == '-') - no_options = 0; + if (arg[0] == '-') + no_options = false; - if (a[0] != '-') + if (arg[0] != '-') { - if (dir != NULL) - usage("extra argument", a); - dir = a; + if (dir) + usage("extra argument", arg); + dir = arg; } - else if (!strcmp(a, "-q") || !strcmp(a, "--quiet")) - quiet = 1; - else if (!strcmp(a, "--bare")) - bare = 1; - else if ((pfxlen = is_prefixed(a, "--template=")) > 0) - templ = a + pfxlen; - else if (!strcmp(a, "--separate-git-dir")) + else if (a == "-q" || a == "--quiet") + quiet = true; + else if (a == "--bare") + bare = true; + else if (auto pfxlen = is_prefixed(a, "--template=")) + templ = arg + pfxlen; + else if (a == "--separate-git-dir") gitdir = argv[++i]; - else if ((pfxlen = is_prefixed(a, "--separate-git-dir=")) > 0) - gitdir = a + pfxlen; - else if (!strcmp(a, "--shared")) + else if (auto pfxlen = is_prefixed(a, "--separate-git-dir=")) + gitdir = arg + pfxlen; + else if (a == "--shared") shared = GIT_REPOSITORY_INIT_SHARED_GROUP; - else if ((pfxlen = is_prefixed(a, "--shared=")) > 0) - shared = parse_shared(a + pfxlen); - else if (!strcmp(a, "--initial-commit")) - initial_commit = 1; + else if (auto pfxlen = is_prefixed(a, "--shared=")) + shared = parse_shared(arg + pfxlen); + else if (a == "--initial-commit") + initial_commit = true; else - usage("unknown option", a); + usage("unknown option", arg); } if (!dir) - usage("must specify directory to init", NULL); + usage("must specify directory to init", nullptr); /* Initialize repository */ @@ -178,32 +214,3 @@ int main(int argc, char * argv[]) return 0; } - -/* Unlike regular "git init", this example shows how to create an initial - * empty commit in the repository. This is the helper function that does - * that. - */ -static void create_initial_commit(Repository & repo) -{ - /* First use the config to initialize a commit signature for the user */ - Signature sig = repo.signature(); - - /* Now let's create an empty tree for this commit */ - Index index = repo.index(); - - /* Outside of this example, you could call git_index_add_bypath() - * here to put actual files into the index. For our purposes, we'll - * leave it empty for now. - */ - - git_oid tree_id = index.write_tree(); - Tree tree = repo.tree_lookup(tree_id); - - /* Ready to create the initial commit - * - * Normally creating a commit would involve looking up the current - * HEAD commit and making that be the parent of the initial commit, - * but here this is the first commit so there will be no parent. - */ - repo.create_commit("HEAD", sig, sig, "Initial commit", tree); -} From 6430b38ad0fbcb6ae5caad773b81c5c5ec1477d1 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 23:49:38 +0300 Subject: [PATCH 119/171] + StrArray move constructor --- include/git2cpp/str_array.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/git2cpp/str_array.h b/include/git2cpp/str_array.h index 1ffb12f..ab63ea5 100644 --- a/include/git2cpp/str_array.h +++ b/include/git2cpp/str_array.h @@ -2,6 +2,8 @@ #include +#include + namespace git { struct StrArray @@ -13,6 +15,12 @@ namespace git StrArray(StrArray const &) = delete; StrArray& operator =(StrArray const &) = delete; + StrArray(StrArray && other) noexcept + : str_array_(other.str_array_) + { + std::memset(&other.str_array_, 0, sizeof(git_strarray)); + } + size_t count() const { return str_array_.count; } const char * operator[](size_t i) const From c658f3e440e7a3e36c7555187de3aa3e744991fd Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 8 Jan 2019 23:51:54 +0300 Subject: [PATCH 120/171] 'remote' exported from libgit2 examples --- CMakeLists.txt | 1 + examples/remote.cpp | 234 +++++++++++++++++++++++++++++++++++++++ include/git2cpp/error.h | 28 +++++ include/git2cpp/remote.h | 3 +- include/git2cpp/repo.h | 8 ++ src/remote.cpp | 5 + src/repo.cpp | 44 ++++++++ 7 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 examples/remote.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d5044ca..6981d33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ set(examples init rev-parse general + remote ) foreach (example ${examples}) diff --git a/examples/remote.cpp b/examples/remote.cpp new file mode 100644 index 0000000..580401d --- /dev/null +++ b/examples/remote.cpp @@ -0,0 +1,234 @@ +/* + * libgit2 "remote" example - shows how to modify remotes for a repo + * + * 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 "git2cpp/repo.h" +#include "git2cpp/initializer.h" + +#include "git2/errors.h" + +#include + +/** + * This is a sample program that is similar to "git remote". See the + * documentation for that (try "git help remote") to understand what this + * program is emulating. + * + * This demonstrates using the libgit2 APIs to modify remotes of a repository. + */ + +namespace { + +[[noreturn]] void usage(const char *msg, const char *arg = nullptr) +{ + fputs("usage: remote add \n", stderr); + fputs(" remote remove \n", stderr); + fputs(" remote rename \n", stderr); + fputs(" remote set-url [--push] \n", stderr); + fputs(" remote show [-v|--verbose]\n", stderr); + + if (msg && !arg) + fprintf(stderr, "\n%s\n", msg); + else if (msg && arg) + fprintf(stderr, "\n%s: %s\n", msg, arg); + exit(1); +} + +[[noreturn]] void report_error(const char *message) +{ + const git_error *lg2err = giterr_last(); + const char *lg2msg = "", *lg2spacer = ""; + + if (lg2err && lg2err->message) + { + lg2msg = lg2err->message; + lg2spacer = " - "; + } + + fprintf(stderr, "%s %s%s\n", message, lg2spacer, lg2msg); + exit(1); +} + +enum class Subcmd { + add, + remove, + rename, + seturl, + show, +}; + +struct Options { + Subcmd cmd; + + /* for command-specific args */ + int argc; + char **argv; + + Options(int argc, char **argv) + : argc(argc - 2) /* executable and subcommand are removed */ + , argv(argv + 2) + { + char *arg = argv[1]; + if (argc < 2) + usage("no command specified"); + + if (!strcmp(arg, "add")) { + cmd = Subcmd::add; + } else if (!strcmp(arg, "remove")) { + cmd = Subcmd::remove; + } else if (!strcmp(arg, "rename")) { + cmd = Subcmd::rename; + } else if (!strcmp(arg, "set-url")) { + cmd = Subcmd::seturl; + } else if (!strcmp(arg, "show")) { + cmd = Subcmd::show; + } else { + usage("command is not valid", arg); + } + } +}; + +using git::Repository; + +void cmd_add(Repository & repo, Options const & o) +{ + if (o.argc != 2) + usage("you need to specify a name and URL"); + + auto name = o.argv[0], url = o.argv[1]; + repo.create_remote(name, url); +} + +void cmd_remove(Repository & repo, Options const & o) +{ + if (o.argc != 1) + usage("you need to specify a name"); + + auto name = o.argv[0]; + repo.delete_remote(name); +} + +void cmd_rename(Repository & repo, Options const & o) +{ + if (o.argc != 2) + usage("you need to specify old and new remote name"); + + auto old_name = o.argv[0]; + auto new_name = o.argv[1]; + if (auto problems = repo.rename_remote(old_name, new_name)) + { + for (size_t i = 0, n = problems->count(); i != n; ++i) + puts((*problems)[i]); + } +} + +void cmd_seturl(Repository & repo, Options const & o) +{ + bool push = false; + char const * name = nullptr, *url = nullptr; + + for (auto i = 0; i != o.argc; ++i) + { + char const * arg = o.argv[i]; + + if (!strcmp(arg, "--push")) { + push = 1; + } else if (arg[0] != '-' && !name) { + name = arg; + } else if (arg[0] != '-' && !url) { + url = arg; + } else { + usage("invalid argument to set-url", arg); + } + } + + if (!name || !url) + usage("you need to specify remote and the new URL"); + + if (push) + repo.set_pushurl(name, url); + else + repo.set_url(name, url); +} + +void cmd_show(Repository const & repo, Options const & o) +{ + bool verbose = false; + + for (int i = 0; i != o.argc; ++i) + { + auto arg = o.argv[i]; + + if (!strcmp(arg, "-v") || + !strcmp(arg, "--verbose")) + { + verbose = true; + } + } + + auto remotes = repo.remotes(); + + for (size_t i = 0, n = remotes.count(); i != n; ++i) + { + auto name = remotes[i]; + if (!verbose) { + puts(name); + continue; + } + + auto remote = repo.remote(name); + + auto fetch = remote.url(); + if (fetch) + printf("%s\t%s (fetch)\n", name, fetch); + auto push = remote.pushurl(); + /* use fetch URL if no distinct push URL has been set */ + push = push ? push : fetch; + if (push) + printf("%s\t%s (push)\n", name, push); + } +} + +} + +int main(int argc, char *argv[]) +{ + Options opt(argc, argv); + + auto_git_initializer; + + auto path_to_repo = git::Repository::discover("."); + if (!path_to_repo) + report_error("Could not find repository"); + + Repository repo(*path_to_repo); + + switch (opt.cmd) + { + case Subcmd::add: + cmd_add(repo, opt); + break; + case Subcmd::remove: + cmd_remove(repo, opt); + break; + case Subcmd::rename: + cmd_rename(repo, opt); + break; + case Subcmd::seturl: + cmd_seturl(repo, opt); + break; + case Subcmd::show: + cmd_show(repo, opt); + break; + } +} diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 696c9ff..c15ef60 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -85,6 +85,34 @@ namespace git {} }; + struct remote_delete_error : error_t + { + explicit remote_delete_error(std::string const & name) + : error_t("Could not delete remote " + name) + {} + }; + + struct remote_create_error : error_t + { + explicit remote_create_error(const char * name, const char * url) + : error_t(internal::format("Could not create remote '%s', url='%s'", name, url)) + {} + }; + + struct remote_set_url_error : error_t + { + explicit remote_set_url_error(const char * name, const char * url) + : error_t(internal::format("Could not set url '%s' for remote '%s'", url, name)) + {} + }; + + struct remote_set_pushurl_error : error_t + { + explicit remote_set_pushurl_error(const char * name, const char * url) + : error_t(internal::format("Could not set pushurl '%s' for remote '%s'", url, name)) + {} + }; + struct commit_parent_error : error_t { explicit commit_parent_error(git_oid const & id) diff --git a/include/git2cpp/remote.h b/include/git2cpp/remote.h index bb2b31a..9bee445 100644 --- a/include/git2cpp/remote.h +++ b/include/git2cpp/remote.h @@ -6,7 +6,8 @@ namespace git { struct Remote { - const char * url() const; + const char * url() const; + const char * pushurl() const; private: friend struct Repository; diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index b96ea44..a04a946 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -16,6 +16,7 @@ #include "str_array.h" #include "submodule.h" #include "tag.h" +#include "internal/optional.h" #include #include @@ -111,6 +112,11 @@ namespace git StrArray remotes() const; Remote remote(const char * name) const; + Remote create_remote(const char * name, const char * url); + void delete_remote(const char * name); + internal::optional rename_remote(const char * old_name, const char * new_name); + void set_url (const char * name, const char * url); + void set_pushurl(const char * name, const char * url); explicit Repository(const char * dir); explicit Repository(std::string const & dir); @@ -130,6 +136,8 @@ namespace git ~Repository(); + static internal::optional discover(const char * start_path); + private: git_repository * repo_; }; diff --git a/src/remote.cpp b/src/remote.cpp index bd700c6..040660b 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -8,4 +8,9 @@ namespace git { return git_remote_url(remote_); } + + const char * Remote::pushurl() const + { + return git_remote_pushurl(remote_); + } } diff --git a/src/repo.cpp b/src/repo.cpp index b3c4253..8eb6160 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -441,4 +441,48 @@ namespace git else return Remote(remote); } + + Remote Repository::create_remote(const char * name, const char * url) + { + git_remote * remote; + if (git_remote_create(&remote, repo_, name, url)) + throw remote_create_error(name, url); + else + return Remote(remote); + } + + void Repository::delete_remote(const char * name) + { + if (git_remote_delete(repo_, name)) + throw remote_delete_error(name); + } + + internal::optional Repository::rename_remote(const char * old_name, const char * new_name) + { + git_strarray problems {}; + if (git_remote_rename(&problems, repo_, old_name, new_name)) + return StrArray(problems); + else + return internal::none; + } + + void Repository::set_url(const char * name, const char * url) + { + if (git_remote_set_url(repo_, name, url)) + throw remote_set_url_error(name, url); + } + + void Repository::set_pushurl(const char * name, const char * url) + { + if (git_remote_set_pushurl(repo_, name, url)) + throw remote_set_pushurl_error(name, url); + } + + internal::optional Repository::discover(const char * start_path) + { + git_buf buf = GIT_BUF_INIT_CONST(nullptr, 0); + if (git_repository_discover(&buf, start_path, 0, nullptr)) + return internal::none; + return std::string(buf.ptr, buf.size); + } } From b04d563a73462c591cf14edab0afeb4050f93d73 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 12 Jan 2019 16:47:21 +0300 Subject: [PATCH 121/171] + missing `noexcept` and code cleanup --- include/git2cpp/buffer.h | 2 +- include/git2cpp/commit.h | 3 ++- include/git2cpp/config.h | 2 +- include/git2cpp/error.h | 2 +- include/git2cpp/internal/format.h | 2 +- include/git2cpp/odb.h | 2 +- include/git2cpp/odb_object.h | 2 +- include/git2cpp/repo.h | 2 ++ include/git2cpp/revwalker.h | 18 ++++++++---------- include/git2cpp/status.h | 2 -- include/git2cpp/submodule.h | 4 ++-- include/git2cpp/tag.h | 2 +- libs/libgit2 | 2 +- src/commit.cpp | 2 +- src/repo.cpp | 5 +++-- 15 files changed, 26 insertions(+), 26 deletions(-) diff --git a/include/git2cpp/buffer.h b/include/git2cpp/buffer.h index 7c3f69b..f130e18 100644 --- a/include/git2cpp/buffer.h +++ b/include/git2cpp/buffer.h @@ -9,7 +9,7 @@ namespace git Buffer(Buffer const &) = delete; Buffer & operator=(Buffer const &) = delete; - Buffer(Buffer &&); + Buffer(Buffer &&) noexcept; explicit Buffer(git_buf buf) : buf_(buf) diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index 242c415..ec070f3 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -1,7 +1,6 @@ #pragma once #include "repo_fwd.h" -#include "tree.h" #include @@ -11,6 +10,8 @@ struct git_repository; namespace git { + struct Tree; + struct Commit { size_t parents_num() const; diff --git a/include/git2cpp/config.h b/include/git2cpp/config.h index 97e6705..502167b 100644 --- a/include/git2cpp/config.h +++ b/include/git2cpp/config.h @@ -17,7 +17,7 @@ namespace git : key_(std::move(key)) {} - virtual const char * what() const noexcept override + const char * what() const noexcept override { return "no such key in config"; } diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index c15ef60..24749f0 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -74,7 +74,7 @@ namespace git struct submodule_lookup_error : error_t { explicit submodule_lookup_error(std::string const & name) - : error_t("Counld not lookup submodule " + name) + : error_t("Could not lookup submodule " + name) {} }; diff --git a/include/git2cpp/internal/format.h b/include/git2cpp/internal/format.h index 2dbb7c9..a680dc8 100644 --- a/include/git2cpp/internal/format.h +++ b/include/git2cpp/internal/format.h @@ -13,7 +13,7 @@ namespace internal #ifndef USE_BOOST template - inline std::string format(const char * fmt, Args&& ... args) + std::string format(const char * fmt, Args&& ... args) { auto size = std::snprintf(nullptr, 0, fmt, args...); std::string result(size, 0); diff --git a/include/git2cpp/odb.h b/include/git2cpp/odb.h index a427bff..d4078bf 100644 --- a/include/git2cpp/odb.h +++ b/include/git2cpp/odb.h @@ -19,7 +19,7 @@ namespace git Odb(Odb const &) = delete; Odb & operator=(Odb const &) = delete; - Odb(Odb && other); + Odb(Odb && other) noexcept; private: git_odb * odb_; diff --git a/include/git2cpp/odb_object.h b/include/git2cpp/odb_object.h index 5eee662..4c69547 100644 --- a/include/git2cpp/odb_object.h +++ b/include/git2cpp/odb_object.h @@ -23,7 +23,7 @@ namespace git OdbObject(OdbObject const &) = delete; OdbObject & operator=(OdbObject const &) = delete; - OdbObject(OdbObject && other); + OdbObject(OdbObject && other) noexcept; private: git_odb_object * obj_; diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index a04a946..3aa579f 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -16,6 +16,8 @@ #include "str_array.h" #include "submodule.h" #include "tag.h" +#include "tree.h" + #include "internal/optional.h" #include diff --git a/include/git2cpp/revwalker.h b/include/git2cpp/revwalker.h index 7ed2240..22a4821 100644 --- a/include/git2cpp/revwalker.h +++ b/include/git2cpp/revwalker.h @@ -2,6 +2,7 @@ #include "commit.h" #include "tagged_mask.h" +#include namespace git { @@ -42,18 +43,15 @@ namespace git RevWalker(RevWalker const &) = delete; RevWalker & operator=(RevWalker const &) = delete; - RevWalker(RevWalker && other) - : walker_(other.walker_) - , repo_(other.repo_) - { - other.walker_ = nullptr; - } + RevWalker(RevWalker && other) noexcept + : walker_(std::exchange(other.walker_, nullptr)) + , repo_(std::exchange(other.repo_, nullptr)) + {} - RevWalker & operator=(RevWalker && other) + RevWalker & operator=(RevWalker && other) noexcept { - walker_ = other.walker_; - repo_ = other.repo_; - other.walker_ = nullptr; + std::swap(walker_, other.walker_); + std::swap(repo_, other.repo_); return *this; } diff --git a/include/git2cpp/status.h b/include/git2cpp/status.h index d5c4a39..394a4e9 100644 --- a/include/git2cpp/status.h +++ b/include/git2cpp/status.h @@ -1,8 +1,6 @@ #pragma once -#include #include -#include namespace git { diff --git a/include/git2cpp/submodule.h b/include/git2cpp/submodule.h index e801409..93aa931 100644 --- a/include/git2cpp/submodule.h +++ b/include/git2cpp/submodule.h @@ -15,8 +15,8 @@ namespace git Submodule(Submodule const &) = delete; Submodule & operator=(Submodule const &) = delete; - Submodule(Submodule &&); - Submodule & operator=(Submodule &&); + Submodule(Submodule &&) noexcept; + Submodule & operator=(Submodule &&) noexcept; enum class status : unsigned int { diff --git a/include/git2cpp/tag.h b/include/git2cpp/tag.h index 6f9a893..05168c6 100644 --- a/include/git2cpp/tag.h +++ b/include/git2cpp/tag.h @@ -12,7 +12,7 @@ namespace git struct Tag { - Tag(git_tag *); + explicit Tag(git_tag *); ~Tag(); Tag & operator=(Tag const &) = delete; diff --git a/libs/libgit2 b/libs/libgit2 index a3e53c1..99afd41 160000 --- a/libs/libgit2 +++ b/libs/libgit2 @@ -1 +1 @@ -Subproject commit a3e53c166c742da5913f776944be2c7fa94db838 +Subproject commit 99afd41f1c43c856d39e3b9572d7a2103875a771 diff --git a/src/commit.cpp b/src/commit.cpp index ca72e88..bbf0f83 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -1,9 +1,9 @@ #include "git2cpp/commit.h" #include "git2cpp/error.h" #include "git2cpp/repo.h" +#include "git2cpp/tree.h" #include -#include #include diff --git a/src/repo.cpp b/src/repo.cpp index 8eb6160..4b2d29d 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -100,7 +100,7 @@ namespace git if (git_tag_lookup(&tag, repo_, &oid)) throw tag_lookup_error(oid); else - return { tag }; + return Tag(tag); } Blob Repository::blob_lookup(git_oid const & oid) const @@ -141,6 +141,7 @@ namespace git git_status_t Repository::file_status(const char * filepath) const { + static_assert(sizeof(git_status_t) == sizeof(unsigned int)); git_status_t res; switch (git_status_file(reinterpret_cast(&res), repo_, filepath)) { @@ -196,7 +197,7 @@ namespace git } private: - git_branch_t convert(branch_type t) const + static git_branch_t convert(branch_type t) { switch (t) { From e405c30d96f1d98c398d69bd1349e0ebc966be9e Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 12 Jan 2019 18:02:42 +0300 Subject: [PATCH 122/171] fix VS 2015 compilation --- src/repo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.cpp b/src/repo.cpp index 4b2d29d..41d5f5f 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -141,7 +141,7 @@ namespace git git_status_t Repository::file_status(const char * filepath) const { - static_assert(sizeof(git_status_t) == sizeof(unsigned int)); + static_assert(sizeof(git_status_t) == sizeof(unsigned int), "sizeof(git_status_t) != sizeof(unsigned int)"); git_status_t res; switch (git_status_file(reinterpret_cast(&res), repo_, filepath)) { From 47aa4b1f8c23d661acda934c53b09bdade91282c Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 15 Jan 2019 09:02:09 +0300 Subject: [PATCH 123/171] 'checkout' exported from libgit2 examples --- CMakeLists.txt | 1 + examples/checkout.cpp | 289 +++++++++++++++++++++++++++++ include/git2cpp/annotated_commit.h | 32 ++++ include/git2cpp/reference.h | 4 + include/git2cpp/repo.h | 17 ++ src/annotated_commit.cpp | 34 ++++ src/repo.cpp | 46 +++++ 7 files changed, 423 insertions(+) create mode 100644 examples/checkout.cpp create mode 100644 include/git2cpp/annotated_commit.h create mode 100644 src/annotated_commit.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6981d33..d2d8860 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,7 @@ set(examples rev-parse general remote + checkout ) foreach (example ${examples}) diff --git a/examples/checkout.cpp b/examples/checkout.cpp new file mode 100644 index 0000000..acd8b0b --- /dev/null +++ b/examples/checkout.cpp @@ -0,0 +1,289 @@ +/* + * libgit2 "checkout" example - shows how to perform checkouts + * + * 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 "git2cpp/repo.h" +#include "git2cpp/initializer.h" +#include "git2cpp/annotated_commit.h" + +#include + +#include +#include +#include +#include + +/* Define the printf format specifer to use for size_t output */ +#if defined(_MSC_VER) || defined(__MINGW32__) +# define PRIuZ "Iu" +# define PRIxZ "Ix" +# define PRIdZ "Id" +#else +# define PRIuZ "zu" +# define PRIxZ "zx" +# define PRIdZ "zd" +#endif + +/** + * The following example demonstrates how to do checkouts with libgit2. + * + * Recognized options are : + * --force: force the checkout to happen. + * --[no-]progress: show checkout progress, on by default. + * --perf: show performance data. + */ + +namespace { + +struct args_info { + int argc; + char **argv; + int pos; +}; + +typedef struct { + int force : 1; + int progress : 1; + int perf : 1; +} checkout_options; + +[[noreturn]] void print_usage() +{ + fprintf(stderr, "usage: checkout [options] \n" + "Options are :\n" + " --git-dir: use the following git repository.\n" + " --force: force the checkout.\n" + " --[no-]progress: show checkout progress.\n" + " --perf: show performance data.\n"); + exit(1); +} + +bool match_bool_arg(int *out, args_info *args, const char *opt) +{ + const char *found = args->argv[args->pos]; + + if (!strcmp(found, opt)) { + *out = 1; + return true; + } + + if (!strncmp(found, "--no-", strlen("--no-")) && + !strcmp(found + strlen("--no-"), opt + 2)) { + *out = 0; + return true; + } + + *out = -1; + return false; +} + +[[noreturn]] 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; +} + +bool 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 false; + + if (!found[len]) { + if (args->pos + 1 == args->argc) + fatal("expected value following argument", opt); + args->pos += 1; + *out = args->argv[args->pos]; + return true; + } + + if (found[len] == '=') { + *out = found + len + 1; + return true; + } + + return false; +} + +void parse_options(const char **repo_path, checkout_options *opts, struct args_info *args) +{ + if (args->argc <= 1) + print_usage(); + + memset(opts, 0, sizeof(*opts)); + + /* Default values */ + opts->progress = 1; + + for (args->pos = 1; args->pos < args->argc; ++args->pos) { + const char *curr = args->argv[args->pos]; + int bool_arg; + + if (strcmp(curr, "--") == 0) { + break; + } else if (!strcmp(curr, "--force")) { + opts->force = 1; + } else if (match_bool_arg(&bool_arg, args, "--progress")) { + opts->progress = bool_arg; + } else if (match_bool_arg(&bool_arg, args, "--perf")) { + opts->perf = bool_arg; + } else if (match_str_arg(repo_path, args, "--git-dir")) { + continue; + } else { + break; + } + } +} + +/** + * This function is called to report progression, ie. it's called once with + * a NULL path and the number of total steps, then for each subsequent path, + * the current completed_step value. + */ +void print_checkout_progress(const char *path, size_t completed_steps, size_t total_steps, void */*payload*/) +{ + if (path == NULL) { + printf("checkout started: %" PRIuZ " steps\n", total_steps); + } else { + printf("checkout: %s %" PRIuZ "/%" PRIuZ "\n", path, completed_steps, total_steps); + } +} + +/** + * This function is called when the checkout completes, and is used to report the + * number of syscalls performed. + */ +void print_perf_data(const git_checkout_perfdata *perfdata, void* /*payload*/) +{ + printf("perf: stat: %" PRIuZ " mkdir: %" PRIuZ " chmod: %" PRIuZ "\n", + perfdata->stat_calls, perfdata->mkdir_calls, perfdata->chmod_calls); +} + +/** + * This is the main "checkout " function, responsible for performing + * a branch-based checkout. + */ +void perform_checkout_ref(git::Repository & repo, git::AnnotatedCommit const & target, checkout_options const & opts) +{ + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + + /** Setup our checkout options from the parsed options */ + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + if (opts.force) + checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + if (opts.progress) + checkout_opts.progress_cb = print_checkout_progress; + + if (opts.perf) + checkout_opts.perfdata_cb = print_perf_data; + + /** Grab the commit we're interested to move to */ + auto target_commit = repo.commit_lookup(target.commit_id()); + /** + * Perform the checkout so the workdir corresponds to what target_commit + * contains. + * + * Note that it's okay to pass a git_commit here, because it will be + * peeled to a tree. + */ + ; + if (repo.checkout_tree(target_commit, checkout_opts)) + { + fprintf(stderr, "failed to checkout tree: %s\n", giterr_last()->message); + return; + } + + /** + * Now that the checkout has completed, we have to update HEAD. + * + * Depending on the "origin" of target (ie. it's an OID or a branch name), + * we might need to detach HEAD. + */ + int err; + if (auto ref = target.commit_ref()) { + err = repo.set_head(ref); + } else { + err = repo.set_head_detached(target); + } + if (err != 0) { + fprintf(stderr, "failed to update HEAD reference: %s\n", giterr_last()->message); + } +} + +git::AnnotatedCommit resolve_refish(git::Repository const & repo, const char *refish) +{ + if (auto ref = repo.dwim(refish)) + return repo.annotated_commit_from_ref(ref); + + auto obj = repo.revparse_single(refish); + return repo.annotated_commit_lookup(obj.single()->id()); +} + +} + +/** That example's entry point */ +int main(int argc, char **argv) +{ + args_info args { argc, argv }; + checkout_options opts; + const char *path = "."; + + /** Parse our command line options */ + parse_options(&path, &opts, &args); + + /** Initialize the library */ + auto_git_initializer; + + git::Repository repo(path); + + /** Make sure we're not about to checkout while something else is going on */ + auto const state = repo.state(); + if (state != GIT_REPOSITORY_STATE_NONE) { + fprintf(stderr, "repository is in unexpected state %d\n", state); + return EXIT_FAILURE; + } + + if (args.pos >= args.argc) { + fprintf(stderr, "unhandled\n"); + return EXIT_FAILURE; + } + + if (strcmp("--", args.argv[args.pos])) + { + /** + * Try to checkout the given path + */ + + fprintf(stderr, "unhandled path-based checkout\n"); + return EXIT_FAILURE; + } + + /** + * Try to resolve a "refish" argument to a target libgit2 can use + */ + auto checkout_target = resolve_refish(repo, args.argv[args.pos]); + perform_checkout_ref(repo, checkout_target, opts); +} diff --git a/include/git2cpp/annotated_commit.h b/include/git2cpp/annotated_commit.h new file mode 100644 index 0000000..d2ca819 --- /dev/null +++ b/include/git2cpp/annotated_commit.h @@ -0,0 +1,32 @@ +#pragma once + +struct git_annotated_commit; +struct git_oid; + +namespace git +{ + struct AnnotatedCommit + { + AnnotatedCommit(git_annotated_commit * commit) + : commit_(commit) + {} + + AnnotatedCommit(AnnotatedCommit const &) = delete; + AnnotatedCommit& operator = (AnnotatedCommit const &) = delete; + + AnnotatedCommit(AnnotatedCommit &&) noexcept; + AnnotatedCommit& operator = (AnnotatedCommit&&) noexcept; + + ~AnnotatedCommit(); + + git_oid const & commit_id() const; + char const * commit_ref() const; + + private: + friend struct Repository; + git_annotated_commit * ptr() const { return commit_; } + + private: + git_annotated_commit * commit_; + }; +} diff --git a/include/git2cpp/reference.h b/include/git2cpp/reference.h index bd09360..a9d7bf4 100644 --- a/include/git2cpp/reference.h +++ b/include/git2cpp/reference.h @@ -29,6 +29,10 @@ namespace git Reference(Reference &&) noexcept; Reference & operator=(Reference && other) noexcept; + private: + friend struct Repository; + git_reference * ptr() const { return ref_; } + private: git_reference * ref_; }; diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 3aa579f..65f14d7 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -45,6 +45,8 @@ namespace git ~FileDiffHandler() = default; }; + struct AnnotatedCommit; + struct Repository { Commit commit_lookup(git_oid const & oid) const; @@ -78,10 +80,18 @@ namespace git Status status(Status::Options const &) const; + git_repository_state_t state() const; + StrArray reference_list() const; std::vector branches(branch_type) const; + /// @return can be empty + Reference dwim(const char * shorthand) const; + + AnnotatedCommit annotated_commit_from_ref(Reference const &) const; + AnnotatedCommit annotated_commit_lookup(git_oid const &) const; + bool is_bare() const; Reference head() const; @@ -120,6 +130,13 @@ namespace git void set_url (const char * name, const char * url); void set_pushurl(const char * name, const char * url); + /// @return raw error code + int checkout_tree(Commit const &, git_checkout_options const &); + + /// @return raw error code + int set_head(char const* ref); + int set_head_detached(AnnotatedCommit const&); + explicit Repository(const char * dir); explicit Repository(std::string const & dir); diff --git a/src/annotated_commit.cpp b/src/annotated_commit.cpp new file mode 100644 index 0000000..147f161 --- /dev/null +++ b/src/annotated_commit.cpp @@ -0,0 +1,34 @@ +#include "git2cpp/annotated_commit.h" + +#include + +#include + +namespace git +{ + AnnotatedCommit::AnnotatedCommit(AnnotatedCommit && other) noexcept + : commit_(std::exchange(other.commit_, nullptr)) + { + } + + AnnotatedCommit& AnnotatedCommit::operator=(AnnotatedCommit && other) noexcept + { + std::swap(commit_, other.commit_); + return *this; + } + + AnnotatedCommit::~AnnotatedCommit() + { + git_annotated_commit_free(commit_); + } + + git_oid const& AnnotatedCommit::commit_id() const + { + return *git_annotated_commit_id(commit_); + } + + char const* AnnotatedCommit::commit_ref() const + { + return git_annotated_commit_ref(commit_); + } +} diff --git a/src/repo.cpp b/src/repo.cpp index 41d5f5f..52d534b 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -1,5 +1,6 @@ #include "git2cpp/repo.h" +#include "git2cpp/annotated_commit.h" #include "git2cpp/error.h" #include "git2cpp/internal/optional.h" @@ -225,6 +226,31 @@ namespace git return res; } + Reference Repository::dwim(const char* shorthand) const + { + git_reference * ref; + if (git_reference_dwim(&ref, repo_, shorthand) == GIT_OK) + return Reference(ref); + else + return Reference(); + } + + AnnotatedCommit Repository::annotated_commit_from_ref(Reference const& ref) const + { + git_annotated_commit * commit; + const auto err = git_annotated_commit_from_ref(&commit, repo_, ref.ptr()); + assert(err == GIT_OK); + return AnnotatedCommit(commit); + } + + AnnotatedCommit Repository::annotated_commit_lookup(git_oid const& id) const + { + git_annotated_commit * commit; + const auto err = git_annotated_commit_lookup(&commit, repo_, &id); + assert(err == GIT_OK); + return AnnotatedCommit(commit); + } + RevWalker Repository::rev_walker() const { git_revwalk * walker; @@ -275,6 +301,11 @@ namespace git return Status(repo_, opts); } + git_repository_state_t Repository::state() const + { + return static_cast(git_repository_state(repo_)); + } + StrArray Repository::reference_list() const { git_strarray str_array; @@ -479,6 +510,21 @@ namespace git throw remote_set_pushurl_error(name, url); } + int Repository::checkout_tree(Commit const& commit, git_checkout_options const& options) + { + return git_checkout_tree(repo_, reinterpret_cast(commit.ptr()), &options); + } + + int Repository::set_head(char const* ref) + { + return git_repository_set_head(repo_, ref); + } + + int Repository::set_head_detached(AnnotatedCommit const& commit) + { + return git_repository_set_head_detached_from_annotated(repo_, commit.ptr()); + } + internal::optional Repository::discover(const char * start_path) { git_buf buf = GIT_BUF_INIT_CONST(nullptr, 0); From 72dada9854e836171682142ef5d76872aff5353b Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 11 Feb 2019 12:41:26 +0300 Subject: [PATCH 124/171] + StrArray move assignment --- include/git2cpp/str_array.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/git2cpp/str_array.h b/include/git2cpp/str_array.h index ab63ea5..5345de5 100644 --- a/include/git2cpp/str_array.h +++ b/include/git2cpp/str_array.h @@ -21,6 +21,12 @@ namespace git std::memset(&other.str_array_, 0, sizeof(git_strarray)); } + StrArray& operator =(StrArray && other) noexcept + { + std::swap(str_array_, other.str_array_); + return *this; + } + size_t count() const { return str_array_.count; } const char * operator[](size_t i) const From ccf9eac7ccac190d64e88c0a2d3ed4ed3f602817 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 25 Feb 2019 09:16:04 +0300 Subject: [PATCH 125/171] use std::unique_ptr where possible --- include/git2cpp/annotated_commit.h | 15 ++-- include/git2cpp/blob.h | 15 ++-- include/git2cpp/commit.h | 18 ++-- include/git2cpp/config.h | 9 +- include/git2cpp/diff.h | 24 +---- include/git2cpp/index.h | 11 +-- include/git2cpp/object.h | 15 ++-- include/git2cpp/odb.h | 15 ++-- include/git2cpp/odb_object.h | 17 +--- include/git2cpp/reference.h | 13 +-- include/git2cpp/repo.h | 11 +-- include/git2cpp/revwalker.h | 20 +---- include/git2cpp/signature.h | 10 ++- include/git2cpp/status.h | 16 ++-- include/git2cpp/submodule.h | 17 ++-- include/git2cpp/tag.h | 10 +-- include/git2cpp/tree.h | 31 ++----- src/annotated_commit.cpp | 25 ++---- src/blob.cpp | 18 ++-- src/buffer.cpp | 2 +- src/commit.cpp | 45 +++------- src/config.cpp | 12 +-- src/diff.cpp | 16 ++-- src/index.cpp | 48 +++++----- src/object.cpp | 25 ++---- src/odb.cpp | 15 ++-- src/odb_object.cpp | 12 +-- src/reference.cpp | 23 ++--- src/repo.cpp | 136 ++++++++++++++--------------- src/revwalker.cpp | 18 ++-- src/signature.cpp | 15 +++- src/status.cpp | 24 ++--- src/submodule.cpp | 6 +- src/tag.cpp | 22 ++--- src/tree.cpp | 43 ++------- 35 files changed, 284 insertions(+), 488 deletions(-) diff --git a/include/git2cpp/annotated_commit.h b/include/git2cpp/annotated_commit.h index d2ca819..b266861 100644 --- a/include/git2cpp/annotated_commit.h +++ b/include/git2cpp/annotated_commit.h @@ -1,5 +1,7 @@ #pragma once +#include + struct git_annotated_commit; struct git_oid; @@ -11,22 +13,15 @@ namespace git : commit_(commit) {} - AnnotatedCommit(AnnotatedCommit const &) = delete; - AnnotatedCommit& operator = (AnnotatedCommit const &) = delete; - - AnnotatedCommit(AnnotatedCommit &&) noexcept; - AnnotatedCommit& operator = (AnnotatedCommit&&) noexcept; - - ~AnnotatedCommit(); - git_oid const & commit_id() const; char const * commit_ref() const; private: friend struct Repository; - git_annotated_commit * ptr() const { return commit_; } + git_annotated_commit * ptr() const { return commit_.get(); } private: - git_annotated_commit * commit_; + struct Destroy { void operator() (git_annotated_commit*) const; }; + std::unique_ptr commit_; }; } diff --git a/include/git2cpp/blob.h b/include/git2cpp/blob.h index 61d8bd5..87efcf9 100644 --- a/include/git2cpp/blob.h +++ b/include/git2cpp/blob.h @@ -1,32 +1,27 @@ #pragma once #include +#include struct git_blob; -struct git_repository; -struct git_oid; namespace git { struct Blob { explicit Blob(git_blob *); - ~Blob(); std::size_t size() const; const void * content() const; - Blob & operator=(Blob const &) = delete; - Blob(Blob const &) = delete; - - Blob(Blob &&) noexcept; - private: friend struct Repository; - git_blob const * ptr() const { return blob_; } + git_blob const * ptr() const { return blob_.get(); } private: - git_blob * blob_; + struct Destroy { void operator() (git_blob *) const; }; + + std::unique_ptr blob_; }; } diff --git a/include/git2cpp/commit.h b/include/git2cpp/commit.h index ec070f3..01700ad 100644 --- a/include/git2cpp/commit.h +++ b/include/git2cpp/commit.h @@ -4,6 +4,8 @@ #include +#include + struct git_commit; struct git_oid; struct git_repository; @@ -37,22 +39,16 @@ namespace git Repository const & repo() const { return *repo_; } Commit(git_commit *, Repository const &); - - Commit(); - Commit(Commit &&) noexcept; - Commit & operator=(Commit &&) noexcept; - Commit(Commit const &) = delete; - Commit & operator=(Commit const &) = delete; - - ~Commit(); + Commit() = default; private: friend struct Repository; - git_commit const * ptr() const { return commit_; } + git_commit const * ptr() const { return commit_.get(); } private: - git_commit * commit_; - Repository const * repo_; + struct Destroy { void operator() (git_commit*) const; }; + std::unique_ptr commit_; + Repository const * repo_ = nullptr; }; } diff --git a/include/git2cpp/config.h b/include/git2cpp/config.h index 502167b..51cdb9b 100644 --- a/include/git2cpp/config.h +++ b/include/git2cpp/config.h @@ -1,6 +1,8 @@ #pragma once +#include #include +#include struct git_config; @@ -9,7 +11,6 @@ namespace git struct Config { explicit Config(std::string const & filename); - ~Config(); struct no_such_key_error : std::exception { @@ -32,10 +33,8 @@ namespace git int get_int(const char * key) const; - Config(Config const &) = delete; - Config & operator=(Config const &) = delete; - private: - git_config * cfg_; + struct Destroy { void operator() (git_config*) const; }; + std::unique_ptr cfg_; }; } diff --git a/include/git2cpp/diff.h b/include/git2cpp/diff.h index e6a4e81..9514e86 100644 --- a/include/git2cpp/diff.h +++ b/include/git2cpp/diff.h @@ -39,13 +39,6 @@ namespace git { struct Stats { - ~Stats(); - - Stats(Stats const &) = delete; - Stats & operator=(Stats const &) = delete; - - Stats(Stats &&) noexcept; - Buffer to_buf(diff::stats::format::type, size_t width) const; private: @@ -56,7 +49,8 @@ namespace git {} private: - git_diff_stats * stats_; + struct Destroy { void operator() (git_diff_stats*) const; }; + std::unique_ptr stats_; }; size_t deltas_num() const; @@ -74,18 +68,8 @@ namespace git : diff_(diff) {} - ~Diff(); - - Diff(Diff const &) = delete; - Diff & operator=(Diff const &) = delete; - - Diff(Diff && other) noexcept - : diff_(other.diff_) - { - other.diff_ = nullptr; - } - private: - git_diff * diff_; + struct Destroy { void operator() (git_diff *) const; }; + std::unique_ptr diff_; }; } diff --git a/include/git2cpp/index.h b/include/git2cpp/index.h index 8bee61b..4d56e39 100644 --- a/include/git2cpp/index.h +++ b/include/git2cpp/index.h @@ -16,8 +16,6 @@ namespace git explicit Index(git_repository * repo); explicit Index(const char * dir); - ~Index(); - size_t entrycount() const; git_index_entry const * operator[](size_t i) const; @@ -37,13 +35,8 @@ namespace git void write() const; - Index(Index const &) = delete; - Index & operator=(Index const &) = delete; - - Index(Index &&) noexcept; - Index & operator=(Index &&) noexcept; - private: - git_index * index_; + struct Destroy { void operator() (git_index*) const; }; + std::unique_ptr index_; }; } diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index de4c5b3..7ca7785 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -1,6 +1,7 @@ #pragma once #include +#include struct git_object; struct git_oid; @@ -18,12 +19,10 @@ namespace git struct Object { - Object() {} - + Object() = default; Object(git_object * obj, Repository const &); - ~Object(); - explicit operator bool() const { return obj_ != nullptr; } + explicit operator bool() const { return obj_.operator bool(); } git_otype type() const; git_oid const & id() const; @@ -38,13 +37,9 @@ namespace git Blob to_blob() /*&&*/; Tag to_tag() /*&&*/; - Object(Object const &) = delete; - Object & operator=(Object const &) = delete; - - Object(Object && other) noexcept; - private: - git_object * obj_ = nullptr; + struct Destroy { void operator() (git_object*) const; }; + std::unique_ptr obj_; Repository const * repo_ = nullptr; }; } diff --git a/include/git2cpp/odb.h b/include/git2cpp/odb.h index d4078bf..f34c1a7 100644 --- a/include/git2cpp/odb.h +++ b/include/git2cpp/odb.h @@ -10,18 +10,15 @@ namespace git { struct Odb { - explicit Odb(git_repository * repo); - ~Odb(); - OdbObject read(git_oid const & oid) const; - git_oid write(const void * data, size_t len, git_otype type); - - Odb(Odb const &) = delete; - Odb & operator=(Odb const &) = delete; + git_oid write(const void * data, size_t len, git_object_t type); - Odb(Odb && other) noexcept; + private: + friend struct Repository; + explicit Odb(git_repository * repo); private: - git_odb * odb_; + struct Destroy { void operator() (git_odb* odb) const; }; + std::unique_ptr odb_; }; } diff --git a/include/git2cpp/odb_object.h b/include/git2cpp/odb_object.h index 4c69547..b3b5b21 100644 --- a/include/git2cpp/odb_object.h +++ b/include/git2cpp/odb_object.h @@ -1,10 +1,7 @@ #pragma once -#include - -extern "C" { #include -} +#include namespace git { @@ -14,18 +11,12 @@ namespace git : obj_(obj) {} - ~OdbObject(); - - git_otype type() const; + git_object_t type() const; unsigned char const * data() const; size_t size() const; - OdbObject(OdbObject const &) = delete; - OdbObject & operator=(OdbObject const &) = delete; - - OdbObject(OdbObject && other) noexcept; - private: - git_odb_object * obj_; + struct Destroy { void operator() (git_odb_object *) const; }; + std::unique_ptr obj_; }; } diff --git a/include/git2cpp/reference.h b/include/git2cpp/reference.h index a9d7bf4..d9cbb2b 100644 --- a/include/git2cpp/reference.h +++ b/include/git2cpp/reference.h @@ -1,6 +1,7 @@ #pragma once #include +#include struct git_reference; struct git_oid; @@ -14,7 +15,6 @@ namespace git {} explicit Reference(git_reference * ref); - ~Reference(); explicit operator bool() const { return ref_ != nullptr; } @@ -23,17 +23,12 @@ namespace git git_oid const & target() const; const char * symbolic_target() const; - Reference & operator=(Reference const &) = delete; - Reference(Reference const &) = delete; - - Reference(Reference &&) noexcept; - Reference & operator=(Reference && other) noexcept; - private: friend struct Repository; - git_reference * ptr() const { return ref_; } + git_reference * ptr() const { return ref_.get(); } private: - git_reference * ref_; + struct Destroy { void operator() (git_reference*) const; }; + std::unique_ptr ref_; }; } diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 65f14d7..d873525 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -147,18 +147,11 @@ namespace git Repository(const char * dir, init_tag, git_repository_init_options opts); Repository(std::string const & dir, init_tag); - Repository(Repository const &) = delete; - Repository & operator=(Repository const &) = delete; - - Repository(Repository &&) noexcept; - Repository & operator=(Repository &&) noexcept; - - ~Repository(); - static internal::optional discover(const char * start_path); private: - git_repository * repo_; + struct Destroy { void operator() (git_repository *) const; }; + std::unique_ptr repo_; }; Object revparse_single(Repository const & repo, const char * spec); diff --git a/include/git2cpp/revwalker.h b/include/git2cpp/revwalker.h index 22a4821..ac426eb 100644 --- a/include/git2cpp/revwalker.h +++ b/include/git2cpp/revwalker.h @@ -28,8 +28,6 @@ namespace git , repo_(&repo) {} - ~RevWalker(); - void sort(revwalker::sorting::type); void simplify_first_parent(); @@ -40,23 +38,9 @@ namespace git Commit next() const; bool next(char * id_buffer) const; - RevWalker(RevWalker const &) = delete; - RevWalker & operator=(RevWalker const &) = delete; - - RevWalker(RevWalker && other) noexcept - : walker_(std::exchange(other.walker_, nullptr)) - , repo_(std::exchange(other.repo_, nullptr)) - {} - - RevWalker & operator=(RevWalker && other) noexcept - { - std::swap(walker_, other.walker_); - std::swap(repo_, other.repo_); - return *this; - } - private: - git_revwalk * walker_; + struct Destroy { void operator() (git_revwalk*) const; }; + std::unique_ptr walker_; Repository const * repo_; }; } diff --git a/include/git2cpp/signature.h b/include/git2cpp/signature.h index 4992cac..3903287 100644 --- a/include/git2cpp/signature.h +++ b/include/git2cpp/signature.h @@ -7,14 +7,16 @@ namespace git { struct Signature { - git_signature const * ptr() const { return sig_; } + Signature(const char * name, const char * email, git_time_t time, int offset); + private: + friend struct Repository; explicit Signature(git_repository * repo); - Signature(const char * name, const char * email, git_time_t time, int offset); - ~Signature(); + git_signature const * ptr() const { return sig_.get(); } private: - git_signature * sig_; + struct Destroy { void operator() (git_signature*) const; }; + std::unique_ptr sig_; }; } diff --git a/include/git2cpp/status.h b/include/git2cpp/status.h index 394a4e9..7372da9 100644 --- a/include/git2cpp/status.h +++ b/include/git2cpp/status.h @@ -2,6 +2,8 @@ #include +#include + namespace git { struct Status @@ -38,19 +40,15 @@ namespace git git_status_options opts_; }; - Status(git_repository * repo, Options const & opts); - ~Status(); - size_t entrycount() const; git_status_entry const & operator[](size_t i) const; - Status(Status const &) = delete; - Status & operator=(Status const &) = delete; - - Status(Status &&) noexcept; - Status & operator=(Status &&) noexcept; + private: + friend struct Repository; + Status(git_repository * repo, Options const & opts); private: - git_status_list * status_; + struct Destroy { void operator() (git_status_list*) const; }; + std::unique_ptr status_; }; } diff --git a/include/git2cpp/submodule.h b/include/git2cpp/submodule.h index 93aa931..6877538 100644 --- a/include/git2cpp/submodule.h +++ b/include/git2cpp/submodule.h @@ -1,6 +1,7 @@ #pragma once #include +#include struct git_submodule; struct git_repository; @@ -9,15 +10,6 @@ namespace git { struct Submodule { - Submodule(git_submodule *, git_repository *); - ~Submodule(); - - Submodule(Submodule const &) = delete; - Submodule & operator=(Submodule const &) = delete; - - Submodule(Submodule &&) noexcept; - Submodule & operator=(Submodule &&) noexcept; - enum class status : unsigned int { in_head = GIT_SUBMODULE_STATUS_IN_HEAD, @@ -41,7 +33,12 @@ namespace git status get_status() const; private: - git_submodule * sm_; + friend struct Repository; + Submodule(git_submodule *, git_repository *); + + private: + struct Destroy { void operator() (git_submodule*) const; }; + std::unique_ptr sm_; git_repository * repo_; }; } diff --git a/include/git2cpp/tag.h b/include/git2cpp/tag.h index 05168c6..bf6aab1 100644 --- a/include/git2cpp/tag.h +++ b/include/git2cpp/tag.h @@ -1,6 +1,7 @@ #pragma once #include +#include struct git_tag; struct git_oid; @@ -13,12 +14,6 @@ namespace git struct Tag { explicit Tag(git_tag *); - ~Tag(); - - Tag & operator=(Tag const &) = delete; - Tag(Tag const &) = delete; - - Tag(Tag &&) noexcept; Object target(Repository const &) const; @@ -30,6 +25,7 @@ namespace git git_signature const * tagger() const; private: - git_tag * tag_; + struct Destroy { void operator() (git_tag*) const; }; + std::unique_ptr tag_; }; } diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index 7b1509e..05e47cd 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -31,14 +31,6 @@ namespace git struct OwnedEntry { - ~OwnedEntry(); - - OwnedEntry(OwnedEntry const &) = delete; - OwnedEntry & operator=(OwnedEntry const &) = delete; - - OwnedEntry(OwnedEntry &&) noexcept; - OwnedEntry & operator=(OwnedEntry &&) noexcept; - Tree to_tree() /*&&*/; private: @@ -47,15 +39,16 @@ namespace git OwnedEntry(git_tree_entry * entry, Repository const & repo); - git_tree_entry const * ptr() const { return entry_; } + git_tree_entry const * ptr() const { return entry_.get(); } private: - git_tree_entry * entry_; + struct Destroy { void operator() (git_tree_entry*) const; }; + std::unique_ptr entry_; Repository const * repo_; }; - git_tree const * ptr() const { return tree_; } - git_tree * ptr() { return tree_; } + git_tree const * ptr() const { return tree_.get(); } + git_tree * ptr() { return tree_.get(); } int pathspec_match(uint32_t flags, Pathspec const & ps); @@ -69,19 +62,13 @@ namespace git Tree(git_tree *, Repository const &); - Tree(); - ~Tree(); - - Tree(Tree &&) noexcept; - Tree & operator=(Tree &&) noexcept; - - Tree(Tree const &) = delete; - Tree & operator=(Tree const &) = delete; + Tree() = default; explicit operator bool() const { return tree_ != nullptr; } private: - git_tree * tree_; - Repository const * repo_; + struct Destroy { void operator() (git_tree*) const; }; + std::unique_ptr tree_; + Repository const * repo_ = nullptr; }; } diff --git a/src/annotated_commit.cpp b/src/annotated_commit.cpp index 147f161..8eecef3 100644 --- a/src/annotated_commit.cpp +++ b/src/annotated_commit.cpp @@ -2,33 +2,20 @@ #include -#include - namespace git { - AnnotatedCommit::AnnotatedCommit(AnnotatedCommit && other) noexcept - : commit_(std::exchange(other.commit_, nullptr)) - { - } - - AnnotatedCommit& AnnotatedCommit::operator=(AnnotatedCommit && other) noexcept - { - std::swap(commit_, other.commit_); - return *this; - } - - AnnotatedCommit::~AnnotatedCommit() + git_oid const& AnnotatedCommit::commit_id() const { - git_annotated_commit_free(commit_); + return *git_annotated_commit_id(ptr()); } - git_oid const& AnnotatedCommit::commit_id() const + char const* AnnotatedCommit::commit_ref() const { - return *git_annotated_commit_id(commit_); + return git_annotated_commit_ref(ptr()); } - char const* AnnotatedCommit::commit_ref() const + void AnnotatedCommit::Destroy::operator()(git_annotated_commit* commit) const { - return git_annotated_commit_ref(commit_); + git_annotated_commit_free(commit); } } diff --git a/src/blob.cpp b/src/blob.cpp index 38c799b..4b31df7 100644 --- a/src/blob.cpp +++ b/src/blob.cpp @@ -9,24 +9,18 @@ namespace git { } - Blob::Blob(Blob && other) noexcept - : blob_(other.blob_) - { - other.blob_ = nullptr; - } - - Blob::~Blob() + std::size_t Blob::size() const { - git_blob_free(blob_); + return static_cast(git_blob_rawsize(ptr())); } - std::size_t Blob::size() const + const void * Blob::content() const { - return static_cast(git_blob_rawsize(blob_)); + return git_blob_rawcontent(ptr()); } - const void * Blob::content() const + void Blob::Destroy::operator()(git_blob * blob) const { - return git_blob_rawcontent(blob_); + git_blob_free(blob); } } diff --git a/src/buffer.cpp b/src/buffer.cpp index 5b49529..8d15189 100644 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -4,6 +4,6 @@ namespace git { Buffer::~Buffer() { - git_buf_free(&buf_); + git_buf_dispose(&buf_); } } diff --git a/src/commit.cpp b/src/commit.cpp index bbf0f83..760d8eb 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -5,8 +5,6 @@ #include -#include - namespace git { Commit::Commit(git_commit * commit, Repository const & repo) @@ -15,29 +13,14 @@ namespace git { } - Commit::Commit() - : commit_(nullptr) - , repo_(nullptr) - { - } - - Commit::Commit(Commit && other) noexcept - : commit_(std::exchange(other.commit_, nullptr)) - , repo_(other.repo_) - { - } - - Commit & Commit::operator=(Commit && other) noexcept - { - std::swap(commit_, other.commit_); - std::swap(repo_, other.repo_); - return *this; + void Commit::Destroy::operator()(git_commit* commit) const { + git_commit_free(commit); } Commit Commit::parent(size_t i) const { git_commit * parent; - if (git_commit_parent(&parent, commit_, static_cast(i))) + if (git_commit_parent(&parent, ptr(), static_cast(i))) throw commit_parent_error(id()); return Commit(parent, *repo_); } @@ -45,60 +28,58 @@ namespace git Tree Commit::tree() const { git_tree * tree; - if (git_commit_tree(&tree, commit_)) + if (git_commit_tree(&tree, ptr())) throw commit_tree_error(id()); return Tree(tree, *repo_); } size_t Commit::parents_num() const { - return git_commit_parentcount(commit_); + return git_commit_parentcount(ptr()); } git_oid const & Commit::id() const { - return *git_commit_id(commit_); + return *git_commit_id(ptr()); } git_oid const & Commit::tree_id() const { - return *git_commit_tree_id(commit_); + return *git_commit_tree_id(ptr()); } git_oid const & Commit::parent_id(size_t i) const { - return *git_commit_parent_id(commit_, static_cast(i)); + return *git_commit_parent_id(ptr(), static_cast(i)); } git_signature const * Commit::author() const { - return git_commit_author(commit_); + return git_commit_author(ptr()); } git_signature const * Commit::commiter() const { - return git_commit_committer(commit_); + return git_commit_committer(ptr()); } const char * Commit::message() const { - return git_commit_message(commit_); + return git_commit_message(ptr()); } const char * Commit::summary() const { - return git_commit_summary(commit_); + return git_commit_summary(commit_.get()); } git_time_t Commit::time() const { - return git_commit_time(commit_); + return git_commit_time(ptr()); } git_oid Commit::merge_base(size_t p1, size_t p2) const { return repo_->merge_base(parent_id(p1), parent_id(p2)); } - - Commit::~Commit() { git_commit_free(commit_); } } diff --git a/src/config.cpp b/src/config.cpp index 25db76d..cdae46e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -7,19 +7,21 @@ namespace git { Config::Config(std::string const & filename) { - if (git_config_open_ondisk(&cfg_, filename.c_str())) + git_config * cfg; + if (git_config_open_ondisk(&cfg, filename.c_str())) throw config_open_error(); + cfg_.reset(cfg); } - Config::~Config() + void Config::Destroy::operator()(git_config* cfg) const { - git_config_free(cfg_); + git_config_free(cfg); } std::string Config::operator[](const char * key) const { const char * res; - if (git_config_get_string(&res, cfg_, key)) + if (git_config_get_string(&res, cfg_.get(), key)) throw no_such_key_error(key); return res; } @@ -27,7 +29,7 @@ namespace git int Config::get_int(const char * key) const { int res; - if (git_config_get_int32(&res, cfg_, key)) + if (git_config_get_int32(&res, cfg_.get(), key)) throw no_such_key_error(key); return res; } diff --git a/src/diff.cpp b/src/diff.cpp index dccb1ae..0ff4464 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -67,41 +67,41 @@ namespace git } } - Diff::~Diff() { git_diff_free(diff_); } + void Diff::Destroy::operator() (git_diff* diff) const { git_diff_free(diff); } void Diff::find_similar(git_diff_find_options & findopts) { - git_diff_find_similar(diff_, &findopts); + git_diff_find_similar(diff_.get(), &findopts); } size_t Diff::deltas_num() const { - return git_diff_num_deltas(diff_); + return git_diff_num_deltas(diff_.get()); } void Diff::print(diff::format f, print_callback_t print_callback) const { - git_diff_print(diff_, convert(f), &apply_callback, &print_callback); + git_diff_print(diff_.get(), convert(f), &apply_callback, &print_callback); } Diff::Stats Diff::stats() const { git_diff_stats * stats; - if (git_diff_get_stats(&stats, diff_)) + if (git_diff_get_stats(&stats, diff_.get())) throw error_t("git_diff_get_stats fail"); else return Stats(stats); } - Diff::Stats::~Stats() + void Diff::Stats::Destroy::operator()(git_diff_stats* stats) const { - git_diff_stats_free(stats_); + git_diff_stats_free(stats); } Buffer Diff::Stats::to_buf(diff::stats::format::type format, size_t width) const { git_buf buf = GIT_BUF_INIT_CONST(nullptr, 0); - if (git_diff_stats_to_buf(&buf, stats_, git_diff_stats_format_t(format.value()), width)) + if (git_diff_stats_to_buf(&buf, stats_.get(), git_diff_stats_format_t(format.value()), width)) throw error_t("git_diff_stats_to_buf fail"); else return Buffer(buf); diff --git a/src/index.cpp b/src/index.cpp index cfa82af..0fd6197 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -10,42 +10,34 @@ namespace git { Index::Index(git_repository * repo) { - if (git_repository_index(&index_, repo) < 0) + git_index * index; + if (git_repository_index(&index, repo) < 0) throw index_open_error(); + index_.reset(index); } Index::Index(const char * dir) { - if (git_index_open(&index_, dir)) + git_index * index; + if (git_index_open(&index, dir)) throw index_open_error(); - git_index_read(index_, true); + index_.reset(index); + git_index_read(index, true); } - Index::~Index() + void Index::Destroy::operator()(git_index* index) const { - git_index_free(index_); - } - - Index::Index(Index && other) noexcept - : index_(other.index_) - { - other.index_ = nullptr; - } - - Index & Index::operator=(Index && other) noexcept - { - std::swap(index_, other.index_); - return *this; + git_index_free(index); } size_t Index::entrycount() const { - return git_index_entrycount(index_); + return git_index_entrycount(index_.get()); } git_index_entry const * Index::operator[](size_t i) const { - return git_index_get_byindex(index_, i); + return git_index_get_byindex(index_.get(), i); } namespace @@ -60,28 +52,28 @@ namespace git void Index::update_all(git_strarray const & pathspec, matched_path_callback_t cb) { int res = cb - ? git_index_update_all(index_, &pathspec, &apply_callback, &cb) - : git_index_update_all(index_, &pathspec, nullptr, nullptr); + ? git_index_update_all(index_.get(), &pathspec, &apply_callback, &cb) + : git_index_update_all(index_.get(), &pathspec, nullptr, nullptr); assert(res == 0); } void Index::add_all(git_strarray const & pathspec, matched_path_callback_t cb, unsigned int flags) { int res = cb - ? git_index_add_all(index_, &pathspec, flags, &apply_callback, &cb) - : git_index_add_all(index_, &pathspec, flags, nullptr, nullptr); + ? git_index_add_all(index_.get(), &pathspec, flags, &apply_callback, &cb) + : git_index_add_all(index_.get(), &pathspec, flags, nullptr, nullptr); assert(res == 0); } void Index::clear() { - int res = git_index_clear(index_); + int res = git_index_clear(index_.get()); assert(res == 0); } void Index::add_path(const char * path) { - int res = git_index_add_bypath(index_, path); + int res = git_index_add_bypath(index_.get(), path); assert(res == 0); } @@ -92,7 +84,7 @@ namespace git void Index::remove_path(const char * path) { - int res = git_index_remove_bypath(index_, path); + int res = git_index_remove_bypath(index_.get(), path); assert(res == 0); } @@ -103,14 +95,14 @@ namespace git void Index::write() const { - if (git_index_write(index_)) + if (git_index_write(index_.get())) throw index_write_error(); } git_oid Index::write_tree() const { git_oid res; - if (git_index_write_tree(&res, index_) < 0) + if (git_index_write_tree(&res, index_.get()) < 0) throw index_write_tree_error(); return res; } diff --git a/src/object.cpp b/src/object.cpp index 0ad0121..d2981e8 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -16,33 +16,26 @@ namespace git { } - Object::~Object() + void Object::Destroy::operator()(git_object* obj) const { - git_object_free(obj_); - } - - Object::Object(Object && other) noexcept - : obj_(other.obj_) - , repo_(other.repo_) - { - other.obj_ = nullptr; + git_object_free(obj); } git_otype Object::type() const { - return git_object_type(obj_); + return git_object_type(obj_.get()); } git_oid const & Object::id() const { - return *git_object_id(obj_); + return *git_object_id(obj_.get()); } #define DEFINE_METHOD_AS(type_name, enum_element) \ git_##type_name const * Object::as_##type_name() const \ { \ assert(type() == GIT_OBJ_##enum_element); \ - return reinterpret_cast(obj_); \ + return reinterpret_cast(obj_.get()); \ } DEFINE_METHOD_AS(blob, BLOB) @@ -55,7 +48,7 @@ namespace git Tree Object::to_tree() /*&&*/ { assert(type() == GIT_OBJ_TREE); - Tree res(reinterpret_cast(obj_), *repo_); + Tree res(reinterpret_cast(obj_.get()), *repo_); obj_ = nullptr; return res; } @@ -63,7 +56,7 @@ namespace git Commit Object::to_commit() /*&&*/ { assert(type() == GIT_OBJ_COMMIT); - Commit res(reinterpret_cast(obj_), *repo_); + Commit res(reinterpret_cast(obj_.get()), *repo_); obj_ = nullptr; return res; } @@ -71,7 +64,7 @@ namespace git Blob Object::to_blob() /*&&*/ { assert(type() == GIT_OBJ_BLOB); - Blob res(reinterpret_cast(obj_)); + Blob res(reinterpret_cast(obj_.get())); obj_ = nullptr; return res; } @@ -79,7 +72,7 @@ namespace git Tag Object::to_tag() /*&&*/ { assert(type() == GIT_OBJ_TAG); - Tag res(reinterpret_cast(obj_)); + Tag res(reinterpret_cast(obj_.get())); obj_ = nullptr; return res; } diff --git a/src/odb.cpp b/src/odb.cpp index 61230cc..5db95fd 100644 --- a/src/odb.cpp +++ b/src/odb.cpp @@ -8,28 +8,29 @@ namespace git { Odb::Odb(git_repository * repo) { - if (git_repository_odb(&odb_, repo)) + git_odb * odb; + if (git_repository_odb(&odb, repo)) throw odb_open_error(); + odb_.reset(odb); } - Odb::~Odb() + void Odb::Destroy::operator()(git_odb* odb) const { - if (odb_) - git_odb_free(odb_); + git_odb_free(odb); } OdbObject Odb::read(git_oid const & oid) const { git_odb_object * obj; - if (git_odb_read(&obj, odb_, &oid)) + if (git_odb_read(&obj, odb_.get(), &oid)) throw odb_read_error(oid); return OdbObject(obj); } - git_oid Odb::write(const void * data, size_t len, git_otype type) + git_oid Odb::write(const void * data, size_t len, git_object_t type) { git_oid res; - if (git_odb_write(&res, odb_, data, len, type)) + if (git_odb_write(&res, odb_.get(), data, len, type)) throw odb_write_error(); return res; } diff --git a/src/odb_object.cpp b/src/odb_object.cpp index 13d367c..ffe86e3 100644 --- a/src/odb_object.cpp +++ b/src/odb_object.cpp @@ -4,24 +4,24 @@ namespace git { - OdbObject::~OdbObject() + void OdbObject::Destroy::operator()(git_odb_object* obj) const { - if (obj_) - git_odb_object_free(obj_); + git_odb_object_free(obj); } git_otype OdbObject::type() const { - return git_odb_object_type(obj_); + return git_odb_object_type(obj_.get()); } unsigned char const * OdbObject::data() const { - return reinterpret_cast(git_odb_object_data(obj_)); + return reinterpret_cast(git_odb_object_data(obj_.get())); } size_t OdbObject::size() const { - return git_odb_object_size(obj_); + return git_odb_object_size(obj_.get()); } + } diff --git a/src/reference.cpp b/src/reference.cpp index f64a293..0466e67 100644 --- a/src/reference.cpp +++ b/src/reference.cpp @@ -7,9 +7,9 @@ namespace git { - Reference::~Reference() + void Reference::Destroy::operator()(git_reference* ref) const { - git_reference_free(ref_); + git_reference_free(ref); } Reference::Reference(git_reference * ref) @@ -19,33 +19,22 @@ namespace git const char * Reference::name() const { - return git_reference_name(ref_); + return git_reference_name(ptr()); } git_ref_t Reference::type() const { - return git_reference_type(ref_); + return git_reference_type(ptr()); } git_oid const & Reference::target() const { assert(type() != GIT_REF_SYMBOLIC); - return *git_reference_target(ref_); + return *git_reference_target(ptr()); } const char * Reference::symbolic_target() const { - return git_reference_symbolic_target(ref_); - } - - Reference::Reference(Reference && other) noexcept - : ref_(std::exchange(other.ref_, nullptr)) - { - } - - Reference & Reference::operator=(Reference && other) noexcept - { - std::swap(ref_, other.ref_); - return *this; + return git_reference_symbolic_target(ptr()); } } diff --git a/src/repo.cpp b/src/repo.cpp index 52d534b..7b359e7 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -23,64 +23,51 @@ namespace git Repository::Repository(const char * dir) { - if (git_repository_open_ext(&repo_, dir, 0, nullptr)) + git_repository * repo; + if (git_repository_open_ext(&repo, dir, 0, nullptr)) throw repository_open_error(dir); + repo_.reset(repo); } Repository::Repository(std::string const & dir) + : Repository(dir.c_str()) { - if (git_repository_open_ext(&repo_, dir.c_str(), 0, nullptr)) - throw repository_open_error(dir); } Repository::Repository(const char * dir, init_tag) { - if (git_repository_init(&repo_, dir, false) < 0) + git_repository * repo; + if (git_repository_init(&repo, dir, false) < 0) throw repository_init_error(dir); + repo_.reset(repo); } - Repository::Repository(std::string const & dir, init_tag) - { - if (git_repository_init(&repo_, dir.c_str(), false) < 0) - throw repository_init_error(dir); - } + Repository::Repository(std::string const & dir, init_tag tag) + : Repository(dir.c_str(), tag) + {} Repository::Repository(const char * dir, init_tag, git_repository_init_options opts) { - if (git_repository_init_ext(&repo_, dir, &opts) < 0) + git_repository * repo; + if (git_repository_init_ext(&repo, dir, &opts) < 0) throw repository_init_error(dir); - } - - Repository::Repository(Repository && other) noexcept - : repo_(std::exchange(other.repo_, nullptr)) - { - } - - Repository & Repository::operator=(Repository && other) noexcept - { - std::swap(repo_, other.repo_); - return *this; - } - - Repository::~Repository() - { - git_repository_free(repo_); + repo_.reset(repo); } bool Repository::is_bare() const { - return git_repository_is_bare(repo_) != 0; + return git_repository_is_bare(repo_.get()) != 0; } Signature Repository::signature() const { - return Signature(repo_); + return Signature(repo_.get()); } Commit Repository::commit_lookup(git_oid const & oid) const { git_commit * commit; - if (git_commit_lookup(&commit, repo_, &oid)) + if (git_commit_lookup(&commit, repo_.get(), &oid)) throw commit_lookup_error(oid); else return {commit, *this}; @@ -89,7 +76,7 @@ namespace git Tree Repository::tree_lookup(git_oid const & oid) const { git_tree * tree; - if (git_tree_lookup(&tree, repo_, &oid)) + if (git_tree_lookup(&tree, repo_.get(), &oid)) throw tree_lookup_error(oid); else return {tree, *this}; @@ -98,7 +85,7 @@ namespace git Tag Repository::tag_lookup(git_oid const & oid) const { git_tag * tag; - if (git_tag_lookup(&tag, repo_, &oid)) + if (git_tag_lookup(&tag, repo_.get(), &oid)) throw tag_lookup_error(oid); else return Tag(tag); @@ -107,7 +94,7 @@ namespace git Blob Repository::blob_lookup(git_oid const & oid) const { git_blob * blob; - if (git_blob_lookup(&blob, repo_, &oid)) + if (git_blob_lookup(&blob, repo_.get(), &oid)) throw blob_lookup_error(oid); else return Blob(blob); @@ -116,7 +103,7 @@ namespace git Revspec Repository::revparse(const char * spec) const { git_revspec revspec; - if (git_revparse(&revspec, repo_, spec)) + if (git_revparse(&revspec, repo_.get(), spec)) throw revparse_error(spec); else return {revspec, *this}; @@ -125,26 +112,26 @@ namespace git Revspec Repository::revparse_single(const char * spec) const { git_object * obj; - if (git_revparse_single(&obj, repo_, spec) < 0) + if (git_revparse_single(&obj, repo_.get(), spec) < 0) throw revparse_error(spec); return Revspec(obj, *this); } Index Repository::index() const { - return Index(repo_); + return Index(repo_.get()); } Odb Repository::odb() const { - return Odb(repo_); + return Odb(repo_.get()); } git_status_t Repository::file_status(const char * filepath) const { static_assert(sizeof(git_status_t) == sizeof(unsigned int), "sizeof(git_status_t) != sizeof(unsigned int)"); git_status_t res; - switch (git_status_file(reinterpret_cast(&res), repo_, filepath)) + switch (git_status_file(reinterpret_cast(&res), repo_.get(), filepath)) { case GIT_ENOTFOUND: throw file_not_found_error(filepath); @@ -221,7 +208,7 @@ namespace git std::vector Repository::branches(branch_type type) const { std::vector res; - for (branch_iterator it(repo_, type); it; ++it) + for (branch_iterator it(repo_.get(), type); it; ++it) res.emplace_back(std::move(*it)); return res; } @@ -229,7 +216,7 @@ namespace git Reference Repository::dwim(const char* shorthand) const { git_reference * ref; - if (git_reference_dwim(&ref, repo_, shorthand) == GIT_OK) + if (git_reference_dwim(&ref, repo_.get(), shorthand) == GIT_OK) return Reference(ref); else return Reference(); @@ -238,7 +225,7 @@ namespace git AnnotatedCommit Repository::annotated_commit_from_ref(Reference const& ref) const { git_annotated_commit * commit; - const auto err = git_annotated_commit_from_ref(&commit, repo_, ref.ptr()); + const auto err = git_annotated_commit_from_ref(&commit, repo_.get(), ref.ptr()); assert(err == GIT_OK); return AnnotatedCommit(commit); } @@ -246,7 +233,7 @@ namespace git AnnotatedCommit Repository::annotated_commit_lookup(git_oid const& id) const { git_annotated_commit * commit; - const auto err = git_annotated_commit_lookup(&commit, repo_, &id); + const auto err = git_annotated_commit_lookup(&commit, repo_.get(), &id); assert(err == GIT_OK); return AnnotatedCommit(commit); } @@ -254,7 +241,7 @@ namespace git RevWalker Repository::rev_walker() const { git_revwalk * walker; - if (git_revwalk_new(&walker, repo_)) + if (git_revwalk_new(&walker, repo_.get())) throw revwalk_new_error(); else return {walker, *this}; @@ -263,7 +250,7 @@ namespace git git_oid Repository::merge_base(git_oid const & a, git_oid const & b) const { git_oid res; - if (git_merge_base(&res, repo_, &a, &b)) + if (git_merge_base(&res, repo_.get(), &a, &b)) throw merge_base_error(a, b); return res; } @@ -276,7 +263,7 @@ namespace git Reference Repository::head() const { git_reference * head; - switch (git_repository_head(&head, repo_)) + switch (git_repository_head(&head, repo_.get())) { case GIT_OK: return Reference(head); @@ -292,44 +279,44 @@ namespace git Reference Repository::ref(const char * name) const { git_reference * ref; - git_reference_lookup(&ref, repo_, name); + git_reference_lookup(&ref, repo_.get(), name); return Reference(ref); } Status Repository::status(Status::Options const & opts) const { - return Status(repo_, opts); + return Status(repo_.get(), opts); } git_repository_state_t Repository::state() const { - return static_cast(git_repository_state(repo_)); + return static_cast(git_repository_state(repo_.get())); } StrArray Repository::reference_list() const { git_strarray str_array; - git_reference_list(&str_array, repo_); + git_reference_list(&str_array, repo_.get()); return StrArray(str_array); } Submodule Repository::submodule_lookup(const char * name) const { git_submodule * sm; - if (git_submodule_lookup(&sm, repo_, name)) + if (git_submodule_lookup(&sm, repo_.get(), name)) throw submodule_lookup_error(name); else - return {sm, repo_}; + return {sm, repo_.get()}; } const char * Repository::path() const { - return git_repository_path(repo_); + return git_repository_path(repo_.get()); } const char * Repository::workdir() const { - return git_repository_workdir(repo_); + return git_repository_workdir(repo_.get()); } git_oid Repository::create_commit(const char * update_ref, @@ -340,7 +327,7 @@ namespace git const char * message_encoding) { git_oid res; - if (git_commit_create_v(&res, repo_, update_ref, + if (git_commit_create_v(&res, repo_.get(), update_ref, author.ptr(), commiter.ptr(), message_encoding, message, tree.ptr(), 0)) @@ -359,7 +346,7 @@ namespace git const char * message_encoding) { git_oid res; - if (git_commit_create_v(&res, repo_, update_ref, + if (git_commit_create_v(&res, repo_.get(), update_ref, author.ptr(), commiter.ptr(), message_encoding, message, tree.ptr(), 1, parent.ptr())) @@ -381,12 +368,12 @@ namespace git Object Repository::entry_to_object(Tree::BorrowedEntry entry) const { - return tree_entry_to_object(entry.ptr(), *this, repo_); + return tree_entry_to_object(entry.ptr(), *this, repo_.get()); } Object Repository::entry_to_object(Tree::OwnedEntry entry) const { - return tree_entry_to_object(entry.ptr(), *this, repo_); + return tree_entry_to_object(entry.ptr(), *this, repo_.get()); } Object revparse_single(Repository const & repo, const char * spec) @@ -397,7 +384,7 @@ namespace git Diff Repository::diff(Tree & a, Tree & b, git_diff_options const & opts) const { git_diff * diff; - auto op_res = git_diff_tree_to_tree(&diff, repo_, a.ptr(), b.ptr(), &opts); + auto op_res = git_diff_tree_to_tree(&diff, repo_.get(), a.ptr(), b.ptr(), &opts); assert(op_res == 0); return Diff(diff); } @@ -405,7 +392,7 @@ namespace git Diff Repository::diff_to_index(Tree & t, git_diff_options const & opts) const { git_diff * diff; - auto op_res = git_diff_tree_to_index(&diff, repo_, t.ptr(), nullptr, &opts); + auto op_res = git_diff_tree_to_index(&diff, repo_.get(), t.ptr(), nullptr, &opts); assert(op_res == 0); return Diff(diff); } @@ -413,7 +400,7 @@ namespace git Diff Repository::diff_to_workdir(Tree & t, git_diff_options const & opts) const { git_diff * diff; - auto op_res = git_diff_tree_to_workdir(&diff, repo_, t.ptr(), &opts); + auto op_res = git_diff_tree_to_workdir(&diff, repo_.get(), t.ptr(), &opts); assert(op_res == 0); return Diff(diff); } @@ -421,7 +408,7 @@ namespace git Diff Repository::diff_to_workdir_with_index(Tree & t, git_diff_options const & opts) const { git_diff * diff; - auto op_res = git_diff_tree_to_workdir_with_index(&diff, repo_, t.ptr(), &opts); + auto op_res = git_diff_tree_to_workdir_with_index(&diff, repo_.get(), t.ptr(), &opts); assert(op_res == 0); return Diff(diff); } @@ -429,14 +416,14 @@ namespace git Diff Repository::diff_index_to_workdir(git_diff_options const & opts) const { git_diff * diff; - auto op_res = git_diff_index_to_workdir(&diff, repo_, nullptr, &opts); + auto op_res = git_diff_index_to_workdir(&diff, repo_.get(), nullptr, &opts); assert(op_res == 0); return Diff(diff); } void Repository::reset_default(Commit const & commit, git_strarray const & pathspecs) { - auto op_res = git_reset_default(repo_, reinterpret_cast(const_cast(commit.ptr())), const_cast(&pathspecs)); + auto op_res = git_reset_default(repo_.get(), reinterpret_cast(const_cast(commit.ptr())), const_cast(&pathspecs)); assert(op_res == GIT_OK); } @@ -460,7 +447,7 @@ namespace git StrArray Repository::remotes() const { git_strarray result; - auto op_res = git_remote_list(&result, repo_); + auto op_res = git_remote_list(&result, repo_.get()); assert(op_res == GIT_OK); return StrArray(result); } @@ -468,7 +455,7 @@ namespace git Remote Repository::remote(const char * name) const { git_remote * remote; - if (git_remote_lookup(&remote, repo_, name)) + if (git_remote_lookup(&remote, repo_.get(), name)) throw remote_lookup_error(name); else return Remote(remote); @@ -477,7 +464,7 @@ namespace git Remote Repository::create_remote(const char * name, const char * url) { git_remote * remote; - if (git_remote_create(&remote, repo_, name, url)) + if (git_remote_create(&remote, repo_.get(), name, url)) throw remote_create_error(name, url); else return Remote(remote); @@ -485,14 +472,14 @@ namespace git void Repository::delete_remote(const char * name) { - if (git_remote_delete(repo_, name)) + if (git_remote_delete(repo_.get(), name)) throw remote_delete_error(name); } internal::optional Repository::rename_remote(const char * old_name, const char * new_name) { git_strarray problems {}; - if (git_remote_rename(&problems, repo_, old_name, new_name)) + if (git_remote_rename(&problems, repo_.get(), old_name, new_name)) return StrArray(problems); else return internal::none; @@ -500,29 +487,29 @@ namespace git void Repository::set_url(const char * name, const char * url) { - if (git_remote_set_url(repo_, name, url)) + if (git_remote_set_url(repo_.get(), name, url)) throw remote_set_url_error(name, url); } void Repository::set_pushurl(const char * name, const char * url) { - if (git_remote_set_pushurl(repo_, name, url)) + if (git_remote_set_pushurl(repo_.get(), name, url)) throw remote_set_pushurl_error(name, url); } int Repository::checkout_tree(Commit const& commit, git_checkout_options const& options) { - return git_checkout_tree(repo_, reinterpret_cast(commit.ptr()), &options); + return git_checkout_tree(repo_.get(), reinterpret_cast(commit.ptr()), &options); } int Repository::set_head(char const* ref) { - return git_repository_set_head(repo_, ref); + return git_repository_set_head(repo_.get(), ref); } int Repository::set_head_detached(AnnotatedCommit const& commit) { - return git_repository_set_head_detached_from_annotated(repo_, commit.ptr()); + return git_repository_set_head_detached_from_annotated(repo_.get(), commit.ptr()); } internal::optional Repository::discover(const char * start_path) @@ -532,4 +519,9 @@ namespace git return internal::none; return std::string(buf.ptr, buf.size); } + + void Repository::Destroy::operator() (git_repository* repo) const + { + git_repository_free(repo); + } } diff --git a/src/revwalker.cpp b/src/revwalker.cpp index b1c2ba5..692666b 100644 --- a/src/revwalker.cpp +++ b/src/revwalker.cpp @@ -17,43 +17,43 @@ namespace git } } - RevWalker::~RevWalker() + void RevWalker::Destroy::operator()(git_revwalk* walker) const { - git_revwalk_free(walker_); + git_revwalk_free(walker); } void RevWalker::sort(revwalker::sorting::type s) { - git_revwalk_sorting(walker_, s.value()); + git_revwalk_sorting(walker_.get(), s.value()); } void RevWalker::simplify_first_parent() { - git_revwalk_simplify_first_parent(walker_); + git_revwalk_simplify_first_parent(walker_.get()); } void RevWalker::push_head() const { - if (git_revwalk_push_head(walker_)) + if (git_revwalk_push_head(walker_.get())) throw invalid_head_error(); } void RevWalker::hide(git_oid const & obj) const { - if (git_revwalk_hide(walker_, &obj)) + if (git_revwalk_hide(walker_.get(), &obj)) throw non_commit_object_error(obj); } void RevWalker::push(git_oid const & obj) const { - if (git_revwalk_push(walker_, &obj)) + if (git_revwalk_push(walker_.get(), &obj)) throw non_commit_object_error(obj); } Commit RevWalker::next() const { git_oid oid; - if (git_revwalk_next(&oid, walker_) == 0) + if (git_revwalk_next(&oid, walker_.get()) == 0) return repo_->commit_lookup(oid); else return Commit(); @@ -62,7 +62,7 @@ namespace git bool RevWalker::next(char * id_buffer) const { git_oid oid; - bool valid = (git_revwalk_next(&oid, walker_) == 0); + bool valid = (git_revwalk_next(&oid, walker_.get()) == 0); if (valid) git_oid_fmt(id_buffer, &oid); return valid; diff --git a/src/signature.cpp b/src/signature.cpp index 7b41910..8677a95 100644 --- a/src/signature.cpp +++ b/src/signature.cpp @@ -3,21 +3,28 @@ #include "git2cpp/error.h" #include "git2cpp/signature.h" +#include + namespace git { Signature::Signature(git_repository * repo) { - if (git_signature_default(&sig_, repo) < 0) + git_signature * sig; + if (git_signature_default(&sig, repo) != GIT_OK) throw signature_create_error(); + sig_.reset(sig); } Signature::Signature(const char * name, const char * email, git_time_t time, int offset) { - git_signature_new(&sig_, name, email, time, offset); + git_signature * sig; + if (git_signature_new(&sig, name, email, time, offset) != GIT_OK) + throw signature_create_error(); + sig_.reset(sig); } - Signature::~Signature() + void Signature::Destroy::operator()(git_signature* sig) const { - git_signature_free(sig_); + git_signature_free(sig); } } diff --git a/src/status.cpp b/src/status.cpp index 12ffa7b..3fe3af0 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -5,12 +5,12 @@ namespace git { size_t Status::entrycount() const { - return git_status_list_entrycount(status_); + return git_status_list_entrycount(status_.get()); } git_status_entry const & Status::operator[](size_t i) const { - if (auto res = git_status_byindex(status_, i)) + if (auto res = git_status_byindex(status_.get(), i)) return *res; else throw error_t("status entry index out of bounds: " + std::to_string(i)); @@ -92,24 +92,14 @@ namespace git Status::Status(git_repository * repo, Options const & opts) { - if (git_status_list_new(&status_, repo, opts.raw())) + git_status_list * status; + if (git_status_list_new(&status, repo, opts.raw())) throw get_status_error(); + status_.reset(status); } - Status::Status(Status && other) noexcept - : status_(other.status_) + void Status::Destroy::operator()(git_status_list* status) const { - other.status_ = nullptr; - } - - Status & Status::operator=(Status && other) noexcept - { - std::swap(status_, other.status_); - return *this; - } - - Status::~Status() - { - git_status_list_free(status_); + git_status_list_free(status); } } diff --git a/src/submodule.cpp b/src/submodule.cpp index 30b917a..9136ac8 100644 --- a/src/submodule.cpp +++ b/src/submodule.cpp @@ -12,15 +12,15 @@ namespace git { } - Submodule::~Submodule() + void Submodule::Destroy::operator()(git_submodule* sm) const { - git_submodule_free(sm_); + git_submodule_free(sm); } Submodule::status Submodule::get_status() const { unsigned int res; - if (auto err = git_submodule_status(&res, repo_, git_submodule_name(sm_), git_submodule_ignore(sm_))) + if (auto err = git_submodule_status(&res, repo_, git_submodule_name(sm_.get()), git_submodule_ignore(sm_.get()))) throw error_t("git_submodule_status failed with error code " + std::to_string(err)); else return static_cast(res); diff --git a/src/tag.cpp b/src/tag.cpp index c65b56b..e58ac14 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -12,45 +12,41 @@ namespace git { } - Tag::Tag(Tag && other) noexcept - : tag_(std::exchange(other.tag_, nullptr)) + void Tag::Destroy::operator()(git_tag* tag) const { - } - - Tag::~Tag() - { - git_tag_free(tag_); + git_tag_free(tag); } Object Tag::target(Repository const & repo) const { git_object * obj; - git_tag_target(&obj, tag_); + git_tag_target(&obj, tag_.get()); return Object(obj, repo); } git_oid const & Tag::target_id() const { - return *git_tag_target_id(tag_); + return *git_tag_target_id(tag_.get()); } git_otype Tag::target_type() const { - return git_tag_target_type(tag_); + return git_tag_target_type(tag_.get()); } const char * Tag::name() const { - return git_tag_name(tag_); + return git_tag_name(tag_.get()); } const char * Tag::message() const { - return git_tag_message(tag_); + return git_tag_message(tag_.get()); } git_signature const * Tag::tagger() const { - return git_tag_tagger(tag_); + return git_tag_tagger(tag_.get()); } + } diff --git a/src/tree.cpp b/src/tree.cpp index cbb0417..d9405fa 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -12,48 +12,29 @@ namespace git { } - Tree::Tree() - : tree_(nullptr) - , repo_(nullptr) + void Tree::Destroy::operator()(git_tree* tree) const { - } - - Tree::Tree(Tree && other) noexcept - : tree_(std::exchange(other.tree_, nullptr)) - , repo_(std::exchange(other.repo_, nullptr)) - { - } - - Tree & Tree::operator=(Tree && other) noexcept - { - std::swap(tree_, other.tree_); - std::swap(repo_, other.repo_); - return *this; - } - - Tree::~Tree() - { - git_tree_free(tree_); + git_tree_free(tree); } int Tree::pathspec_match(uint32_t flags, Pathspec const & ps) { - return git_pathspec_match_tree(nullptr, tree_, flags, ps.ptr()); + return git_pathspec_match_tree(nullptr, ptr(), flags, ps.ptr()); } size_t Tree::entrycount() const { - return git_tree_entrycount(tree_); + return git_tree_entrycount(ptr()); } Tree::BorrowedEntry Tree::operator[](size_t i) const { - return BorrowedEntry(git_tree_entry_byindex(tree_, i)); + return BorrowedEntry(git_tree_entry_byindex(ptr(), i)); } Tree::BorrowedEntry Tree::operator[](std::string const & filename) const { - if (auto entry = git_tree_entry_byname(tree_, filename.c_str())) + if (auto entry = git_tree_entry_byname(ptr(), filename.c_str())) return BorrowedEntry(entry); else throw file_not_found_error(filename.c_str()); @@ -62,7 +43,7 @@ namespace git Tree::OwnedEntry Tree::find(const char * path) const { git_tree_entry * res; - const auto status = git_tree_entry_bypath(&res, tree_, path); + const auto status = git_tree_entry_bypath(&res, ptr(), path); switch (status) { case GIT_OK: @@ -80,15 +61,9 @@ namespace git { } - Tree::OwnedEntry::~OwnedEntry() - { - git_tree_entry_free(entry_); - } - - Tree::OwnedEntry::OwnedEntry(OwnedEntry && other) noexcept - : entry_(std::exchange(other.entry_, nullptr)) - , repo_(std::exchange(other.repo_, nullptr)) + void Tree::OwnedEntry::Destroy::operator()(git_tree_entry* entry) const { + git_tree_entry_free(entry); } Tree Tree::OwnedEntry::to_tree() /* && */ From 854c28f540ed9ac667b405c135d98358fef9cf2a Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 11 Mar 2019 08:37:17 +0300 Subject: [PATCH 126/171] + missing #includes --- include/git2cpp/diff.h | 7 ++++--- include/git2cpp/index.h | 1 + include/git2cpp/signature.h | 4 ++++ include/git2cpp/tree.h | 2 ++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/git2cpp/diff.h b/include/git2cpp/diff.h index 9514e86..045c80c 100644 --- a/include/git2cpp/diff.h +++ b/include/git2cpp/diff.h @@ -1,11 +1,12 @@ #pragma once -#include +#include "buffer.h" +#include "tagged_mask.h" #include -#include "buffer.h" -#include "tagged_mask.h" +#include +#include namespace git { diff --git a/include/git2cpp/index.h b/include/git2cpp/index.h index 4d56e39..b23c6bc 100644 --- a/include/git2cpp/index.h +++ b/include/git2cpp/index.h @@ -3,6 +3,7 @@ #include #include +#include struct git_index; struct git_repository; diff --git a/include/git2cpp/signature.h b/include/git2cpp/signature.h index 3903287..75756d4 100644 --- a/include/git2cpp/signature.h +++ b/include/git2cpp/signature.h @@ -1,5 +1,9 @@ #pragma once +#include + +#include + struct git_signature; struct git_repository; diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index 05e47cd..da2763f 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -2,6 +2,8 @@ #include "pathspec.h" +#include + namespace git { struct Repository; From 654e33d045bf75b367b9dc17f0057271c5d1343d Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 11 Mar 2019 08:42:08 +0300 Subject: [PATCH 127/171] AppVeyor: add x64 configurations --- appveyor.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 3e95f73..4baf481 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,6 +14,14 @@ environment: GENERATOR: "Visual Studio 15 2017" ARCH: 32 BOOST: 1_65_1 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + GENERATOR: "Visual Studio 14 2015 Win64" + ARCH: 64 + BOOST: 1_63_0 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + GENERATOR: "Visual Studio 15 2017 Win64" + ARCH: 64 + BOOST: 1_65_1 clone_script: - cmd: git clone --branch=%APPVEYOR_REPO_BRANCH% https://github.com/%APPVEYOR_REPO_NAME%.git %APPVEYOR_BUILD_FOLDER% From 9283f035550aed46874eacc04a42571c54ab4f00 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 27 Apr 2019 11:58:20 +0300 Subject: [PATCH 128/171] internal::format doesn't support std::string as argument --- include/git2cpp/error.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 24749f0..410b73e 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -193,7 +193,7 @@ namespace git struct non_commit_object_error : error_t { explicit non_commit_object_error(git_oid const & id) - : error_t(internal::format("object %s is not a commit", id_to_str(id))) + : error_t("object " + id_to_str(id) + " is not a commit") {} }; @@ -243,8 +243,7 @@ namespace git struct merge_base_error : error_t { merge_base_error(git_oid const & c1, git_oid const & c2) - : error_t(internal::format( - "Could not find merge base for commits %s and %s", id_to_str(c1, 8), id_to_str(c2, 8))) + : error_t("Could not find merge base for commits " + id_to_str(c1, 8) + " and " + id_to_str(c2, 8)) {} }; From fb5f99bf508c6ac6e7382c696114d960439b3093 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 21 Jun 2019 07:49:30 +0300 Subject: [PATCH 129/171] implement Repository::create_branch --- examples/branch.cpp | 75 ++++++++++++++++++++++++++++++++++++----- include/git2cpp/error.h | 15 +++++++++ include/git2cpp/repo.h | 2 ++ src/repo.cpp | 18 ++++++++++ 4 files changed, 102 insertions(+), 8 deletions(-) diff --git a/examples/branch.cpp b/examples/branch.cpp index 9df894c..7d8f291 100644 --- a/examples/branch.cpp +++ b/examples/branch.cpp @@ -1,14 +1,73 @@ -#include - #include "git2cpp/initializer.h" #include "git2cpp/repo.h" -int main() +#include +#include + +namespace +{ + using namespace git; + + int create_branch(Repository & repo, const char * name, bool force) + { + try + { + auto head = repo.head(); + auto branch = repo.create_branch(name, repo.commit_lookup(head.target()), force); + assert(branch); + assert(std::strcmp(branch.name(), name)); + std::cout << "branch " << name << " has been created" << std::endl; + return EXIT_SUCCESS; + } + catch (branch_create_error const & e) + { + switch (e.reason) + { + case branch_create_error::already_exists:; + std::cerr << "a branch named '" << name << "' already exists" << std::endl; + break; + case branch_create_error::invalid_spec: + std::cerr << "'" << name << "' is not a valid branch name" << std::endl; + break; + case branch_create_error::unknown: + break; + } + return EXIT_FAILURE; + } + } + + void print_help() + { + std::cerr << "invalid command line arguments, expected are:" << std::endl + << "[[-f] branch_name]" << std::endl; + } +} + +int main(int argc, char* argv[]) { - git::Initializer threads_initializer; + Initializer threads_initializer; - git::Repository repo("."); - auto branches = repo.branches(git::branch_type::ALL); - for (auto const & b : branches) - std::cout << b.name() << std::endl; + Repository repo("."); + switch (argc) + { + case 1: + { + auto branches = repo.branches(git::branch_type::ALL); + for (auto const & b : branches) + std::cout << b.name() << std::endl; + return EXIT_SUCCESS; + } + case 2: + return create_branch(repo, argv[1], false); + case 3: + if (std::strcmp(argv[1], "-f") != 0) + { + print_help(); + return EXIT_FAILURE; + } + return create_branch(repo, argv[2], true); + default: + print_help(); + return EXIT_FAILURE; + } } diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 410b73e..0265f45 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -253,4 +253,19 @@ namespace git : error_t("Could not open config") {} }; + + struct branch_create_error : error_t + { + enum reason_t + { + already_exists, + invalid_spec, + unknown + } reason; + + branch_create_error(reason_t r) + : error_t("Could not create branch") + , reason(r) + {} + }; } diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index d873525..b9f8f4d 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -86,6 +86,8 @@ namespace git std::vector branches(branch_type) const; + Reference create_branch(const char * name, Commit const & target, bool force); + /// @return can be empty Reference dwim(const char * shorthand) const; diff --git a/src/repo.cpp b/src/repo.cpp index 7b359e7..92a43f7 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -213,6 +213,24 @@ namespace git return res; } + Reference Repository::create_branch(const char * name, Commit const & target, bool force) + { + git_reference * ref; + const auto err = git_branch_create(&ref, repo_.get(), name, target.ptr(), force); + switch (err) + { + case GIT_OK: + return Reference(ref); + case GIT_EEXISTS: + assert(!force); + throw branch_create_error(branch_create_error::already_exists); + case GIT_EINVALIDSPEC: + throw branch_create_error(branch_create_error::invalid_spec); + default: + throw branch_create_error(branch_create_error::unknown); + } + } + Reference Repository::dwim(const char* shorthand) const { git_reference * ref; From 72b185329f045cff7a17f966abbeef1827885981 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 22 Jun 2019 13:58:36 +0300 Subject: [PATCH 130/171] + Index::get_by_path --- include/git2cpp/index.h | 2 ++ src/index.cpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/include/git2cpp/index.h b/include/git2cpp/index.h index b23c6bc..28e0bc5 100644 --- a/include/git2cpp/index.h +++ b/include/git2cpp/index.h @@ -20,6 +20,8 @@ namespace git size_t entrycount() const; git_index_entry const * operator[](size_t i) const; + git_index_entry const * get_by_path(const char *path, int stage) const; + typedef std::function matched_path_callback_t; void update_all(git_strarray const & pathspec, matched_path_callback_t cb); diff --git a/src/index.cpp b/src/index.cpp index 0fd6197..b1d83c3 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -40,6 +40,11 @@ namespace git return git_index_get_byindex(index_.get(), i); } + git_index_entry const* Index::get_by_path(const char* path, int stage) const + { + return git_index_get_bypath(index_.get(), path, stage); + } + namespace { int apply_callback(const char * path, const char * matched_pathspec, void * payload) From 076efa03149c0214e79033a5c07390143700be1e Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 22 Jun 2019 14:00:30 +0300 Subject: [PATCH 131/171] 'ls-files' exported from libgit2 examples --- CMakeLists.txt | 1 + examples/ls-files.cpp | 128 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 examples/ls-files.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d2d8860..cdc9716 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ set(examples general remote checkout + ls-files ) foreach (example ${examples}) diff --git a/examples/ls-files.cpp b/examples/ls-files.cpp new file mode 100644 index 0000000..5e42ed4 --- /dev/null +++ b/examples/ls-files.cpp @@ -0,0 +1,128 @@ +/* + * libgit2 "ls-files" example - shows how to view all files currently in the index + * + * 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 + * . + */ + +/** + * This example demonstrates the libgit2 index APIs to roughly + * simulate the output of `git ls-files`. + * `git ls-files` has many options and this currently does not show them. + * + * `git ls-files` base command shows all paths in the index at that time. + * This includes staged and committed files, but unstaged files will not display. + * + * This currently supports the default behavior and the `--error-unmatch` option. + */ + +#include +#include +#include + +#include "git2/index.h" + +typedef struct { + int error_unmatch; + char *files[1024]; + size_t file_count; +} ls_options; + +static void usage(const char *message, const char *arg) +{ + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: ls-files [--error-unmatch] [--] [...]\n"); + exit(1); +} + +static int parse_options(ls_options *opts, int argc, char *argv[]) +{ + int parsing_files = 0; + int i; + + memset(opts, 0, sizeof(ls_options)); + + if (argc < 2) + return 0; + + for (i = 1; i < argc; ++i) { + char *a = argv[i]; + + /* if it doesn't start with a '-' or is after the '--' then it is a file */ + if (a[0] != '-' || parsing_files) { + parsing_files = 1; + + /* watch for overflows (just in case) */ + if (opts->file_count == 1024) { + fprintf(stderr, "ls-files can only support 1024 files at this time.\n"); + return -1; + } + + opts->files[opts->file_count++] = a; + } else if (!strcmp(a, "--")) { + parsing_files = 1; + } else if (!strcmp(a, "--error-unmatch")) { + opts->error_unmatch = 1; + } else { + usage("Unsupported argument", a); + return -1; + } + } + + return 0; +} + +static int print_paths(ls_options *opts, git::Index & index) +{ + /* if there are no files explicitly listed by the user print all entries in the index */ + if (opts->file_count == 0) { + size_t const entry_count = index.entrycount(); + + for (size_t i = 0; i < entry_count; i++) { + auto entry = index[i]; + puts(entry->path); + } + return 0; + } + + /* loop through the files found in the args and print them if they exist */ + for (size_t i = 0; i < opts->file_count; ++i) { + const char *path = opts->files[i]; + + if (index.get_by_path(path, GIT_INDEX_STAGE_NORMAL)) { + puts(path); + } else if (opts->error_unmatch) { + fprintf(stderr, "error: pathspec '%s' did not match any file(s) known to git.\n", path); + fprintf(stderr, "Did you forget to 'git add'?\n"); + return -1; + } + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + ls_options opts; + + auto error = parse_options(&opts, argc, argv); + if (error < 0) + return error; + + auto_git_initializer; + + git::Repository repo("."); + auto index = repo.index(); + + return print_paths(&opts, index); +} From 040d602dcb523e9854669cc7441dabc1223aedf2 Mon Sep 17 00:00:00 2001 From: ballessay Date: Sat, 6 Jul 2019 01:12:55 +0200 Subject: [PATCH 132/171] Add option for examples build --- CMakeLists.txt | 56 +++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cdc9716..d64b1bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,29 +56,33 @@ set_target_properties(git2cpp PROPERTIES INTERFACE_COMPILE_FEATURES cxx_std_17 ) -set(examples - add - branch - cat-file - diff - log - rev-list - showindex - status - init - rev-parse - general - remote - checkout - ls-files -) - -foreach (example ${examples}) - add_executable("${example}-cpp" examples/${example}.cpp) - target_link_libraries("${example}-cpp" git2cpp) -endforeach(example) - -add_executable(commit-graph-generator examples/commit-graph-generator.cpp) -target_link_libraries(commit-graph-generator git2cpp) - -file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) +option(BUILD_LIBGIT2CPP_EXAMPLES ON) + +if(BUILD_LIBGIT2CPP_EXAMPLES) + set(examples + add + branch + cat-file + diff + log + rev-list + showindex + status + init + rev-parse + general + remote + checkout + ls-files + ) + + foreach (example ${examples}) + add_executable("${example}-cpp" examples/${example}.cpp) + target_link_libraries("${example}-cpp" git2cpp) + endforeach(example) + + add_executable(commit-graph-generator examples/commit-graph-generator.cpp) + target_link_libraries(commit-graph-generator git2cpp) + + file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) +endif() From 9ce3427bf9f2075d138f8754ad3e2fbce9be0106 Mon Sep 17 00:00:00 2001 From: ballessay Date: Sat, 13 Jul 2019 13:06:33 +0200 Subject: [PATCH 133/171] Add new option to README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 74e4613..f7427a8 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Building libgit2cpp - Using CMake $ cmake .. $ make -Supporting CMake options: `USE_BOOST`, `BUNDLE_LIBGIT2`. +Supporting CMake options: `USE_BOOST`, `BUNDLE_LIBGIT2`, `BUILD_LIBGIT2CPP_EXAMPLES`. Testing ======= From 42ef719d38857b2e59e6609fe3fba2b31c05016b Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 13 Jul 2019 18:55:43 +0300 Subject: [PATCH 134/171] 'blame' exported from libgit2 examples --- CMakeLists.txt | 1 + examples/blame.cpp | 199 ++++++++++++++++++++++++++++++++++++++++ include/git2cpp/blame.h | 23 +++++ include/git2cpp/error.h | 7 ++ include/git2cpp/repo.h | 5 + src/blame.cpp | 16 ++++ src/repo.cpp | 13 +++ 7 files changed, 264 insertions(+) create mode 100644 examples/blame.cpp create mode 100644 include/git2cpp/blame.h create mode 100644 src/blame.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d64b1bb..9f6011e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,7 @@ if(BUILD_LIBGIT2CPP_EXAMPLES) remote checkout ls-files + blame ) foreach (example ${examples}) diff --git a/examples/blame.cpp b/examples/blame.cpp new file mode 100644 index 0000000..c9b584c --- /dev/null +++ b/examples/blame.cpp @@ -0,0 +1,199 @@ +/* + * libgit2 "blame" example - shows how to use the blame API + * + * 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 "git2cpp/repo.h" +#include "git2cpp/initializer.h" +#include "git2/blame.h" + +#ifdef _MSC_VER +#define snprintf sprintf_s +#define strcasecmp strcmpi +#endif + +/** + * This example demonstrates how to invoke the libgit2 blame API to roughly + * simulate the output of `git blame` and a few of its command line arguments. + */ + +struct opts { + char *path; + char *commitspec; + int C; + int M; + int start_line; + int end_line; + int F; +}; +static void parse_opts(struct opts *o, int argc, char *argv[]); + +int main(int argc, char *argv[]) +{ + opts o = {0}; + parse_opts(&o, argc, argv); + + git_blame_options blameopts = GIT_BLAME_OPTIONS_INIT; + + if (o.M) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; + if (o.C) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; + if (o.F) blameopts.flags |= GIT_BLAME_FIRST_PARENT; + + auto_git_initializer; + + git::Repository repo("."); + /** + * The commit range comes in "commitish" form. Use the rev-parse API to + * nail down the end points. + */ + if (o.commitspec) + { + auto revspec = repo.revparse(o.commitspec); + + if (revspec.flags() & GIT_REVPARSE_SINGLE) + { + blameopts.newest_commit = revspec.single()->id(); + } + else + { + auto const & range = *revspec.range(); + blameopts.oldest_commit = range.from.id(); + blameopts.newest_commit = range.to.id(); + } + } + + /** Run the blame. */ + auto blame = repo.blame_file(o.path, blameopts); + + char spec[1024] = {0}; + + /** + * Get the raw data inside the blob for output. We use the + * `commitish:path/to/file.txt` format to find it. + */ + if (git_oid_iszero(&blameopts.newest_commit)) + strcpy(spec, "HEAD"); + else + git_oid_tostr(spec, sizeof(spec), &blameopts.newest_commit); + strcat(spec, ":"); + strcat(spec, o.path); + + auto blob = repo.blob_lookup(repo.revparse_single(spec).single()->id()); + + char const * rawdata = reinterpret_cast(blob.content()); + size_t rawsize = blob.size(); + + /** Produce the output. */ + int line = 1; + bool break_on_null_hunk = false; + for (size_t i = 0; i < rawsize; ++line) { + const git_blame_hunk *hunk = blame.get_hunk_byline(line); + + if (break_on_null_hunk && !hunk) + break; + + char const * eol = reinterpret_cast(memchr(rawdata + i, '\n', rawsize - i)); + if (hunk) { + break_on_null_hunk = true; + + char oid[10] = {0}; + git_oid_tostr(oid, 10, &hunk->final_commit_id); + char sig[128] = {0}; + snprintf(sig, 127, "%s <%s>", hunk->final_signature->name, hunk->final_signature->email); + + printf("%s ( %-30s %3d) %.*s\n", + oid, + sig, + line, + (int)(eol - rawdata - i), + rawdata + i); + } + + i = (int)(eol - rawdata + 1); + } + + return 0; +} + +/** Tell the user how to make this thing work. */ +static void usage(const char *msg, const char *arg) +{ + if (msg && arg) + fprintf(stderr, "%s: %s\n", msg, arg); + else if (msg) + fprintf(stderr, "%s\n", msg); + fprintf(stderr, "usage: blame [options] [] \n"); + fprintf(stderr, "\n"); + fprintf(stderr, " example: `HEAD~10..HEAD`, or `1234abcd`\n"); + fprintf(stderr, " -L process only line range n-m, counting from 1\n"); + fprintf(stderr, " -M find line moves within and across files\n"); + fprintf(stderr, " -C find line copies within and across files\n"); + fprintf(stderr, " -F follow only the first parent commits\n"); + fprintf(stderr, "\n"); + exit(1); +} + +/** Parse the arguments. */ +static void parse_opts(struct opts *o, int argc, char *argv[]) +{ + int i; + char *bare_args[3] = {0}; + + if (argc < 2) usage(NULL, NULL); + + for (i=1; i= 3) + usage("Invalid argument set", NULL); + bare_args[i] = a; + } + else if (!strcmp(a, "--")) + continue; + else if (!strcasecmp(a, "-M")) + o->M = 1; + else if (!strcasecmp(a, "-C")) + o->C = 1; + else if (!strcasecmp(a, "-F")) + o->F = 1; + else if (!strcasecmp(a, "-L")) { + i++; a = argv[i]; + if (i >= argc) throw std::runtime_error("Not enough arguments to -L"); + if (sscanf(a, "%d,%d", &o->start_line, &o->end_line)-2, "-L format error", NULL) + std::abort(); + } + else { + /* commit range */ + if (o->commitspec) throw std::runtime_error("Only one commit spec allowed"); + o->commitspec = a; + } + } + + /* Handle the bare arguments */ + if (!bare_args[0]) usage("Please specify a path", NULL); + o->path = bare_args[0]; + if (bare_args[1]) { + /* */ + o->path = bare_args[1]; + o->commitspec = bare_args[0]; + } + if (bare_args[2]) { + /* */ + char spec[128] = {0}; + o->path = bare_args[2]; + sprintf(spec, "%s..%s", bare_args[0], bare_args[1]); + o->commitspec = spec; + } +} diff --git a/include/git2cpp/blame.h b/include/git2cpp/blame.h new file mode 100644 index 0000000..3b1c4ef --- /dev/null +++ b/include/git2cpp/blame.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +struct git_blame; +struct git_blame_hunk; + +namespace git +{ + struct Blame + { + explicit Blame(git_blame * blame) + : blame_(blame) + {} + + git_blame_hunk const * get_hunk_byline(size_t lineno) const; + + private: + struct Destroy { void operator() (git_blame *) const; }; + + std::unique_ptr blame_; + }; +} diff --git a/include/git2cpp/error.h b/include/git2cpp/error.h index 0265f45..e62c692 100644 --- a/include/git2cpp/error.h +++ b/include/git2cpp/error.h @@ -268,4 +268,11 @@ namespace git , reason(r) {} }; + + struct blame_file_error : error_t + { + explicit blame_file_error(std::string const & path) + : error_t("Could not blame file " + path) + {} + }; } diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index b9f8f4d..71eee3d 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -2,6 +2,7 @@ #include "repo_fwd.h" +#include "blame.h" #include "blob.h" #include "commit.h" #include "diff.h" @@ -23,6 +24,8 @@ #include #include +struct git_blame_options; + namespace git { struct non_existing_branch_error @@ -139,6 +142,8 @@ namespace git int set_head(char const* ref); int set_head_detached(AnnotatedCommit const&); + Blame blame_file(const char * path, git_blame_options const &); + explicit Repository(const char * dir); explicit Repository(std::string const & dir); diff --git a/src/blame.cpp b/src/blame.cpp new file mode 100644 index 0000000..3d7acc8 --- /dev/null +++ b/src/blame.cpp @@ -0,0 +1,16 @@ +#include "git2cpp/blame.h" + +#include + +namespace git +{ + git_blame_hunk const* Blame::get_hunk_byline(size_t lineno) const + { + return git_blame_get_hunk_byline(blame_.get(), lineno); + } + + void Blame::Destroy::operator()(git_blame* blame) const + { + git_blame_free(blame); + } +} diff --git a/src/repo.cpp b/src/repo.cpp index 92a43f7..952b50f 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -4,6 +4,7 @@ #include "git2cpp/error.h" #include "git2cpp/internal/optional.h" +#include #include #include #include @@ -530,6 +531,18 @@ namespace git return git_repository_set_head_detached_from_annotated(repo_.get(), commit.ptr()); } + Blame Repository::blame_file(const char* path, git_blame_options const& options) + { + git_blame * blame; + const auto err = git_blame_file( + &blame, repo_.get(), path, + /*IMO `options` can be const, git_blame_file doesn't change it*/ const_cast(&options) + ); + if (err != GIT_OK) + throw blame_file_error(path); + return Blame(blame); + } + internal::optional Repository::discover(const char * start_path) { git_buf buf = GIT_BUF_INIT_CONST(nullptr, 0); From 21cc11065fadfba44aef22ad7cdfd49efc205334 Mon Sep 17 00:00:00 2001 From: ballessay Date: Sat, 13 Jul 2019 17:41:11 +0200 Subject: [PATCH 135/171] Add blame struct #9 --- include/git2cpp/blame.h | 13 ++++++++----- src/blame.cpp | 19 ++++++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/git2cpp/blame.h b/include/git2cpp/blame.h index 3b1c4ef..2ad639c 100644 --- a/include/git2cpp/blame.h +++ b/include/git2cpp/blame.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include @@ -9,15 +9,18 @@ namespace git { struct Blame { + uint32_t hunk_count() const; + + const git_blame_hunk * hunk_byindex(uint32_t index) const; + + const git_blame_hunk * hunk_byline(size_t lineno) const; + explicit Blame(git_blame * blame) : blame_(blame) {} - git_blame_hunk const * get_hunk_byline(size_t lineno) const; - private: struct Destroy { void operator() (git_blame *) const; }; - - std::unique_ptr blame_; + std::unique_ptr blame_; }; } diff --git a/src/blame.cpp b/src/blame.cpp index 3d7acc8..53262ad 100644 --- a/src/blame.cpp +++ b/src/blame.cpp @@ -1,15 +1,24 @@ -#include "git2cpp/blame.h" - -#include +#include "git2cpp/blame.h" +#include "git2/blame.h" namespace git { - git_blame_hunk const* Blame::get_hunk_byline(size_t lineno) const + uint32_t Blame::hunk_count() const + { + return git_blame_get_hunk_count(blame_.get()); + } + + const git_blame_hunk* Blame::hunk_byindex(uint32_t index) const + { + return git_blame_get_hunk_byindex(blame_.get(), index); + } + + const git_blame_hunk* Blame::hunk_byline(size_t lineno) const { return git_blame_get_hunk_byline(blame_.get(), lineno); } - void Blame::Destroy::operator()(git_blame* blame) const + void Blame::Destroy::operator() (git_blame * blame) const { git_blame_free(blame); } From 79ebcf5cd98747391ae089ce270dfae2ba56e27a Mon Sep 17 00:00:00 2001 From: ballessay Date: Sat, 13 Jul 2019 18:30:35 +0200 Subject: [PATCH 136/171] Fix blame example --- examples/blame.cpp | 244 ++++++++++++++++++++++----------------------- 1 file changed, 122 insertions(+), 122 deletions(-) diff --git a/examples/blame.cpp b/examples/blame.cpp index c9b584c..d36d545 100644 --- a/examples/blame.cpp +++ b/examples/blame.cpp @@ -27,34 +27,34 @@ */ struct opts { - char *path; - char *commitspec; - int C; - int M; - int start_line; - int end_line; - int F; + char *path; + char *commitspec; + int C; + int M; + int start_line; + int end_line; + int F; }; static void parse_opts(struct opts *o, int argc, char *argv[]); int main(int argc, char *argv[]) { opts o = {0}; - parse_opts(&o, argc, argv); + parse_opts(&o, argc, argv); - git_blame_options blameopts = GIT_BLAME_OPTIONS_INIT; + git_blame_options blameopts = GIT_BLAME_OPTIONS_INIT; - if (o.M) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; - if (o.C) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; - if (o.F) blameopts.flags |= GIT_BLAME_FIRST_PARENT; + if (o.M) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; + if (o.C) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; + if (o.F) blameopts.flags |= GIT_BLAME_FIRST_PARENT; auto_git_initializer; git::Repository repo("."); - /** - * The commit range comes in "commitish" form. Use the rev-parse API to - * nail down the end points. - */ + /** + * The commit range comes in "commitish" form. Use the rev-parse API to + * nail down the end points. + */ if (o.commitspec) { auto revspec = repo.revparse(o.commitspec); @@ -71,129 +71,129 @@ int main(int argc, char *argv[]) } } - /** Run the blame. */ + /** Run the blame. */ auto blame = repo.blame_file(o.path, blameopts); char spec[1024] = {0}; /** - * Get the raw data inside the blob for output. We use the - * `commitish:path/to/file.txt` format to find it. - */ - if (git_oid_iszero(&blameopts.newest_commit)) - strcpy(spec, "HEAD"); - else - git_oid_tostr(spec, sizeof(spec), &blameopts.newest_commit); - strcat(spec, ":"); - strcat(spec, o.path); + * Get the raw data inside the blob for output. We use the + * `commitish:path/to/file.txt` format to find it. + */ + if (git_oid_iszero(&blameopts.newest_commit)) + strcpy(spec, "HEAD"); + else + git_oid_tostr(spec, sizeof(spec), &blameopts.newest_commit); + strcat(spec, ":"); + strcat(spec, o.path); auto blob = repo.blob_lookup(repo.revparse_single(spec).single()->id()); - char const * rawdata = reinterpret_cast(blob.content()); - size_t rawsize = blob.size(); - - /** Produce the output. */ - int line = 1; - bool break_on_null_hunk = false; - for (size_t i = 0; i < rawsize; ++line) { - const git_blame_hunk *hunk = blame.get_hunk_byline(line); - - if (break_on_null_hunk && !hunk) - break; - - char const * eol = reinterpret_cast(memchr(rawdata + i, '\n', rawsize - i)); - if (hunk) { - break_on_null_hunk = true; - - char oid[10] = {0}; - git_oid_tostr(oid, 10, &hunk->final_commit_id); - char sig[128] = {0}; - snprintf(sig, 127, "%s <%s>", hunk->final_signature->name, hunk->final_signature->email); - - printf("%s ( %-30s %3d) %.*s\n", - oid, - sig, - line, - (int)(eol - rawdata - i), - rawdata + i); - } - - i = (int)(eol - rawdata + 1); - } - - return 0; + char const * rawdata = reinterpret_cast(blob.content()); + size_t rawsize = blob.size(); + + /** Produce the output. */ + int line = 1; + bool break_on_null_hunk = false; + for (size_t i = 0; i < rawsize; ++line) { + const git_blame_hunk *hunk = blame.hunk_byline(line); + + if (break_on_null_hunk && !hunk) + break; + + char const * eol = reinterpret_cast(memchr(rawdata + i, '\n', rawsize - i)); + if (hunk) { + break_on_null_hunk = true; + + char oid[10] = {0}; + git_oid_tostr(oid, 10, &hunk->final_commit_id); + char sig[128] = {0}; + snprintf(sig, 127, "%s <%s>", hunk->final_signature->name, hunk->final_signature->email); + + printf("%s ( %-30s %3d) %.*s\n", + oid, + sig, + line, + (int)(eol - rawdata - i), + rawdata + i); + } + + i = (int)(eol - rawdata + 1); + } + + return 0; } /** Tell the user how to make this thing work. */ static void usage(const char *msg, const char *arg) { - if (msg && arg) - fprintf(stderr, "%s: %s\n", msg, arg); - else if (msg) - fprintf(stderr, "%s\n", msg); - fprintf(stderr, "usage: blame [options] [] \n"); - fprintf(stderr, "\n"); - fprintf(stderr, " example: `HEAD~10..HEAD`, or `1234abcd`\n"); - fprintf(stderr, " -L process only line range n-m, counting from 1\n"); - fprintf(stderr, " -M find line moves within and across files\n"); - fprintf(stderr, " -C find line copies within and across files\n"); - fprintf(stderr, " -F follow only the first parent commits\n"); - fprintf(stderr, "\n"); - exit(1); + if (msg && arg) + fprintf(stderr, "%s: %s\n", msg, arg); + else if (msg) + fprintf(stderr, "%s\n", msg); + fprintf(stderr, "usage: blame [options] [] \n"); + fprintf(stderr, "\n"); + fprintf(stderr, " example: `HEAD~10..HEAD`, or `1234abcd`\n"); + fprintf(stderr, " -L process only line range n-m, counting from 1\n"); + fprintf(stderr, " -M find line moves within and across files\n"); + fprintf(stderr, " -C find line copies within and across files\n"); + fprintf(stderr, " -F follow only the first parent commits\n"); + fprintf(stderr, "\n"); + exit(1); } /** Parse the arguments. */ static void parse_opts(struct opts *o, int argc, char *argv[]) { - int i; - char *bare_args[3] = {0}; - - if (argc < 2) usage(NULL, NULL); - - for (i=1; i= 3) - usage("Invalid argument set", NULL); - bare_args[i] = a; - } - else if (!strcmp(a, "--")) - continue; - else if (!strcasecmp(a, "-M")) - o->M = 1; - else if (!strcasecmp(a, "-C")) - o->C = 1; - else if (!strcasecmp(a, "-F")) - o->F = 1; - else if (!strcasecmp(a, "-L")) { - i++; a = argv[i]; - if (i >= argc) throw std::runtime_error("Not enough arguments to -L"); - if (sscanf(a, "%d,%d", &o->start_line, &o->end_line)-2, "-L format error", NULL) + int i; + char *bare_args[3] = {0}; + + if (argc < 2) usage(NULL, NULL); + + for (i=1; i= 3) + usage("Invalid argument set", NULL); + bare_args[i] = a; + } + else if (!strcmp(a, "--")) + continue; + else if (!strcasecmp(a, "-M")) + o->M = 1; + else if (!strcasecmp(a, "-C")) + o->C = 1; + else if (!strcasecmp(a, "-F")) + o->F = 1; + else if (!strcasecmp(a, "-L")) { + i++; a = argv[i]; + if (i >= argc) throw std::runtime_error("Not enough arguments to -L"); + if (sscanf(a, "%d,%d", &o->start_line, &o->end_line)-2, "-L format error", NULL) std::abort(); - } - else { - /* commit range */ - if (o->commitspec) throw std::runtime_error("Only one commit spec allowed"); - o->commitspec = a; - } - } - - /* Handle the bare arguments */ - if (!bare_args[0]) usage("Please specify a path", NULL); - o->path = bare_args[0]; - if (bare_args[1]) { - /* */ - o->path = bare_args[1]; - o->commitspec = bare_args[0]; - } - if (bare_args[2]) { - /* */ - char spec[128] = {0}; - o->path = bare_args[2]; - sprintf(spec, "%s..%s", bare_args[0], bare_args[1]); - o->commitspec = spec; - } + } + else { + /* commit range */ + if (o->commitspec) throw std::runtime_error("Only one commit spec allowed"); + o->commitspec = a; + } + } + + /* Handle the bare arguments */ + if (!bare_args[0]) usage("Please specify a path", NULL); + o->path = bare_args[0]; + if (bare_args[1]) { + /* */ + o->path = bare_args[1]; + o->commitspec = bare_args[0]; + } + if (bare_args[2]) { + /* */ + char spec[128] = {0}; + o->path = bare_args[2]; + sprintf(spec, "%s..%s", bare_args[0], bare_args[1]); + o->commitspec = spec; + } } From 67248602e0885412715c7e6f43c5c99ba8bd6acc Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 6 Aug 2019 12:05:25 +0300 Subject: [PATCH 137/171] remove usages of deprecated macros --- examples/general.cpp | 6 +++--- src/odb_object.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/general.cpp b/examples/general.cpp index 2a32565..249c0e7 100644 --- a/examples/general.cpp +++ b/examples/general.cpp @@ -122,7 +122,7 @@ int main(int argc, char ** argv) // binary data. For a tree it is a special binary format, so it's unlikely // to be hugely helpful as a raw object. const unsigned char * data = obj.data(); - git_otype otype = obj.type(); + git_object_t otype = obj.type(); // We provide methods to convert from the object type which is an enum, to // a string representation of that value (and vice-versa). @@ -141,7 +141,7 @@ int main(int argc, char ** argv) // it gives you direct access to the key/value properties of Git. Here // we'll write a new blob object that just contains a simple string. // Notice that we have to specify the object type as the `git_otype` enum. - git_oid oid = odb.write("test data", sizeof("test data") - 1, GIT_OBJ_BLOB); + git_oid oid = odb.write("test data", sizeof("test data") - 1, GIT_OBJECT_BLOB); // Now that we've written the object, we can check out what SHA1 was // generated when the object was written to our database. @@ -255,7 +255,7 @@ int main(int argc, char ** argv) // git_signature - name, email, timestamp), and the tag message. Object commit = tag.target(repo); const char * tname = tag.name(); // "test" - git_otype ttype = tag.target_type(); // GIT_OBJ_COMMIT (otype enum) + git_object_t ttype = tag.target_type(); // GIT_OBJ_COMMIT (otype enum) const char * tmessage = tag.message(); // "tag message\n" std::cout << "Tag Message: " << tmessage << std::endl; } diff --git a/src/odb_object.cpp b/src/odb_object.cpp index ffe86e3..b3c2f5a 100644 --- a/src/odb_object.cpp +++ b/src/odb_object.cpp @@ -9,7 +9,7 @@ namespace git git_odb_object_free(obj); } - git_otype OdbObject::type() const + git_object_t OdbObject::type() const { return git_odb_object_type(obj_.get()); } From 8b8451842219c5e366278312fcf817e00f05dc38 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 6 Aug 2019 12:11:45 +0300 Subject: [PATCH 138/171] code cleanup --- examples/rev-list.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/examples/rev-list.cpp b/examples/rev-list.cpp index 6b2fbfb..57f79af 100644 --- a/examples/rev-list.cpp +++ b/examples/rev-list.cpp @@ -1,16 +1,13 @@ -#include -#include - -#include - #include "git2cpp/initializer.h" #include "git2cpp/repo.h" #include "git2cpp/revwalker.h" -extern "C" { #include -#include -} + +#include + +#include +#include using namespace git; @@ -88,7 +85,7 @@ void revwalk_parseopts(Repository const & repo, RevWalker & walk, int nopts, cha int main(int argc, char ** argv) { - git::Initializer threads_initializer; + auto_git_initializer; try { From a0a519c4434d7ae402e101a13cdaa1c51da44f34 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 6 Aug 2019 19:42:16 +0300 Subject: [PATCH 139/171] remove usages of deprecated macros --- include/git2cpp/object.h | 2 +- src/object.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index 7ca7785..ad1929b 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -24,7 +24,7 @@ namespace git explicit operator bool() const { return obj_.operator bool(); } - git_otype type() const; + git_object_t type() const; git_oid const & id() const; git_blob const * as_blob() const; diff --git a/src/object.cpp b/src/object.cpp index d2981e8..fccda57 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -47,7 +47,7 @@ namespace git Tree Object::to_tree() /*&&*/ { - assert(type() == GIT_OBJ_TREE); + assert(type() == GIT_OBJECT_TREE); Tree res(reinterpret_cast(obj_.get()), *repo_); obj_ = nullptr; return res; @@ -55,7 +55,7 @@ namespace git Commit Object::to_commit() /*&&*/ { - assert(type() == GIT_OBJ_COMMIT); + assert(type() == GIT_OBJECT_COMMIT); Commit res(reinterpret_cast(obj_.get()), *repo_); obj_ = nullptr; return res; @@ -63,7 +63,7 @@ namespace git Blob Object::to_blob() /*&&*/ { - assert(type() == GIT_OBJ_BLOB); + assert(type() == GIT_OBJECT_BLOB); Blob res(reinterpret_cast(obj_.get())); obj_ = nullptr; return res; @@ -71,7 +71,7 @@ namespace git Tag Object::to_tag() /*&&*/ { - assert(type() == GIT_OBJ_TAG); + assert(type() == GIT_OBJECT_TAG); Tag res(reinterpret_cast(obj_.get())); obj_ = nullptr; return res; From 02eeae8008481eb62e2e2c875f770090b5970965 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 6 Aug 2019 19:46:32 +0300 Subject: [PATCH 140/171] make methods `Object::as_*` private --- include/git2cpp/object.h | 11 ++++++----- src/object.cpp | 16 ++++++---------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/git2cpp/object.h b/include/git2cpp/object.h index ad1929b..6e00c57 100644 --- a/include/git2cpp/object.h +++ b/include/git2cpp/object.h @@ -27,16 +27,17 @@ namespace git git_object_t type() const; git_oid const & id() const; - git_blob const * as_blob() const; - git_commit const * as_commit() const; - git_tree const * as_tree() const; - git_tag const * as_tag() const; - Commit to_commit() /*&&*/; Tree to_tree() /*&&*/; Blob to_blob() /*&&*/; Tag to_tag() /*&&*/; + private: + git_blob * as_blob(); + git_commit * as_commit(); + git_tree * as_tree(); + git_tag * as_tag(); + private: struct Destroy { void operator() (git_object*) const; }; std::unique_ptr obj_; diff --git a/src/object.cpp b/src/object.cpp index fccda57..48d8ba3 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -32,10 +32,10 @@ namespace git } #define DEFINE_METHOD_AS(type_name, enum_element) \ - git_##type_name const * Object::as_##type_name() const \ + git_##type_name * Object::as_##type_name() \ { \ assert(type() == GIT_OBJ_##enum_element); \ - return reinterpret_cast(obj_.get()); \ + return reinterpret_cast(obj_.get()); \ } DEFINE_METHOD_AS(blob, BLOB) @@ -47,32 +47,28 @@ namespace git Tree Object::to_tree() /*&&*/ { - assert(type() == GIT_OBJECT_TREE); - Tree res(reinterpret_cast(obj_.get()), *repo_); + Tree res(as_tree(), *repo_); obj_ = nullptr; return res; } Commit Object::to_commit() /*&&*/ { - assert(type() == GIT_OBJECT_COMMIT); - Commit res(reinterpret_cast(obj_.get()), *repo_); + Commit res(as_commit(), *repo_); obj_ = nullptr; return res; } Blob Object::to_blob() /*&&*/ { - assert(type() == GIT_OBJECT_BLOB); - Blob res(reinterpret_cast(obj_.get())); + Blob res(as_blob()); obj_ = nullptr; return res; } Tag Object::to_tag() /*&&*/ { - assert(type() == GIT_OBJECT_TAG); - Tag res(reinterpret_cast(obj_.get())); + Tag res(as_tag()); obj_ = nullptr; return res; } From 5ce59c29cf1cddeeaeb69e494852aae88e33e03f Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 3 Sep 2019 10:00:02 +0300 Subject: [PATCH 141/171] update libgit2 to v0.28.3 (issue #12) --- examples/checkout.cpp | 9 ++++----- examples/remote.cpp | 2 +- examples/rev-list.cpp | 2 +- include/git2cpp/reference.h | 2 +- include/git2cpp/tag.h | 2 +- include/git2cpp/tree.h | 2 +- libs/libgit2 | 2 +- src/object.cpp | 4 ++-- src/reference.cpp | 4 ++-- src/tag.cpp | 2 +- src/tree.cpp | 2 +- 11 files changed, 16 insertions(+), 17 deletions(-) diff --git a/examples/checkout.cpp b/examples/checkout.cpp index acd8b0b..e6ba273 100644 --- a/examples/checkout.cpp +++ b/examples/checkout.cpp @@ -201,7 +201,7 @@ void perform_checkout_ref(git::Repository & repo, git::AnnotatedCommit const & t checkout_opts.perfdata_cb = print_perf_data; /** Grab the commit we're interested to move to */ - auto target_commit = repo.commit_lookup(target.commit_id()); + auto target_commit = repo.commit_lookup(target.commit_id()); /** * Perform the checkout so the workdir corresponds to what target_commit * contains. @@ -209,10 +209,9 @@ void perform_checkout_ref(git::Repository & repo, git::AnnotatedCommit const & t * Note that it's okay to pass a git_commit here, because it will be * peeled to a tree. */ - ; if (repo.checkout_tree(target_commit, checkout_opts)) - { - fprintf(stderr, "failed to checkout tree: %s\n", giterr_last()->message); + { + fprintf(stderr, "failed to checkout tree: %s\n", git_error_last()->message); return; } @@ -229,7 +228,7 @@ void perform_checkout_ref(git::Repository & repo, git::AnnotatedCommit const & t err = repo.set_head_detached(target); } if (err != 0) { - fprintf(stderr, "failed to update HEAD reference: %s\n", giterr_last()->message); + fprintf(stderr, "failed to update HEAD reference: %s\n", git_error_last()->message); } } diff --git a/examples/remote.cpp b/examples/remote.cpp index 580401d..90bd93d 100644 --- a/examples/remote.cpp +++ b/examples/remote.cpp @@ -46,7 +46,7 @@ namespace { [[noreturn]] void report_error(const char *message) { - const git_error *lg2err = giterr_last(); + const git_error *lg2err = git_error_last(); const char *lg2msg = "", *lg2spacer = ""; if (lg2err && lg2err->message) diff --git a/examples/rev-list.cpp b/examples/rev-list.cpp index 57f79af..b6e7955 100644 --- a/examples/rev-list.cpp +++ b/examples/rev-list.cpp @@ -107,7 +107,7 @@ int main(int argc, char ** argv) catch (std::exception const & e) { std::cerr << e.what() << std::endl; - if (auto err = giterr_last()) + if (auto err = git_error_last()) { if (err->message) std::cerr << "libgit2 last error: " << err->message << std::endl; diff --git a/include/git2cpp/reference.h b/include/git2cpp/reference.h index d9cbb2b..a71947a 100644 --- a/include/git2cpp/reference.h +++ b/include/git2cpp/reference.h @@ -19,7 +19,7 @@ namespace git explicit operator bool() const { return ref_ != nullptr; } const char * name() const; - git_ref_t type() const; + git_reference_t type() const; git_oid const & target() const; const char * symbolic_target() const; diff --git a/include/git2cpp/tag.h b/include/git2cpp/tag.h index bf6aab1..bb57c9b 100644 --- a/include/git2cpp/tag.h +++ b/include/git2cpp/tag.h @@ -18,7 +18,7 @@ namespace git Object target(Repository const &) const; git_oid const & target_id() const; - git_otype target_type() const; + git_object_t target_type() const; const char * name() const; const char * message() const; diff --git a/include/git2cpp/tree.h b/include/git2cpp/tree.h index da2763f..9ca5821 100644 --- a/include/git2cpp/tree.h +++ b/include/git2cpp/tree.h @@ -14,7 +14,7 @@ namespace git { const char * name() const; git_oid const & id() const; - git_otype type() const; + git_object_t type() const; git_filemode_t filemode() const; private: diff --git a/libs/libgit2 b/libs/libgit2 index 99afd41..7ce88e6 160000 --- a/libs/libgit2 +++ b/libs/libgit2 @@ -1 +1 @@ -Subproject commit 99afd41f1c43c856d39e3b9572d7a2103875a771 +Subproject commit 7ce88e66a19e3b48340abcdd86aeaae1882e63cc diff --git a/src/object.cpp b/src/object.cpp index 48d8ba3..9acef11 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -21,7 +21,7 @@ namespace git git_object_free(obj); } - git_otype Object::type() const + git_object_t Object::type() const { return git_object_type(obj_.get()); } @@ -34,7 +34,7 @@ namespace git #define DEFINE_METHOD_AS(type_name, enum_element) \ git_##type_name * Object::as_##type_name() \ { \ - assert(type() == GIT_OBJ_##enum_element); \ + assert(type() == GIT_OBJECT_##enum_element); \ return reinterpret_cast(obj_.get()); \ } diff --git a/src/reference.cpp b/src/reference.cpp index 0466e67..bf95b39 100644 --- a/src/reference.cpp +++ b/src/reference.cpp @@ -22,14 +22,14 @@ namespace git return git_reference_name(ptr()); } - git_ref_t Reference::type() const + git_reference_t Reference::type() const { return git_reference_type(ptr()); } git_oid const & Reference::target() const { - assert(type() != GIT_REF_SYMBOLIC); + assert(type() != GIT_REFERENCE_SYMBOLIC); return *git_reference_target(ptr()); } diff --git a/src/tag.cpp b/src/tag.cpp index e58ac14..dd5b4fc 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -29,7 +29,7 @@ namespace git return *git_tag_target_id(tag_.get()); } - git_otype Tag::target_type() const + git_object_t Tag::target_type() const { return git_tag_target_type(tag_.get()); } diff --git a/src/tree.cpp b/src/tree.cpp index d9405fa..c315d21 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -82,7 +82,7 @@ namespace git return *git_tree_entry_id(entry_); } - git_otype Tree::BorrowedEntry::type() const + git_object_t Tree::BorrowedEntry::type() const { return git_tree_entry_type(entry_); } From 16813e37c839757bfeea801917c6fcb0143fabaa Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Thu, 5 Sep 2019 09:14:56 +0300 Subject: [PATCH 142/171] examples/blame: code cleanup --- examples/blame.cpp | 79 ++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/examples/blame.cpp b/examples/blame.cpp index d36d545..3a639d8 100644 --- a/examples/blame.cpp +++ b/examples/blame.cpp @@ -27,21 +27,20 @@ */ struct opts { - char *path; - char *commitspec; - int C; - int M; + const char * path; + const char * commitspec = nullptr; int start_line; int end_line; - int F; + bool C = false; + bool M = false; + bool F = false; + + opts(int argc, char *argv[]); }; -static void parse_opts(struct opts *o, int argc, char *argv[]); int main(int argc, char *argv[]) { - opts o = {0}; - parse_opts(&o, argc, argv); - + opts o(argc, argv); git_blame_options blameopts = GIT_BLAME_OPTIONS_INIT; if (o.M) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; @@ -74,26 +73,23 @@ int main(int argc, char *argv[]) /** Run the blame. */ auto blame = repo.blame_file(o.path, blameopts); - char spec[1024] = {0}; - /** * Get the raw data inside the blob for output. We use the * `commitish:path/to/file.txt` format to find it. */ - if (git_oid_iszero(&blameopts.newest_commit)) - strcpy(spec, "HEAD"); - else - git_oid_tostr(spec, sizeof(spec), &blameopts.newest_commit); - strcat(spec, ":"); - strcat(spec, o.path); + std::string spec = git_oid_iszero(&blameopts.newest_commit) + ? "HEAD" + : git::id_to_str(blameopts.newest_commit); + spec += ":"; + spec += o.path; - auto blob = repo.blob_lookup(repo.revparse_single(spec).single()->id()); + auto blob = repo.blob_lookup(repo.revparse_single(spec.c_str()).single()->id()); char const * rawdata = reinterpret_cast(blob.content()); size_t rawsize = blob.size(); /** Produce the output. */ - int line = 1; + size_t line = 1; bool break_on_null_hunk = false; for (size_t i = 0; i < rawsize; ++line) { const git_blame_hunk *hunk = blame.hunk_byline(line); @@ -113,23 +109,21 @@ int main(int argc, char *argv[]) printf("%s ( %-30s %3d) %.*s\n", oid, sig, - line, + (int)line, (int)(eol - rawdata - i), rawdata + i); } - i = (int)(eol - rawdata + 1); + i = eol - rawdata + 1; } return 0; } /** Tell the user how to make this thing work. */ -static void usage(const char *msg, const char *arg) +static void usage(const char *msg) { - if (msg && arg) - fprintf(stderr, "%s: %s\n", msg, arg); - else if (msg) + if (msg) fprintf(stderr, "%s\n", msg); fprintf(stderr, "usage: blame [options] [] \n"); fprintf(stderr, "\n"); @@ -143,12 +137,12 @@ static void usage(const char *msg, const char *arg) } /** Parse the arguments. */ -static void parse_opts(struct opts *o, int argc, char *argv[]) +opts::opts(int argc, char *argv[]) { int i; - char *bare_args[3] = {0}; + const char * bare_args[3] = {}; - if (argc < 2) usage(NULL, NULL); + if (argc < 2) usage(nullptr); for (i=1; i= 3) - usage("Invalid argument set", NULL); + usage("Invalid argument set"); bare_args[i] = a; } else if (!strcmp(a, "--")) continue; else if (!strcasecmp(a, "-M")) - o->M = 1; + M = true; else if (!strcasecmp(a, "-C")) - o->C = 1; + C = true; else if (!strcasecmp(a, "-F")) - o->F = 1; + F = true; else if (!strcasecmp(a, "-L")) { i++; a = argv[i]; if (i >= argc) throw std::runtime_error("Not enough arguments to -L"); - if (sscanf(a, "%d,%d", &o->start_line, &o->end_line)-2, "-L format error", NULL) + if (sscanf(a, "%d,%d", &start_line, &end_line) != 2) + { + fprintf(stderr, "-L format error\n"); std::abort(); + } } else { /* commit range */ - if (o->commitspec) throw std::runtime_error("Only one commit spec allowed"); - o->commitspec = a; + if (commitspec) throw std::runtime_error("Only one commit spec allowed"); + commitspec = a; } } /* Handle the bare arguments */ - if (!bare_args[0]) usage("Please specify a path", NULL); - o->path = bare_args[0]; + if (!bare_args[0]) usage("Please specify a path"); + path = bare_args[0]; if (bare_args[1]) { /* */ - o->path = bare_args[1]; - o->commitspec = bare_args[0]; + path = bare_args[1]; + commitspec = bare_args[0]; } if (bare_args[2]) { /* */ char spec[128] = {0}; - o->path = bare_args[2]; + path = bare_args[2]; sprintf(spec, "%s..%s", bare_args[0], bare_args[1]); - o->commitspec = spec; + commitspec = spec; } } From 38d5c26bca91bebca2aee47284772cdf2ee678e2 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 17 Jan 2020 10:58:02 +0300 Subject: [PATCH 143/171] examples/log: code cleanup --- examples/log.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/examples/log.cpp b/examples/log.cpp index 50dd947..47a9b29 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -156,36 +156,34 @@ static void print_time(const git_time * intime, const char * prefix) static void print_commit(git::Commit const & commit) { - int i, count; - const git_signature * sig; - const char *scan, *eol; - printf("commit %s\n", git::id_to_str(commit.id()).c_str()); - if ((count = (int)commit.parents_num()) > 1) + const auto count = commit.parents_num(); + if (count > 1) { printf("Merge:"); - for (i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) { printf(" %s", git::id_to_str(commit.parent_id(i), 7).c_str()); } printf("\n"); } - if ((sig = commit.author()) != NULL) + if (auto sig = commit.author()) { printf("Author: %s <%s>\n", sig->name, sig->email); print_time(&sig->when, "Date: "); } printf("\n"); - for (scan = commit.message(); scan && *scan;) + for (const char* scan = commit.message(); scan && *scan;) { - for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */ + const char *eol = scan; + for (; *eol && *eol != '\n'; ++eol) /* find eol */ ; printf(" %.*s\n", (int)(eol - scan), scan); - scan = *eol ? eol + 1 : NULL; + scan = *eol ? eol + 1 : nullptr; } printf("\n"); } From 45762e692d202cb80b3d07f5da7e2f85191b6608 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sat, 1 Feb 2020 11:33:35 +0300 Subject: [PATCH 144/171] + Repository::checkout_head --- include/git2cpp/repo.h | 1 + src/repo.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 71eee3d..e3839c5 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -137,6 +137,7 @@ namespace git /// @return raw error code int checkout_tree(Commit const &, git_checkout_options const &); + int checkout_head(git_checkout_options const &); /// @return raw error code int set_head(char const* ref); diff --git a/src/repo.cpp b/src/repo.cpp index 952b50f..8cc8306 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -521,6 +521,11 @@ namespace git return git_checkout_tree(repo_.get(), reinterpret_cast(commit.ptr()), &options); } + int Repository::checkout_head(git_checkout_options const & options) + { + return git_checkout_head(repo_.get(), &options); + } + int Repository::set_head(char const* ref) { return git_repository_set_head(repo_.get(), ref); From 1fb9e6a84cdaea8ab146eb6a5846d631b575408e Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 1 May 2020 19:37:38 +0300 Subject: [PATCH 145/171] + missing destructor for git::Remote --- include/git2cpp/remote.h | 6 +++++- src/remote.cpp | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/git2cpp/remote.h b/include/git2cpp/remote.h index 9bee445..95c3def 100644 --- a/include/git2cpp/remote.h +++ b/include/git2cpp/remote.h @@ -1,5 +1,7 @@ #pragma once +#include + struct git_remote; namespace git @@ -12,10 +14,12 @@ namespace git private: friend struct Repository; + struct Destroy { void operator() (git_remote*) const; }; + explicit Remote(git_remote * remote) : remote_(remote) {} - git_remote * remote_; + std::unique_ptr remote_; }; } diff --git a/src/remote.cpp b/src/remote.cpp index 040660b..f7e881a 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -6,11 +6,16 @@ namespace git { const char * Remote::url() const { - return git_remote_url(remote_); + return git_remote_url(remote_.get()); } const char * Remote::pushurl() const { - return git_remote_pushurl(remote_); + return git_remote_pushurl(remote_.get()); + } + + void Remote::Destroy::operator()(git_remote * remote) const + { + git_remote_free(remote); } } From d290f4436b4067387343bdc00f20a069103103d2 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 1 May 2020 20:15:52 +0300 Subject: [PATCH 146/171] initial implementation of Remote::fetch, only few options are supported --- include/git2cpp/remote.h | 14 ++++++++++++++ src/remote.cpp | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/include/git2cpp/remote.h b/include/git2cpp/remote.h index 95c3def..8630f63 100644 --- a/include/git2cpp/remote.h +++ b/include/git2cpp/remote.h @@ -3,6 +3,9 @@ #include struct git_remote; +struct git_oid; +struct git_transfer_progress; +struct git_cred; namespace git { @@ -11,6 +14,17 @@ namespace git const char * url() const; const char * pushurl() const; + struct FetchCallbacks + { + virtual void update_tips(char const * refname, git_oid const & a, git_oid const & b) {} + virtual void sideband_progress(char const * str, int len) {} + virtual void transfer_progress(git_transfer_progress const &) {} + + virtual git_cred* acquire_cred(const char * url, const char * username_from_url, unsigned int allowed_types) = 0; + }; + + void fetch(FetchCallbacks &, char const * reflog_message = nullptr); + private: friend struct Repository; diff --git a/src/remote.cpp b/src/remote.cpp index f7e881a..b39f9aa 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -14,6 +14,41 @@ namespace git return git_remote_pushurl(remote_.get()); } + void Remote::fetch(FetchCallbacks & callbacks, char const * reflog_message) + { + git_fetch_options opts = GIT_FETCH_OPTIONS_INIT; + opts.callbacks.payload = &callbacks; + + opts.callbacks.update_tips = [] (char const * refname, git_oid const * a, git_oid const * b, void * data) + { + auto callbacks = static_cast(data); + callbacks->update_tips(refname, *a, *b); + return 0; + }; + opts.callbacks.sideband_progress = [] (char const * str, int len, void * data) + { + auto callbacks = static_cast(data); + callbacks->sideband_progress(str, len); + return 0; + }; + opts.callbacks.transfer_progress = [] (git_transfer_progress const * stats, void * data) + { + auto callbacks = static_cast(data); + callbacks->transfer_progress(*stats); + return 0; + }; + opts.callbacks.credentials = [] (git_cred ** out, char const *url, char const * user_from_url, unsigned int allowed_types, void * data) + { + auto callbacks = static_cast(data); + auto cred = callbacks->acquire_cred(url, user_from_url, allowed_types); + if (!cred) + return -1; + *out = cred; + return 0; + }; + git_remote_fetch(remote_.get(), nullptr, &opts, reflog_message); + } + void Remote::Destroy::operator()(git_remote * remote) const { git_remote_free(remote); From a5e738dd86b2bdcdd4beb2589023a3a2505c5890 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 29 Jun 2020 14:26:59 +0300 Subject: [PATCH 147/171] + Reference::has_same_target_as --- include/git2cpp/reference.h | 2 ++ src/reference.cpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/include/git2cpp/reference.h b/include/git2cpp/reference.h index a71947a..d9dc98b 100644 --- a/include/git2cpp/reference.h +++ b/include/git2cpp/reference.h @@ -23,6 +23,8 @@ namespace git git_oid const & target() const; const char * symbolic_target() const; + bool has_same_target_as(Reference const & other) const; + private: friend struct Repository; git_reference * ptr() const { return ref_.get(); } diff --git a/src/reference.cpp b/src/reference.cpp index bf95b39..ed94531 100644 --- a/src/reference.cpp +++ b/src/reference.cpp @@ -37,4 +37,9 @@ namespace git { return git_reference_symbolic_target(ptr()); } + + bool Reference::has_same_target_as(Reference const & other) const + { + return git_oid_equal(&target(), &other.target()); + } } From 5a85ca76ac15ffa224a38ac1d18c822359812479 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 6 Jul 2020 19:38:19 +0300 Subject: [PATCH 148/171] + Repository::set_head_detached(git_oid) --- include/git2cpp/repo.h | 1 + src/repo.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index e3839c5..fb22afa 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -141,6 +141,7 @@ namespace git /// @return raw error code int set_head(char const* ref); + int set_head_detached(git_oid const&); int set_head_detached(AnnotatedCommit const&); Blame blame_file(const char * path, git_blame_options const &); diff --git a/src/repo.cpp b/src/repo.cpp index 8cc8306..d54e55b 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -531,6 +531,11 @@ namespace git return git_repository_set_head(repo_.get(), ref); } + int Repository::set_head_detached(git_oid const & commit) + { + return git_repository_set_head_detached(repo_.get(), &commit); + } + int Repository::set_head_detached(AnnotatedCommit const& commit) { return git_repository_set_head_detached_from_annotated(repo_.get(), commit.ptr()); From c2ea92d1366dd623a56987eaa2fe89ae94c35879 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 6 Jul 2020 22:51:11 +0300 Subject: [PATCH 149/171] Repository::braches(): + option to filter by reference kind --- include/git2cpp/repo.h | 2 +- src/repo.cpp | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index fb22afa..01eeb14 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -87,7 +87,7 @@ namespace git StrArray reference_list() const; - std::vector branches(branch_type) const; + std::vector branches(branch_type, git_reference_t ref_kind = GIT_REFERENCE_ALL) const; Reference create_branch(const char * name, Commit const & target, bool force); diff --git a/src/repo.cpp b/src/repo.cpp index d54e55b..84606ce 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -185,6 +185,11 @@ namespace git return *ref_; } + Reference * operator->() + { + return &*ref_; + } + private: static git_branch_t convert(branch_type t) { @@ -206,11 +211,14 @@ namespace git internal::optional ref_; }; - std::vector Repository::branches(branch_type type) const + std::vector Repository::branches(branch_type type, git_reference_t ref_kind) const { std::vector res; for (branch_iterator it(repo_.get(), type); it; ++it) - res.emplace_back(std::move(*it)); + { + if (ref_kind == GIT_REFERENCE_ALL || it->type() == ref_kind) + res.emplace_back(std::move(*it)); + } return res; } From f3fe2fb50b1645c0772d9d0a9ebdfee68030925f Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 6 Jul 2020 22:51:27 +0300 Subject: [PATCH 150/171] code cleanup --- src/reference.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reference.cpp b/src/reference.cpp index ed94531..617819a 100644 --- a/src/reference.cpp +++ b/src/reference.cpp @@ -29,7 +29,7 @@ namespace git git_oid const & Reference::target() const { - assert(type() != GIT_REFERENCE_SYMBOLIC); + assert(type() == GIT_REFERENCE_DIRECT); return *git_reference_target(ptr()); } From 9e193ad6decfbc47084c9bdb8fb0799bbff95f33 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 30 Nov 2020 11:26:02 +0300 Subject: [PATCH 151/171] fix copypaste error --- src/status.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/status.cpp b/src/status.cpp index 3fe3af0..0f76bcc 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -25,7 +25,7 @@ namespace git case Status::Options::Show::IndexOnly: return GIT_STATUS_SHOW_INDEX_ONLY; case Status::Options::Show::WorkdirOnly: - return GIT_STATUS_SHOW_INDEX_ONLY; + return GIT_STATUS_SHOW_WORKDIR_ONLY; default: return GIT_STATUS_SHOW_INDEX_AND_WORKDIR; } From 7fd98b0bdb37d5d3a5487b69e13f5609f87ce7bc Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 30 Nov 2020 11:27:06 +0300 Subject: [PATCH 152/171] + Repository::amend_commit --- include/git2cpp/repo.h | 2 ++ src/repo.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index 01eeb14..b58b114 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -122,6 +122,8 @@ namespace git Commit const & parent, const char * message_encoding = nullptr); + git_oid amend_commit(Commit const & commit_to_amend, const char * update_ref, const char * message, Tree const & tree); + void reset_default(Commit const &, git_strarray const & pathspecs); void file_diff(std::string const & old_path, git_oid const & old_id, diff --git a/src/repo.cpp b/src/repo.cpp index 84606ce..514852a 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -383,6 +383,14 @@ namespace git return res; } + git_oid Repository::amend_commit(Commit const & commit_to_amend, const char * update_ref, const char * message, Tree const & tree) + { + git_oid res; + auto op_res = git_commit_amend(&res, commit_to_amend.ptr(), update_ref, nullptr, nullptr, nullptr, message, tree.ptr()); + assert(op_res == GIT_OK); + return res; + } + namespace { Object tree_entry_to_object(git_tree_entry const * entry, Repository const & repo, git_repository * repo_ptr) From e58632d2ec94add20ca26d60f0af17895e0bbe5d Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 29 Aug 2021 14:23:31 +0300 Subject: [PATCH 153/171] update libgit2 to v1.1.0 --- CMakeLists.txt | 2 +- include/git2cpp/remote.h | 8 ++++---- include/git2cpp/str_array.h | 2 +- libs/libgit2 | 2 +- src/remote.cpp | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f6011e..e9712f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ project (libgit2cpp) -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5.1) # Build options OPTION(USE_BOOST "Enable use of boost header libraries" OFF) diff --git a/include/git2cpp/remote.h b/include/git2cpp/remote.h index 8630f63..1908623 100644 --- a/include/git2cpp/remote.h +++ b/include/git2cpp/remote.h @@ -4,8 +4,8 @@ struct git_remote; struct git_oid; -struct git_transfer_progress; -struct git_cred; +struct git_indexer_progress; +struct git_credential; namespace git { @@ -18,9 +18,9 @@ namespace git { virtual void update_tips(char const * refname, git_oid const & a, git_oid const & b) {} virtual void sideband_progress(char const * str, int len) {} - virtual void transfer_progress(git_transfer_progress const &) {} + virtual void transfer_progress(git_indexer_progress const &) {} - virtual git_cred* acquire_cred(const char * url, const char * username_from_url, unsigned int allowed_types) = 0; + virtual git_credential* acquire_cred(const char * url, const char * username_from_url, unsigned int allowed_types) = 0; }; void fetch(FetchCallbacks &, char const * reflog_message = nullptr); diff --git a/include/git2cpp/str_array.h b/include/git2cpp/str_array.h index 5345de5..6c02abc 100644 --- a/include/git2cpp/str_array.h +++ b/include/git2cpp/str_array.h @@ -36,7 +36,7 @@ namespace git ~StrArray() { - git_strarray_free(&str_array_); + git_strarray_dispose(&str_array_); } private: diff --git a/libs/libgit2 b/libs/libgit2 index 7ce88e6..7f4fa17 160000 --- a/libs/libgit2 +++ b/libs/libgit2 @@ -1 +1 @@ -Subproject commit 7ce88e66a19e3b48340abcdd86aeaae1882e63cc +Subproject commit 7f4fa178629d559c037a1f72f79f79af9c1ef8ce diff --git a/src/remote.cpp b/src/remote.cpp index b39f9aa..04543b9 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -31,13 +31,13 @@ namespace git callbacks->sideband_progress(str, len); return 0; }; - opts.callbacks.transfer_progress = [] (git_transfer_progress const * stats, void * data) + opts.callbacks.transfer_progress = [] (git_indexer_progress const * stats, void * data) { auto callbacks = static_cast(data); callbacks->transfer_progress(*stats); return 0; }; - opts.callbacks.credentials = [] (git_cred ** out, char const *url, char const * user_from_url, unsigned int allowed_types, void * data) + opts.callbacks.credentials = [] (git_credential ** out, char const *url, char const * user_from_url, unsigned int allowed_types, void * data) { auto callbacks = static_cast(data); auto cred = callbacks->acquire_cred(url, user_from_url, allowed_types); From 8f446b47ace5c076a9f2cb875b5ddac64c1c519b Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 18 Oct 2021 22:30:06 +0300 Subject: [PATCH 154/171] fix examples/blame.cpp after update of libgit2 --- examples/blame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/blame.cpp b/examples/blame.cpp index 3a639d8..b20ea01 100644 --- a/examples/blame.cpp +++ b/examples/blame.cpp @@ -77,7 +77,7 @@ int main(int argc, char *argv[]) * Get the raw data inside the blob for output. We use the * `commitish:path/to/file.txt` format to find it. */ - std::string spec = git_oid_iszero(&blameopts.newest_commit) + std::string spec = git_oid_is_zero(&blameopts.newest_commit) ? "HEAD" : git::id_to_str(blameopts.newest_commit); spec += ":"; From c6ea3ab97ee1857fb99e07117c451fccec48f7ae Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Mon, 18 Oct 2021 22:34:03 +0300 Subject: [PATCH 155/171] update libgit2 to v1.3.0 --- examples/blame.cpp | 2 +- examples/log.cpp | 2 +- examples/rev-list.cpp | 2 +- examples/rev-parse.cpp | 2 +- libs/libgit2 | 2 +- src/revspec.cpp | 8 ++++---- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/blame.cpp b/examples/blame.cpp index b20ea01..dc589e3 100644 --- a/examples/blame.cpp +++ b/examples/blame.cpp @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) { auto revspec = repo.revparse(o.commitspec); - if (revspec.flags() & GIT_REVPARSE_SINGLE) + if (revspec.flags() & GIT_REVSPEC_SINGLE) { blameopts.newest_commit = revspec.single()->id(); } diff --git a/examples/log.cpp b/examples/log.cpp index 47a9b29..aa04446 100644 --- a/examples/log.cpp +++ b/examples/log.cpp @@ -118,7 +118,7 @@ void add_revision(struct log_state * s, const char * revstr) git::Revspec::Range const & range = *revs.range(); push_rev(s, range.to, hide); - if ((revs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) + if ((revs.flags() & GIT_REVSPEC_MERGE_BASE) != 0) { git_oid base = s->repo->merge_base(range); push_rev(s, s->repo->commit_lookup(base), hide); diff --git a/examples/rev-list.cpp b/examples/rev-list.cpp index b6e7955..3adc8c5 100644 --- a/examples/rev-list.cpp +++ b/examples/rev-list.cpp @@ -28,7 +28,7 @@ void push_range(Repository const & repo, RevWalker const & walk, const char * ra { auto revspec = repo.revparse(range); - if (revspec.flags() & GIT_REVPARSE_MERGE_BASE) + if (revspec.flags() & GIT_REVSPEC_MERGE_BASE) { /* TODO: support "..." */ throw std::runtime_error("unsupported operation"); diff --git a/examples/rev-parse.cpp b/examples/rev-parse.cpp index 37bf368..9c14b1e 100644 --- a/examples/rev-parse.cpp +++ b/examples/rev-parse.cpp @@ -43,7 +43,7 @@ void parse_revision(parse_state & ps, const char * revstr) auto const & range = *rs.range(); std::cout << id_to_str(range.to.id()) << std::endl; - if ((rs.flags() & GIT_REVPARSE_MERGE_BASE) != 0) + if ((rs.flags() & GIT_REVSPEC_MERGE_BASE) != 0) { git_oid base = ps.repo->merge_base(range); std::cout << id_to_str(base) << std::endl; diff --git a/libs/libgit2 b/libs/libgit2 index 7f4fa17..b7bad55 160000 --- a/libs/libgit2 +++ b/libs/libgit2 @@ -1 +1 @@ -Subproject commit 7f4fa178629d559c037a1f72f79f79af9c1ef8ce +Subproject commit b7bad55e4bb0a285b073ba5e02b01d3f522fc95d diff --git a/src/revspec.cpp b/src/revspec.cpp index 0de9d5a..ba3b9cd 100644 --- a/src/revspec.cpp +++ b/src/revspec.cpp @@ -3,14 +3,14 @@ namespace git { Revspec::Revspec(git_object * single, Repository const & repo) - : flags_(GIT_REVPARSE_SINGLE) + : flags_(GIT_REVSPEC_SINGLE) , revspec_(single, repo) { } Revspec::Revspec(git_revspec const & revspec, Repository const & repo) : flags_(revspec.flags) - , revspec_((revspec.flags & GIT_REVPARSE_SINGLE) + , revspec_((revspec.flags & GIT_REVSPEC_SINGLE) ? Range(revspec.from, repo) : Range(revspec, repo)) { @@ -18,7 +18,7 @@ namespace git Object * Revspec::single() { - if (flags_ & GIT_REVPARSE_SINGLE) + if (flags_ & GIT_REVSPEC_SINGLE) return &revspec_.from; else return nullptr; @@ -26,7 +26,7 @@ namespace git Revspec::Range const * Revspec::range() const { - if (flags_ & GIT_REVPARSE_SINGLE) + if (flags_ & GIT_REVSPEC_SINGLE) return nullptr; else return &revspec_; From 385f56d8abfe4da2dfaa7c82628f689cf286a727 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Tue, 16 Nov 2021 09:43:39 +0300 Subject: [PATCH 156/171] 'clone' exported from libgit2 examples (#15) --- CMakeLists.txt | 1 + examples/clone.cpp | 130 +++++++++++++++++++++++++++++++++++++++ include/git2cpp/remote.h | 4 ++ include/git2cpp/repo.h | 15 +++++ src/remote.cpp | 10 ++- src/repo.cpp | 23 +++++++ 6 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 examples/clone.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e9712f4..b7db2c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ if(BUILD_LIBGIT2CPP_EXAMPLES) checkout ls-files blame + clone ) foreach (example ${examples}) diff --git a/examples/clone.cpp b/examples/clone.cpp new file mode 100644 index 0000000..ee5d266 --- /dev/null +++ b/examples/clone.cpp @@ -0,0 +1,130 @@ +#include "git2cpp/initializer.h" +#include "git2cpp/remote.h" +#include "git2cpp/repo.h" + +#include + +#include + +/* Define the printf format specifer to use for size_t output */ +#if defined(_MSC_VER) || defined(__MINGW32__) +# define PRIuZ "Iu" +# define PRIxZ "Ix" +# define PRIdZ "Id" +#else +# define PRIuZ "zu" +# define PRIxZ "zx" +# define PRIdZ "zd" +#endif + +namespace +{ + struct progress_data + { + git_indexer_progress fetch_progress; + size_t completed_steps; + size_t total_steps; + const char * path; + + void print() + { + int network_percent = fetch_progress.total_objects > 0 ? (100 * fetch_progress.received_objects) / fetch_progress.total_objects : 0; + int index_percent = fetch_progress.total_objects > 0 ? (100 * fetch_progress.indexed_objects) / fetch_progress.total_objects : 0; + + int checkout_percent = total_steps > 0 + ? (int)((100 * completed_steps) / total_steps) + : 0; + size_t kbytes = fetch_progress.received_bytes / 1024; + + if (fetch_progress.total_objects && + fetch_progress.received_objects == fetch_progress.total_objects) + { + printf("Resolving deltas %u/%u\r", + fetch_progress.indexed_deltas, + fetch_progress.total_deltas); + } + else + { + printf("net %3d%% (%4" PRIuZ " kb, %5u/%5u) / idx %3d%% (%5u/%5u) / chk %3d%% (%4" PRIuZ "/%4" PRIuZ")%s\n", + network_percent, kbytes, + fetch_progress.received_objects, fetch_progress.total_objects, + index_percent, fetch_progress.indexed_objects, fetch_progress.total_objects, + checkout_percent, + completed_steps, total_steps, + path); + } + } + }; + + void checkout_progress(const char * path, size_t cur, size_t tot, void * payload) + { + progress_data * pd = static_cast(payload); + pd->completed_steps = cur; + pd->total_steps = tot; + pd->path = path; + pd->print(); + } + + struct FetchCallbacks final : git::Remote::FetchCallbacks + { + FetchCallbacks(progress_data & pd) + : pd_(pd) + { + } + + void sideband_progress(char const * str, int len) override + { + printf("remote: %.*s", len, str); + fflush(stdout); + } + + void transfer_progress(git_indexer_progress const & progress) override + { + pd_.fetch_progress = progress; + pd_.print(); + } + + git_credential * acquire_cred(const char * url, const char * username_from_url, unsigned allowed_types) override + { + return nullptr; + } + + private: + progress_data & pd_; + }; +} + +int main(int argc, char ** argv) +{ + /* Validate args */ + if (argc != 3) + { + printf("USAGE: %s \n", argv[0]); + return EXIT_FAILURE; + } + + auto_git_initializer; + + progress_data pd = {{0}}; + FetchCallbacks fetch_callbacks(pd); + git_checkout_options checkout_opts = {GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE}; + /* Set up options */ + checkout_opts.progress_cb = checkout_progress; + checkout_opts.progress_payload = &pd; + const char * url = argv[1]; + const char * path = argv[2]; + /* Do the clone */ + try + { + git::Repository::clone(url, path, checkout_opts, fetch_callbacks); + } + catch (git::repository_clone_error err) + { + printf("\n"); + if (auto detailed_info = std::get_if(&err.data)) + printf("ERROR %d: %s\n", detailed_info->klass, detailed_info->message); + else + printf("ERROR %d: no detailed info\n", std::get(err.data)); + return EXIT_FAILURE; + } +} diff --git a/include/git2cpp/remote.h b/include/git2cpp/remote.h index 1908623..917e315 100644 --- a/include/git2cpp/remote.h +++ b/include/git2cpp/remote.h @@ -16,6 +16,10 @@ namespace git struct FetchCallbacks { + protected: + ~FetchCallbacks() = default; + + public: virtual void update_tips(char const * refname, git_oid const & a, git_oid const & b) {} virtual void sideband_progress(char const * str, int len) {} virtual void transfer_progress(git_indexer_progress const &) {} diff --git a/include/git2cpp/repo.h b/include/git2cpp/repo.h index b58b114..9b4ab3e 100644 --- a/include/git2cpp/repo.h +++ b/include/git2cpp/repo.h @@ -22,6 +22,7 @@ #include "internal/optional.h" #include +#include #include struct git_blame_options; @@ -33,6 +34,16 @@ namespace git struct missing_head_error {}; + struct repository_clone_error + { + struct detailed_info + { + char const* message; + int klass; + }; + std::variant data; + }; + enum class branch_type { LOCAL, @@ -158,11 +169,15 @@ namespace git Repository(const char * dir, init_tag, git_repository_init_options opts); Repository(std::string const & dir, init_tag); + static Repository clone(const char * url, const char* path, git_checkout_options const &, Remote::FetchCallbacks &); + static internal::optional discover(const char * start_path); private: struct Destroy { void operator() (git_repository *) const; }; std::unique_ptr repo_; + + explicit Repository(git_repository*); }; Object revparse_single(Repository const & repo, const char * spec); diff --git a/src/remote.cpp b/src/remote.cpp index 04543b9..a024701 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -14,8 +14,10 @@ namespace git return git_remote_pushurl(remote_.get()); } - void Remote::fetch(FetchCallbacks & callbacks, char const * reflog_message) + git_fetch_options fetch_options_from_callbacks(Remote::FetchCallbacks & callbacks) { + using FetchCallbacks = Remote::FetchCallbacks; + git_fetch_options opts = GIT_FETCH_OPTIONS_INIT; opts.callbacks.payload = &callbacks; @@ -46,6 +48,12 @@ namespace git *out = cred; return 0; }; + return opts; + } + + void Remote::fetch(FetchCallbacks & callbacks, char const * reflog_message) + { + const auto opts = fetch_options_from_callbacks(callbacks); git_remote_fetch(remote_.get(), nullptr, &opts, reflog_message); } diff --git a/src/repo.cpp b/src/repo.cpp index 514852a..e341a54 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -1,5 +1,7 @@ #include "git2cpp/repo.h" +#include "git2/clone.h" + #include "git2cpp/annotated_commit.h" #include "git2cpp/error.h" #include "git2cpp/internal/optional.h" @@ -22,6 +24,11 @@ namespace git { const Repository::init_tag Repository::init; + Repository::Repository(git_repository * repo) + : repo_(repo) + { + } + Repository::Repository(const char * dir) { git_repository * repo; @@ -55,6 +62,22 @@ namespace git repo_.reset(repo); } + git_fetch_options fetch_options_from_callbacks(Remote::FetchCallbacks &); + + Repository Repository::clone(const char * url, const char* path, git_checkout_options const & checkout_opts, Remote::FetchCallbacks & fetch_callbacks) + { + const git_clone_options clone_opts = { GIT_CLONE_OPTIONS_VERSION, checkout_opts, fetch_options_from_callbacks(fetch_callbacks) }; + git_repository *cloned_repo = nullptr; + if (auto error = git_clone(&cloned_repo, url, path, &clone_opts)) + { + if (auto err = git_error_last()) + throw repository_clone_error{ repository_clone_error::detailed_info{ err->message, err->klass } }; + else + throw repository_clone_error{ error }; + } + return Repository(cloned_repo); + } + bool Repository::is_bare() const { return git_repository_is_bare(repo_.get()) != 0; From 96ee7acc51fbfb2052580100f976e1e01b21cbe8 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 16 Nov 2021 10:14:27 +0300 Subject: [PATCH 157/171] Drop support of VS 2015 It's too old now, there is VS 2022 already. --- appveyor.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4baf481..cf75efc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,18 +6,10 @@ branches: environment: matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - GENERATOR: "Visual Studio 14 2015" - ARCH: 32 - BOOST: 1_63_0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 GENERATOR: "Visual Studio 15 2017" ARCH: 32 BOOST: 1_65_1 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - GENERATOR: "Visual Studio 14 2015 Win64" - ARCH: 64 - BOOST: 1_63_0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 GENERATOR: "Visual Studio 15 2017 Win64" ARCH: 64 From e6c2545c8696c274b3d17ec5df9be6349f3adb99 Mon Sep 17 00:00:00 2001 From: GravisZro Date: Sun, 4 Jun 2023 07:29:43 -0400 Subject: [PATCH 158/171] Update code for use with libgit2 version 1.7.0 --- examples/cat-file.cpp | 6 +++--- src/diff.cpp | 2 +- src/id_to_str.cpp | 4 ++-- src/repo.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/cat-file.cpp b/examples/cat-file.cpp index c27b80c..1b28176 100644 --- a/examples/cat-file.cpp +++ b/examples/cat-file.cpp @@ -64,7 +64,7 @@ void show_blob(git::Blob const & blob) void show_tree(git::Tree const & tree) { - char oidstr[GIT_OID_HEXSZ + 1]; + char oidstr[GIT_OID_SHA1_HEXSIZE + 1]; for (size_t i = 0, n = tree.entrycount(); i < n; ++i) { @@ -81,7 +81,7 @@ void show_tree(git::Tree const & tree) void show_commit(git::Commit const & commit) { - char oidstr[GIT_OID_HEXSZ + 1]; + char oidstr[GIT_OID_SHA1_HEXSIZE + 1]; git_oid_tostr(oidstr, sizeof(oidstr), &commit.tree_id()); printf("tree %s\n", oidstr); @@ -127,7 +127,7 @@ int main(int argc, char * argv[]) const char *dir = ".", *rev = nullptr; int i, verbose = 0; Action action = Action::NONE; - char oidstr[GIT_OID_HEXSZ + 1]; + char oidstr[GIT_OID_SHA1_HEXSIZE + 1]; for (i = 1; i < argc; ++i) { diff --git a/src/diff.cpp b/src/diff.cpp index 0ff4464..5c8ab85 100644 --- a/src/diff.cpp +++ b/src/diff.cpp @@ -100,7 +100,7 @@ namespace git Buffer Diff::Stats::to_buf(diff::stats::format::type format, size_t width) const { - git_buf buf = GIT_BUF_INIT_CONST(nullptr, 0); + git_buf buf = GIT_BUF_INIT; if (git_diff_stats_to_buf(&buf, stats_.get(), git_diff_stats_format_t(format.value()), width)) throw error_t("git_diff_stats_to_buf fail"); else diff --git a/src/id_to_str.cpp b/src/id_to_str.cpp index 48c48c9..b58dfb5 100644 --- a/src/id_to_str.cpp +++ b/src/id_to_str.cpp @@ -6,12 +6,12 @@ namespace git { std::string id_to_str(git_oid const & oid) { - return id_to_str(oid, GIT_OID_HEXSZ); + return id_to_str(oid, GIT_OID_SHA1_HEXSIZE); } std::string id_to_str(git_oid const & oid, size_t digits_num) { - char buf[GIT_OID_HEXSZ + 1]; + char buf[GIT_OID_SHA1_HEXSIZE + 1]; git_oid_tostr(buf, sizeof(buf), &oid); return std::string(buf, buf + digits_num); } diff --git a/src/repo.cpp b/src/repo.cpp index e341a54..bb59846 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -594,7 +594,7 @@ namespace git internal::optional Repository::discover(const char * start_path) { - git_buf buf = GIT_BUF_INIT_CONST(nullptr, 0); + git_buf buf = GIT_BUF_INIT; if (git_repository_discover(&buf, start_path, 0, nullptr)) return internal::none; return std::string(buf.ptr, buf.size); From eb35b274636b05f7756a973b8c74e5ec65b4d69d Mon Sep 17 00:00:00 2001 From: ballessay Date: Sun, 11 Jun 2023 01:59:35 +0200 Subject: [PATCH 159/171] Fix cmake warning Fixes the following warning: cmake_minimum_required() should be called prior to this top-level project() --- CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7db2c4..19dfadf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ -project (libgit2cpp) cmake_minimum_required(VERSION 3.5.1) +project (libgit2cpp) + # Build options OPTION(USE_BOOST "Enable use of boost header libraries" OFF) @@ -77,14 +78,14 @@ if(BUILD_LIBGIT2CPP_EXAMPLES) blame clone ) - + foreach (example ${examples}) add_executable("${example}-cpp" examples/${example}.cpp) target_link_libraries("${example}-cpp" git2cpp) endforeach(example) - + add_executable(commit-graph-generator examples/commit-graph-generator.cpp) target_link_libraries(commit-graph-generator git2cpp) - + file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) endif() From 664016c0b407322ad370563977e6ca7fce4861e5 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 11 Jun 2023 11:28:53 +0200 Subject: [PATCH 160/171] + missing #include --- include/git2cpp/index.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/git2cpp/index.h b/include/git2cpp/index.h index 28e0bc5..2d899ad 100644 --- a/include/git2cpp/index.h +++ b/include/git2cpp/index.h @@ -4,6 +4,7 @@ #include #include +#include struct git_index; struct git_repository; From 9868e379e805a937197ea9c0bbb5da8918edc413 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 11 Jun 2023 11:29:56 +0200 Subject: [PATCH 161/171] update version of bundled libgit2 after e6c2545c --- CMakeLists.txt | 5 +++-- libs/libgit2 | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7db2c4..901fd2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,10 +46,11 @@ if (BUNDLE_LIBGIT2) target_include_directories(git2cpp PUBLIC libs/libgit2/include ) + target_link_libraries(git2cpp libgit2package) +else() + target_link_libraries(git2cpp LibGit2::LibGit2) endif() -target_link_libraries(git2cpp git2) - set_target_properties(git2cpp PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES diff --git a/libs/libgit2 b/libs/libgit2 index b7bad55..e632535 160000 --- a/libs/libgit2 +++ b/libs/libgit2 @@ -1 +1 @@ -Subproject commit b7bad55e4bb0a285b073ba5e02b01d3f522fc95d +Subproject commit e6325351ceee58cf56f58bdce61b38907805544f From c785afef63f99917167df87b3b63bd76686a93a0 Mon Sep 17 00:00:00 2001 From: "SM9()" Date: Mon, 9 Oct 2023 10:30:01 +0100 Subject: [PATCH 162/171] Update CMakeLists.txt to find and link against libgit2 using PkgConfig. Signed-off-by: Michael Bolden Jnr / SM9(); --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73bee65..0019aa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,9 @@ if (BUNDLE_LIBGIT2) ) target_link_libraries(git2cpp libgit2package) else() - target_link_libraries(git2cpp LibGit2::LibGit2) + find_package(PkgConfig REQUIRED) + pkg_search_module(LibGit2 REQUIRED libgit2) + target_link_libraries(git2cpp ${LibGit2_LIBRARIES}) endif() set_target_properties(git2cpp PROPERTIES From 71fe3641ab06652a9f499375a2392dc6db8e140a Mon Sep 17 00:00:00 2001 From: "SM9()" Date: Mon, 9 Oct 2023 10:39:47 +0100 Subject: [PATCH 163/171] Add CMake installation rules Signed-off-by: Michael Bolden Jnr / SM9(); --- CMakeLists.txt | 2 ++ cmake/InstallConfig.cmake | 1 + cmake/InstallRules.cmake | 60 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 cmake/InstallConfig.cmake create mode 100644 cmake/InstallRules.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 73bee65..21d5e59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,3 +90,5 @@ if(BUILD_LIBGIT2CPP_EXAMPLES) file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) endif() + +include(cmake/InstallRules.cmake) diff --git a/cmake/InstallConfig.cmake b/cmake/InstallConfig.cmake new file mode 100644 index 0000000..d9ce767 --- /dev/null +++ b/cmake/InstallConfig.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/git2cppTargets.cmake") diff --git a/cmake/InstallRules.cmake b/cmake/InstallRules.cmake new file mode 100644 index 0000000..7f126fb --- /dev/null +++ b/cmake/InstallRules.cmake @@ -0,0 +1,60 @@ +set(CMAKE_INSTALL_LIBDIR lib CACHE PATH "") + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) + +set(package git2cpp) + +install( + DIRECTORY include/ + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT git2cpp_Development +) + +install( + TARGETS git2cpp + EXPORT git2cppTargets + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +if (NOT DEFINED VERSION) + set(VERSION "1.0.0") +endif() + +write_basic_package_version_file( + "${package}ConfigVersion.cmake" + VERSION ${VERSION} + COMPATIBILITY SameMajorVersion + ARCH_INDEPENDENT +) + +set( + git2cpp_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/${package}" + CACHE PATH "CMake package config location relative to the install prefix" +) + +mark_as_advanced(git2cpp_INSTALL_CMAKEDIR) + +install( + FILES cmake/InstallConfig.cmake + DESTINATION "${git2cpp_INSTALL_CMAKEDIR}" + RENAME "${package}Config.cmake" + COMPONENT git2cpp_Development +) + +install( + FILES "${PROJECT_BINARY_DIR}/${package}ConfigVersion.cmake" + DESTINATION "${git2cpp_INSTALL_CMAKEDIR}" + COMPONENT git2cpp_Development +) + +install( + EXPORT git2cppTargets + NAMESPACE git2cpp:: + DESTINATION "${git2cpp_INSTALL_CMAKEDIR}" + COMPONENT git2cpp_Development +) + +if(PROJECT_IS_TOP_LEVEL) + include(CPack) +endif() From 8b127ba316c8037b0f9bf0482866ab3d16b612b8 Mon Sep 17 00:00:00 2001 From: "SM9()" Date: Mon, 9 Oct 2023 10:44:50 +0100 Subject: [PATCH 164/171] Add cmake build directories and .idea to .gitignore Signed-off-by: Michael Bolden Jnr / SM9(); --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index a027f93..4ff7967 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ *.swo build *.user +cmake-build-debug/ +cmake-build-release/ +.idea/ From be07c1ab151fcf193515eca6942b0cd818a15968 Mon Sep 17 00:00:00 2001 From: "SM9()" Date: Mon, 9 Oct 2023 11:59:43 +0100 Subject: [PATCH 165/171] Add Version.cmake to extract project version from Git Signed-off-by: Michael Bolden Jnr / SM9(); --- CMakeLists.txt | 6 +++++- cmake/Version.cmake | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 cmake/Version.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 73bee65..f3379a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.5.1) +include(cmake/Version.cmake) + project (libgit2cpp) # Build options @@ -49,7 +51,9 @@ if (BUNDLE_LIBGIT2) ) target_link_libraries(git2cpp libgit2package) else() - target_link_libraries(git2cpp LibGit2::LibGit2) + find_package(PkgConfig REQUIRED) + pkg_search_module(LibGit2 REQUIRED libgit2) + target_link_libraries(git2cpp ${LibGit2_LIBRARIES}) endif() set_target_properties(git2cpp PROPERTIES diff --git a/cmake/Version.cmake b/cmake/Version.cmake new file mode 100644 index 0000000..d61a5e5 --- /dev/null +++ b/cmake/Version.cmake @@ -0,0 +1,33 @@ +set(VERSION "0.0.0" CACHE STRING "libgit2cpp Version") +set(COMMIT_HASH "") +set(COMMIT_COUNT 0) + +find_package(Git) + +if (Git_FOUND AND VERSION STREQUAL "0.0.0") + message(STATUS "No version defined, fetching one from git") + + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE COMMIT_COUNT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + + set(VERSION "r${COMMIT_COUNT}.${COMMIT_HASH}") +endif () + +message(STATUS "Version: ${VERSION}") +string(REGEX REPLACE "([0-9]+\\.[0-9]+\\.[0-9]+(\\.[0-9])?)(.*)" "\\1" VERSION_FOR_CMAKE "${VERSION}") +message(STATUS "Version for CMake: ${VERSION_FOR_CMAKE}") + +#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/version.h.in ${CMAKE_CURRENT_SOURCE_DIR}/include/version.h) From a5a411ad8b5d385c557ff74fe54cd07801296845 Mon Sep 17 00:00:00 2001 From: "SM9()" Date: Mon, 9 Oct 2023 12:28:55 +0100 Subject: [PATCH 166/171] Reformat CMakeLists.txt to follow consistent indentation style Signed-off-by: Michael Bolden Jnr / SM9(); --- CMakeLists.txt | 128 ++++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d1c2382..4575e98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,97 +2,97 @@ cmake_minimum_required(VERSION 3.5.1) include(cmake/Version.cmake) -project (libgit2cpp) +project(libgit2cpp) # Build options OPTION(USE_BOOST "Enable use of boost header libraries" OFF) -IF(USE_BOOST) - add_definitions(-DUSE_BOOST=1) - find_package(Boost REQUIRED) - include_directories(${BOOST_INCLUDEDIR}) -ENDIF() +IF (USE_BOOST) + add_definitions(-DUSE_BOOST=1) + find_package(Boost REQUIRED) + include_directories(${BOOST_INCLUDEDIR}) +ENDIF () if (MSVC) - OPTION(BUNDLE_LIBGIT2 "use bundled libgit2" ON) -else() - OPTION(BUNDLE_LIBGIT2 "use bundled libgit2" OFF) -endif() + OPTION(BUNDLE_LIBGIT2 "use bundled libgit2" ON) +else () + OPTION(BUNDLE_LIBGIT2 "use bundled libgit2" OFF) +endif () if (BUNDLE_LIBGIT2) - add_subdirectory(libs/libgit2) -endif() + add_subdirectory(libs/libgit2) +endif () file(GLOB_RECURSE lib_sources - src/*.cpp - include/git2cpp/*.h + src/*.cpp + include/git2cpp/*.h ) if (MSVC AND ($MSVC_VERSION VERSION_GREATER 1900)) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") -endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") +endif () add_library(git2cpp STATIC ${lib_sources}) target_include_directories(git2cpp - PRIVATE - src - PUBLIC - $ + PRIVATE + src + PUBLIC + $ ) if (USE_BOOST) - target_include_directories(git2cpp PUBLIC ${Boost_INCLUDE_DIRS}) -endif() + target_include_directories(git2cpp PUBLIC ${Boost_INCLUDE_DIRS}) +endif () if (BUNDLE_LIBGIT2) - target_include_directories(git2cpp - PUBLIC libs/libgit2/include - ) - target_link_libraries(git2cpp libgit2package) -else() - find_package(PkgConfig REQUIRED) - pkg_search_module(LibGit2 REQUIRED libgit2) - target_link_libraries(git2cpp ${LibGit2_LIBRARIES}) -endif() + target_include_directories(git2cpp + PUBLIC libs/libgit2/include + ) + target_link_libraries(git2cpp libgit2package) +else () + find_package(PkgConfig REQUIRED) + pkg_search_module(LibGit2 REQUIRED libgit2) + target_link_libraries(git2cpp ${LibGit2_LIBRARIES}) +endif () set_target_properties(git2cpp PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED YES - INTERFACE_COMPILE_FEATURES cxx_std_17 + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED YES + INTERFACE_COMPILE_FEATURES cxx_std_17 ) option(BUILD_LIBGIT2CPP_EXAMPLES ON) -if(BUILD_LIBGIT2CPP_EXAMPLES) - set(examples - add - branch - cat-file - diff - log - rev-list - showindex - status - init - rev-parse - general - remote - checkout - ls-files - blame - clone - ) - - foreach (example ${examples}) - add_executable("${example}-cpp" examples/${example}.cpp) - target_link_libraries("${example}-cpp" git2cpp) - endforeach(example) - - add_executable(commit-graph-generator examples/commit-graph-generator.cpp) - target_link_libraries(commit-graph-generator git2cpp) - - file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) -endif() +if (BUILD_LIBGIT2CPP_EXAMPLES) + set(examples + add + branch + cat-file + diff + log + rev-list + showindex + status + init + rev-parse + general + remote + checkout + ls-files + blame + clone + ) + + foreach (example ${examples}) + add_executable("${example}-cpp" examples/${example}.cpp) + target_link_libraries("${example}-cpp" git2cpp) + endforeach (example) + + add_executable(commit-graph-generator examples/commit-graph-generator.cpp) + target_link_libraries(commit-graph-generator git2cpp) + + file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) +endif () include(cmake/InstallRules.cmake) From aa0910922a761b0e69a21f63c1a9b5a9f65742d5 Mon Sep 17 00:00:00 2001 From: "SM9()" Date: Mon, 9 Oct 2023 23:39:07 +0100 Subject: [PATCH 167/171] Refactor CMakeLists.txt and related files for better readability and maintainability. Signed-off-by: Michael Bolden Jnr / SM9(); --- CMakeLists.txt | 97 +++++++++++++--------------------------- cmake/InstallRules.cmake | 10 ++--- examples/CMakeLists.txt | 4 ++ 3 files changed, 39 insertions(+), 72 deletions(-) create mode 100644 examples/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 4575e98..0bf7e0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,98 +1,63 @@ cmake_minimum_required(VERSION 3.5.1) -include(cmake/Version.cmake) +project(libgit2cpp LANGUAGES C CXX) +set(package git2cpp) -project(libgit2cpp) +option(USE_BOOST "Enable use of Boost header libraries" OFF) +option(BUNDLE_LIBGIT2 "Use bundled libgit2" ${MSVC}) +option(BUILD_LIBGIT2CPP_EXAMPLES "Build libgit2cpp examples" ON) -# Build options -OPTION(USE_BOOST "Enable use of boost header libraries" OFF) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +include(Version) -IF (USE_BOOST) - add_definitions(-DUSE_BOOST=1) +if (USE_BOOST) find_package(Boost REQUIRED) + add_definitions(-DUSE_BOOST=1) include_directories(${BOOST_INCLUDEDIR}) -ENDIF () - -if (MSVC) - OPTION(BUNDLE_LIBGIT2 "use bundled libgit2" ON) -else () - OPTION(BUNDLE_LIBGIT2 "use bundled libgit2" OFF) endif () if (BUNDLE_LIBGIT2) add_subdirectory(libs/libgit2) endif () -file(GLOB_RECURSE lib_sources +file(GLOB_RECURSE LIBGIT2CPP_SOURCES src/*.cpp include/git2cpp/*.h ) +add_library(${package} STATIC ${LIBGIT2CPP_SOURCES}) + +set_target_properties(${package} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON + INTERFACE_COMPILE_FEATURES cxx_std_17 +) + if (MSVC AND ($MSVC_VERSION VERSION_GREATER 1900)) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") endif () -add_library(git2cpp STATIC ${lib_sources}) - -target_include_directories(git2cpp - PRIVATE - src - PUBLIC - $ +target_include_directories(${package} + PRIVATE src + PUBLIC $ ) if (USE_BOOST) - target_include_directories(git2cpp PUBLIC ${Boost_INCLUDE_DIRS}) + target_include_directories(${package} PUBLIC ${Boost_INCLUDE_DIRS}) +endif () + +if (BUILD_LIBGIT2CPP_EXAMPLES) + add_subdirectory(examples) + file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) endif () if (BUNDLE_LIBGIT2) - target_include_directories(git2cpp - PUBLIC libs/libgit2/include - ) - target_link_libraries(git2cpp libgit2package) + target_include_directories(${package} PUBLIC libs/libgit2/include) + target_link_libraries(${package} libgit2package) else () find_package(PkgConfig REQUIRED) pkg_search_module(LibGit2 REQUIRED libgit2) - target_link_libraries(git2cpp ${LibGit2_LIBRARIES}) -endif () - -set_target_properties(git2cpp PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED YES - INTERFACE_COMPILE_FEATURES cxx_std_17 -) - -option(BUILD_LIBGIT2CPP_EXAMPLES ON) - -if (BUILD_LIBGIT2CPP_EXAMPLES) - set(examples - add - branch - cat-file - diff - log - rev-list - showindex - status - init - rev-parse - general - remote - checkout - ls-files - blame - clone - ) - - foreach (example ${examples}) - add_executable("${example}-cpp" examples/${example}.cpp) - target_link_libraries("${example}-cpp" git2cpp) - endforeach (example) - - add_executable(commit-graph-generator examples/commit-graph-generator.cpp) - target_link_libraries(commit-graph-generator git2cpp) - - file(COPY test.sh DESTINATION . FILE_PERMISSIONS ${EXE_PERM}) + target_link_libraries(${package} ${LibGit2_LIBRARIES}) endif () -include(cmake/InstallRules.cmake) +include(InstallRules) diff --git a/cmake/InstallRules.cmake b/cmake/InstallRules.cmake index 7f126fb..bf387bd 100644 --- a/cmake/InstallRules.cmake +++ b/cmake/InstallRules.cmake @@ -3,8 +3,6 @@ set(CMAKE_INSTALL_LIBDIR lib CACHE PATH "") include(CMakePackageConfigHelpers) include(GNUInstallDirs) -set(package git2cpp) - install( DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" @@ -12,14 +10,14 @@ install( ) install( - TARGETS git2cpp + TARGETS ${package} EXPORT git2cppTargets INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) if (NOT DEFINED VERSION) set(VERSION "1.0.0") -endif() +endif () write_basic_package_version_file( "${package}ConfigVersion.cmake" @@ -55,6 +53,6 @@ install( COMPONENT git2cpp_Development ) -if(PROJECT_IS_TOP_LEVEL) +if (PROJECT_IS_TOP_LEVEL) include(CPack) -endif() +endif () diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..a6d5cba --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,4 @@ +get_filename_component(CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) +file(GLOB_RECURSE SOURCES ${CURRENT_DIR}/*.cpp) +file(GLOB_RECURSE HEADERS ${CURRENT_DIR}/*.h) +add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS}) From 0242c3921326d3e18f71c7ef888a4779a6e539df Mon Sep 17 00:00:00 2001 From: StillGreen-san <40620628+StillGreen-san@users.noreply.github.com> Date: Tue, 9 Apr 2024 20:19:36 +0200 Subject: [PATCH 168/171] generalize gitignore for default clion cmake build folders --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4ff7967..ee42b85 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,5 @@ *.swo build *.user -cmake-build-debug/ -cmake-build-release/ +cmake-build*/ .idea/ From 38d57a330e8125acdd99ec31e4867e1832fd963d Mon Sep 17 00:00:00 2001 From: StillGreen-san <40620628+StillGreen-san@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:38:04 +0200 Subject: [PATCH 169/171] restore example targets and test script functionality --- examples/CMakeLists.txt | 10 ++++++---- test.sh | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a6d5cba..d840b21 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,4 +1,6 @@ -get_filename_component(CURRENT_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) -file(GLOB_RECURSE SOURCES ${CURRENT_DIR}/*.cpp) -file(GLOB_RECURSE HEADERS ${CURRENT_DIR}/*.h) -add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS}) +file(GLOB_RECURSE LIBGIT2CPP_EXAMPLE_SOURCES *.cpp) +foreach(EXAMPLE_SOURCE ${LIBGIT2CPP_EXAMPLE_SOURCES}) + get_filename_component(EXAMPLE_NAME ${EXAMPLE_SOURCE} NAME_WE) + add_executable(${EXAMPLE_NAME}-cpp ${EXAMPLE_SOURCE}) + target_link_libraries(${EXAMPLE_NAME}-cpp ${package}) +endforeach() diff --git a/test.sh b/test.sh index 3f1f276..a32334a 100755 --- a/test.sh +++ b/test.sh @@ -23,7 +23,7 @@ function test() { local test_name="$1" echo -e "**** test $test_name *********************************\n\n" - local bin="$CWD/$test_name" + local bin="$CWD/examples/$test_name" shift @@ -41,7 +41,7 @@ pushd $REPO test branch-cpp test diff-cpp -test commit-graph-generator . "$CWD/commit-graph.dot" +test commit-graph-generator-cpp . "$CWD/commit-graph.dot" test log-cpp test rev-list-cpp --topo-order HEAD test rev-parse-cpp HEAD From fd126c7e75d7027c5c3118e8b68676b68e17654f Mon Sep 17 00:00:00 2001 From: StillGreen-san <40620628+StillGreen-san@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:52:10 +0200 Subject: [PATCH 170/171] use IMPORTED_TARGET for pkg_search_module & bump min cmake version --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bf7e0f..fa4ba6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5.1) +cmake_minimum_required(VERSION 3.6) project(libgit2cpp LANGUAGES C CXX) set(package git2cpp) @@ -56,8 +56,8 @@ if (BUNDLE_LIBGIT2) target_link_libraries(${package} libgit2package) else () find_package(PkgConfig REQUIRED) - pkg_search_module(LibGit2 REQUIRED libgit2) - target_link_libraries(${package} ${LibGit2_LIBRARIES}) + pkg_search_module(LibGit2 REQUIRED IMPORTED_TARGET libgit2) + target_link_libraries(${package} PkgConfig::LibGit2) endif () include(InstallRules) From e9651575e388d7e5832ff64955b2f3304bac33db Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Sun, 9 Jun 2024 16:26:35 +0200 Subject: [PATCH 171/171] + missing #include --- examples/add.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/add.cpp b/examples/add.cpp index c24721e..d616a5b 100644 --- a/examples/add.cpp +++ b/examples/add.cpp @@ -6,6 +6,8 @@ #include "git2cpp/initializer.h" #include "git2cpp/repo.h" +#include + enum print_options { SKIP = 1,