Skip to content

cleanup mirror config command #6339

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 1 commit into from
Mar 28, 2023
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
127 changes: 90 additions & 37 deletions Sources/Commands/PackageTools/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,108 +20,161 @@ extension SwiftPackageTool {
struct Config: ParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Manipulate configuration of the package",
subcommands: [SetMirror.self, UnsetMirror.self, GetMirror.self])
subcommands: [SetMirror.self, UnsetMirror.self, GetMirror.self]
)
}
}

extension SwiftPackageTool.Config {
struct SetMirror: SwiftCommand {
static let configuration = CommandConfiguration(
abstract: "Set a mirror for a dependency")
abstract: "Set a mirror for a dependency"
)

@OptionGroup(visibility: .hidden)
var globalOptions: GlobalOptions

@Option(help: "The package dependency url")
var packageURL: String?
@Option(name: .customLong("package-url"), help: .hidden)
var _deprecate_packageURL: String?

@Option(name: .customLong("original-url"), help: .hidden)
var _deprecate_originalURL: String?

@Option(help: "The original url")
var originalURL: String?
@Option(name: .customLong("mirror-url"), help: .hidden)
var _deprecate_mirrorURL: String?

@Option(help: "The mirror url")
var mirrorURL: String
@Option(help: "The original url or identity")
var original: String?

@Option(help: "The mirror url or identity")
var mirror: String?

func run(_ swiftTool: SwiftTool) throws {
let config = try getMirrorsConfig(swiftTool)

if self.packageURL != nil {
if self._deprecate_packageURL != nil {
swiftTool.observabilityScope.emit(
warning: "'--package-url' option is deprecated; use '--original' instead"
)
}
if self._deprecate_originalURL != nil {
swiftTool.observabilityScope.emit(
warning: "'--package-url' option is deprecated; use '--original-url' instead")
warning: "'--original-url' option is deprecated; use '--original' instead"
)
}
if self._deprecate_mirrorURL != nil {
swiftTool.observabilityScope.emit(
warning: "'--mirror-url' option is deprecated; use '--mirror' instead"
)
}

guard let original = self._deprecate_packageURL ?? self._deprecate_originalURL ?? self.original else {
swiftTool.observabilityScope.emit(.missingRequiredArg("--original"))
throw ExitCode.failure
}

guard let originalURL = self.packageURL ?? self.originalURL else {
swiftTool.observabilityScope.emit(.missingRequiredArg("--original-url"))
guard let mirror = self._deprecate_mirrorURL ?? self.mirror else {
swiftTool.observabilityScope.emit(.missingRequiredArg("--mirror"))
throw ExitCode.failure
}

try config.applyLocal { mirrors in
mirrors.set(mirrorURL: self.mirrorURL, forURL: originalURL)
mirrors.set(mirror: mirror, for: original)
}
}
}

struct UnsetMirror: SwiftCommand {
static let configuration = CommandConfiguration(
abstract: "Remove an existing mirror")
abstract: "Remove an existing mirror"
)

@OptionGroup(visibility: .hidden)
var globalOptions: GlobalOptions

@Option(help: "The package dependency url")
var packageURL: String?
@Option(name: .customLong("package-url"), help: .hidden)
var _deprecate_packageURL: String?

@Option(name: .customLong("original-url"), help: .hidden)
var _deprecate_originalURL: String?

@Option(name: .customLong("mirror-url"), help: .hidden)
var _deprecate_mirrorURL: String?

@Option(help: "The original url")
var originalURL: String?
@Option(help: "The original url or identity")
var original: String?

@Option(help: "The mirror url")
var mirrorURL: String?
@Option(help: "The mirror url or identity")
var mirror: String?

func run(_ swiftTool: SwiftTool) throws {
let config = try getMirrorsConfig(swiftTool)

if self.packageURL != nil {
if self._deprecate_packageURL != nil {
swiftTool.observabilityScope.emit(
warning: "'--package-url' option is deprecated; use '--original' instead"
)
}
if self._deprecate_originalURL != nil {
swiftTool.observabilityScope.emit(
warning: "'--package-url' option is deprecated; use '--original-url' instead")
warning: "'--original-url' option is deprecated; use '--original' instead"
)
}
if self._deprecate_mirrorURL != nil {
swiftTool.observabilityScope.emit(
warning: "'--mirror-url' option is deprecated; use '--mirror' instead"
)
}

guard let originalOrMirrorURL = self.packageURL ?? self.originalURL ?? self.mirrorURL else {
swiftTool.observabilityScope.emit(.missingRequiredArg("--original-url or --mirror-url"))
guard let originalOrMirror = self._deprecate_packageURL ?? self._deprecate_originalURL ?? self
.original ?? self._deprecate_mirrorURL ?? self.mirror
else {
swiftTool.observabilityScope.emit(.missingRequiredArg("--original or --mirror"))
throw ExitCode.failure
}

try config.applyLocal { mirrors in
try mirrors.unset(originalOrMirrorURL: originalOrMirrorURL)
try mirrors.unset(originalOrMirror: originalOrMirror)
}
}
}

struct GetMirror: SwiftCommand {
static let configuration = CommandConfiguration(
abstract: "Print mirror configuration for the given package dependency")
abstract: "Print mirror configuration for the given package dependency"
)

@OptionGroup(visibility: .hidden)
var globalOptions: GlobalOptions
@Option(name: .customLong("package-url"), help: .hidden)
var _deprecate_packageURL: String?

@Option(help: "The package dependency url")
var packageURL: String?
@Option(name: .customLong("original-url"), help: .hidden)
var _deprecate_originalURL: String?

@Option(help: "The original url")
var originalURL: String?
@Option(help: "The original url or identity")
var original: String?

func run(_ swiftTool: SwiftTool) throws {
let config = try getMirrorsConfig(swiftTool)

if self.packageURL != nil {
if self._deprecate_packageURL != nil {
swiftTool.observabilityScope.emit(
warning: "'--package-url' option is deprecated; use '--original' instead"
)
}
if self._deprecate_originalURL != nil {
swiftTool.observabilityScope.emit(
warning: "'--package-url' option is deprecated; use '--original-url' instead")
warning: "'--original-url' option is deprecated; use '--original' instead"
)
}

guard let originalURL = self.packageURL ?? self.originalURL else {
swiftTool.observabilityScope.emit(.missingRequiredArg("--original-url"))
guard let original = self._deprecate_packageURL ?? self._deprecate_originalURL ?? self.original else {
swiftTool.observabilityScope.emit(.missingRequiredArg("--original"))
throw ExitCode.failure
}

if let mirror = config.mirrors.mirrorURL(for: originalURL) {
if let mirror = config.mirrors.mirror(for: original) {
print(mirror)
} else {
stderrStream <<< "not found\n"
Expand All @@ -141,8 +194,8 @@ extension SwiftPackageTool.Config {
}
}

private extension Basics.Diagnostic {
static func missingRequiredArg(_ argument: String) -> Self {
extension Basics.Diagnostic {
fileprivate static func missingRequiredArg(_ argument: String) -> Self {
.error("missing required argument \(argument)")
}
}
74 changes: 37 additions & 37 deletions Sources/PackageGraph/DependencyMirrors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public final class DependencyMirrors: Equatable {

public var mapping: [String: String] {
self.lock.withLock {
return self.index
self.index
}
}

Expand All @@ -38,34 +38,34 @@ public final class DependencyMirrors: Equatable {
}

public static func == (lhs: DependencyMirrors, rhs: DependencyMirrors) -> Bool {
return lhs.mapping == rhs.mapping
lhs.mapping == rhs.mapping
}

/// Sets a mirror URL for the given URL.
/// Sets a mirror for the given origin.
/// - Parameters:
/// - mirrorURL: The mirrored URL
/// - forURL: The original URL
public func set(mirrorURL: String, forURL url: String) {
/// - mirror: The mirror
/// - for: The original
public func set(mirror: String, for key: String) {
self.lock.withLock {
self.index[url] = mirrorURL
self.reverseIndex[mirrorURL, default: []].append(url)
self.index[key] = mirror
self.reverseIndex[mirror, default: []].append(key)
}
}

/// Unsets a mirror for the given URL.
/// Unsets a mirror for the given.
/// - Parameters:
/// - originalOrMirrorURL: The original URL or the mirrored URL
/// - Throws: `Error.mirrorNotFound` if no mirror exists for the provided URL.
public func unset(originalOrMirrorURL: String) throws {
/// - originalOrMirror: The original or the mirrored
/// - Throws: `Error.mirrorNotFound` if no mirror exists for the provided origin or mirror.
public func unset(originalOrMirror: String) throws {
try self.lock.withLock {
if let value = self.index[originalOrMirrorURL] {
self.index[originalOrMirrorURL] = nil
if let value = self.index[originalOrMirror] {
self.index[originalOrMirror] = nil
self.reverseIndex[value] = nil
} else if let mirror = self.index.first(where: { $0.value == originalOrMirrorURL }) {
} else if let mirror = self.index.first(where: { $0.value == originalOrMirror }) {
self.index[mirror.key] = nil
self.reverseIndex[originalOrMirrorURL] = nil
self.reverseIndex[originalOrMirror] = nil
} else {
throw StringError("Mirror not found for '\(originalOrMirrorURL)'")
throw StringError("Mirror not found for '\(originalOrMirror)'")
}
}
}
Expand All @@ -75,7 +75,7 @@ public final class DependencyMirrors: Equatable {
/// - contentsOf: The DependencyMirrors to append from.
public func append(contentsOf mirrors: DependencyMirrors) {
mirrors.index.forEach {
self.set(mirrorURL: $0.value, forURL: $0.key)
self.set(mirror: $0.value, for: $0.key)
}
}

Expand All @@ -101,36 +101,36 @@ public final class DependencyMirrors: Equatable {
}
}

/// Returns the mirrored URL for a package dependency URL.
/// Returns the mirrored for a package dependency.
/// - Parameters:
/// - url: The original URL
/// - Returns: The mirrored URL, if one exists.
public func mirrorURL(for url: String) -> String? {
/// - for: The original
/// - Returns: The mirrored, if one exists.
public func mirror(for key: String) -> String? {
self.lock.withLock {
let value = self.index[url]
let value = self.index[key]
if value != nil {
// record visited mirrors for reverse index lookup sorting
self.visited.append(url)
self.visited.append(key)
}
return value
}
}

/// Returns the effective URL for a package dependency URL.
/// Returns the effective value for a package dependency.
/// - Parameters:
/// - url: The original URL
/// - Returns: The mirrored URL if it exists, otherwise the original URL.
public func effectiveURL(for url: String) -> String {
return self.mirrorURL(for: url) ?? url
/// - for: The original
/// - Returns: The mirrored if it exists, otherwise the original.
public func effective(for key: String) -> String {
self.mirror(for: key) ?? key
}

/// Returns the original URL for a mirrored package dependency URL.
/// Returns the original for a mirrored package dependency.
/// - Parameters:
/// - url: The mirror URL
/// - Returns: The original URL, if one exists.
public func originalURL(for url: String) -> String? {
/// - for: The mirror
/// - Returns: The original , if one exists.
public func original(for key: String) -> String? {
self.lock.withLock {
let alternatives = self.reverseIndex[url]
let alternatives = self.reverseIndex[key]
// since there are potentially multiple mapping, we need to sort them to produce deterministic results
let sorted = alternatives?.sorted(by: { lhs, rhs in
// check if it was visited (which means it used by the package)
Expand All @@ -152,17 +152,17 @@ public final class DependencyMirrors: Equatable {

public func effectiveIdentity(for identity: PackageIdentity) throws -> PackageIdentity {
// TODO: cache
let mirrorIndex = try self.mapping.reduce(into: [PackageIdentity: PackageIdentity](), { partial, item in
let mirrorIndex = try self.mapping.reduce(into: [PackageIdentity: PackageIdentity]()) { partial, item in
try partial[parseLocation(item.key)] = parseLocation(item.value)
})
}

return mirrorIndex[identity] ?? identity
}

private func parseLocation(_ location: String) throws -> PackageIdentity {
if PackageIdentity.plain(location).isRegistry {
return PackageIdentity.plain(location)
} else if let path = try? AbsolutePath(validating: location) {
} else if let path = try? AbsolutePath(validating: location) {
return PackageIdentity(path: path)
} else if let url = URL(string: location) {
return PackageIdentity(url: url)
Expand Down
Loading