Class: RepoTender::CLI::Sync::Run

Inherits:
Dry::CLI::Command
  • Object
show all
Includes:
GlobalOptions
Defined in:
lib/repo_tender/cli/sync.rb

Instance Method Summary collapse

Methods included from GlobalOptions

included

Instance Method Details

#call(repo: nil, plain: nil, json: nil, no_color: nil, quiet: nil) ⇒ Object



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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/repo_tender/cli/sync.rb', line 30

def call(repo: nil, plain: nil, json: nil, no_color: nil, quiet: nil, **)
  paths = CLI.make_paths
  paths.ensure!
  config = Config::Store.load(paths.config_file).success

  # Log rotation pre-step (slice-4 gate G5). launchd owns
  # the stdout/stderr redirect via StandardOutPath /
  # StandardErrorPath; the sync process rotates those
  # files at the start of each run so the previous run's
  # log doesn't grow unbounded. The rotator renames the
  # file to a timestamped archive (preserving bytes); the
  # current process's inherited fd still points to the
  # renamed file, so writes during this run succeed.
  # launchd opens a fresh file at the original path on
  # the next spawn. No-op when the log is missing or
  # under-threshold (sync tests in G4 stay green).
  rotate_plist_logs(paths)
  if repo
    target = scope_target(repo)
    return fail_with(self, "invalid repo reference: #{repo.inspect} (expected host/owner/name)") if target.failure?

    match = target.success
    found = config.repos.find { |r| Repo::Helpers.same_repo?(r, match) }
    if found.nil?
      return fail_with(self, "no such tracked repo: #{Repo::Helpers.format_ref(match)}")
    end
    # Filtered config: only the one matched repo, no orgs
    # (org expansion would discover other repos — that's
    # exactly the G4 "other repo gets no state row" test
    # path, so we explicitly empty orgs here).
    config = Config::Store.with(config, repos: [found], orgs: [])
    out.puts "scoping sync to: #{Repo::Helpers.format_ref(found)}"
  end

  mode = UI::Mode.resolve(
    flags: {plain: plain, json: json, no_color: no_color, quiet: quiet},
    env: CLI.env,
    out: out
  )
  reporter = if mode.format == :json
    UI::JsonReporter.new(out)
  elsif mode.animate
    UI::InteractiveReporter.new(out, mode: mode)
  else
    UI::PlainReporter.new(out, mode: mode)
  end

  result = RepoTender::Sync::Engine.new(reporter: reporter).call(config: config, paths: paths)
  if result.failure?
    return fail_with(self, "sync failed: #{format_failure(result.failure)}")
  end

  new_state = result.success
  n = new_state.repos.size
  out.puts "synced #{n} repo(s)"
  CLI.record_outcome(Outcome.new(exit_code: 0))
end