Xcode cannot load a package manifest unless its URLs are percent encoded

I already filed FB7655953, but I thought I’d mention it here where it’s more likely to be seen by the relevant developers. This way it’s also visible to anyone else looking for a workaround.

As of 11.4, Xcode is once again incapable of loading a manifest containing something like this:

.package(url: "file:///Wherever/Παράδειγμα", from: "1.0.0")

SwiftPM handles that just fine on its own, but for Xcode you have to manually percent‐encode it:

import Foundation
let path = ProcessInfo.processInfo.environment["PATH"] ?? ""
let firstColon = path.range(of: ":")?.lowerBound ?? path.endIndex
let firstEntry = path[..<firstColon]
if firstEntry.hasSuffix("/Contents/Developer/usr/bin") {
  // Xcode is loading the manifest, not SwiftPM
  package.dependencies = package.dependencies.map { dependency in
    var modifiedURL = dependency.url.components(separatedBy: "/")
    var last = modifiedURL.removeLast()
    last = last.addingPercentEncoding(
      withAllowedCharacters: CharacterSet.urlPathAllowed
    )!
    modifiedURL.append(last)
    return .package(
      name: dependency.name,
      url: modifiedURL.joined(separator: "/"),
      dependency.requirement
    )
  }
}
3 Likes

Xcode 12.5 seems fatally broken.

Now, with the %, it objects:

The source control operation failed because the specified URL cannot be used. Make sure the URL is valid and try again.

But even without, it still objects:

The URL “blah.blah/blah” is invalid

A new workaround would be much appreciated if anyone can figure one out.

Out of curiosity, is this actually for a file URL? Does it perhaps work if you use a path (without %-encoding) instead?

I tried a local URL expressed both as a path /Users/... and as a URL file:///Users/.... It makes no difference. Both work with SwiftPM; neither works with Xcode.

Using the path argument instead does work, but it rules out versioning and cannot point at a bare repository.