From fb5f99bf508c6ac6e7382c696114d960439b3093 Mon Sep 17 00:00:00 2001 From: Andrey Davydov Date: Fri, 21 Jun 2019 07:49:30 +0300 Subject: [PATCH 01/43] 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 02/43] + 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 03/43] '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 04/43] 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 05/43] 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 06/43] '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 07/43] 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 08/43] 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 09/43] 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 10/43] 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 11/43] 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 12/43] 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 13/43] 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 14/43] 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 15/43] 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 16/43] + 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 17/43] + 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 18/43] 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 19/43] + 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 20/43] + 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 21/43] 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 22/43] 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 23/43] 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 24/43] + 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 25/43] 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 26/43] 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 27/43] 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 28/43] '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 29/43] 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 30/43] 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 31/43] 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 32/43] + 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 33/43] 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 34/43] 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 35/43] 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 36/43] 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 37/43] 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 38/43] 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 39/43] 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 40/43] 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 41/43] 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 42/43] 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 43/43] + 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,