Class: Ace::Git::Worktree::Molecules::PullRequestCheckoutPreparer

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/git/worktree/molecules/pull_request_checkout_preparer.rb

Overview

Fetches the exact source repository/ref declared by PR evidence and proves the fetched commit before any worktree is created.

Canonical-repository and fork source URLs are equally valid: the fetch goes through a matching local remote when one exists, and by explicit URL otherwise (no remote ref is created for URL fetches).

Constant Summary collapse

DEFAULT_TIMEOUT =
60

Instance Method Summary collapse

Constructor Details

#initialize(timeout: DEFAULT_TIMEOUT) ⇒ PullRequestCheckoutPreparer

Returns a new instance of PullRequestCheckoutPreparer.

Parameters:

  • timeout (Integer) (defaults to: DEFAULT_TIMEOUT) —

    git command timeout in seconds



19
20
21
# File 'lib/ace/git/worktree/molecules/pull_request_checkout_preparer.rb', line 19

def initialize(timeout: DEFAULT_TIMEOUT)
  @timeout = timeout
end

Instance Method Details

#prepare(evidence) ⇒ Hash

Fetch the declared source ref and verify its SHA against the evidence head.

Parameters:

  • evidence (Ace::Git::ProviderPullRequest) —

    normalized PR evidence

Returns:

  • (Hash) —

    local_ref:, sha:, remote_tracking:, error: local_ref is the exact verified commit SHA (immutable), safe for git worktree add even if later fetches move FETCH_HEAD.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/ace/git/worktree/molecules/pull_request_checkout_preparer.rb', line 30

def prepare(evidence)
  head_url = evidence.head_repository_url
  head_ref = evidence.head_ref
  return error_result("PR evidence is missing the source repository URL") if head_url.nil? || head_url.empty?
  return error_result("PR evidence is missing the source branch") if head_ref.nil? || head_ref.empty?
  return error_result("PR evidence is missing the exact head SHA") unless evidence.head_sha

  local_remote = matching_local_remote(head_url)
  fetch_source = local_remote || head_url
  fetch_desc = "#{head_url}@#{head_ref}"

  fetch_result = Ace::Git::Worktree::Atoms::GitCommand.execute(
    "fetch", fetch_source, head_ref, timeout: @timeout
  )
  return error_result("Failed to fetch #{fetch_desc}: #{fetch_result[:error]}") unless fetch_result[:success]

  sha = resolve_fetch_head
  return error_result("Cannot resolve fetched commit for #{fetch_desc}") unless sha

  if sha != evidence.head_sha
    return error_result(
      "Fetched head #{sha} does not match PR evidence head #{evidence.head_sha} " \
      "(#{head_url}@#{head_ref}); the PR head moved since the evidence was captured"
    )
  end

  {
    success: true,
    # The immutable verified SHA, not FETCH_HEAD: a later fetch must
    # never be able to change what the worktree is created from.
    local_ref: sha,
    sha: sha,
    remote_tracking: local_remote ? "#{local_remote}/#{head_ref}" : nil,
    error: nil
  }
end