feat(freeze): no authors in the config, no author check
A repository that takes commits from people it cannot list has no way to freeze a range today: a null `authors` falls back to `git config user.email`, so every foreign author or committer fails. Null, or no key, now means neither is checked; the freeze warns that it did not check them and records `authors` as null. A list is checked as before. An empty list, which no commit could pass, is a config error that points at null. Released as 1.1.0.
This commit is contained in:
parent
0d3d8ed2d2
commit
c6b4d78245
10 changed files with 52 additions and 49 deletions
|
|
@ -9,7 +9,6 @@ import :Core;
|
|||
import :Plan;
|
||||
import :Tools;
|
||||
import :PgWire;
|
||||
import :Process;
|
||||
import :Platform;
|
||||
import :Prompt;
|
||||
import std;
|
||||
|
|
@ -151,8 +150,8 @@ namespace Crafter::Review::Config {
|
|||
// when HEAD tracks nothing; base: always merge-base HEAD
|
||||
// <base>..HEAD, the whole pull request.
|
||||
{"rangeFrom", "upstream"},
|
||||
// Author and committer emails the freeze accepts; null: the
|
||||
// repository's `git config user.email`.
|
||||
// Author and committer emails the freeze accepts; null: neither
|
||||
// is checked.
|
||||
{"authors", nullptr},
|
||||
// forbid | allow: Assisted-by / Co-Authored-By trailers in the
|
||||
// range.
|
||||
|
|
@ -266,6 +265,8 @@ namespace Crafter::Review::Config {
|
|||
return a.is_string() && a.get_ref<const std::string&>().contains('@');
|
||||
}))) {
|
||||
out.emplace_back("authors must be null or a list of email addresses");
|
||||
} else if (authors.is_array() && authors.empty()) {
|
||||
out.emplace_back("authors is an empty list, which no commit passes - null leaves author and committer unchecked");
|
||||
}
|
||||
for (const std::string_view key : {"allowDirty", "gate0"}) {
|
||||
if (!AllStrings(Dyn::At(config, key))) out.push_back(std::format("{} must be a list of strings", key));
|
||||
|
|
@ -453,21 +454,12 @@ namespace Crafter::Review::Config {
|
|||
return copy;
|
||||
}
|
||||
|
||||
std::string GitUserEmail(const fs::path& repo) {
|
||||
const Process::Captured run = Process::Run({"git", "-C", repo.string(), "config", "user.email"});
|
||||
return run.returnCode == 0 ? Dyn::Strip(Dyn::UniversalNewlines(Dyn::DecodeReplace(run.out))) : std::string();
|
||||
}
|
||||
|
||||
std::vector<std::string> Authors(const Json& config, const fs::path& repo) {
|
||||
std::optional<std::vector<std::string>> Authors(const Json& config) {
|
||||
const Json& authors = Dyn::Get(config, "authors");
|
||||
if (Dyn::Truthy(authors)) {
|
||||
std::vector<std::string> out;
|
||||
for (const Json& author : authors) out.push_back(Dyn::Str(author));
|
||||
return out;
|
||||
}
|
||||
const std::string email = GitUserEmail(repo);
|
||||
if (email.empty()) return {};
|
||||
return {email};
|
||||
if (!authors.is_array()) return std::nullopt;
|
||||
std::vector<std::string> out;
|
||||
for (const Json& author : authors) out.push_back(Dyn::Str(author));
|
||||
return out;
|
||||
}
|
||||
|
||||
std::map<std::string, fs::path> LensSectionsOf(const Json& config, const fs::path& repo) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue