space-architect 1.3.0 → 2.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +103 -0
- data/README.md +248 -155
- data/exe/architect +1 -1
- data/exe/space +2 -2
- data/exe/src +13 -0
- data/lib/space_architect/architect_mission.rb +84 -53
- data/lib/space_architect/cli/architect.rb +92 -132
- data/lib/space_architect/cli/research.rb +94 -0
- data/lib/space_architect/cli/space.rb +25 -31
- data/lib/space_architect/cli/src.rb +20 -14
- data/lib/space_architect/cli.rb +22 -22
- data/lib/space_architect/dispatcher.rb +5 -1
- data/lib/space_architect/harness.rb +123 -16
- data/lib/space_architect/research/mux.rb +127 -0
- data/lib/space_architect/research/registry.rb +70 -0
- data/lib/space_architect/research/renderer.rb +101 -0
- data/lib/space_architect/research/run.rb +7 -0
- data/lib/space_architect/research/supervisor.rb +108 -0
- data/lib/space_architect/research.rb +13 -0
- data/lib/space_architect/run_creator.rb +53 -0
- data/lib/space_architect/skill_installer.rb +81 -79
- data/lib/space_architect.rb +5 -20
- data/lib/{space_architect → space_core}/atomic_write.rb +1 -1
- data/lib/space_core/cli/base_command.rb +19 -0
- data/lib/space_core/cli/config.rb +49 -0
- data/lib/space_core/cli/current.rb +16 -0
- data/lib/space_core/cli/help.rb +110 -0
- data/lib/space_core/cli/helpers.rb +115 -0
- data/lib/space_core/cli/init.rb +29 -0
- data/lib/space_core/cli/list.rb +24 -0
- data/lib/space_core/cli/new.rb +38 -0
- data/lib/space_core/cli/path.rb +16 -0
- data/lib/space_core/cli/repeatable_options.rb +75 -0
- data/lib/space_core/cli/repo.rb +76 -0
- data/lib/space_core/cli/shell.rb +125 -0
- data/lib/space_core/cli/show.rb +21 -0
- data/lib/space_core/cli/status.rb +33 -0
- data/lib/space_core/cli/use.rb +17 -0
- data/lib/space_core/cli.rb +171 -0
- data/lib/{space_architect → space_core}/config.rb +1 -1
- data/lib/{space_architect → space_core}/errors.rb +1 -1
- data/lib/{space_architect → space_core}/git_client.rb +1 -1
- data/lib/{space_architect → space_core}/mise_client.rb +1 -1
- data/lib/{space_architect → space_core}/repo_reference.rb +1 -1
- data/lib/{space_architect → space_core}/repo_resolver.rb +1 -1
- data/lib/{space_architect → space_core}/shell_integration.rb +1 -1
- data/lib/{space_architect → space_core}/slugger.rb +1 -1
- data/lib/{space_architect → space_core}/space.rb +1 -1
- data/lib/{space_architect → space_core}/space_store.rb +12 -12
- data/lib/{space_architect → space_core}/state.rb +1 -1
- data/lib/{space_architect → space_core}/terminal.rb +1 -1
- data/lib/space_core/version.rb +7 -0
- data/lib/{space_architect → space_core}/warnings.rb +1 -1
- data/lib/{space_architect → space_core}/xdg.rb +1 -1
- data/lib/space_core.rb +24 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/clone.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/config.rb +7 -7
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/daemon.rb +46 -30
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/options.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/org.rb +9 -9
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/repo.rb +9 -9
- data/lib/space_src/cli/shell.rb +122 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/status.rb +7 -7
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/sync.rb +17 -17
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli.rb +42 -11
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cloner.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/contract.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/duration.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/model.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/store.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/forge/client.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/forge/github.rb +4 -4
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/launchd/agent.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/launchd/plist.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/log_rotator.rb +1 -1
- data/lib/space_src/migration.rb +43 -0
- data/lib/space_src/nav.rb +98 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/paths.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/client.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/git.rb +4 -4
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/status.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/shell.rb +1 -1
- data/lib/space_src/shell_integration.rb +321 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/state/lock.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/state/store.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/sync/engine.rb +12 -12
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/sync/repo_plan.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/interactive_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/json_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/mode.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/plain_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/version.rb +2 -2
- data/lib/space_src.rb +37 -0
- data/skill/architect/SKILL.md +2 -2
- data/skill/architect/research.md +46 -37
- metadata +115 -67
- data/lib/space_architect/cli/config.rb +0 -61
- data/lib/space_architect/cli/current.rb +0 -22
- data/lib/space_architect/cli/helpers.rb +0 -117
- data/lib/space_architect/cli/init.rb +0 -35
- data/lib/space_architect/cli/list.rb +0 -30
- data/lib/space_architect/cli/new.rb +0 -43
- data/lib/space_architect/cli/options.rb +0 -12
- data/lib/space_architect/cli/path.rb +0 -22
- data/lib/space_architect/cli/repo.rb +0 -88
- data/lib/space_architect/cli/shell.rb +0 -137
- data/lib/space_architect/cli/show.rb +0 -27
- data/lib/space_architect/cli/status.rb +0 -39
- data/lib/space_architect/cli/use.rb +0 -23
- data/lib/space_architect/version.rb +0 -5
- data/vendor/repo-tender/lib/space_architect/pristine.rb +0 -44
|
@@ -6,10 +6,10 @@ require "async/semaphore"
|
|
|
6
6
|
require "pathname"
|
|
7
7
|
require "time"
|
|
8
8
|
require "dry/monads"
|
|
9
|
-
require "
|
|
10
|
-
require "
|
|
9
|
+
require "space_src/scm/git"
|
|
10
|
+
require "space_src/cloner"
|
|
11
11
|
|
|
12
|
-
module
|
|
12
|
+
module Space::Core
|
|
13
13
|
class SpaceStore
|
|
14
14
|
include Dry::Monads[:result, :maybe]
|
|
15
15
|
|
|
@@ -46,7 +46,7 @@ module SpaceArchitect
|
|
|
46
46
|
init_git(path:, id:, git_client:) if git
|
|
47
47
|
state.touch_recent(id)
|
|
48
48
|
Success(space)
|
|
49
|
-
rescue
|
|
49
|
+
rescue Error => e
|
|
50
50
|
Failure(e)
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -67,7 +67,7 @@ module SpaceArchitect
|
|
|
67
67
|
if looks_like_path?(value)
|
|
68
68
|
begin
|
|
69
69
|
return Success(Space.load(File.expand_path(value)))
|
|
70
|
-
rescue
|
|
70
|
+
rescue Error => e
|
|
71
71
|
return Failure(e)
|
|
72
72
|
end
|
|
73
73
|
end
|
|
@@ -80,13 +80,13 @@ module SpaceArchitect
|
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
Failure(AmbiguousSpaceError.new("Space '#{value}' is ambiguous: #{matches.map(&:id).join(', ')}"))
|
|
83
|
-
rescue
|
|
83
|
+
rescue Error => e
|
|
84
84
|
Failure(e)
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
def current(from: Dir.pwd)
|
|
88
88
|
current_from_pwd(from:).to_result(CurrentSpaceMissingError.new("No current space found from #{from}. Run this inside a space or pass a space id."))
|
|
89
|
-
rescue
|
|
89
|
+
rescue Error => e
|
|
90
90
|
Failure(e)
|
|
91
91
|
end
|
|
92
92
|
|
|
@@ -112,15 +112,15 @@ module SpaceArchitect
|
|
|
112
112
|
find(identifier).fmap { |space| state.touch_recent(space.id); space }
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
-
def add_repo(spec, from: Dir.pwd, scm:
|
|
115
|
+
def add_repo(spec, from: Dir.pwd, scm: ::Space::Src::SCM::Git.new, cloner: nil, mise_client: MiseClient.new)
|
|
116
116
|
add_repos([spec], from:, scm:, cloner:, mise_client:).fmap(&:first)
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
-
def add_repos(specs, from: Dir.pwd, scm:
|
|
119
|
+
def add_repos(specs, from: Dir.pwd, scm: ::Space::Src::SCM::Git.new, cloner: nil, mise_client: MiseClient.new, reporter: nil)
|
|
120
120
|
current(from:).bind { |space| add_repos_to(space, specs, scm:, cloner:, mise_client:, reporter:) }
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
-
def add_repos_to(space, specs, scm:
|
|
123
|
+
def add_repos_to(space, specs, scm: ::Space::Src::SCM::Git.new, cloner: nil, mise_client: MiseClient.new, reporter: nil)
|
|
124
124
|
additions = prepare_repo_additions(space, specs)
|
|
125
125
|
first_error = nil
|
|
126
126
|
|
|
@@ -148,7 +148,7 @@ module SpaceArchitect
|
|
|
148
148
|
repo_data = space.add_repo(addition.fetch(:reference), relative_path: addition.fetch(:relative_path), now: now.call)
|
|
149
149
|
{ space: space, repo: repo_data, reference: addition.fetch(:reference), path: addition.fetch(:path) }
|
|
150
150
|
end)
|
|
151
|
-
rescue
|
|
151
|
+
rescue Error => e
|
|
152
152
|
Failure(e)
|
|
153
153
|
end
|
|
154
154
|
|
|
@@ -178,7 +178,7 @@ module SpaceArchitect
|
|
|
178
178
|
source = addition.fetch(:src_source)
|
|
179
179
|
|
|
180
180
|
if source&.directory?
|
|
181
|
-
actual_cloner = cloner ||
|
|
181
|
+
actual_cloner = cloner || ::Space::Src::Cloner.new(base_dir: config.src_dir)
|
|
182
182
|
result = actual_cloner.call(name: reference.full_name, into: destination.dirname.to_s)
|
|
183
183
|
raise GitError, "clone failed (copy): #{result.failure}" if result.failure?
|
|
184
184
|
else
|
data/lib/space_core.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "space_core/version"
|
|
4
|
+
|
|
5
|
+
module Space::Core
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
require "space_core/errors"
|
|
9
|
+
require "space_core/warnings"
|
|
10
|
+
Space::Core::Warnings.disable_experimental!
|
|
11
|
+
require "space_core/atomic_write"
|
|
12
|
+
require "space_core/xdg"
|
|
13
|
+
require "space_core/config"
|
|
14
|
+
require "space_core/state"
|
|
15
|
+
require "space_core/slugger"
|
|
16
|
+
require "space_core/space"
|
|
17
|
+
require "space_core/repo_reference"
|
|
18
|
+
require "space_core/repo_resolver"
|
|
19
|
+
require "space_core/git_client"
|
|
20
|
+
require "space_core/mise_client"
|
|
21
|
+
require "space_core/space_store"
|
|
22
|
+
require "space_core/shell_integration"
|
|
23
|
+
require "space_core/terminal"
|
|
24
|
+
require "space_core/cli"
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require "pastel"
|
|
4
4
|
require "dry/monads"
|
|
5
|
-
require "
|
|
6
|
-
require "
|
|
7
|
-
require "
|
|
5
|
+
require "space_src/cli"
|
|
6
|
+
require "space_src/cli/options"
|
|
7
|
+
require "space_src/cloner"
|
|
8
8
|
|
|
9
|
-
module
|
|
9
|
+
module Space::Src
|
|
10
10
|
module CLI
|
|
11
11
|
# `clone` command: APFS COW copy of an evergreen repo into a working dir.
|
|
12
12
|
# Resolves each NAME against config.base_dir and copies via cp -Rc.
|
|
@@ -52,4 +52,4 @@ module SpaceArchitect::Pristine
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
Space::Src::CLI::Registry.register "clone", Space::Src::CLI::Clone
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require "pastel"
|
|
4
4
|
require "yaml"
|
|
5
|
-
require "
|
|
6
|
-
require "
|
|
7
|
-
require "
|
|
5
|
+
require "space_src/cli"
|
|
6
|
+
require "space_src/ui/mode"
|
|
7
|
+
require "space_src/cli/options"
|
|
8
8
|
|
|
9
|
-
module
|
|
9
|
+
module Space::Src
|
|
10
10
|
module CLI
|
|
11
11
|
# `config` command group: path / show.
|
|
12
12
|
module ConfigCmd
|
|
@@ -60,7 +60,7 @@ end
|
|
|
60
60
|
# the CLI command group. We register under a different module name
|
|
61
61
|
# (ConfigCmd) to avoid the constant clash, then alias the
|
|
62
62
|
# registration key as "config".
|
|
63
|
-
|
|
64
|
-
prefix.register "path",
|
|
65
|
-
prefix.register "show",
|
|
63
|
+
Space::Src::CLI::Registry.register "config" do |prefix|
|
|
64
|
+
prefix.register "path", Space::Src::CLI::ConfigCmd::Path
|
|
65
|
+
prefix.register "show", Space::Src::CLI::ConfigCmd::Show
|
|
66
66
|
end
|
|
@@ -3,17 +3,18 @@
|
|
|
3
3
|
require "pastel"
|
|
4
4
|
require "fileutils"
|
|
5
5
|
require "dry/monads"
|
|
6
|
-
require "
|
|
7
|
-
require "
|
|
8
|
-
require "
|
|
9
|
-
require "
|
|
10
|
-
require "
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
require "space_src/cli"
|
|
7
|
+
require "space_src/ui/mode"
|
|
8
|
+
require "space_src/cli/options"
|
|
9
|
+
require "space_src/launchd/agent"
|
|
10
|
+
require "space_src/launchd/plist"
|
|
11
|
+
require "space_src/migration"
|
|
12
|
+
|
|
13
|
+
module Space::Src
|
|
13
14
|
module CLI
|
|
14
15
|
# `daemon` command group: install / uninstall / start / stop
|
|
15
16
|
# / restart / status. Installs a per-user launchd agent
|
|
16
|
-
# (`gui/<UID>`) that fires `
|
|
17
|
+
# (`gui/<UID>`) that fires `src sync` on a
|
|
17
18
|
# `StartInterval`. The launchctl side is exercised ONLY
|
|
18
19
|
# through an injected command runner (slice-4 gates G2–G4);
|
|
19
20
|
# the live domain is proven by the manual real-Mac checklist
|
|
@@ -57,7 +58,7 @@ module SpaceArchitect::Pristine
|
|
|
57
58
|
# toolchain-resolved ruby; pinned via mise.toml).
|
|
58
59
|
# * `bin_path` — `RbConfig.ruby` + the script path
|
|
59
60
|
# (we use `__dir__` of this file's caller; for the
|
|
60
|
-
# gem install, this is `<gem>/
|
|
61
|
+
# gem install, this is `<gem>/exe/src`).
|
|
61
62
|
#
|
|
62
63
|
# In tests, we inject these via the `Resolve` object
|
|
63
64
|
# (see below) — never call out to the shell.
|
|
@@ -78,7 +79,7 @@ module SpaceArchitect::Pristine
|
|
|
78
79
|
|
|
79
80
|
def fail_with(cmd, msg)
|
|
80
81
|
cmd.send(:err).puts msg
|
|
81
|
-
|
|
82
|
+
Space::Src::CLI.record_outcome(Outcome.new(exit_code: 1, message: msg))
|
|
82
83
|
end
|
|
83
84
|
|
|
84
85
|
# Bundle of resolved absolute paths the plist needs.
|
|
@@ -113,6 +114,15 @@ module SpaceArchitect::Pristine
|
|
|
113
114
|
label = Launchd::Agent::DEFAULT_LABEL
|
|
114
115
|
pp = plist_path(paths, label)
|
|
115
116
|
|
|
117
|
+
# Relabel: if old-identity plist exists, bootout (benign-failure-tolerant)
|
|
118
|
+
# and remove it before bootstrapping the new-label plist.
|
|
119
|
+
old_pp = plist_path(paths, Migration::OLD_LABEL)
|
|
120
|
+
if File.exist?(old_pp)
|
|
121
|
+
old_agent = make_agent(label: Migration::OLD_LABEL)
|
|
122
|
+
old_agent.uninstall
|
|
123
|
+
File.delete(old_pp) if File.exist?(old_pp)
|
|
124
|
+
end
|
|
125
|
+
|
|
116
126
|
resolve = Resolve.detect(repo_root: Dir.pwd)
|
|
117
127
|
xml = build_plist(resolve: resolve, config: config, paths: paths, label: label)
|
|
118
128
|
FileUtils.mkdir_p(File.dirname(pp))
|
|
@@ -264,6 +274,12 @@ module SpaceArchitect::Pristine
|
|
|
264
274
|
)
|
|
265
275
|
pastel = Pastel.new(enabled: mode.color)
|
|
266
276
|
|
|
277
|
+
paths = CLI.make_paths
|
|
278
|
+
old_pp = plist_path(paths, Migration::OLD_LABEL)
|
|
279
|
+
if File.exist?(old_pp)
|
|
280
|
+
err.puts pastel.yellow("warning: stale agent #{Migration::OLD_LABEL} detected; run `src daemon install` to upgrade")
|
|
281
|
+
end
|
|
282
|
+
|
|
267
283
|
label = Launchd::Agent::DEFAULT_LABEL
|
|
268
284
|
agent = make_agent
|
|
269
285
|
result = agent.status
|
|
@@ -283,12 +299,12 @@ module SpaceArchitect::Pristine
|
|
|
283
299
|
end
|
|
284
300
|
end
|
|
285
301
|
|
|
286
|
-
# Detect the runtime paths the plist needs. The
|
|
287
|
-
#
|
|
288
|
-
#
|
|
289
|
-
#
|
|
290
|
-
#
|
|
291
|
-
class
|
|
302
|
+
# Detect the runtime paths the plist needs. The src install path
|
|
303
|
+
# matters because the plist stores an absolute `bin_path` — that
|
|
304
|
+
# is the script launchd invokes. We resolve `bin_path` from the
|
|
305
|
+
# on-disk gem layout if we can, else fall back to the directory
|
|
306
|
+
# the daemon command was run from.
|
|
307
|
+
class Space::Src::CLI::Daemon::Helpers::Resolve
|
|
292
308
|
# @param repo_root [String] absolute path of the working directory (where mise.toml is expected)
|
|
293
309
|
# @return [Resolve]
|
|
294
310
|
def self.detect(repo_root:)
|
|
@@ -300,7 +316,7 @@ class SpaceArchitect::Pristine::CLI::Daemon::Helpers::Resolve
|
|
|
300
316
|
end
|
|
301
317
|
|
|
302
318
|
def self.detect_mise_bin
|
|
303
|
-
path = ENV["
|
|
319
|
+
path = ENV["SPACE_SRC_MISE_BIN"]
|
|
304
320
|
return path if path && !path.empty?
|
|
305
321
|
require "open3"
|
|
306
322
|
out, _e, st = Open3.capture3("which", "mise")
|
|
@@ -308,7 +324,7 @@ class SpaceArchitect::Pristine::CLI::Daemon::Helpers::Resolve
|
|
|
308
324
|
end
|
|
309
325
|
|
|
310
326
|
def self.detect_ruby_bin(repo_root, mise_bin)
|
|
311
|
-
path = ENV["
|
|
327
|
+
path = ENV["SPACE_SRC_RUBY_BIN"]
|
|
312
328
|
return path if path && !path.empty?
|
|
313
329
|
# `mise exec -- which ruby` — but we avoid spawning in tests;
|
|
314
330
|
# production path goes through here.
|
|
@@ -321,27 +337,27 @@ class SpaceArchitect::Pristine::CLI::Daemon::Helpers::Resolve
|
|
|
321
337
|
end
|
|
322
338
|
|
|
323
339
|
def self.detect_bin_path(repo_root)
|
|
324
|
-
path = ENV["
|
|
340
|
+
path = ENV["SPACE_SRC_BIN_PATH"]
|
|
325
341
|
return path if path && !path.empty?
|
|
326
|
-
# Prefer the on-disk dev bin at `<repo_root>/
|
|
342
|
+
# Prefer the on-disk dev bin at `<repo_root>/exe/src`
|
|
327
343
|
# — it's what the human runs during testing, and the gem is
|
|
328
344
|
# typically not `gem install`ed in a source checkout.
|
|
329
|
-
dev = File.join(repo_root, "
|
|
345
|
+
dev = File.join(repo_root, "exe", "src")
|
|
330
346
|
return dev if File.exist?(dev)
|
|
331
347
|
# Next, an installed binary on PATH.
|
|
332
348
|
require "open3"
|
|
333
|
-
out, _e, st = Open3.capture3("which", "
|
|
349
|
+
out, _e, st = Open3.capture3("which", "src")
|
|
334
350
|
return out.strip if st.success? && !out.strip.empty?
|
|
335
351
|
# Last resort: the installed gem's bin (raises if not installed).
|
|
336
|
-
Gem.bin_path("
|
|
352
|
+
Gem.bin_path("space-architect", "src")
|
|
337
353
|
end
|
|
338
354
|
end
|
|
339
355
|
|
|
340
|
-
|
|
341
|
-
prefix.register "install",
|
|
342
|
-
prefix.register "uninstall",
|
|
343
|
-
prefix.register "start",
|
|
344
|
-
prefix.register "stop",
|
|
345
|
-
prefix.register "restart",
|
|
346
|
-
prefix.register "status",
|
|
356
|
+
Space::Src::CLI::Registry.register "daemon" do |prefix|
|
|
357
|
+
prefix.register "install", Space::Src::CLI::Daemon::Install
|
|
358
|
+
prefix.register "uninstall", Space::Src::CLI::Daemon::Uninstall
|
|
359
|
+
prefix.register "start", Space::Src::CLI::Daemon::Start
|
|
360
|
+
prefix.register "stop", Space::Src::CLI::Daemon::Stop
|
|
361
|
+
prefix.register "restart", Space::Src::CLI::Daemon::Restart
|
|
362
|
+
prefix.register "status", Space::Src::CLI::Daemon::Status
|
|
347
363
|
end
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require "pastel"
|
|
4
4
|
require "dry/monads"
|
|
5
|
-
require "
|
|
6
|
-
require "
|
|
7
|
-
require "
|
|
5
|
+
require "space_src/cli"
|
|
6
|
+
require "space_src/ui/mode"
|
|
7
|
+
require "space_src/cli/options"
|
|
8
8
|
|
|
9
|
-
module
|
|
9
|
+
module Space::Src
|
|
10
10
|
module CLI
|
|
11
11
|
# `org` command group: add / remove / list tracked orgs.
|
|
12
12
|
# Same shape as `repo` but against `Config::OrgRef` (host + name
|
|
@@ -60,7 +60,7 @@ module SpaceArchitect::Pristine
|
|
|
60
60
|
|
|
61
61
|
def fail_with(cmd, msg)
|
|
62
62
|
cmd.send(:err).puts msg
|
|
63
|
-
|
|
63
|
+
Space::Src::CLI.record_outcome(Outcome.new(exit_code: 1, message: msg))
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
@@ -193,8 +193,8 @@ module SpaceArchitect::Pristine
|
|
|
193
193
|
end
|
|
194
194
|
end
|
|
195
195
|
|
|
196
|
-
|
|
197
|
-
prefix.register "add",
|
|
198
|
-
prefix.register "remove",
|
|
199
|
-
prefix.register "list",
|
|
196
|
+
Space::Src::CLI::Registry.register "org" do |prefix|
|
|
197
|
+
prefix.register "add", Space::Src::CLI::Org::Add
|
|
198
|
+
prefix.register "remove", Space::Src::CLI::Org::Remove
|
|
199
|
+
prefix.register "list", Space::Src::CLI::Org::List
|
|
200
200
|
end
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require "pastel"
|
|
4
4
|
require "dry/monads"
|
|
5
|
-
require "
|
|
6
|
-
require "
|
|
7
|
-
require "
|
|
5
|
+
require "space_src/cli"
|
|
6
|
+
require "space_src/ui/mode"
|
|
7
|
+
require "space_src/cli/options"
|
|
8
8
|
|
|
9
|
-
module
|
|
9
|
+
module Space::Src
|
|
10
10
|
module CLI
|
|
11
11
|
# `repo` command group: add / remove / list tracked repos.
|
|
12
12
|
# Backed by Config::Store (the on-disk config.yaml is the
|
|
@@ -39,7 +39,7 @@ module SpaceArchitect::Pristine
|
|
|
39
39
|
|
|
40
40
|
def fail_with(cmd, msg)
|
|
41
41
|
cmd.send(:err).puts msg
|
|
42
|
-
|
|
42
|
+
Space::Src::CLI.record_outcome(Outcome.new(exit_code: 1, message: msg))
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
@@ -163,8 +163,8 @@ end
|
|
|
163
163
|
# Register the `repo` group + its subcommands. The block's `prefix`
|
|
164
164
|
# is a Dry::CLI::Registry::Prefix proxy that namespaces the
|
|
165
165
|
# subcommand names under "repo".
|
|
166
|
-
|
|
167
|
-
prefix.register "add",
|
|
168
|
-
prefix.register "remove",
|
|
169
|
-
prefix.register "list",
|
|
166
|
+
Space::Src::CLI::Registry.register "repo" do |prefix|
|
|
167
|
+
prefix.register "add", Space::Src::CLI::Repo::Add
|
|
168
|
+
prefix.register "remove", Space::Src::CLI::Repo::Remove
|
|
169
|
+
prefix.register "list", Space::Src::CLI::Repo::List
|
|
170
170
|
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "space_src/cli"
|
|
4
|
+
require "space_src/shell_integration"
|
|
5
|
+
|
|
6
|
+
module Space::Src
|
|
7
|
+
module CLI
|
|
8
|
+
module Shell
|
|
9
|
+
class Init < Dry::CLI::Command
|
|
10
|
+
desc "Print shell integration script"
|
|
11
|
+
argument :shell_name, required: true, desc: "Shell name (e.g. fish)"
|
|
12
|
+
|
|
13
|
+
def call(shell_name:, **)
|
|
14
|
+
out.puts ShellIntegration.for(shell_name)
|
|
15
|
+
CLI.record_outcome(Outcome.new(exit_code: 0))
|
|
16
|
+
rescue => e
|
|
17
|
+
err.puts "src shell init: #{e.message}"
|
|
18
|
+
CLI.record_outcome(Outcome.new(exit_code: 1))
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Fish < Dry::CLI::Command
|
|
23
|
+
desc "Manage fish shell integration: install, uninstall, path"
|
|
24
|
+
argument :subcommand, required: false, desc: "install, uninstall, or path (default: install)"
|
|
25
|
+
option :force, type: :boolean, default: false, desc: "Overwrite or remove existing shell files"
|
|
26
|
+
|
|
27
|
+
def call(subcommand: "install", force: false, **)
|
|
28
|
+
case subcommand
|
|
29
|
+
when "install"
|
|
30
|
+
result = ShellIntegration.install("fish", env: CLI.env, force: force)
|
|
31
|
+
out.puts fish_install_message(result.fetch(:action), result.fetch(:path))
|
|
32
|
+
out.puts fish_completions_install_message(result.fetch(:completions_action), result.fetch(:completions_path))
|
|
33
|
+
out.puts "Restart fish to load the integration in this terminal: exec fish"
|
|
34
|
+
CLI.record_outcome(Outcome.new(exit_code: 0))
|
|
35
|
+
when "uninstall"
|
|
36
|
+
result = ShellIntegration.uninstall("fish", env: CLI.env, force: force)
|
|
37
|
+
out.puts fish_uninstall_message(result.fetch(:action), result.fetch(:path))
|
|
38
|
+
out.puts fish_completions_uninstall_message(result.fetch(:completions_action), result.fetch(:completions_path))
|
|
39
|
+
CLI.record_outcome(Outcome.new(exit_code: 0))
|
|
40
|
+
when "path"
|
|
41
|
+
out.puts "Function: #{ShellIntegration.path_for("fish", env: CLI.env)}"
|
|
42
|
+
out.puts "Completions: #{ShellIntegration.completions_path_for("fish", env: CLI.env)}"
|
|
43
|
+
CLI.record_outcome(Outcome.new(exit_code: 0))
|
|
44
|
+
else
|
|
45
|
+
err.puts "Usage: src shell fish [install|uninstall|path]"
|
|
46
|
+
CLI.record_outcome(Outcome.new(exit_code: 1))
|
|
47
|
+
end
|
|
48
|
+
rescue => e
|
|
49
|
+
err.puts "src shell fish: #{e.message}"
|
|
50
|
+
CLI.record_outcome(Outcome.new(exit_code: 1))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def fish_install_message(action, path)
|
|
56
|
+
case action
|
|
57
|
+
when :unchanged then "Fish integration already installed: #{path}"
|
|
58
|
+
when :updated then "Updated fish integration: #{path}"
|
|
59
|
+
else "Installed fish integration: #{path}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def fish_uninstall_message(action, path)
|
|
64
|
+
case action
|
|
65
|
+
when :missing then "Fish integration was not installed: #{path}"
|
|
66
|
+
else "Removed fish integration: #{path}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def fish_completions_install_message(action, path)
|
|
71
|
+
case action
|
|
72
|
+
when :unchanged then "Fish completions already installed: #{path}"
|
|
73
|
+
when :updated then "Updated fish completions: #{path}"
|
|
74
|
+
else "Installed fish completions: #{path}"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def fish_completions_uninstall_message(action, path)
|
|
79
|
+
case action
|
|
80
|
+
when :missing then "Fish completions were not installed: #{path}"
|
|
81
|
+
else "Removed fish completions: #{path}"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class Complete < Dry::CLI::Command
|
|
87
|
+
desc "Print completion candidates"
|
|
88
|
+
argument :kind, required: true, desc: "Completion kind"
|
|
89
|
+
argument :extra, type: :array, required: false, desc: "Extra args for completion"
|
|
90
|
+
|
|
91
|
+
def call(kind:, extra: [], **)
|
|
92
|
+
case kind
|
|
93
|
+
when "checkouts"
|
|
94
|
+
begin
|
|
95
|
+
paths = CLI.make_paths
|
|
96
|
+
config = Config::Store.load(paths.config_file).success
|
|
97
|
+
Nav.scan(config.base_dir).each { |e| out.puts e[:target] }
|
|
98
|
+
rescue
|
|
99
|
+
# Never raise on a completion call — missing/unparseable config is fine.
|
|
100
|
+
end
|
|
101
|
+
CLI.record_outcome(Outcome.new(exit_code: 0))
|
|
102
|
+
when "shells"
|
|
103
|
+
out.puts "fish"
|
|
104
|
+
CLI.record_outcome(Outcome.new(exit_code: 0))
|
|
105
|
+
else
|
|
106
|
+
err.puts "Usage: src shell complete checkouts|shells"
|
|
107
|
+
CLI.record_outcome(Outcome.new(exit_code: 1))
|
|
108
|
+
end
|
|
109
|
+
rescue => e
|
|
110
|
+
err.puts "src shell complete: #{e.message}"
|
|
111
|
+
CLI.record_outcome(Outcome.new(exit_code: 1))
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
Space::Src::CLI::Registry.register "shell" do |prefix|
|
|
119
|
+
prefix.register "init", Space::Src::CLI::Shell::Init
|
|
120
|
+
prefix.register "fish", Space::Src::CLI::Shell::Fish
|
|
121
|
+
prefix.register "complete", Space::Src::CLI::Shell::Complete
|
|
122
|
+
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "pastel"
|
|
4
|
-
require "
|
|
5
|
-
require "
|
|
6
|
-
require "
|
|
4
|
+
require "space_src/cli"
|
|
5
|
+
require "space_src/ui/mode"
|
|
6
|
+
require "space_src/cli/options"
|
|
7
7
|
|
|
8
|
-
module
|
|
8
|
+
module Space::Src
|
|
9
9
|
module CLI
|
|
10
10
|
# `status` command: render a per-repo evergreen table from
|
|
11
11
|
# State::Store. Per G5, the rows must include each repo key
|
|
@@ -23,7 +23,7 @@ module SpaceArchitect::Pristine
|
|
|
23
23
|
"error" => :red
|
|
24
24
|
}.freeze
|
|
25
25
|
|
|
26
|
-
desc "Show the per-repo evergreen status table (from $XDG_STATE_HOME/
|
|
26
|
+
desc "Show the per-repo evergreen status table (from $XDG_STATE_HOME/space-src/state.yaml)"
|
|
27
27
|
|
|
28
28
|
def call(plain: nil, json: nil, no_color: nil, quiet: nil, **)
|
|
29
29
|
mode = UI::Mode.resolve(
|
|
@@ -37,7 +37,7 @@ module SpaceArchitect::Pristine
|
|
|
37
37
|
state = State::Store.load(paths.state_file).success
|
|
38
38
|
|
|
39
39
|
if state.repos.empty?
|
|
40
|
-
out.puts "(no repos in state — run `
|
|
40
|
+
out.puts "(no repos in state — run `src sync` to populate)"
|
|
41
41
|
return CLI.record_outcome(Outcome.new(exit_code: 0))
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -73,4 +73,4 @@ module SpaceArchitect::Pristine
|
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
Space::Src::CLI::Registry.register "status", Space::Src::CLI::Status::Show
|