├── .clang-format ├── .gitignore ├── .gitmodules ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── clang-format.bash ├── img └── logo.png ├── include └── cppgit2 │ ├── annotated_commit.hpp │ ├── apply.hpp │ ├── attribute.hpp │ ├── bitmask_operators.hpp │ ├── blame.hpp │ ├── blob.hpp │ ├── branch.hpp │ ├── checkout.hpp │ ├── cherrypick.hpp │ ├── clone.hpp │ ├── commit.hpp │ ├── config.hpp │ ├── connection_direction.hpp │ ├── credential.hpp │ ├── data_buffer.hpp │ ├── diff.hpp │ ├── fetch.hpp │ ├── file_mode.hpp │ ├── git_exception.hpp │ ├── index.hpp │ ├── indexer.hpp │ ├── libgit2_api.hpp │ ├── merge.hpp │ ├── note.hpp │ ├── object.hpp │ ├── odb.hpp │ ├── oid.hpp │ ├── ownership.hpp │ ├── pack_builder.hpp │ ├── patch.hpp │ ├── pathspec.hpp │ ├── proxy.hpp │ ├── push.hpp │ ├── rebase.hpp │ ├── refdb.hpp │ ├── reference.hpp │ ├── reflog.hpp │ ├── refspec.hpp │ ├── remote.hpp │ ├── repository.hpp │ ├── reset.hpp │ ├── revert.hpp │ ├── revision.hpp │ ├── revparse.hpp │ ├── revspec.hpp │ ├── revwalk.hpp │ ├── signature.hpp │ ├── stash.hpp │ ├── status.hpp │ ├── strarray.hpp │ ├── submodule.hpp │ ├── tag.hpp │ ├── time.hpp │ ├── transaction.hpp │ ├── tree.hpp │ ├── tree_builder.hpp │ └── worktree.hpp ├── samples ├── add_attribute_macro.cpp ├── blame_file.cpp ├── branch_remote_name.cpp ├── cat_file.cpp ├── check_ignore_rules.cpp ├── clone_and_checkout_branch.cpp ├── clone_repository.cpp ├── commit_file.cpp ├── create_bare_repository.cpp ├── create_branch.cpp ├── create_empty_initial_commit.cpp ├── create_remote.cpp ├── create_repository.cpp ├── discover_path.cpp ├── lookup_submodule.cpp ├── open_submodule.cpp ├── pathspec_match_repo_workdir.cpp ├── print_attributes.cpp ├── print_branches.cpp ├── print_commits.cpp ├── print_default_signature.cpp ├── print_diff_index_to_workdir.cpp ├── print_references.cpp ├── print_reflog_head.cpp ├── print_stash_entries.cpp ├── print_status.cpp ├── print_submodules.cpp ├── print_tag_names.cpp ├── print_tags.cpp ├── revwalk_from_head.cpp └── walk_tree.cpp ├── src ├── annotated_commit.cpp ├── attribute.cpp ├── blame.cpp ├── blob.cpp ├── commit.cpp ├── config.cpp ├── credential.cpp ├── data_buffer.cpp ├── diff.cpp ├── index.cpp ├── indexer.cpp ├── merge.cpp ├── note.cpp ├── object.cpp ├── odb.cpp ├── oid.cpp ├── pack_builder.cpp ├── patch.cpp ├── pathspec.cpp ├── rebase.cpp ├── reference.cpp ├── reflog.cpp ├── refspec.cpp ├── remote.cpp ├── repository.cpp ├── revwalk.cpp ├── signature.cpp ├── strarray.cpp ├── submodule.cpp ├── tag.cpp ├── transaction.cpp ├── tree.cpp ├── tree_builder.cpp └── worktree.cpp └── test ├── doctest.hpp ├── main.cpp ├── test_data_buffer.cpp ├── test_oid.cpp ├── test_signature.cpp └── test_strarray.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -2 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Right 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: All 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: false 21 | BinPackArguments: true 22 | BinPackParameters: true 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: false 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | AfterExternBlock: false 33 | BeforeCatch: false 34 | BeforeElse: false 35 | IndentBraces: false 36 | SplitEmptyFunction: true 37 | SplitEmptyRecord: true 38 | SplitEmptyNamespace: true 39 | BreakBeforeBinaryOperators: None 40 | BreakBeforeBraces: Attach 41 | BreakBeforeInheritanceComma: false 42 | BreakBeforeTernaryOperators: true 43 | BreakConstructorInitializersBeforeComma: false 44 | BreakConstructorInitializers: BeforeColon 45 | BreakAfterJavaFieldAnnotations: false 46 | BreakStringLiterals: true 47 | ColumnLimit: 80 48 | CommentPragmas: '^ IWYU pragma:' 49 | CompactNamespaces: false 50 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 51 | ConstructorInitializerIndentWidth: 4 52 | ContinuationIndentWidth: 4 53 | Cpp11BracedListStyle: true 54 | DerivePointerAlignment: false 55 | DisableFormat: false 56 | ExperimentalAutoDetectBinPacking: false 57 | FixNamespaceComments: true 58 | ForEachMacros: 59 | - foreach 60 | - Q_FOREACH 61 | - BOOST_FOREACH 62 | IncludeBlocks: Preserve 63 | IncludeCategories: 64 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 65 | Priority: 2 66 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 67 | Priority: 3 68 | - Regex: '.*' 69 | Priority: 1 70 | IncludeIsMainRegex: '(Test)?$' 71 | IndentCaseLabels: false 72 | IndentPPDirectives: None 73 | IndentWidth: 2 74 | IndentWrappedFunctionNames: false 75 | JavaScriptQuotes: Leave 76 | JavaScriptWrapImports: true 77 | KeepEmptyLinesAtTheStartOfBlocks: true 78 | MacroBlockBegin: '' 79 | MacroBlockEnd: '' 80 | MaxEmptyLinesToKeep: 1 81 | NamespaceIndentation: None 82 | ObjCBlockIndentWidth: 2 83 | ObjCSpaceAfterProperty: false 84 | ObjCSpaceBeforeProtocolList: true 85 | PenaltyBreakAssignment: 2 86 | PenaltyBreakBeforeFirstCallParameter: 19 87 | PenaltyBreakComment: 300 88 | PenaltyBreakFirstLessLess: 120 89 | PenaltyBreakString: 1000 90 | PenaltyExcessCharacter: 1000000 91 | PenaltyReturnTypeOnItsOwnLine: 60 92 | PointerAlignment: Right 93 | RawStringFormats: 94 | - Delimiter: pb 95 | Language: TextProto 96 | BasedOnStyle: google 97 | ReflowComments: true 98 | SortIncludes: true 99 | SortUsingDeclarations: true 100 | SpaceAfterCStyleCast: false 101 | SpaceAfterTemplateKeyword: true 102 | SpaceBeforeAssignmentOperators: true 103 | SpaceBeforeParens: ControlStatements 104 | SpaceInEmptyParentheses: false 105 | SpacesBeforeTrailingComments: 1 106 | SpacesInAngles: false 107 | SpacesInContainerLiterals: true 108 | SpacesInCStyleCastParentheses: false 109 | SpacesInParentheses: false 110 | SpacesInSquareBrackets: false 111 | Standard: Cpp11 112 | TabWidth: 8 113 | UseTab: Never 114 | ... 115 | 116 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .vscode 3 | .DS_Store 4 | main 5 | 6 | # Prerequisites 7 | *.d 8 | 9 | # Compiled Object files 10 | *.slo 11 | *.lo 12 | *.o 13 | *.obj 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Compiled Dynamic libraries 20 | *.so 21 | *.dylib 22 | *.dll 23 | 24 | # Fortran module files 25 | *.mod 26 | *.smod 27 | 28 | # Compiled Static libraries 29 | *.lai 30 | *.la 31 | *.a 32 | *.lib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/libgit2"] 2 | path = ext/libgit2 3 | url = https://github.com/libgit2/libgit2 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | 3 | dist: bionic 4 | 5 | matrix: 6 | include: 7 | - env: CXX=g++-9 CC=gcc-9 8 | addons: 9 | apt: 10 | packages: 11 | - g++-9 12 | sources: 13 | - sourceline: 'ppa:ubuntu-toolchain-r/test' 14 | - env: CXX=g++-8 CC=gcc-8 15 | addons: 16 | apt: 17 | packages: 18 | - g++-8 19 | - env: CXX=g++-7 CC=gcc-7 20 | addons: 21 | apt: 22 | packages: 23 | - g++-7 24 | - env: CXX=g++-6 CC=gcc-6 25 | addons: 26 | apt: 27 | packages: 28 | - g++-6 29 | - env: CXX=g++-5 CC=gcc-5 30 | addons: 31 | apt: 32 | packages: 33 | - g++-5 34 | 35 | - env: CXX=clang++-9 CC=clang-9 36 | addons: 37 | apt: 38 | packages: 39 | - clang-9 40 | - libc++-9-dev 41 | - libc++abi-9-dev 42 | sources: 43 | - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main' 44 | key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' 45 | - env: CXX=clang++-8 CC=clang-8 46 | addons: 47 | apt: 48 | packages: 49 | - clang-8 50 | - libc++-8-dev 51 | - libc++abi-8-dev 52 | - env: CXX=clang++-7 CC=clang-7 53 | addons: 54 | apt: 55 | packages: 56 | - clang-7 57 | - libc++-7-dev 58 | - libc++abi-7-dev 59 | 60 | 61 | script: 62 | - if [[ "$CXX" == clang* ]]; then export CXXFLAGS="-stdlib=libc++"; fi 63 | - git submodule update --init --recursive 64 | - mkdir build && cd build 65 | - cmake .. && make -j20 66 | - ./test/cppgit2_test 67 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(cppgit2) 2 | CMAKE_MINIMUM_REQUIRED(VERSION 3.8) 3 | 4 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 5 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 6 | 7 | # Add libgit2 8 | find_package(PkgConfig) 9 | if(PkgConfig_FOUND) 10 | PKG_CHECK_MODULES(LIBGIT2 libgit2>=0.99) 11 | endif() 12 | if(NOT LIBGIT2_FOUND) 13 | ADD_SUBDIRECTORY(ext/libgit2 ${CMAKE_BINARY_DIR}/lib) 14 | set(LIBGIT2_INCLUDEDIR ext/libgit2/include) 15 | endif() 16 | 17 | INCLUDE(CMakePackageConfigHelpers) 18 | 19 | # Sources for cppgit2 20 | FILE(GLOB CPPGIT2_SOURCES "src/*.cpp") 21 | 22 | # Version information 23 | SET(CPPGIT2_VERSION_MAJOR 0) 24 | SET(CPPGIT2_VERSION_MINOR 1) 25 | SET(CPPGIT2_VERSION_REV 0) 26 | SET(CPPGIT2_VERSION_STRING "${CPPGIT2_VERSION_MAJOR}.${CPPGIT2_VERSION_MINOR}.${CPPGIT2_VERSION_REV}") 27 | 28 | # Build option for shared vs. static lib (Same option as for libgit2) 29 | OPTION(BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON) 30 | 31 | # Build object library 32 | ADD_LIBRARY(CPPGIT2_OBJECT_LIBRARY OBJECT ${CPPGIT2_SOURCES}) 33 | INCLUDE_DIRECTORIES("include" "${LIBGIT2_INCLUDEDIR}" "test") 34 | SET_PROPERTY(TARGET CPPGIT2_OBJECT_LIBRARY PROPERTY CXX_STANDARD 11) 35 | 36 | # Shared libraries need PIC 37 | SET_PROPERTY(TARGET CPPGIT2_OBJECT_LIBRARY PROPERTY POSITION_INDEPENDENT_CODE 1) 38 | 39 | # Build shared/static library 40 | if (BUILD_SHARED_LIBS) 41 | ADD_LIBRARY(cppgit2 SHARED $) 42 | SET_TARGET_PROPERTIES(cppgit2 PROPERTIES 43 | VERSION ${CPPGIT2_VERSION_STRING} 44 | SOVERSION ${CPPGIT2_VERSION_MINOR} 45 | WINDOWS_EXPORT_ALL_SYMBOLS ON) 46 | else () 47 | ADD_LIBRARY(cppgit2 STATIC $) 48 | endif () 49 | SET_TARGET_PROPERTIES(cppgit2 PROPERTIES CXX_STANDARD 11) 50 | TARGET_LINK_LIBRARIES(cppgit2 git2) 51 | 52 | # Copy include directories to build/include 53 | FILE(COPY "include" DESTINATION "${CMAKE_BINARY_DIR}/.") 54 | FILE(COPY "${LIBGIT2_INCLUDEDIR}/git2" DESTINATION "${CMAKE_BINARY_DIR}/include") 55 | FILE(COPY "${LIBGIT2_INCLUDEDIR}/git2.h" DESTINATION "${CMAKE_BINARY_DIR}/include") 56 | 57 | # Build samples 58 | FILE(GLOB SAMPLES "samples/*.cpp") 59 | FOREACH(SAMPLE ${SAMPLES}) 60 | GET_FILENAME_COMPONENT(SAMPLE_EXE ${SAMPLE} NAME_WE) 61 | ADD_EXECUTABLE(${SAMPLE_EXE} ${SAMPLE}) 62 | SET_TARGET_PROPERTIES(${SAMPLE_EXE} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/samples") 63 | TARGET_LINK_LIBRARIES(${SAMPLE_EXE} cppgit2) 64 | SET_PROPERTY(TARGET ${SAMPLE_EXE} PROPERTY CXX_STANDARD 11) 65 | ENDFOREACH() 66 | 67 | # Build tests 68 | FILE(GLOB TESTS "test/*.cpp") 69 | SET_SOURCE_FILES_PROPERTIES(test/main.cpp 70 | PROPERTIES 71 | COMPILE_DEFINITIONS DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) 72 | ADD_EXECUTABLE(cppgit2_test ${TESTS}) 73 | SET_TARGET_PROPERTIES(cppgit2_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test") 74 | TARGET_LINK_LIBRARIES(cppgit2_test cppgit2) 75 | SET_PROPERTY(TARGET cppgit2_test PROPERTY CXX_STANDARD 11) 76 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Pranav Srinivas Kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /clang-format.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | find ./include ./src ./samples -type f \( -iname \*.cpp -o -iname \*.hpp \) | xargs clang-format -style=llvm -i 3 | find ./test -type f \( -iname \*.cpp \) | xargs clang-format -style=llvm -i 4 | -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p-ranav/cppgit2/c8e08a4dbea7ead1b712a6a3333a32ef3bd9ce64/img/logo.png -------------------------------------------------------------------------------- /include/cppgit2/annotated_commit.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace cppgit2 { 7 | 8 | class annotated_commit : public libgit2_api { 9 | public: 10 | // Default construct annotated commit 11 | annotated_commit(); 12 | 13 | // Construct from libgit2 C ptr 14 | // If owned by user, will be free'd in the destructor 15 | annotated_commit(git_annotated_commit *c_ptr, 16 | ownership owner = ownership::libgit2); 17 | 18 | // Cleanup 19 | ~annotated_commit(); 20 | 21 | // Gets the commit ID that the given git_annotated_commit refers to. 22 | oid id() const; 23 | 24 | // Get the refname that the given git_annotated_commit refers to. 25 | std::string refname() const; 26 | 27 | const git_annotated_commit *c_ptr() const; 28 | 29 | private: 30 | friend class repository; 31 | git_annotated_commit *c_ptr_; 32 | ownership owner_; 33 | }; 34 | 35 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/apply.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace cppgit2 { 11 | 12 | class apply : public libgit2_api { 13 | public: 14 | // Possible application locations for git_apply 15 | enum class location { 16 | // Apply the patch to the workdir, leaving the index untouched. 17 | // This is the equivalent of `git apply` with no location argument. 18 | workdir = 0, 19 | // Apply the patch to the index, leaving the working directory 20 | // untouched. This is the equivalent of `git apply --cached 21 | index = 1, 22 | // Apply the patch to both the working directory and the index. 23 | // This is the equivalent of `git apply --index`. 24 | both = 2 25 | }; 26 | 27 | class options : public libgit2_api { 28 | public: 29 | // Default construct apply::options 30 | options() { 31 | if (git_apply_options_init(&default_options_, GIT_APPLY_OPTIONS_VERSION)) 32 | throw git_exception(); 33 | c_ptr_ = &default_options_; 34 | } 35 | 36 | // Construct from libgit2 C ptr 37 | options(git_apply_options *c_ptr) : c_ptr_(c_ptr) {} 38 | 39 | // Version 40 | 41 | unsigned int version() const { return c_ptr_->version; } 42 | 43 | void set_version(unsigned int value) { c_ptr_->version = value; } 44 | 45 | // Flags controlling the behavior of git_apply 46 | enum class flag { 47 | // Don't actually make changes, just test that the patch applies. 48 | // This is the equivalent of `git apply --check`. 49 | check = (1 << 0) 50 | }; 51 | 52 | flag flags() const { return static_cast(c_ptr_->flags); } 53 | 54 | void set_flags(flag flag) { 55 | c_ptr_->flags = static_cast(flag); 56 | } 57 | 58 | // Access libgit2 C ptr 59 | const git_apply_options *c_ptr() const { return c_ptr_; } 60 | 61 | private: 62 | git_apply_options *c_ptr_; 63 | git_apply_options default_options_; 64 | }; 65 | }; 66 | ENABLE_BITMASK_OPERATORS(apply::options::flag); 67 | 68 | }; // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/attribute.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cppgit2 { 8 | 9 | class attribute { 10 | public: 11 | // Possible states for an attribute 12 | enum class attribute_value { 13 | unspecified = 0, // The attribute has been left unspecified 14 | true_, // The attribute has been set 15 | false_, // The attribute has been unset 16 | string // This attribute has a valu 17 | }; 18 | 19 | // Return the value type for a given attribute. 20 | // This can be either TRUE, FALSE, UNSPECIFIED (if the attribute was not set 21 | // at all), or VALUE, if the attribute was set to an actual string. 22 | static attribute_value value(const std::string &attr); 23 | 24 | enum class flag { 25 | // Reading values from index and working directory. 26 | // 27 | // When checking attributes, it is possible to check attribute files 28 | // in both the working directory (if there is one) and the index (if 29 | // there is one). You can explicitly choose where to check and in 30 | // which order using the following flags. 31 | // 32 | // Core git usually checks the working directory then the index, 33 | // except during a checkout when it checks the index first. It will 34 | // use index only for creating archives or for a bare repo (if an 35 | // index has been specified for the bare repo). 36 | file_then_index = 0, 37 | index_then_file = 1, 38 | index_only = 2, 39 | // Controlling extended attribute behavior. 40 | // 41 | // Normally, attribute checks include looking in the /etc (or system 42 | // equivalent) directory for a `gitattributes` file. Passing this 43 | // flag will cause attribute checks to ignore that file. 44 | // equivalent) directory for a `gitattributes` file. Passing the 45 | // `GIT_ATTR_CHECK_NO_SYSTEM` flag will cause attribute checks to 46 | // ignore that file. 47 | // 48 | // Passing the `GIT_ATTR_CHECK_INCLUDE_HEAD` flag will use attributes 49 | // from a `.gitattributes` file in the repository at the HEAD revision. 50 | no_system = (1 << 2), 51 | include_head = (1 << 3) 52 | }; 53 | }; 54 | ENABLE_BITMASK_OPERATORS(attribute::flag); 55 | 56 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/bitmask_operators.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace cppgit2 { 5 | 6 | template struct EnableBitMaskOperators { 7 | static const bool enable = false; 8 | }; 9 | 10 | template 11 | typename std::enable_if::enable, Enum>::type 12 | operator|(Enum lhs, Enum rhs) { 13 | using underlying = typename std::underlying_type::type; 14 | return static_cast(static_cast(lhs) | 15 | static_cast(rhs)); 16 | } 17 | 18 | template 19 | typename std::enable_if::enable, Enum>::type 20 | operator&(Enum lhs, Enum rhs) { 21 | using underlying = typename std::underlying_type::type; 22 | return static_cast(static_cast(lhs) & 23 | static_cast(rhs)); 24 | } 25 | 26 | template 27 | typename std::enable_if::enable, Enum>::type 28 | operator^(Enum lhs, Enum rhs) { 29 | using underlying = typename std::underlying_type::type; 30 | return static_cast(static_cast(lhs) ^ 31 | static_cast(rhs)); 32 | } 33 | 34 | template 35 | typename std::enable_if::enable, Enum>::type 36 | operator~(Enum rhs) { 37 | using underlying = typename std::underlying_type::type; 38 | return static_cast(~static_cast(rhs)); 39 | } 40 | 41 | template 42 | typename std::enable_if::enable, Enum>::type 43 | operator|=(Enum &lhs, Enum rhs) { 44 | using underlying = typename std::underlying_type::type; 45 | lhs = static_cast(static_cast(lhs) | 46 | static_cast(rhs)); 47 | } 48 | 49 | template 50 | typename std::enable_if::enable, Enum>::type 51 | operator&=(Enum &lhs, Enum rhs) { 52 | using underlying = typename std::underlying_type::type; 53 | lhs = static_cast(static_cast(lhs) & 54 | static_cast(rhs)); 55 | } 56 | 57 | template 58 | typename std::enable_if::enable, Enum>::type 59 | operator^=(Enum &lhs, Enum rhs) { 60 | using underlying = typename std::underlying_type::type; 61 | lhs = static_cast(static_cast(lhs) ^ 62 | static_cast(rhs)); 63 | } 64 | 65 | #define ENABLE_BITMASK_OPERATORS(x) \ 66 | template <> struct EnableBitMaskOperators { \ 67 | static const bool enable = true; \ 68 | }; 69 | 70 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/blob.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cppgit2 { 8 | 9 | using blob_size = git_off_t; 10 | 11 | // Always owned by user 12 | // Free'd in destructor 13 | class blob : public libgit2_api { 14 | public: 15 | // Default construct a blob 16 | blob(); 17 | 18 | // Construct a blob from libgit2 C ptr 19 | // Calls git_blob_dup to create a duplicate 20 | blob(const git_blob *c_ptr); 21 | 22 | // Free blob with git_blob_free 23 | ~blob(); 24 | 25 | // Owner repository 26 | class repository owner() const; 27 | 28 | // Create an in-memory copy of a blob 29 | blob copy() const; 30 | 31 | // SHA1 hash for this blob 32 | oid id() const; 33 | 34 | // Determine if the blob content is binary or not 35 | bool is_binary() const; 36 | 37 | // Get read-only buffer with raw contents of this blob 38 | const void *raw_contents() const; 39 | 40 | // Get size in bytes of the contents of this blob 41 | blob_size raw_size() const; 42 | 43 | // Access libgit2 C ptr 44 | const git_blob *c_ptr() const; 45 | 46 | private: 47 | friend class repository; 48 | git_blob *c_ptr_; 49 | }; 50 | 51 | } // namespace cppgit2 52 | -------------------------------------------------------------------------------- /include/cppgit2/branch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace cppgit2 { 6 | 7 | class branch : public libgit2_api { 8 | public: 9 | enum class branch_type { local = 1, remote = 2, all = local | remote }; 10 | }; 11 | 12 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/cherrypick.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cppgit2 { 8 | 9 | class cherrypick : public libgit2_api { 10 | public: 11 | class options : public libgit2_api { 12 | public: 13 | options() : c_ptr_(nullptr) { 14 | auto ret = git_cherrypick_init_options(&default_options_, 15 | GIT_CHERRYPICK_OPTIONS_VERSION); 16 | c_ptr_ = &default_options_; 17 | if (ret != 0) 18 | throw git_exception(); 19 | } 20 | 21 | options(git_cherrypick_options *c_ptr) : c_ptr_(c_ptr) {} 22 | 23 | // Version 24 | unsigned int version() const { return c_ptr_->version; } 25 | void set_version(unsigned int version) { c_ptr_->version = version; } 26 | 27 | // Mainline 28 | // For merge commits, the "mainline" is treated as the parent. 29 | unsigned int mainline() const { return c_ptr_->mainline; } 30 | void set_mainline(unsigned int mainline) { c_ptr_->mainline = mainline; } 31 | 32 | // Checkout options 33 | checkout::options checkout_options() const { 34 | return checkout::options(&c_ptr_->checkout_opts); 35 | } 36 | void set_checkout_options(const checkout::options &checkout_options) { 37 | c_ptr_->checkout_opts = *(checkout_options.c_ptr()); 38 | } 39 | 40 | // Merge options 41 | merge::options merge_options() const { 42 | return merge::options(&c_ptr_->merge_opts); 43 | } 44 | void set_merge_options(const merge::options &merge_options) { 45 | c_ptr_->merge_opts = *(merge_options.c_ptr()); 46 | } 47 | 48 | const git_cherrypick_options *c_ptr() const { return c_ptr_; } 49 | 50 | private: 51 | git_cherrypick_options *c_ptr_; 52 | git_cherrypick_options default_options_; 53 | }; 54 | }; 55 | 56 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/clone.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class clone : public libgit2_api { 12 | public: 13 | class options : public libgit2_api { 14 | public: 15 | options() : c_ptr_(nullptr) { 16 | auto ret = 17 | git_clone_init_options(&default_options_, GIT_CLONE_OPTIONS_VERSION); 18 | c_ptr_ = &default_options_; 19 | if (ret != 0) 20 | throw git_exception(); 21 | } 22 | 23 | options(git_clone_options *c_ptr) : c_ptr_(c_ptr) {} 24 | 25 | // Version 26 | unsigned int version() const { return c_ptr_->version; } 27 | void set_version(unsigned int version) { c_ptr_->version = version; } 28 | 29 | // Checkout options 30 | checkout::options checkout_options() const { 31 | return checkout::options(&c_ptr_->checkout_opts); 32 | } 33 | void set_checkout_options(const checkout::options &checkout_options) { 34 | c_ptr_->checkout_opts = *(checkout_options.c_ptr()); 35 | } 36 | 37 | // Fetch options 38 | fetch::options fetch_options() const { 39 | return fetch::options(&c_ptr_->fetch_opts); 40 | } 41 | void set_fetch_options(const fetch::options &fetch_options) { 42 | c_ptr_->fetch_opts = *(fetch_options.c_ptr()); 43 | } 44 | 45 | // Bare? 46 | bool is_bare() const { return c_ptr_->bare; } 47 | void set_bare(bool value) { c_ptr_->bare = value; } 48 | 49 | // Options for bypassing the git-aware transport on clone. Bypassing 50 | // it means that instead of a fetch, libgit2 will copy the object 51 | // database directory instead of figuring out what it needs, which is 52 | // faster. If possible, it will hardlink the files to save space. 53 | enum class local { 54 | // Auto-detect (default), libgit2 will bypass the git-aware 55 | // transport for local paths, but use a normal fetch for 56 | // `file://` urls. 57 | auto_, 58 | 59 | // Bypass the git-aware transport even for a `file://` url. 60 | local, 61 | 62 | // Do no bypass the git-aware transport 63 | no_local, 64 | 65 | // Bypass the git-aware transport, but do not try to use hardlinks 66 | local_no_links 67 | }; 68 | 69 | // Local 70 | // Whether to use a fetch or copy the object database. 71 | local local_option() const { 72 | return static_cast(c_ptr_->local); 73 | } 74 | void set_local_option(local option) { 75 | c_ptr_->local = static_cast(option); 76 | } 77 | 78 | // Checkout branch name 79 | std::string checkout_branch_name() const { 80 | auto ret = c_ptr_->checkout_branch; 81 | return ret ? std::string(ret) : ""; 82 | } 83 | void set_checkout_branch_name(const std::string &checkout_branch_name) { 84 | c_ptr_->checkout_branch = checkout_branch_name.c_str(); 85 | } 86 | 87 | // Access libgit2 C ptr 88 | const git_clone_options *c_ptr() const { return c_ptr_; } 89 | 90 | private: 91 | git_clone_options *c_ptr_; 92 | git_clone_options default_options_; 93 | }; 94 | }; 95 | 96 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/commit.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace cppgit2 { 14 | 15 | class commit : public libgit2_api { 16 | public: 17 | commit(); 18 | commit(git_commit *c_ptr, ownership owner = ownership::libgit2); 19 | ~commit(); 20 | 21 | // Amend an existing commit by replacing only non-NULL values 22 | void amend(const oid &id, const std::string &update_ref, 23 | const signature &author, const signature &committer, 24 | const std::string &message_encoding, const std::string &message, 25 | const tree &tree); 26 | 27 | // Author of this commit 28 | signature author() const; 29 | 30 | // Long "body" of the commit message 31 | std::string body() const; 32 | 33 | // Committer of this commit 34 | signature committer() const; 35 | 36 | // Duplicate this commit object 37 | commit copy() const; 38 | 39 | // Get an arbitrary header field 40 | std::string operator[](const std::string &field) const; 41 | 42 | // SHA-1 hash of this commit 43 | oid id() const; 44 | 45 | // Full message of this commit 46 | std::string message() const; 47 | 48 | // Get the encoding for the message of a commit, 49 | // as a string representing a standard encoding name 50 | std::string message_encoding() const; 51 | 52 | // Full raw message of this commit 53 | std::string message_raw() const; 54 | 55 | // Get the commit ob`ject that is the < nth gen ancestopr 56 | // of the named commit object. 57 | // 58 | // Returned commit is owned by the caller. 59 | // Passing 0 returns another instance of the base commit itself. 60 | commit ancestor(unsigned long n) const; 61 | 62 | // n is the position of the parent (from 0 to `parentcount`) 63 | commit parent(unsigned int n) const; 64 | 65 | // SHA-1 hash of the parent commit 66 | // n is the position of the parent (from 0 to `parentcount`) 67 | oid parent_id(unsigned int n) const; 68 | 69 | // Number of parents of this commit 70 | unsigned int parent_count() const; 71 | 72 | // Full raw text of this commit's header 73 | std::string raw_header() const; 74 | 75 | // Get the "short" summary of the git commit message 76 | std::string summary() const; 77 | 78 | // Commit time (i.e., committer time) of a commit 79 | epoch_time_seconds time() const; 80 | 81 | // Commit timezone offset (i.e., committer's preferred timezone) 82 | offset_minutes time_offset() const; 83 | 84 | // Get the tree pointed by this commit 85 | cppgit2::tree tree() const; 86 | 87 | // SHA-1 has of the tree pointed to by this commit 88 | // No attempts are made to fetch an object from the ODB 89 | oid tree_id() const; 90 | 91 | // Get owner repository 92 | class repository owner() const; 93 | 94 | // Access libgit2 C ptr 95 | const git_commit *c_ptr() const; 96 | 97 | private: 98 | friend class repository; 99 | git_commit *c_ptr_; 100 | ownership owner_; 101 | }; 102 | 103 | } // namespace cppgit2 104 | -------------------------------------------------------------------------------- /include/cppgit2/connection_direction.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cppgit2 { 4 | 5 | // Direction of the connection 6 | // We need this because we need to know whether 7 | // we should call git-upload-pack or git-receive-pack 8 | // on the remote end when get_refs gets called. 9 | enum class connection_direction { fetch, push }; 10 | 11 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/credential.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cppgit2 { 9 | 10 | // Owned by user, cleaned up in destructor 11 | class credential : public libgit2_api { 12 | public: 13 | // Create a "default" credential usable for Negotiate mechanisms like NTLM or 14 | // Kerberos authentication. 15 | credential(); 16 | 17 | // Create a new plain-text username and password credential object. The 18 | // supplied credential parameter will be internally duplicated. 19 | credential(const std::string &username, const std::string &password); 20 | 21 | // Create a new passphrase-protected ssh key credential object. The supplied 22 | // credential parameter will be internally duplicated. 23 | credential(const std::string &username, const std::string &public_key, 24 | const std::string &private_key, const std::string &passphrase); 25 | 26 | // Create a new ssh key credential object used for querying an ssh-agent. The 27 | // supplied credential parameter will be internally duplicated. 28 | credential(const std::string &username); 29 | 30 | // Create a new ssh keyboard-interactive based credential object. The supplied 31 | // credential parameter will be internally duplicated. 32 | // 33 | // Not much wrapping happening here - More or less same signature as libgit2 34 | credential(const std::string &username, 35 | git_credential_ssh_interactive_cb prompt_callback, void *payload); 36 | 37 | // Create an ssh key credential with a custom signing function. 38 | // 39 | // This lets you use your own function to sign the challenge. 40 | // This function and its credential type is provided for completeness and 41 | // wraps libssh2_userauth_publickey(), which is undocumented. 42 | // 43 | // Not much wrapping happening here - More or less same signature as libgit2 44 | credential(const std::string &username, const std::string &public_key, 45 | git_credential_sign_cb sign_callback, void *payload); 46 | 47 | // Cleanup credential object 48 | ~credential(); 49 | 50 | // Supported credential types 51 | // This represents the various types of authentication methods supported by 52 | // the library. 53 | enum class type { 54 | // a vanilla user/password request 55 | userpass_plaintext = (1u << 0), 56 | 57 | // an ssh key-based authentication request 58 | ssh_key = (1u << 1), 59 | 60 | // an ssh key-based authentication request, with a custom signature 61 | ssh_custom = (1u << 2), 62 | 63 | // an ntlm/negotiate-based authentication request. 64 | default_ = (1u << 3), 65 | 66 | // an ssh interactive authentication request 67 | ssh_interactive = (1u << 4), 68 | 69 | // username-only authentication request 70 | // 71 | // used as a pre-authentication step if the underlying transport 72 | // (eg. ssh, with no username in its url) does not know which username 73 | // to use. 74 | username = (1u << 5), 75 | 76 | // an ssh key-based authentication request 77 | // 78 | // allows credentials to be read from memory instead of files. 79 | // note that because of differences in crypto backend support, it might 80 | // not be functional. 81 | ssh_memory = (1u << 6), 82 | }; 83 | 84 | // Return the username associated with a credential object. 85 | std::string username() const; 86 | 87 | // Check whether a credential object contains username information. 88 | bool has_username() const; 89 | 90 | // Access libgit2 C ptr 91 | const git_credential *c_ptr() const; 92 | 93 | private: 94 | git_credential *c_ptr_; 95 | }; 96 | ENABLE_BITMASK_OPERATORS(credential::type); 97 | 98 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/data_buffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class data_buffer : public libgit2_api { 12 | public: 13 | // Default construct a data buffer using GIT_BUF_INIT 14 | data_buffer(); 15 | 16 | // Construct buffer of size n 17 | // Contains a git_buf with char buffer of size n 18 | data_buffer(size_t n); 19 | 20 | // Construct buffer from libgit2 C ptr 21 | data_buffer(const git_buf *c_ptr); 22 | 23 | // Dispose internal buffer 24 | ~data_buffer(); 25 | 26 | // Check quickly if buffer contains a NUL byte 27 | bool contains_nul() const; 28 | 29 | // Resize buffer allocation to make more space 30 | // Currently, this will never shrink a buffer, only expand it 31 | void grow_to_size(size_t target_size); 32 | 33 | // Check quickly if buffer looks like it contains binary data 34 | bool is_binary() const; 35 | 36 | // Set buffer to a copy of some raw data 37 | void set_buffer(const std::string &buffer); 38 | 39 | // Get string representation of data buffer 40 | std::string to_string() const; 41 | 42 | // Access libgit2 C ptr 43 | git_buf *c_ptr(); 44 | const git_buf *c_ptr() const; 45 | 46 | private: 47 | git_buf c_struct_; 48 | }; 49 | 50 | } // namespace cppgit2 51 | -------------------------------------------------------------------------------- /include/cppgit2/fetch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class fetch : public libgit2_api { 12 | public: 13 | class options : public libgit2_api { 14 | public: 15 | options() : c_ptr_(nullptr) { 16 | auto ret = 17 | git_fetch_init_options(&default_options_, GIT_FETCH_OPTIONS_VERSION); 18 | c_ptr_ = &default_options_; 19 | if (ret != 0) 20 | throw git_exception(); 21 | } 22 | 23 | options(git_fetch_options *c_ptr) : c_ptr_(c_ptr) {} 24 | 25 | // Version 26 | unsigned int version() const { return c_ptr_->version; } 27 | void set_version(unsigned int version) { c_ptr_->version = version; } 28 | 29 | // TODO: Add callbacks to use for this fetch operation 30 | 31 | // Acceptable prune settings when fetching 32 | enum class prune { 33 | // Use the setting from the configuration 34 | unspecified, 35 | 36 | // Force pruning on 37 | prune, 38 | 39 | // Force pruning off 40 | no_prune 41 | }; 42 | 43 | // Prune - Whether to perform a prune after the fetch 44 | prune prune_option() const { 45 | return static_cast(c_ptr_->prune); 46 | } 47 | void set_prune_option(prune option) { 48 | c_ptr_->prune = static_cast(option); 49 | } 50 | 51 | // Update fetchhead 52 | // Whether to write the results to FETCH_HEAD. Defaults to on. Leave this 53 | // default in order to behave like git. 54 | bool update_fetchhead() const { return c_ptr_->update_fetchhead; } 55 | void set_update_fetchhead(bool value) { c_ptr_->update_fetchhead = value; } 56 | 57 | // Automatic tag following option 58 | // Lets us select the --tags option to use. 59 | enum class autotag { 60 | // Use the setting from the configuration 61 | unspecified = 0, 62 | // Ask the server for tags pointing to objects we're already downloading. 63 | auto_, 64 | // Don't ask for any tags beyond the refspecs. 65 | none, 66 | // Ask for the all the tags. 67 | all 68 | }; 69 | 70 | // Download tags 71 | // Determines how to behave regarding tags on the remote, such as 72 | // auto-downloading tags for objects we're downloading or downloading all of 73 | // them. The default is to auto-follow tags. 74 | autotag download_tags_option() const { 75 | return static_cast(c_ptr_->download_tags); 76 | } 77 | void set_download_tags_option(autotag download_tags) { 78 | c_ptr_->download_tags = 79 | static_cast(download_tags); 80 | } 81 | 82 | // Proxy options 83 | proxy::options proxy_options() const { 84 | return proxy::options(&c_ptr_->proxy_opts); 85 | } 86 | void set_proxy_options(const proxy::options &options) { 87 | c_ptr_->proxy_opts = *(options.c_ptr()); 88 | } 89 | 90 | // Custom headers 91 | strarray custom_headers() const { 92 | return strarray(&c_ptr_->custom_headers); 93 | } 94 | void set_custom_headers(const std::vector &headers) { 95 | c_ptr_->custom_headers = *(strarray(headers).c_ptr()); 96 | } 97 | 98 | // Access libgit2 C ptr 99 | const git_fetch_options *c_ptr() const { return c_ptr_; } 100 | 101 | private: 102 | git_fetch_options *c_ptr_; 103 | git_fetch_options default_options_; 104 | }; 105 | }; 106 | 107 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/file_mode.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cppgit2 { 4 | 5 | // Valid modes for index and tree entries. 6 | enum class file_mode { 7 | unreadable = 0000000, 8 | tree = 0040000, 9 | blob = 0100644, 10 | blob_executable = 0100755, 11 | link = 0120000, 12 | commit = 0160000 13 | }; 14 | 15 | } // namespace cppgit2 16 | -------------------------------------------------------------------------------- /include/cppgit2/git_exception.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace cppgit2 { 7 | 8 | class git_exception : public std::exception { 9 | public: 10 | git_exception() { 11 | auto error = git_error_last(); 12 | message_ = error ? error->message : "unknown error"; 13 | } 14 | git_exception(const char *message) : message_(message) {} 15 | git_exception(const std::string &message) : message_(message.c_str()) {} 16 | virtual ~git_exception() throw() {} 17 | virtual const char *what() const throw() { return message_; } 18 | 19 | static void clear() { git_error_clear(); } 20 | 21 | protected: 22 | const char *message_; 23 | }; 24 | 25 | } // namespace cppgit2 26 | -------------------------------------------------------------------------------- /include/cppgit2/indexer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class indexer : public libgit2_api { 12 | public: 13 | // Default construct an indexer 14 | indexer(); 15 | 16 | // Construct from libgit2 C ptr 17 | indexer(git_indexer *c_ptr, ownership owner); 18 | 19 | // Free indexer if owned by user 20 | ~indexer(); 21 | 22 | // This structure is used to provide callers information about the progress of 23 | // indexing a packfile, either directly or part of a fetch or clone that 24 | // downloads a packfile. 25 | class progress : public libgit2_api { 26 | public: 27 | // Default construct progress 28 | progress() : c_ptr_(nullptr) { c_ptr_ = &default_; } 29 | 30 | // Construct from libgit2 C ptr 31 | progress(const git_indexer_progress *c_ptr) : c_ptr_(c_ptr) {} 32 | 33 | // number of objects in the packfile being indexed 34 | unsigned long total_objects() const { return c_ptr_->total_objects; } 35 | 36 | // received objects that have been hashed 37 | unsigned long indexer_objects() const { return c_ptr_->indexed_objects; } 38 | 39 | // received_objects: objects which have been downloaded 40 | unsigned long received_objects() const { return c_ptr_->received_objects; } 41 | 42 | // locally-available objects that have been injected in order to fix a thin 43 | // pack 44 | unsigned long local_objects() const { return c_ptr_->local_objects; } 45 | 46 | // number of deltas in the packfile being indexed 47 | unsigned long total_deltas() const { return c_ptr_->total_deltas; } 48 | 49 | // received deltas that have been indexed 50 | unsigned long indexed_deltas() const { return c_ptr_->indexed_deltas; } 51 | 52 | // size of the packfile received up to now 53 | size_t received_bytes() const { return c_ptr_->received_bytes; } 54 | 55 | const git_indexer_progress *c_ptr() const { return c_ptr_; } 56 | 57 | private: 58 | friend indexer; 59 | const git_indexer_progress *c_ptr_; 60 | git_indexer_progress default_; 61 | }; 62 | 63 | // Add data to the indexer 64 | void append(void *data, size_t size); 65 | 66 | // Finalize the pack and index 67 | // Resolve any pending deltas and write out the index file 68 | void commit(); 69 | 70 | // Get the packfile's hash 71 | // A packfile's name is derived from the sorted hashing of 72 | // all object names. This is only correct after the index 73 | // has been finalized. 74 | oid hash(); 75 | 76 | class options : public libgit2_api { 77 | public: 78 | options() { 79 | auto ret = git_indexer_init_options(&default_options_, 80 | GIT_INDEXER_OPTIONS_VERSION); 81 | c_ptr_ = &default_options_; 82 | if (ret != 0) 83 | throw git_exception(); 84 | } 85 | 86 | options(git_indexer_options *c_ptr) : c_ptr_(c_ptr) {} 87 | 88 | // Version 89 | unsigned int version() const { return c_ptr_->version; } 90 | void set_version(unsigned int value) { c_ptr_->version = value; } 91 | 92 | // Indexer Progress callback 93 | void set_indexer_progress_callback( 94 | std::function callback) { 95 | struct visitor_wrapper { 96 | std::function fn; 97 | }; 98 | 99 | visitor_wrapper wrapper; 100 | wrapper.fn = callback; 101 | 102 | c_ptr_->progress_cb = [](const git_indexer_progress *stats, 103 | void *payload) { 104 | auto wrapper = reinterpret_cast(payload); 105 | wrapper->fn(indexer::progress(stats)); 106 | return 0; 107 | }; 108 | } 109 | 110 | // Do connectivity checks for the received pack 111 | unsigned char verify() const { return c_ptr_->verify; } 112 | 113 | const git_indexer_options *c_ptr() const { return c_ptr_; } 114 | 115 | private: 116 | friend indexer; 117 | git_indexer_options *c_ptr_; 118 | git_indexer_options default_options_; 119 | }; 120 | 121 | // Create a new indexer instance 122 | indexer(const std::string &path, unsigned int mode, const odb &odb, 123 | const indexer::options &options = indexer::options()); 124 | 125 | private: 126 | friend class repository; 127 | progress progress_; // stat storage 128 | ownership owner_; 129 | git_indexer *c_ptr_; 130 | }; 131 | 132 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/libgit2_api.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cppgit2 { 9 | 10 | class libgit2_api { 11 | public: 12 | libgit2_api() { git_libgit2_init(); } 13 | 14 | ~libgit2_api() { git_libgit2_shutdown(); } 15 | 16 | std::tuple version() const { 17 | int major, minor, revision; 18 | if (git_libgit2_version(&major, &minor, &revision)) 19 | throw git_exception(); 20 | return std::tuple{major, minor, revision}; 21 | } 22 | }; 23 | 24 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/note.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class note : public libgit2_api { 12 | public: 13 | note(); 14 | note(git_note *c_ptr, ownership owner = ownership::libgit2); 15 | ~note(); 16 | 17 | // Get the note author 18 | signature author() const; 19 | 20 | // Get the note committer 21 | signature committer() const; 22 | 23 | // Get the note object's id 24 | oid id() const; 25 | 26 | // Get the note message 27 | std::string message() const; 28 | 29 | // Access libgit2 C ptr 30 | const git_note *c_ptr() const; 31 | 32 | private: 33 | friend class repository; 34 | git_note *c_ptr_; 35 | ownership owner_; 36 | }; 37 | 38 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/object.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cppgit2 { 9 | 10 | class object : public libgit2_api { 11 | public: 12 | // Default construct a git object 13 | object(); 14 | 15 | // Construct from libgit2 C ptr 16 | object(git_object *c_ptr, ownership owner_ = ownership::libgit2); 17 | 18 | // Free git object if owned by user 19 | ~object(); 20 | 21 | // SHA1 hash of this object 22 | oid id() const; 23 | 24 | // Short abbreviated OID string of this object 25 | std::string short_id() const; 26 | 27 | // Clone this object 28 | object copy() const; 29 | 30 | // Basic type (loose or packed) of any git object 31 | enum class object_type { 32 | any = -2, 33 | invalid = -1, 34 | commit = 1, 35 | tree = 2, 36 | blob = 3, 37 | tag = 4, 38 | ofs_delta = 6, 39 | ref_delta = 7 40 | }; 41 | 42 | // object tyoe to string 43 | static std::string object_type_to_string(object_type type); 44 | 45 | using object_size = git_object_size_t; 46 | 47 | // Recursively peel until an object of the specified type is met 48 | object peel_until(object_type target); 49 | 50 | // Type of this git object 51 | object_type type() const; 52 | 53 | // Type of this git object - as string 54 | std::string type_string() const; 55 | 56 | // Convert a string object type to object_type 57 | static object_type type_from_string(const std::string &type_string); 58 | 59 | // Convert an object type to string representation 60 | static std::string string_from_type(object_type type); 61 | 62 | // Determine if the given type is a valid loose object type 63 | static bool is_type_loose(object_type type); 64 | 65 | // Get owner repository 66 | class repository owner() const; 67 | 68 | // Cast to blob 69 | // Throws git_exception if object is not a blob 70 | class blob as_blob(); 71 | 72 | // Cast to commit 73 | // Throws git_exception if object is not a commit 74 | class commit as_commit(); 75 | 76 | // Cast to tree 77 | // Throws git_exception if object is not a tree 78 | class tree as_tree(); 79 | 80 | // Cast to tag 81 | // Throws git_exception if object is not a tag 82 | class tag as_tag(); 83 | 84 | // Access libgit2 C ptr 85 | const git_object *c_ptr() const { return c_ptr_; } 86 | 87 | private: 88 | friend class reference; 89 | friend class repository; 90 | friend class revspec; 91 | friend class tag; 92 | ownership owner_; 93 | git_object *c_ptr_; 94 | }; 95 | 96 | } // namespace cppgit2 97 | -------------------------------------------------------------------------------- /include/cppgit2/oid.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cppgit2 { 8 | 9 | class oid : public libgit2_api { 10 | public: 11 | // Default constructor 12 | // Initializes libgit2 13 | oid(); 14 | 15 | // Construct from string 16 | oid(const std::string &hex_string); 17 | 18 | // Construct from string with size `length` 19 | oid(const std::string &hex_string, size_t length); 20 | 21 | // Construct from C API 22 | oid(const git_oid *c_ptr); 23 | 24 | // Construct from raw bytes 25 | oid(const unsigned char *raw); 26 | 27 | // Compare two oid structions 28 | // 29 | // < 0 if oid sorts before rhs 30 | // 0 if oid matches rhs 31 | // > 0 if oid sorts after rhs 32 | int compare(const oid &rhs) const; 33 | 34 | // Compare the first `length` hexadecimal characters 35 | // (packets of 4 bits) of two oid structures 36 | int compare(const oid &rhs, size_t length) const; 37 | 38 | // Compare this oid to an hex formatted object id. 39 | int compare(const std::string &rhs) const; 40 | 41 | // Copy an oid from one structure to another 42 | oid copy() const; 43 | 44 | // Check if an oid is all zeros 45 | bool is_zero() const; 46 | 47 | // Compare two oid structures for equality 48 | bool operator==(const oid &rhs) const; 49 | 50 | // Check if an oid equals a hex formatted object id 51 | bool operator==(const std::string &rhs) const; 52 | 53 | // Format oid into hex format string 54 | std::string to_hex_string(size_t n = GIT_OID_HEXSZ) const; 55 | 56 | // Format an oid into a loose-object path string 57 | // 58 | // Return string is "aa/...", where "aa" is the first two 59 | // digits of the oid and "..." is the remaining 38 digits. 60 | std::string to_path_string() const; 61 | 62 | // Access libgit2 C pointer 63 | git_oid *c_ptr(); 64 | const git_oid *c_ptr() const; 65 | 66 | // The OID shortener is used to process a list of OIDs 67 | // in text form and return the shortest length that 68 | // would uniquely identify all of them. 69 | // 70 | // e.g. look at the result of git log --abbrev. 71 | class shortener : public libgit2_api { 72 | public: 73 | // The minimal length for all identifiers, 74 | // which will be used even if shorter 75 | // OIDs would still be unique. 76 | explicit shortener(size_t min_length = 0) { 77 | c_ptr_ = git_oid_shorten_new(min_length); 78 | } 79 | 80 | ~shortener() { 81 | if (c_ptr_) 82 | git_oid_shorten_free(c_ptr_); 83 | } 84 | 85 | // Add a new OID to set of shortened OIDs 86 | // Returns the minimal length to uniquely identify 87 | // all the OIDs in the set. 88 | // 89 | // For performance reasons, there is a hard-limit of 90 | // how many OIDs can be added to a single set 91 | // (around ~32000, assuming a mostly randomized distribution) 92 | int add(const std::string &text_id) { 93 | auto result = git_oid_shorten_add(c_ptr_, text_id.c_str()); 94 | if (result < 0) 95 | throw git_exception(); 96 | return result; 97 | } 98 | 99 | private: 100 | git_oid_shorten *c_ptr_; 101 | }; 102 | 103 | private: 104 | friend class repository; 105 | git_oid c_struct_; 106 | }; 107 | 108 | } // namespace cppgit2 109 | -------------------------------------------------------------------------------- /include/cppgit2/ownership.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cppgit2 { 4 | 5 | enum class ownership { user, libgit2 }; 6 | } 7 | -------------------------------------------------------------------------------- /include/cppgit2/pack_builder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace cppgit2 { 13 | 14 | class pack_builder : public libgit2_api { 15 | public: 16 | // Default construct a pack_builder 17 | pack_builder(); 18 | 19 | // Construct from libgit2 C ptr 20 | pack_builder(git_packbuilder *c_ptr, ownership owner); 21 | 22 | // Free packbuilder ptr if owned by user 23 | ~pack_builder(); 24 | 25 | // Create the new pack and pass each object to the callback 26 | void for_each_object( 27 | std::function visitor); 28 | 29 | // Get the packfile's hash 30 | // A packfile's name is derived from the sorted hashing of all object names. 31 | // This is only correct after the packfile has been written. 32 | oid hash(); 33 | 34 | // Get the packfile's hash 35 | oid id() const; 36 | 37 | // Insert a commit object 38 | void insert_commit(const oid &commit_id); 39 | 40 | // Insert a single object 41 | // For an optimal pack it's mandatory to insert objects in recency order, 42 | // commits followed by trees and blobs. 43 | void insert_object(const oid &commit_id, const std::string &name = ""); 44 | 45 | // Recursively insert an object and its referenced objects 46 | // Insert the object as well as any object it references 47 | void insert_object_recursively(const oid &commit_id, 48 | const std::string &name = ""); 49 | 50 | // Insert a tree object 51 | // This will add the tree as well as all referenced trees and blobs 52 | void insert_tree(const oid &tree_id); 53 | 54 | // Insert objects as given by the walk 55 | void insert_revwalk(const revwalk &walk); 56 | 57 | // Get the total number of objects the packbuilder will write out 58 | size_t size() const; 59 | 60 | // Set the callbacks for a packbuilder 61 | void 62 | set_progress_callback(std::function callback); 63 | 64 | // Set number of threads to spawn 65 | void set_threads(unsigned int num_threads); 66 | 67 | // Write the new pack and corresponding index file to path. 68 | void write(const std::string &path, unsigned int mode, 69 | std::function &progress_callback); 70 | 71 | // Write the contents of the packfile to an in-memory buffer 72 | data_buffer write_to_buffer(); 73 | 74 | // Get the number of objects the packbuilder has already written out 75 | size_t written() const; 76 | 77 | // Access libgit2 C ptr 78 | const git_packbuilder *c_ptr() const; 79 | 80 | private: 81 | friend class repository; 82 | git_packbuilder *c_ptr_; 83 | ownership owner_; 84 | }; 85 | 86 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/patch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace cppgit2 { 12 | 13 | class patch : public libgit2_api { 14 | public: 15 | // Default construct a patch object 16 | patch(); 17 | 18 | // Construct from libgit2 C ptr 19 | patch(git_patch *c_ptr, ownership owner = ownership::libgit2); 20 | 21 | // Directly generate a patch from the difference between a blob and a buffer. 22 | patch(const blob &old_blob, const std::string &old_as_path, 23 | const void *buffer, size_t buffer_length, 24 | const std::string &buffer_as_path, 25 | const diff::options &options = diff::options()); 26 | 27 | // Directly generate a patch from the difference between two blobs. 28 | patch(const blob &old_blob, const std::string &old_as_path, 29 | const blob &new_blob, const std::string &new_as_path, 30 | const diff::options &options = diff::options()); 31 | 32 | // Directly generate a patch from the difference between two buffers. 33 | patch(const void *old_buffer, size_t old_buffer_length, 34 | const std::string &old_as_path, const void *new_buffer, 35 | size_t new_buffer_length, const std::string &new_as_path, 36 | const diff::options &options = diff::options()); 37 | 38 | // Return a patch for an entry in the diff list. 39 | // The git_patch is a newly created object contains the text diffs for the 40 | // delta. 41 | patch(const diff &diff, size_t index); 42 | 43 | // Cleanup patch object 44 | ~patch(); 45 | 46 | // Get the delta associated with a patch. 47 | // This delta points to internal data, owned by libgit2 48 | diff::delta delta() const; 49 | 50 | // Get the information about a hunk in a patch 51 | // Returns a pair of results: {hunk, lines_in_hunk} 52 | std::pair hunk(size_t hunk_index) const; 53 | 54 | // Get data about a line in a hunk of a patch. 55 | diff::line line_in_hunk(size_t hunk_index, size_t line_of_hunk) const; 56 | 57 | // Get line counts of each type in a patch. 58 | // Returns {Count of context lines in output, 59 | // Count of addition lines in output, 60 | // Count of deletion lines in output} 61 | // This helps imitate a diff --numstat type of output 62 | std::tuple line_stats() const; 63 | 64 | // Get the number of hunks in a patch 65 | size_t num_hunks() const; 66 | 67 | // Get the number of lines in a hunk. 68 | size_t num_lines_in_hunk(size_t hunk_index) const; 69 | 70 | // Serialize the patch to text via callback. 71 | void print(std::function 73 | line_callback); 74 | 75 | // Look up size of patch diff data in bytes 76 | // 77 | // This returns the raw size of the patch data. 78 | // This only includes the actual data from the lines of the diff, 79 | // not the file or hunk headers. 80 | size_t size(bool include_context, bool include_hunk_headers, 81 | bool include_file_headers) const; 82 | 83 | // Get the content of a patch as a single diff text. 84 | data_buffer to_buffer(); 85 | 86 | // Access to libgit2 C ptr 87 | const git_patch *c_ptr() const; 88 | 89 | private: 90 | ownership owner_; 91 | git_patch *c_ptr_; 92 | }; 93 | 94 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/pathspec.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace cppgit2 { 11 | 12 | class pathspec : public libgit2_api { 13 | public: 14 | // Default construct a pathspec object 15 | pathspec(); 16 | 17 | // Construct from libgit2 C ptr 18 | pathspec(git_pathspec *c_ptr, ownership owner); 19 | 20 | // Cleanup pathspec if needed 21 | ~pathspec(); 22 | 23 | enum class flag { 24 | default_ = 0, 25 | ignore_case = (1u << 0), 26 | use_case = (1u << 1), 27 | no_glob = (1u << 2), 28 | no_match_error = (1u << 3), 29 | find_failures = (1u << 4), 30 | failures_only = (1u << 5), 31 | }; 32 | 33 | class match_list { 34 | public: 35 | match_list() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 36 | match_list(git_pathspec_match_list *c_ptr, 37 | ownership owner = ownership::libgit2) 38 | : c_ptr_(c_ptr), owner_(owner) {} 39 | 40 | ~match_list() { 41 | if (c_ptr_ && owner_ == ownership::user) 42 | git_pathspec_match_list_free(c_ptr_); 43 | } 44 | 45 | // Get a matching diff delta by position. 46 | diff::delta diff_entry(size_t pos) const { 47 | return diff::delta(git_pathspec_match_list_diff_entry(c_ptr_, pos)); 48 | } 49 | 50 | // Get a matching filename by position. 51 | std::string entry(size_t pos) const { 52 | auto ret = git_pathspec_match_list_entry(c_ptr_, pos); 53 | if (ret) 54 | return std::string(ret); 55 | return ""; 56 | } 57 | 58 | // Get an original pathspec string that had no matches. 59 | std::string failed_entry(size_t pos) const { 60 | auto ret = git_pathspec_match_list_failed_entry(c_ptr_, pos); 61 | if (ret) 62 | return std::string(ret); 63 | return ""; 64 | } 65 | 66 | // Get the number of items in a match list. 67 | size_t size() const { return git_pathspec_match_list_entrycount(c_ptr_); } 68 | 69 | // Get the number of pathspec items that did not match. 70 | size_t failed_entrycount() const { 71 | return git_pathspec_match_list_failed_entrycount(c_ptr_); 72 | } 73 | 74 | // Acecss libgit2 C ptr 75 | const git_pathspec_match_list *c_ptr() const { return c_ptr_; } 76 | 77 | private: 78 | ownership owner_; 79 | git_pathspec_match_list *c_ptr_; 80 | }; 81 | 82 | // Compile a pathspec 83 | static pathspec compile(const strarray &paths); 84 | 85 | // Match a pathspec against files in a diff list. 86 | match_list match_diff(const diff &diff, flag flags); 87 | 88 | // Match a pathspec against entries in an index. 89 | match_list match_index(const index &index, flag flags); 90 | 91 | // Match a pathspec against files in a tree. 92 | match_list match_tree(const tree &tree, flag flags); 93 | 94 | // Match a pathspec against the working directory of a repository. 95 | match_list match_workdir(const class repository &repo, flag flags); 96 | 97 | // Try to match a path against a pathspec 98 | // Returns true if path matches spec, false if it does not 99 | bool matches_path(flag flags, const std::string &path) const; 100 | 101 | // Access libgit2 C ptr 102 | const git_pathspec *c_ptr() const; 103 | 104 | private: 105 | ownership owner_; 106 | git_pathspec *c_ptr_; 107 | }; 108 | ENABLE_BITMASK_OPERATORS(pathspec::flag); 109 | 110 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/proxy.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace cppgit2 { 6 | 7 | class proxy : public libgit2_api { 8 | public: 9 | // The type of proxy to use. 10 | enum class proxy_type { 11 | none, // Do not attempt to connect through a proxy 12 | auto_, // Try to auto-detect the proxy from the git configuration. 13 | specified // Connect via the URL given in the options 14 | }; 15 | 16 | class options : public libgit2_api { 17 | public: 18 | options() { 19 | auto ret = 20 | git_proxy_init_options(&default_options_, GIT_PROXY_OPTIONS_VERSION); 21 | c_ptr_ = &default_options_; 22 | if (ret != 0) 23 | throw git_exception(); 24 | } 25 | 26 | options(git_proxy_options *c_ptr) : c_ptr_(c_ptr) {} 27 | 28 | // Version 29 | unsigned int version() const { return c_ptr_->version; } 30 | void set_version(unsigned int value) { c_ptr_->version = value; } 31 | 32 | // The type of proxy to use, by URL, auto-detect. 33 | proxy::proxy_type proxy_type() const { 34 | return static_cast(c_ptr_->type); 35 | } 36 | void set_proxy_type(proxy::proxy_type type) { 37 | c_ptr_->type = static_cast(type); 38 | } 39 | 40 | // URL 41 | std::string url() const { 42 | if (c_ptr_->url) 43 | return std::string(c_ptr_->url); 44 | return ""; 45 | } 46 | void set_url(const std::string &url) { c_ptr_->url = url.c_str(); } 47 | 48 | // Access libgit2 C ptr 49 | const git_proxy_options *c_ptr() const { return c_ptr_; } 50 | 51 | private: 52 | friend proxy; 53 | git_proxy_options *c_ptr_; 54 | git_proxy_options default_options_; 55 | }; 56 | }; 57 | 58 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/push.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cppgit2 { 8 | 9 | class push : public libgit2_api { 10 | public: 11 | class options : public libgit2_api { 12 | public: 13 | options() { 14 | auto ret = 15 | git_push_init_options(&default_options_, GIT_PUSH_OPTIONS_VERSION); 16 | c_ptr_ = &default_options_; 17 | if (ret != 0) 18 | throw git_exception(); 19 | } 20 | 21 | options(git_push_options *c_ptr) : c_ptr_(c_ptr) {} 22 | 23 | // Version 24 | unsigned int version() const { return c_ptr_->version; } 25 | void set_version(unsigned int value) { c_ptr_->version = value; } 26 | 27 | // Parallelism 28 | // If the transport being used to push to the remote 29 | // requires the creation of a pack file, 30 | // this controls the number of worker threads used by the packbuilder 31 | // when creating that pack file to be sent to the remote. 32 | // If set to 0, the packbuilder will auto-detect the number 33 | // of threads to create. The default value is 1. 34 | unsigned int pb_parallelism() const { return c_ptr_->pb_parallelism; } 35 | void set_pb_parallelism(unsigned int value) { 36 | c_ptr_->pb_parallelism = value; 37 | } 38 | 39 | // Proxy options to use, by default no proxy is used. 40 | proxy::options proxy_options() const { 41 | return proxy::options(&c_ptr_->proxy_opts); 42 | } 43 | void set_proxy_options(const proxy::options &options) { 44 | c_ptr_->proxy_opts = *(options.c_ptr()); 45 | } 46 | 47 | // Extra headers for this push operation 48 | strarray custom_headers() const { 49 | return strarray(&c_ptr_->custom_headers); 50 | } 51 | void set_custom_headers(const strarray &headers) { 52 | c_ptr_->custom_headers = *(headers.c_ptr()); 53 | } 54 | 55 | // Access libgit2 C ptr 56 | const git_push_options *c_ptr() const { return c_ptr_; } 57 | 58 | private: 59 | friend push; 60 | git_push_options *c_ptr_; 61 | git_push_options default_options_; 62 | }; 63 | }; 64 | 65 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/refdb.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cppgit2 { 9 | 10 | class refdb : public libgit2_api { 11 | public: 12 | // Default constructor 13 | // Initializes libgit2 14 | refdb() : owner_(ownership::libgit2), c_ptr_(nullptr) {} 15 | 16 | // Construct from C API 17 | refdb(git_refdb *c_ptr, ownership owner = ownership::libgit2) 18 | : c_ptr_(c_ptr), owner_(owner) {} 19 | 20 | // Free if owned by user 21 | ~refdb() { 22 | if (c_ptr_ && owner_ == ownership::user) 23 | git_refdb_free(c_ptr_); 24 | } 25 | 26 | // Suggests that the given refdb compress or optimize its references. 27 | // This mechanism is implementation specific. For on-disk reference 28 | // databases, for example, this may pack all loose references. 29 | void compress() { 30 | if (git_refdb_compress(c_ptr_)) 31 | throw git_exception(); 32 | } 33 | 34 | private: 35 | friend class repository; 36 | ownership owner_; 37 | git_refdb *c_ptr_; 38 | }; 39 | 40 | } // namespace cppgit2 41 | -------------------------------------------------------------------------------- /include/cppgit2/reference.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace cppgit2 { 11 | 12 | class reference : public libgit2_api { 13 | public: 14 | reference(); 15 | reference(git_reference *c_ptr, ownership owner = ownership::libgit2); 16 | ~reference(); 17 | 18 | // Basic type of any Git reference 19 | enum class reference_type { 20 | invalid = 0, // Invalid reference 21 | direct = 1, // A reference that points at an object id 22 | symbolic = 2, // A reference that points at another reference 23 | all = direct | symbolic 24 | }; 25 | 26 | // Compare two references. 27 | // 0 if the same, else a stable but meaningless ordering. 28 | int compare(const reference &rhs) const; 29 | 30 | // Delete an existing reference. 31 | static void delete_reference(reference &ref); 32 | 33 | // Create a duplicate of an existing reference 34 | reference copy() const; 35 | 36 | // Check if this reference ... 37 | bool is_branch() const; 38 | bool is_note() const; 39 | bool is_remote() const; 40 | bool is_tag() const; 41 | 42 | // Check if a reference name is well-formed. 43 | // Valid reference names must follow one of two patterns: 44 | // 1. Top-level names must contain only capital letters and underscores, and 45 | // must begin and end 46 | // with a letter. (e.g. "HEAD", "ORIG_HEAD"). 47 | // 2. Names prefixed with "refs/" can be almost 48 | // anything. You must avoid the characters '~', '^', ':', '\', '?', '[', 49 | // and '*', and the sequences ".." and "@{" which have special meaning to 50 | // revparse. 51 | static bool is_valid_name(const std::string &refname); 52 | 53 | // Full name of this reference 54 | std::string name() const; 55 | 56 | // Normalization options for reference lookup 57 | enum class format { 58 | normal = 0u, 59 | allow_onelevel = (1u << 0), 60 | refspec_pattern = (1u << 1), 61 | refspec_shorthand = (1u << 2) 62 | }; 63 | 64 | // Normalize reference name and check validity. 65 | // This will normalize the reference name by removing any leading 66 | // slash '/' characters and collapsing runs of adjacent 67 | // slashes between name components into a single slash. 68 | static std::string normalize_name(size_t length, const std::string &name, 69 | reference::format flags); 70 | 71 | // This will transform the reference name into a name "human-readable" 72 | // version. If no shortname is appropriate, it will return the full name. 73 | std::string shorthand_name() const; 74 | 75 | // Get the repository where a reference resides 76 | class repository owner() const; 77 | 78 | // Recursively peel reference until object of the specified type is found. 79 | object peel_until(object::object_type type); 80 | 81 | // Rename an existing reference. 82 | // This method works for both direct and symbolic references. 83 | // IMPORTANT: The user needs to write a proper reflog entry 84 | // if the reflog is enabled for the repository. We only rename the reflog if 85 | // it exists. 86 | reference rename(const std::string &new_name, bool force, 87 | const std::string &log_message); 88 | 89 | // Resolve a sym reference to a direct reference 90 | // If a direct reference is passed as an argument, a copy of that reference is 91 | // returned. This copy must be manually freed too. 92 | reference resolve(); 93 | 94 | // Conditionally create a new reference with the same name as 95 | // the given reference but a different OID target. 96 | // The reference must be a direct reference, otherwise this will fail. 97 | reference set_target(const oid &id, const std::string &log_message); 98 | 99 | // Create a new reference with the same name as the given reference 100 | // but a different symbolic target. 101 | // The reference must be a symbolic reference, otherwise this will fail. 102 | reference set_symbolic_target(const std::string &target, 103 | const std::string &log_message); 104 | 105 | // Get the OID pointed by a direct reference 106 | // Only available if the reference is direct (i.e. an object id reference, not 107 | // a symbolic one). 108 | // 109 | // To find the OID of a symbolic ref, call reference.resolve() and then this 110 | // function (or maybe use reference.name_to_id() to directly resolve a 111 | // reference name all the way through to an OID). 112 | oid target() const; 113 | 114 | // Get full name to the reference pointed to by a symbolic reference. 115 | std::string symbolic_target() const; 116 | 117 | // Return the peeled OID target of this reference 118 | oid peeled_target() const; 119 | 120 | // Get the type of a reference 121 | reference_type type() const; 122 | 123 | // Access libgit2 C ptr 124 | const git_reference *c_ptr() const; 125 | 126 | private: 127 | friend class repository; 128 | git_reference *c_ptr_; 129 | ownership owner_; 130 | }; 131 | ENABLE_BITMASK_OPERATORS(reference::format); 132 | 133 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/reflog.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class reflog : public libgit2_api { 12 | public: 13 | // Default construct a reflog 14 | reflog(); 15 | 16 | // Construct reflog from libgit2 C ptr 17 | // If owned by user, will be free'd in the destructor 18 | // using git_reflog_free 19 | reflog(git_reflog *c_ptr, ownership owner = ownership::libgit2); 20 | 21 | // Free reflog if owned by user 22 | ~reflog(); 23 | 24 | // Entry in this reflog 25 | class entry : public libgit2_api { 26 | public: 27 | entry(const git_reflog_entry *c_ptr) : c_ptr_(c_ptr) {} 28 | 29 | signature committer() { 30 | return signature(git_reflog_entry_committer(c_ptr_)); 31 | } 32 | 33 | std::string message() { 34 | auto ret = git_reflog_entry_message(c_ptr_); 35 | if (ret) 36 | return std::string(ret); 37 | else 38 | return ""; 39 | } 40 | 41 | oid new_oid() { return oid(git_reflog_entry_id_new(c_ptr_)); } 42 | 43 | oid old_oid() { return oid(git_reflog_entry_id_old(c_ptr_)); } 44 | 45 | const git_reflog_entry *c_ptr() { return c_ptr_; } 46 | 47 | private: 48 | const git_reflog_entry *c_ptr_; 49 | }; 50 | 51 | // Remove entry from reflog by index 52 | // To ensure there's no gap in the log history, 53 | // set rewrite_previous_entry to true 54 | void remove(size_t index, bool rewrite_previous_entry); 55 | 56 | // Get the number of log entries in this reflog 57 | size_t size() const; 58 | 59 | // Add a new entry to the in-memory reflog 60 | void append(const oid &id, const signature &committer, 61 | const std::string &message = ""); 62 | 63 | // Lookup an entry by index 64 | // Requesting reflog[0] will return the most recently created entry 65 | entry operator[](size_t index) const; 66 | 67 | // Write an existing in-memory reflog object back to disk 68 | // Uses atomic file lock 69 | void write_to_disk(); 70 | 71 | // Access libgit2 C ptr 72 | const git_reflog *c_ptr() const; 73 | 74 | private: 75 | friend class repository; 76 | git_reflog *c_ptr_; 77 | ownership owner_; 78 | }; 79 | 80 | } // namespace cppgit2 81 | -------------------------------------------------------------------------------- /include/cppgit2/refspec.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class refspec : public libgit2_api { 12 | public: 13 | // Default construct a refspec object 14 | refspec(); 15 | 16 | // Construct from libgit2 C ptr 17 | refspec(git_refspec *c_ptr, ownership owner = ownership::libgit2); 18 | 19 | // Cleanup refspec object 20 | ~refspec(); 21 | 22 | // Get the refspec's direction. 23 | connection_direction direction() const; 24 | 25 | // Get the destination specifier 26 | std::string destination() const; 27 | 28 | // Check if a refspec's destination descriptor matches a reference 29 | bool destination_matches_reference(const std::string &refname) const; 30 | 31 | // Get the force update setting 32 | bool is_force_update_enabled() const; 33 | 34 | // Parse a given refspec string 35 | static refspec parse(const std::string &input, bool is_fetch); 36 | 37 | // Transform a target reference to its 38 | // source reference following the refspec's rules 39 | data_buffer transform_target_to_source_reference(const std::string &name); 40 | 41 | // Get the source specifier 42 | std::string source() const; 43 | 44 | // Check if a refspec's source descriptor matches a reference 45 | bool source_matches_reference(const std::string &refname) const; 46 | 47 | // Get the refspec's string 48 | std::string to_string() const; 49 | 50 | // Transform a reference to its target following the refspec's rules 51 | data_buffer transform_reference(const std::string &name); 52 | 53 | // Access to libgit2 C ptr 54 | const git_refspec *c_ptr() const; 55 | 56 | private: 57 | ownership owner_; 58 | git_refspec *c_ptr_; 59 | }; 60 | 61 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/reset.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | class reset : public libgit2_api { 6 | public: 7 | enum class reset_type { 8 | soft = 1, // Move the head to the given commit 9 | mixed = 2, // SOFT plus reset index to the commit 10 | hard = 3 // MIXED plus changes in working tree discarded 11 | }; 12 | }; 13 | 14 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/revert.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class revert : public libgit2_api { 12 | public: 13 | class options : public libgit2_api { 14 | public: 15 | options() { 16 | auto ret = git_revert_init_options(&default_options_, 17 | GIT_REVERT_OPTIONS_VERSION); 18 | c_ptr_ = &default_options_; 19 | if (ret != 0) 20 | throw git_exception(); 21 | } 22 | 23 | options(git_revert_options *c_ptr) : c_ptr_(c_ptr) {} 24 | 25 | // Version 26 | unsigned int version() const { return c_ptr_->version; } 27 | void set_version(unsigned int value) { c_ptr_->version = value; } 28 | 29 | // For merge commits, the "mainline" is treated as the parent. 30 | unsigned int mainline() const { return c_ptr_->mainline; } 31 | void set_mainline(unsigned int value) { c_ptr_->mainline = value; } 32 | 33 | // Options for the merging 34 | merge::options merge_options() const { 35 | return merge::options(&c_ptr_->merge_opts); 36 | } 37 | void set_merge_options(const merge::options &options) { 38 | c_ptr_->merge_opts = *(options.c_ptr()); 39 | } 40 | 41 | // Options for the checkout 42 | checkout::options checkout_options() const { 43 | return checkout::options(&c_ptr_->checkout_opts); 44 | } 45 | void set_checkout_options(const checkout::options &options) { 46 | c_ptr_->checkout_opts = *(options.c_ptr()); 47 | } 48 | 49 | const git_revert_options *c_ptr() const { return c_ptr_; } 50 | 51 | private: 52 | friend revert; 53 | git_revert_options *c_ptr_; 54 | git_revert_options default_options_; 55 | }; 56 | }; 57 | 58 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/revision.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | namespace revision { 6 | 7 | // Flags to specify the sorting which a revwalk should perform. 8 | // Used in e.g., repository.for_each_revision 9 | enum class sort { 10 | // Sort the output with the same default method from `git`: reverse 11 | // chronological order. This is the default sorting for new walkers. 12 | none = 0, 13 | // Sort the repository contents in topological order (no parents before 14 | // all of its children are shown); this sorting mode can be combined 15 | // with time sorting to produce `git`'s `--date-order``. 16 | topological = 1 << 0, 17 | // Sort the repository contents by commit time; 18 | // this sorting mode can be combined with topological sorting 19 | commit_time = 1 << 1, 20 | // Iterate through the repository contents in reverse 21 | // order; this sorting mode can be combined with 22 | // any of the above. 23 | reverse = 1 << 2 24 | }; 25 | 26 | } // namespace revision 27 | ENABLE_BITMASK_OPERATORS(revision::sort); 28 | 29 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/revparse.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace cppgit2 { 6 | 7 | class revparse { 8 | public: 9 | // Revparse flags. These indicate the intended behavior of the spec passed to 10 | // git_revparse 11 | enum class mode { 12 | // The spec targeted a single object. 13 | single = 1 << 0, 14 | 15 | // The spec targeted a range of commits. 16 | range = 1 << 1, 17 | 18 | // The spec used the '...' operator, which invokes special semantics. 19 | merge_base = 1 << 2, 20 | }; 21 | }; 22 | ENABLE_BITMASK_OPERATORS(revparse::mode); 23 | 24 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/revspec.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cppgit2 { 8 | 9 | // Git Revision Spec: output of a `git_revparse` operation 10 | // Contents are owned by the user 11 | class revspec : public libgit2_api { 12 | public: 13 | // Default construct a revspec 14 | revspec() : c_ptr_(nullptr) {} 15 | 16 | // Construct from libgit2 C ptr 17 | revspec(git_revspec *c_ptr) : c_ptr_(c_ptr) { 18 | from_ = object(c_ptr_->from, ownership::user); 19 | to_ = object(c_ptr_->to, ownership::user); 20 | } 21 | 22 | // The left element of the revspec; must be freed by the user 23 | object from() const { return from_; } 24 | 25 | // The right element of the revspec; must be freed by the user 26 | object to() const { return to_; } 27 | 28 | revparse::mode flags() const { 29 | return static_cast(c_ptr_->flags); 30 | } 31 | 32 | const git_revspec *c_ptr() const { return c_ptr_; } 33 | 34 | private: 35 | friend class repository; 36 | object from_; 37 | object to_; 38 | git_revspec *c_ptr_; 39 | }; 40 | 41 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/revwalk.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class revwalk : public libgit2_api { 12 | public: 13 | // Default construct a revwalk 14 | revwalk(); 15 | 16 | // Construct from libgit2 C ptr 17 | revwalk(git_revwalk *c_ptr, ownership owner); 18 | 19 | // Cleanup revwalk 20 | ~revwalk(); 21 | 22 | // Adds, changes or removes a callback function to hide a commit and its 23 | // parents. 24 | // 25 | // This is a callback function that user can provide to hide a commit 26 | // and its parents. If the callback function returns non-zero value, then this 27 | // commit and its parents will be hidden. 28 | void add_hide_callback(std::function callback); 29 | 30 | // Returns true if there are no more commits left to walk 31 | bool done() const; 32 | 33 | // Mark a commit (and its ancestors) uninteresting for the output. 34 | // The given id must belong to a committish on the walked repository. 35 | void hide(const oid &commit_id); 36 | 37 | // Hide matching references. 38 | void hide_glob(const std::string &glob); 39 | 40 | // Hide the repository's HEAD 41 | void hide_head(); 42 | 43 | // Hide the OID pointed to by a reference 44 | void hide_reference(const std::string &ref); 45 | 46 | // Get the next commit from the revision walk. 47 | // The initial call to this method is not blocking when iterating through a 48 | // repo with a time-sorting mode. 49 | // 50 | // Iterating with Topological or inverted modes makes the initial call 51 | // blocking to preprocess the commit list, but this block should be mostly 52 | // unnoticeable on most repositories (topological preprocessing times at 0.3s 53 | // on the git.git repo). 54 | // 55 | // The revision walker is reset when the walk is over. 56 | oid next(); 57 | 58 | // Add a new root for the traversal 59 | // The pushed commit will be marked as one of the roots from which to start 60 | // the walk. This commit may not be walked if it or a child is hidden. 61 | void push(const oid &id); 62 | 63 | // Push matching references 64 | void push_glob(const std::string &glob); 65 | 66 | // Push the repository's HEAD 67 | void push_head(); 68 | 69 | // Push and hide the respective endpoints of the given range. 70 | void push_range(const std::string &range); 71 | 72 | // Push the OID pointed to by a reference 73 | void push_reference(const std::string &ref); 74 | 75 | // Return the repository on which this walker is operating. 76 | class repository repository(); 77 | 78 | // Reset the revision walker for reuse. 79 | // This will clear all the pushed and hidden commits, 80 | // and leave the walker in a blank state 81 | void reset(); 82 | 83 | // Flags to specify the sorting which a revwalk should perform. 84 | enum class sort { 85 | none = 0, 86 | topological = (1 << 0), 87 | time = (1 << 1), 88 | reverse = (1 << 2) 89 | }; 90 | 91 | // Change the sorting mode when iterating through the repository's contents. 92 | void set_sorting_mode(revwalk::sort sorting_mode); 93 | 94 | // Simplify the history by first-parent 95 | void simplify_first_parent(); 96 | 97 | // Access libgit2 C ptr 98 | const git_revwalk *c_ptr() const; 99 | 100 | private: 101 | friend class pack_builder; 102 | friend class repository; 103 | bool done_; 104 | ownership owner_; 105 | git_revwalk *c_ptr_; 106 | }; 107 | ENABLE_BITMASK_OPERATORS(revwalk::sort); 108 | 109 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/signature.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cppgit2 { 9 | 10 | class signature : public libgit2_api { 11 | public: 12 | signature(); 13 | 14 | // Create a new action signature with 15 | // 1. name of person 16 | // 2. email of person 17 | // Uses "now" for signature time 18 | signature(const std::string &name, const std::string &email); 19 | 20 | // Create a new action signature with 21 | // 1. name of person 22 | // 2. email of person 23 | // 3. time (in seconds from epoch) when the action happened 24 | // 4. offset (timezone offset in minutes) for the time 25 | signature(const std::string &name, const std::string &email, 26 | epoch_time_seconds time, int offset_minutes); 27 | 28 | // Create a new action signature from buffer 29 | // Buffer should be in the format: 30 | // "Real Name timestamp tzoffset" 31 | // 32 | // timestamp is the number of seconds since the Unix epoch 33 | // tzoffset is the timezone offset in hhmm format 34 | // - (note the lack of a colon separator). 35 | signature(const std::string &buffer); 36 | 37 | // Construct from C ptr 38 | signature(const git_signature *c_ptr); 39 | 40 | // Duplicate this signature 41 | signature copy() const; 42 | 43 | // Getters 44 | std::string name() const; 45 | std::string email() const; 46 | epoch_time_seconds time() const; 47 | offset_minutes offset() const; 48 | 49 | // Access libgit2 C pointer 50 | const git_signature *c_ptr() const; 51 | 52 | private: 53 | friend class repository; 54 | git_signature *c_ptr_; 55 | git_signature default_; 56 | std::string default_name_{""}; 57 | std::string default_email_{""}; 58 | }; 59 | 60 | } // namespace cppgit2 61 | -------------------------------------------------------------------------------- /include/cppgit2/stash.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace cppgit2 { 11 | 12 | class stash : public libgit2_api { 13 | public: 14 | class apply : public libgit2_api { 15 | public: 16 | // Stash application flags. 17 | enum class flag { default_ = 0, reinstate_index = (1 << 0) }; 18 | 19 | // Stash apply progression states 20 | enum class progress { 21 | none = 0, 22 | // loading the stashed data from the object database. 23 | loading_stash, 24 | // the stored index is being analyzed. 25 | analyze_index, 26 | // the modified files are being analyzed. 27 | analyze_modified, 28 | // the untracked and ignored files are being analyzed. 29 | analyze_untracked, 30 | // the untracked files are being written to disk. 31 | checkout_untracked, 32 | // the modified files are being written to disk. 33 | checkout_modified, 34 | // the stash was applied successfully. 35 | done 36 | }; 37 | 38 | class options : public libgit2_api { 39 | public: 40 | options() { 41 | auto ret = git_stash_apply_init_options( 42 | &default_options_, GIT_STASH_APPLY_OPTIONS_VERSION); 43 | c_ptr_ = &default_options_; 44 | if (ret != 0) 45 | throw git_exception(); 46 | } 47 | 48 | options(git_stash_apply_options *c_ptr) : c_ptr_(c_ptr) {} 49 | 50 | // Version 51 | unsigned int version() const { return c_ptr_->version; } 52 | void set_version(unsigned int value) { c_ptr_->version = value; } 53 | 54 | // Flags 55 | flag flags() const { return static_cast(c_ptr_->flags); } 56 | void set_flags(flag value) { 57 | c_ptr_->flags = static_cast(value); 58 | } 59 | 60 | // Checkout options 61 | checkout::options checkout_options() const { 62 | return checkout::options(&c_ptr_->checkout_options); 63 | } 64 | void set_checkout_options(const checkout::options &options) { 65 | c_ptr_->checkout_options = *(options.c_ptr()); 66 | } 67 | 68 | // Access libgit2 C ptr 69 | const git_stash_apply_options *c_ptr() const { return c_ptr_; } 70 | 71 | private: 72 | friend stash; 73 | git_stash_apply_options *c_ptr_; 74 | git_stash_apply_options default_options_; 75 | }; 76 | }; 77 | 78 | private: 79 | }; 80 | ENABLE_BITMASK_OPERATORS(stash::apply::flag); 81 | 82 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/status.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class status : public libgit2_api { 12 | public: 13 | // Status flags for a single file. 14 | // 15 | // The `index_` set of flags 16 | // represents the status of file in the index relative to the HEAD 17 | // 18 | // `wt_` set of flags represent the status of the file in the 19 | // working directory relative to the index. 20 | enum class status_type { 21 | current = 0, 22 | 23 | index_new = (1u << 0), 24 | index_modified = (1u << 1), 25 | index_deleted = (1u << 2), 26 | index_renamed = (1u << 3), 27 | index_typechange = (1u << 4), 28 | 29 | wt_new = (1u << 7), 30 | wt_modified = (1u << 8), 31 | wt_deleted = (1u << 9), 32 | wt_typechange = (1u << 10), 33 | wt_renamed = (1u << 11), 34 | wt_unreadable = (1u << 12), 35 | 36 | ignored = (1u << 14), 37 | conflicted = (1u << 15) 38 | }; 39 | 40 | // Select the files on which to report status 41 | enum class show { index_and_workdir = 0, index_only = 1, workdir_only = 2 }; 42 | 43 | class options : public libgit2_api { 44 | public: 45 | options() { 46 | auto ret = git_status_init_options(&default_options_, 47 | GIT_STATUS_OPTIONS_VERSION); 48 | c_ptr_ = &default_options_; 49 | if (ret != 0) 50 | throw git_exception(); 51 | } 52 | 53 | options(git_status_options *c_ptr) : c_ptr_(c_ptr) {} 54 | 55 | // Version 56 | unsigned int version() const { return c_ptr_->version; } 57 | void set_version(unsigned int value) { c_ptr_->version = value; } 58 | 59 | // Show setting 60 | status::show show() const { 61 | return static_cast(c_ptr_->show); 62 | } 63 | void set_show(status::show value) { 64 | c_ptr_->show = static_cast(value); 65 | } 66 | 67 | enum class flag { 68 | include_untracked = (1u << 0), 69 | include_ignored = (1u << 1), 70 | include_unmodified = (1u << 2), 71 | exclude_submodules = (1u << 3), 72 | recurse_untracked_dirs = (1u << 4), 73 | disable_pathspec_match = (1u << 5), 74 | recurse_ignored_dirs = (1u << 6), 75 | renames_head_to_index = (1u << 7), 76 | renames_index_to_workdir = (1u << 8), 77 | sort_case_sensitively = (1u << 9), 78 | sort_case_insensitively = (1u << 10), 79 | renames_from_rewrites = (1u << 11), 80 | no_refresh = (1u << 12), 81 | update_index = (1u << 13), 82 | include_unreadable = (1u << 14), 83 | include_unreadable_as_untracked = (1u << 15) 84 | }; 85 | 86 | // Flags 87 | flag flags() const { return static_cast(c_ptr_->flags); } 88 | void set_flags(flag value) { 89 | c_ptr_->flags = static_cast(value); 90 | } 91 | 92 | // Pathspec 93 | strarray pathspec() const { return strarray(&c_ptr_->pathspec); } 94 | void set_pathspec(const strarray &value) { 95 | c_ptr_->pathspec = *(value.c_ptr()); 96 | } 97 | 98 | // Baseline tree 99 | tree baseline() const { return tree(c_ptr_->baseline); } 100 | void set_baseline(const tree &baseline_tree) { 101 | c_ptr_->baseline = const_cast(baseline_tree.c_ptr()); 102 | } 103 | 104 | // Access libgit2 C ptr 105 | const git_status_options *c_ptr() const { return c_ptr_; } 106 | 107 | private: 108 | friend status; 109 | git_status_options *c_ptr_; 110 | git_status_options default_options_; 111 | }; 112 | 113 | class entry : public libgit2_api { 114 | public: 115 | entry(const git_status_entry *c_ptr) : c_ptr_(c_ptr) {} 116 | 117 | private: 118 | const git_status_entry *c_ptr_; 119 | }; 120 | 121 | class list : public libgit2_api { 122 | public: 123 | list() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 124 | 125 | list(git_status_list *c_ptr, ownership owner = ownership::libgit2) 126 | : c_ptr_(c_ptr), owner_(owner) {} 127 | 128 | ~list() { 129 | if (c_ptr_ && owner_ == ownership::user) 130 | git_status_list_free(c_ptr_); 131 | } 132 | 133 | // Get one of the entries in the status list. 134 | // The entry is not modifiable and should not be freed. 135 | const entry operator[](size_t index) const { 136 | return entry(git_status_byindex(c_ptr_, index)); 137 | } 138 | 139 | // Gets the count of status entries in this list. 140 | size_t size() const { return git_status_list_entrycount(c_ptr_); } 141 | 142 | private: 143 | friend class status; 144 | friend class repository; 145 | ownership owner_; 146 | git_status_list *c_ptr_; 147 | }; 148 | 149 | private: 150 | }; 151 | ENABLE_BITMASK_OPERATORS(status::status_type); 152 | ENABLE_BITMASK_OPERATORS(status::options::flag); 153 | 154 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/strarray.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cppgit2 { 9 | 10 | class strarray : public libgit2_api { 11 | public: 12 | // Default construction 13 | // Initializes libgit2 14 | strarray(); 15 | 16 | // Construct from vector of strings 17 | strarray(const std::vector &strings); 18 | 19 | // Construct from libgit2 C ptr 20 | strarray(const git_strarray *c_ptr); 21 | 22 | // Free the git_strarray struct 23 | ~strarray(); 24 | 25 | // Duplicate this array 26 | strarray copy() const; 27 | 28 | // Build vector of tag names from strarray 29 | std::vector to_vector() const; 30 | 31 | // Iterator for use in range-based for loops 32 | class iterator { 33 | public: 34 | explicit iterator(char **ptr) : ptr_(ptr) {} 35 | 36 | iterator operator++() { 37 | ++ptr_; 38 | return *this; 39 | } 40 | 41 | bool operator!=(const iterator &other) const { return ptr_ != other.ptr_; } 42 | 43 | std::string operator*() { return std::string(*ptr_); } 44 | 45 | private: 46 | char **ptr_; 47 | }; 48 | 49 | iterator begin() { return iterator(&c_struct_.strings[0]); } 50 | 51 | iterator begin() const { return iterator(&c_struct_.strings[0]); } 52 | 53 | iterator end() { return iterator(&c_struct_.strings[c_struct_.count]); } 54 | 55 | iterator end() const { return iterator(&c_struct_.strings[c_struct_.count]); } 56 | 57 | // Returns number of strings in strarray 58 | size_t count() const { return c_struct_.count; } 59 | 60 | // Get string at index 61 | std::string operator[](size_t index) { 62 | return std::string(c_struct_.strings[index]); 63 | } 64 | 65 | // Access libgit2 C ptr 66 | const git_strarray *c_ptr() const; 67 | 68 | private: 69 | friend class remote; 70 | friend class repository; 71 | git_strarray c_struct_; 72 | }; 73 | 74 | } // namespace cppgit2 75 | -------------------------------------------------------------------------------- /include/cppgit2/tag.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class tag : public libgit2_api { 12 | public: 13 | // Default construct a tag 14 | tag(); 15 | 16 | // Construct from libgit2 C ptr 17 | // If owned by user, this will be free'd in destructor 18 | tag(git_tag *c_ptr, ownership owner = ownership::libgit2); 19 | 20 | // Cleanup tag ptr 21 | ~tag(); 22 | 23 | // Create an in-memory copy of a tag 24 | tag copy() const; 25 | 26 | // Id of the tag 27 | oid id() const; 28 | 29 | // Tag mesage 30 | std::string message() const; 31 | 32 | // Tag name 33 | std::string name() const; 34 | 35 | // Recursively peel until a non-tag git_object is found 36 | object peel() const; 37 | 38 | // Get tagger (author) of this tag 39 | signature tagger() const; 40 | 41 | // Get the tagged object of this tag 42 | object target() const; 43 | 44 | // Get the OID of the tagged object 45 | oid target_id() const; 46 | 47 | // Get the type of a tag's tagged object 48 | object::object_type target_type() const; 49 | 50 | // Owner repository for this tag 51 | class repository owner() const; 52 | 53 | // Access to libgit2 C ptr 54 | git_tag *c_ptr(); 55 | const git_tag *c_ptr() const; 56 | 57 | private: 58 | friend class repository; 59 | git_tag *c_ptr_; 60 | ownership owner_; 61 | }; 62 | 63 | } // namespace cppgit2 64 | -------------------------------------------------------------------------------- /include/cppgit2/time.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace cppgit2 { 6 | 7 | using epoch_time_seconds = git_time_t; 8 | using offset_minutes = int; 9 | 10 | class time : public libgit2_api { 11 | public: 12 | time(git_time *c_ptr) : c_ptr_(c_ptr) {} 13 | 14 | private: 15 | git_time *c_ptr_; 16 | }; 17 | 18 | } // namespace cppgit2 19 | -------------------------------------------------------------------------------- /include/cppgit2/transaction.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cppgit2 { 10 | 11 | class transaction : public libgit2_api { 12 | public: 13 | // Default construct a transaction 14 | transaction(); 15 | 16 | // Construct from libgit2 C ptr 17 | // If owned by user, free'd in the destructor 18 | transaction(git_transaction *c_ptr, ownership owner = ownership::libgit2); 19 | 20 | // Free transaction if owned by user 21 | ~transaction(); 22 | 23 | // Commit changes from this transaction 24 | void commit(); 25 | 26 | // Lock the specified reference 27 | // This is the first step to updating a reference 28 | void lock_reference(const std::string &refname); 29 | 30 | // Remove a reference 31 | void remove_reference(const std::string &refname); 32 | 33 | // Set the specified reference's reflog 34 | void set_reflog(const std::string &refname, const reflog &reflog); 35 | 36 | // Set the symbolic target of a reference 37 | void set_symbolic_target(const std::string &refname, 38 | const std::string &target, 39 | const signature &signature, 40 | const std::string &message); 41 | 42 | // Set the target of a reference 43 | void set_target(const std::string &refname, const oid &target, 44 | const signature &signature, const std::string &message); 45 | 46 | // Access the libgit2 C ptr 47 | git_transaction *c_ptr(); 48 | const git_transaction *c_ptr() const; 49 | 50 | private: 51 | friend class repository; 52 | git_transaction *c_ptr_; 53 | ownership owner_; 54 | }; 55 | 56 | } // namespace cppgit2 57 | -------------------------------------------------------------------------------- /include/cppgit2/tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace cppgit2 { 14 | 15 | class tree : public libgit2_api { 16 | public: 17 | // Default construct a tree 18 | tree(); 19 | 20 | // Construct from libgit2 C ptr 21 | // If owned by user, will be free'd in destructor 22 | tree(git_tree *c_ptr, ownership owner = ownership::libgit2); 23 | 24 | // Cleanup 25 | ~tree(); 26 | 27 | class entry : public libgit2_api { 28 | public: 29 | // Default construction 30 | entry() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 31 | 32 | // Construct from libgit2 C ptr 33 | // If owned by user, will be free'd in destructor 34 | entry(git_tree_entry *c_ptr, ownership owner = ownership::libgit2) 35 | : c_ptr_(c_ptr), owner_(owner) {} 36 | 37 | entry(const git_tree_entry *c_ptr) 38 | : c_ptr_(const_cast(c_ptr)), 39 | owner_(ownership::libgit2) {} 40 | 41 | // Clean up tree entry 42 | ~entry() { 43 | if (c_ptr_ && owner_ == ownership::user) 44 | git_tree_entry_free(c_ptr_); 45 | } 46 | 47 | // Duplicate a tree entry 48 | entry copy() const { 49 | entry result; 50 | if (git_tree_entry_dup(&result.c_ptr_, c_ptr_)) 51 | throw git_exception(); 52 | return result; 53 | } 54 | 55 | // UNIX file attributes of a tree entry 56 | file_mode filemode() const { 57 | return static_cast(git_tree_entry_filemode(c_ptr_)); 58 | } 59 | 60 | // Raw UNIX file attributes of this tree entry 61 | file_mode raw_filemode() const { 62 | return static_cast(git_tree_entry_filemode_raw(c_ptr_)); 63 | } 64 | 65 | // SHA1 hash of this tree entry 66 | oid id() const { return oid(git_tree_entry_id(c_ptr_)); } 67 | 68 | // Filename of tree entry 69 | std::string filename() const { 70 | auto entry_name = git_tree_entry_name(c_ptr_); 71 | if (entry_name) 72 | return std::string(entry_name); 73 | else 74 | return ""; 75 | } 76 | 77 | // Type of object pointed to by this entry 78 | object::object_type type() const { 79 | return static_cast(git_tree_entry_type(c_ptr_)); 80 | } 81 | 82 | // Compare two tree entries 83 | // < 0 if this is before e2 84 | // 0 if this == e2 85 | // > 0 if this is after e2 86 | int compare(const entry &e2) { 87 | return git_tree_entry_cmp(c_ptr_, e2.c_ptr()); 88 | } 89 | 90 | // Access libgit2 C ptr 91 | git_tree_entry *c_ptr() { return c_ptr_; } 92 | const git_tree_entry *c_ptr() const { return c_ptr_; } 93 | 94 | private: 95 | friend tree; 96 | friend class tree_builder; 97 | git_tree_entry *c_ptr_; 98 | ownership owner_; 99 | }; 100 | 101 | // SHA1 hash of this tree 102 | oid id() const; 103 | 104 | // Duplicate of tree 105 | tree copy() const; 106 | 107 | // Lookup tree entry by SHA value 108 | // Returned entry is owned by the tree 109 | // This must examine every entry in the tree, so it's not fast 110 | entry lookup_entry_by_id(const oid &id) const; 111 | 112 | // Lookup tree entry by its position in the tree 113 | // Returned entry is owned by the tree 114 | entry lookup_entry_by_index(size_t index) const; 115 | 116 | // Lookup tree entry by its filename 117 | // Returned entry is owned by the tree 118 | entry lookup_entry_by_name(const std::string &filename) const; 119 | 120 | // Lookup tree entry given its relative path 121 | // Returned tree entry is owned by the user 122 | entry lookup_entry_by_path(const std::string &path) const; 123 | 124 | // Number of entries in tree 125 | size_t size() const; 126 | 127 | // Tree traversal modes 128 | enum class traversal_mode { preorder = 0, postorder = 1 }; 129 | 130 | // Owning repository 131 | class repository owner() const; 132 | 133 | // Traverse the entries in a tree and its subtrees in post or pre order. 134 | void walk(traversal_mode mode, 135 | std::function 136 | visitor) const; 137 | 138 | enum class update_type { 139 | upsert, // Update or insert an entry at the specified path 140 | remove // Remove an entry from the specified path 141 | }; 142 | 143 | class update : public libgit2_api { 144 | public: 145 | tree::update_type action() const { 146 | return static_cast(c_struct_.action); 147 | } 148 | 149 | void set_action(tree::update_type update_type) { 150 | c_struct_.action = static_cast(update_type); 151 | } 152 | 153 | oid id() const { return oid(&c_struct_.id); } 154 | 155 | void set_id(const oid &id) { c_struct_.id = *(id.c_ptr()); } 156 | 157 | cppgit2::file_mode file_mode() const { 158 | return static_cast(c_struct_.filemode); 159 | } 160 | 161 | void set_file_mode(cppgit2::file_mode mode) { 162 | c_struct_.filemode = static_cast(mode); 163 | } 164 | 165 | std::string path() const { 166 | if (c_struct_.path) 167 | return std::string(c_struct_.path); 168 | else 169 | return ""; 170 | } 171 | 172 | void set_path(const std::string &path) { c_struct_.path = path.c_str(); } 173 | 174 | private: 175 | friend class repository; 176 | git_tree_update c_struct_; 177 | }; 178 | 179 | // Access libgit2 C ptr 180 | git_tree *c_ptr(); 181 | const git_tree *c_ptr() const; 182 | 183 | private: 184 | friend class commit; 185 | friend class pathspec; 186 | friend class repository; 187 | git_tree *c_ptr_; 188 | ownership owner_; 189 | }; 190 | 191 | } // namespace cppgit2 192 | -------------------------------------------------------------------------------- /include/cppgit2/tree_builder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace cppgit2 { 13 | 14 | // Always owned by user 15 | class tree_builder : public libgit2_api { 16 | public: 17 | // Create a new tree builder. 18 | // The tree builder can be used to create or modify trees in memory and write 19 | // them as tree objects to the database. 20 | tree_builder(repository &repo, tree source = tree()); 21 | 22 | // Free git_treebuilder c_ptr_ 23 | ~tree_builder(); 24 | 25 | // Clear all the entires in the builder 26 | void clear(); 27 | 28 | // The filter callback will be called for each entry in the 29 | // tree with a pointer to the entry and the provided payload; 30 | // if the callback returns non-zero, the entry will be filtered 31 | // (removed from the builder). 32 | void filter(std::function visitor); 33 | 34 | // Get the number of entries listed in a treebuilder 35 | size_t size() const; 36 | 37 | // Get an entry from the builder from its filename 38 | tree::entry operator[](const std::string &filename) const; 39 | 40 | // Add or update an entry to the builder 41 | void insert(const std::string &filename, const oid &id, file_mode mode); 42 | 43 | // Remove an entry from the builder by its filename 44 | void remove(const std::string &filename); 45 | 46 | // Write the contents of the tree builder as a tree object 47 | // The tree builder will be written to the given repo, and its identifying 48 | // SHA1 hash will be stored in the id pointer. 49 | oid write(); 50 | 51 | // Write the contents of the tree builder as a tree object using a shared 52 | // git_buf. 53 | oid write(data_buffer &tree); 54 | 55 | // Acesss libgit2 C ptr 56 | const git_treebuilder *c_ptr() const; 57 | 58 | private: 59 | git_treebuilder *c_ptr_; 60 | }; 61 | 62 | } // namespace cppgit2 -------------------------------------------------------------------------------- /include/cppgit2/worktree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace cppgit2 { 13 | 14 | class worktree : public libgit2_api { 15 | public: 16 | // Default construct a worktree 17 | worktree(); 18 | 19 | // Construct from libgit2 C ptr 20 | // If owned by user, will be free'd in the destructor 21 | worktree(git_worktree *c_ptr, ownership owner = ownership::libgit2); 22 | 23 | // Free worktree if owned by user 24 | ~worktree(); 25 | 26 | // If true, the string holds the reason 27 | std::pair is_locked() const; 28 | 29 | // 30 | // TODO: CONSIDER ADDING AN OPTIONS CLASS 31 | // AND MERGE is_prunable() & prune() METHODS 32 | // 33 | 34 | // Is the worktree prunable with the given options? 35 | // A worktree is not prunable in the following scenarios: 36 | // - the worktree is linking to a valid on-disk worktree. The valid member 37 | // will cause this check to be ignored. 38 | // - the worktree is locked. The locked flag will cause this check to be 39 | // ignored. 40 | bool is_prunable(unsigned int version, uint32_t flags) const; 41 | 42 | // Uses git_worktree_prune_options_init to initialize prune options 43 | bool is_prunable() const; 44 | 45 | // Lock worktree if not already locked 46 | // 47 | // Lock a worktree, optionally specifying a reason why the linked working tree 48 | // is being locked. 49 | void lock(const std::string &reason = ""); 50 | 51 | // Retrieve the name of the worktree 52 | std::string name() const; 53 | 54 | // Retrieve the filesystem path for the worktree 55 | std::string path() const; 56 | 57 | // Prune working tree 58 | // 59 | // Prune the working tree, that is remove the git data structures on disk. The 60 | // repository will only be pruned of worktree.is_prunable succeeds. 61 | void prune(unsigned int version, uint32_t flags); 62 | 63 | // Prune working tree 64 | // 65 | // Uses git_worktree_prune_options_init to initialize prune options 66 | void prune(); 67 | 68 | // Unlock a locked worktree 69 | void unlock(); 70 | 71 | // Check if worktree is valid 72 | // 73 | // A valid worktree requires both the git data structures inside the linked 74 | // parent repository and the linked working copy to be present. 75 | bool is_valid(); 76 | 77 | // Similar to is_valid but throws exception 78 | // if worktree is invalid 79 | bool validate(); 80 | 81 | class add_options : public libgit2_api { 82 | public: 83 | add_options() : c_ptr_(nullptr) { 84 | auto ret = git_worktree_add_init_options( 85 | &default_options_, GIT_WORKTREE_ADD_OPTIONS_VERSION); 86 | c_ptr_ = &default_options_; 87 | if (ret != 0) 88 | throw git_exception(); 89 | } 90 | 91 | add_options(git_worktree_add_options *c_ptr) : c_ptr_(c_ptr) {} 92 | 93 | // Version 94 | unsigned int version() const { return c_ptr_->version; } 95 | void set_version(unsigned int version) { c_ptr_->version = version; } 96 | 97 | // lock newly created worktree 98 | bool lock() const { return c_ptr_->lock; } 99 | void set_lock(bool value) { c_ptr_->lock = value; } 100 | 101 | // reference to use for the new worktree HEAD 102 | cppgit2::reference reference() const { 103 | return cppgit2::reference(c_ptr_->ref); 104 | } 105 | void set_reference(const cppgit2::reference &ref) { 106 | c_ptr_->ref = const_cast(ref.c_ptr()); 107 | } 108 | 109 | // Access libgit2 C ptr 110 | const git_worktree_add_options *c_ptr() const { return c_ptr_; } 111 | 112 | private: 113 | git_worktree_add_options *c_ptr_; 114 | git_worktree_add_options default_options_; 115 | }; 116 | 117 | // Flags which can be passed to git_worktree_prune to alter its 118 | // behavior. 119 | enum class prune_type { 120 | // Prune working tree even if working tree is valid 121 | valid = 1u << 0, 122 | // Prune working tree even if it is locked 123 | locked = 1u << 1, 124 | // Prune checked out working tree 125 | tree = 1u << 2, 126 | }; 127 | 128 | // Worktree prune options structure 129 | class prune_options : public libgit2_api { 130 | prune_options() : c_ptr_(nullptr) { 131 | auto ret = git_worktree_prune_init_options( 132 | &default_options_, GIT_WORKTREE_PRUNE_OPTIONS_VERSION); 133 | c_ptr_ = &default_options_; 134 | if (ret != 0) 135 | throw git_exception(); 136 | } 137 | 138 | prune_options(git_worktree_prune_options *c_ptr) : c_ptr_(c_ptr) {} 139 | 140 | // Version 141 | unsigned int version() const { return c_ptr_->version; } 142 | void set_version(unsigned int version) { c_ptr_->version = version; } 143 | 144 | // Flags 145 | prune_type flags() const { return static_cast(c_ptr_->flags); } 146 | void set_flags(prune_type flags) { 147 | c_ptr_->flags = static_cast(flags); 148 | } 149 | 150 | // Access libgit2 C ptr 151 | const git_worktree_prune_options *c_ptr() const { return c_ptr_; } 152 | 153 | private: 154 | git_worktree_prune_options *c_ptr_; 155 | git_worktree_prune_options default_options_; 156 | }; 157 | 158 | // Access libgit2 C ptr 159 | const git_worktree *c_ptr() const; 160 | 161 | private: 162 | friend class repository; 163 | git_worktree *c_ptr_; 164 | ownership owner_; 165 | }; 166 | ENABLE_BITMASK_OPERATORS(worktree::prune_type); 167 | 168 | } // namespace cppgit2 -------------------------------------------------------------------------------- /samples/add_attribute_macro.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::init(argv[1], false); 8 | repo.add_attributes_macro("abc", "foo bar baz"); 9 | repo.flush_attributes_cache(); 10 | } else { 11 | std::cout << "Usage: ./executable \n"; 12 | } 13 | } -------------------------------------------------------------------------------- /samples/blame_file.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 3) { 7 | auto repo = repository::init(argv[1], false); 8 | auto blame = repo.blame_file(argv[2]); 9 | auto hunk_count = blame.hunk_count(); 10 | std::cout << "Blame Hunk count: " << hunk_count << std::endl; 11 | std::cout << "Blame Hunk by index:" << std::endl; 12 | for (uint32_t i = 0; i < hunk_count; ++i) { 13 | auto hunk = blame.hunk_by_index(i); 14 | auto original_commit_id = hunk.orig_commit_id(); 15 | auto original_signature = hunk.orig_signature(); 16 | std::cout << "[" << i << "] " << original_commit_id.to_hex_string() << " " 17 | << hunk.boundary() << " " << original_signature.name() << " " 18 | << original_signature.email() << std::endl; 19 | } 20 | } else { 21 | std::cout 22 | << "Usage: ./executable \n"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /samples/branch_remote_name.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | int main(int argc, char **argv) { 5 | if (argc == 2) { 6 | auto repo = repository::open(argv[1]); 7 | std::cout << repo.branch_remote_name( 8 | "refs/remotes/origin/master") // prints "origin" 9 | << std::endl; 10 | } else { 11 | std::cout << "Usage: ./executable \n"; 12 | } 13 | } -------------------------------------------------------------------------------- /samples/cat_file.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace cppgit2; 6 | 7 | void print_signature(const std::string &header, const signature &sig) { 8 | char sign; 9 | auto offset = sig.offset(); 10 | if (offset < 0) { 11 | sign = '-'; 12 | offset = -offset; 13 | } else { 14 | sign = '+'; 15 | } 16 | 17 | auto hours = offset / 60; 18 | auto minutes = offset % 60; 19 | 20 | std::cout << header << " " << sig.name() << " " 21 | << "<" << sig.email() << "> " << sig.time() << " " << sign; 22 | std::cout << std::setfill('0') << std::setw(2) << hours; 23 | std::cout << std::setfill('0') << std::setw(2) << minutes << std::endl; 24 | } 25 | 26 | // Printing out a blob is simple, get the contents and print 27 | void show_blob(const blob &blob) { 28 | std::fwrite(blob.raw_contents(), blob.raw_size(), 1, stdout); 29 | } 30 | 31 | // Show each entry with its type, id and attributes 32 | void show_tree(const tree &tree) { 33 | size_t count = tree.size(); 34 | for (size_t i = 0; i < tree.size(); ++i) { 35 | auto entry = tree.lookup_entry_by_index(i); 36 | 37 | std::cout << std::setfill('0') << std::oct << std::setw(6) 38 | << static_cast(entry.filemode()); 39 | std::cout << " " << object::object_type_to_string(entry.type()) << " " 40 | << entry.id().to_hex_string() << "\t" << entry.filename() 41 | << std::endl; 42 | } 43 | } 44 | 45 | // Commits and tags have a few interesting fields in their header. 46 | void show_commit(const commit &commit) { 47 | std::cout << "tree " << commit.tree_id().to_hex_string() << std::endl; 48 | 49 | for (size_t i = 0; i < commit.parent_count(); ++i) 50 | std::cout << "parent " << commit.parent_id(i).to_hex_string() << std::endl; 51 | 52 | print_signature("author", commit.author()); 53 | print_signature("committer", commit.committer()); 54 | 55 | auto message = commit.message(); 56 | if (!message.empty()) 57 | std::cout << "\n" << message << std::endl; 58 | } 59 | 60 | void show_tag(const tag &tag) { 61 | std::cout << "object " << tag.id().to_hex_string() << std::endl; 62 | std::cout << "type " << object::object_type_to_string(tag.target_type()) 63 | << std::endl; 64 | std::cout << "tag " << tag.name() << std::endl; 65 | print_signature("tagger", tag.tagger()); 66 | 67 | auto tag_message = tag.message(); 68 | if (!tag_message.empty()) 69 | std::cout << "\n" << tag_message << std::endl; 70 | } 71 | 72 | int main(int argc, char **argv) { 73 | if (argc == 3) { 74 | auto repo_path = repository::discover_path("."); 75 | auto repo = repository::open(repo_path); 76 | 77 | enum class actions { size, type, pretty }; 78 | actions action; 79 | 80 | if (strncmp(argv[1], "-s", 2) == 0) { 81 | action = actions::size; 82 | } else if (strncmp(argv[1], "-t", 2) == 0) { 83 | action = actions::type; 84 | } else if (strncmp(argv[1], "-p", 2) == 0) { 85 | action = actions::pretty; 86 | } 87 | 88 | auto revision_str = argv[2]; 89 | auto object = repo.revparse_to_object(revision_str); 90 | 91 | switch (action) { 92 | case actions::type: 93 | std::cout << object::object_type_to_string(object.type()) << std::endl; 94 | break; 95 | case actions::size: 96 | std::cout << repo.odb().read(object.id()).size() << std::endl; 97 | break; 98 | case actions::pretty: 99 | switch (object.type()) { 100 | case object::object_type::blob: 101 | show_blob(object.as_blob()); 102 | break; 103 | case object::object_type::commit: 104 | show_commit(object.as_commit()); 105 | break; 106 | case object::object_type::tree: 107 | show_tree(object.as_tree()); 108 | break; 109 | case object::object_type::tag: 110 | show_tag(object.as_tag()); 111 | break; 112 | default: 113 | std::cout << "unknown " << revision_str << std::endl; 114 | break; 115 | } 116 | break; 117 | } 118 | 119 | } else { 120 | std::cout << "Usage: ./executable (-s | -t | -p) \n"; 121 | } 122 | } -------------------------------------------------------------------------------- /samples/check_ignore_rules.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace cppgit2; 5 | 6 | int main(int argc, char **argv) { 7 | if (argc == 3) { 8 | auto repo = repository::open(argv[1]); 9 | 10 | std::cout << "Should ignore file " << argv[2] << "? "; 11 | std::cout << std::boolalpha << repo.should_ignore(argv[2]) << std::endl; 12 | 13 | // Example output: 14 | 15 | // $ ./samples/check_ignore_rules ../. .gitignore 16 | // Should ignore file .gitignore? false 17 | 18 | // $ ./samples/check_ignore_rules ../. main.cpp 19 | // Should ignore file main.cpp? false 20 | 21 | // $ ./samples/check_ignore_rules ../. build 22 | // Should ignore file build? true 23 | 24 | } else { 25 | std::cout << "Usage: ./executable \n"; 26 | } 27 | } -------------------------------------------------------------------------------- /samples/clone_and_checkout_branch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 4) { 7 | clone::options options; 8 | options.set_checkout_branch_name(argv[3]); 9 | auto repo = repository::clone(argv[1], argv[2], options); 10 | } else { 11 | std::cout 12 | << "Usage: ./executable \n"; 13 | } 14 | } -------------------------------------------------------------------------------- /samples/clone_repository.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 3) { 7 | auto repo = repository::clone(argv[1], argv[2]); 8 | } else { 9 | std::cout << "Usage: ./executable \n"; 10 | } 11 | } -------------------------------------------------------------------------------- /samples/commit_file.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace cppgit2; 5 | 6 | int main(int argc, char **argv) { 7 | if (argc == 2) { 8 | // Create new repo 9 | auto repo = repository::init(argv[1], false); 10 | 11 | // Write README file 12 | std::ofstream readme; 13 | readme.open(std::string{argv[1]} + "/README.md"); 14 | readme << "Hello, World!"; 15 | readme.close(); 16 | 17 | // Get repo index and write as tree 18 | auto index = repo.index(); 19 | index.add_entry_by_path("README.md"); 20 | index.write(); 21 | auto tree_oid = index.write_tree(); 22 | 23 | // Prepare signatures 24 | auto author = signature("foobar", "foo.bar@baz.com"); 25 | auto committer = signature("foobar", "foo.bar@baz.com"); 26 | 27 | // Create commit 28 | auto commit_oid = 29 | repo.create_commit("HEAD", author, committer, "utf-8", "Update README", 30 | repo.lookup_tree(tree_oid), {}); 31 | 32 | std::cout << "Created commit with ID: " << commit_oid.to_hex_string() 33 | << std::endl; 34 | 35 | } else { 36 | std::cout << "Usage: ./executable \n"; 37 | } 38 | } -------------------------------------------------------------------------------- /samples/create_bare_repository.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::init(argv[1], true); 8 | } else { 9 | std::cout << "Usage: ./executable \n"; 10 | } 11 | } -------------------------------------------------------------------------------- /samples/create_branch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace cppgit2; 5 | 6 | int main(int argc, char **argv) { 7 | if (argc == 2) { 8 | // Create new repo 9 | auto repo = repository::init(argv[1], false); 10 | 11 | std::cout << "Initialized repository " << argv[1] << std::endl; 12 | 13 | // Write README file 14 | std::ofstream readme; 15 | readme.open(std::string{argv[1]} + "/README.md"); 16 | readme << "Hello, World!\n"; 17 | readme.close(); 18 | 19 | std::cout << "Created README file" << std::endl; 20 | 21 | // Get repo index and write as tree 22 | auto index = repo.index(); 23 | index.add_entry_by_path("README.md"); 24 | index.write(); 25 | auto tree_oid = index.write_tree(); 26 | 27 | std::cout << "Staged README.md" << std::endl; 28 | 29 | // Prepare signatures 30 | auto author = signature("foobar", "foo.bar@baz.com"); 31 | auto committer = signature("foobar", "foo.bar@baz.com"); 32 | 33 | // Create commit 34 | auto commit_oid = 35 | repo.create_commit("HEAD", author, committer, "utf-8", "Initial README", 36 | repo.lookup_tree(tree_oid), {}); 37 | auto commit = repo.lookup_commit(commit_oid); 38 | 39 | std::cout << "Created commit " << commit_oid.to_hex_string(8) 40 | << " in the master branch" << std::endl; 41 | 42 | // Create branch - update_readme 43 | auto branch_name = "update_readme"; 44 | auto branch_ref = repo.create_branch(branch_name, commit, false); 45 | 46 | std::cout << "Created branch " << branch_name << std::endl; 47 | 48 | // Checkout branch - update_readme 49 | auto treeish = repo.revparse_to_object(branch_name); 50 | repo.checkout_tree(treeish); 51 | repo.set_head(branch_ref.name()); 52 | 53 | std::cout << "Checked out " << branch_name << std::endl; 54 | 55 | // Update the README file 56 | readme.open(std::string{argv[1]} + "/README.md"); 57 | readme << "Hello, World!\nUpdated README"; 58 | readme.close(); 59 | 60 | std::cout << "Updated README.md" << std::endl; 61 | 62 | // Get repo index and write as tree 63 | index = repo.index(); 64 | index.add_entry_by_path("README.md"); 65 | index.write(); 66 | tree_oid = index.write_tree(); 67 | 68 | std::cout << "Staged README.md\n"; 69 | 70 | // Create commit in update_readme branch 71 | auto commit_oid_2 = repo.create_commit( 72 | branch_ref.name(), author, committer, "utf-8", "Update README", 73 | repo.lookup_tree(tree_oid), {commit}); 74 | auto commit_2 = repo.lookup_commit(commit_oid_2); 75 | 76 | std::cout << "Created commit " << commit_oid_2.to_hex_string(8) << "in " 77 | << branch_name << std::endl; 78 | 79 | } else { 80 | std::cout << "Usage: ./executable \n"; 81 | } 82 | } -------------------------------------------------------------------------------- /samples/create_empty_initial_commit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace cppgit2; 5 | 6 | int main(int argc, char **argv) { 7 | if (argc == 2) { 8 | 9 | // Create new repo 10 | auto repo = repository::init(argv[1], false); 11 | 12 | // Write repo index as tree 13 | auto index = repo.index(); 14 | auto tree_oid = index.write_tree(); 15 | 16 | // Prepare signatures 17 | auto author = signature("foobar", "foo.bar@baz.com"); 18 | auto committer = signature("foobar", "foo.bar@baz.com"); 19 | 20 | // Create commit 21 | auto commit_oid = 22 | repo.create_commit("HEAD", author, committer, "utf-8", "Initial commit", 23 | repo.lookup_tree(tree_oid), {}); 24 | 25 | std::cout << "Created commit with ID: " << commit_oid.to_hex_string() 26 | << std::endl; 27 | 28 | } else { 29 | std::cout << "Usage: ./executable \n"; 30 | } 31 | } -------------------------------------------------------------------------------- /samples/create_remote.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace cppgit2; 5 | 6 | int main(int argc, char **argv) { 7 | if (argc == 2) { 8 | 9 | // Create new repo 10 | auto repo = repository::init(argv[1], false); 11 | 12 | // Create remote 13 | auto remote = 14 | repo.create_remote("origin", "https://github.com/p-ranav/test"); 15 | 16 | } else { 17 | std::cout << "Usage: ./executable \n"; 18 | } 19 | } -------------------------------------------------------------------------------- /samples/create_repository.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::init(argv[1], false); 8 | } else { 9 | std::cout << "Usage: ./executable \n"; 10 | } 11 | } -------------------------------------------------------------------------------- /samples/discover_path.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | int main(int argc, char **argv) { 5 | if (argc == 2) { 6 | // Discover repository path by walking up from argv[1] 7 | // When a repository is discovered, its .git directory is returned 8 | // as the result 9 | std::cout << repository::discover_path(argv[1], true, "/") << std::endl; 10 | } else { 11 | std::cout << "Usage: ./executable \n"; 12 | } 13 | } -------------------------------------------------------------------------------- /samples/lookup_submodule.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 3) { 7 | 8 | auto repo = repository::open(argv[1]); 9 | auto module = repo.lookup_submodule(argv[2]); 10 | std::cout << module.name() << " from " << module.url() << std::endl; 11 | 12 | } else { 13 | std::cout << "Usage: ./executable \n"; 14 | } 15 | } -------------------------------------------------------------------------------- /samples/open_submodule.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | int main(int argc, char **argv) { 5 | if (argc == 3) { 6 | auto repo = repository::open(argv[1]); 7 | auto sm = repo.lookup_submodule(argv[2]); 8 | std::cout << sm.name() << " from " << sm.url() << std::endl; 9 | std::cout << "Opening submodule as repo\n"; 10 | 11 | auto submodule_repo = sm.open_repository(); 12 | std::cout << "Path: " << submodule_repo.path() << std::endl; 13 | 14 | std::cout << "References\n:"; 15 | submodule_repo.for_each_reference( 16 | [](const reference &ref) { std::cout << ref.name() << std::endl; }); 17 | 18 | } else { 19 | // Example usage: ./samples/repository_open_submodule ../. "ext/libgit2" 20 | std::cout << "Usage: ./executable \n"; 21 | std::cout 22 | << "Example usage: ▶ ./samples/open_submodule ../. \"ext/libgit2\"" 23 | << std::endl; 24 | } 25 | } -------------------------------------------------------------------------------- /samples/pathspec_match_repo_workdir.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | int main(int argc, char **argv) { 5 | if (argc == 3) { 6 | auto repo = repository::open(argv[1]); 7 | 8 | auto pathspec = pathspec::compile(std::vector{argv[2]}); 9 | auto match_list = pathspec.match_workdir(repo, pathspec::flag::default_); 10 | std::cout << "Matched " << match_list.size() << " files\n"; 11 | for (size_t i = 0; i < match_list.size(); ++i) { 12 | std::cout << "* " << match_list.entry(i) << std::endl; 13 | } 14 | } else { 15 | std::cout << "Usage: ./executable \n"; 16 | } 17 | } 18 | 19 | // Example output: 20 | // $ ./samples/pathspec_match_repo_workdir ../. "include/cppgit2/*.hpp" 21 | 22 | /* 23 | Matched 41 files 24 | * include/cppgit2/annotated_commit.hpp 25 | * include/cppgit2/apply.hpp 26 | * include/cppgit2/attribute.hpp 27 | * include/cppgit2/bitmask_operators.hpp 28 | * include/cppgit2/blame.hpp 29 | * include/cppgit2/blob.hpp 30 | * include/cppgit2/branch.hpp 31 | * include/cppgit2/checkout.hpp 32 | * include/cppgit2/commit.hpp 33 | * include/cppgit2/config.hpp 34 | * include/cppgit2/data_buffer.hpp 35 | * include/cppgit2/diff.hpp 36 | * include/cppgit2/file_mode.hpp 37 | * include/cppgit2/git_exception.hpp 38 | * include/cppgit2/index.hpp 39 | * include/cppgit2/libgit2_api.hpp 40 | * include/cppgit2/note.hpp 41 | * include/cppgit2/object.hpp 42 | * include/cppgit2/odb.hpp 43 | * include/cppgit2/oid.hpp 44 | * include/cppgit2/ownership.hpp 45 | * include/cppgit2/pack_builder.hpp 46 | * include/cppgit2/pathspec.hpp 47 | * include/cppgit2/proxy.hpp 48 | * include/cppgit2/push.hpp 49 | * include/cppgit2/reference.hpp 50 | * include/cppgit2/reflog.hpp 51 | * include/cppgit2/repository.hpp 52 | * include/cppgit2/reset.hpp 53 | * include/cppgit2/revision.hpp 54 | * include/cppgit2/signature.hpp 55 | * include/cppgit2/stash.hpp 56 | * include/cppgit2/status.hpp 57 | * include/cppgit2/strarray.hpp 58 | * include/cppgit2/submodule.hpp 59 | * include/cppgit2/tag.hpp 60 | * include/cppgit2/time.hpp 61 | * include/cppgit2/transaction.hpp 62 | * include/cppgit2/tree.hpp 63 | * include/cppgit2/tree_builder.hpp 64 | * include/cppgit2/worktree.hpp 65 | */ -------------------------------------------------------------------------------- /samples/print_attributes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::init(argv[1], false); 8 | 9 | repo.for_each_attribute( 10 | attribute::flag::file_then_index, ".gitattributes", 11 | [](const std::string &name, const std::string &value) { 12 | std::cout << name << ": " << value << std::endl; 13 | }); 14 | } else { 15 | std::cout << "Usage: ./executable \n"; 16 | } 17 | } -------------------------------------------------------------------------------- /samples/print_branches.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::open(argv[1]); 8 | 9 | std::cout << "Local branches:\n"; 10 | repo.for_each_branch( 11 | [](const reference &ref) { 12 | std::cout << "* " << ref.name() << std::endl; 13 | }, 14 | branch::branch_type::local); 15 | 16 | std::cout << "Remote branches:\n"; 17 | repo.for_each_branch( 18 | [](const reference &ref) { 19 | std::cout << "* " << ref.name() << std::endl; 20 | }, 21 | branch::branch_type::remote); 22 | 23 | } else { 24 | std::cout << "Usage: ./executable \n"; 25 | } 26 | } -------------------------------------------------------------------------------- /samples/print_commits.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::open(argv[1]); 8 | 9 | repo.for_each_commit([](const commit &c) { 10 | std::cout << c.id().to_hex_string(8) << " [" << c.committer().name() 11 | << "]" 12 | << " " << c.summary() << std::endl; 13 | }); 14 | 15 | } else { 16 | std::cout << "Usage: ./executable \n"; 17 | } 18 | } -------------------------------------------------------------------------------- /samples/print_default_signature.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::open(argv[1]); 8 | 9 | auto default_signature = repo.default_signature(); 10 | std::cout << "Name: " << default_signature.name() 11 | << "\nEmail: " << default_signature.email() << std::endl; 12 | 13 | } else { 14 | std::cout << "Usage: ./executable \n"; 15 | } 16 | } -------------------------------------------------------------------------------- /samples/print_diff_index_to_workdir.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace cppgit2; 5 | 6 | int main(int argc, char **argv) { 7 | if (argc == 2) { 8 | auto repo = repository::open(argv[1]); 9 | auto index = repo.index(); 10 | 11 | auto diff = repo.create_diff_index_to_workdir(index); 12 | 13 | diff.for_each( 14 | // File Callback 15 | [](const diff::delta &delta, float progress) { 16 | auto status = delta.status(); 17 | 18 | switch (status) { 19 | case diff::delta::type::added: 20 | std::cout << "Added " << delta.new_file().path() << std::endl; 21 | break; 22 | case diff::delta::type::deleted: 23 | std::cout << "Deleted " << delta.new_file().path() << std::endl; 24 | break; 25 | case diff::delta::type::modified: 26 | std::cout << "Modified " << delta.new_file().path() << std::endl; 27 | break; 28 | case diff::delta::type::renamed: 29 | std::cout << "Renamed " << delta.old_file().path() << " -> " 30 | << delta.new_file().path() << std::endl; 31 | break; 32 | case diff::delta::type::copied: 33 | std::cout << "Copied " << delta.new_file().path() << std::endl; 34 | break; 35 | case diff::delta::type::untracked: 36 | std::cout << "Untracked " << delta.new_file().path() << std::endl; 37 | break; 38 | default: 39 | break; 40 | } 41 | } 42 | // TODO: add the 3 other callbacks - binary_callback, hunk_callback, 43 | // line_callback and prepare a nice diff view 44 | ); 45 | 46 | } else { 47 | std::cout << "Usage: ./executable \n"; 48 | } 49 | } -------------------------------------------------------------------------------- /samples/print_references.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::open(argv[1]); 8 | 9 | repo.for_each_reference( 10 | [](const reference &ref) { std::cout << ref.name() << std::endl; }); 11 | 12 | // Use the following if you just want to iterate over reference names 13 | // repo.for_each_reference_name( 14 | // [](const std::string &refname) { std::cout << refname << std::endl; 15 | // }); 16 | 17 | // Use the following if you want to print normalized reference names 18 | // repo.for_each_reference( 19 | // [](const reference &ref) { 20 | // std::cout << reference::normalize_name(256, ref.name(), 21 | // reference::format::allow_onelevel) << std::endl; }); 22 | 23 | } else { 24 | std::cout << "Usage: ./executable \n"; 25 | } 26 | } -------------------------------------------------------------------------------- /samples/print_reflog_head.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | int main(int argc, char **argv) { 5 | if (argc == 2) { 6 | auto repo = repository::open(argv[1]); 7 | 8 | auto reflog = repo.read_reflog("HEAD"); 9 | for (size_t i = 0; i < reflog.size(); ++i) { 10 | auto entry = reflog[i]; 11 | std::cout << entry.new_oid().to_hex_string(8) << " HEAD@{" << i 12 | << "}: " << entry.message() << std::endl; 13 | } 14 | } else { 15 | std::cout << "Usage: ./executable \n"; 16 | } 17 | } -------------------------------------------------------------------------------- /samples/print_stash_entries.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::open(argv[1]); 8 | 9 | repo.for_each_stash( 10 | [](size_t index, const std::string &message, const oid &id) { 11 | std::cout << index << " [" << id.to_hex_string(8) << "] " << message 12 | << std::endl; 13 | }); 14 | 15 | } else { 16 | std::cout << "Usage: ./executable \n"; 17 | } 18 | } -------------------------------------------------------------------------------- /samples/print_status.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace cppgit2; 5 | 6 | int main(int argc, char **argv) { 7 | if (argc == 2) { 8 | auto repo = repository::open(argv[1]); 9 | 10 | repo.for_each_status( 11 | [](const std::string &path, status::status_type status_flags) { 12 | if ((status_flags & status::status_type::index_modified) != 13 | status::status_type::index_modified) { 14 | if ((status_flags & status::status_type::ignored) != 15 | status::status_type::ignored) { 16 | std::cout << "modified: " << path << std::endl; 17 | } else { 18 | std::cout << "ignored: " << path << std::endl; 19 | } 20 | } 21 | }); 22 | 23 | } else { 24 | std::cout << "Usage: ./executable \n"; 25 | } 26 | } -------------------------------------------------------------------------------- /samples/print_submodules.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace cppgit2; 5 | 6 | int main(int argc, char **argv) { 7 | if (argc == 2) { 8 | auto repo = repository::open(argv[1]); 9 | 10 | repo.for_each_submodule( 11 | [](const submodule &module, const std::string &path) { 12 | std::cout << module.name() << " " << module.url() << std::endl; 13 | }); 14 | 15 | } else { 16 | std::cout << "Usage: ./executable \n"; 17 | } 18 | } -------------------------------------------------------------------------------- /samples/print_tag_names.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::open(argv[1]); 8 | 9 | // Fetch, iterate over and print tags 10 | for (const auto &tag : repo.tags()) 11 | std::cout << tag << std::endl; 12 | 13 | } else { 14 | std::cout << "Usage: ./executable \n"; 15 | } 16 | } -------------------------------------------------------------------------------- /samples/print_tags.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::open(argv[1]); 8 | 9 | repo.for_each_tag([&repo](const std::string &name, const oid &id) { 10 | std::cout << "[" << id.to_hex_string(8) << "] " << name << std::endl; 11 | }); 12 | 13 | } else { 14 | std::cout << "Usage: ./executable \n"; 15 | } 16 | } -------------------------------------------------------------------------------- /samples/revwalk_from_head.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | int main(int argc, char **argv) { 5 | if (argc == 2) { 6 | auto repo = repository::open(argv[1]); 7 | auto revwalk = repo.create_revwalk(); 8 | revwalk.push_head(); 9 | while (!revwalk.done()) { 10 | auto id = revwalk.next(); 11 | auto commit = repo.lookup_commit(id); 12 | 13 | std::cout << "[" << id.to_hex_string(8) << "] " << commit.summary() 14 | << std::endl; 15 | } 16 | } else { 17 | std::cout << "Usage: ./executable \n"; 18 | } 19 | } -------------------------------------------------------------------------------- /samples/walk_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cppgit2; 4 | 5 | int main(int argc, char **argv) { 6 | if (argc == 2) { 7 | auto repo = repository::open(argv[1]); 8 | 9 | // Get the HEAD tree 10 | auto head = repo.head(); 11 | auto head_commit = repo.lookup_commit(head.target()); 12 | auto tree = head_commit.tree(); 13 | 14 | tree.walk(tree::traversal_mode::preorder, 15 | [](const std::string &root, const tree::entry &entry) { 16 | auto type = entry.type(); 17 | std::string type_string{""}; 18 | switch (type) { 19 | case object::object_type::blob: 20 | type_string = " - blob"; 21 | break; 22 | case object::object_type::tree: 23 | type_string = "tree"; 24 | break; 25 | case object::object_type::commit: 26 | type_string = " - commit"; 27 | break; 28 | default: 29 | type_string = "other"; 30 | break; 31 | } 32 | std::cout << type_string << " [" << entry.id().to_hex_string(8) 33 | << "] " << entry.filename() << std::endl; 34 | }); 35 | 36 | } else { 37 | std::cout << "Usage: ./executable \n"; 38 | } 39 | } -------------------------------------------------------------------------------- /src/annotated_commit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | annotated_commit::annotated_commit() 6 | : c_ptr_(nullptr), owner_(ownership::libgit2) {} 7 | 8 | annotated_commit::annotated_commit(git_annotated_commit *c_ptr, ownership owner) 9 | : c_ptr_(c_ptr), owner_(owner) {} 10 | 11 | annotated_commit::~annotated_commit() { 12 | if (c_ptr_ && owner_ == ownership::user) 13 | git_annotated_commit_free(c_ptr_); 14 | } 15 | 16 | oid annotated_commit::id() const { 17 | return oid(git_annotated_commit_id(c_ptr_)); 18 | } 19 | 20 | std::string annotated_commit::refname() const { 21 | auto ret = git_annotated_commit_ref(c_ptr_); 22 | if (ret) 23 | return std::string(ret); 24 | else 25 | return ""; 26 | } 27 | 28 | const git_annotated_commit *annotated_commit::c_ptr() const { return c_ptr_; } 29 | 30 | } // namespace cppgit2 -------------------------------------------------------------------------------- /src/attribute.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | attribute::attribute_value attribute::value(const std::string &attr) { 6 | auto attr_c = attr.empty() ? nullptr : attr.c_str(); 7 | return static_cast(git_attr_value(attr_c)); 8 | } 9 | 10 | } // namespace cppgit2 -------------------------------------------------------------------------------- /src/blame.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | blame::blame() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 6 | 7 | blame::blame(git_blame *c_ptr, ownership owner) 8 | : c_ptr_(c_ptr), owner_(owner) {} 9 | 10 | blame::~blame() { 11 | if (c_ptr_ && owner_ == ownership::user) 12 | git_blame_free(c_ptr_); 13 | } 14 | 15 | blame blame::get_blame_for_buffer(const blame &reference, 16 | const std::string &buffer) { 17 | blame result(nullptr, ownership::user); 18 | if (git_blame_buffer(&result.c_ptr_, 19 | const_cast(reference.c_ptr()), 20 | buffer.c_str(), buffer.size())) 21 | throw git_exception(); 22 | return result; 23 | } 24 | 25 | blame::hunk blame::hunk_by_index(uint32_t index) const { 26 | return hunk(git_blame_get_hunk_byindex(c_ptr_, index)); 27 | } 28 | 29 | blame::hunk blame::hunk_by_line(size_t lineno) const { 30 | return hunk(git_blame_get_hunk_byline(c_ptr_, lineno)); 31 | } 32 | 33 | size_t blame::hunk_count() const { return git_blame_get_hunk_count(c_ptr_); } 34 | 35 | const git_blame *blame::c_ptr() const { return c_ptr_; } 36 | 37 | } // namespace cppgit2 -------------------------------------------------------------------------------- /src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | blob::blob() : c_ptr_(nullptr) {} 6 | 7 | blob::blob(const git_blob *c_ptr) { 8 | if (git_blob_dup(&c_ptr_, const_cast(c_ptr))) 9 | throw git_exception(); 10 | } 11 | 12 | blob::~blob() { 13 | if (c_ptr_) 14 | git_blob_free(c_ptr_); 15 | } 16 | 17 | repository blob::owner() const { return repository(git_blob_owner(c_ptr_)); } 18 | 19 | blob blob::copy() const { 20 | blob result; 21 | if (git_blob_dup(&result.c_ptr_, c_ptr_)) 22 | throw git_exception(); 23 | return result; 24 | } 25 | 26 | oid blob::id() const { return oid(git_blob_id(c_ptr_)); } 27 | 28 | bool blob::is_binary() const { return git_blob_is_binary(c_ptr_); } 29 | 30 | const void *blob::raw_contents() const { return git_blob_rawcontent(c_ptr_); } 31 | 32 | blob_size blob::raw_size() const { return git_blob_rawsize(c_ptr_); } 33 | 34 | const git_blob *blob::c_ptr() const { return c_ptr_; } 35 | 36 | } // namespace cppgit2 37 | -------------------------------------------------------------------------------- /src/commit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | commit::commit() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 6 | 7 | commit::commit(git_commit *c_ptr, ownership owner) 8 | : c_ptr_(c_ptr), owner_(owner) {} 9 | 10 | commit::~commit() { 11 | if (c_ptr_ && owner_ == ownership::user) 12 | git_commit_free(c_ptr_); 13 | } 14 | 15 | void commit::amend(const oid &id, const std::string &update_ref, 16 | const signature &author, const signature &committer, 17 | const std::string &message_encoding, 18 | const std::string &message, const cppgit2::tree &tree) { 19 | if (git_commit_amend(const_cast(id.c_ptr()), c_ptr_, 20 | update_ref.c_str(), author.c_ptr(), committer.c_ptr(), 21 | message_encoding.c_str(), message.c_str(), tree.c_ptr())) 22 | throw git_exception(); 23 | } 24 | 25 | signature commit::author() const { 26 | auto ret = git_commit_author(c_ptr_); 27 | return signature(ret->name, ret->email, ret->when.time, ret->when.offset); 28 | } 29 | 30 | std::string commit::body() const { 31 | auto ret = git_commit_body(c_ptr_); 32 | if (ret) 33 | return std::string(ret); 34 | else 35 | return ""; 36 | } 37 | 38 | signature commit::committer() const { 39 | auto ret = git_commit_committer(c_ptr_); 40 | return signature(ret->name, ret->email, ret->when.time, ret->when.offset); 41 | } 42 | 43 | commit commit::copy() const { 44 | commit result(nullptr, ownership::user); 45 | if (git_commit_dup(&result.c_ptr_, c_ptr_)) 46 | throw git_exception(); 47 | return result; 48 | } 49 | 50 | std::string commit::operator[](const std::string &field) const { 51 | data_buffer result(nullptr); 52 | if (git_commit_header_field(result.c_ptr(), c_ptr_, field.c_str())) 53 | throw git_exception(); 54 | return result.to_string(); 55 | } 56 | 57 | oid commit::id() const { return oid(git_commit_id(c_ptr_)); } 58 | 59 | std::string commit::message() const { 60 | auto ret = git_commit_message(c_ptr_); 61 | if (ret) 62 | return std::string(ret); 63 | else 64 | return ""; 65 | } 66 | 67 | std::string commit::message_encoding() const { 68 | auto ret = git_commit_message_encoding(c_ptr_); 69 | if (ret) 70 | return std::string(ret); 71 | else 72 | return ""; 73 | } 74 | 75 | std::string commit::message_raw() const { 76 | auto ret = git_commit_message_raw(c_ptr_); 77 | if (ret) 78 | return std::string(ret); 79 | else 80 | return ""; 81 | } 82 | 83 | commit commit::ancestor(unsigned long n) const { 84 | commit result(nullptr, ownership::user); 85 | if (git_commit_nth_gen_ancestor(&result.c_ptr_, c_ptr_, n)) 86 | throw git_exception(); 87 | return result; 88 | } 89 | 90 | commit commit::parent(const unsigned int n) const { 91 | commit result(nullptr, ownership::user); 92 | if (git_commit_parent(&result.c_ptr_, c_ptr_, n)) 93 | throw git_exception(); 94 | return result; 95 | } 96 | 97 | oid commit::parent_id(unsigned int n) const { 98 | return oid(git_commit_parent_id(c_ptr_, n)); 99 | } 100 | 101 | unsigned int commit::parent_count() const { 102 | return git_commit_parentcount(c_ptr_); 103 | } 104 | 105 | std::string commit::raw_header() const { 106 | auto ret = git_commit_raw_header(c_ptr_); 107 | if (ret) 108 | return std::string(ret); 109 | else 110 | return ""; 111 | } 112 | 113 | std::string commit::summary() const { 114 | auto ret = git_commit_summary(c_ptr_); 115 | if (ret) 116 | return std::string(ret); 117 | else 118 | return ""; 119 | } 120 | 121 | epoch_time_seconds commit::time() const { return git_commit_time(c_ptr_); } 122 | 123 | offset_minutes commit::time_offset() const { 124 | return git_commit_time_offset(c_ptr_); 125 | } 126 | 127 | tree commit::tree() const { 128 | cppgit2::tree result(nullptr, ownership::user); 129 | if (git_commit_tree(&result.c_ptr_, c_ptr_)) 130 | throw git_exception(); 131 | return result; 132 | } 133 | 134 | oid commit::tree_id() const { return oid(git_commit_tree_id(c_ptr_)); } 135 | 136 | repository commit::owner() const { 137 | return repository(git_commit_owner(c_ptr_)); 138 | } 139 | 140 | const git_commit *commit::c_ptr() const { return c_ptr_; } 141 | 142 | } // namespace cppgit2 -------------------------------------------------------------------------------- /src/credential.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | credential::credential() { 5 | if (git_credential_default_new(&c_ptr_)) 6 | throw git_exception(); 7 | } 8 | 9 | credential::credential(const std::string &username, 10 | const std::string &password) { 11 | if (git_credential_userpass_plaintext_new(&c_ptr_, username.c_str(), 12 | password.c_str())) 13 | throw git_exception(); 14 | } 15 | 16 | credential::credential(const std::string &username, 17 | const std::string &public_key, 18 | const std::string &private_key, 19 | const std::string &passphrase) { 20 | if (git_credential_ssh_key_new(&c_ptr_, username.c_str(), public_key.c_str(), 21 | private_key.c_str(), passphrase.c_str())) 22 | throw git_exception(); 23 | } 24 | 25 | credential::credential(const std::string &username) { 26 | if (git_credential_ssh_key_from_agent(&c_ptr_, username.c_str())) 27 | throw git_exception(); 28 | } 29 | 30 | credential::credential(const std::string &username, 31 | git_credential_ssh_interactive_cb prompt_callback, 32 | void *payload) { 33 | if (git_credential_ssh_interactive_new(&c_ptr_, username.c_str(), 34 | prompt_callback, payload)) 35 | throw git_exception(); 36 | } 37 | 38 | credential::credential(const std::string &username, 39 | const std::string &public_key, 40 | git_credential_sign_cb sign_callback, void *payload) { 41 | if (git_credential_ssh_custom_new(&c_ptr_, username.c_str(), 42 | public_key.c_str(), public_key.size(), 43 | sign_callback, payload)) 44 | throw git_exception(); 45 | } 46 | 47 | credential::~credential() { 48 | if (c_ptr_) 49 | git_credential_free(c_ptr_); 50 | } 51 | 52 | std::string credential::username() const { 53 | auto ret = git_credential_get_username(c_ptr_); 54 | return ret ? std::string(ret) : ""; 55 | } 56 | 57 | bool credential::has_username() const { 58 | return git_credential_has_username(c_ptr_); 59 | } 60 | 61 | const git_credential *credential::c_ptr() const { return c_ptr_; } -------------------------------------------------------------------------------- /src/data_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | /* Used as default value for git_buf->ptr so that people can always 6 | * assume ptr is non-NULL and zero terminated even for new git_bufs. 7 | */ 8 | char git_buf__initbuf[1]; 9 | /* Use to initialize buffer structure when git_buf is on stack */ 10 | #define GIT_BUF_INIT \ 11 | { git_buf__initbuf, 0, 0 } 12 | 13 | data_buffer::data_buffer() { c_struct_ = GIT_BUF_INIT; } 14 | 15 | data_buffer::data_buffer(size_t n) { 16 | c_struct_.ptr = (char *)malloc(n * sizeof(char)); 17 | if (c_struct_.ptr) 18 | memset(c_struct_.ptr, '\0', n * sizeof(char)); 19 | c_struct_.asize = n; 20 | c_struct_.size = 0; 21 | } 22 | 23 | data_buffer::data_buffer(const git_buf *c_ptr) { 24 | c_struct_.ptr = (char *)malloc(c_ptr->asize * sizeof(char)); 25 | c_struct_.asize = c_ptr->asize; 26 | c_struct_.size = c_ptr->size; 27 | if (c_struct_.ptr) 28 | strncpy(c_struct_.ptr, c_ptr->ptr, c_ptr->asize); 29 | } 30 | 31 | data_buffer::~data_buffer() { 32 | if (c_struct_.size) 33 | git_buf_dispose(&c_struct_); 34 | } 35 | 36 | bool data_buffer::contains_nul() const { 37 | return git_buf_contains_nul(&c_struct_); 38 | } 39 | 40 | void data_buffer::grow_to_size(size_t target_size) { 41 | if (git_buf_grow(&c_struct_, target_size)) 42 | throw git_exception(); 43 | } 44 | 45 | bool data_buffer::is_binary() const { return git_buf_is_binary(&c_struct_); } 46 | 47 | void data_buffer::set_buffer(const std::string &buffer) { 48 | if (git_buf_set(&c_struct_, buffer.c_str(), buffer.size())) 49 | throw git_exception(); 50 | } 51 | 52 | std::string data_buffer::to_string() const { 53 | if (c_struct_.size) 54 | return std::string(c_struct_.ptr); 55 | else 56 | return ""; 57 | } 58 | 59 | git_buf *data_buffer::c_ptr() { return &c_struct_; } 60 | 61 | const git_buf *data_buffer::c_ptr() const { return &c_struct_; } 62 | 63 | } // namespace cppgit2 64 | -------------------------------------------------------------------------------- /src/indexer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | indexer::indexer() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 5 | 6 | indexer::indexer(git_indexer *c_ptr, ownership owner) 7 | : c_ptr_(c_ptr), owner_(ownership::libgit2) {} 8 | 9 | indexer::indexer(const std::string &path, unsigned int mode, const odb &odb, 10 | const indexer::options &options) { 11 | if (git_indexer_new(&c_ptr_, path.c_str(), mode, odb.c_ptr_, options.c_ptr_)) 12 | throw git_exception(); 13 | } 14 | 15 | indexer::~indexer() { 16 | if (c_ptr_ && owner_ == ownership::user) 17 | git_indexer_free(c_ptr_); 18 | } 19 | 20 | void indexer::append(void *data, size_t size) { 21 | if (git_indexer_append(c_ptr_, data, size, 22 | const_cast(progress_.c_ptr_))) 23 | throw git_exception(); 24 | } 25 | 26 | void indexer::commit() { 27 | if (git_indexer_commit(c_ptr_, 28 | const_cast(progress_.c_ptr_))) 29 | throw git_exception(); 30 | } 31 | 32 | oid indexer::hash() { return oid(git_indexer_hash(c_ptr_)); } -------------------------------------------------------------------------------- /src/merge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | merge::file::result merge::merge_files(const merge::file::input &ancestor, 5 | const merge::file::input &ours, 6 | const merge::file::input &theirs, 7 | const merge::file::options &options) { 8 | git_merge_file_result result; 9 | if (git_merge_file(&result, ancestor.c_ptr(), ours.c_ptr(), theirs.c_ptr(), 10 | options.c_ptr())) 11 | throw git_exception(); 12 | return merge::file::result(&result); 13 | } -------------------------------------------------------------------------------- /src/note.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | note::note() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 6 | 7 | note::note(git_note *c_ptr, ownership owner) : c_ptr_(c_ptr), owner_(owner) {} 8 | 9 | note::~note() { 10 | if (c_ptr_ && owner_ == ownership::user) 11 | git_note_free(c_ptr_); 12 | } 13 | 14 | signature note::author() const { return signature(git_note_author(c_ptr_)); } 15 | 16 | signature note::committer() const { 17 | return signature(git_note_committer(c_ptr_)); 18 | } 19 | 20 | oid note::id() const { return oid(git_note_id(c_ptr_)); } 21 | 22 | std::string note::message() const { 23 | auto ret = git_note_message(c_ptr_); 24 | if (ret) 25 | return std::string(ret); 26 | else 27 | return ""; 28 | } 29 | 30 | const git_note *note::c_ptr() const { return c_ptr_; } 31 | 32 | } // namespace cppgit2 -------------------------------------------------------------------------------- /src/object.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace cppgit2 { 5 | 6 | object::object() : c_ptr_(nullptr), owner_(ownership::user) {} 7 | 8 | object::object(git_object *c_ptr, ownership owner) 9 | : c_ptr_(c_ptr), owner_(owner) {} 10 | 11 | object::~object() { 12 | if (c_ptr_ && owner_ == ownership::user) 13 | git_object_free(c_ptr_); 14 | } 15 | 16 | oid object::id() const { return oid(git_object_id(c_ptr_)->id); } 17 | 18 | std::string object::short_id() const { 19 | git_buf result; 20 | if (git_object_short_id(&result, c_ptr_)) 21 | throw git_exception(); 22 | return data_buffer(&result).to_string(); 23 | } 24 | 25 | object object::copy() const { 26 | object result(nullptr, ownership::user); 27 | if (git_object_dup(&result.c_ptr_, c_ptr_)) 28 | throw git_exception(); 29 | return result; 30 | } 31 | 32 | std::string object::object_type_to_string(object_type type) { 33 | auto ret = git_object_type2string(static_cast(type)); 34 | return ret ? std::string(ret) : ""; 35 | } 36 | 37 | object object::peel_until(object_type target_type) { 38 | object result(nullptr, ownership::user); 39 | if (git_object_peel(&result.c_ptr_, c_ptr_, 40 | static_cast(target_type))) 41 | throw git_exception(); 42 | return result; 43 | } 44 | 45 | object::object_type object::type() const { 46 | return static_cast(git_object_type(c_ptr_)); 47 | } 48 | 49 | std::string object::type_string() const { 50 | return object::string_from_type(this->type()); 51 | } 52 | 53 | object::object_type object::type_from_string(const std::string &type_string) { 54 | return static_cast(git_object_string2type(type_string.c_str())); 55 | } 56 | 57 | std::string object::string_from_type(object_type type) { 58 | return std::string(git_object_type2string(static_cast(type))); 59 | } 60 | 61 | bool object::is_type_loose(object_type type) { 62 | return git_object_typeisloose(static_cast(type)); 63 | } 64 | 65 | repository object::owner() const { 66 | return repository(git_object_owner(c_ptr_)); 67 | } 68 | 69 | blob object::as_blob() { 70 | if (type() == object::object_type::blob) 71 | return blob((git_blob *)c_ptr_); 72 | else 73 | throw git_exception("object is not a blob"); 74 | } 75 | 76 | commit object::as_commit() { 77 | if (type() == object::object_type::commit) 78 | return commit((git_commit *)c_ptr_); 79 | else 80 | throw git_exception("object is not a commit"); 81 | } 82 | 83 | tree object::as_tree() { 84 | if (type() == object::object_type::tree) 85 | return tree((git_tree *)c_ptr_); 86 | else 87 | throw git_exception("object is not a tree"); 88 | } 89 | 90 | tag object::as_tag() { 91 | if (type() == object::object_type::tag) 92 | return tag((git_tag *)c_ptr_); 93 | else 94 | throw git_exception("object is not a tag"); 95 | } 96 | 97 | } // namespace cppgit2 98 | -------------------------------------------------------------------------------- /src/oid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace cppgit2 { 5 | 6 | oid::oid() {} 7 | 8 | oid::oid(const std::string &hex_string) { 9 | if (git_oid_fromstr(&c_struct_, hex_string.c_str())) 10 | throw git_exception(); 11 | } 12 | 13 | oid::oid(const std::string &hex_string, size_t length) { 14 | if (git_oid_fromstrn(&c_struct_, hex_string.c_str(), length)) 15 | throw git_exception(); 16 | } 17 | 18 | oid::oid(const git_oid *c_ptr) { 19 | // Convert git_oid * to string and construct this oid 20 | size_t n = GIT_OID_HEXSZ; 21 | std::string buffer(n, '0'); 22 | if (!git_oid_tostr(const_cast(buffer.c_str()), n + 1, c_ptr)) 23 | throw git_exception(); 24 | // Construct from string 25 | if (git_oid_fromstr(&c_struct_, buffer.c_str())) 26 | throw git_exception(); 27 | } 28 | 29 | oid::oid(const unsigned char *raw) { git_oid_fromraw(&c_struct_, raw); } 30 | 31 | int oid::compare(const oid &rhs) const { 32 | return git_oid_cmp(&c_struct_, rhs.c_ptr()); 33 | } 34 | 35 | int oid::compare(const oid &rhs, size_t length) const { 36 | return git_oid_ncmp(&c_struct_, rhs.c_ptr(), length); 37 | } 38 | 39 | oid oid::copy() const { 40 | oid result; 41 | git_oid_cpy(&result.c_struct_, &c_struct_); 42 | return result; 43 | } 44 | 45 | bool oid::is_zero() const { return git_oid_iszero(&c_struct_); } 46 | 47 | bool oid::operator==(const oid &rhs) const { 48 | return git_oid_equal(&c_struct_, rhs.c_ptr()); 49 | } 50 | 51 | bool oid::operator==(const std::string &rhs) const { 52 | return git_oid_streq(&c_struct_, rhs.c_str()) ? false : true; 53 | } 54 | 55 | std::string oid::to_hex_string(size_t n) const { 56 | std::string result(n, '0'); 57 | if (!git_oid_tostr(const_cast(result.c_str()), n + 1, &c_struct_)) 58 | throw git_exception(); 59 | return result; 60 | } 61 | 62 | std::string oid::to_path_string() const { 63 | std::string result(GIT_OID_HEXSZ + 1, '0'); 64 | git_oid_pathfmt(const_cast(result.c_str()), &c_struct_); 65 | return result; 66 | } 67 | 68 | git_oid *oid::c_ptr() { return &c_struct_; } 69 | 70 | const git_oid *oid::c_ptr() const { return &c_struct_; } 71 | 72 | } // namespace cppgit2 73 | -------------------------------------------------------------------------------- /src/pack_builder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace cppgit2 { 5 | 6 | pack_builder::pack_builder() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 7 | 8 | pack_builder::pack_builder(git_packbuilder *c_ptr, ownership owner) 9 | : c_ptr_(c_ptr), owner_(owner) {} 10 | 11 | pack_builder::~pack_builder() { 12 | if (c_ptr_ && owner_ == ownership::user) 13 | git_packbuilder_free(c_ptr_); 14 | } 15 | 16 | void pack_builder::for_each_object( 17 | std::function visitor) { 18 | struct visitor_wrapper { 19 | std::function fn; 20 | }; 21 | 22 | visitor_wrapper wrapper; 23 | wrapper.fn = visitor; 24 | 25 | auto callback_c = [](void *buffer, size_t size, void *payload) { 26 | auto wrapper = reinterpret_cast(payload); 27 | wrapper->fn(buffer, size); 28 | return 0; 29 | }; 30 | 31 | if (git_packbuilder_foreach(c_ptr_, callback_c, (void *)(&wrapper))) 32 | throw git_exception(); 33 | } 34 | 35 | oid pack_builder::hash() { return oid(git_packbuilder_hash(c_ptr_)); } 36 | 37 | oid pack_builder::id() const { return oid(git_packbuilder_hash(c_ptr_)); } 38 | 39 | void pack_builder::insert_commit(const oid &commit_id) { 40 | if (git_packbuilder_insert_commit(c_ptr_, commit_id.c_ptr())) 41 | throw git_exception(); 42 | } 43 | 44 | void pack_builder::insert_object(const oid &commit_id, 45 | const std::string &name) { 46 | auto name_c = name.empty() ? nullptr : name.c_str(); 47 | if (git_packbuilder_insert(c_ptr_, commit_id.c_ptr(), name_c)) 48 | throw git_exception(); 49 | } 50 | 51 | void pack_builder::insert_object_recursively(const oid &commit_id, 52 | const std::string &name) { 53 | auto name_c = name.empty() ? nullptr : name.c_str(); 54 | if (git_packbuilder_insert_recur(c_ptr_, commit_id.c_ptr(), name_c)) 55 | throw git_exception(); 56 | } 57 | 58 | void pack_builder::insert_tree(const oid &tree_id) { 59 | if (git_packbuilder_insert_tree(c_ptr_, tree_id.c_ptr())) 60 | throw git_exception(); 61 | } 62 | 63 | void pack_builder::insert_revwalk(const revwalk &walk) { 64 | if (git_packbuilder_insert_walk(c_ptr_, walk.c_ptr_)) 65 | throw git_exception(); 66 | } 67 | 68 | size_t pack_builder::size() const { 69 | return git_packbuilder_object_count(c_ptr_); 70 | } 71 | 72 | void pack_builder::set_progress_callback( 73 | std::function callback) { 74 | // Wrap user provided visitor in a callback fn 75 | struct visitor_wrapper { 76 | std::function fn; 77 | }; 78 | 79 | visitor_wrapper wrapper; 80 | wrapper.fn = callback; 81 | 82 | // Prepare callback function to pass to git_packbuilder_set_callbacks(...) 83 | auto callback_c = [](int stage, uint32_t current, uint32_t total, 84 | void *payload) { 85 | auto wrapper = reinterpret_cast(payload); 86 | wrapper->fn(stage, current, total); 87 | return 0; 88 | }; 89 | 90 | if (git_packbuilder_set_callbacks(c_ptr_, callback_c, (void *)(&wrapper))) 91 | throw git_exception(); 92 | } 93 | 94 | void pack_builder::set_threads(unsigned int num_threads) { 95 | if (git_packbuilder_set_threads(c_ptr_, num_threads)) 96 | throw git_exception(); 97 | } 98 | 99 | void pack_builder::write( 100 | const std::string &path, unsigned int mode, 101 | std::function &progress_callback) { 102 | 103 | struct visitor_wrapper { 104 | std::function fn; 105 | }; 106 | 107 | visitor_wrapper wrapper; 108 | wrapper.fn = progress_callback; 109 | 110 | auto callback_c = [](const git_indexer_progress *stats, void *payload) { 111 | auto wrapper = reinterpret_cast(payload); 112 | wrapper->fn(indexer::progress(stats)); 113 | return 0; 114 | }; 115 | 116 | if (git_packbuilder_write(c_ptr_, path.c_str(), mode, callback_c, 117 | (void *)(&wrapper))) 118 | throw git_exception(); 119 | } 120 | 121 | data_buffer pack_builder::write_to_buffer() { 122 | data_buffer result; 123 | if (git_packbuilder_write_buf(result.c_ptr(), c_ptr_)) 124 | throw git_exception(); 125 | return result; 126 | } 127 | 128 | size_t pack_builder::written() const { return git_packbuilder_written(c_ptr_); } 129 | 130 | const git_packbuilder *pack_builder::c_ptr() const { return c_ptr_; } 131 | 132 | } // namespace cppgit2 -------------------------------------------------------------------------------- /src/patch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | #include 4 | 5 | patch::patch() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 6 | 7 | patch::patch(git_patch *c_ptr, ownership owner) 8 | : c_ptr_(c_ptr), owner_(owner) {} 9 | 10 | patch::patch(const blob &old_blob, const std::string &old_as_path, 11 | const void *buffer, size_t buffer_length, 12 | const std::string &buffer_as_path, const diff::options &options) { 13 | owner_ = ownership::user; 14 | if (git_patch_from_blob_and_buffer(&c_ptr_, old_blob.c_ptr(), 15 | old_as_path.c_str(), buffer, buffer_length, 16 | buffer_as_path.c_str(), options.c_ptr())) 17 | throw git_exception(); 18 | } 19 | 20 | patch::patch(const blob &old_blob, const std::string &old_as_path, 21 | const blob &new_blob, const std::string &new_as_path, 22 | const diff::options &options) { 23 | owner_ = ownership::user; 24 | if (git_patch_from_blobs(&c_ptr_, old_blob.c_ptr(), old_as_path.c_str(), 25 | new_blob.c_ptr(), new_as_path.c_str(), 26 | options.c_ptr())) 27 | throw git_exception(); 28 | } 29 | 30 | patch::patch(const void *old_buffer, size_t old_buffer_length, 31 | const std::string &old_as_path, const void *new_buffer, 32 | size_t new_buffer_length, const std::string &new_as_path, 33 | const diff::options &options) { 34 | owner_ = ownership::user; 35 | if (git_patch_from_buffers(&c_ptr_, old_buffer, old_buffer_length, 36 | old_as_path.c_str(), new_buffer, new_buffer_length, 37 | new_as_path.c_str(), options.c_ptr())) 38 | throw git_exception(); 39 | } 40 | 41 | patch::patch(const diff &diff, size_t index) { 42 | owner_ = ownership::user; 43 | if (git_patch_from_diff(&c_ptr_, diff.c_ptr_, index)) 44 | throw git_exception(); 45 | } 46 | 47 | patch::~patch() { 48 | if (c_ptr_ && owner_ == ownership::user) 49 | git_patch_free(c_ptr_); 50 | } 51 | 52 | diff::delta patch::delta() const { 53 | return diff::delta(git_patch_get_delta(c_ptr_)); 54 | } 55 | 56 | std::pair patch::hunk(size_t hunk_index) const { 57 | diff::hunk hunk_result(nullptr); 58 | auto hunk_result_ptr = hunk_result.c_ptr(); 59 | size_t lines_in_hunk; 60 | if (git_patch_get_hunk(&hunk_result_ptr, &lines_in_hunk, c_ptr_, hunk_index)) 61 | throw git_exception(); 62 | return std::pair{hunk_result, lines_in_hunk}; 63 | } 64 | 65 | diff::line patch::line_in_hunk(size_t hunk_index, size_t line_of_hunk) const { 66 | diff::line result(nullptr); 67 | auto result_ptr = result.c_ptr(); 68 | if (git_patch_get_line_in_hunk(&result_ptr, c_ptr_, hunk_index, line_of_hunk)) 69 | throw git_exception(); 70 | return result; 71 | } 72 | 73 | std::tuple patch::line_stats() const { 74 | size_t context_lines = 0, addition_lines = 0, deletion_lines = 0; 75 | if (git_patch_line_stats(&context_lines, &addition_lines, &deletion_lines, 76 | c_ptr_)) 77 | throw git_exception(); 78 | return std::tuple{context_lines, addition_lines, 79 | deletion_lines}; 80 | } 81 | 82 | size_t patch::num_hunks() const { return git_patch_num_hunks(c_ptr_); } 83 | 84 | size_t patch::num_lines_in_hunk(size_t hunk_index) const { 85 | return git_patch_num_lines_in_hunk(c_ptr_, hunk_index); 86 | } 87 | 88 | void patch::print(std::function 90 | line_callback) { 91 | 92 | // Prepare wrapper to pass to C API 93 | struct visitor_wrapper { 94 | std::function 96 | line_callback; 97 | }; 98 | 99 | visitor_wrapper wrapper; 100 | wrapper.line_callback = line_callback; 101 | 102 | auto line_callback_c = [](const git_diff_delta *delta_c, 103 | const git_diff_hunk *hunk_c, 104 | const git_diff_line *line_c, void *payload) { 105 | auto wrapper = reinterpret_cast(payload); 106 | if (wrapper->line_callback) 107 | wrapper->line_callback(diff::delta(delta_c), diff::hunk(hunk_c), 108 | diff::line(line_c)); 109 | return 0; 110 | }; 111 | 112 | if (git_patch_print(c_ptr_, line_callback_c, (void *)(&wrapper))) 113 | throw git_exception(); 114 | } 115 | 116 | size_t patch::size(bool include_context, bool include_hunk_headers, 117 | bool include_file_headers) const { 118 | return git_patch_size(c_ptr_, include_context, include_hunk_headers, 119 | include_file_headers); 120 | } 121 | 122 | data_buffer patch::to_buffer() { 123 | data_buffer result; 124 | if (git_patch_to_buf(result.c_ptr(), c_ptr_)) 125 | throw git_exception(); 126 | return result; 127 | } 128 | 129 | const git_patch *patch::c_ptr() const { return c_ptr_; } -------------------------------------------------------------------------------- /src/pathspec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | pathspec::pathspec() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 5 | 6 | pathspec::pathspec(git_pathspec *c_ptr, ownership owner) 7 | : c_ptr_(c_ptr), owner_(owner) {} 8 | 9 | pathspec::~pathspec() { 10 | if (c_ptr_ && owner_ == ownership::user) 11 | git_pathspec_free(c_ptr_); 12 | } 13 | 14 | pathspec pathspec::compile(const strarray &paths) { 15 | pathspec result(nullptr, ownership::user); 16 | if (git_pathspec_new(&result.c_ptr_, paths.c_ptr())) 17 | throw git_exception(); 18 | return result; 19 | } 20 | 21 | pathspec::match_list pathspec::match_diff(const diff &diff, 22 | pathspec::flag flags) { 23 | git_pathspec_match_list **result_c = 24 | (git_pathspec_match_list **)malloc(sizeof(git_pathspec_match_list *)); 25 | if (git_pathspec_match_diff(result_c, diff.c_ptr_, 26 | static_cast(flags), c_ptr_)) 27 | throw git_exception(); 28 | return pathspec::match_list(*result_c); 29 | } 30 | 31 | pathspec::match_list pathspec::match_index(const index &index, 32 | pathspec::flag flags) { 33 | git_pathspec_match_list **result_c = 34 | (git_pathspec_match_list **)malloc(sizeof(git_pathspec_match_list *)); 35 | if (git_pathspec_match_index(result_c, index.c_ptr_, 36 | static_cast(flags), c_ptr_)) 37 | throw git_exception(); 38 | return pathspec::match_list(*result_c); 39 | } 40 | 41 | pathspec::match_list pathspec::match_tree(const tree &tree, 42 | pathspec::flag flags) { 43 | git_pathspec_match_list **result_c = 44 | (git_pathspec_match_list **)malloc(sizeof(git_pathspec_match_list *)); 45 | if (git_pathspec_match_tree(result_c, tree.c_ptr_, 46 | static_cast(flags), c_ptr_)) 47 | throw git_exception(); 48 | return pathspec::match_list(*result_c); 49 | } 50 | 51 | pathspec::match_list pathspec::match_workdir(const repository &repo, 52 | pathspec::flag flags) { 53 | git_pathspec_match_list **result_c = 54 | (git_pathspec_match_list **)malloc(sizeof(git_pathspec_match_list *)); 55 | if (git_pathspec_match_workdir(result_c, repo.c_ptr_, 56 | static_cast(flags), c_ptr_)) 57 | throw git_exception(); 58 | return pathspec::match_list(*result_c); 59 | } 60 | 61 | bool pathspec::matches_path(pathspec::flag flags, 62 | const std::string &path) const { 63 | return git_pathspec_matches_path(c_ptr_, static_cast(flags), 64 | path.c_str()); 65 | } 66 | 67 | const git_pathspec *pathspec::c_ptr() const { return c_ptr_; } -------------------------------------------------------------------------------- /src/rebase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | rebase::rebase() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 5 | 6 | rebase::rebase(git_rebase *c_ptr, ownership owner) 7 | : c_ptr_(c_ptr), owner_(owner) {} 8 | 9 | rebase::~rebase() { 10 | if (c_ptr_ && owner_ == ownership::user) 11 | git_rebase_free(c_ptr_); 12 | } 13 | 14 | void rebase::abort() { 15 | if (git_rebase_abort(c_ptr_)) 16 | throw git_exception(); 17 | } 18 | 19 | oid rebase::commit(const signature &author, const signature &committer, 20 | const std::string &message_encoding, 21 | const std::string &message) { 22 | oid result; 23 | if (git_rebase_commit(result.c_ptr(), c_ptr_, author.c_ptr(), 24 | committer.c_ptr(), message_encoding.c_str(), 25 | message.c_str())) 26 | throw git_exception(); 27 | return result; 28 | } 29 | 30 | void rebase::finish(const signature &sig) { 31 | if (git_rebase_finish(c_ptr_, sig.c_ptr())) 32 | throw git_exception(); 33 | } 34 | 35 | cppgit2::index rebase::index() { 36 | cppgit2::index result(nullptr, ownership::user); 37 | if (git_rebase_inmemory_index(&result.c_ptr_, c_ptr_)) 38 | throw git_exception(); 39 | return result; 40 | } 41 | 42 | rebase::operation rebase::next() { 43 | operation result; 44 | if (git_rebase_next(&result.c_ptr_, c_ptr_)) 45 | throw git_exception(); 46 | return result; 47 | } 48 | 49 | oid rebase::onto_id() { return oid(git_rebase_onto_id(c_ptr_)); } 50 | 51 | std::string rebase::onto_refname() { 52 | auto ret = git_rebase_onto_name(c_ptr_); 53 | return ret ? std::string(ret) : ""; 54 | } 55 | 56 | rebase::operation rebase::operator[](size_t index) { 57 | return operation(git_rebase_operation_byindex(c_ptr_, index)); 58 | } 59 | 60 | size_t rebase::current_operation() { 61 | return git_rebase_operation_current(c_ptr_); 62 | } 63 | 64 | size_t rebase::size() { return git_rebase_operation_entrycount(c_ptr_); } 65 | 66 | oid rebase::original_head_id() { return oid(git_rebase_orig_head_id(c_ptr_)); } 67 | 68 | std::string rebase::original_head_name() { 69 | auto ret = git_rebase_orig_head_name(c_ptr_); 70 | return ret ? std::string(ret) : ""; 71 | } -------------------------------------------------------------------------------- /src/reference.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | reference::reference() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 6 | 7 | reference::reference(git_reference *c_ptr, ownership owner) 8 | : c_ptr_(c_ptr), owner_(owner) {} 9 | 10 | reference::~reference() { 11 | if (c_ptr_ && owner_ == ownership::user) 12 | git_reference_free(c_ptr_); 13 | } 14 | 15 | int reference::compare(const reference &rhs) const { 16 | return git_reference_cmp(c_ptr_, rhs.c_ptr()); 17 | } 18 | 19 | reference reference::copy() const { 20 | reference result(nullptr, ownership::user); 21 | if (git_reference_dup(&result.c_ptr_, c_ptr_)) 22 | throw git_exception(); 23 | return result; 24 | } 25 | 26 | void reference::delete_reference(reference &ref) { 27 | if (git_reference_delete(ref.c_ptr_)) 28 | throw git_exception(); 29 | } 30 | 31 | bool reference::is_branch() const { return git_reference_is_branch(c_ptr_); } 32 | 33 | bool reference::is_note() const { return git_reference_is_note(c_ptr_); } 34 | 35 | bool reference::is_remote() const { return git_reference_is_remote(c_ptr_); } 36 | 37 | bool reference::is_tag() const { return git_reference_is_tag(c_ptr_); } 38 | 39 | bool reference::is_valid_name(const std::string &refname) { 40 | return git_reference_is_valid_name(refname.c_str()); 41 | } 42 | 43 | std::string reference::name() const { 44 | auto ret = git_reference_name(c_ptr_); 45 | if (ret) 46 | return std::string(ret); 47 | else 48 | return ""; 49 | } 50 | 51 | std::string reference::normalize_name(size_t length, const std::string &name, 52 | reference::format flags) { 53 | char *buffer = (char *)malloc(length * sizeof(char)); 54 | if (git_reference_normalize_name(buffer, length, name.c_str(), 55 | static_cast(flags))) 56 | throw git_exception(); 57 | std::string result{""}; 58 | if (buffer) 59 | result = std::string(buffer); 60 | free(buffer); 61 | return result; 62 | } 63 | 64 | std::string reference::shorthand_name() const { 65 | auto ret = git_reference_shorthand(c_ptr_); 66 | if (ret) 67 | return std::string(ret); 68 | else 69 | return ""; 70 | } 71 | 72 | repository reference::owner() const { 73 | return repository(git_reference_owner(c_ptr_)); 74 | } 75 | 76 | object reference::peel_until(object::object_type type) { 77 | object result(nullptr, ownership::user); 78 | if (git_reference_peel(&result.c_ptr_, c_ptr_, 79 | static_cast(type))) 80 | throw git_exception(); 81 | return result; 82 | } 83 | 84 | reference reference::rename(const std::string &new_name, bool force, 85 | const std::string &log_message) { 86 | reference result(nullptr, ownership::user); 87 | if (git_reference_rename(&result.c_ptr_, c_ptr_, new_name.c_str(), force, 88 | log_message.c_str())) 89 | throw git_exception(); 90 | return result; 91 | } 92 | 93 | reference reference::resolve() { 94 | reference result(nullptr, ownership::user); 95 | if (git_reference_resolve(&result.c_ptr_, c_ptr_)) 96 | throw git_exception(); 97 | return result; 98 | } 99 | 100 | reference reference::set_target(const oid &id, const std::string &log_message) { 101 | reference result(nullptr, ownership::user); 102 | if (git_reference_set_target(&result.c_ptr_, c_ptr_, id.c_ptr(), 103 | log_message.c_str())) 104 | throw git_exception(); 105 | return result; 106 | } 107 | 108 | reference reference::set_symbolic_target(const std::string &target, 109 | const std::string &log_message) { 110 | reference result(nullptr, ownership::user); 111 | if (git_reference_symbolic_set_target(&result.c_ptr_, c_ptr_, target.c_str(), 112 | log_message.c_str())) 113 | throw git_exception(); 114 | return result; 115 | } 116 | 117 | oid reference::target() const { return oid(git_reference_target(c_ptr_)); } 118 | 119 | std::string reference::symbolic_target() const { 120 | auto ret = git_reference_symbolic_target(c_ptr_); 121 | if (ret) 122 | return std::string(ret); 123 | else 124 | return ""; 125 | } 126 | 127 | oid reference::peeled_target() const { 128 | return oid(git_reference_target_peel(c_ptr_)); 129 | } 130 | 131 | reference::reference_type reference::type() const { 132 | return static_cast(git_reference_type(c_ptr_)); 133 | } 134 | 135 | const git_reference *reference::c_ptr() const { return c_ptr_; } 136 | 137 | } // namespace cppgit2 -------------------------------------------------------------------------------- /src/reflog.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | reflog::reflog() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 6 | 7 | reflog::reflog(git_reflog *c_ptr, ownership owner) 8 | : c_ptr_(c_ptr), owner_(owner) {} 9 | 10 | reflog::~reflog() { 11 | if (c_ptr_ && owner_ == ownership::user) 12 | git_reflog_free(c_ptr_); 13 | } 14 | 15 | void reflog::remove(size_t index, bool rewrite_previous_entry) { 16 | if (git_reflog_drop(c_ptr_, index, rewrite_previous_entry)) 17 | throw git_exception(); 18 | } 19 | 20 | void reflog::append(const oid &id, const signature &committer, 21 | const std::string &message) { 22 | if (git_reflog_append(c_ptr_, id.c_ptr(), committer.c_ptr(), message.c_str())) 23 | throw git_exception(); 24 | } 25 | 26 | reflog::entry reflog::operator[](size_t index) const { 27 | return reflog::entry(git_reflog_entry_byindex(c_ptr_, index)); 28 | } 29 | 30 | void reflog::write_to_disk() { 31 | if (git_reflog_write(c_ptr_)) 32 | throw git_exception(); 33 | } 34 | 35 | size_t reflog::size() const { return git_reflog_entrycount(c_ptr_); } 36 | 37 | const git_reflog *reflog::c_ptr() const { return c_ptr_; } 38 | 39 | } // namespace cppgit2 40 | -------------------------------------------------------------------------------- /src/refspec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | 4 | refspec::refspec() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 5 | 6 | refspec::refspec(git_refspec *c_ptr, ownership owner) 7 | : c_ptr_(c_ptr), owner_(owner) {} 8 | 9 | refspec::~refspec() { 10 | if (c_ptr_ && owner_ == ownership::user) 11 | git_refspec_free(c_ptr_); 12 | } 13 | 14 | connection_direction refspec::direction() const { 15 | return static_cast(git_refspec_direction(c_ptr_)); 16 | } 17 | 18 | std::string refspec::destination() const { 19 | auto ret = git_refspec_dst(c_ptr_); 20 | return ret ? std::string(ret) : ""; 21 | } 22 | 23 | bool refspec::destination_matches_reference(const std::string &refname) const { 24 | return git_refspec_dst_matches(c_ptr_, refname.c_str()); 25 | } 26 | 27 | bool refspec::is_force_update_enabled() const { 28 | return git_refspec_force(c_ptr_); 29 | } 30 | 31 | refspec refspec::parse(const std::string &input, bool is_fetch) { 32 | refspec result(nullptr, ownership::user); 33 | if (git_refspec_parse(&result.c_ptr_, input.c_str(), is_fetch)) 34 | throw git_exception(); 35 | return result; 36 | } 37 | 38 | data_buffer 39 | refspec::transform_target_to_source_reference(const std::string &name) { 40 | data_buffer result; 41 | if (git_refspec_rtransform(result.c_ptr(), c_ptr_, name.c_str())) 42 | throw git_exception(); 43 | return result; 44 | } 45 | 46 | std::string refspec::source() const { 47 | auto ret = git_refspec_src(c_ptr_); 48 | return ret ? std::string(ret) : ""; 49 | } 50 | 51 | bool refspec::source_matches_reference(const std::string &refname) const { 52 | return git_refspec_src_matches(c_ptr_, refname.c_str()); 53 | } 54 | 55 | std::string refspec::to_string() const { 56 | auto ret = git_refspec_string(c_ptr_); 57 | return ret ? std::string(ret) : ""; 58 | } 59 | 60 | data_buffer refspec::transform_reference(const std::string &name) { 61 | data_buffer result; 62 | if (git_refspec_transform(result.c_ptr(), c_ptr_, name.c_str())) 63 | throw git_exception(); 64 | return result; 65 | } 66 | 67 | const git_refspec *refspec::c_ptr() const { return c_ptr_; } -------------------------------------------------------------------------------- /src/revwalk.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cppgit2; 3 | #include 4 | 5 | revwalk::revwalk() 6 | : done_(false), c_ptr_(nullptr), owner_(ownership::libgit2) {} 7 | 8 | // Construct from libgit2 C ptr 9 | revwalk::revwalk(git_revwalk *c_ptr, ownership owner) 10 | : done_(false), c_ptr_(c_ptr), owner_(owner) {} 11 | 12 | // Cleanup revwalk 13 | revwalk::~revwalk() { 14 | if (c_ptr_ && owner_ == ownership::user) 15 | git_revwalk_free(c_ptr_); 16 | } 17 | 18 | void revwalk::add_hide_callback(std::function callback) { 19 | struct visitor_wrapper { 20 | std::function fn; 21 | }; 22 | 23 | visitor_wrapper wrapper; 24 | wrapper.fn = callback; 25 | 26 | auto callback_c = [](const git_oid *commit_id, void *payload) { 27 | auto wrapper = reinterpret_cast(payload); 28 | return wrapper->fn(oid(commit_id)); 29 | }; 30 | 31 | if (git_revwalk_add_hide_cb(c_ptr_, callback_c, (void *)(&wrapper))) 32 | throw git_exception(); 33 | } 34 | 35 | bool revwalk::done() const { return done_; } 36 | 37 | void revwalk::hide(const oid &commit_id) { 38 | if (git_revwalk_hide(c_ptr_, commit_id.c_ptr())) 39 | throw git_exception(); 40 | } 41 | 42 | void revwalk::hide_glob(const std::string &glob) { 43 | if (git_revwalk_hide_glob(c_ptr_, glob.c_str())) 44 | throw git_exception(); 45 | } 46 | 47 | void revwalk::hide_head() { 48 | if (git_revwalk_hide_head(c_ptr_)) 49 | throw git_exception(); 50 | } 51 | 52 | void revwalk::hide_reference(const std::string &ref) { 53 | if (git_revwalk_hide_ref(c_ptr_, ref.c_str())) 54 | throw git_exception(); 55 | } 56 | 57 | oid revwalk::next() { 58 | oid result; 59 | if (git_revwalk_next(result.c_ptr(), c_ptr_) == GIT_ITEROVER) 60 | done_ = true; 61 | return result; 62 | } 63 | 64 | void revwalk::push(const oid &id) { 65 | if (git_revwalk_push(c_ptr_, id.c_ptr())) 66 | throw git_exception(); 67 | } 68 | 69 | void revwalk::push_glob(const std::string &glob) { 70 | if (git_revwalk_push_glob(c_ptr_, glob.c_str())) 71 | throw git_exception(); 72 | } 73 | 74 | void revwalk::push_head() { 75 | if (git_revwalk_push_head(c_ptr_)) 76 | throw git_exception(); 77 | } 78 | 79 | void revwalk::push_range(const std::string &range) { 80 | if (git_revwalk_push_range(c_ptr_, range.c_str())) 81 | throw git_exception(); 82 | } 83 | 84 | void revwalk::push_reference(const std::string &ref) { 85 | if (git_revwalk_push_ref(c_ptr_, ref.c_str())) 86 | throw git_exception(); 87 | } 88 | 89 | cppgit2::repository revwalk::repository() { 90 | return cppgit2::repository(git_revwalk_repository(c_ptr_)); 91 | } 92 | 93 | void revwalk::reset() { 94 | done_ = false; 95 | if (git_revwalk_reset(c_ptr_)) 96 | throw git_exception(); 97 | } 98 | 99 | void revwalk::set_sorting_mode(revwalk::sort sorting_mode) { 100 | if (git_revwalk_sorting(c_ptr_, static_cast(sorting_mode))) 101 | throw git_exception(); 102 | } 103 | 104 | void revwalk::simplify_first_parent() { 105 | if (git_revwalk_simplify_first_parent(c_ptr_)) 106 | throw git_exception(); 107 | } 108 | 109 | const git_revwalk *revwalk::c_ptr() const { return c_ptr_; } -------------------------------------------------------------------------------- /src/signature.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | signature::signature() { 6 | default_.name = const_cast(default_name_.c_str()); 7 | default_.email = const_cast(default_email_.c_str()); 8 | default_.when.time = 0; 9 | default_.when.offset = 0; 10 | c_ptr_ = &default_; 11 | } 12 | 13 | signature::signature(const std::string &name, const std::string &email) { 14 | if (git_signature_now(&c_ptr_, name.c_str(), email.c_str())) 15 | throw git_exception(); 16 | } 17 | 18 | signature::signature(const std::string &name, const std::string &email, 19 | epoch_time_seconds time, int offset_minutes) { 20 | if (git_signature_new(&c_ptr_, name.c_str(), email.c_str(), time, 21 | offset_minutes)) 22 | throw git_exception(); 23 | } 24 | 25 | signature::signature(const std::string &buffer) { 26 | if (git_signature_from_buffer(&c_ptr_, buffer.c_str())) 27 | throw git_exception(); 28 | } 29 | 30 | signature::signature(const git_signature *c_ptr) { 31 | if (git_signature_dup(&c_ptr_, c_ptr)) 32 | throw git_exception(); 33 | } 34 | 35 | signature signature::copy() const { 36 | signature result; 37 | if (git_signature_dup(&result.c_ptr_, c_ptr_)) 38 | throw git_exception(); 39 | return result; 40 | } 41 | 42 | std::string signature::name() const { 43 | if (c_ptr_) 44 | return c_ptr_->name ? c_ptr_->name : ""; 45 | else 46 | throw git_exception("signature is null"); 47 | } 48 | 49 | std::string signature::email() const { 50 | if (c_ptr_) 51 | return c_ptr_->email ? c_ptr_->email : ""; 52 | else 53 | throw git_exception("signature is null"); 54 | } 55 | 56 | epoch_time_seconds signature::time() const { 57 | if (c_ptr_) 58 | return c_ptr_->when.time; 59 | else 60 | throw git_exception("signature is null"); 61 | } 62 | 63 | offset_minutes signature::offset() const { 64 | if (c_ptr_) 65 | return c_ptr_->when.offset; 66 | else 67 | throw git_exception("signature is null"); 68 | } 69 | 70 | const git_signature *signature::c_ptr() const { return c_ptr_; } 71 | 72 | } // namespace cppgit2 73 | -------------------------------------------------------------------------------- /src/strarray.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace cppgit2 { 6 | 7 | strarray::strarray() { 8 | c_struct_.count = 0; 9 | c_struct_.strings = nullptr; 10 | } 11 | 12 | strarray::strarray(const std::vector &strings) { 13 | auto size = strings.size(); 14 | c_struct_.count = size; 15 | c_struct_.strings = (char **)malloc(size * sizeof(char *)); 16 | for (size_t i = 0; i < size; ++i) { 17 | auto length = strings[i].size() + 1; 18 | c_struct_.strings[i] = (char *)malloc(length * sizeof(char)); 19 | strncpy(c_struct_.strings[i], strings[i].c_str(), length); 20 | c_struct_.strings[i][length] = '\0'; 21 | } 22 | } 23 | 24 | strarray::strarray(const git_strarray *c_ptr) { 25 | c_struct_.count = c_ptr->count; 26 | c_struct_.strings = (char **)malloc(c_ptr->count * sizeof(char *)); 27 | for (size_t i = 0; i < c_ptr->count; ++i) { 28 | auto length = strlen(c_ptr->strings[i]) + 1; 29 | c_struct_.strings[i] = (char *)malloc(length * sizeof(char)); 30 | strncpy(c_struct_.strings[i], c_ptr->strings[i], length); 31 | c_struct_.strings[i][length] = '\0'; 32 | } 33 | } 34 | 35 | strarray::~strarray() { 36 | if (c_struct_.count) 37 | git_strarray_free(&c_struct_); 38 | } 39 | 40 | strarray strarray::copy() const { 41 | strarray result; 42 | if (git_strarray_copy(&result.c_struct_, &c_struct_)) 43 | throw git_exception(); 44 | return result; 45 | } 46 | 47 | std::vector strarray::to_vector() const { 48 | std::vector result{}; 49 | for (auto tag : *this) 50 | result.push_back(tag); 51 | return result; 52 | } 53 | 54 | const git_strarray *strarray::c_ptr() const { return &c_struct_; } 55 | 56 | } // namespace cppgit2 57 | -------------------------------------------------------------------------------- /src/submodule.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | submodule::submodule() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 6 | 7 | submodule::submodule(git_submodule *c_ptr, ownership owner) 8 | : c_ptr_(c_ptr), owner_(owner) {} 9 | 10 | submodule::~submodule() { 11 | if (c_ptr_ && owner_ == ownership::user) 12 | git_submodule_free(c_ptr_); 13 | } 14 | 15 | void submodule::init(bool overwrite) { 16 | if (git_submodule_init(c_ptr_, overwrite)) 17 | throw git_exception(); 18 | } 19 | 20 | void submodule::resolve_setup() { 21 | if (git_submodule_add_finalize(c_ptr_)) 22 | throw git_exception(); 23 | } 24 | 25 | void submodule::add_to_index(bool write_index) { 26 | if (git_submodule_add_to_index(c_ptr_, write_index)) 27 | throw git_exception(); 28 | } 29 | 30 | std::string submodule::branch_name() const { 31 | auto ret = git_submodule_branch(c_ptr_); 32 | if (ret) 33 | return std::string(ret); 34 | else 35 | return ""; 36 | } 37 | 38 | submodule::recurse submodule::recurse_submodules_option() const { 39 | return static_cast( 40 | git_submodule_fetch_recurse_submodules(c_ptr_)); 41 | } 42 | 43 | oid submodule::head_id() const { return oid(git_submodule_head_id(c_ptr_)); } 44 | 45 | submodule::ignore submodule::ignore_option() const { 46 | return static_cast(git_submodule_ignore(c_ptr_)); 47 | } 48 | 49 | repository submodule::initialize_repository(bool use_gitlink) { 50 | repository result; 51 | if (git_submodule_repo_init(&result.c_ptr_, c_ptr_, use_gitlink)) 52 | throw git_exception(); 53 | return result; 54 | } 55 | 56 | submodule::update_strategy submodule::get_update_strategy() const { 57 | return static_cast( 58 | git_submodule_update_strategy(c_ptr_)); 59 | } 60 | 61 | oid submodule::index_id() const { return oid(git_submodule_index_id(c_ptr_)); } 62 | 63 | std::string submodule::name() const { 64 | auto ret = git_submodule_name(c_ptr_); 65 | if (ret) 66 | return std::string(ret); 67 | else 68 | return ""; 69 | } 70 | 71 | std::string submodule::path() const { 72 | auto ret = git_submodule_path(c_ptr_); 73 | if (ret) 74 | return std::string(ret); 75 | else 76 | return ""; 77 | } 78 | 79 | void submodule::reload(bool force) { 80 | if (git_submodule_reload(c_ptr_, force)) 81 | throw git_exception(); 82 | } 83 | 84 | cppgit2::repository submodule::open_repository() { 85 | cppgit2::repository result; 86 | if (git_submodule_open(&result.c_ptr_, c_ptr_)) 87 | throw git_exception(); 88 | return result; 89 | } 90 | 91 | cppgit2::repository submodule::owner() { 92 | return repository(git_submodule_owner(c_ptr_)); 93 | } 94 | 95 | void submodule::sync() { 96 | if (git_submodule_sync(c_ptr_)) 97 | throw git_exception(); 98 | } 99 | 100 | std::string submodule::url() const { 101 | auto ret = git_submodule_url(c_ptr_); 102 | if (ret) 103 | return std::string(ret); 104 | else 105 | return ""; 106 | } 107 | 108 | submodule::status submodule::location_status() const { 109 | unsigned int result; 110 | if (git_submodule_location(&result, c_ptr_)) 111 | throw git_exception(); 112 | return static_cast(result); 113 | } 114 | 115 | repository submodule::clone(const update_options &options) { 116 | repository result; 117 | if (git_submodule_clone(&result.c_ptr_, c_ptr_, options.c_ptr_)) 118 | throw git_exception(); 119 | return result; 120 | } 121 | 122 | void submodule::update(bool init, const update_options &options) { 123 | if (git_submodule_update(c_ptr_, init, options.c_ptr_)) 124 | throw git_exception(); 125 | } 126 | 127 | const git_submodule *submodule::c_ptr() const { return c_ptr_; } 128 | 129 | } // namespace cppgit2 -------------------------------------------------------------------------------- /src/tag.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | tag::tag() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 5 | 6 | tag::tag(git_tag *c_ptr, ownership owner) : c_ptr_(c_ptr), owner_(owner) {} 7 | 8 | tag::~tag() { 9 | if (c_ptr_ && owner_ == ownership::user) 10 | git_tag_free(c_ptr_); 11 | } 12 | 13 | tag tag::copy() const { 14 | tag result(nullptr, ownership::user); 15 | if (git_tag_dup(&result.c_ptr_, c_ptr_)) 16 | throw git_exception(); 17 | return result; 18 | } 19 | 20 | oid tag::id() const { return oid(git_tag_id(c_ptr_)); } 21 | 22 | std::string tag::message() const { 23 | auto ret = git_tag_message(c_ptr_); 24 | if (ret) 25 | return std::string(ret); 26 | else 27 | return ""; 28 | } 29 | 30 | std::string tag::name() const { 31 | auto ret = git_tag_name(c_ptr_); 32 | if (ret) 33 | return std::string(ret); 34 | else 35 | return ""; 36 | } 37 | 38 | object tag::peel() const { 39 | object result(nullptr, ownership::user); 40 | if (git_tag_peel(&result.c_ptr_, c_ptr_)) 41 | throw git_exception(); 42 | return result; 43 | } 44 | 45 | signature tag::tagger() const { return signature(git_tag_tagger(c_ptr_)); } 46 | 47 | object tag::target() const { 48 | object result(nullptr, ownership::user); 49 | if (git_tag_target(&result.c_ptr_, c_ptr_)) 50 | throw git_exception(); 51 | return result; 52 | } 53 | 54 | oid tag::target_id() const { return oid(git_tag_target_id(c_ptr_)); } 55 | 56 | object::object_type tag::target_type() const { 57 | return static_cast(git_tag_target_type(c_ptr_)); 58 | } 59 | 60 | repository tag::owner() const { return repository(git_tag_owner(c_ptr_)); } 61 | 62 | git_tag *tag::c_ptr() { return c_ptr_; } 63 | 64 | const git_tag *tag::c_ptr() const { return c_ptr_; } 65 | 66 | } // namespace cppgit2 67 | -------------------------------------------------------------------------------- /src/transaction.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | transaction::transaction() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 6 | 7 | transaction::transaction(git_transaction *c_ptr, ownership owner) 8 | : c_ptr_(c_ptr), owner_(owner) {} 9 | 10 | transaction::~transaction() { 11 | if (c_ptr_ && owner_ == ownership::user) 12 | git_transaction_free(c_ptr_); 13 | } 14 | 15 | void transaction::commit() { 16 | if (git_transaction_commit(c_ptr_)) 17 | throw git_exception(); 18 | } 19 | 20 | void transaction::lock_reference(const std::string &refname) { 21 | if (git_transaction_lock_ref(c_ptr_, refname.c_str())) 22 | throw git_exception(); 23 | } 24 | 25 | void transaction::remove_reference(const std::string &refname) { 26 | if (git_transaction_remove(c_ptr_, refname.c_str())) 27 | throw git_exception(); 28 | } 29 | 30 | void transaction::set_reflog(const std::string &refname, const reflog &reflog) { 31 | if (git_transaction_set_reflog(c_ptr_, refname.c_str(), reflog.c_ptr())) 32 | throw git_exception(); 33 | } 34 | 35 | void transaction::set_symbolic_target(const std::string &refname, 36 | const std::string &target, 37 | const signature &signature, 38 | const std::string &message) { 39 | if (git_transaction_set_symbolic_target(c_ptr_, refname.c_str(), 40 | target.c_str(), signature.c_ptr(), 41 | message.c_str())) 42 | throw git_exception(); 43 | } 44 | 45 | void transaction::set_target(const std::string &refname, const oid &target, 46 | const signature &signature, 47 | const std::string &message) { 48 | if (git_transaction_set_target(c_ptr_, refname.c_str(), target.c_ptr(), 49 | signature.c_ptr(), message.c_str())) 50 | throw git_exception(); 51 | } 52 | 53 | git_transaction *transaction::c_ptr() { return c_ptr_; } 54 | 55 | const git_transaction *transaction::c_ptr() const { return c_ptr_; } 56 | 57 | } // namespace cppgit2 58 | -------------------------------------------------------------------------------- /src/tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace cppgit2 { 5 | 6 | tree::tree() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 7 | 8 | tree::tree(git_tree *c_ptr, ownership owner) : c_ptr_(c_ptr), owner_(owner) {} 9 | 10 | tree::~tree() { 11 | if (c_ptr_ && owner_ == ownership::user) 12 | git_tree_free(c_ptr_); 13 | } 14 | 15 | tree::entry tree::lookup_entry_by_id(const oid &id) const { 16 | return tree::entry( 17 | const_cast(git_tree_entry_byid(c_ptr_, id.c_ptr()))); 18 | } 19 | 20 | tree::entry tree::lookup_entry_by_index(size_t index) const { 21 | return tree::entry( 22 | const_cast(git_tree_entry_byindex(c_ptr_, index))); 23 | } 24 | 25 | tree::entry tree::lookup_entry_by_name(const std::string &filename) const { 26 | return tree::entry(const_cast( 27 | git_tree_entry_byname(c_ptr_, filename.c_str()))); 28 | } 29 | 30 | tree::entry tree::lookup_entry_by_path(const std::string &path) const { 31 | tree::entry result(nullptr, ownership::user); 32 | result.owner_ = ownership::user; 33 | if (git_tree_entry_bypath(&result.c_ptr_, c_ptr_, path.c_str())) 34 | throw git_exception(); 35 | return result; 36 | } 37 | 38 | oid tree::id() const { return oid(git_tree_id(c_ptr_)); } 39 | 40 | tree tree::copy() const { 41 | tree result(nullptr, ownership::user); 42 | if (git_tree_dup(&result.c_ptr_, c_ptr_)) 43 | throw git_exception(); 44 | return result; 45 | } 46 | 47 | size_t tree::size() const { return git_tree_entrycount(c_ptr_); } 48 | 49 | repository tree::owner() const { return repository(git_tree_owner(c_ptr_)); } 50 | 51 | void tree::walk(traversal_mode mode, 52 | std::function 53 | visitor) const { 54 | struct visitor_wrapper { 55 | std::function fn; 56 | }; 57 | 58 | visitor_wrapper wrapper; 59 | wrapper.fn = visitor; 60 | 61 | auto callback_c = [](const char *root, const git_tree_entry *entry, 62 | void *payload) { 63 | auto wrapper = reinterpret_cast(payload); 64 | wrapper->fn(root ? std::string(root) : "", tree::entry(entry)); 65 | return 0; 66 | }; 67 | 68 | if (git_tree_walk(c_ptr_, static_cast(mode), callback_c, 69 | (void *)(&wrapper))) 70 | throw git_exception(); 71 | } 72 | 73 | git_tree *tree::c_ptr() { return c_ptr_; } 74 | 75 | const git_tree *tree::c_ptr() const { return c_ptr_; } 76 | 77 | } // namespace cppgit2 78 | -------------------------------------------------------------------------------- /src/tree_builder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace cppgit2 { 5 | 6 | tree_builder::tree_builder(repository &repo, tree source) { 7 | if (git_treebuilder_new(&c_ptr_, repo.c_ptr_, source.c_ptr())) 8 | throw git_exception(); 9 | } 10 | 11 | tree_builder::~tree_builder() { 12 | if (c_ptr_) 13 | git_treebuilder_free(c_ptr_); 14 | } 15 | 16 | void tree_builder::clear() { git_treebuilder_clear(c_ptr_); } 17 | 18 | void tree_builder::filter(std::function visitor) { 19 | // Wrap user-provided visitor funciton in a struct 20 | struct visitor_wrapper { 21 | std::function fn; 22 | }; 23 | 24 | visitor_wrapper wrapper; 25 | wrapper.fn = visitor; 26 | 27 | auto visitor_c = [](const git_tree_entry *entry, void *payload) { 28 | auto wrapped = reinterpret_cast(payload); 29 | const tree::entry entry_arg = tree::entry(entry); 30 | return wrapped->fn(entry_arg); 31 | }; 32 | 33 | git_treebuilder_filter(c_ptr_, visitor_c, (void *)(&wrapper)); 34 | } 35 | 36 | size_t tree_builder::size() const { return git_treebuilder_entrycount(c_ptr_); } 37 | 38 | tree::entry tree_builder::operator[](const std::string &filename) const { 39 | return tree::entry(const_cast( 40 | git_treebuilder_get(c_ptr_, filename.c_str())), 41 | ownership::libgit2); 42 | } 43 | 44 | void tree_builder::insert(const std::string &filename, const oid &id, 45 | file_mode mode) { 46 | const git_tree_entry *result = nullptr; 47 | if (git_treebuilder_insert(&result, c_ptr_, filename.c_str(), id.c_ptr(), 48 | static_cast(mode))) 49 | throw git_exception(); 50 | } 51 | 52 | void tree_builder::remove(const std::string &filename) { 53 | if (git_treebuilder_remove(c_ptr_, filename.c_str())) 54 | throw git_exception(); 55 | } 56 | 57 | oid tree_builder::write() { 58 | git_oid id; 59 | if (git_treebuilder_write(&id, c_ptr_)) 60 | throw git_exception(); 61 | return oid(&id); 62 | } 63 | 64 | oid tree_builder::write(data_buffer &tree) { 65 | git_oid id; 66 | if (git_treebuilder_write_with_buffer(&id, c_ptr_, tree.c_ptr())) 67 | throw git_exception(); 68 | return oid(&id); 69 | } 70 | 71 | const git_treebuilder *tree_builder::c_ptr() const { return c_ptr_; } 72 | 73 | } // namespace cppgit2 -------------------------------------------------------------------------------- /src/worktree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cppgit2 { 4 | 5 | worktree::worktree() : c_ptr_(nullptr), owner_(ownership::libgit2) {} 6 | 7 | worktree::worktree(git_worktree *c_ptr, ownership owner) 8 | : c_ptr_(c_ptr), owner_(owner) {} 9 | 10 | worktree::~worktree() { 11 | if (c_ptr_ && owner_ == ownership::user) 12 | git_worktree_free(c_ptr_); 13 | } 14 | 15 | std::pair worktree::is_locked() const { 16 | data_buffer result; 17 | auto ret = git_worktree_is_locked(result.c_ptr(), c_ptr_); 18 | if (ret > 0) { 19 | // Locked 20 | if (result.c_ptr()->size) // size > 0 => reason available 21 | return std::pair{true, result.to_string()}; 22 | else 23 | return std::pair{true, ""}; 24 | } else if (ret == 0) { 25 | // Not locked 26 | return std::pair{false, ""}; 27 | } else { 28 | throw git_exception(); 29 | } 30 | } 31 | 32 | bool worktree::is_prunable(unsigned int version, uint32_t flags) const { 33 | git_worktree_prune_options options; 34 | options.version = version; 35 | options.flags = flags; 36 | auto ret = git_worktree_is_prunable(c_ptr_, &options); 37 | if (ret == 1) 38 | return true; 39 | else if (ret == 0) 40 | return false; 41 | else 42 | throw git_exception(); 43 | } 44 | 45 | bool worktree::is_prunable() const { 46 | git_worktree_prune_options options; 47 | // Initializes a git_worktree_prune_options with default values. Equivalent to 48 | // creating an instance with GIT_WORKTREE_PRUNE_OPTIONS_INIT. 49 | auto ret = git_worktree_prune_options_init( 50 | &options, GIT_WORKTREE_PRUNE_OPTIONS_VERSION); 51 | if (ret == 0) { 52 | ret = git_worktree_is_prunable(c_ptr_, &options); 53 | if (ret == 1) 54 | return true; 55 | else if (ret == 0) 56 | return false; 57 | else 58 | throw git_exception(); 59 | } else 60 | throw git_exception(); 61 | } 62 | 63 | void worktree::lock(const std::string &reason) { 64 | const char *reason_c = reason.empty() ? nullptr : reason.c_str(); 65 | if (git_worktree_lock(c_ptr_, reason_c)) 66 | throw git_exception(); 67 | } 68 | 69 | std::string worktree::name() const { 70 | auto ret = git_worktree_name(c_ptr_); 71 | if (ret) 72 | return std::string(ret); 73 | else 74 | return ""; 75 | } 76 | 77 | std::string worktree::path() const { 78 | auto ret = git_worktree_path(c_ptr_); 79 | if (ret) 80 | return std::string(ret); 81 | else 82 | return ""; 83 | } 84 | 85 | void worktree::prune(unsigned int version, uint32_t flags) { 86 | git_worktree_prune_options options; 87 | options.version = version; 88 | options.flags = flags; 89 | if (git_worktree_prune(c_ptr_, &options)) 90 | throw git_exception(); 91 | } 92 | 93 | void worktree::prune() { 94 | git_worktree_prune_options options; 95 | // Initializes a git_worktree_prune_options with default values. Equivalent to 96 | // creating an instance with GIT_WORKTREE_PRUNE_OPTIONS_INIT. 97 | auto ret = git_worktree_prune_options_init( 98 | &options, GIT_WORKTREE_PRUNE_OPTIONS_VERSION); 99 | if (ret == 0) { 100 | if (git_worktree_prune(c_ptr_, &options)) 101 | throw git_exception(); 102 | } else 103 | throw git_exception(); 104 | } 105 | 106 | void worktree::unlock() { 107 | if (git_worktree_unlock(c_ptr_)) 108 | throw git_exception(); 109 | } 110 | 111 | bool worktree::is_valid() { return git_worktree_validate(c_ptr_) == 0; } 112 | 113 | bool worktree::validate() { 114 | if (!is_valid()) 115 | throw git_exception(); 116 | return true; 117 | } 118 | 119 | const git_worktree *worktree::c_ptr() const { return c_ptr_; } 120 | 121 | } // namespace cppgit2 -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /test/test_data_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using doctest::test_suite; 4 | using namespace cppgit2; 5 | 6 | TEST_CASE("Construct an empty data_buffer" * test_suite("data_buffer")) { 7 | data_buffer foo; 8 | REQUIRE(foo.to_string() == ""); 9 | foo.grow_to_size(5); 10 | foo.set_buffer("ABCDE"); 11 | foo.grow_to_size(10); 12 | foo.set_buffer("ABCDEFGHIJ"); 13 | REQUIRE(foo.to_string() == "ABCDEFGHIJ"); 14 | } 15 | 16 | TEST_CASE("Construct data buffer of size `n`" * test_suite("data_buffer")) { 17 | data_buffer foo(5); // 5 characters 18 | foo.set_buffer("ABCDE"); 19 | REQUIRE(foo.to_string() == "ABCDE"); 20 | } 21 | 22 | TEST_CASE("Construct data buffer from C ptr" * test_suite("data_buffer")) { 23 | data_buffer foo(5); // 5 characters 24 | foo.set_buffer("ABCDE"); 25 | data_buffer bar(foo.c_ptr()); 26 | REQUIRE(bar.to_string() == "ABCDE"); 27 | } 28 | 29 | TEST_CASE("Grow a data buffer to size `n`" * test_suite("data_buffer")) { 30 | data_buffer foo(5); // 5 characters 31 | foo.set_buffer("ABCDE"); 32 | foo.grow_to_size(10); 33 | foo.set_buffer("ABCDEFGHIJ"); 34 | REQUIRE(foo.to_string() == "ABCDEFGHIJ"); 35 | } 36 | -------------------------------------------------------------------------------- /test/test_oid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using doctest::test_suite; 4 | using namespace cppgit2; 5 | 6 | TEST_CASE("Construct oid from string" * test_suite("oid")) { 7 | oid oid("f9de917ac729414151fdce077d4098cfec9a45a5"); 8 | REQUIRE(oid.to_hex_string() == "f9de917ac729414151fdce077d4098cfec9a45a5"); 9 | } 10 | 11 | TEST_CASE("Construct oid from C ptr" * test_suite("oid")) { 12 | oid oid1("f9de917ac729414151fdce077d4098cfec9a45a5"); 13 | oid oid2(oid1.c_ptr()); 14 | REQUIRE(oid2.to_hex_string() == "f9de917ac729414151fdce077d4098cfec9a45a5"); 15 | } 16 | 17 | TEST_CASE("Invalid oid construction" * test_suite("oid")) { 18 | bool exception_thrown = false; 19 | try { 20 | oid foo("f9de90000&^$%_%#"); 21 | } catch (git_exception &) { 22 | exception_thrown = true; 23 | } 24 | REQUIRE(exception_thrown); 25 | } 26 | 27 | TEST_CASE("Clone oid from existing oid struct" * test_suite("oid")) { 28 | oid id("f9de917ac729414151fdce077d4098cfec9a45a5"); 29 | oid clone = id.copy(); 30 | REQUIRE(clone.to_hex_string() == "f9de917ac729414151fdce077d4098cfec9a45a5"); 31 | } 32 | 33 | TEST_CASE("Get path formatted string from oid" * test_suite("oid")) { 34 | oid id("f9de917ac729414151fdce077d4098cfec9a45a5"); 35 | REQUIRE(id.to_path_string() == "f9/de917ac729414151fdce077d4098cfec9a45a5"); 36 | } 37 | 38 | TEST_CASE("Construct oid from string with 5 characters" * test_suite("oid")) { 39 | oid oid("f9de917ac729414151fdce077d4098cfec9a45a5", 5); 40 | REQUIRE(oid.to_hex_string(5) == "f9de9"); 41 | } 42 | 43 | TEST_CASE("to_hex_string() on oid constructed with 5 characters has 35 zeros" * 44 | test_suite("oid")) { 45 | oid oid("f9de917ac729414151fdce077d4098cfec9a45a5", 5); 46 | REQUIRE(oid.to_hex_string() == "f9de900000000000000000000000000000000000"); 47 | } 48 | 49 | TEST_CASE("Check if oid is all zeros" * test_suite("oid")) { 50 | oid oid1("f9de917ac729414151fdce077d4098cfec9a45a5"); 51 | REQUIRE(oid1.is_zero() == false); 52 | 53 | oid oid2("f9de917ac729414151fdce077d4098cfec9a45a5", 5); 54 | REQUIRE(oid2.is_zero() == false); 55 | 56 | oid oid3("00000", 3); 57 | REQUIRE(oid3.is_zero() == true); 58 | 59 | oid oid4("0000000000000000000000000000000000000000"); 60 | REQUIRE(oid4.is_zero() == true); 61 | } 62 | 63 | TEST_CASE("Check if two oids are equal" * test_suite("oid")) { 64 | oid oid1("f9de917ac729414151fdce077d4098cfec9a45a5"); 65 | oid oid2("f9de917ac729414151fdce077d4098cfec9a45a5"); 66 | REQUIRE_FALSE(oid1 == "fa64cv"); 67 | REQUIRE(oid1 == "f9de917ac729414151fdce077d4098cfec9a45a5"); 68 | REQUIRE(oid1 == oid2); 69 | REQUIRE(oid2 == oid1); 70 | } 71 | 72 | TEST_CASE("Compare two oids" * test_suite("oid")) { 73 | oid oid1("f9de917ac729414151fdce077d4098cfec9a45a5"); 74 | oid oid2("698b74a011ce48d2cae918129e8392c8987e0777"); 75 | REQUIRE(oid1.compare(oid2) > 0); 76 | REQUIRE(oid2.compare(oid1) < 0); 77 | 78 | oid oid3("69de917ac729414151fdce077d4098cfec9a45a5"); 79 | REQUIRE(oid2.compare(oid3) < 0); 80 | REQUIRE(oid2.compare(oid3, 2) == 0); 81 | 82 | oid oid4("f9de900000000000000000000000000000000000"); 83 | REQUIRE(oid1.compare(oid4, 5) == 0); 84 | } 85 | 86 | TEST_CASE("Interoperatbility with libgit2" * test_suite("oid")) { 87 | // Construct cppgit2 OID object 88 | oid oid1("f9de917ac729414151fdce077d4098cfec9a45a5"); 89 | 90 | // Access libgit2 C ptr 91 | auto oid1_cptr = oid1.c_ptr(); 92 | 93 | // Use the libgit2 C API to format 94 | size_t n = 8; 95 | char *oid1_formatted = (char *)malloc(sizeof(char) * n); 96 | git_oid_tostr(oid1_formatted, n + 1, oid1_cptr); 97 | 98 | // Results are the same 99 | REQUIRE(oid1.to_hex_string(8) == std::string(oid1_formatted)); // f9de917 100 | } -------------------------------------------------------------------------------- /test/test_signature.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using doctest::test_suite; 4 | using namespace cppgit2; 5 | 6 | TEST_CASE("Default, empty signature" * test_suite("signature")) { 7 | signature foo; 8 | REQUIRE(foo.name().empty()); 9 | REQUIRE(foo.email().empty()); 10 | REQUIRE(foo.time() == 0); 11 | REQUIRE(foo.offset() == 0); 12 | } 13 | 14 | TEST_CASE("Construct signature with name and email" * test_suite("signature")) { 15 | signature foo("Foo Bar", "foo.bar@baz.com"); 16 | REQUIRE(foo.name() == "Foo Bar"); 17 | REQUIRE(foo.email() == "foo.bar@baz.com"); 18 | } 19 | 20 | TEST_CASE("Construct signature with name, email, time and offset" * 21 | test_suite("signature")) { 22 | signature foo("Foo Bar", "foo.bar@baz.com", 50, 3); 23 | REQUIRE(foo.name() == "Foo Bar"); 24 | REQUIRE(foo.email() == "foo.bar@baz.com"); 25 | REQUIRE(foo.time() == 50); 26 | REQUIRE(foo.offset() == 3); 27 | } 28 | 29 | TEST_CASE("Construct signature from formatted buffer" * 30 | test_suite("signature")) { 31 | std::string buffer{"Foo Bar 1580583850756 0600"}; 32 | signature foo(buffer); 33 | REQUIRE(foo.name() == "Foo Bar"); 34 | REQUIRE(foo.email() == "foo.bar@baz.com"); 35 | REQUIRE(foo.time() == 1580583850756); 36 | } 37 | 38 | TEST_CASE("Construct signature from ptr to libgit2 C-struct" * 39 | test_suite("signature")) { 40 | signature foo("Foo Bar", "foo.bar@baz.com", 50, 3); 41 | signature bar(foo.c_ptr()); 42 | REQUIRE(bar.name() == "Foo Bar"); 43 | REQUIRE(bar.email() == "foo.bar@baz.com"); 44 | REQUIRE(bar.time() == 50); 45 | REQUIRE(bar.offset() == 3); 46 | } 47 | 48 | TEST_CASE("Clone signature struct" * test_suite("signature")) { 49 | signature foo("Foo Bar", "foo.bar@baz.com", 50, 3); 50 | auto bar = foo.copy(); 51 | REQUIRE(bar.name() == "Foo Bar"); 52 | REQUIRE(bar.email() == "foo.bar@baz.com"); 53 | REQUIRE(bar.time() == 50); 54 | REQUIRE(bar.offset() == 3); 55 | } 56 | 57 | TEST_CASE("Interoperatbility with libgit2" * test_suite("signature")) { 58 | 59 | // Construct libgit2 signature 60 | git_signature sig; 61 | sig.name = (char *)"Foo Bar"; 62 | sig.email = (char *)"foo.bar@baz.com"; 63 | 64 | // Construct cppgit2 wrapper 65 | cppgit2::signature sig2(&sig); 66 | 67 | REQUIRE(sig2.name() == std::string(sig.name)); 68 | REQUIRE(sig2.email() == std::string(sig.email)); 69 | } -------------------------------------------------------------------------------- /test/test_strarray.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using doctest::test_suite; 4 | using namespace cppgit2; 5 | 6 | TEST_CASE("Default construct strarray" * test_suite("strarray")) { 7 | strarray arr; 8 | REQUIRE(arr.count() == 0); 9 | } 10 | 11 | TEST_CASE("Construct strarray from vector of strings" * 12 | test_suite("strarray")) { 13 | strarray arr({"Hello", "World"}); 14 | REQUIRE(arr.count() == 2); 15 | REQUIRE(arr[0] == "Hello"); 16 | REQUIRE(arr[1] == "World"); 17 | } 18 | 19 | TEST_CASE("Construct strarray from libgit2 C ptr" * test_suite("strarray")) { 20 | strarray foo({"Hello", "World"}); 21 | strarray bar(foo.c_ptr()); 22 | REQUIRE(bar.count() == 2); 23 | REQUIRE(bar[0] == "Hello"); 24 | REQUIRE(bar[1] == "World"); 25 | } 26 | 27 | TEST_CASE("Clone strarray using .copy()" * test_suite("strarray")) { 28 | strarray foo({"Hello", "World", "!"}); 29 | strarray bar = foo.copy(); 30 | REQUIRE(bar.count() == 3); 31 | REQUIRE(bar[0] == "Hello"); 32 | REQUIRE(bar[1] == "World"); 33 | REQUIRE(bar[2] == "!"); 34 | } 35 | 36 | TEST_CASE("Get vector of strings from strarray" * test_suite("strarray")) { 37 | strarray foo({"This", "is", "an", "strarray", "!"}); 38 | auto vec = foo.to_vector(); 39 | REQUIRE(vec.size() == 5); 40 | REQUIRE(vec[0] == "This"); 41 | REQUIRE(vec[1] == "is"); 42 | REQUIRE(vec[2] == "an"); 43 | REQUIRE(vec[3] == "strarray"); 44 | REQUIRE(vec[4] == "!"); 45 | } 46 | --------------------------------------------------------------------------------