├── .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 | [](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 |
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 |
--------------------------------------------------------------------------------