|
1 | 1 |
|
2 | 2 | #include "git.hpp" |
| 3 | +#include "defer.hpp" |
3 | 4 | #include <git2.h> |
4 | 5 | #include <mutex> |
5 | 6 | #include <format> |
@@ -159,13 +160,84 @@ class git_lib { |
159 | 160 | return r; |
160 | 161 | } |
161 | 162 |
|
162 | | -//[[nodiscard]] std::expected<git_oid, git_error> git_hash(std::string const& url, std::string const& branch) |
163 | | -//{ |
164 | | -// |
165 | | -//} |
| 163 | +/** Check if one of the remote has the correct branch checked out. |
| 164 | + * |
| 165 | + * @param repository The repository to check all the remotes |
| 166 | + * @param branch The branch to compare. |
| 167 | + * @retval true The correct branch was checked out. |
| 168 | + * @retval false Another branch was checked out. |
| 169 | + * @retval error An error during query. |
| 170 | + */ |
| 171 | +[[nodiscard]] std::expected<bool, git_error> repository_matches_branch(::git_repository *repository, std::string const& branch) |
| 172 | +{ |
| 173 | + |
| 174 | +} |
| 175 | + |
| 176 | +/** Check if one of the remote has a url that matches the given url. |
| 177 | + * |
| 178 | + * @param repository The repository to check all the remotes |
| 179 | + * @param url The url to compare. |
| 180 | + * @retval true The url is a remote of the @a repository. |
| 181 | + * @retval false None of the remotes match. |
| 182 | + * @retval error An error during query. |
| 183 | + */ |
| 184 | +[[nodiscard]] std::expected<bool, git_error> repository_matches_url(::git_repository *repository, std::string const& url) |
| 185 | +{ |
| 186 | + assert(repository != nullptr); |
| 187 | + |
| 188 | + auto remote_names = ::git_strarray{}; |
| 189 | + if (auto const result = ::git_remote_list(&remote_names, repository); result != GIT_OK) { |
| 190 | + return std::unexpected{make_git_error(result)}; |
| 191 | + } |
| 192 | + auto const _ = defer{[&]{ ::git_strarray_dispose(&remote_names); }}; |
| 193 | + |
| 194 | + for (auto i = 0uz; i != remote_names.count; ++i) { |
| 195 | + ::git_remote *remote = nullptr; |
| 196 | + if (auto const result = ::git_remote_lookup(&remote, repository, remote_names.strings[i]); result != GIT_OK) { |
| 197 | + return std::unexpected{make_git_error(result)}; |
| 198 | + } |
| 199 | + auto const _ = defer{[&]{ ::git_remote_free(remote); }}; |
| 200 | + |
| 201 | + auto const remote_url = ::git_remote_url(remote); |
| 202 | + if (remote_url and url == remote_url) { |
| 203 | + return true; |
| 204 | + } |
| 205 | + } |
| 206 | + |
| 207 | + return false; |
| 208 | +} |
| 209 | + |
| 210 | +[[nodiscard]] git_error git_fetch_and_update(std::string const& url, std::string const& branch, std::filesystem::path path, git_checkout_flags flags) |
| 211 | +{ |
| 212 | + auto const& _ = git_lib_initialize(); |
| 213 | + |
| 214 | + auto r = git_error::ok; |
| 215 | + |
| 216 | + ::git_repository *repository = nullptr; |
| 217 | + if (auto const result = ::git_repository_open(&repository, url.c_str()); result != GIT_OK) { |
| 218 | + return make_git_error(result); |
| 219 | + } |
| 220 | + auto const d1 = defer{[&]{ ::git_repository_free(repository); }}; |
| 221 | + |
| 222 | + if (auto result = repository_matches_url(repository, url)) { |
| 223 | + if (not *result) { |
| 224 | + std::print("The repository at {}, does not have a remote with the url {}", path.string(), url); |
| 225 | + return git_error::remote_url_mismatch; |
| 226 | + } |
| 227 | + } else { |
| 228 | + return result.error(); |
| 229 | + } |
| 230 | + |
| 231 | + if (auto result = repository_matches_branch(repository, branch)) { |
| 232 | + |
| 233 | + } |
| 234 | +} |
166 | 235 |
|
167 | 236 | [[nodiscard]] git_error git_clone(std::string const& url, std::string const& branch, std::filesystem::path path) |
168 | 237 | { |
| 238 | + auto const& _ = git_lib_initialize(); |
| 239 | + |
| 240 | + |
169 | 241 | auto force_checkout = false; |
170 | 242 |
|
171 | 243 | auto ref_list = git_references{}; |
|
0 commit comments