Skip to content
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

refactor workspace initializers #3933

Merged
merged 3 commits into from
Jan 27, 2022
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
6 changes: 3 additions & 3 deletions Sources/Basics/FileSystem+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ extension FileSystem {
}

extension FileSystem {
public func getOrCreateSwiftPMConfigurationDirectory(observabilityScope: ObservabilityScope?) throws -> AbsolutePath {
public func getOrCreateSwiftPMConfigurationDirectory(warningHandler: (String) -> Void) throws -> AbsolutePath {
let idiomaticConfigurationDirectory = self.swiftPMConfigurationDirectory

// temporary 5.6, remove on next version: transition from previous configuration location
Expand All @@ -108,10 +108,10 @@ extension FileSystem {
.filter{ self.isFile($0) && !self.isSymlink($0) && $0.extension != "lock"}
for file in configurationFiles {
let destination = idiomaticConfigurationDirectory.appending(component: file.basename)
observabilityScope?.emit(warning: "Usage of \(file) has been deprecated. Please delete it and use the new \(destination) instead.")
if !self.exists(destination) {
try self.copy(from: file, to: destination)
}
warningHandler("Usage of \(file) has been deprecated. Please delete it and use the new \(destination) instead.")
}
}
// in the case where ~/.swiftpm/configuration is the idiomatic location (eg on Linux)
Expand All @@ -125,10 +125,10 @@ extension FileSystem {
.filter{ self.isFile($0) && !self.isSymlink($0) && $0.extension != "lock"}
for file in configurationFiles {
let destination = idiomaticConfigurationDirectory.appending(component: file.basename)
observabilityScope?.emit(warning: "Usage of \(file) has been deprecated. Please delete it and use the new \(destination) instead.")
if !self.exists(destination) {
try self.copy(from: file, to: destination)
}
warningHandler("Usage of \(file) has been deprecated. Please delete it and use the new \(destination) instead.")
}
}
}
Expand Down
6 changes: 2 additions & 4 deletions Sources/Commands/APIDigester.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,11 @@ struct APIDigesterBaselineDumper {
try workingCopy.checkout(revision: baselineRevision)

// Create the workspace for this package.
let workspace = try Workspace(
forRootPackage: baselinePackageRoot
)
let workspace = try Workspace(forRootPackage: baselinePackageRoot)

let graph = try workspace.loadPackageGraph(
rootPath: baselinePackageRoot,
observabilityScope: observabilityScope
observabilityScope: self.observabilityScope
)

// Don't emit a baseline for a module that didn't exist yet in this revision.
Expand Down
17 changes: 13 additions & 4 deletions Sources/Commands/SwiftPackageRegistryTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ public struct SwiftPackageRegistryTool: ParsableCommand {
}
}

let configuration = try swiftTool.getRegistriesConfig()
if global {
let configuration = try getRegistriesConfig(swiftTool)
if self.global {
try configuration.updateShared(with: set)
} else {
try configuration.updateLocal(with: set)
Expand Down Expand Up @@ -141,12 +141,21 @@ public struct SwiftPackageRegistryTool: ParsableCommand {
}
}

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

static func getRegistriesConfig(_ swiftTool: SwiftTool) throws -> Workspace.Configuration.Registries {
let workspace = try swiftTool.getActiveWorkspace()
return try .init(
fileSystem: localFileSystem,
localRegistriesFile: workspace.location.localRegistriesConfigurationFile,
sharedRegistriesFile: workspace.location.sharedRegistriesConfigurationFile
)
}
}
29 changes: 19 additions & 10 deletions Sources/Commands/SwiftPackageTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1549,20 +1549,20 @@ extension SwiftPackageTool.Config {
var mirrorURL: String

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

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

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

try config.applyLocal { mirrors in
mirrors.set(mirrorURL: mirrorURL, forURL: originalURL)
mirrors.set(mirrorURL: self.mirrorURL, forURL: originalURL)
}
}
}
Expand All @@ -1584,14 +1584,14 @@ extension SwiftPackageTool.Config {
var mirrorURL: String?

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

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

guard let originalOrMirrorURL = packageURL ?? originalURL ?? mirrorURL else {
guard let originalOrMirrorURL = self.packageURL ?? self.originalURL ?? self.mirrorURL else {
swiftTool.observabilityScope.emit(.missingRequiredArg("--original-url or --mirror-url"))
throw ExitCode.failure
}
Expand All @@ -1616,14 +1616,14 @@ extension SwiftPackageTool.Config {
var originalURL: String?

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

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

guard let originalURL = packageURL ?? originalURL else {
guard let originalURL = self.packageURL ?? self.originalURL else {
swiftTool.observabilityScope.emit(.missingRequiredArg("--original-url"))
throw ExitCode.failure
}
Expand All @@ -1637,6 +1637,15 @@ extension SwiftPackageTool.Config {
}
}
}

static func getMirrorsConfig(_ swiftTool: SwiftTool) throws -> Workspace.Configuration.Mirrors {
let workspace = try swiftTool.getActiveWorkspace()
return try .init(
fileSystem: localFileSystem,
localMirrorsFile: workspace.location.localMirrorsConfigurationFile,
sharedMirrorsFile: workspace.location.sharedMirrorsConfigurationFile
)
}
}

extension SwiftPackageTool {
Expand Down
164 changes: 58 additions & 106 deletions Sources/Commands/SwiftTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import ArgumentParser
import Basics
import Build
import Dispatch
import func Foundation.NSUserName
import class Foundation.ProcessInfo
import func Foundation.NSHomeDirectory
import PackageGraph
import PackageLoading
import PackageModel
Expand Down Expand Up @@ -489,51 +487,75 @@ public class SwiftTool {

}

private func editsDirectory() throws -> AbsolutePath {
/// Returns the currently active workspace.
func getActiveWorkspace() throws -> Workspace {
if let workspace = _workspace {
return workspace
}

let delegate = ToolWorkspaceDelegate(self.outputStream, logLevel: self.logLevel, observabilityScope: self.observabilityScope)
let repositoryProvider = GitRepositoryProvider(processSet: self.processSet)
let isXcodeBuildSystemEnabled = self.options.buildSystem == .xcode
let workspace = try Workspace(
fileSystem: localFileSystem,
location: .init(
workingDirectory: self.buildPath,
editsDirectory: self.getEditsDirectory(),
resolvedVersionsFile: self.getResolvedVersionsFile(),
localConfigurationDirectory: try self.getLocalConfigurationDirectory(),
sharedConfigurationDirectory: self.sharedConfigurationDirectory,
sharedSecurityDirectory: self.sharedSecurityDirectory,
sharedCacheDirectory: self.sharedCacheDirectory
),
authorizationProvider: self.getAuthorizationProvider(),
configuration: .init(
skipDependenciesUpdates: options.skipDependencyUpdate,
prefetchBasedOnResolvedFile: options.shouldEnableResolverPrefetching,
additionalFileRules: isXcodeBuildSystemEnabled ? FileRuleDescription.xcbuildFileTypes : FileRuleDescription.swiftpmFileTypes,
sharedRepositoriesCacheEnabled: self.options.useRepositoriesCache,
fingerprintCheckingMode: self.options.resolverFingerprintCheckingMode
),
initializationWarningHandler: { self.observabilityScope.emit(warning: $0) },
customManifestLoader: self.getManifestLoader(), // FIXME: ideally we would not customize the manifest loader
tomerd marked this conversation as resolved.
Show resolved Hide resolved
customRepositoryProvider: repositoryProvider, // FIXME: ideally we would not customize the repository provider. its currently done for shutdown handling which can be better abstracted
delegate: delegate
)
_workspace = workspace
_workspaceDelegate = delegate
return workspace
}

private func getEditsDirectory() throws -> AbsolutePath {
// TODO: replace multiroot-data-file with explicit overrides
if let multiRootPackageDataFile = options.multirootPackageDataFile {
return multiRootPackageDataFile.appending(component: "Packages")
}
return try Workspace.DefaultLocations.editsDirectory(forRootPackage: self.getPackageRoot())
}

private func resolvedVersionsFile() throws -> AbsolutePath {
private func getResolvedVersionsFile() throws -> AbsolutePath {
// TODO: replace multiroot-data-file with explicit overrides
if let multiRootPackageDataFile = options.multirootPackageDataFile {
return multiRootPackageDataFile.appending(components: "xcshareddata", "swiftpm", "Package.resolved")
}
return try Workspace.DefaultLocations.resolvedVersionsFile(forRootPackage: self.getPackageRoot())
}

func getMirrorsConfig() throws -> Workspace.Configuration.Mirrors {
let sharedMirrorFile = self.sharedConfigurationDirectory.map {
Workspace.DefaultLocations.mirrorsConfigurationFile(at: $0)
}
return try .init(
localMirrorFile: self.mirrorsConfigFile(),
sharedMirrorFile: sharedMirrorFile,
fileSystem: localFileSystem
)
}

private func mirrorsConfigFile() throws -> AbsolutePath {
// TODO: does this make sense now that we a global configuration as well? or should we at least rename it?
// Look for the override in the environment.
if let envPath = ProcessEnv.vars["SWIFTPM_MIRROR_CONFIG"] {
return try AbsolutePath(validating: envPath)
}

internal func getLocalConfigurationDirectory() throws -> AbsolutePath {
// Otherwise, use the default path.
// TODO: replace multiroot-data-file with explicit overrides
if let multiRootPackageDataFile = options.multirootPackageDataFile {
// migrate from legacy location
let legacyPath = multiRootPackageDataFile.appending(components: "xcshareddata", "swiftpm", "config")
let newPath = multiRootPackageDataFile.appending(components: "xcshareddata", "swiftpm", "configuration", "mirrors.json")
let newPath = Workspace.DefaultLocations.mirrorsConfigurationFile(at: multiRootPackageDataFile.appending(components: "xcshareddata", "swiftpm", "configuration"))
if localFileSystem.exists(legacyPath) {
try localFileSystem.createDirectory(newPath.parentDirectory, recursive: true)
try localFileSystem.move(from: legacyPath, to: newPath)
observabilityScope.emit(warning: "Usage of \(legacyPath) has been deprecated. Please delete it and use the new \(newPath) instead.")
if !localFileSystem.exists(newPath) {
try localFileSystem.createDirectory(newPath.parentDirectory, recursive: true)
try localFileSystem.copy(from: legacyPath, to: newPath)
}
}
return newPath
return newPath.parentDirectory
}

// migrate from legacy location
Expand All @@ -546,20 +568,7 @@ public class SwiftTool {
try localFileSystem.copy(from: legacyPath, to: newPath)
}
}
return newPath
}

func getRegistriesConfig() throws -> Workspace.Configuration.Registries {
let localRegistriesFile = try Workspace.DefaultLocations.registriesConfigurationFile(forRootPackage: self.getPackageRoot())
let sharedRegistriesFile = self.sharedConfigurationDirectory.map {
Workspace.DefaultLocations.registriesConfigurationFile(at: $0)
}

return try .init(
localRegistriesFile: localRegistriesFile,
sharedRegistriesFile: sharedRegistriesFile,
fileSystem: localFileSystem
)
return newPath.parentDirectory
}

func getAuthorizationProvider() throws -> AuthorizationProvider? {
Expand Down Expand Up @@ -620,42 +629,6 @@ public class SwiftTool {
return providers
}

/// Returns the currently active workspace.
func getActiveWorkspace() throws -> Workspace {
if let workspace = _workspace {
return workspace
}

let delegate = ToolWorkspaceDelegate(self.outputStream, logLevel: self.logLevel, observabilityScope: self.observabilityScope)
let provider = GitRepositoryProvider(processSet: processSet)
let isXcodeBuildSystemEnabled = self.options.buildSystem == .xcode
let workspace = try Workspace(
fileSystem: localFileSystem,
location: .init(
workingDirectory: self.buildPath,
editsDirectory: self.editsDirectory(),
resolvedVersionsFile: self.resolvedVersionsFile(),
sharedSecurityDirectory: self.sharedSecurityDirectory,
sharedCacheDirectory: self.sharedCacheDirectory,
sharedConfigurationDirectory: self.sharedConfigurationDirectory
),
mirrors: self.getMirrorsConfig().mirrors,
registries: try self.getRegistriesConfig().configuration,
authorizationProvider: self.getAuthorizationProvider(),
customManifestLoader: self.getManifestLoader(), // FIXME: doe we really need to customize it?
customRepositoryProvider: provider, // FIXME: doe we really need to customize it?
additionalFileRules: isXcodeBuildSystemEnabled ? FileRuleDescription.xcbuildFileTypes : FileRuleDescription.swiftpmFileTypes,
resolverUpdateEnabled: !self.options.skipDependencyUpdate,
resolverPrefetchingEnabled: self.options.shouldEnableResolverPrefetching,
resolverFingerprintCheckingMode: self.options.resolverFingerprintCheckingMode,
sharedRepositoriesCacheEnabled: self.options.useRepositoriesCache,
delegate: delegate
)
_workspace = workspace
_workspaceDelegate = delegate
return workspace
}

/// Start redirecting the standard output stream to the standard error stream.
func redirectStdoutToStderr() {
self.outputStream = TSCBasic.stderrStream
Expand Down Expand Up @@ -1030,16 +1003,9 @@ private func getSharedSecurityDirectory(options: SwiftToolOptions, observability
try localFileSystem.createDirectory(explicitSecurityPath, recursive: true)
}
return explicitSecurityPath
}

do {
let sharedSecurityDirectory = try localFileSystem.getOrCreateSwiftPMSecurityDirectory()
// make sure we can write files
try withTemporaryFile(dir: sharedSecurityDirectory) { _ in }
return sharedSecurityDirectory
} catch {
observabilityScope.emit(warning: "Failed creating default security location, \(error)")
return .none
} else {
// further validation is done in workspace
return localFileSystem.swiftPMSecurityDirectory
}
}

Expand All @@ -1050,16 +1016,9 @@ private func getSharedConfigurationDirectory(options: SwiftToolOptions, observab
try localFileSystem.createDirectory(explicitConfigPath, recursive: true)
}
return explicitConfigPath
}

do {
let sharedConfigurationDirector = try localFileSystem.getOrCreateSwiftPMConfigurationDirectory(observabilityScope: observabilityScope)
// make sure we can write files
try withTemporaryFile(dir: sharedConfigurationDirector) { _ in }
return sharedConfigurationDirector
} catch {
observabilityScope.emit(warning: "Failed creating default configuration location, \(error)")
return .none
} else {
// further validation is done in workspace
return localFileSystem.swiftPMConfigurationDirectory
}
}

Expand All @@ -1070,16 +1029,9 @@ private func getSharedCacheDirectory(options: SwiftToolOptions, observabilitySco
try localFileSystem.createDirectory(explicitCachePath, recursive: true)
}
return explicitCachePath
}

do {
let sharedCacheDirector = try localFileSystem.getOrCreateSwiftPMCacheDirectory()
// make sure we can write files
try withTemporaryFile(dir: sharedCacheDirector) { _ in }
return sharedCacheDirector
} catch {
observabilityScope.emit(warning: "Failed creating default cache location, \(error)")
return .none
} else {
// further validation is done in workspace
return localFileSystem.swiftPMCacheDirectory
}
}

Expand Down
Loading