Skip to content

Commit

Permalink
CLI tools necessary for the binary targets proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
hartbit committed Jan 10, 2020
1 parent fba8a19 commit 147b13f
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 40 deletions.
87 changes: 69 additions & 18 deletions Sources/Commands/SwiftPackageTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ public class SwiftPackageTool: SwiftTool<PackageToolOptions> {

switch configMode {
case .getMirror:
guard let packageURL = options.configOptions.packageURL else {
diagnostics.emit(.missingRequiredArg("--package-url"))
guard let originalURL = options.configOptions.originalURL else {
diagnostics.emit(.missingRequiredArg("--original-url"))
return
}

if let mirror = config.getMirror(forURL: packageURL) {
if let mirror = config.getMirror(forURL: originalURL) {
print(mirror)
} else {
stderrStream <<< "not found\n"
Expand All @@ -62,24 +62,25 @@ public class SwiftPackageTool: SwiftTool<PackageToolOptions> {
}

case .unsetMirror:
guard let packageOrMirror = options.configOptions.packageURL ?? options.configOptions.mirrorURL else {
diagnostics.emit(.missingRequiredArg("--package-url or --mirror-url"))
guard let originalOrMirrorURL = options.configOptions.originalURL ?? options.configOptions.mirrorURL
else {
diagnostics.emit(.missingRequiredArg("--original-url or --mirror-url"))
return
}

try config.unset(packageOrMirrorURL: packageOrMirror)
try config.unset(originalOrMirrorURL: originalOrMirrorURL)

case .setMirror:
guard let packageURL = options.configOptions.packageURL else {
diagnostics.emit(.missingRequiredArg("--package-url"))
guard let originalURL = options.configOptions.originalURL else {
diagnostics.emit(.missingRequiredArg("--original-url"))
return
}
guard let mirrorURL = options.configOptions.mirrorURL else {
diagnostics.emit(.missingRequiredArg("--mirror-url"))
return
}

try config.set(mirrorURL: mirrorURL, forPackageURL: packageURL)
try config.set(mirrorURL: mirrorURL, forURL: originalURL)
}

case .initPackage:
Expand Down Expand Up @@ -379,6 +380,21 @@ public class SwiftPackageTool: SwiftTool<PackageToolOptions> {
default:
preconditionFailure("somehow we ended up with an invalid positional argument")
}

case .computeChecksum:
let workspace = try getActiveWorkspace()
let checksum = workspace.checksum(
forBinaryArtifactAt: options.computeChecksumOptions.path,
diagnostics: diagnostics
)

guard !diagnostics.hasErrors else {
return
}

stdoutStream <<< checksum <<< "\n"
stdoutStream.flush()

case .help:
parser.printUsage(on: stdoutStream)
}
Expand Down Expand Up @@ -507,17 +523,19 @@ public class SwiftPackageTool: SwiftTool<PackageToolOptions> {
let setMirrorParser = configParser.add(
subparser: PackageToolOptions.ConfigMode.setMirror.rawValue,
overview: "Set a mirror for a dependency")

binder.bind(
setMirrorParser.add(
option: "--package-url", kind: String.self,
usage: "The package dependency url"),
setMirrorParser.add(
option: "--original-url", kind: String.self,
usage: "The original url"),
setMirrorParser.add(
option: "--mirror-url", kind: String.self,
usage: "The mirror url"),
to: {
$0.configOptions.packageURL = $1
$0.configOptions.mirrorURL = $2
$0.configOptions.originalURL = $1 ?? $2
$0.configOptions.mirrorURL = $3
}
)

Expand All @@ -528,23 +546,30 @@ public class SwiftPackageTool: SwiftTool<PackageToolOptions> {
unsetMirrorParser.add(
option: "--package-url", kind: String.self,
usage: "The package dependency url"),
unsetMirrorParser.add(
option: "--original-url", kind: String.self,
usage: "The original url"),
unsetMirrorParser.add(
option: "--mirror-url", kind: String.self,
usage: "The mirror url"),
to: {
$0.configOptions.packageURL = $1
$0.configOptions.mirrorURL = $2
$0.configOptions.originalURL = $1 ?? $2
$0.configOptions.mirrorURL = $3
}
)

let getMirrorParser = configParser.add(
subparser: PackageToolOptions.ConfigMode.getMirror.rawValue,
overview: "Print mirror configuration for the given package dependency")
binder.bind(
option: getMirrorParser.add(
option: "--package-url", kind: String.self, usage: "The package dependency url"),
getMirrorParser.add(
option: "--package-url", kind: String.self,
usage: "The package dependency url"),
getMirrorParser.add(
option: "--original-url", kind: String.self,
usage: "The original url"),
to: {
$0.configOptions.packageURL = $1
$0.configOptions.originalURL = $1 ?? $2
}
)

Expand Down Expand Up @@ -635,10 +660,30 @@ public class SwiftPackageTool: SwiftTool<PackageToolOptions> {
usage: "Invert the baseline which is helpful for determining API additions"),
to: { $0.apiDiffOptions.invertBaseline = $1 })

let computeChecksumParser = parser.add(
subparser: PackageMode.computeChecksum.rawValue,
overview: "Compute the checksum for a binary artifact.")
binder.bind(
positional: computeChecksumParser.add(
positional: "file", kind: PathArgument.self,
usage: "The absolute or relative path to the binary artifact"),
to: { $0.computeChecksumOptions.path = $1.path })

binder.bind(
parser: parser,
to: { $0.mode = PackageMode(rawValue: $1)! })
}

override class func postprocessArgParserResult(
result: ArgumentParser.Result,
diagnostics: DiagnosticsEngine
) throws {
try super.postprocessArgParserResult(result: result, diagnostics: diagnostics)

if result.exists(arg: "--package-url") {
diagnostics.emit(warning: "'--package-url' option is deprecated; use '--original-url' instead")
}
}
}

public class PackageToolOptions: ToolOptions {
Expand Down Expand Up @@ -700,6 +745,11 @@ public class PackageToolOptions: ToolOptions {
}
var apiDiffOptions = APIDiffOptions()

struct ComputeChecksumOptions {
var path: AbsolutePath!
}
var computeChecksumOptions = ComputeChecksumOptions()

enum ToolsVersionMode {
case display
case set(String)
Expand All @@ -721,7 +771,7 @@ public class PackageToolOptions: ToolOptions {
var configMode: ConfigMode?

struct ConfigOptions {
var packageURL: String?
var originalURL: String?
var mirrorURL: String?
}
var configOptions = ConfigOptions()
Expand Down Expand Up @@ -749,6 +799,7 @@ public enum PackageMode: String, StringEnumArgument {
case update
case version
case apidiff = "experimental-api-diff"
case computeChecksum = "compute-checksum"
case help

// PackageMode is not used as an argument; completions will be
Expand Down
2 changes: 1 addition & 1 deletion Sources/Commands/SwiftTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ public class SwiftTool<Options: ToolOptions> {
(packageRoot ?? cwd).appending(component: ".build")
}

static func postprocessArgParserResult(result: ArgumentParser.Result, diagnostics: DiagnosticsEngine) throws {
class func postprocessArgParserResult(result: ArgumentParser.Result, diagnostics: DiagnosticsEngine) throws {
if result.exists(arg: "--chdir") || result.exists(arg: "-C") {
diagnostics.emit(warning: "'--chdir/-C' option is deprecated; use '--package-path' instead")
}
Expand Down
16 changes: 8 additions & 8 deletions Sources/SourceControl/SwiftPMConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,19 @@ public final class SwiftPMConfig {
self.persistence = nil
}

/// Set a mirror URL for the given package URL.
public func set(mirrorURL: String, forPackageURL packageURL: String) throws {
mirrors[packageURL] = Mirror(original: packageURL, mirror: mirrorURL)
/// Set a mirror URL for the given URL.
public func set(mirrorURL: String, forURL url: String) throws {
mirrors[url] = Mirror(original: url, mirror: mirrorURL)
try saveState()
}

/// Unset a mirror for the given package or mirror URL.
/// Unset a mirror for the given URL.
///
/// This method will throw if there is no mirror for the given input.
public func unset(packageOrMirrorURL: String) throws {
if mirrors.keys.contains(packageOrMirrorURL) {
mirrors[packageOrMirrorURL] = nil
} else if let mirror = mirrors.first(where: { $0.value.mirror == packageOrMirrorURL }) {
public func unset(originalOrMirrorURL: String) throws {
if mirrors.keys.contains(originalOrMirrorURL) {
mirrors[originalOrMirrorURL] = nil
} else if let mirror = mirrors.first(where: { $0.value.mirror == originalOrMirrorURL }) {
mirrors[mirror.key] = nil
} else {
throw Error.mirrorNotFound
Expand Down
21 changes: 21 additions & 0 deletions Sources/Workspace/Workspace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,9 @@ public class Workspace {
/// The package container provider.
fileprivate let containerProvider: RepositoryPackageContainerProvider

/// The algorithm used for generating file checksums.
fileprivate let checksumAlgorithm: HashAlgorithm

/// Enable prefetching containers in resolver.
fileprivate let isResolverPrefetchingEnabled: Bool

Expand Down Expand Up @@ -386,6 +389,7 @@ public class Workspace {
config: SwiftPMConfig = SwiftPMConfig(),
fileSystem: FileSystem = localFileSystem,
repositoryProvider: RepositoryProvider = GitRepositoryProvider(),
checksumAlgorithm: HashAlgorithm = SHA256(),
additionalFileRules: [FileRuleDescription] = [],
isResolverPrefetchingEnabled: Bool = false,
enablePubgrubResolver: Bool = false,
Expand All @@ -399,6 +403,7 @@ public class Workspace {
self.manifestLoader = manifestLoader
self.currentToolsVersion = currentToolsVersion
self.toolsVersionLoader = toolsVersionLoader
self.checksumAlgorithm = checksumAlgorithm
self.isResolverPrefetchingEnabled = isResolverPrefetchingEnabled
self.enablePubgrubResolver = enablePubgrubResolver
self.skipUpdate = skipUpdate
Expand Down Expand Up @@ -800,6 +805,22 @@ extension Workspace {

return rootManifests
}

/// Generates the checksum
public func checksum(
forBinaryArtifactAt path: AbsolutePath,
diagnostics: DiagnosticsEngine
) -> String {
guard fileSystem.isFile(path) else {
diagnostics.emit(error: "file not found at path: \(path.pathString)")
return ""
}

return diagnostics.wrap {
let contents = try fileSystem.readFileContents(path)
return checksumAlgorithm.hash(contents).hexadecimalRepresentation
} ?? ""
}
}

// MARK: - Editing Functions
Expand Down
43 changes: 32 additions & 11 deletions Tests/CommandsTests/PackageToolTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -567,19 +567,21 @@ final class PackageToolTests: XCTestCase {
)

// Test writing.
try execute(["config", "set-mirror", "--package-url", "https://github.com/foo/bar", "--mirror-url", "https://mygithub.com/foo/bar"], packagePath: packageRoot)
try execute(["config", "set-mirror", "--package-url", "git@github.com:apple/swift-package-manager.git", "--mirror-url", "git@mygithub.com:foo/swift-package-manager.git"], packagePath: packageRoot)
var (stdout, stderr) = try execute(["config", "set-mirror", "--package-url", "https://github.com/foo/bar", "--mirror-url", "https://mygithub.com/foo/bar"], packagePath: packageRoot)
XCTAssertMatch(stderr, .contains("warning: '--package-url' option is deprecated; use '--original-url' instead"))
try execute(["config", "set-mirror", "--original-url", "git@github.com:apple/swift-package-manager.git", "--mirror-url", "git@mygithub.com:foo/swift-package-manager.git"], packagePath: packageRoot)
XCTAssertTrue(fs.isFile(configFile))

// Test env override.
try execute(["config", "set-mirror", "--package-url", "https://github.com/foo/bar", "--mirror-url", "https://mygithub.com/foo/bar"], packagePath: packageRoot, env: ["SWIFTPM_MIRROR_CONFIG": configOverride.pathString])
try execute(["config", "set-mirror", "--original-url", "https://github.com/foo/bar", "--mirror-url", "https://mygithub.com/foo/bar"], packagePath: packageRoot, env: ["SWIFTPM_MIRROR_CONFIG": configOverride.pathString])
XCTAssertTrue(fs.isFile(configOverride))
XCTAssertTrue(try fs.readFileContents(configOverride).description.contains("mygithub"))

// Test reading.
var (stdout, stderr) = try execute(["config", "get-mirror", "--package-url", "https://github.com/foo/bar"], packagePath: packageRoot)
(stdout, stderr) = try execute(["config", "get-mirror", "--package-url", "https://github.com/foo/bar"], packagePath: packageRoot)
XCTAssertEqual(stdout.spm_chomp(), "https://mygithub.com/foo/bar")
(stdout, _) = try execute(["config", "get-mirror", "--package-url", "git@github.com:apple/swift-package-manager.git"], packagePath: packageRoot)
XCTAssertMatch(stderr, .contains("warning: '--package-url' option is deprecated; use '--original-url' instead"))
(stdout, _) = try execute(["config", "get-mirror", "--original-url", "git@github.com:apple/swift-package-manager.git"], packagePath: packageRoot)
XCTAssertEqual(stdout.spm_chomp(), "git@mygithub.com:foo/swift-package-manager.git")

func check(stderr: String, _ block: () throws -> ()) {
Expand All @@ -594,23 +596,42 @@ final class PackageToolTests: XCTestCase {
}

check(stderr: "not found\n") {
try execute(["config", "get-mirror", "--package-url", "foo"], packagePath: packageRoot)
try execute(["config", "get-mirror", "--original-url", "foo"], packagePath: packageRoot)
}

// Test deletion.
try execute(["config", "unset-mirror", "--package-url", "https://github.com/foo/bar"], packagePath: packageRoot)
try execute(["config", "unset-mirror", "--mirror-url", "git@mygithub.com:foo/swift-package-manager.git"], packagePath: packageRoot)
(_, stderr) = try execute(["config", "unset-mirror", "--package-url", "https://github.com/foo/bar"], packagePath: packageRoot)
XCTAssertMatch(stderr, .contains("warning: '--package-url' option is deprecated; use '--original-url' instead"))
try execute(["config", "unset-mirror", "--original-url", "git@mygithub.com:foo/swift-package-manager.git"], packagePath: packageRoot)

check(stderr: "not found\n") {
try execute(["config", "get-mirror", "--package-url", "https://github.com/foo/bar"], packagePath: packageRoot)
try execute(["config", "get-mirror", "--original-url", "https://github.com/foo/bar"], packagePath: packageRoot)
}
check(stderr: "not found\n") {
try execute(["config", "get-mirror", "--package-url", "git@github.com:apple/swift-package-manager.git"], packagePath: packageRoot)
try execute(["config", "get-mirror", "--original-url", "git@github.com:apple/swift-package-manager.git"], packagePath: packageRoot)
}

check(stderr: "error: mirror not found\n") {
try execute(["config", "unset-mirror", "--package-url", "foo"], packagePath: packageRoot)
try execute(["config", "unset-mirror", "--original-url", "foo"], packagePath: packageRoot)
}
}
}

func testComputeChecksum() {
fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { prefix in
let invalid = prefix.appending(component: "invalid-file")
do {
try execute(["compute-checksum", invalid.pathString], packagePath: prefix)
XCTFail("expected to fail")
} catch SwiftPMProductError.executionFailure(_, _, let stderr) {
XCTAssertMatch(stderr, .contains("error: file not found at path: \(invalid.pathString)"))
} catch {
XCTFail("unexpected error: \(error)")
}

let readme = prefix.appending(component: "README.md")
let (stdout, _) = try execute(["compute-checksum", readme.pathString], packagePath: prefix)
XCTAssertEqual(stdout.spm_chomp(), "5a2cd751cc6e8005a56c836c7269b038bbd536ee998275a1497c37fc986c4352")
}
}
}
1 change: 1 addition & 0 deletions Tests/CommandsTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extension PackageToolTests {
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__PackageToolTests = [
("testComputeChecksum", testComputeChecksum),
("testDescribe", testDescribe),
("testDumpPackage", testDumpPackage),
("testInitCustomNameExecutable", testInitCustomNameExecutable),
Expand Down
4 changes: 2 additions & 2 deletions Tests/WorkspaceTests/WorkspaceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3243,8 +3243,8 @@ final class WorkspaceTests: XCTestCase {
result.check(notPresent: "Baz")
}

try workspace.config.set(mirrorURL: workspace.packagesDir.appending(component: "Baz").pathString, forPackageURL: workspace.packagesDir.appending(component: "Bar").pathString)
try workspace.config.set(mirrorURL: workspace.packagesDir.appending(component: "Baz").pathString, forPackageURL: workspace.packagesDir.appending(component: "Bam").pathString)
try workspace.config.set(mirrorURL: workspace.packagesDir.appending(component: "Baz").pathString, forURL: workspace.packagesDir.appending(component: "Bar").pathString)
try workspace.config.set(mirrorURL: workspace.packagesDir.appending(component: "Baz").pathString, forURL: workspace.packagesDir.appending(component: "Bam").pathString)

let deps: [TestWorkspace.PackageDependency] = [
.init(name: "Bam", requirement: .upToNextMajor(from: "1.0.0")),
Expand Down

0 comments on commit 147b13f

Please sign in to comment.