Skip to content

Fix Swift SDK bundles not working due to quarantine #6426

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 10 commits into from
May 11, 2023
5 changes: 3 additions & 2 deletions Sources/Basics/FileSystem/FileSystem+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import struct TSCBasic.ByteString
import struct TSCBasic.FileInfo
import class TSCBasic.FileLock
import enum TSCBasic.FileMode
import enum TSCBasic.FileSystemAttribute
import protocol TSCBasic.FileSystem
import var TSCBasic.localFileSystem
import protocol TSCBasic.WritableByteStream
Expand Down Expand Up @@ -71,8 +72,8 @@ extension FileSystem {

/// Returns `true` if a given path has a quarantine attribute applied if when file system supports this attribute.
/// Returns `false` if such attribute is not applied or it isn't supported.
public func hasQuarantineAttribute(_ path: AbsolutePath) -> Bool {
self.hasQuarantineAttribute(path.underlying)
public func hasAttribute(_ name: FileSystemAttribute, _ path: AbsolutePath) -> Bool {
self.hasAttribute(name, path.underlying)
}

/// Get the contents of the given directory, in an undefined order.
Expand Down
16 changes: 16 additions & 0 deletions Sources/PackageModel/Destination.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ public enum DestinationError: Swift.Error {
/// A destination with this artifact ID is already installed. Can't install a new bundle with this artifact,
/// installed artifact IDs are expected to be unique.
case destinationArtifactAlreadyInstalled(installedBundleName: String, newBundleName: String, artifactID: String)

#if os(macOS)
/// Quarantine attribute should be removed by the `xattr` command from an installed bundle.
case quarantineAttributePresent(bundlePath: AbsolutePath)
#endif
}

extension DestinationError: CustomStringConvertible {
Expand Down Expand Up @@ -93,6 +98,17 @@ extension DestinationError: CustomStringConvertible {
`\(installedBundleName)`. Can't install a new bundle `\(newBundleName)` with this artifact, artifact IDs \
are expected to be unique across all installed Swift SDK bundles.
"""
#if os(macOS)
case .quarantineAttributePresent(let bundlePath):
return """
Quarantine attribute is present on a Swift SDK bundle at path `\(bundlePath)`. If you're certain that the \
bundle was downloaded from a trusted source, you can remove the attribute with this command:

xattr -d -r -s com.apple.quarantine "\(bundlePath)"

and try to install this bundle again.
"""
#endif
}
}
}
Expand Down
15 changes: 12 additions & 3 deletions Sources/PackageModel/SwiftSDKBundle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import Basics

import struct Foundation.URL
import protocol TSCBasic.FileSystem
import struct TSCBasic.RegEx

/// Represents an `.artifactbundle` on the filesystem that contains a Swift SDK.
Expand Down Expand Up @@ -120,7 +121,7 @@ public struct SwiftSDKBundle {

return selectedDestination
}

/// Installs a destination bundle from a given path or URL to a destinations installation directory.
/// - Parameters:
/// - bundlePathOrURL: A string passed on the command line, which is either an absolute or relative to a current
Expand Down Expand Up @@ -245,6 +246,13 @@ public struct SwiftSDKBundle {
_ archiver: some Archiver,
_ observabilityScope: ObservabilityScope
) throws {
#if os(macOS)
// Check the quarantine attribute on bundles downloaded manually in the browser.
guard !fileSystem.hasAttribute(.quarantine, bundlePath) else {
throw DestinationError.quarantineAttributePresent(bundlePath: bundlePath)
}
#endif

let unpackedBundlePath = try unpackIfNeeded(
bundlePath: bundlePath,
destinationsDirectory: destinationsDirectory,
Expand Down Expand Up @@ -359,7 +367,8 @@ extension ArtifactsArchiveMetadata {

do {
let destinations = try Destination.decode(
fromFile: variantConfigurationPath, fileSystem: fileSystem, observabilityScope: observabilityScope
fromFile: variantConfigurationPath, fileSystem: fileSystem,
observabilityScope: observabilityScope
)

variants.append(.init(metadata: variantMetadata, swiftSDKs: destinations))
Expand All @@ -378,7 +387,7 @@ extension ArtifactsArchiveMetadata {
}
}

extension Array where Element == SwiftSDKBundle {
extension [SwiftSDKBundle] {
/// Select a destination with a given artifact ID from a `self` array of available destinations.
/// - Parameters:
/// - id: artifact ID of the destination to look up.
Expand Down