Class: ToggleLocalSpm::CLI
- Inherits:
-
Object
- Object
- ToggleLocalSpm::CLI
- Defined in:
- lib/toggle_local_spm/cli.rb
Overview
Toggles one or more Swift Package Manager dependencies between their
remote (git) reference and a local checkout. Run again on the same
package to swap back to the original remote reference. Afterwards,
optionally runs xcodebuild -resolvePackageDependencies so
Package.resolved is updated to match (requires network access and, for
private repos, a working SSH key).
Run from the root of the Xcode project's repo (the directory containing
the .xcodeproj). A spm-local-overrides.json file is kept at the repo
root as a permanent record of each package's remote reference and local
checkout path (see README).
Packages come in two flavors:
- "direct": already has (or had) a top-level XCRemoteSwiftPackageReference/ XCLocalSwiftPackageReference entry in project.pbxproj. Toggling off always leaves a reference behind (swapped back to remote) since the project genuinely depends on it.
- "indirect": only known via Package.resolved — a transitive dependency of one of the project's own direct dependencies (e.g. a package declared in another package's own Package.swift), with no top-level reference of its own. Toggling one of these on adds a brand-new, unlinked local reference (no product/target linkage) purely so SwiftPM's identity-based graph resolution overrides the transitive pin with the local checkout; toggling off removes that reference entirely, since it was never a real project dependency.
Which of these two states a package is in is recorded as "type" in spm-local-overrides.json. Whether it's currently local or remote is always read from the live project (an existing ref's isa, or its absence for a not-yet-toggled indirect package) — never from the state file or from Package.resolved, which can lag behind.
Defined Under Namespace
Classes: Candidate
Constant Summary collapse
- RemoteRef =
Xcodeproj::Project::Object::XCRemoteSwiftPackageReference
- LocalRef =
Xcodeproj::Project::Object::XCLocalSwiftPackageReference
- ProductDependency =
Xcodeproj::Project::Object::XCSwiftPackageProductDependency
- TYPE_LABELS =
{ "direct" => "🎯 direct", "indirect" => "🧩 indirect" }.freeze
- STATE_LABELS =
{ local: "📁 local", remote: "🌏 remote" }.freeze
- MANAGED_LABELS =
{ set: "✅", found: "📁" }.freeze
- MANAGED_LEGEND =
[ "#{MANAGED_LABELS[:set]} Local mock set", "#{MANAGED_LABELS[:found]} Mock not set. Mock found (recorded in spm-local-overrides.json)", " Blank — no record for this dependency in spm-local-overrides.json" ].freeze
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(argv, root: Dir.pwd) ⇒ CLI
constructor
A new instance of CLI.
- #run ⇒ Object
Constructor Details
Class Method Details
.run(argv) ⇒ Object
60 61 62 |
# File 'lib/toggle_local_spm/cli.rb', line 60 def self.run(argv) new(argv).run end |
Instance Method Details
#run ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/toggle_local_spm/cli.rb', line 70 def run xcodeproj_path = find_xcodeproj_path project = Xcodeproj::Project.open(xcodeproj_path) state = load_state candidates = build_candidates(project, xcodeproj_path, state) abort_with("no Swift package dependencies found") if candidates.empty? selected = select_candidates(candidates) check_xcode_running selected.each { |candidate| toggle(project, xcodeproj_path, candidate, state) } save_state(state) project.save resolve_package_dependencies(xcodeproj_path) if prompt_resolve? open_in_xcode(xcodeproj_path) if prompt_open_in_xcode? puts "Done." end |