-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for dependencies as binary targets
- Loading branch information
1 parent
3a91f22
commit c344094
Showing
18 changed files
with
571 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// CachingFlags.swift | ||
|
||
import ArgumentParser | ||
|
||
struct CachingFlags: ParsableArguments { | ||
|
||
@Flag(name: .long, help: "Whether to use binary targets for dependencies.") | ||
var dependenciesAsBinaryTargets: Bool = false | ||
|
||
@Option(name: .long, help: "Path to a folder containing dependencies. Required if --dependencies-as-binary-targets is set.") | ||
var relativeDependenciesPath: String? | ||
|
||
@Option(name: .long, help: "List of required relative paths to use when generating the hash for local dependencies. Required if --dependencies-as-binary-targets is set.") | ||
var requiredHashingPaths: [String] = [] | ||
|
||
@Option(name: .long, help: "List of optional relative paths to use when generating the hash for local dependencies.") | ||
var optionalHashingPaths: [String] = [] | ||
|
||
@Option(name: .long, help: "List of dependencies to exclude from the list of binary targets.") | ||
var exclusions: [String] = [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// ContentGenerator.swift | ||
|
||
import Foundation | ||
|
||
struct ContentGenerator { | ||
|
||
func content(for spec: Spec, templateUrl: URL) throws -> Content { | ||
let templater = Templater(templateUrl: templateUrl) | ||
return try templater.renderTemplate(context: spec.makeContext()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// DTOLoader.swift | ||
|
||
import Foundation | ||
import Yams | ||
|
||
final class DTOLoader { | ||
|
||
enum GeneratorError: Error { | ||
case invalidFormat(String) | ||
} | ||
|
||
func loadDto<T: Decodable>(url: URL) throws -> T { | ||
let data = try Data(contentsOf: url) | ||
switch url.pathExtension { | ||
case "json": | ||
let decoder = JSONDecoder() | ||
return try decoder.decode(T.self, from: data) | ||
case "yaml", "yml": | ||
let decoder = YAMLDecoder() | ||
return try decoder.decode(T.self, from: data) | ||
default: | ||
throw GeneratorError.invalidFormat(url.pathExtension) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// DependencyFinder.swift | ||
|
||
import Foundation | ||
|
||
final class DependencyFinder { | ||
|
||
enum DependencyFinderError: Error, LocalizedError { | ||
case failedCollectingDependencies(packageUrl: URL) | ||
|
||
var errorDescription: String? { | ||
switch self { | ||
case .failedCollectingDependencies(let packageUrl): | ||
return "Failed collecting dependencies at \(packageUrl.path)" | ||
} | ||
} | ||
} | ||
|
||
private let fileManager: FileManager | ||
|
||
private lazy var dependencyHasher: DependencyHasher = { | ||
DependencyHasher(fileManager: fileManager) | ||
}() | ||
|
||
// MARK: - Inits | ||
|
||
init(fileManager: FileManager = .default) { | ||
self.fileManager = fileManager | ||
} | ||
|
||
// MARK: - Functions | ||
|
||
func findPackageDependencies(at url: URL, requiredHashingPaths: [String], optionalHashingPaths: [String] = []) async throws -> [PackageDependency] { | ||
let process = Process() | ||
process.executableURL = URL(filePath: "/usr/bin/swift", directoryHint: .notDirectory) | ||
process.arguments = ["package", "show-dependencies", "--format", "json"] | ||
process.currentDirectoryURL = url | ||
|
||
let pipe = Pipe() | ||
process.standardOutput = pipe | ||
process.standardError = Pipe() | ||
|
||
try process.run() | ||
process.waitUntilExit() | ||
|
||
guard process.terminationStatus == 0 else { | ||
throw DependencyFinderError.failedCollectingDependencies(packageUrl: url) | ||
} | ||
|
||
let data = pipe.fileHandleForReading.readDataToEndOfFile() | ||
let packageDescription = try JSONDecoder().decode(PackageSpec.self, from: data) | ||
return try parseDependencies( | ||
packageDescription.dependencies, | ||
requiredHashingPaths: requiredHashingPaths, | ||
optionalHashingPaths: optionalHashingPaths | ||
) | ||
} | ||
|
||
// MARK: - Helper Functions | ||
|
||
private func parseDependencies(_ dependencies: [DependencySpec], requiredHashingPaths: [String], optionalHashingPaths: [String] = []) throws -> [PackageDependency] { | ||
var result = [PackageDependency]() | ||
|
||
for dependency in dependencies { | ||
if dependency.version == "unspecified" { | ||
let url = URL(filePath: dependency.path, directoryHint: .isDirectory) | ||
let hash = try dependencyHasher.hashForPackage( | ||
at: url, | ||
requiredSubpaths: requiredHashingPaths, | ||
optionalSubpaths: optionalHashingPaths | ||
) | ||
result.append( | ||
PackageDependency( | ||
name: dependency.name, | ||
type: .local(hash: hash) | ||
) | ||
) | ||
} | ||
else { | ||
result.append( | ||
PackageDependency( | ||
name: dependency.name, | ||
type: .remote(tag: dependency.version) | ||
) | ||
) | ||
} | ||
|
||
let nestedDependencies = try parseDependencies( | ||
dependency.dependencies, | ||
requiredHashingPaths: requiredHashingPaths, | ||
optionalHashingPaths: optionalHashingPaths | ||
) | ||
result.append(contentsOf: nestedDependencies) | ||
} | ||
|
||
return Set(result) | ||
.sorted { $0.name.lowercased() < $1.name.lowercased() } | ||
} | ||
} |
Oops, something went wrong.