diff options
author | Théophane Hufschmitt <theophane.hufschmitt@tweag.io> | 2022-05-04 14:32:21 +0200 |
---|---|---|
committer | Théophane Hufschmitt <theophane.hufschmitt@tweag.io> | 2022-05-04 14:38:59 +0200 |
commit | e68676e6c859815f40079b6340399d82cc1913b6 (patch) | |
tree | 830a0e12317ce9e467556c79d9926e7c693bad5b /src/libfetchers | |
parent | 470e27ce8008ba952225b9f9f7f61a9627376f33 (diff) |
Fix the parsing of the sourcehut refs file
Since a26be9f3b89be2ee90c6358250b9889b37f95cf8, the same parser is used
to parse the result of sourcehut’s `HEAD` endpoint (coming from [git
dumb protocol]) and the output of `git ls-remote`. However, they are very
slightly different (the former doesn’t specify the current reference
since it’s implied to be `HEAD`).
Unify both, and make the parser a bit more robust and understandable (by
making it more typed and adding tests for it)
[git dumb protocol]: https://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols#_the_dumb_protocol
Diffstat (limited to 'src/libfetchers')
-rw-r--r-- | src/libfetchers/git-utils.cc | 27 | ||||
-rw-r--r-- | src/libfetchers/git-utils.hh | 23 | ||||
-rw-r--r-- | src/libfetchers/git.cc | 19 | ||||
-rw-r--r-- | src/libfetchers/github.cc | 12 |
4 files changed, 18 insertions, 63 deletions
diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc deleted file mode 100644 index b2d6b7893..000000000 --- a/src/libfetchers/git-utils.cc +++ /dev/null @@ -1,27 +0,0 @@ -#include "git-utils.hh" - -#include <regex> - -std::optional<std::string> parseListReferenceHeadRef(std::string_view line) -{ - const static std::regex head_ref_regex("^ref: ([^\\s]+)\\t+HEAD$"); - std::match_results<std::string_view::const_iterator> match; - if (std::regex_match(line.cbegin(), line.cend(), match, head_ref_regex)) { - return match[1]; - } else { - return std::nullopt; - } -} - -std::optional<std::string> parseListReferenceForRev(std::string_view rev, std::string_view line) -{ - const static std::regex rev_regex("^([^\\t]+)\\t+(.*)$"); - std::match_results<std::string_view::const_iterator> match; - if (!std::regex_match(line.cbegin(), line.cend(), match, rev_regex)) { - return std::nullopt; - } - if (rev != match[2].str()) { - return std::nullopt; - } - return match[1]; -} diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh deleted file mode 100644 index 946a68a9e..000000000 --- a/src/libfetchers/git-utils.hh +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include <string> -#include <string_view> -#include <optional> - -// Parses the HEAD ref as reported by `git ls-remote --symref` -// -// Returns the head branch name as reported by `git ls-remote --symref`, e.g., if -// ls-remote returns the output below, "main" is returned based on the ref line. -// -// ref: refs/heads/main HEAD -// -// If the repository is in 'detached head' state (HEAD is pointing to a rev -// instead of a branch), parseListReferenceForRev("HEAD") may be used instead. -std::optional<std::string> parseListReferenceHeadRef(std::string_view line); - -// Parses a reference line from `git ls-remote --symref`, e.g., -// parseListReferenceForRev("refs/heads/master", line) will return 6926... -// given the line below. -// -// 6926beab444c33fb57b21819b6642d032016bb1e refs/heads/master -std::optional<std::string> parseListReferenceForRev(std::string_view rev, std::string_view line); diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 266246fe9..d23a820a4 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -6,7 +6,7 @@ #include "url-parts.hh" #include "pathlocks.hh" #include "util.hh" -#include "git-utils.hh" +#include "git.hh" #include "fetch-settings.hh" @@ -72,13 +72,16 @@ std::optional<std::string> readHead(const Path & path) std::string_view line = output; line = line.substr(0, line.find("\n")); - if (const auto ref = parseListReferenceHeadRef(line); ref) { - debug("resolved HEAD ref '%s' for repo '%s'", *ref, path); - return *ref; - } - if (const auto rev = parseListReferenceForRev("HEAD", line); rev) { - debug("resolved HEAD rev '%s' for repo '%s'", *rev, path); - return *rev; + if (const auto parseResult = git::parseLsRemoteLine(line)) { + switch (parseResult->kind) { + case git::LsRemoteRefLine::Kind::Symbolic: + debug("resolved HEAD ref '%s' for repo '%s'", parseResult->target, path); + break; + case git::LsRemoteRefLine::Kind::Object: + debug("resolved HEAD rev '%s' for repo '%s'", parseResult->target, path); + break; + } + return parseResult->target; } return std::nullopt; } diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index 1bdf2759f..a1084c984 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -4,7 +4,7 @@ #include "store-api.hh" #include "types.hh" #include "url-parts.hh" -#include "git-utils.hh" +#include "git.hh" #include "fetchers.hh" #include "fetch-settings.hh" @@ -383,11 +383,11 @@ struct SourceHutInputScheme : GitArchiveInputScheme std::string line; getline(is, line); - auto r = parseListReferenceHeadRef(line); - if (!r) { + auto remoteLine = git::parseLsRemoteLine(line); + if (!remoteLine) { throw BadURL("in '%d', couldn't resolve HEAD ref '%d'", input.to_string(), ref); } - ref_uri = *r; + ref_uri = remoteLine->target; } else { ref_uri = fmt("refs/(heads|tags)/%s", ref); } @@ -399,7 +399,9 @@ struct SourceHutInputScheme : GitArchiveInputScheme std::string line; std::optional<std::string> id; while(!id && getline(is, line)) { - id = parseListReferenceForRev(ref_uri, line); + auto parsedLine = git::parseLsRemoteLine(line); + if (parsedLine && parsedLine->reference == ref_uri) + id = parsedLine->target; } if(!id) |