├── .gitattributes ├── .github └── workflows │ ├── build.yml │ └── clang-format.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── SConstruct ├── THIRDPARTY.md ├── addons └── godot-git-plugin │ └── git_plugin.gdextension ├── godot-git-plugin ├── .editorconfig ├── SCsub ├── cpp.hint └── src │ ├── .clang-format │ ├── gdlibrary.cpp │ ├── git_callbacks.cpp │ ├── git_callbacks.h │ ├── git_plugin.cpp │ ├── git_plugin.h │ ├── git_wrappers.cpp │ └── git_wrappers.h ├── icon.png ├── icon.svg ├── release.sh ├── thirdparty └── ssh2 │ └── libssh2_config.h └── tools ├── cmake.py ├── git2.py ├── openssl.py └── ssh2.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize EOL for all files that Git considers text files. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: [push, pull_request] 4 | 5 | env: 6 | # Only used for the cache key. Increment version to force clean build. 7 | GODOT_BASE_BRANCH: master 8 | SCONS_CACHE: ${{ github.workspace }}/.scons-cache/ 9 | 10 | jobs: 11 | linux-x64: 12 | runs-on: ubuntu-22.04 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | submodules: recursive 17 | - name: Setup Godot build cache 18 | uses: ./godot-cpp/.github/actions/godot-cache 19 | with: 20 | cache-name: linux-x86_64 21 | continue-on-error: true 22 | - name: Build for Linux editor x86_64 23 | run: | 24 | pip3 install scons 25 | scons platform=linux arch=x86_64 target=editor generate_bindings=yes 26 | ldd addons/godot-git-plugin/linux/*.so 27 | - name: Prepare artifact 28 | run: | 29 | mkdir out 30 | mv addons out/ 31 | - uses: actions/upload-artifact@v4 32 | with: 33 | name: libgit_plugin.linux.x86_64.editor.so-${{ github.sha }} 34 | if-no-files-found: error 35 | path: | 36 | out/ 37 | 38 | windows-x64: 39 | runs-on: windows-2022 40 | steps: 41 | - uses: actions/checkout@v4 42 | with: 43 | submodules: recursive 44 | - name: Setup Godot build cache 45 | uses: ./godot-cpp/.github/actions/godot-cache 46 | with: 47 | cache-name: windows-x86_64 48 | - uses: ilammy/msvc-dev-cmd@v1 # For dumpbin. 49 | - uses: ilammy/setup-nasm@v1 50 | - name: Build for Windows editor x86_64 51 | shell: powershell 52 | run: | 53 | pip3 install scons 54 | scons platform=windows arch=x86_64 target=editor generate_bindings=yes 55 | dumpbin /dependents .\addons\godot-git-plugin\windows\*.dll 56 | - name: Prepare artifact 57 | shell: bash 58 | run: | 59 | # Not needed to use the plugin. 60 | rm -f addons/godot-git-plugin/windows/*.{exp,lib} 61 | mkdir out 62 | mv addons out/ 63 | - uses: actions/upload-artifact@v4 64 | with: 65 | name: libgit_plugin.windows.x86_64.editor.dll-${{ github.sha }} 66 | if-no-files-found: error 67 | path: | 68 | out/ 69 | 70 | macos-universal: 71 | runs-on: macos-15 72 | steps: 73 | - uses: actions/checkout@v4 74 | with: 75 | submodules: recursive 76 | - name: Setup Godot build cache 77 | uses: ./godot-cpp/.github/actions/godot-cache 78 | with: 79 | cache-name: macos-universal 80 | - name: Build for macOS editor universal 81 | run: | 82 | pip install scons 83 | scons platform=macos arch=universal target=editor generate_bindings=yes macos_deployment_target=10.13 84 | otool -L addons/godot-git-plugin/macos/*.dylib 85 | - name: Prepare artifact 86 | run: | 87 | mkdir out 88 | mv addons out/ 89 | - uses: actions/upload-artifact@v4 90 | with: 91 | name: libgit_plugin.macos.universal.editor.dylib-${{ github.sha }} 92 | if-no-files-found: error 93 | path: | 94 | out/ 95 | -------------------------------------------------------------------------------- /.github/workflows/clang-format.yml: -------------------------------------------------------------------------------- 1 | name: clang-format 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | clang-format: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: DoozyX/clang-format-lint-action@v0.18.2 12 | with: 13 | source: "godot-git-plugin/src" 14 | extensions: "h,cpp" 15 | clangFormatVersion: 18 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SConstruct db 2 | *.dblite 3 | 4 | # Godot Serialisations 5 | extension_api.json 6 | !/ci/extension_api.json 7 | 8 | # Visual Studio Cache 9 | .vs/ 10 | 11 | # VSCode Cache 12 | .vscode/ 13 | 14 | # Mac stuff 15 | .DS_Store 16 | 17 | # Vim 18 | *.swp 19 | 20 | # Binaries 21 | __pycache__/ 22 | build/ 23 | bin/ 24 | macos/ 25 | linux/ 26 | win64/ 27 | *.lib 28 | *.a 29 | *.obj 30 | *.os 31 | *.ilk 32 | *.pdb 33 | *.pyc 34 | *.zip 35 | 36 | # Misc 37 | *.log 38 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "godot-cpp"] 2 | path = godot-cpp 3 | url = https://github.com/godotengine/godot-cpp 4 | branch = 3.x 5 | [submodule "thirdparty/git2/libgit2"] 6 | path = thirdparty/git2/libgit2 7 | url = https://github.com/libgit2/libgit2 8 | ignore = untracked 9 | [submodule "thirdparty/ssh2/libssh2"] 10 | path = thirdparty/ssh2/libssh2 11 | url = https://github.com/libssh2/libssh2 12 | [submodule "thirdparty/openssl"] 13 | path = thirdparty/openssl 14 | url = https://github.com/openssl/openssl 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016-2023 The Godot Engine community 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![C/C++ CI](https://github.com/godotengine/godot-git-plugin/actions/workflows/build.yml/badge.svg)](https://github.com/godotengine/godot-git-plugin/actions/workflows/build.yml) 2 | 3 | 4 | 5 | # Godot Git Plugin 6 | 7 | Git implementation of the Godot Engine VCS interface in Godot. We use [libgit2](https://libgit2.org) as our backend to simulate Git in code. 8 | 9 | ## Installation 10 | 11 | 1. Grab the platform binaries here: https://github.com/godotengine/godot-git-plugin/releases 12 | 2. Then read the installation instructions: https://github.com/godotengine/godot-git-plugin/wiki 13 | 14 | ## Build 15 | 16 | This section onwards is only meant to be used if you intend to compile the plugin from source. 17 | 18 | ### Required tools 19 | 20 | - Full copy of the source code. Remember to use `git clone --recursive`, or initialize submodules with `git submodule update --init`. 21 | - [SCons](https://scons.org/pages/download.html) (v3.1.2+), CMake, and Perl. 22 | - C++17 and C90 compilers detectable by SCons and present in `PATH`. 23 | 24 | ### Release build 25 | 26 | ``` 27 | scons platform= target=editor 28 | ``` 29 | 30 | > You may get the GDExtension dump yourself from Godot using the instructions in the next section, or use the ones provided in `godot-cpp`. 31 | 32 | For more build options, run `scons platform= -h` 33 | 34 | ## Dev builds 35 | 36 | When new features are being worked on for the Godot VCS Integration, the build process sometimes requires developers to make changes in the GDExtension API along with this plugin. This means we need to manually generate the GDExtension API from the custom Godot builds and use it to compile godot-cpp, and then finally link the resulting godot-cpp binary into this plugin. 37 | 38 | If you need to use a custom GDExtension API: 39 | 40 | 1. Dump the new bindings from the custom Godot build. 41 | 42 | ```shell 43 | ./path/to/godot/bin/godot..editor. --headless --dump-gdextension-interface --dump-extension-api 44 | ``` 45 | 46 | 2. Build the plugin along with the godot-cpp library. 47 | 48 | ``` 49 | scons platform= target=editor generate_bindings=yes dev_build=yes 50 | ``` 51 | 52 | > You only need to build godot-cpp once every change in the GDExtension API, hence, `generate_bindings=yes` should only be passed in during the first time after generating a new GDExtension API dump. 53 | 54 | 3. To test the plugin, set up a testing project with Godot, and copy or symlink the `addons` folder. 55 | 56 | To view more options available while recompiling godot-git-plugin, run `scons platform= -h`. 57 | 58 | --- 59 | 60 | ## License 61 | 62 | This plugin is under the MIT License. Third-party notices are present in [THIRDPARTY.md](THIRDPARTY.md). 63 | 64 | OpenSSL License Attributions - This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/). This product includes cryptographic software written by Eric Young (eay@cryptsoft.com) 65 | -------------------------------------------------------------------------------- /SConstruct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | EnsureSConsVersion(3, 1, 2) 6 | EnsurePythonVersion(3, 6) 7 | 8 | opts = Variables([], ARGUMENTS) 9 | 10 | env = Environment(ENV=os.environ) 11 | 12 | # Define our options 13 | opts.Add(PathVariable("target_path", 14 | "The path where the lib is installed.", "addons/godot-git-plugin/")) 15 | opts.Add(PathVariable("target_name", "The library name.", 16 | "libgit_plugin", PathVariable.PathAccept)) 17 | 18 | # Updates the environment with the option variables. 19 | opts.Update(env) 20 | 21 | if ARGUMENTS.get("custom_api_file", "") != "": 22 | ARGUMENTS["custom_api_file"] = "../" + ARGUMENTS["custom_api_file"] 23 | 24 | ARGUMENTS["target"] = "editor" 25 | env = SConscript("godot-cpp/SConstruct").Clone() 26 | env.PrependENVPath("PATH", os.getenv("PATH")) # Prepend PATH, done upstream in recent godot-cpp verions. 27 | 28 | # Force linking with LTO on windows MSVC, silence the linker complaining that libgit uses LTO but we are not linking with it. 29 | if env["platform"] == "windows" and env.get("is_msvc", False): 30 | env.AppendUnique(LINKFLAGS=["/LTCG"]) 31 | 32 | # OpenSSL Builder 33 | env.Tool("openssl", toolpath=["tools"]) 34 | 35 | # SSH2 Builder 36 | env.Tool("cmake", toolpath=["tools"]) 37 | env.Tool("ssh2", toolpath=["tools"]) 38 | env.Tool("git2", toolpath=["tools"]) 39 | 40 | opts.Update(env) 41 | 42 | ssl = env.OpenSSL() 43 | ssh2 = env.BuildSSH2(ssl) 44 | ssl += ssh2 45 | git2 = env.BuildGIT2(ssl) 46 | 47 | Export("ssl") 48 | Export("env") 49 | 50 | SConscript("godot-git-plugin/SCsub") 51 | 52 | # Generates help for the -h scons option. 53 | Help(opts.GenerateHelpText(env)) 54 | -------------------------------------------------------------------------------- /THIRDPARTY.md: -------------------------------------------------------------------------------- 1 | # Third-Party Notices 2 | 3 | The Godot Git Plugin source code uses the following third-party source code: 4 | 5 | 1. godotengine/godot-cpp - MIT License - https://github.com/godotengine/godot-cpp/tree/02336831735fd6affbe0a6fa252ec98d3e78120c 6 | 2. libgit2/libgit2 - GPLv2 with a special Linking Exception - https://github.com/libgit2/libgit2/tree/b7bad55e4bb0a285b073ba5e02b01d3f522fc95d 7 | 3. libssh2/libssh2 - BSD-3-Clause License - https://github.com/libssh2/libssh2/tree/635caa90787220ac3773c1d5ba11f1236c22eae8 8 | 4. openssl - OpenSSL License - https://github.com/openssl/openssl/tree/26baecb28ce461696966dac9ac889629db0b3b96 9 | 10 | ## License Texts 11 | 12 | ### godotengine/godot-cpp 13 | 14 | ``` 15 | # MIT License 16 | 17 | Copyright (c) 2017-2022 Godot Engine contributors. 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in all 27 | copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. 36 | ``` 37 | 38 | ### libgit2/libgit2 39 | 40 | ``` 41 | libgit2 is Copyright (C) the libgit2 contributors, 42 | unless otherwise stated. See the AUTHORS file for details. 43 | 44 | Note that the only valid version of the GPL as far as this project 45 | is concerned is _this_ particular version of the license (ie v2, not 46 | v2.2 or v3.x or whatever), unless explicitly otherwise stated. 47 | 48 | ---------------------------------------------------------------------- 49 | 50 | LINKING EXCEPTION 51 | 52 | In addition to the permissions in the GNU General Public License, 53 | the authors give you unlimited permission to link the compiled 54 | version of this library into combinations with other programs, 55 | and to distribute those combinations without any restriction 56 | coming from the use of this file. (The General Public License 57 | restrictions do apply in other respects; for example, they cover 58 | modification of the file, and distribution when not linked into 59 | a combined executable.) 60 | 61 | ---------------------------------------------------------------------- 62 | 63 | GNU GENERAL PUBLIC LICENSE 64 | Version 2, June 1991 65 | 66 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 67 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 68 | Everyone is permitted to copy and distribute verbatim copies 69 | of this license document, but changing it is not allowed. 70 | 71 | Preamble 72 | 73 | The licenses for most software are designed to take away your 74 | freedom to share and change it. By contrast, the GNU General Public 75 | License is intended to guarantee your freedom to share and change free 76 | software--to make sure the software is free for all its users. This 77 | General Public License applies to most of the Free Software 78 | Foundation's software and to any other program whose authors commit to 79 | using it. (Some other Free Software Foundation software is covered by 80 | the GNU Library General Public License instead.) You can apply it to 81 | your programs, too. 82 | 83 | When we speak of free software, we are referring to freedom, not 84 | price. Our General Public Licenses are designed to make sure that you 85 | have the freedom to distribute copies of free software (and charge for 86 | this service if you wish), that you receive source code or can get it 87 | if you want it, that you can change the software or use pieces of it 88 | in new free programs; and that you know you can do these things. 89 | 90 | To protect your rights, we need to make restrictions that forbid 91 | anyone to deny you these rights or to ask you to surrender the rights. 92 | These restrictions translate to certain responsibilities for you if you 93 | distribute copies of the software, or if you modify it. 94 | 95 | For example, if you distribute copies of such a program, whether 96 | gratis or for a fee, you must give the recipients all the rights that 97 | you have. You must make sure that they, too, receive or can get the 98 | source code. And you must show them these terms so they know their 99 | rights. 100 | 101 | We protect your rights with two steps: (1) copyright the software, and 102 | (2) offer you this license which gives you legal permission to copy, 103 | distribute and/or modify the software. 104 | 105 | Also, for each author's protection and ours, we want to make certain 106 | that everyone understands that there is no warranty for this free 107 | software. If the software is modified by someone else and passed on, we 108 | want its recipients to know that what they have is not the original, so 109 | that any problems introduced by others will not reflect on the original 110 | authors' reputations. 111 | 112 | Finally, any free program is threatened constantly by software 113 | patents. We wish to avoid the danger that redistributors of a free 114 | program will individually obtain patent licenses, in effect making the 115 | program proprietary. To prevent this, we have made it clear that any 116 | patent must be licensed for everyone's free use or not licensed at all. 117 | 118 | The precise terms and conditions for copying, distribution and 119 | modification follow. 120 | 121 | GNU GENERAL PUBLIC LICENSE 122 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 123 | 124 | 0. This License applies to any program or other work which contains 125 | a notice placed by the copyright holder saying it may be distributed 126 | under the terms of this General Public License. The "Program", below, 127 | refers to any such program or work, and a "work based on the Program" 128 | means either the Program or any derivative work under copyright law: 129 | that is to say, a work containing the Program or a portion of it, 130 | either verbatim or with modifications and/or translated into another 131 | language. (Hereinafter, translation is included without limitation in 132 | the term "modification".) Each licensee is addressed as "you". 133 | 134 | Activities other than copying, distribution and modification are not 135 | covered by this License; they are outside its scope. The act of 136 | running the Program is not restricted, and the output from the Program 137 | is covered only if its contents constitute a work based on the 138 | Program (independent of having been made by running the Program). 139 | Whether that is true depends on what the Program does. 140 | 141 | 1. You may copy and distribute verbatim copies of the Program's 142 | source code as you receive it, in any medium, provided that you 143 | conspicuously and appropriately publish on each copy an appropriate 144 | copyright notice and disclaimer of warranty; keep intact all the 145 | notices that refer to this License and to the absence of any warranty; 146 | and give any other recipients of the Program a copy of this License 147 | along with the Program. 148 | 149 | You may charge a fee for the physical act of transferring a copy, and 150 | you may at your option offer warranty protection in exchange for a fee. 151 | 152 | 2. You may modify your copy or copies of the Program or any portion 153 | of it, thus forming a work based on the Program, and copy and 154 | distribute such modifications or work under the terms of Section 1 155 | above, provided that you also meet all of these conditions: 156 | 157 | a) You must cause the modified files to carry prominent notices 158 | stating that you changed the files and the date of any change. 159 | 160 | b) You must cause any work that you distribute or publish, that in 161 | whole or in part contains or is derived from the Program or any 162 | part thereof, to be licensed as a whole at no charge to all third 163 | parties under the terms of this License. 164 | 165 | c) If the modified program normally reads commands interactively 166 | when run, you must cause it, when started running for such 167 | interactive use in the most ordinary way, to print or display an 168 | announcement including an appropriate copyright notice and a 169 | notice that there is no warranty (or else, saying that you provide 170 | a warranty) and that users may redistribute the program under 171 | these conditions, and telling the user how to view a copy of this 172 | License. (Exception: if the Program itself is interactive but 173 | does not normally print such an announcement, your work based on 174 | the Program is not required to print an announcement.) 175 | 176 | These requirements apply to the modified work as a whole. If 177 | identifiable sections of that work are not derived from the Program, 178 | and can be reasonably considered independent and separate works in 179 | themselves, then this License, and its terms, do not apply to those 180 | sections when you distribute them as separate works. But when you 181 | distribute the same sections as part of a whole which is a work based 182 | on the Program, the distribution of the whole must be on the terms of 183 | this License, whose permissions for other licensees extend to the 184 | entire whole, and thus to each and every part regardless of who wrote it. 185 | 186 | Thus, it is not the intent of this section to claim rights or contest 187 | your rights to work written entirely by you; rather, the intent is to 188 | exercise the right to control the distribution of derivative or 189 | collective works based on the Program. 190 | 191 | In addition, mere aggregation of another work not based on the Program 192 | with the Program (or with a work based on the Program) on a volume of 193 | a storage or distribution medium does not bring the other work under 194 | the scope of this License. 195 | 196 | 3. You may copy and distribute the Program (or a work based on it, 197 | under Section 2) in object code or executable form under the terms of 198 | Sections 1 and 2 above provided that you also do one of the following: 199 | 200 | a) Accompany it with the complete corresponding machine-readable 201 | source code, which must be distributed under the terms of Sections 202 | 1 and 2 above on a medium customarily used for software interchange; or, 203 | 204 | b) Accompany it with a written offer, valid for at least three 205 | years, to give any third party, for a charge no more than your 206 | cost of physically performing source distribution, a complete 207 | machine-readable copy of the corresponding source code, to be 208 | distributed under the terms of Sections 1 and 2 above on a medium 209 | customarily used for software interchange; or, 210 | 211 | c) Accompany it with the information you received as to the offer 212 | to distribute corresponding source code. (This alternative is 213 | allowed only for noncommercial distribution and only if you 214 | received the program in object code or executable form with such 215 | an offer, in accord with Subsection b above.) 216 | 217 | The source code for a work means the preferred form of the work for 218 | making modifications to it. For an executable work, complete source 219 | code means all the source code for all modules it contains, plus any 220 | associated interface definition files, plus the scripts used to 221 | control compilation and installation of the executable. However, as a 222 | special exception, the source code distributed need not include 223 | anything that is normally distributed (in either source or binary 224 | form) with the major components (compiler, kernel, and so on) of the 225 | operating system on which the executable runs, unless that component 226 | itself accompanies the executable. 227 | 228 | If distribution of executable or object code is made by offering 229 | access to copy from a designated place, then offering equivalent 230 | access to copy the source code from the same place counts as 231 | distribution of the source code, even though third parties are not 232 | compelled to copy the source along with the object code. 233 | 234 | 4. You may not copy, modify, sublicense, or distribute the Program 235 | except as expressly provided under this License. Any attempt 236 | otherwise to copy, modify, sublicense or distribute the Program is 237 | void, and will automatically terminate your rights under this License. 238 | However, parties who have received copies, or rights, from you under 239 | this License will not have their licenses terminated so long as such 240 | parties remain in full compliance. 241 | 242 | 5. You are not required to accept this License, since you have not 243 | signed it. However, nothing else grants you permission to modify or 244 | distribute the Program or its derivative works. These actions are 245 | prohibited by law if you do not accept this License. Therefore, by 246 | modifying or distributing the Program (or any work based on the 247 | Program), you indicate your acceptance of this License to do so, and 248 | all its terms and conditions for copying, distributing or modifying 249 | the Program or works based on it. 250 | 251 | 6. Each time you redistribute the Program (or any work based on the 252 | Program), the recipient automatically receives a license from the 253 | original licensor to copy, distribute or modify the Program subject to 254 | these terms and conditions. You may not impose any further 255 | restrictions on the recipients' exercise of the rights granted herein. 256 | You are not responsible for enforcing compliance by third parties to 257 | this License. 258 | 259 | 7. If, as a consequence of a court judgment or allegation of patent 260 | infringement or for any other reason (not limited to patent issues), 261 | conditions are imposed on you (whether by court order, agreement or 262 | otherwise) that contradict the conditions of this License, they do not 263 | excuse you from the conditions of this License. If you cannot 264 | distribute so as to satisfy simultaneously your obligations under this 265 | License and any other pertinent obligations, then as a consequence you 266 | may not distribute the Program at all. For example, if a patent 267 | license would not permit royalty-free redistribution of the Program by 268 | all those who receive copies directly or indirectly through you, then 269 | the only way you could satisfy both it and this License would be to 270 | refrain entirely from distribution of the Program. 271 | 272 | If any portion of this section is held invalid or unenforceable under 273 | any particular circumstance, the balance of the section is intended to 274 | apply and the section as a whole is intended to apply in other 275 | circumstances. 276 | 277 | It is not the purpose of this section to induce you to infringe any 278 | patents or other property right claims or to contest validity of any 279 | such claims; this section has the sole purpose of protecting the 280 | integrity of the free software distribution system, which is 281 | implemented by public license practices. Many people have made 282 | generous contributions to the wide range of software distributed 283 | through that system in reliance on consistent application of that 284 | system; it is up to the author/donor to decide if he or she is willing 285 | to distribute software through any other system and a licensee cannot 286 | impose that choice. 287 | 288 | This section is intended to make thoroughly clear what is believed to 289 | be a consequence of the rest of this License. 290 | 291 | 8. If the distribution and/or use of the Program is restricted in 292 | certain countries either by patents or by copyrighted interfaces, the 293 | original copyright holder who places the Program under this License 294 | may add an explicit geographical distribution limitation excluding 295 | those countries, so that distribution is permitted only in or among 296 | countries not thus excluded. In such case, this License incorporates 297 | the limitation as if written in the body of this License. 298 | 299 | 9. The Free Software Foundation may publish revised and/or new versions 300 | of the General Public License from time to time. Such new versions will 301 | be similar in spirit to the present version, but may differ in detail to 302 | address new problems or concerns. 303 | 304 | Each version is given a distinguishing version number. If the Program 305 | specifies a version number of this License which applies to it and "any 306 | later version", you have the option of following the terms and conditions 307 | either of that version or of any later version published by the Free 308 | Software Foundation. If the Program does not specify a version number of 309 | this License, you may choose any version ever published by the Free Software 310 | Foundation. 311 | 312 | 10. If you wish to incorporate parts of the Program into other free 313 | programs whose distribution conditions are different, write to the author 314 | to ask for permission. For software which is copyrighted by the Free 315 | Software Foundation, write to the Free Software Foundation; we sometimes 316 | make exceptions for this. Our decision will be guided by the two goals 317 | of preserving the free status of all derivatives of our free software and 318 | of promoting the sharing and reuse of software generally. 319 | 320 | NO WARRANTY 321 | 322 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 323 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 324 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 325 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 326 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 327 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 328 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 329 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 330 | REPAIR OR CORRECTION. 331 | 332 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 333 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 334 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 335 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 336 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 337 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 338 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 339 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 340 | POSSIBILITY OF SUCH DAMAGES. 341 | 342 | END OF TERMS AND CONDITIONS 343 | 344 | How to Apply These Terms to Your New Programs 345 | 346 | If you develop a new program, and you want it to be of the greatest 347 | possible use to the public, the best way to achieve this is to make it 348 | free software which everyone can redistribute and change under these terms. 349 | 350 | To do so, attach the following notices to the program. It is safest 351 | to attach them to the start of each source file to most effectively 352 | convey the exclusion of warranty; and each file should have at least 353 | the "copyright" line and a pointer to where the full notice is found. 354 | 355 | 356 | Copyright (C) 357 | 358 | This program is free software; you can redistribute it and/or modify 359 | it under the terms of the GNU General Public License as published by 360 | the Free Software Foundation; either version 2 of the License, or 361 | (at your option) any later version. 362 | 363 | This program is distributed in the hope that it will be useful, 364 | but WITHOUT ANY WARRANTY; without even the implied warranty of 365 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 366 | GNU General Public License for more details. 367 | 368 | You should have received a copy of the GNU General Public License 369 | along with this program; if not, write to the Free Software 370 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 371 | 372 | 373 | Also add information on how to contact you by electronic and paper mail. 374 | 375 | If the program is interactive, make it output a short notice like this 376 | when it starts in an interactive mode: 377 | 378 | Gnomovision version 69, Copyright (C) year name of author 379 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 380 | This is free software, and you are welcome to redistribute it 381 | under certain conditions; type `show c' for details. 382 | 383 | The hypothetical commands `show w' and `show c' should show the appropriate 384 | parts of the General Public License. Of course, the commands you use may 385 | be called something other than `show w' and `show c'; they could even be 386 | mouse-clicks or menu items--whatever suits your program. 387 | 388 | You should also get your employer (if you work as a programmer) or your 389 | school, if any, to sign a "copyright disclaimer" for the program, if 390 | necessary. Here is a sample; alter the names: 391 | 392 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 393 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 394 | 395 | , 1 April 1989 396 | Ty Coon, President of Vice 397 | 398 | This General Public License does not permit incorporating your program into 399 | proprietary programs. If your program is a subroutine library, you may 400 | consider it more useful to permit linking proprietary applications with the 401 | library. If this is what you want to do, use the GNU Library General 402 | Public License instead of this License. 403 | 404 | ---------------------------------------------------------------------- 405 | 406 | The bundled ZLib code is licensed under the ZLib license: 407 | 408 | Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler 409 | 410 | This software is provided 'as-is', without any express or implied 411 | warranty. In no event will the authors be held liable for any damages 412 | arising from the use of this software. 413 | 414 | Permission is granted to anyone to use this software for any purpose, 415 | including commercial applications, and to alter it and redistribute it 416 | freely, subject to the following restrictions: 417 | 418 | 1. The origin of this software must not be misrepresented; you must not 419 | claim that you wrote the original software. If you use this software 420 | in a product, an acknowledgment in the product documentation would be 421 | appreciated but is not required. 422 | 2. Altered source versions must be plainly marked as such, and must not be 423 | misrepresented as being the original software. 424 | 3. This notice may not be removed or altered from any source distribution. 425 | 426 | Jean-loup Gailly Mark Adler 427 | jloup@gzip.org madler@alumni.caltech.edu 428 | 429 | ---------------------------------------------------------------------- 430 | 431 | The Clar framework is licensed under the ISC license: 432 | 433 | Copyright (c) 2011-2015 Vicent Marti 434 | 435 | Permission to use, copy, modify, and/or distribute this software for any 436 | purpose with or without fee is hereby granted, provided that the above 437 | copyright notice and this permission notice appear in all copies. 438 | 439 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 440 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 441 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 442 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 443 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 444 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 445 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 446 | 447 | ---------------------------------------------------------------------- 448 | 449 | The regex library (deps/regex/) is licensed under the GNU LGPL 450 | (available at the end of this file). 451 | 452 | Definitions for data structures and routines for the regular 453 | expression library. 454 | 455 | Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006,2008 456 | Free Software Foundation, Inc. 457 | This file is part of the GNU C Library. 458 | 459 | The GNU C Library is free software; you can redistribute it and/or 460 | modify it under the terms of the GNU Lesser General Public 461 | License as published by the Free Software Foundation; either 462 | version 2.1 of the License, or (at your option) any later version. 463 | 464 | The GNU C Library is distributed in the hope that it will be useful, 465 | but WITHOUT ANY WARRANTY; without even the implied warranty of 466 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 467 | Lesser General Public License for more details. 468 | 469 | You should have received a copy of the GNU Lesser General Public 470 | License along with the GNU C Library; if not, write to the Free 471 | Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 472 | 02110-1301 USA. 473 | 474 | ---------------------------------------------------------------------- 475 | 476 | The bundled winhttp definition files (deps/winhttp/) are licensed under 477 | the GNU LGPL (available at the end of this file). 478 | 479 | Copyright (C) 2007 Francois Gouget 480 | 481 | This library is free software; you can redistribute it and/or 482 | modify it under the terms of the GNU Lesser General Public 483 | License as published by the Free Software Foundation; either 484 | version 2.1 of the License, or (at your option) any later version. 485 | 486 | This library is distributed in the hope that it will be useful, 487 | but WITHOUT ANY WARRANTY; without even the implied warranty of 488 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 489 | Lesser General Public License for more details. 490 | 491 | You should have received a copy of the GNU Lesser General Public 492 | License along with this library; if not, write to the Free Software 493 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 494 | 495 | ---------------------------------------------------------------------- 496 | 497 | GNU LESSER GENERAL PUBLIC LICENSE 498 | Version 2.1, February 1999 499 | 500 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 501 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 502 | Everyone is permitted to copy and distribute verbatim copies 503 | of this license document, but changing it is not allowed. 504 | 505 | [This is the first released version of the Lesser GPL. It also counts 506 | as the successor of the GNU Library Public License, version 2, hence 507 | the version number 2.1.] 508 | 509 | Preamble 510 | 511 | The licenses for most software are designed to take away your 512 | freedom to share and change it. By contrast, the GNU General Public 513 | Licenses are intended to guarantee your freedom to share and change 514 | free software--to make sure the software is free for all its users. 515 | 516 | This license, the Lesser General Public License, applies to some 517 | specially designated software packages--typically libraries--of the 518 | Free Software Foundation and other authors who decide to use it. You 519 | can use it too, but we suggest you first think carefully about whether 520 | this license or the ordinary General Public License is the better 521 | strategy to use in any particular case, based on the explanations below. 522 | 523 | When we speak of free software, we are referring to freedom of use, 524 | not price. Our General Public Licenses are designed to make sure that 525 | you have the freedom to distribute copies of free software (and charge 526 | for this service if you wish); that you receive source code or can get 527 | it if you want it; that you can change the software and use pieces of 528 | it in new free programs; and that you are informed that you can do 529 | these things. 530 | 531 | To protect your rights, we need to make restrictions that forbid 532 | distributors to deny you these rights or to ask you to surrender these 533 | rights. These restrictions translate to certain responsibilities for 534 | you if you distribute copies of the library or if you modify it. 535 | 536 | For example, if you distribute copies of the library, whether gratis 537 | or for a fee, you must give the recipients all the rights that we gave 538 | you. You must make sure that they, too, receive or can get the source 539 | code. If you link other code with the library, you must provide 540 | complete object files to the recipients, so that they can relink them 541 | with the library after making changes to the library and recompiling 542 | it. And you must show them these terms so they know their rights. 543 | 544 | We protect your rights with a two-step method: (1) we copyright the 545 | library, and (2) we offer you this license, which gives you legal 546 | permission to copy, distribute and/or modify the library. 547 | 548 | To protect each distributor, we want to make it very clear that 549 | there is no warranty for the free library. Also, if the library is 550 | modified by someone else and passed on, the recipients should know 551 | that what they have is not the original version, so that the original 552 | author's reputation will not be affected by problems that might be 553 | introduced by others. 554 | 555 | Finally, software patents pose a constant threat to the existence of 556 | any free program. We wish to make sure that a company cannot 557 | effectively restrict the users of a free program by obtaining a 558 | restrictive license from a patent holder. Therefore, we insist that 559 | any patent license obtained for a version of the library must be 560 | consistent with the full freedom of use specified in this license. 561 | 562 | Most GNU software, including some libraries, is covered by the 563 | ordinary GNU General Public License. This license, the GNU Lesser 564 | General Public License, applies to certain designated libraries, and 565 | is quite different from the ordinary General Public License. We use 566 | this license for certain libraries in order to permit linking those 567 | libraries into non-free programs. 568 | 569 | When a program is linked with a library, whether statically or using 570 | a shared library, the combination of the two is legally speaking a 571 | combined work, a derivative of the original library. The ordinary 572 | General Public License therefore permits such linking only if the 573 | entire combination fits its criteria of freedom. The Lesser General 574 | Public License permits more lax criteria for linking other code with 575 | the library. 576 | 577 | We call this license the "Lesser" General Public License because it 578 | does Less to protect the user's freedom than the ordinary General 579 | Public License. It also provides other free software developers Less 580 | of an advantage over competing non-free programs. These disadvantages 581 | are the reason we use the ordinary General Public License for many 582 | libraries. However, the Lesser license provides advantages in certain 583 | special circumstances. 584 | 585 | For example, on rare occasions, there may be a special need to 586 | encourage the widest possible use of a certain library, so that it becomes 587 | a de-facto standard. To achieve this, non-free programs must be 588 | allowed to use the library. A more frequent case is that a free 589 | library does the same job as widely used non-free libraries. In this 590 | case, there is little to gain by limiting the free library to free 591 | software only, so we use the Lesser General Public License. 592 | 593 | In other cases, permission to use a particular library in non-free 594 | programs enables a greater number of people to use a large body of 595 | free software. For example, permission to use the GNU C Library in 596 | non-free programs enables many more people to use the whole GNU 597 | operating system, as well as its variant, the GNU/Linux operating 598 | system. 599 | 600 | Although the Lesser General Public License is Less protective of the 601 | users' freedom, it does ensure that the user of a program that is 602 | linked with the Library has the freedom and the wherewithal to run 603 | that program using a modified version of the Library. 604 | 605 | The precise terms and conditions for copying, distribution and 606 | modification follow. Pay close attention to the difference between a 607 | "work based on the library" and a "work that uses the library". The 608 | former contains code derived from the library, whereas the latter must 609 | be combined with the library in order to run. 610 | 611 | GNU LESSER GENERAL PUBLIC LICENSE 612 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 613 | 614 | 0. This License Agreement applies to any software library or other 615 | program which contains a notice placed by the copyright holder or 616 | other authorized party saying it may be distributed under the terms of 617 | this Lesser General Public License (also called "this License"). 618 | Each licensee is addressed as "you". 619 | 620 | A "library" means a collection of software functions and/or data 621 | prepared so as to be conveniently linked with application programs 622 | (which use some of those functions and data) to form executables. 623 | 624 | The "Library", below, refers to any such software library or work 625 | which has been distributed under these terms. A "work based on the 626 | Library" means either the Library or any derivative work under 627 | copyright law: that is to say, a work containing the Library or a 628 | portion of it, either verbatim or with modifications and/or translated 629 | straightforwardly into another language. (Hereinafter, translation is 630 | included without limitation in the term "modification".) 631 | 632 | "Source code" for a work means the preferred form of the work for 633 | making modifications to it. For a library, complete source code means 634 | all the source code for all modules it contains, plus any associated 635 | interface definition files, plus the scripts used to control compilation 636 | and installation of the library. 637 | 638 | Activities other than copying, distribution and modification are not 639 | covered by this License; they are outside its scope. The act of 640 | running a program using the Library is not restricted, and output from 641 | such a program is covered only if its contents constitute a work based 642 | on the Library (independent of the use of the Library in a tool for 643 | writing it). Whether that is true depends on what the Library does 644 | and what the program that uses the Library does. 645 | 646 | 1. You may copy and distribute verbatim copies of the Library's 647 | complete source code as you receive it, in any medium, provided that 648 | you conspicuously and appropriately publish on each copy an 649 | appropriate copyright notice and disclaimer of warranty; keep intact 650 | all the notices that refer to this License and to the absence of any 651 | warranty; and distribute a copy of this License along with the 652 | Library. 653 | 654 | You may charge a fee for the physical act of transferring a copy, 655 | and you may at your option offer warranty protection in exchange for a 656 | fee. 657 | 658 | 2. You may modify your copy or copies of the Library or any portion 659 | of it, thus forming a work based on the Library, and copy and 660 | distribute such modifications or work under the terms of Section 1 661 | above, provided that you also meet all of these conditions: 662 | 663 | a) The modified work must itself be a software library. 664 | 665 | b) You must cause the files modified to carry prominent notices 666 | stating that you changed the files and the date of any change. 667 | 668 | c) You must cause the whole of the work to be licensed at no 669 | charge to all third parties under the terms of this License. 670 | 671 | d) If a facility in the modified Library refers to a function or a 672 | table of data to be supplied by an application program that uses 673 | the facility, other than as an argument passed when the facility 674 | is invoked, then you must make a good faith effort to ensure that, 675 | in the event an application does not supply such function or 676 | table, the facility still operates, and performs whatever part of 677 | its purpose remains meaningful. 678 | 679 | (For example, a function in a library to compute square roots has 680 | a purpose that is entirely well-defined independent of the 681 | application. Therefore, Subsection 2d requires that any 682 | application-supplied function or table used by this function must 683 | be optional: if the application does not supply it, the square 684 | root function must still compute square roots.) 685 | 686 | These requirements apply to the modified work as a whole. If 687 | identifiable sections of that work are not derived from the Library, 688 | and can be reasonably considered independent and separate works in 689 | themselves, then this License, and its terms, do not apply to those 690 | sections when you distribute them as separate works. But when you 691 | distribute the same sections as part of a whole which is a work based 692 | on the Library, the distribution of the whole must be on the terms of 693 | this License, whose permissions for other licensees extend to the 694 | entire whole, and thus to each and every part regardless of who wrote 695 | it. 696 | 697 | Thus, it is not the intent of this section to claim rights or contest 698 | your rights to work written entirely by you; rather, the intent is to 699 | exercise the right to control the distribution of derivative or 700 | collective works based on the Library. 701 | 702 | In addition, mere aggregation of another work not based on the Library 703 | with the Library (or with a work based on the Library) on a volume of 704 | a storage or distribution medium does not bring the other work under 705 | the scope of this License. 706 | 707 | 3. You may opt to apply the terms of the ordinary GNU General Public 708 | License instead of this License to a given copy of the Library. To do 709 | this, you must alter all the notices that refer to this License, so 710 | that they refer to the ordinary GNU General Public License, version 2, 711 | instead of to this License. (If a newer version than version 2 of the 712 | ordinary GNU General Public License has appeared, then you can specify 713 | that version instead if you wish.) Do not make any other change in 714 | these notices. 715 | 716 | Once this change is made in a given copy, it is irreversible for 717 | that copy, so the ordinary GNU General Public License applies to all 718 | subsequent copies and derivative works made from that copy. 719 | 720 | This option is useful when you wish to copy part of the code of 721 | the Library into a program that is not a library. 722 | 723 | 4. You may copy and distribute the Library (or a portion or 724 | derivative of it, under Section 2) in object code or executable form 725 | under the terms of Sections 1 and 2 above provided that you accompany 726 | it with the complete corresponding machine-readable source code, which 727 | must be distributed under the terms of Sections 1 and 2 above on a 728 | medium customarily used for software interchange. 729 | 730 | If distribution of object code is made by offering access to copy 731 | from a designated place, then offering equivalent access to copy the 732 | source code from the same place satisfies the requirement to 733 | distribute the source code, even though third parties are not 734 | compelled to copy the source along with the object code. 735 | 736 | 5. A program that contains no derivative of any portion of the 737 | Library, but is designed to work with the Library by being compiled or 738 | linked with it, is called a "work that uses the Library". Such a 739 | work, in isolation, is not a derivative work of the Library, and 740 | therefore falls outside the scope of this License. 741 | 742 | However, linking a "work that uses the Library" with the Library 743 | creates an executable that is a derivative of the Library (because it 744 | contains portions of the Library), rather than a "work that uses the 745 | library". The executable is therefore covered by this License. 746 | Section 6 states terms for distribution of such executables. 747 | 748 | When a "work that uses the Library" uses material from a header file 749 | that is part of the Library, the object code for the work may be a 750 | derivative work of the Library even though the source code is not. 751 | Whether this is true is especially significant if the work can be 752 | linked without the Library, or if the work is itself a library. The 753 | threshold for this to be true is not precisely defined by law. 754 | 755 | If such an object file uses only numerical parameters, data 756 | structure layouts and accessors, and small macros and small inline 757 | functions (ten lines or less in length), then the use of the object 758 | file is unrestricted, regardless of whether it is legally a derivative 759 | work. (Executables containing this object code plus portions of the 760 | Library will still fall under Section 6.) 761 | 762 | Otherwise, if the work is a derivative of the Library, you may 763 | distribute the object code for the work under the terms of Section 6. 764 | Any executables containing that work also fall under Section 6, 765 | whether or not they are linked directly with the Library itself. 766 | 767 | 6. As an exception to the Sections above, you may also combine or 768 | link a "work that uses the Library" with the Library to produce a 769 | work containing portions of the Library, and distribute that work 770 | under terms of your choice, provided that the terms permit 771 | modification of the work for the customer's own use and reverse 772 | engineering for debugging such modifications. 773 | 774 | You must give prominent notice with each copy of the work that the 775 | Library is used in it and that the Library and its use are covered by 776 | this License. You must supply a copy of this License. If the work 777 | during execution displays copyright notices, you must include the 778 | copyright notice for the Library among them, as well as a reference 779 | directing the user to the copy of this License. Also, you must do one 780 | of these things: 781 | 782 | a) Accompany the work with the complete corresponding 783 | machine-readable source code for the Library including whatever 784 | changes were used in the work (which must be distributed under 785 | Sections 1 and 2 above); and, if the work is an executable linked 786 | with the Library, with the complete machine-readable "work that 787 | uses the Library", as object code and/or source code, so that the 788 | user can modify the Library and then relink to produce a modified 789 | executable containing the modified Library. (It is understood 790 | that the user who changes the contents of definitions files in the 791 | Library will not necessarily be able to recompile the application 792 | to use the modified definitions.) 793 | 794 | b) Use a suitable shared library mechanism for linking with the 795 | Library. A suitable mechanism is one that (1) uses at run time a 796 | copy of the library already present on the user's computer system, 797 | rather than copying library functions into the executable, and (2) 798 | will operate properly with a modified version of the library, if 799 | the user installs one, as long as the modified version is 800 | interface-compatible with the version that the work was made with. 801 | 802 | c) Accompany the work with a written offer, valid for at 803 | least three years, to give the same user the materials 804 | specified in Subsection 6a, above, for a charge no more 805 | than the cost of performing this distribution. 806 | 807 | d) If distribution of the work is made by offering access to copy 808 | from a designated place, offer equivalent access to copy the above 809 | specified materials from the same place. 810 | 811 | e) Verify that the user has already received a copy of these 812 | materials or that you have already sent this user a copy. 813 | 814 | For an executable, the required form of the "work that uses the 815 | Library" must include any data and utility programs needed for 816 | reproducing the executable from it. However, as a special exception, 817 | the materials to be distributed need not include anything that is 818 | normally distributed (in either source or binary form) with the major 819 | components (compiler, kernel, and so on) of the operating system on 820 | which the executable runs, unless that component itself accompanies 821 | the executable. 822 | 823 | It may happen that this requirement contradicts the license 824 | restrictions of other proprietary libraries that do not normally 825 | accompany the operating system. Such a contradiction means you cannot 826 | use both them and the Library together in an executable that you 827 | distribute. 828 | 829 | 7. You may place library facilities that are a work based on the 830 | Library side-by-side in a single library together with other library 831 | facilities not covered by this License, and distribute such a combined 832 | library, provided that the separate distribution of the work based on 833 | the Library and of the other library facilities is otherwise 834 | permitted, and provided that you do these two things: 835 | 836 | a) Accompany the combined library with a copy of the same work 837 | based on the Library, uncombined with any other library 838 | facilities. This must be distributed under the terms of the 839 | Sections above. 840 | 841 | b) Give prominent notice with the combined library of the fact 842 | that part of it is a work based on the Library, and explaining 843 | where to find the accompanying uncombined form of the same work. 844 | 845 | 8. You may not copy, modify, sublicense, link with, or distribute 846 | the Library except as expressly provided under this License. Any 847 | attempt otherwise to copy, modify, sublicense, link with, or 848 | distribute the Library is void, and will automatically terminate your 849 | rights under this License. However, parties who have received copies, 850 | or rights, from you under this License will not have their licenses 851 | terminated so long as such parties remain in full compliance. 852 | 853 | 9. You are not required to accept this License, since you have not 854 | signed it. However, nothing else grants you permission to modify or 855 | distribute the Library or its derivative works. These actions are 856 | prohibited by law if you do not accept this License. Therefore, by 857 | modifying or distributing the Library (or any work based on the 858 | Library), you indicate your acceptance of this License to do so, and 859 | all its terms and conditions for copying, distributing or modifying 860 | the Library or works based on it. 861 | 862 | 10. Each time you redistribute the Library (or any work based on the 863 | Library), the recipient automatically receives a license from the 864 | original licensor to copy, distribute, link with or modify the Library 865 | subject to these terms and conditions. You may not impose any further 866 | restrictions on the recipients' exercise of the rights granted herein. 867 | You are not responsible for enforcing compliance by third parties with 868 | this License. 869 | 870 | 11. If, as a consequence of a court judgment or allegation of patent 871 | infringement or for any other reason (not limited to patent issues), 872 | conditions are imposed on you (whether by court order, agreement or 873 | otherwise) that contradict the conditions of this License, they do not 874 | excuse you from the conditions of this License. If you cannot 875 | distribute so as to satisfy simultaneously your obligations under this 876 | License and any other pertinent obligations, then as a consequence you 877 | may not distribute the Library at all. For example, if a patent 878 | license would not permit royalty-free redistribution of the Library by 879 | all those who receive copies directly or indirectly through you, then 880 | the only way you could satisfy both it and this License would be to 881 | refrain entirely from distribution of the Library. 882 | 883 | If any portion of this section is held invalid or unenforceable under any 884 | particular circumstance, the balance of the section is intended to apply, 885 | and the section as a whole is intended to apply in other circumstances. 886 | 887 | It is not the purpose of this section to induce you to infringe any 888 | patents or other property right claims or to contest validity of any 889 | such claims; this section has the sole purpose of protecting the 890 | integrity of the free software distribution system which is 891 | implemented by public license practices. Many people have made 892 | generous contributions to the wide range of software distributed 893 | through that system in reliance on consistent application of that 894 | system; it is up to the author/donor to decide if he or she is willing 895 | to distribute software through any other system and a licensee cannot 896 | impose that choice. 897 | 898 | This section is intended to make thoroughly clear what is believed to 899 | be a consequence of the rest of this License. 900 | 901 | 12. If the distribution and/or use of the Library is restricted in 902 | certain countries either by patents or by copyrighted interfaces, the 903 | original copyright holder who places the Library under this License may add 904 | an explicit geographical distribution limitation excluding those countries, 905 | so that distribution is permitted only in or among countries not thus 906 | excluded. In such case, this License incorporates the limitation as if 907 | written in the body of this License. 908 | 909 | 13. The Free Software Foundation may publish revised and/or new 910 | versions of the Lesser General Public License from time to time. 911 | Such new versions will be similar in spirit to the present version, 912 | but may differ in detail to address new problems or concerns. 913 | 914 | Each version is given a distinguishing version number. If the Library 915 | specifies a version number of this License which applies to it and 916 | "any later version", you have the option of following the terms and 917 | conditions either of that version or of any later version published by 918 | the Free Software Foundation. If the Library does not specify a 919 | license version number, you may choose any version ever published by 920 | the Free Software Foundation. 921 | 922 | 14. If you wish to incorporate parts of the Library into other free 923 | programs whose distribution conditions are incompatible with these, 924 | write to the author to ask for permission. For software which is 925 | copyrighted by the Free Software Foundation, write to the Free 926 | Software Foundation; we sometimes make exceptions for this. Our 927 | decision will be guided by the two goals of preserving the free status 928 | of all derivatives of our free software and of promoting the sharing 929 | and reuse of software generally. 930 | 931 | NO WARRANTY 932 | 933 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 934 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 935 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 936 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 937 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 938 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 939 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 940 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 941 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 942 | 943 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 944 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 945 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 946 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 947 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 948 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 949 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 950 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 951 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 952 | DAMAGES. 953 | 954 | END OF TERMS AND CONDITIONS 955 | 956 | How to Apply These Terms to Your New Libraries 957 | 958 | If you develop a new library, and you want it to be of the greatest 959 | possible use to the public, we recommend making it free software that 960 | everyone can redistribute and change. You can do so by permitting 961 | redistribution under these terms (or, alternatively, under the terms of the 962 | ordinary General Public License). 963 | 964 | To apply these terms, attach the following notices to the library. It is 965 | safest to attach them to the start of each source file to most effectively 966 | convey the exclusion of warranty; and each file should have at least the 967 | "copyright" line and a pointer to where the full notice is found. 968 | 969 | 970 | Copyright (C) 971 | 972 | This library is free software; you can redistribute it and/or 973 | modify it under the terms of the GNU Lesser General Public 974 | License as published by the Free Software Foundation; either 975 | version 2.1 of the License, or (at your option) any later version. 976 | 977 | This library is distributed in the hope that it will be useful, 978 | but WITHOUT ANY WARRANTY; without even the implied warranty of 979 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 980 | Lesser General Public License for more details. 981 | 982 | You should have received a copy of the GNU Lesser General Public 983 | License along with this library; if not, write to the Free Software 984 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 985 | 986 | Also add information on how to contact you by electronic and paper mail. 987 | 988 | You should also get your employer (if you work as a programmer) or your 989 | school, if any, to sign a "copyright disclaimer" for the library, if 990 | necessary. Here is a sample; alter the names: 991 | 992 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 993 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 994 | 995 | , 1 April 1990 996 | Ty Coon, President of Vice 997 | 998 | That's all there is to it! 999 | 1000 | ---------------------------------------------------------------------- 1001 | 1002 | The bundled SHA1 collision detection code is licensed under the MIT license: 1003 | 1004 | MIT License 1005 | 1006 | Copyright (c) 2017: 1007 | Marc Stevens 1008 | Cryptology Group 1009 | Centrum Wiskunde & Informatica 1010 | P.O. Box 94079, 1090 GB Amsterdam, Netherlands 1011 | marc@marc-stevens.nl 1012 | 1013 | Dan Shumow 1014 | Microsoft Research 1015 | danshu@microsoft.com 1016 | 1017 | Permission is hereby granted, free of charge, to any person obtaining a copy 1018 | of this software and associated documentation files (the "Software"), to deal 1019 | in the Software without restriction, including without limitation the rights 1020 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1021 | copies of the Software, and to permit persons to whom the Software is 1022 | furnished to do so, subject to the following conditions: 1023 | 1024 | The above copyright notice and this permission notice shall be included in all 1025 | copies or substantial portions of the Software. 1026 | 1027 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1028 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1029 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1030 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1031 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1032 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1033 | SOFTWARE. 1034 | 1035 | ---------------------------------------------------------------------- 1036 | 1037 | The bundled wildmatch code is licensed under the BSD license: 1038 | 1039 | Copyright Rich Salz. 1040 | All rights reserved. 1041 | 1042 | Redistribution and use in any form are permitted provided that the 1043 | following restrictions are are met: 1044 | 1045 | 1. Source distributions must retain this entire copyright notice 1046 | and comment. 1047 | 2. Binary distributions must include the acknowledgement ``This 1048 | product includes software developed by Rich Salz'' in the 1049 | documentation or other materials provided with the 1050 | distribution. This must not be represented as an endorsement 1051 | or promotion without specific prior written permission. 1052 | 3. The origin of this software must not be misrepresented, either 1053 | by explicit claim or by omission. Credits must appear in the 1054 | source and documentation. 1055 | 4. Altered versions must be plainly marked as such in the source 1056 | and documentation and must not be misrepresented as being the 1057 | original software. 1058 | 1059 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1060 | WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1061 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1062 | 1063 | ---------------------------------------------------------------------- 1064 | 1065 | Portions of the OpenSSL headers are included under the OpenSSL license: 1066 | 1067 | Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 1068 | All rights reserved. 1069 | 1070 | This package is an SSL implementation written 1071 | by Eric Young (eay@cryptsoft.com). 1072 | The implementation was written so as to conform with Netscapes SSL. 1073 | 1074 | This library is free for commercial and non-commercial use as long as 1075 | the following conditions are aheared to. The following conditions 1076 | apply to all code found in this distribution, be it the RC4, RSA, 1077 | lhash, DES, etc., code; not just the SSL code. The SSL documentation 1078 | included with this distribution is covered by the same copyright terms 1079 | except that the holder is Tim Hudson (tjh@cryptsoft.com). 1080 | 1081 | Copyright remains Eric Young's, and as such any Copyright notices in 1082 | the code are not to be removed. 1083 | If this package is used in a product, Eric Young should be given attribution 1084 | as the author of the parts of the library used. 1085 | This can be in the form of a textual message at program startup or 1086 | in documentation (online or textual) provided with the package. 1087 | 1088 | Redistribution and use in source and binary forms, with or without 1089 | modification, are permitted provided that the following conditions 1090 | are met: 1091 | 1. Redistributions of source code must retain the copyright 1092 | notice, this list of conditions and the following disclaimer. 1093 | 2. Redistributions in binary form must reproduce the above copyright 1094 | notice, this list of conditions and the following disclaimer in the 1095 | documentation and/or other materials provided with the distribution. 1096 | 3. All advertising materials mentioning features or use of this software 1097 | must display the following acknowledgement: 1098 | "This product includes cryptographic software written by 1099 | Eric Young (eay@cryptsoft.com)" 1100 | The word 'cryptographic' can be left out if the rouines from the library 1101 | being used are not cryptographic related :-). 1102 | 4. If you include any Windows specific code (or a derivative thereof) from 1103 | the apps directory (application code) you must include an acknowledgement: 1104 | "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 1105 | 1106 | THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 1107 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1108 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1109 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1110 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1111 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1112 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1113 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1114 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1115 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1116 | SUCH DAMAGE. 1117 | 1118 | The licence and distribution terms for any publically available version or 1119 | derivative of this code cannot be changed. i.e. this code cannot simply be 1120 | copied and put under another distribution licence 1121 | [including the GNU Public Licence.] 1122 | 1123 | ==================================================================== 1124 | Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. 1125 | 1126 | Redistribution and use in source and binary forms, with or without 1127 | modification, are permitted provided that the following conditions 1128 | are met: 1129 | 1130 | 1. Redistributions of source code must retain the above copyright 1131 | notice, this list of conditions and the following disclaimer. 1132 | 1133 | 2. Redistributions in binary form must reproduce the above copyright 1134 | notice, this list of conditions and the following disclaimer in 1135 | the documentation and/or other materials provided with the 1136 | distribution. 1137 | 1138 | 3. All advertising materials mentioning features or use of this 1139 | software must display the following acknowledgment: 1140 | "This product includes software developed by the OpenSSL Project 1141 | for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 1142 | 1143 | 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 1144 | endorse or promote products derived from this software without 1145 | prior written permission. For written permission, please contact 1146 | openssl-core@openssl.org. 1147 | 1148 | 5. Products derived from this software may not be called "OpenSSL" 1149 | nor may "OpenSSL" appear in their names without prior written 1150 | permission of the OpenSSL Project. 1151 | 1152 | 6. Redistributions of any form whatsoever must retain the following 1153 | acknowledgment: 1154 | "This product includes software developed by the OpenSSL Project 1155 | for use in the OpenSSL Toolkit (http://www.openssl.org/)" 1156 | 1157 | THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 1158 | EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1159 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1160 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 1161 | ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1162 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1163 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1164 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1165 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 1166 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1167 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 1168 | OF THE POSSIBILITY OF SUCH DAMAGE. 1169 | ``` 1170 | 1171 | ### libssh2/libssh2 1172 | 1173 | ``` 1174 | /* Copyright (c) 2004-2007 Sara Golemon 1175 | * Copyright (c) 2005,2006 Mikhail Gusarov 1176 | * Copyright (c) 2006-2007 The Written Word, Inc. 1177 | * Copyright (c) 2007 Eli Fant 1178 | * Copyright (c) 2009-2021 Daniel Stenberg 1179 | * Copyright (C) 2008, 2009 Simon Josefsson 1180 | * Copyright (c) 2000 Markus Friedl 1181 | * Copyright (c) 2015 Microsoft Corp. 1182 | * All rights reserved. 1183 | * 1184 | * Redistribution and use in source and binary forms, 1185 | * with or without modification, are permitted provided 1186 | * that the following conditions are met: 1187 | * 1188 | * Redistributions of source code must retain the above 1189 | * copyright notice, this list of conditions and the 1190 | * following disclaimer. 1191 | * 1192 | * Redistributions in binary form must reproduce the above 1193 | * copyright notice, this list of conditions and the following 1194 | * disclaimer in the documentation and/or other materials 1195 | * provided with the distribution. 1196 | * 1197 | * Neither the name of the copyright holder nor the names 1198 | * of any other contributors may be used to endorse or 1199 | * promote products derived from this software without 1200 | * specific prior written permission. 1201 | * 1202 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 1203 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 1204 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1205 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1206 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 1207 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1208 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 1209 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 1210 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1211 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 1212 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 1213 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 1214 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 1215 | * OF SUCH DAMAGE. 1216 | */ 1217 | ``` 1218 | 1219 | ### OpenSSL 1220 | 1221 | ``` 1222 | 1223 | LICENSE ISSUES 1224 | ============== 1225 | 1226 | The OpenSSL toolkit stays under a double license, i.e. both the conditions of 1227 | the OpenSSL License and the original SSLeay license apply to the toolkit. 1228 | See below for the actual license texts. 1229 | 1230 | OpenSSL License 1231 | --------------- 1232 | 1233 | /* ==================================================================== 1234 | * Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved. 1235 | * 1236 | * Redistribution and use in source and binary forms, with or without 1237 | * modification, are permitted provided that the following conditions 1238 | * are met: 1239 | * 1240 | * 1. Redistributions of source code must retain the above copyright 1241 | * notice, this list of conditions and the following disclaimer. 1242 | * 1243 | * 2. Redistributions in binary form must reproduce the above copyright 1244 | * notice, this list of conditions and the following disclaimer in 1245 | * the documentation and/or other materials provided with the 1246 | * distribution. 1247 | * 1248 | * 3. All advertising materials mentioning features or use of this 1249 | * software must display the following acknowledgment: 1250 | * "This product includes software developed by the OpenSSL Project 1251 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 1252 | * 1253 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 1254 | * endorse or promote products derived from this software without 1255 | * prior written permission. For written permission, please contact 1256 | * openssl-core@openssl.org. 1257 | * 1258 | * 5. Products derived from this software may not be called "OpenSSL" 1259 | * nor may "OpenSSL" appear in their names without prior written 1260 | * permission of the OpenSSL Project. 1261 | * 1262 | * 6. Redistributions of any form whatsoever must retain the following 1263 | * acknowledgment: 1264 | * "This product includes software developed by the OpenSSL Project 1265 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 1266 | * 1267 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 1268 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1269 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1270 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 1271 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1272 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1273 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1274 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1275 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 1276 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1277 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 1278 | * OF THE POSSIBILITY OF SUCH DAMAGE. 1279 | * ==================================================================== 1280 | * 1281 | * This product includes cryptographic software written by Eric Young 1282 | * (eay@cryptsoft.com). This product includes software written by Tim 1283 | * Hudson (tjh@cryptsoft.com). 1284 | * 1285 | */ 1286 | 1287 | Original SSLeay License 1288 | ----------------------- 1289 | 1290 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 1291 | * All rights reserved. 1292 | * 1293 | * This package is an SSL implementation written 1294 | * by Eric Young (eay@cryptsoft.com). 1295 | * The implementation was written so as to conform with Netscapes SSL. 1296 | * 1297 | * This library is free for commercial and non-commercial use as long as 1298 | * the following conditions are aheared to. The following conditions 1299 | * apply to all code found in this distribution, be it the RC4, RSA, 1300 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1301 | * included with this distribution is covered by the same copyright terms 1302 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1303 | * 1304 | * Copyright remains Eric Young's, and as such any Copyright notices in 1305 | * the code are not to be removed. 1306 | * If this package is used in a product, Eric Young should be given attribution 1307 | * as the author of the parts of the library used. 1308 | * This can be in the form of a textual message at program startup or 1309 | * in documentation (online or textual) provided with the package. 1310 | * 1311 | * Redistribution and use in source and binary forms, with or without 1312 | * modification, are permitted provided that the following conditions 1313 | * are met: 1314 | * 1. Redistributions of source code must retain the copyright 1315 | * notice, this list of conditions and the following disclaimer. 1316 | * 2. Redistributions in binary form must reproduce the above copyright 1317 | * notice, this list of conditions and the following disclaimer in the 1318 | * documentation and/or other materials provided with the distribution. 1319 | * 3. All advertising materials mentioning features or use of this software 1320 | * must display the following acknowledgement: 1321 | * "This product includes cryptographic software written by 1322 | * Eric Young (eay@cryptsoft.com)" 1323 | * The word 'cryptographic' can be left out if the rouines from the library 1324 | * being used are not cryptographic related :-). 1325 | * 4. If you include any Windows specific code (or a derivative thereof) from 1326 | * the apps directory (application code) you must include an acknowledgement: 1327 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 1328 | * 1329 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 1330 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1331 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1332 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1333 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1334 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1335 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1336 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1337 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1338 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1339 | * SUCH DAMAGE. 1340 | * 1341 | * The licence and distribution terms for any publically available version or 1342 | * derivative of this code cannot be changed. i.e. this code cannot simply be 1343 | * copied and put under another distribution licence 1344 | * [including the GNU Public Licence.] 1345 | */ 1346 | ``` 1347 | -------------------------------------------------------------------------------- /addons/godot-git-plugin/git_plugin.gdextension: -------------------------------------------------------------------------------- 1 | [configuration] 2 | 3 | entry_symbol = "git_plugin_init" 4 | compatibility_minimum = "4.2.0" 5 | 6 | [libraries] 7 | 8 | linux.editor.x86_64 = "linux/libgit_plugin.linux.editor.x86_64.so" 9 | macos.editor = "macos/libgit_plugin.macos.editor.universal.dylib" 10 | windows.editor.x86_64 = "windows/libgit_plugin.windows.editor.x86_64.dll" 11 | -------------------------------------------------------------------------------- /godot-git-plugin/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = tab 7 | insert_final_newline = true 8 | 9 | [*.{cpp,hpp,c,h,mm}] 10 | trim_trailing_whitespace = true 11 | 12 | [{*.{py,cs},SConstruct,SCsub}] 13 | indent_style = space 14 | indent_size = 4 15 | 16 | [.travis.yml] 17 | indent_style = space 18 | indent_size = 2 19 | -------------------------------------------------------------------------------- /godot-git-plugin/SCsub: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | env = {} 6 | Import("env") 7 | Import("ssl") 8 | 9 | env["target_path"] = "../" + env["target_path"] 10 | 11 | if not os.path.isdir(env["target_path"]): 12 | os.mkdir(env["target_path"]) 13 | 14 | # Check our platform specifics 15 | env["target_path"] += env["platform"] + "/" 16 | 17 | if env["platform"] == "macos": 18 | if env["macos_deployment_target"] != "default": 19 | env.Append(CCFLAGS=["-mmacosx-version-min=" + 20 | env["macos_deployment_target"]]) 21 | env.Append(LINKFLAGS=["-mmacosx-version-min=" + 22 | env["macos_deployment_target"]]) 23 | elif env["platform"] == "windows": 24 | env.Append(LIBS=["advapi32", "winhttp", "rpcrt4", "crypt32", 25 | "ole32", "user32", "wsock32", "ws2_32", "bcrypt"]) 26 | 27 | env.Append(CPPPATH=[".", "src/"]) 28 | 29 | env.Append(CPPPATH=["#thirdparty/git2/libgit2/include/"]) 30 | 31 | lib_sources = Glob("src/*.cpp") 32 | env.Depends(lib_sources, ssl) 33 | library = env.SharedLibrary( 34 | target=env["target_path"] + 35 | "{}{}{}".format(env["target_name"], env["suffix"], env["SHLIBSUFFIX"]), 36 | source=lib_sources 37 | ) 38 | Default(library) 39 | -------------------------------------------------------------------------------- /godot-git-plugin/cpp.hint: -------------------------------------------------------------------------------- 1 | // Hint files help the Visual Studio IDE interpret Visual C++ identifiers 2 | // such as names of functions and macros. 3 | // For more information see https://go.microsoft.com/fwlink/?linkid=865984 4 | #define GODOT_CLASS(Name, Base) public: inline static const char *___get_type_name() { return static_cast(#Name); } enum { ___CLASS_IS_SCRIPT = 1, }; inline static Name *_new() { godot::NativeScript *script = godot::NativeScript::_new(); script->set_library(godot::get_wrapper((godot_object *)godot::gdnlib)); script->set_class_name(#Name); Name *instance = godot::as(script->new_()); return instance; } inline static size_t ___get_id() { return typeid(Name).hash_code(); } inline static size_t ___get_base_id() { return typeid(Base).hash_code(); } inline static const char *___get_base_type_name() { return Base::___get_class_name(); } inline static Object *___get_from_variant(godot::Variant a) { return (godot::Object *)godot::as(godot::Object::___get_from_variant(a)); } private: 5 | -------------------------------------------------------------------------------- /godot-git-plugin/src/.clang-format: -------------------------------------------------------------------------------- 1 | # Commented out parameters are those with the same value as base LLVM style 2 | # We can uncomment them if we want to change their value, or enforce the 3 | # chosen value in case the base style changes (last sync: Clang 6.0.1). 4 | --- 5 | ### General config, applies to all languages ### 6 | BasedOnStyle: LLVM 7 | AccessModifierOffset: -4 8 | AlignAfterOpenBracket: DontAlign 9 | # AlignConsecutiveAssignments: false 10 | # AlignConsecutiveDeclarations: false 11 | # AlignEscapedNewlines: Right 12 | # AlignOperands: true 13 | AlignTrailingComments: false 14 | AllowAllParametersOfDeclarationOnNextLine: false 15 | # AllowShortBlocksOnASingleLine: false 16 | # AllowShortCaseLabelsOnASingleLine: false 17 | AllowShortFunctionsOnASingleLine: Inline 18 | # AllowShortIfStatementsOnASingleLine: false 19 | # AllowShortLoopsOnASingleLine: false 20 | # AlwaysBreakAfterDefinitionReturnType: None 21 | # AlwaysBreakAfterReturnType: None 22 | # AlwaysBreakBeforeMultilineStrings: false 23 | # AlwaysBreakTemplateDeclarations: false 24 | # BinPackArguments: true 25 | # BinPackParameters: true 26 | # BraceWrapping: 27 | # AfterClass: false 28 | # AfterControlStatement: false 29 | # AfterEnum: false 30 | # AfterFunction: false 31 | # AfterNamespace: false 32 | # AfterObjCDeclaration: false 33 | # AfterStruct: false 34 | # AfterUnion: false 35 | # AfterExternBlock: false 36 | # BeforeCatch: false 37 | # BeforeElse: false 38 | # IndentBraces: false 39 | # SplitEmptyFunction: true 40 | # SplitEmptyRecord: true 41 | # SplitEmptyNamespace: true 42 | # BreakBeforeBinaryOperators: None 43 | # BreakBeforeBraces: Attach 44 | # BreakBeforeInheritanceComma: false 45 | BreakBeforeTernaryOperators: false 46 | # BreakConstructorInitializersBeforeComma: false 47 | BreakConstructorInitializers: AfterColon 48 | # BreakStringLiterals: true 49 | ColumnLimit: 0 50 | # CommentPragmas: '^ IWYU pragma:' 51 | # CompactNamespaces: false 52 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 53 | ConstructorInitializerIndentWidth: 8 54 | ContinuationIndentWidth: 8 55 | Cpp11BracedListStyle: false 56 | # DerivePointerAlignment: false 57 | # DisableFormat: false 58 | # ExperimentalAutoDetectBinPacking: false 59 | # FixNamespaceComments: true 60 | # ForEachMacros: 61 | # - foreach 62 | # - Q_FOREACH 63 | # - BOOST_FOREACH 64 | # IncludeBlocks: Preserve 65 | IncludeCategories: 66 | - Regex: '".*"' 67 | Priority: 1 68 | - Regex: '^<.*\.h>' 69 | Priority: 2 70 | - Regex: "^<.*" 71 | Priority: 3 72 | # IncludeIsMainRegex: '(Test)?$' 73 | IndentCaseLabels: true 74 | # IndentPPDirectives: None 75 | IndentWidth: 4 76 | # IndentWrappedFunctionNames: false 77 | # JavaScriptQuotes: Leave 78 | # JavaScriptWrapImports: true 79 | KeepEmptyLinesAtTheStartOfBlocks: false 80 | # MacroBlockBegin: '' 81 | # MacroBlockEnd: '' 82 | # MaxEmptyLinesToKeep: 1 83 | # NamespaceIndentation: None 84 | # PenaltyBreakAssignment: 2 85 | # PenaltyBreakBeforeFirstCallParameter: 19 86 | # PenaltyBreakComment: 300 87 | # PenaltyBreakFirstLessLess: 120 88 | # PenaltyBreakString: 1000 89 | # PenaltyExcessCharacter: 1000000 90 | # PenaltyReturnTypeOnItsOwnLine: 60 91 | # PointerAlignment: Right 92 | # RawStringFormats: 93 | # - Delimiter: pb 94 | # Language: TextProto 95 | # BasedOnStyle: google 96 | # ReflowComments: true 97 | SortIncludes: false 98 | # SortUsingDeclarations: true 99 | # SpaceAfterCStyleCast: false 100 | # SpaceAfterTemplateKeyword: true 101 | # SpaceBeforeAssignmentOperators: true 102 | # SpaceBeforeParens: ControlStatements 103 | # SpaceInEmptyParentheses: false 104 | # SpacesBeforeTrailingComments: 1 105 | # SpacesInAngles: false 106 | # SpacesInContainerLiterals: true 107 | # SpacesInCStyleCastParentheses: false 108 | # SpacesInParentheses: false 109 | # SpacesInSquareBrackets: false 110 | TabWidth: 4 111 | UseTab: Always 112 | --- 113 | ### C++ specific config ### 114 | Language: Cpp 115 | Standard: Cpp11 116 | --- 117 | ### ObjC specific config ### 118 | Language: ObjC 119 | Standard: Cpp11 120 | ObjCBlockIndentWidth: 4 121 | # ObjCSpaceAfterProperty: false 122 | # ObjCSpaceBeforeProtocolList: true 123 | --- 124 | ### Java specific config ### 125 | Language: Java 126 | # BreakAfterJavaFieldAnnotations: false 127 | JavaImportGroups: 128 | [ 129 | "org.godotengine", 130 | "android", 131 | "androidx", 132 | "com.android", 133 | "com.google", 134 | "java", 135 | "javax", 136 | ] 137 | -------------------------------------------------------------------------------- /godot-git-plugin/src/gdlibrary.cpp: -------------------------------------------------------------------------------- 1 | #include "git_plugin.h" 2 | 3 | #include "godot_cpp/core/class_db.hpp" 4 | #include "godot_cpp/godot.hpp" 5 | 6 | void initialize_git_plugin_module(godot::ModuleInitializationLevel p_level) { 7 | if (p_level != godot::MODULE_INITIALIZATION_LEVEL_EDITOR) { 8 | return; 9 | } 10 | 11 | godot::ClassDB::register_class(); 12 | } 13 | 14 | void uninitialize_git_plugin_module(godot::ModuleInitializationLevel p_level) { 15 | if (p_level != godot::MODULE_INITIALIZATION_LEVEL_EDITOR) { 16 | return; 17 | } 18 | } 19 | 20 | extern "C" { 21 | 22 | GDExtensionBool GDE_EXPORT git_plugin_init(const GDExtensionInterfaceGetProcAddress p_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { 23 | godot::GDExtensionBinding::InitObject init_obj(p_address, p_library, r_initialization); 24 | 25 | init_obj.register_initializer(initialize_git_plugin_module); 26 | init_obj.register_terminator(uninitialize_git_plugin_module); 27 | init_obj.set_minimum_library_initialization_level(godot::MODULE_INITIALIZATION_LEVEL_EDITOR); 28 | 29 | return init_obj.init(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /godot-git-plugin/src/git_callbacks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "git_callbacks.h" 5 | #include "git_plugin.h" 6 | 7 | #include "godot_cpp/godot.hpp" 8 | #include "godot_cpp/variant/utility_functions.hpp" 9 | 10 | extern "C" int progress_cb(const char *str, int len, void *data) { 11 | (void)data; 12 | 13 | godot::UtilityFunctions::print("remote: ", godot::String::utf8(str, len).strip_edges()); 14 | 15 | return 0; 16 | } 17 | 18 | extern "C" int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data) { 19 | constexpr int short_commit_length = 8; 20 | char a_str[short_commit_length + 1]; 21 | char b_str[short_commit_length + 1]; 22 | (void)data; 23 | 24 | git_oid_tostr(b_str, short_commit_length, b); 25 | if (git_oid_is_zero(a)) { 26 | godot::UtilityFunctions::print("* [new] ", godot::String::utf8(b_str), " ", godot::String::utf8(refname)); 27 | } else { 28 | git_oid_tostr(a_str, short_commit_length, a); 29 | godot::UtilityFunctions::print("[updated] ", godot::String::utf8(a_str), "...", godot::String::utf8(b_str), " ", godot::String::utf8(refname)); 30 | } 31 | 32 | return 0; 33 | } 34 | 35 | extern "C" int transfer_progress_cb(const git_indexer_progress *stats, void *payload) { 36 | (void)payload; 37 | 38 | if (stats->received_objects == stats->total_objects) { 39 | godot::UtilityFunctions::print("Resolving deltas ", uint32_t(stats->indexed_deltas), "/", uint32_t(stats->total_deltas)); 40 | } else if (stats->total_objects > 0) { 41 | godot::UtilityFunctions::print( 42 | "Received ", uint32_t(stats->received_objects), "/", uint32_t(stats->total_objects), 43 | " objects (", uint32_t(stats->indexed_objects), ") in ", uint32_t(stats->received_bytes), " bytes"); 44 | } 45 | return 0; 46 | } 47 | 48 | extern "C" int fetchhead_foreach_cb(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload) { 49 | if (is_merge) { 50 | git_oid_cpy((git_oid *)payload, oid); 51 | } 52 | return 0; 53 | } 54 | 55 | extern "C" int push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void *payload) { 56 | int64_t progress = 100; 57 | 58 | if (total != 0) { 59 | progress = (current * 100) / total; 60 | } 61 | 62 | godot::UtilityFunctions::print("Writing Objects: ", uint32_t(progress), "% (", uint32_t(current), "/", uint32_t(total), ", ", uint32_t(bytes), " bytes done.)"); 63 | return 0; 64 | } 65 | 66 | extern "C" int push_update_reference_cb(const char *refname, const char *status, void *data) { 67 | if (status != NULL) { 68 | godot::String status_str = godot::String::utf8(status); 69 | godot::UtilityFunctions::print("[rejected] ", godot::String::utf8(refname), " ", status_str); 70 | } else { 71 | godot::UtilityFunctions::print("[updated] ", godot::String::utf8(refname)); 72 | } 73 | return 0; 74 | } 75 | 76 | extern "C" int credentials_cb(git_cred **out, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload) { 77 | Credentials *creds = (Credentials *)payload; 78 | 79 | godot::String proper_username = username_from_url ? username_from_url : creds->username; 80 | 81 | if (!creds->ssh_public_key_path.is_empty()) { 82 | if (allowed_types & GIT_CREDENTIAL_SSH_KEY) { 83 | return git_credential_ssh_key_new(out, 84 | CString(proper_username).data, 85 | CString(creds->ssh_public_key_path).data, 86 | CString(creds->ssh_private_key_path).data, 87 | CString(creds->ssh_passphrase).data); 88 | } 89 | } 90 | 91 | if (allowed_types & GIT_CREDENTIAL_USERPASS_PLAINTEXT) { 92 | return git_cred_userpass_plaintext_new(out, CString(proper_username).data, CString(creds->password).data); 93 | } 94 | 95 | if (allowed_types & GIT_CREDENTIAL_USERNAME) { 96 | return git_credential_username_new(out, CString(proper_username).data); 97 | } 98 | 99 | return GIT_EUSER; 100 | } 101 | 102 | extern "C" int diff_hunk_cb(const git_diff_delta *delta, const git_diff_hunk *range, void *payload) { 103 | DiffHelper *diff_helper = (DiffHelper *)payload; 104 | 105 | godot::Dictionary hunk = diff_helper->git_plugin->create_diff_hunk(range->old_start, range->new_start, range->old_lines, range->new_lines); 106 | diff_helper->diff_hunks->push_back(hunk); 107 | 108 | return 1; 109 | } 110 | -------------------------------------------------------------------------------- /godot-git-plugin/src/git_callbacks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "godot_cpp/variant/array.hpp" 4 | #include "git2.h" 5 | 6 | class GitPlugin; 7 | 8 | struct DiffHelper { 9 | godot::Array *diff_hunks; 10 | GitPlugin *git_plugin; 11 | }; 12 | 13 | extern "C" int progress_cb(const char *str, int len, void *data); 14 | extern "C" int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data); 15 | extern "C" int transfer_progress_cb(const git_indexer_progress *stats, void *payload); 16 | extern "C" int fetchhead_foreach_cb(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload); 17 | extern "C" int credentials_cb(git_cred **out, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload); 18 | extern "C" int push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void *payload); 19 | extern "C" int push_update_reference_cb(const char *refname, const char *status, void *data); 20 | extern "C" int diff_hunk_cb(const git_diff_delta *delta, const git_diff_hunk *range, void *payload); 21 | -------------------------------------------------------------------------------- /godot-git-plugin/src/git_plugin.cpp: -------------------------------------------------------------------------------- 1 | #include "git_plugin.h" 2 | 3 | #include 4 | 5 | #include 6 | #include "godot_cpp/core/class_db.hpp" 7 | #include "godot_cpp/classes/file_access.hpp" 8 | #include "godot_cpp/variant/utility_functions.hpp" 9 | 10 | #define GIT2_CALL(error, msg) \ 11 | if (check_errors(error, __FUNCTION__, __FILE__, __LINE__, msg)) { \ 12 | return; \ 13 | } 14 | 15 | #define GIT2_CALL_R(error, msg, return_value) \ 16 | if (check_errors(error, __FUNCTION__, __FILE__, __LINE__, msg)) { \ 17 | return return_value; \ 18 | } 19 | 20 | #define GIT2_CALL_IGNORE(error, msg, ignores) \ 21 | if (check_errors(error, __FUNCTION__, __FILE__, __LINE__, msg, ignores)) { \ 22 | return; \ 23 | } 24 | 25 | #define GIT2_CALL_R_IGNORE(error, msg, return_value, ignores) \ 26 | if (check_errors(error, __FUNCTION__, __FILE__, __LINE__, msg, ignores)) { \ 27 | return return_value; \ 28 | } 29 | 30 | #define COMMA , 31 | 32 | void GitPlugin::_bind_methods() { 33 | // Doesn't seem to require binding functions for now 34 | } 35 | 36 | GitPlugin::GitPlugin() { 37 | map_changes[GIT_STATUS_WT_NEW] = CHANGE_TYPE_NEW; 38 | map_changes[GIT_STATUS_INDEX_NEW] = CHANGE_TYPE_NEW; 39 | map_changes[GIT_STATUS_WT_MODIFIED] = CHANGE_TYPE_MODIFIED; 40 | map_changes[GIT_STATUS_INDEX_MODIFIED] = CHANGE_TYPE_MODIFIED; 41 | map_changes[GIT_STATUS_WT_RENAMED] = CHANGE_TYPE_RENAMED; 42 | map_changes[GIT_STATUS_INDEX_RENAMED] = CHANGE_TYPE_RENAMED; 43 | map_changes[GIT_STATUS_WT_DELETED] = CHANGE_TYPE_DELETED; 44 | map_changes[GIT_STATUS_INDEX_DELETED] = CHANGE_TYPE_DELETED; 45 | map_changes[GIT_STATUS_WT_TYPECHANGE] = CHANGE_TYPE_TYPECHANGE; 46 | map_changes[GIT_STATUS_INDEX_TYPECHANGE] = CHANGE_TYPE_TYPECHANGE; 47 | map_changes[GIT_STATUS_CONFLICTED] = CHANGE_TYPE_UNMERGED; 48 | } 49 | 50 | bool GitPlugin::check_errors(int error, godot::String function, godot::String file, int line, godot::String message, const std::vector &ignores) { 51 | const git_error *lg2err; 52 | 53 | if (error == 0) { 54 | return false; 55 | } 56 | 57 | for (auto &ig : ignores) { 58 | if (error == ig) { 59 | return false; 60 | } 61 | } 62 | 63 | message = message + "."; 64 | if ((lg2err = git_error_last()) != nullptr && lg2err->message != nullptr) { 65 | message = message + " Error " + godot::String::num_int64(error) + ": "; 66 | message = message + godot::String::utf8(lg2err->message); 67 | } 68 | 69 | godot::UtilityFunctions::push_error("GitPlugin: ", message, " in ", file, ":", function, "#L", line); 70 | return true; 71 | } 72 | 73 | void GitPlugin::_set_credentials(const godot::String &username, const godot::String &password, const godot::String &ssh_public_key_path, const godot::String &ssh_private_key_path, const godot::String &ssh_passphrase) { 74 | creds.username = username; 75 | creds.password = password; 76 | creds.ssh_public_key_path = ssh_public_key_path; 77 | creds.ssh_private_key_path = ssh_private_key_path; 78 | creds.ssh_passphrase = ssh_passphrase; 79 | } 80 | 81 | void GitPlugin::_discard_file(const godot::String &file_path) { 82 | git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; 83 | CString c_path(file_path); 84 | char *paths[] = { c_path.data }; 85 | opts.paths = { paths, 1 }; 86 | opts.checkout_strategy = GIT_CHECKOUT_FORCE; 87 | 88 | GIT2_CALL(git_checkout_index(repo.get(), nullptr, &opts), "Could not checkout index"); 89 | } 90 | 91 | void GitPlugin::_commit(const godot::String &msg) { 92 | git_index_ptr repo_index; 93 | GIT2_CALL(git_repository_index(Capture(repo_index), repo.get()), "Could not get repository index"); 94 | 95 | git_oid tree_id; 96 | GIT2_CALL(git_index_write_tree(&tree_id, repo_index.get()), "Could not write index to tree"); 97 | GIT2_CALL(git_index_write(repo_index.get()), "Could not write index to disk"); 98 | 99 | git_tree_ptr tree; 100 | GIT2_CALL(git_tree_lookup(Capture(tree), repo.get(), &tree_id), "Could not lookup tree from ID"); 101 | 102 | git_signature_ptr default_sign; 103 | GIT2_CALL(git_signature_default(Capture(default_sign), repo.get()), "Could not get default signature"); 104 | 105 | git_oid parent_commit_id = {}; 106 | GIT2_CALL_IGNORE(git_reference_name_to_id(&parent_commit_id, repo.get(), "HEAD"), "Could not get repository HEAD", { GIT_ENOTFOUND }); 107 | 108 | git_commit_ptr parent_commit; 109 | if (!git_oid_is_zero(&parent_commit_id)) { 110 | GIT2_CALL(git_commit_lookup(Capture(parent_commit), repo.get(), &parent_commit_id), "Could not lookup parent commit data"); 111 | } 112 | 113 | git_oid new_commit_id; 114 | if (!has_merge) { 115 | GIT2_CALL( 116 | git_commit_create_v( 117 | &new_commit_id, 118 | repo.get(), 119 | "HEAD", 120 | default_sign.get(), 121 | default_sign.get(), 122 | "UTF-8", 123 | CString(msg).data, 124 | tree.get(), 125 | parent_commit.get() ? 1 : 0, 126 | parent_commit.get()), 127 | "Could not create commit"); 128 | } else { 129 | git_commit_ptr fetchhead_commit; 130 | GIT2_CALL(git_commit_lookup(Capture(fetchhead_commit), repo.get(), &pull_merge_oid), "Could not lookup commit pointed to by HEAD"); 131 | 132 | GIT2_CALL( 133 | git_commit_create_v( 134 | &new_commit_id, 135 | repo.get(), 136 | "HEAD", 137 | default_sign.get(), 138 | default_sign.get(), 139 | "UTF-8", 140 | CString(msg).data, 141 | tree.get(), 142 | 2, 143 | parent_commit.get(), 144 | fetchhead_commit.get()), 145 | "Could not create merge commit"); 146 | has_merge = false; 147 | GIT2_CALL(git_repository_state_cleanup(repo.get()), "Could not clean repository state"); 148 | } 149 | } 150 | 151 | void GitPlugin::_stage_file(const godot::String &file_path) { 152 | CString c_path(file_path); 153 | char *paths[] = { c_path.data }; 154 | git_strarray array = { paths, 1 }; 155 | 156 | git_index_ptr index; 157 | GIT2_CALL(git_repository_index(Capture(index), repo.get()), "Could not get repository index"); 158 | GIT2_CALL(git_index_add_all(index.get(), &array, GIT_INDEX_ADD_DEFAULT | GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH, nullptr, nullptr), "Could not add " + file_path + " to index"); 159 | GIT2_CALL(git_index_write(index.get()), "Could not write changes to disk"); 160 | } 161 | 162 | void GitPlugin::_unstage_file(const godot::String &file_path) { 163 | CString c_path(file_path); 164 | char *paths[] = { c_path.data }; 165 | git_strarray array = { paths, 1 }; 166 | 167 | git_reference_ptr head; 168 | GIT2_CALL_IGNORE(git_repository_head(Capture(head), repo.get()), "Could not find repository HEAD", { GIT_ENOTFOUND COMMA GIT_EUNBORNBRANCH }); 169 | 170 | if (head) { 171 | git_object_ptr head_commit; 172 | GIT2_CALL(git_reference_peel(Capture(head_commit), head.get(), GIT_OBJ_COMMIT), "Could not peel HEAD reference"); 173 | GIT2_CALL(git_reset_default(repo.get(), head_commit.get(), &array), "Could not reset " + file_path + " to state at HEAD"); 174 | } else { 175 | // If there is no HEAD commit, we should just remove the file from the index. 176 | 177 | CString c_path(file_path); 178 | 179 | git_index_ptr index; 180 | GIT2_CALL(git_repository_index(Capture(index), repo.get()), "Could not get repository index"); 181 | GIT2_CALL(git_index_remove_bypath(index.get(), c_path.data), "Could not add " + file_path + " to index"); 182 | GIT2_CALL(git_index_write(index.get()), "Could not write changes to disk"); 183 | } 184 | } 185 | 186 | void GitPlugin::create_gitignore_and_gitattributes() { 187 | if (!godot::FileAccess::file_exists(repo_project_path + "/.gitignore")) { 188 | godot::Ref file = godot::FileAccess::open(repo_project_path + "/.gitignore", godot::FileAccess::ModeFlags::WRITE); 189 | ERR_FAIL_COND(file.is_null()); 190 | file->store_string( 191 | "# Godot 4+ specific ignores\n" 192 | ".godot/\n"); 193 | } 194 | 195 | if (!godot::FileAccess::file_exists(repo_project_path + "/.gitattributes")) { 196 | godot::Ref file = godot::FileAccess::open(repo_project_path + "/.gitattributes", godot::FileAccess::ModeFlags::WRITE); 197 | ERR_FAIL_COND(file.is_null()); 198 | file->store_string( 199 | "# Set the default behavior, in case people don't have core.autocrlf set.\n" 200 | "* text=auto\n\n" 201 | 202 | "# Explicitly declare text files you want to always be normalized and converted\n" 203 | "# to native line endings on checkout.\n" 204 | "*.cpp text\n" 205 | "*.c text\n" 206 | "*.h text\n" 207 | "*.gd text\n" 208 | "*.cs text\n\n" 209 | 210 | "# Declare files that will always have CRLF line endings on checkout.\n" 211 | "*.sln text eol=crlf\n\n" 212 | 213 | "# Denote all files that are truly binary and should not be modified.\n" 214 | "*.png binary\n" 215 | "*.jpg binary\n"); 216 | } 217 | } 218 | 219 | godot::TypedArray GitPlugin::_get_modified_files_data() { 220 | godot::TypedArray stats_files; 221 | 222 | git_status_options opts = GIT_STATUS_OPTIONS_INIT; 223 | opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; 224 | opts.flags = GIT_STATUS_OPT_EXCLUDE_SUBMODULES; 225 | opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | GIT_STATUS_OPT_SORT_CASE_SENSITIVELY | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; 226 | 227 | git_status_list_ptr statuses; 228 | GIT2_CALL_R(git_status_list_new(Capture(statuses), repo.get(), &opts), "Could not get status information from repository", godot::TypedArray()); 229 | 230 | size_t count = git_status_list_entrycount(statuses.get()); 231 | for (size_t i = 0; i < count; ++i) { 232 | const git_status_entry *entry = git_status_byindex(statuses.get(), i); 233 | godot::String path; 234 | if (entry->index_to_workdir) { 235 | path = godot::String::utf8(entry->index_to_workdir->new_file.path); 236 | } else { 237 | path = godot::String::utf8(entry->head_to_index->new_file.path); 238 | } 239 | 240 | const static int git_status_wt = GIT_STATUS_WT_NEW | GIT_STATUS_WT_MODIFIED | GIT_STATUS_WT_DELETED | GIT_STATUS_WT_TYPECHANGE | GIT_STATUS_WT_RENAMED | GIT_STATUS_CONFLICTED; 241 | const static int git_status_index = GIT_STATUS_INDEX_NEW | GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_INDEX_DELETED | GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_TYPECHANGE; 242 | 243 | if (entry->status & git_status_wt) { 244 | stats_files.push_back(create_status_file(path, map_changes[git_status_t(entry->status & git_status_wt)], TREE_AREA_UNSTAGED)); 245 | } 246 | 247 | if (entry->status & git_status_index) { 248 | if (entry->status & GIT_STATUS_INDEX_RENAMED) { 249 | godot::String old_path = godot::String::utf8(entry->head_to_index->old_file.path); 250 | stats_files.push_back(create_status_file(old_path, map_changes.at(GIT_STATUS_INDEX_DELETED), TREE_AREA_STAGED)); 251 | stats_files.push_back(create_status_file(path, map_changes.at(GIT_STATUS_INDEX_NEW), TREE_AREA_STAGED)); 252 | } else { 253 | stats_files.push_back(create_status_file(path, map_changes.at(git_status_t(entry->status & git_status_index)), TREE_AREA_STAGED)); 254 | } 255 | } 256 | } 257 | 258 | return stats_files; 259 | } 260 | 261 | godot::TypedArray GitPlugin::_get_branch_list() { 262 | git_branch_iterator_ptr it; 263 | GIT2_CALL_R(git_branch_iterator_new(Capture(it), repo.get(), GIT_BRANCH_LOCAL), "Could not create branch iterator", godot::TypedArray()); 264 | 265 | godot::TypedArray branch_names; 266 | 267 | git_reference_ptr ref; 268 | git_branch_t type; 269 | while (git_branch_next(Capture(ref), &type, it.get()) != GIT_ITEROVER) { 270 | const char *name = nullptr; 271 | 272 | GIT2_CALL_R(git_branch_name(&name, ref.get()), "Could not get branch name", godot::TypedArray()); 273 | 274 | if (git_branch_is_head(ref.get())) { 275 | // Always send the current branch as the first branch in list 276 | branch_names.push_front(godot::String::utf8(name)); 277 | } else { 278 | branch_names.push_back(godot::String::utf8(name)); 279 | } 280 | } 281 | 282 | return branch_names; 283 | } 284 | 285 | void GitPlugin::_create_branch(const godot::String &branch_name) { 286 | git_oid head_commit_id; 287 | GIT2_CALL(git_reference_name_to_id(&head_commit_id, repo.get(), "HEAD"), "Could not get HEAD commit ID"); 288 | 289 | git_commit_ptr head_commit; 290 | GIT2_CALL(git_commit_lookup(Capture(head_commit), repo.get(), &head_commit_id), "Could not lookup HEAD commit"); 291 | 292 | git_reference_ptr branch_ref; 293 | GIT2_CALL(git_branch_create(Capture(branch_ref), repo.get(), CString(branch_name).data, head_commit.get(), 0), "Could not create branch from HEAD"); 294 | } 295 | 296 | void GitPlugin::_create_remote(const godot::String &remote_name, const godot::String &remote_url) { 297 | git_remote_ptr remote; 298 | GIT2_CALL(git_remote_create(Capture(remote), repo.get(), CString(remote_name).data, CString(remote_url).data), "Could not create remote"); 299 | } 300 | 301 | void GitPlugin::_remove_branch(const godot::String &branch_name) { 302 | git_reference_ptr branch; 303 | GIT2_CALL(git_branch_lookup(Capture(branch), repo.get(), CString(branch_name).data, GIT_BRANCH_LOCAL), "Could not find branch " + branch_name); 304 | GIT2_CALL(git_branch_delete(branch.get()), "Could not delete branch reference of " + branch_name); 305 | } 306 | 307 | void GitPlugin::_remove_remote(const godot::String &remote_name) { 308 | GIT2_CALL(git_remote_delete(repo.get(), CString(remote_name).data), "Could not delete remote " + remote_name); 309 | } 310 | 311 | godot::TypedArray GitPlugin::_get_line_diff(const godot::String &file_path, const godot::String &text) { 312 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; 313 | 314 | opts.context_lines = 0; 315 | opts.flags = GIT_DIFF_DISABLE_PATHSPEC_MATCH | GIT_DIFF_INCLUDE_UNTRACKED; 316 | 317 | git_index_ptr index; 318 | GIT2_CALL_R(git_repository_index(Capture(index), repo.get()), "Failed to get repository index", godot::TypedArray()); 319 | GIT2_CALL_R(git_index_read(index.get(), 0), "Failed to read index", godot::TypedArray()); 320 | 321 | const git_index_entry *entry = git_index_get_bypath(index.get(), CString(file_path).data, GIT_INDEX_STAGE_NORMAL); 322 | if (!entry) { 323 | return godot::TypedArray(); 324 | } 325 | 326 | git_reference_ptr head; 327 | GIT2_CALL_R(git_repository_head(Capture(head), repo.get()), "Failed to load repository head", godot::TypedArray()); 328 | 329 | git_blob_ptr blob; 330 | GIT2_CALL_R(git_blob_lookup(Capture(blob), repo.get(), &entry->id), "Failed to load head blob", godot::TypedArray()); 331 | 332 | godot::TypedArray diff_contents; 333 | 334 | DiffHelper diff_helper = { &diff_contents, this }; 335 | GIT2_CALL_R(git_diff_blob_to_buffer(blob.get(), nullptr, CString(text).data, text.length(), nullptr, &opts, nullptr, nullptr, diff_hunk_cb, nullptr, &diff_helper), "Failed to make diff", godot::TypedArray()); 336 | 337 | return diff_contents; 338 | } 339 | 340 | godot::String GitPlugin::_get_current_branch_name() { 341 | git_reference_ptr head; 342 | GIT2_CALL_R_IGNORE(git_repository_head(Capture(head), repo.get()), "Could not find repository HEAD", "", { GIT_ENOTFOUND COMMA GIT_EUNBORNBRANCH }); 343 | 344 | if (!head) { 345 | // We are likely at a state where the initial commit hasn't been made yet. 346 | return ""; 347 | } 348 | 349 | git_reference_ptr branch; 350 | GIT2_CALL_R(git_reference_resolve(Capture(branch), head.get()), "Could not resolve HEAD reference", ""); 351 | 352 | const char *name = ""; 353 | GIT2_CALL_R(git_branch_name(&name, branch.get()), "Could not get branch name from current branch reference", ""); 354 | 355 | return godot::String::utf8(name); 356 | } 357 | 358 | godot::TypedArray GitPlugin::_get_remotes() { 359 | git_strarray remote_array; 360 | GIT2_CALL_R(git_remote_list(&remote_array, repo.get()), "Could not get list of remotes", godot::TypedArray()); 361 | 362 | godot::TypedArray remotes; 363 | for (int i = 0; i < remote_array.count; i++) { 364 | remotes.push_back(godot::String::utf8(remote_array.strings[i])); 365 | } 366 | 367 | return remotes; 368 | } 369 | 370 | godot::TypedArray GitPlugin::_get_previous_commits(int32_t max_commits) { 371 | git_revwalk_ptr walker; 372 | GIT2_CALL_R(git_revwalk_new(Capture(walker), repo.get()), "Could not create new revwalk", godot::TypedArray()); 373 | GIT2_CALL_R(git_revwalk_sorting(walker.get(), GIT_SORT_TIME), "Could not sort revwalk by time", godot::TypedArray()); 374 | 375 | GIT2_CALL_R_IGNORE(git_revwalk_push_head(walker.get()), "Could not push HEAD to revwalk", godot::TypedArray(), { GIT_ENOTFOUND COMMA GIT_ERROR }); 376 | 377 | git_oid oid; 378 | godot::TypedArray commits; 379 | char commit_id[GIT_OID_HEXSZ + 1]; 380 | for (int i = 0; !git_revwalk_next(&oid, walker.get()) && i <= max_commits; i++) { 381 | git_commit_ptr commit; 382 | GIT2_CALL_R(git_commit_lookup(Capture(commit), repo.get(), &oid), "Failed to lookup the commit", commits); 383 | 384 | git_oid_tostr(commit_id, GIT_OID_HEXSZ + 1, git_commit_id(commit.get())); 385 | godot::String msg = godot::String::utf8(git_commit_message(commit.get())); 386 | 387 | const git_signature *sig = git_commit_author(commit.get()); 388 | godot::String author = godot::String::utf8(sig->name) + " <" + godot::String::utf8(sig->email) + ">"; 389 | 390 | commits.push_back(create_commit(msg, author, commit_id, sig->when.time, sig->when.offset)); 391 | } 392 | 393 | return commits; 394 | } 395 | 396 | void GitPlugin::_fetch(const godot::String &remote) { 397 | godot::UtilityFunctions::print("GitPlugin: Performing fetch from ", remote); 398 | 399 | git_remote_ptr remote_object; 400 | GIT2_CALL(git_remote_lookup(Capture(remote_object), repo.get(), CString(remote).data), "Could not lookup remote \"" + remote + "\""); 401 | 402 | git_remote_callbacks remote_cbs = GIT_REMOTE_CALLBACKS_INIT; 403 | remote_cbs.credentials = &credentials_cb; 404 | remote_cbs.update_tips = &update_cb; 405 | remote_cbs.sideband_progress = &progress_cb; 406 | remote_cbs.transfer_progress = &transfer_progress_cb; 407 | remote_cbs.payload = &creds; 408 | remote_cbs.push_transfer_progress = &push_transfer_progress_cb; 409 | remote_cbs.push_update_reference = &push_update_reference_cb; 410 | 411 | GIT2_CALL(git_remote_connect(remote_object.get(), GIT_DIRECTION_FETCH, &remote_cbs, nullptr, nullptr), "Could not connect to remote \"" + remote + "\". Are your credentials correct? Try using a PAT token (in case you are using Github) as your password"); 412 | 413 | git_fetch_options opts = GIT_FETCH_OPTIONS_INIT; 414 | opts.callbacks = remote_cbs; 415 | GIT2_CALL(git_remote_fetch(remote_object.get(), nullptr, &opts, "fetch"), "Could not fetch data from remote"); 416 | 417 | godot::UtilityFunctions::print("GitPlugin: Fetch ended"); 418 | } 419 | 420 | void GitPlugin::_pull(const godot::String &remote) { 421 | godot::UtilityFunctions::print("GitPlugin: Performing pull from ", remote); 422 | 423 | git_remote_ptr remote_object; 424 | GIT2_CALL(git_remote_lookup(Capture(remote_object), repo.get(), CString(remote).data), "Could not lookup remote \"" + remote + "\""); 425 | 426 | git_remote_callbacks remote_cbs = GIT_REMOTE_CALLBACKS_INIT; 427 | remote_cbs.credentials = &credentials_cb; 428 | remote_cbs.update_tips = &update_cb; 429 | remote_cbs.sideband_progress = &progress_cb; 430 | remote_cbs.transfer_progress = &transfer_progress_cb; 431 | remote_cbs.payload = &creds; 432 | remote_cbs.push_transfer_progress = &push_transfer_progress_cb; 433 | remote_cbs.push_update_reference = &push_update_reference_cb; 434 | 435 | GIT2_CALL(git_remote_connect(remote_object.get(), GIT_DIRECTION_FETCH, &remote_cbs, nullptr, nullptr), "Could not connect to remote \"" + remote + "\". Are your credentials correct? Try using a PAT token (in case you are using Github) as your password"); 436 | 437 | git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; 438 | fetch_opts.callbacks = remote_cbs; 439 | 440 | godot::String branch_name = _get_current_branch_name(); 441 | 442 | CString ref_spec_str("refs/heads/" + branch_name); 443 | 444 | char *ref[] = { ref_spec_str.data }; 445 | git_strarray refspec = { ref, 1 }; 446 | 447 | GIT2_CALL(git_remote_fetch(remote_object.get(), &refspec, &fetch_opts, "pull"), "Could not fetch data from remote"); 448 | 449 | pull_merge_oid = {}; 450 | GIT2_CALL(git_repository_fetchhead_foreach(repo.get(), fetchhead_foreach_cb, &pull_merge_oid), "Could not read \"FETCH_HEAD\" file"); 451 | 452 | if (git_oid_is_zero(&pull_merge_oid)) { 453 | godot::UtilityFunctions::push_error("GitPlugin: Could not find remote branch HEAD for " + branch_name + ". Try pushing the branch first."); 454 | return; 455 | } 456 | 457 | git_annotated_commit_ptr fetchhead_annotated_commit; 458 | GIT2_CALL(git_annotated_commit_lookup(Capture(fetchhead_annotated_commit), repo.get(), &pull_merge_oid), "Could not get merge commit"); 459 | 460 | const git_annotated_commit *merge_heads[] = { fetchhead_annotated_commit.get() }; 461 | 462 | git_merge_analysis_t merge_analysis; 463 | git_merge_preference_t preference = GIT_MERGE_PREFERENCE_NONE; 464 | GIT2_CALL(git_merge_analysis(&merge_analysis, &preference, repo.get(), merge_heads, 1), "Merge analysis failed"); 465 | 466 | if (merge_analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) { 467 | git_checkout_options ff_checkout_options = GIT_CHECKOUT_OPTIONS_INIT; 468 | int err = 0; 469 | 470 | git_reference_ptr target_ref; 471 | GIT2_CALL(git_repository_head(Capture(target_ref), repo.get()), "Failed to get HEAD reference"); 472 | 473 | git_object_ptr target; 474 | GIT2_CALL(git_object_lookup(Capture(target), repo.get(), &pull_merge_oid, GIT_OBJECT_COMMIT), "Failed to lookup OID " + godot::String(git_oid_tostr_s(&pull_merge_oid))); 475 | 476 | ff_checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE; 477 | GIT2_CALL(git_checkout_tree(repo.get(), target.get(), &ff_checkout_options), "Failed to checkout HEAD reference"); 478 | 479 | git_reference_ptr new_target_ref; 480 | GIT2_CALL(git_reference_set_target(Capture(new_target_ref), target_ref.get(), &pull_merge_oid, nullptr), "Failed to move HEAD reference"); 481 | 482 | godot::UtilityFunctions::print("GitPlugin: Fast Forwarded"); 483 | GIT2_CALL(git_repository_state_cleanup(repo.get()), "Could not clean repository state"); 484 | 485 | } else if (merge_analysis & GIT_MERGE_ANALYSIS_NORMAL) { 486 | git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT; 487 | git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; 488 | 489 | merge_opts.file_favor = GIT_MERGE_FILE_FAVOR_NORMAL; 490 | merge_opts.file_flags = (GIT_MERGE_FILE_STYLE_DIFF3 | GIT_MERGE_FILE_DIFF_MINIMAL); 491 | checkout_opts.checkout_strategy = (GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS | GIT_CHECKOUT_CONFLICT_STYLE_MERGE); 492 | GIT2_CALL(git_merge(repo.get(), merge_heads, 1, &merge_opts, &checkout_opts), "Merge Failed"); 493 | 494 | git_index_ptr index; 495 | GIT2_CALL(git_repository_index(Capture(index), repo.get()), "Could not get repository index"); 496 | 497 | if (git_index_has_conflicts(index.get())) { 498 | godot::UtilityFunctions::push_error("GitPlugin: Index has conflicts. Solve conflicts and make a merge commit."); 499 | } else { 500 | godot::UtilityFunctions::push_error("GitPlugin: Changes are staged. Make a merge commit."); 501 | } 502 | 503 | has_merge = true; 504 | 505 | } else if (merge_analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE) { 506 | godot::UtilityFunctions::print("GitPlugin: Already up to date"); 507 | 508 | GIT2_CALL(git_repository_state_cleanup(repo.get()), "Could not clean repository state"); 509 | 510 | } else { 511 | godot::UtilityFunctions::push_error("GitPlugin: Can not merge"); 512 | } 513 | 514 | godot::UtilityFunctions::print("GitPlugin: Pull ended"); 515 | } 516 | 517 | void GitPlugin::_push(const godot::String &remote, bool force) { 518 | godot::UtilityFunctions::print("GitPlugin: Performing push to ", remote); 519 | 520 | git_remote_ptr remote_object; 521 | GIT2_CALL(git_remote_lookup(Capture(remote_object), repo.get(), CString(remote).data), "Could not lookup remote \"" + remote + "\""); 522 | 523 | git_remote_callbacks remote_cbs = GIT_REMOTE_CALLBACKS_INIT; 524 | remote_cbs.credentials = &credentials_cb; 525 | remote_cbs.update_tips = &update_cb; 526 | remote_cbs.sideband_progress = &progress_cb; 527 | remote_cbs.transfer_progress = &transfer_progress_cb; 528 | remote_cbs.payload = &creds; 529 | remote_cbs.push_transfer_progress = &push_transfer_progress_cb; 530 | remote_cbs.push_update_reference = &push_update_reference_cb; 531 | 532 | godot::String msg = "Could not connect to remote \"" + remote + "\". Are your credentials correct? Try using a PAT token (in case you are using Github) as your password"; 533 | GIT2_CALL(git_remote_connect(remote_object.get(), GIT_DIRECTION_PUSH, &remote_cbs, nullptr, nullptr), msg); 534 | 535 | godot::String branch_name = _get_current_branch_name(); 536 | 537 | CString pushspec(godot::String() + (force ? "+" : "") + "refs/heads/" + branch_name); 538 | const git_strarray refspec = { &pushspec.data, 1 }; 539 | 540 | git_push_options push_options = GIT_PUSH_OPTIONS_INIT; 541 | push_options.callbacks = remote_cbs; 542 | 543 | GIT2_CALL(git_remote_push(remote_object.get(), &refspec, &push_options), "Failed to push"); 544 | 545 | godot::UtilityFunctions::print("GitPlugin: Push ended"); 546 | } 547 | 548 | bool GitPlugin::_checkout_branch(const godot::String &branch_name) { 549 | git_reference_ptr branch; 550 | GIT2_CALL_R(git_branch_lookup(Capture(branch), repo.get(), CString(branch_name).data, GIT_BRANCH_LOCAL), "Could not find branch", false); 551 | const char *branch_ref_name = git_reference_name(branch.get()); 552 | 553 | git_object_ptr treeish; 554 | GIT2_CALL_R(git_revparse_single(Capture(treeish), repo.get(), CString(branch_name).data), "Could not find branch head", false); 555 | 556 | git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; 557 | opts.checkout_strategy = GIT_CHECKOUT_SAFE; 558 | GIT2_CALL_R(git_checkout_tree(repo.get(), treeish.get(), &opts), "Could not checkout branch tree", false); 559 | GIT2_CALL_R(git_repository_set_head(repo.get(), branch_ref_name), "Could not set head", false); 560 | 561 | return true; 562 | } 563 | 564 | godot::TypedArray GitPlugin::_get_diff(const godot::String &identifier, const int32_t area) { 565 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; 566 | godot::TypedArray diff_contents; 567 | 568 | opts.context_lines = 2; 569 | opts.interhunk_lines = 0; 570 | opts.flags = GIT_DIFF_RECURSE_UNTRACKED_DIRS | GIT_DIFF_DISABLE_PATHSPEC_MATCH | GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT | GIT_DIFF_INCLUDE_TYPECHANGE; 571 | 572 | CString pathspec(identifier); 573 | opts.pathspec.strings = &pathspec.data; 574 | opts.pathspec.count = 1; 575 | 576 | git_diff_ptr diff; 577 | switch ((TreeArea)area) { 578 | case TREE_AREA_UNSTAGED: { 579 | GIT2_CALL_R(git_diff_index_to_workdir(Capture(diff), repo.get(), nullptr, &opts), "Could not create diff for index from working directory", diff_contents); 580 | } break; 581 | case TREE_AREA_STAGED: { 582 | git_object_ptr obj; 583 | 584 | // Ignore the case when HEAD is not found. We need to compare with a null tree in the case where the HEAD reference object is empty. 585 | GIT2_CALL_R_IGNORE(git_revparse_single(Capture(obj), repo.get(), "HEAD^{tree}"), "Could not get HEAD^{tree} object", diff_contents, { GIT_ENOTFOUND }); 586 | 587 | git_tree_ptr tree; 588 | if (obj) { 589 | GIT2_CALL_R_IGNORE(git_tree_lookup(Capture(tree), repo.get(), git_object_id(obj.get())), "Could not lookup HEAD^{tree}", diff_contents, { GIT_ENOTFOUND }); 590 | } 591 | 592 | GIT2_CALL_R(git_diff_tree_to_index(Capture(diff), repo.get(), tree.get(), nullptr, &opts), "Could not create diff for tree from index directory", diff_contents); 593 | } break; 594 | case TREE_AREA_COMMIT: { 595 | opts.pathspec = {}; 596 | 597 | git_object_ptr obj; 598 | GIT2_CALL_R(git_revparse_single(Capture(obj), repo.get(), pathspec.data), "Could not get object at " + identifier, diff_contents); 599 | 600 | git_commit_ptr commit; 601 | GIT2_CALL_R(git_commit_lookup(Capture(commit), repo.get(), git_object_id(obj.get())), "Could not get commit " + identifier, diff_contents); 602 | 603 | git_commit_ptr parent; 604 | 605 | // We ignore the case when the parent is not found to handle the case when this commit is the root commit. We only need to diff against a null tree in that case. 606 | GIT2_CALL_R_IGNORE(git_commit_parent(Capture(parent), commit.get(), 0), "Could not get parent commit of " + identifier, diff_contents, { GIT_ENOTFOUND }); 607 | 608 | git_tree_ptr commit_tree; 609 | GIT2_CALL_R(git_commit_tree(Capture(commit_tree), commit.get()), "Could not get commit tree of " + identifier, diff_contents); 610 | 611 | git_tree_ptr parent_tree; 612 | if (parent) { 613 | GIT2_CALL_R(git_commit_tree(Capture(parent_tree), parent.get()), "Could not get commit tree of " + identifier, diff_contents); 614 | } 615 | 616 | GIT2_CALL_R(git_diff_tree_to_tree(Capture(diff), repo.get(), parent_tree.get(), commit_tree.get(), &opts), "Could not generate diff for commit " + identifier, diff_contents); 617 | } break; 618 | } 619 | 620 | diff_contents = _parse_diff(diff.get()); 621 | 622 | return diff_contents; 623 | } 624 | 625 | godot::TypedArray GitPlugin::_parse_diff(git_diff *diff) { 626 | godot::TypedArray diff_contents; 627 | for (int i = 0; i < git_diff_num_deltas(diff); i++) { 628 | const git_diff_delta *delta = git_diff_get_delta(diff, i); 629 | 630 | git_patch_ptr patch; 631 | GIT2_CALL_R(git_patch_from_diff(Capture(patch), diff, i), "Could not create patch from diff", godot::TypedArray()); 632 | 633 | godot::Dictionary diff_file = create_diff_file(godot::String::utf8(delta->new_file.path), godot::String::utf8(delta->old_file.path)); 634 | 635 | godot::TypedArray diff_hunks; 636 | for (int j = 0; j < git_patch_num_hunks(patch.get()); j++) { 637 | const git_diff_hunk *git_hunk; 638 | size_t line_count; 639 | GIT2_CALL_R(git_patch_get_hunk(&git_hunk, &line_count, patch.get(), j), "Could not get hunk from patch", godot::TypedArray()); 640 | 641 | godot::Dictionary diff_hunk = create_diff_hunk(git_hunk->old_start, git_hunk->new_start, git_hunk->old_lines, git_hunk->new_lines); 642 | 643 | godot::TypedArray diff_lines; 644 | for (int k = 0; k < line_count; k++) { 645 | const git_diff_line *git_diff_line; 646 | GIT2_CALL_R(git_patch_get_line_in_hunk(&git_diff_line, patch.get(), j, k), "Could not get line from hunk in patch", godot::TypedArray()); 647 | 648 | char *content = new char[git_diff_line->content_len + 1]; 649 | std::memcpy(content, git_diff_line->content, git_diff_line->content_len); 650 | content[git_diff_line->content_len] = '\0'; 651 | 652 | godot::String status = " "; // We reserve 1 null terminated space to fill the + or the - character at git_diff_line->origin 653 | status[0] = git_diff_line->origin; 654 | diff_lines.push_back(create_diff_line(git_diff_line->new_lineno, git_diff_line->old_lineno, godot::String::utf8(content), status)); 655 | 656 | delete[] content; 657 | } 658 | 659 | diff_hunk = add_line_diffs_into_diff_hunk(diff_hunk, diff_lines); 660 | diff_hunks.push_back(diff_hunk); 661 | } 662 | diff_file = add_diff_hunks_into_diff_file(diff_file, diff_hunks); 663 | diff_contents.push_back(diff_file); 664 | } 665 | return diff_contents; 666 | } 667 | 668 | godot::String GitPlugin::_get_vcs_name() { 669 | return "Git"; 670 | } 671 | 672 | bool GitPlugin::_initialize(const godot::String &project_path) { 673 | using namespace godot; 674 | 675 | ERR_FAIL_COND_V(project_path == "", false); 676 | 677 | int init = git_libgit2_init(); 678 | if (init > 1) { 679 | WARN_PRINT("Multiple libgit2 instances are running"); 680 | } 681 | 682 | git_buf discovered_repo_path = {}; 683 | if (git_repository_discover(&discovered_repo_path, CString(project_path).data, 1, nullptr) == 0) { 684 | repo_project_path = godot::String::utf8(discovered_repo_path.ptr); 685 | 686 | godot::UtilityFunctions::print("Found a repository at " + repo_project_path + "."); 687 | git_buf_dispose(&discovered_repo_path); 688 | } else { 689 | repo_project_path = project_path; 690 | 691 | godot::UtilityFunctions::push_warning("Could not find any higher level repositories."); 692 | } 693 | 694 | godot::UtilityFunctions::print("Selected repository path: " + repo_project_path + "."); 695 | GIT2_CALL_R(git_repository_init(Capture(repo), CString(repo_project_path).data, 0), "Could not initialize repository", false); 696 | 697 | git_reference_ptr head; 698 | GIT2_CALL_R_IGNORE(git_repository_head(Capture(head), repo.get()), "Could not get repository HEAD", false, { GIT_EUNBORNBRANCH COMMA GIT_ENOTFOUND }); 699 | 700 | if (!head) { 701 | create_gitignore_and_gitattributes(); 702 | } 703 | 704 | return true; 705 | } 706 | 707 | bool GitPlugin::_shut_down() { 708 | repo.reset(); // Destroy repo object before libgit2 shuts down 709 | GIT2_CALL_R(git_libgit2_shutdown(), "Could not shutdown Git Plugin", false); 710 | return true; 711 | } 712 | -------------------------------------------------------------------------------- /godot-git-plugin/src/git_plugin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "git_callbacks.h" 6 | #include "git_wrappers.h" 7 | 8 | #include "godot_cpp/classes/editor_vcs_interface.hpp" 9 | #include "git2.h" 10 | 11 | struct Credentials { 12 | godot::String username; 13 | godot::String password; 14 | godot::String ssh_public_key_path; 15 | godot::String ssh_private_key_path; 16 | godot::String ssh_passphrase; 17 | }; 18 | 19 | class GitPlugin : public godot::EditorVCSInterface { 20 | GDCLASS(GitPlugin, godot::EditorVCSInterface); 21 | 22 | protected: 23 | static void _bind_methods(); 24 | 25 | public: 26 | Credentials creds; 27 | bool has_merge = false; 28 | git_repository_ptr repo; 29 | git_oid pull_merge_oid = {}; 30 | godot::String repo_project_path; 31 | std::unordered_map map_changes; 32 | 33 | GitPlugin(); 34 | 35 | // Endpoints 36 | bool _initialize(const godot::String &project_path) override; 37 | void _set_credentials(const godot::String &username, const godot::String &password, const godot::String &ssh_public_key_path, const godot::String &ssh_private_key_path, const godot::String &ssh_passphrase) override; 38 | godot::TypedArray _get_modified_files_data() override; 39 | void _stage_file(const godot::String &file_path) override; 40 | void _unstage_file(const godot::String &file_path) override; 41 | void _discard_file(const godot::String &file_path) override; 42 | void _commit(const godot::String &msg) override; 43 | godot::TypedArray _get_diff(const godot::String &identifier, int32_t area) override; 44 | bool _shut_down() override; 45 | godot::String _get_vcs_name() override; 46 | godot::TypedArray _get_previous_commits(int32_t max_commits) override; 47 | godot::TypedArray _get_branch_list() override; 48 | godot::TypedArray _get_remotes() override; 49 | void _create_branch(const godot::String &branch_name) override; 50 | void _remove_branch(const godot::String &branch_name) override; 51 | void _create_remote(const godot::String &remote_name, const godot::String &remote_url) override; 52 | void _remove_remote(const godot::String &remote_name) override; 53 | godot::String _get_current_branch_name() override; 54 | bool _checkout_branch(const godot::String &branch_name) override; 55 | void _pull(const godot::String &remote) override; 56 | void _push(const godot::String &remote, bool force) override; 57 | void _fetch(const godot::String &remote) override; 58 | godot::TypedArray _get_line_diff(const godot::String &file_path, const godot::String &text) override; 59 | 60 | // Helpers 61 | godot::TypedArray _parse_diff(git_diff *p_diff); 62 | bool check_errors(int error, godot::String function, godot::String file, int line, godot::String message, const std::vector &ignores = {}); 63 | void create_gitignore_and_gitattributes(); 64 | bool create_initial_commit(); 65 | }; 66 | -------------------------------------------------------------------------------- /godot-git-plugin/src/git_wrappers.cpp: -------------------------------------------------------------------------------- 1 | #include "git_wrappers.h" 2 | 3 | #include 4 | 5 | CString::CString(const godot::String &string) { 6 | godot::CharString godot_char_str = string.utf8(); 7 | 8 | data = new char[godot_char_str.length() + 1]; 9 | std::memcpy(data, (void *)godot_char_str.get_data(), godot_char_str.length()); 10 | data[godot_char_str.length()] = '\0'; 11 | } 12 | 13 | CString::~CString() { 14 | if (data) { 15 | delete[] data; 16 | data = nullptr; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /godot-git-plugin/src/git_wrappers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "godot_cpp/variant/string.hpp" 6 | #include "git2.h" 7 | 8 | class GitPlugin; 9 | 10 | struct CString { 11 | char *data = nullptr; 12 | 13 | CString(const godot::String &string); 14 | ~CString(); 15 | CString() = delete; 16 | CString(CString &&) = delete; 17 | CString &operator=(const CString &) = delete; 18 | CString &operator=(CString &&) = delete; 19 | }; 20 | 21 | template 22 | class Capture { 23 | T &smart_ptr = nullptr; 24 | 25 | using Raw = decltype(smart_ptr.get()); 26 | 27 | Raw raw = nullptr; 28 | 29 | public: 30 | Capture() = delete; 31 | Capture(T &ptr) : 32 | smart_ptr(ptr) {} 33 | Capture(Capture &&) = delete; 34 | Capture &operator=(const Capture &) = delete; 35 | Capture &operator=(Capture &&) = delete; 36 | 37 | operator Raw *() { 38 | return &raw; 39 | } 40 | 41 | ~Capture() { 42 | if (raw) { 43 | smart_ptr.reset(raw); 44 | } 45 | } 46 | }; 47 | 48 | template 49 | struct FunctionDeleter { 50 | template 51 | void operator()(T *ptr) { 52 | DeleteFn(ptr); 53 | } 54 | }; 55 | 56 | template 57 | using unique_ptr_deleter = std::unique_ptr>; 58 | 59 | using git_annotated_commit_ptr = unique_ptr_deleter; 60 | using git_blob_ptr = unique_ptr_deleter; 61 | using git_branch_iterator_ptr = unique_ptr_deleter; 62 | using git_commit_ptr = unique_ptr_deleter; 63 | using git_diff_ptr = unique_ptr_deleter; 64 | using git_index_ptr = unique_ptr_deleter; 65 | using git_object_ptr = unique_ptr_deleter; 66 | using git_patch_ptr = unique_ptr_deleter; 67 | using git_reference_ptr = unique_ptr_deleter; 68 | using git_remote_ptr = unique_ptr_deleter; 69 | using git_repository_ptr = unique_ptr_deleter; 70 | using git_revwalk_ptr = unique_ptr_deleter; 71 | using git_signature_ptr = unique_ptr_deleter; 72 | using git_status_list_ptr = unique_ptr_deleter; 73 | using git_tree_ptr = unique_ptr_deleter; 74 | using git_tree_entry_ptr = unique_ptr_deleter; 75 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godotengine/godot-git-plugin/b51e8ee42a5079c541656d0ee97dd1bf1a7b034b/icon.png -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 16 | 18 | 21 | 28 | 29 | 30 | 50 | 53 | 54 | 59 | 65 | 71 | 76 | 81 | 86 | 91 | 96 | 100 | 104 | 108 | 115 | 122 | 129 | 133 | 137 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script is used to create releases for this plugin. This is mostly a helper script for the maintainer. 4 | 5 | echo "Enter the new version number (e.g. 1.2.1):" 6 | read version 7 | 8 | echo "Enter the Windows x64 release ZIP artifact ID or URL:" 9 | read windowsArtifactID 10 | 11 | echo "Enter the Linux x64 release ZIP artifact ID or URL:" 12 | read linuxArtifactID 13 | 14 | echo "Enter the MacOS universal release ZIP artifact ID or URL:" 15 | read macArtifactID 16 | 17 | # wget-ing the github.com URL gives a 404, so we use the method proposed here - https://github.com/actions/upload-artifact/issues/51#issuecomment-735989475 18 | # The ${foo##*/} syntax extracts the string after the last '/' in case it's a full artifact URL. 19 | baseURL=https://nightly.link/godotengine/godot-git-plugin/actions/artifacts/ 20 | windowsZIPURL=${baseURL}${windowsArtifactID##*/}.zip 21 | linuxZIPURL=${baseURL}${linuxArtifactID##*/}.zip 22 | macZIPURL=${baseURL}${macArtifactID##*/}.zip 23 | 24 | wget -O windows.zip $windowsZIPURL 25 | wget -O linux.zip $linuxZIPURL 26 | wget -O mac.zip $macZIPURL 27 | 28 | unzip windows.zip -d windows/ 29 | unzip linux.zip -d linux/ 30 | unzip mac.zip -d mac/ 31 | 32 | releasePath=godot-git-plugin-v$version 33 | mkdir $releasePath 34 | 35 | cp -r windows/addons/ $releasePath 36 | addonsPath=$releasePath/addons 37 | pluginPath=$addonsPath/godot-git-plugin 38 | 39 | mkdir $pluginPath/linux 40 | mkdir $pluginPath/macos 41 | cp -r linux/addons/godot-git-plugin/linux/ $pluginPath/ 42 | cp -r mac/addons/godot-git-plugin/macos/ $pluginPath/ 43 | 44 | sed -i "s/version=\"[^\"]*\"/version=\"v${version}\"/g" $pluginPath/plugin.cfg 45 | cp LICENSE $pluginPath/LICENSE 46 | cp THIRDPARTY.md $pluginPath/THIRDPARTY.md 47 | 48 | zip -r $releasePath.zip $addonsPath 49 | 50 | rm -rf $releasePath 51 | rm -rf windows 52 | rm -rf linux 53 | rm -rf mac 54 | rm windows.zip 55 | rm linux.zip 56 | rm mac.zip 57 | -------------------------------------------------------------------------------- /thirdparty/ssh2/libssh2_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godotengine/godot-git-plugin/b51e8ee42a5079c541656d0ee97dd1bf1a7b034b/thirdparty/ssh2/libssh2_config.h -------------------------------------------------------------------------------- /tools/cmake.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shlex 3 | import sys 4 | 5 | import SCons.Action 6 | import SCons.Builder 7 | import SCons.Util 8 | 9 | 10 | # This must be kept in sync with the value in https://github.com/godotengine/godot/blob/master/platform/android/detect.py#L58. 11 | def get_ndk_version(): 12 | return "23.2.8568313" 13 | 14 | 15 | def cmake_default_flags(env): 16 | if env.get("cmake_default_flags", ""): 17 | return shlex.split(env["cmake_default_flags"]) 18 | 19 | config = {} 20 | 21 | if "CC" in env: 22 | config["CMAKE_C_COMPILER"] = env["CC"] 23 | if "CXX" in env: 24 | config["CMAKE_CXX_COMPILER"] = env["CXX"] 25 | 26 | if env["platform"] == "android": 27 | api = env["android_api_level"] 28 | abi = { 29 | "arm64": "arm64-v8a", 30 | "arm32": "armeabi-v7a", 31 | "x86_32": "x86", 32 | "x86_64": "x86_64", 33 | }[env["arch"]] 34 | config["CMAKE_SYSTEM_NAME"] = "Android" 35 | config["CMAKE_SYSTEM_VERSION"] = api 36 | config["CMAKE_ANDROID_ARCH_ABI"] = abi 37 | config["ANDROID_ABI"] = abi 38 | ndk_root = os.environ.get("ANDROID_NDK_ROOT", env.get("ANDROID_HOME", "") + "/ndk/" + get_ndk_version()) 39 | config["CMAKE_TOOLCHAIN_FILE"] = "%s/build/cmake/android.toolchain.cmake" % ndk_root 40 | config["CMAKE_ANDROID_STL_TYPE"] = "c++_static" 41 | 42 | elif env["platform"] == "linux": 43 | linux_flags = { 44 | "x86_64": "-m64", 45 | "x86_32": "-m32", 46 | "arm32": "-march=armv7-a", 47 | "arm64": "-march=armv8-a", 48 | }.get(env["arch"], "") 49 | if linux_flags: 50 | config["CMAKE_C_FLAGS"] = linux_flags 51 | config["CMAKE_CXX_FLAGS"] = linux_flags 52 | 53 | elif env["platform"] == "macos": 54 | if env["arch"] == "universal": 55 | config["CMAKE_OSX_ARCHITECTURES"] = '"x86_64;arm64"' 56 | else: 57 | config["CMAKE_OSX_ARCHITECTURES"] = env["arch"] 58 | if env.get("macos_deployment_target", "default") != "default": 59 | config["CMAKE_OSX_DEPLOYMENT_TARGET"] = env["macos_deployment_target"] 60 | if sys.platform != "darwin" and "OSXCROSS_ROOT" in os.environ: 61 | config["CMAKE_AR"] = env["AR"] 62 | config["CMAKE_RANLIB"] = env["RANLIB"] 63 | if env["arch"] == "universal": 64 | flags = "-arch x86_64 -arch arm64" 65 | else: 66 | flags = "-arch " + env["arch"] 67 | if env["macos_deployment_target"] != "default": 68 | flags += " -mmacosx-version-min=" + env["macos_deployment_target"] 69 | config["CMAKE_C_FLAGS"] = flags 70 | config["CMAKE_CXX_FLAGS"] = flags 71 | 72 | elif env["platform"] == "ios": 73 | if env["arch"] == "universal": 74 | raise ValueError("iOS architecture not supported: %s" % env["arch"]) 75 | config["CMAKE_SYSTEM_NAME"] = "iOS" 76 | config["CMAKE_OSX_ARCHITECTURES"] = env["arch"] 77 | if env.get("ios_min_version", "default") != "default": 78 | config["CMAKE_OSX_DEPLOYMENT_TARGET"] = env["ios_min_version"] 79 | if env["ios_simulator"]: 80 | config["CMAKE_OSX_SYSROOT"] = "iphonesimulator" 81 | 82 | elif env["platform"] == "windows": 83 | config["CMAKE_SYSTEM_NAME"] = "Windows" 84 | if env.get("is_msvc", False): 85 | config["CMAKE_POLICY_DEFAULT_CMP0091"] = "NEW" 86 | if env.get("debug_crt", False): 87 | config["CMAKE_MSVC_RUNTIME_LIBRARY"] = "MultiThreadedDebugDLL" 88 | else: 89 | if env.get("use_static_cpp", False): 90 | config["CMAKE_MSVC_RUNTIME_LIBRARY"] = "MultiThreaded" 91 | else: 92 | config["CMAKE_MSVC_RUNTIME_LIBRARY"] = "MultiThreadedDLL" 93 | 94 | return ["-D%s=%s" % it for it in config.items()] 95 | 96 | 97 | def cmake_emitter(target, source, env): 98 | return [str(target[0]) + "/CMakeCache.txt"] + target[1:], [str(source[0]) + "/CMakeLists.txt"] + source[1:] 99 | 100 | 101 | def cmake_generator(target, source, env, for_signature): 102 | # Strip the -j option for signature to avoid rebuilding when num_jobs changes. 103 | build = env["CMAKEBUILDCOM"].replace("-j$CMAKEBUILDJOBS", "") if for_signature else env["CMAKEBUILDCOM"] 104 | actions = [ 105 | SCons.Action.Action("$CMAKECONFCOM", "$CMAKECONFCOMSTR"), 106 | SCons.Action.Action(build, "$CMAKEBUILDCOMSTR"), 107 | ] 108 | if env["CMAKE_INSTALL"]: 109 | actions.append( 110 | SCons.Action.Action("$CMAKEINSTALLCOM", "$CMAKEINSTALLCOMSTR"), 111 | ) 112 | return actions 113 | 114 | 115 | def cmake_build( 116 | env, target_dir, source_dir, cmake_outputs=[], cmake_targets=[], cmake_options=[], dependencies=[], install=False 117 | ): 118 | cmake_env = env.Clone() 119 | target = env.Dir("{}/{}/{}".format(target_dir, env["platform"], env["arch"])) 120 | source = env.Dir(source_dir) 121 | builder_targets = [target] + [str(target) + "/" + f for f in cmake_outputs] 122 | builder_sources = [source] + dependencies 123 | default_flags = cmake_default_flags(env) 124 | 125 | # Merge flags 126 | flags = [] 127 | for df in default_flags: 128 | if not df.startswith("-D"): 129 | flags.append(df) 130 | else: 131 | f = df[2:].split("=")[0] 132 | if f in cmake_options: 133 | df += " " + cmake_options[f] 134 | cmake_options.pop(f) 135 | flags.append(df) 136 | for opt in cmake_options: 137 | flags.append("-D%s=%s" % (opt, cmake_options[opt])) 138 | 139 | # Select generator 140 | if env["cmake_generator"]: 141 | flags.extend(["-G", env["cmake_generator"]]) 142 | elif env["platform"] == "windows": 143 | if env.get("is_msvc", False): 144 | flags.extend(["-G", "NMake Makefiles"]) 145 | elif sys.platform in ["win32", "msys", "cygwin"]: 146 | flags.extend(["-G", "Ninja"]) 147 | else: 148 | flags.extend(["-G", "Unix Makefiles"]) 149 | 150 | cmake_env.Append(CMAKECONFFLAGS=flags) 151 | if len(cmake_targets) > 0: 152 | cmake_env.Append(CMAKEBUILDFLAGS=["-t"] + [t for t in cmake_targets]) 153 | cmake_env["CMAKE_INSTALL"] = install 154 | return cmake_env.CMake(builder_targets, builder_sources) 155 | 156 | 157 | def options(opts): 158 | opts.Add("cmake_default_flags", "Default CMake platform flags override, will be autodetected if not specified.", "") 159 | opts.Add("cmake_generator", "CMake generator override, will be autodetected from platform if not specified.", "") 160 | opts.Add("cmake", "CMake binary to use", "cmake") 161 | 162 | 163 | def exists(env): 164 | return True 165 | 166 | 167 | def generate(env): 168 | env["CMAKE"] = env["cmake"] 169 | env["CMAKECONFFLAGS"] = SCons.Util.CLVar("") 170 | env["CMAKECONFCOM"] = "$CMAKE -B ${TARGET.dir} $CMAKECONFFLAGS ${SOURCE.dir}" 171 | env["CMAKEBUILDJOBS"] = "${__env__.GetOption('num_jobs')}" 172 | env["CMAKEBUILDFLAGS"] = SCons.Util.CLVar("") 173 | env["CMAKEINSTALLFLAGS"] = SCons.Util.CLVar("") 174 | env["CMAKEBUILDCOM"] = "$CMAKE --build ${TARGET.dir} $CMAKEBUILDFLAGS -j$CMAKEBUILDJOBS" 175 | env["CMAKEINSTALLCOM"] = "$CMAKE --install ${TARGET.dir} $CMAKEINSTALLFLAGS" 176 | env["BUILDERS"]["CMake"] = SCons.Builder.Builder(generator=cmake_generator, emitter=cmake_emitter) 177 | env.AddMethod(cmake_build, "CMakeBuild") 178 | -------------------------------------------------------------------------------- /tools/git2.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def build_library(env, deps): 5 | config = { 6 | "CMAKE_BUILD_TYPE": "RelWithDebInfo" if env["debug_symbols"] else "Release", 7 | "OPENSSL_USE_STATIC_LIBS": 1, 8 | "OPENSSL_INCLUDE_DIR": env["SSL_INCLUDE"], 9 | "OPENSSL_SSL_LIBRARY": env["SSL_LIBRARY"], 10 | "OPENSSL_CRYPTO_LIBRARY": env["SSL_CRYPTO_LIBRARY"], 11 | "OPENSSL_ROOT_DIR": env["SSL_INSTALL"], 12 | "BUILD_TESTS": 0, 13 | "BUILD_CLI": 0, 14 | "BUILD_EXAMPLES": 0, 15 | "BUILD_FUZZERS": 0, 16 | "USE_SSH": 1, 17 | "USE_HTTPS": 1, 18 | "USE_SHA1": 1, 19 | "USE_BUNDLED_ZLIB": 1, 20 | "USE_HTTP_PARSER": "builtin", 21 | "REGEX_BACKEND": "builtin", 22 | "USE_HTTPS": "OpenSSL", 23 | "USE_SHA1": "OpenSSL", 24 | "BUILD_SHARED_LIBS": 0, 25 | "LINK_WITH_STATIC_LIBRARIES": 1, 26 | "LIBSSH2_INCLUDE_DIR": env.Dir("#thirdparty/ssh2/libssh2/include").abspath, 27 | "LIBSSH2_LIBRARY": deps[-1], 28 | "USE_WINHTTP": 0, 29 | "STATIC_CRT": env.get("use_static_cpp", True), 30 | "CMAKE_DISABLE_FIND_PACKAGE_ZLIB": 1, 31 | "CMAKE_DISABLE_FIND_PACKAGE_OPENSSL": 1, 32 | } 33 | 34 | if env["platform"] != "windows": 35 | config["CMAKE_C_FLAGS"] = "-fPIC" 36 | else: 37 | config["OPENSSL_ROOT_DIR"] = env["SSL_BUILD"] 38 | 39 | is_msvc = env.get("is_msvc", False) 40 | lib_ext = ".lib" if is_msvc else ".a" 41 | lib_prefix = "" if is_msvc else "lib" 42 | libs = ["{}git2{}".format(lib_prefix, lib_ext)] 43 | 44 | source = env.Dir("#thirdparty/git2/libgit2").abspath 45 | target = env.Dir("#bin/thirdparty/libgit2").abspath 46 | 47 | git2 = env.CMakeBuild( 48 | "#bin/thirdparty/git2/", 49 | "#thirdparty/git2/libgit2", 50 | cmake_options=config, 51 | cmake_outputs=libs, 52 | cmake_targets=[], 53 | dependencies=deps, 54 | ) 55 | 56 | env.Append(CPPPATH=["#thirdparty/git2/libgit2/include"]) 57 | env.Prepend(LIBS=git2[1:]) 58 | if env["platform"] == "windows": 59 | env.PrependUnique(LIBS=["secur32"]) 60 | 61 | return git2 62 | 63 | 64 | def exists(env): 65 | return "CMake" in env 66 | 67 | 68 | def generate(env): 69 | env.AddMethod(build_library, "BuildGIT2") 70 | -------------------------------------------------------------------------------- /tools/openssl.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | import SCons.Util 3 | import SCons.Builder 4 | import SCons.Action 5 | from SCons.Defaults import Mkdir 6 | from SCons.Variables import PathVariable, BoolVariable 7 | 8 | 9 | def ssl_platform_target(env): 10 | targets = {} 11 | platform = env["platform"] 12 | if platform == "linux": 13 | targets = { 14 | "x86_32": "linux-x86", 15 | "x86_64": "linux-x86_64", 16 | "arm64": "linux-aarch64", 17 | "arm32": "linux-armv4", 18 | "rv64": "linux64-riscv64", 19 | } 20 | elif platform == "android": 21 | targets = { 22 | "arm64": "android-arm64", 23 | "arm32": "android-arm", 24 | "x86_32": "android-x86", 25 | "x86_64": "android-x86_64", 26 | } 27 | elif platform == "macos": 28 | targets = { 29 | "x86_64": "darwin64-x86_64", 30 | "arm64": "darwin64-arm64", 31 | } 32 | elif platform == "ios": 33 | if env["ios_simulator"]: 34 | targets = { 35 | "x86_64": "iossimulator-xcrun", 36 | "arm64": "iossimulator-xcrun", 37 | } 38 | else: 39 | targets = { 40 | "arm64": "ios64-xcrun", 41 | "arm32": "ios-xcrun", 42 | } 43 | elif platform == "windows": 44 | if env.get("is_msvc", False): 45 | targets = { 46 | "x86_32": "VC-WIN32", 47 | "x86_64": "VC-WIN64A", 48 | } 49 | else: 50 | targets = { 51 | "x86_32": "mingw", 52 | "x86_64": "mingw64", 53 | } 54 | 55 | arch = env["arch"] 56 | target = targets.get(arch, "") 57 | if target == "": 58 | raise ValueError("Architecture '%s' not supported for platform: '%s'" % (arch, platform)) 59 | return target 60 | 61 | 62 | def ssl_platform_options(env): 63 | ssl_config_options = [ 64 | "no-ssl2", 65 | "no-ssl3", 66 | "no-weak-ssl-ciphers", 67 | "no-legacy", 68 | "no-shared", 69 | "no-tests", 70 | ] 71 | if env["platform"] == "windows": 72 | ssl_config_options.append("enable-capieng") 73 | return ssl_config_options 74 | 75 | 76 | def ssl_platform_flags(env): 77 | args = [] 78 | if env["platform"] == "android": 79 | if env.get("android_api_level", ""): 80 | api = int(env["android_api_level"]) 81 | args.append("-D__ANDROID_API__=%s" % api) 82 | elif env["platform"] == "macos": 83 | if env["macos_deployment_target"] != "default": 84 | args.append("-mmacosx-version-min=%s" % env["macos_deployment_target"]) 85 | # OSXCross toolchain setup. 86 | if sys.platform != "darwin" and "OSXCROSS_ROOT" in os.environ: 87 | for k in ["CC", "CXX", "AR", "AS", "RANLIB"]: 88 | args.append("%s=%s" % (k, env[k])) 89 | elif env["platform"] == "windows": 90 | is_win_host = sys.platform in ["win32", "msys", "cygwin"] 91 | if not (is_win_host or env.get("is_msvc", False)): 92 | mingw_prefixes = { 93 | "x86_32": "--cross-compile-prefix=i686-w64-mingw32-", 94 | "x86_64": "--cross-compile-prefix=x86_64-w64-mingw32-", 95 | } 96 | args.append(mingw_prefixes[env["arch"]]) 97 | return args 98 | 99 | 100 | def ssl_configure_args(env): 101 | if env.get("openssl_configure_options", ""): 102 | opts = SCons.Util.CLVar(env["openssl_configure_options"]) 103 | else: 104 | opts = ssl_platform_options(env) 105 | 106 | if env.get("openssl_configure_target", ""): 107 | target = [env["openssl_configure_target"]] 108 | else: 109 | target = [ssl_platform_target(env)] 110 | 111 | if env.get("openssl_configure_flags", ""): 112 | flags = SCons.Util.CLVar(env["openssl_configure_flags"]) 113 | else: 114 | flags = ssl_platform_flags(env) 115 | 116 | return opts + target + flags 117 | 118 | 119 | def ssl_emitter(target, source, env): 120 | return env["SSL_LIBS"], [env.File(env["SSL_SOURCE"] + "/Configure"), env.File(env["SSL_SOURCE"] + "/VERSION.dat")] 121 | 122 | 123 | def build_openssl(env, jobs=None): 124 | if env["SSL_EXTERNAL"]: 125 | # Setup the env to use the provided libraries, and return them without building. 126 | env.Prepend(CPPPATH=[env["SSL_INCLUDE"]]) 127 | env.Prepend(LIBPATH=[env["SSL_BUILD"]]) 128 | if env["platform"] == "windows": 129 | env.PrependUnique(LIBS=["crypt32", "ws2_32", "advapi32", "user32"]) 130 | env.Prepend(LIBS=env["SSL_LIBS"]) 131 | return [env["SSL_CRYPTO_LIBRARY"], env["SSL_LIBRARY"]] 132 | 133 | if jobs is None: 134 | jobs = int(env.GetOption("num_jobs")) 135 | 136 | # Since the OpenSSL build system does not support macOS universal binaries, we first need to build the two libraries 137 | # separately, then we join them together using lipo. 138 | if env["platform"] == "macos" and env["arch"] == "universal": 139 | build_envs = { 140 | "x86_64": env.Clone(), 141 | "arm64": env.Clone(), 142 | } 143 | arch_ssl = [] 144 | for arch in build_envs: 145 | benv = build_envs[arch] 146 | benv["arch"] = arch 147 | generate(benv) 148 | benv["SSLBUILDJOBS"] = max([1, int(jobs / len(build_envs))]) 149 | ssl = benv.OpenSSLBuilder() 150 | arch_ssl.extend(ssl) 151 | benv.NoCache(ssl) # Needs refactoring to properly cache generated headers. 152 | 153 | # x86_64 and arm64 includes are equivalent. 154 | env["SSL_INCLUDE"] = build_envs["arm64"]["SSL_INCLUDE"] 155 | 156 | # Join libraries using lipo. 157 | lipo_action = "lipo $SOURCES -create -output $TARGET" 158 | ssl_libs = list(map(lambda arch: build_envs[arch]["SSL_LIBRARY"], build_envs)) 159 | ssl_crypto_libs = list(map(lambda arch: build_envs[arch]["SSL_CRYPTO_LIBRARY"], build_envs)) 160 | ssl = env.Command(env["SSL_LIBRARY"], ssl_libs, lipo_action) 161 | ssl += env.Command(env["SSL_CRYPTO_LIBRARY"], ssl_crypto_libs, lipo_action) 162 | env.Depends(ssl, arch_ssl) 163 | else: 164 | benv = env.Clone() 165 | benv["SSLBUILDJOBS"] = jobs 166 | ssl = benv.OpenSSLBuilder() 167 | benv.NoCache(ssl) # Needs refactoring to properly cache generated headers. 168 | 169 | # Setup the environment to use the freshly built openssl. 170 | env.Prepend(CPPPATH=[env["SSL_INCLUDE"]]) 171 | env.Prepend(LIBPATH=[env["SSL_BUILD"]]) 172 | if env["platform"] == "windows": 173 | env.PrependUnique(LIBS=["crypt32", "ws2_32", "advapi32", "user32"]) 174 | env.Prepend(LIBS=env["SSL_LIBS"]) 175 | 176 | return ssl 177 | 178 | 179 | def ssl_generator(target, source, env, for_signature): 180 | # Strip the -j option for signature to avoid rebuilding when num_jobs changes. 181 | build = env["SSLBUILDCOM"].replace("-j$SSLBUILDJOBS", "") if for_signature else env["SSLBUILDCOM"] 182 | return [ 183 | Mkdir("$SSL_BUILD"), 184 | Mkdir("$SSL_INSTALL"), 185 | SCons.Action.Action("$SSLCONFIGCOM", "$SSLCONFIGCOMSTR"), 186 | SCons.Action.Action(build, "$SSLBUILDCOMSTR"), 187 | ] 188 | 189 | 190 | def options(opts): 191 | opts.Add(PathVariable("openssl_source", "Path to the openssl sources.", "thirdparty/openssl")) 192 | opts.Add("openssl_build", "Destination path of the openssl build.", "bin/thirdparty/openssl") 193 | opts.Add( 194 | "openssl_configure_options", 195 | "OpenSSL configure options override. Will use a reasonable default if not specified.", 196 | "", 197 | ) 198 | opts.Add( 199 | "openssl_configure_target", "OpenSSL configure target override, will be autodetected if not specified.", "" 200 | ) 201 | opts.Add( 202 | "openssl_configure_flags", 203 | "OpenSSL configure compiler flags override. Will be autodetected if not specified.", 204 | "", 205 | ) 206 | opts.Add( 207 | "openssl_external_crypto", 208 | 'An external libcrypto static library (e.g. "/usr/lib/x86_64-linux-gnu/libcrypto.a"). If not provided, OpenSSL will be built from source.', 209 | "", 210 | ) 211 | opts.Add( 212 | "openssl_external_ssl", 213 | 'An external libssl static library (e.g. "/usr/lib/x86_64-linux-gnu/libssl.a"). If not provided, OpenSSL will be built from source.', 214 | "", 215 | ) 216 | opts.Add( 217 | "openssl_external_include", 218 | 'An external OpenSSL "include" folder (e.g. "/usr/include/openssl").', 219 | "", 220 | ) 221 | 222 | 223 | def exists(env): 224 | return True 225 | 226 | 227 | def generate(env): 228 | env.AddMethod(build_openssl, "OpenSSL") 229 | 230 | # Check if the user specified infos about external OpenSSL files. 231 | external_opts = ["openssl_external_crypto", "openssl_external_ssl", "openssl_external_include"] 232 | is_set = lambda k: env.get(k, "") != "" 233 | if any(map(is_set, external_opts)): 234 | # Need provide the whole (crypto, ssl, include) triple to proceed. 235 | if not all(map(is_set, external_opts)): 236 | print('Error: The options "%s" must all be set to use a external library.' % '", "'.join(external_opts)) 237 | sys.exit(255) 238 | 239 | env["SSL_CRYPTO_LIBRARY"] = env.File("${openssl_external_crypto}") 240 | env["SSL_LIBRARY"] = env.File("${openssl_external_ssl}") 241 | env["SSL_BUILD"] = env.Dir("${SSL_LIBRARY.dir}").abspath 242 | env["SSL_INSTALL"] = env.Dir("${SSL_LIBRARY.dir}").abspath 243 | env["SSL_INCLUDE"] = env.Dir("${openssl_external_include}").abspath 244 | env["SSL_LIBS"] = [env["SSL_LIBRARY"], env["SSL_CRYPTO_LIBRARY"]] 245 | env["SSL_EXTERNAL"] = True 246 | return 247 | 248 | # We will need to build our own OpenSSL library. 249 | env["SSL_EXTERNAL"] = False 250 | 251 | # Android needs the NDK in ENV, and proper PATH setup. 252 | if env["platform"] == "android" and env["ENV"].get("ANDROID_NDK_ROOT", "") == "": 253 | cc_path = os.path.dirname(env["CC"]) 254 | if cc_path and cc_path not in env["ENV"]: 255 | env.PrependENVPath("PATH", cc_path) 256 | if "ANDROID_NDK_ROOT" not in env["ENV"]: 257 | env["ENV"]["ANDROID_NDK_ROOT"] = env.get("ANDROID_NDK_ROOT", os.environ.get("ANDROID_NDK_ROOT", "")) 258 | 259 | env["SSL_SOURCE"] = env.Dir(env["openssl_source"]).abspath 260 | env["SSL_BUILD"] = env.Dir(env["openssl_build"] + "/{}/{}".format(env["platform"], env["arch"])).abspath 261 | env["SSL_INSTALL"] = env.Dir(env["SSL_BUILD"] + "/dest").abspath 262 | env["SSL_INCLUDE"] = env.Dir(env["SSL_INSTALL"] + "/include").abspath 263 | lib_ext = ".lib" if env.get("is_msvc", False) else ".a" 264 | env["SSL_LIBRARY"] = env.File(env["SSL_BUILD"] + "/libssl" + lib_ext) 265 | env["SSL_CRYPTO_LIBRARY"] = env.File(env["SSL_BUILD"] + "/libcrypto" + lib_ext) 266 | env["SSL_LIBS"] = [env["SSL_LIBRARY"], env["SSL_CRYPTO_LIBRARY"]] 267 | 268 | # Configure action 269 | env["PERL"] = env.get("PERL", "perl") 270 | env["_ssl_configure_args"] = ssl_configure_args 271 | env["SSLPLATFORMCONFIG"] = "${_ssl_configure_args(__env__)}" 272 | env["SSLCONFFLAGS"] = SCons.Util.CLVar("") 273 | # fmt: off 274 | env["SSLCONFIGCOM"] = 'cd ${TARGET.dir} && $PERL -- ${SOURCE.abspath} --prefix="${SSL_INSTALL}" --openssldir="${SSL_INSTALL}" $SSLPLATFORMCONFIG $SSLCONFFLAGS' 275 | # fmt: on 276 | 277 | # Build action 278 | env["SSLBUILDJOBS"] = "${__env__.GetOption('num_jobs')}" 279 | # fmt: off 280 | env["SSLBUILDCOM"] = "make -j$SSLBUILDJOBS -C ${TARGET.dir} && make -j$SSLBUILDJOBS -C ${TARGET.dir} install_sw install_ssldirs" 281 | # fmt: on 282 | 283 | # Windows MSVC needs to build using NMake 284 | if env["platform"] == "windows" and env.get("is_msvc", False): 285 | env["SSLBUILDCOM"] = "cd ${TARGET.dir} && nmake install_sw install_ssldirs" 286 | 287 | env["BUILDERS"]["OpenSSLBuilder"] = SCons.Builder.Builder(generator=ssl_generator, emitter=ssl_emitter) 288 | env.AddMethod(build_openssl, "OpenSSL") 289 | -------------------------------------------------------------------------------- /tools/ssh2.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def build_library(env, deps): 5 | config = { 6 | "CMAKE_BUILD_TYPE": "RelWithDebInfo" if env["debug_symbols"] else "Release", 7 | "OPENSSL_USE_STATIC_LIBS": 1, 8 | "OPENSSL_INCLUDE_DIR": env["SSL_INCLUDE"], 9 | "OPENSSL_SSL_LIBRARY": env["SSL_LIBRARY"].abspath, 10 | "OPENSSL_CRYPTO_LIBRARY": env["SSL_CRYPTO_LIBRARY"].abspath, 11 | "OPENSSL_ROOT_DIR": env["SSL_INSTALL"], 12 | "BUILD_EXAMPLES": 0, 13 | "BUILD_TESTING": 0, 14 | "BUILD_SHARED_LIBS": 0, 15 | "CMAKE_DISABLE_FIND_PACKAGE_ZLIB": 1, 16 | "CMAKE_DISABLE_FIND_PACKAGE_OPENSSL": 1, 17 | "CRYPTO_BACKEND": "OpenSSL", 18 | } 19 | 20 | if env["platform"] != "windows": 21 | config["CMAKE_C_FLAGS"] = "-fPIC" 22 | else: 23 | config["OPENSSL_ROOT_DIR"] = env["SSL_BUILD"] 24 | 25 | is_msvc = env.get("is_msvc", False) 26 | lib_ext = ".lib" if is_msvc else ".a" 27 | libs = ["src/libssh2{}".format(lib_ext)] 28 | 29 | source = env.Dir("#thirdparty/ssh2/libssh2").abspath 30 | target = env.Dir("#bin/thirdparty/libssh2").abspath 31 | 32 | ssh2 = env.CMakeBuild( 33 | "#bin/thirdparty/ssh2/", 34 | "#thirdparty/ssh2/libssh2", 35 | cmake_options=config, 36 | cmake_outputs=libs, 37 | cmake_targets=[], 38 | dependencies=deps, 39 | ) 40 | 41 | env.Append(CPPPATH=["#thirdparty/ssh2/libssh2/include"]) 42 | env.Prepend(LIBS=ssh2[1:]) 43 | 44 | return ssh2 45 | 46 | 47 | def exists(env): 48 | return "CMake" in env 49 | 50 | 51 | def generate(env): 52 | env.AddMethod(build_library, "BuildSSH2") 53 | --------------------------------------------------------------------------------