Skip to content

Add swift package-registry command #3647

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,16 @@ let package = Package(
name: "LLBuildManifest",
dependencies: ["SwiftToolsSupport-auto", "Basics"]),

.target(
/** Package registry support */
name: "PackageRegistry",
dependencies: ["SwiftToolsSupport-auto", "Basics", "PackageLoading", "PackageModel"]),

.target(
/** Source control operations */
name: "SourceControl",
dependencies: ["SwiftToolsSupport-auto", "Basics"]),

.target(
/** Shim for llbuild library */
name: "SPMLLBuild",
Expand All @@ -158,7 +164,7 @@ let package = Package(
.target(
/** Data structures and support for complete package graphs */
name: "PackageGraph",
dependencies: ["SwiftToolsSupport-auto", "Basics", "PackageLoading", "PackageModel", "SourceControl"]),
dependencies: ["SwiftToolsSupport-auto", "Basics", "PackageLoading", "PackageModel", "PackageRegistry", "SourceControl"]),

// MARK: Package Collections

Expand Down Expand Up @@ -234,6 +240,10 @@ let package = Package(
/** Interacts with package collections */
name: "swift-package-collection",
dependencies: ["Commands"]),
.target(
/** Interact with package registry */
name: "swift-package-registry",
dependencies: ["Commands"]),
.target(
/** Shim tool to find test names on OS X */
name: "swiftpm-xctest-helper",
Expand Down Expand Up @@ -300,6 +310,9 @@ let package = Package(
.testTarget(
name: "PackageCollectionsTests",
dependencies: ["PackageCollections", "SPMTestSupport"]),
.testTarget(
name: "PackageRegistryTests",
dependencies: ["SPMTestSupport", "PackageRegistry"]),
.testTarget(
name: "SourceControlTests",
dependencies: ["SourceControl", "SPMTestSupport"]),
Expand Down
1 change: 1 addition & 0 deletions Sources/Basics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_library(Basics
HTPClient+URLSession.swift
HTTPClient.swift
JSON+Extensions.swift
JSONDecoder+Extensions.swift
Sandbox.swift
SwiftVersion.swift
SQLiteBackedCache.swift
Expand Down
22 changes: 22 additions & 0 deletions Sources/Basics/JSONDecoder+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See http://swift.org/LICENSE.txt for license information
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Foundation

extension JSONDecoder {
public func decode<T>(_ type: T.Type, from string: String) throws -> T where T : Decodable {
guard let data = string.data(using: .utf8) else {
let context = DecodingError.Context(codingPath: [], debugDescription: "invalid UTF-8 string")
throw DecodingError.dataCorrupted(context)
}

return try decode(type, from: data)
}
}
1 change: 1 addition & 0 deletions Sources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ add_subdirectory(PackageGraph)
add_subdirectory(PackageLoading)
add_subdirectory(PackageModel)
add_subdirectory(PackagePlugin)
add_subdirectory(PackageRegistry)
add_subdirectory(SPMBuildCore)
add_subdirectory(SPMLLBuild)
add_subdirectory(SourceControl)
Expand Down
1 change: 1 addition & 0 deletions Sources/Commands/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ add_library(Commands
show-dependencies.swift
SwiftBuildTool.swift
SwiftPackageCollectionsTool.swift
SwiftPackageRegistryTool.swift
SwiftPackageTool.swift
SwiftRunTool.swift
SwiftTestTool.swift
Expand Down
170 changes: 170 additions & 0 deletions Sources/Commands/SwiftPackageRegistryTool.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See http://swift.org/LICENSE.txt for license information
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import ArgumentParser
import Basics
import TSCBasic
import SPMBuildCore
import Build
import PackageModel
import PackageLoading
import PackageGraph
import SourceControl
import TSCUtility
import XCBuildSupport
import Workspace
import Foundation
import PackageRegistry

private enum RegistryConfigurationError: Swift.Error {
case missingScope(String? = nil)
case invalidURL(String)
}

extension RegistryConfigurationError: CustomStringConvertible {
var description: String {
switch self {
case .missingScope(let scope?):
return "no existing entry for scope: \(scope)"
case .missingScope:
return "no existing entry for default scope"
case .invalidURL(let url):
return "invalid URL: \(url)"
}
}
}

public struct SwiftPackageRegistryTool: ParsableCommand {
public static var configuration = CommandConfiguration(
commandName: "package-registry",
_superCommandName: "swift",
abstract: "Interact with package registry and manage related configuration",
discussion: "SEE ALSO: swift package",
version: SwiftVersion.currentVersion.completeDisplayString,
subcommands: [
Set.self,
Unset.self
],
helpNames: [.short, .long, .customLong("help", withSingleDash: true)])

@OptionGroup()
var swiftOptions: SwiftToolOptions

public init() {}

struct Set: SwiftCommand {
static let configuration = CommandConfiguration(
abstract: "Set a custom registry")

@OptionGroup(_hiddenFromHelp: true)
var swiftOptions: SwiftToolOptions

@Flag(help: "Apply settings to all projects for this user")
var global: Bool = false

@Option(help: "Associate the registry with a given scope")
var scope: String?

// TODO: Uncomment once .netrc management is implemented

// @Option(help: "Specify a user name for the remote machine")
// var login: String?

// @Option(help: "Supply a password for the remote machine")
// var password: String?

@Argument(help: "The registry URL")
var url: String

func run(_ swiftTool: SwiftTool) throws {
guard let url = URL(string: self.url),
url.scheme == "https"
else {
throw RegistryConfigurationError.invalidURL(self.url)
}

// TODO: Require login if password is specified

let set: (inout RegistryConfiguration) throws -> Void = { configuration in
if let scope = scope {
configuration.scopedRegistries[scope] = .init(url: url)
} else {
configuration.defaultRegistry = .init(url: url)
}
}

let configuration = try swiftTool.getRegistriesConfig()
if global {
try configuration.updateShared(with: set)
} else {
try configuration.updateLocal(with: set)
}

// TODO: Add login and password to .netrc
}
}

struct Unset: SwiftCommand {
static let configuration = CommandConfiguration(
abstract: "Remove a configured registry")

@OptionGroup(_hiddenFromHelp: true)
var swiftOptions: SwiftToolOptions

@Flag(help: "Apply settings to all projects for this user")
var global: Bool = false

@Option(help: "Associate the registry with a given scope")
var scope: String?

func run(_ swiftTool: SwiftTool) throws {
let unset: (inout RegistryConfiguration) throws -> Void = { configuration in
if let scope = scope {
guard let _ = configuration.scopedRegistries[scope] else {
throw RegistryConfigurationError.missingScope(scope)
}
configuration.scopedRegistries.removeValue(forKey: scope)
} else {
guard let _ = configuration.defaultRegistry else {
throw RegistryConfigurationError.missingScope()
}
configuration.defaultRegistry = nil
}
}

let configuration = try swiftTool.getRegistriesConfig()
if global {
try configuration.updateShared(with: unset)
} else {
try configuration.updateLocal(with: unset)
}
}
}
}

// MARK: -


private extension SwiftTool {
func getRegistriesConfig() throws -> Workspace.Configuration.Registries {
let localRegistriesFile = try Workspace.DefaultLocations.registriesConfigurationFile(forRootPackage: self.getPackageRoot())

let workspace = try getActiveWorkspace()
let sharedRegistriesFile = workspace.location.sharedConfigurationDirectory.map {
Workspace.DefaultLocations.registriesConfigurationFile(at: $0)
}

return try .init(
localRegistriesFile: localRegistriesFile,
sharedRegistriesFile: sharedRegistriesFile,
fileSystem: localFileSystem
)
}
}
26 changes: 26 additions & 0 deletions Sources/PackageRegistry/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2021 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See http://swift.org/LICENSE.txt for license information
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors

add_library(PackageRegistry
RegistryConfiguration.swift)
target_link_libraries(PackageRegistry PUBLIC
TSCBasic
PackageLoading
PackageModel
TSCUtility)
# NOTE(compnerd) workaround for CMake not setting up include flags yet
set_target_properties(PackageRegistry PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})

if(USE_CMAKE_INSTALL)
install(TARGETS PackageRegistry
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
endif()
set_property(GLOBAL APPEND PROPERTY SwiftPM_EXPORTS PackageRegistry)
Loading