diff --git a/bake.rb b/bake.rb index 55de3d5..91a9546 100644 --- a/bake.rb +++ b/bake.rb @@ -10,6 +10,7 @@ $LOAD_PATH.unshift(LIB_PATH) unless $LOAD_PATH.include?(LIB_PATH) require "pressa/drafts" require "pressa/coverage" require "pressa/publish" +require "pressa/git" DRAFTS_DIR = "public/drafts".freeze PUBLISH_HOST = "mudge".freeze @@ -272,12 +273,11 @@ end def preferred_remote upstream = capture_command_optional("git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}").strip upstream_remote = upstream.split("/").first unless upstream.empty? - return upstream_remote if upstream_remote && !upstream_remote.empty? - remotes = capture_command("git", "remote").lines.map(&:strip).reject(&:empty?) - abort "Error: no git remotes configured; pass baseline=." if remotes.empty? - remotes.include?("origin") ? "origin" : remotes.first + Pressa::Git.choose_remote(remotes:, upstream_remote:) +rescue Pressa::Git::Error => e + abort "Error: #{e.message}" end def remote_default_branch_ref(remote) diff --git a/lib/pressa.rb b/lib/pressa.rb index a55a4d5..a834794 100644 --- a/lib/pressa.rb +++ b/lib/pressa.rb @@ -9,6 +9,7 @@ require "pressa/config/loader" require "pressa/drafts" require "pressa/coverage" require "pressa/publish" +require "pressa/git" module Pressa def self.create_site(source_path: ".", url_override: nil, output_format: "html") diff --git a/lib/pressa/git.rb b/lib/pressa/git.rb new file mode 100644 index 0000000..d8142ad --- /dev/null +++ b/lib/pressa/git.rb @@ -0,0 +1,23 @@ +module Pressa + # Pure git-related decisions for the coverage tasks. The actual git commands + # run in bake.rb; this just decides which remote to treat as canonical. + module Git + class Error < StandardError; end + + # Remotes are preferred in this order when nothing else picks one. + DEFAULT_REMOTE_PREFERENCE = %w[github origin].freeze + + module_function + + # Pick the remote to resolve the coverage baseline against. An explicit + # upstream wins; otherwise fall back through the preference list, then to + # the first configured remote. + def choose_remote(remotes:, upstream_remote: nil, preference: DEFAULT_REMOTE_PREFERENCE) + return upstream_remote unless upstream_remote.to_s.empty? + + raise Error, "no git remotes configured; pass baseline=." if remotes.empty? + + preference.find { |name| remotes.include?(name) } || remotes.first + end + end +end diff --git a/test/git_test.rb b/test/git_test.rb new file mode 100644 index 0000000..63471ec --- /dev/null +++ b/test/git_test.rb @@ -0,0 +1,32 @@ +require "test_helper" + +class Pressa::GitTest < Minitest::Test + def test_choose_remote_prefers_github_over_origin + assert_equal("github", Pressa::Git.choose_remote(remotes: ["origin", "github"])) + end + + def test_choose_remote_falls_back_to_origin_when_no_github + assert_equal("origin", Pressa::Git.choose_remote(remotes: ["origin", "mirror"])) + end + + def test_choose_remote_falls_back_to_first_remote_when_neither_preferred + assert_equal("mirror", Pressa::Git.choose_remote(remotes: ["mirror", "backup"])) + end + + def test_choose_remote_honours_an_explicit_upstream_remote + assert_equal("fork", Pressa::Git.choose_remote(remotes: ["origin", "github"], upstream_remote: "fork")) + end + + def test_choose_remote_returns_upstream_even_without_other_remotes + assert_equal("fork", Pressa::Git.choose_remote(remotes: [], upstream_remote: "fork")) + end + + def test_choose_remote_raises_when_no_remotes_and_no_upstream + error = assert_raises(Pressa::Git::Error) { Pressa::Git.choose_remote(remotes: []) } + assert_match(/no git remotes/, error.message) + end + + def test_choose_remote_accepts_a_custom_preference_order + assert_equal("upstream", Pressa::Git.choose_remote(remotes: ["origin", "upstream"], preference: ["upstream"])) + end +end