Skip to content
Open
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
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Swift: `Package.swift` manifests declaring package-registry dependencies (`.package(id: "scope.name", from: "1.0.0")` and the other `id:` forms introduced in SwiftPM 5.7) no longer fail analysis with `unexpected "id: "" expecting "name:", "path:", or "url:"`; the dependency is reported under its registry identifier. ([#1773](https://github.com/fossas/fossa-cli/pull/1773))
- Dart: `pubspec.yaml` files using valid dependency forms the parser previously rejected no longer fail analysis with `Aeson exception: ... empty` or `failed parsing pub package's source!`: a bare dependency with no value (any version), a `version:`-only entry, the `hosted: <url>` shorthand introduced in Dart 2.15, a `hosted:` map without a `version`, and a `git:` map without a `ref`. ([#1760](https://github.com/fossas/fossa-cli/pull/1760))
- Workflows: `fossa analyze --x-workflow <path>` runs a dependency-usage workflow analyzer through the embedded ficus and records its result in the debug bundle. ([#1761](https://github.com/fossas/fossa-cli/pull/1761))
- Workflows: the `--x-workflow` result is uploaded to FOSSA against the analyzed revision once the dependency upload succeeds; `--output` runs still upload nothing. ([#1762](https://github.com/fossas/fossa-cli/pull/1762))
Expand Down
8 changes: 6 additions & 2 deletions src/Strategy/Swift/PackageSwift.hs
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,12 @@ parsePackageDep = try parsePathDep <|> parseGitDep
_ <- symbol ".package" <* symbol "("
_ <- optionallyTry (parseKeyValue "name" parseQuotedText)

-- Url (Required Field)
url <- parseKeyValue "url" $ parseQuotedText <* maybeComma
-- Url (Required Field), or -- for a package-registry dependency (SwiftPM 5.7+) --
-- the package's scoped identifier, e.g. `.package(id: "mona.LinkedList", from: "1.0.0")`.
-- https://developer.apple.com/documentation/packagedescription/package/dependency/package(id:from:)
-- Registry dependencies take the same version requirements as url dependencies,
-- so they share this parser; the identifier is used in place of the url.
url <- (parseKeyValue "url" parseQuotedText <|> parseKeyValue "id" parseQuotedText) <* maybeComma

versionRequirement <-
optional $
Expand Down
57 changes: 57 additions & 0 deletions test/Swift/PackageSwiftSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ module Swift.PackageSwiftSpec (
spec,
) where

import Data.Foldable (for_)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
import Data.Map.Strict qualified as Map
import Data.String.Conversion (toString)
import Data.Text (Text)
import Data.Text qualified as Text
import Data.Text.IO qualified as TIO
import DepTypes (DepType (GitType, SwiftType), Dependency (..), VerConstraint (CEq))
import GraphUtil (expectDeps, expectDirect, expectEdges)
Expand Down Expand Up @@ -85,6 +88,23 @@ expectedSwiftPackage =
expectedSwiftPackageNoDeps :: SwiftPackage
expectedSwiftPackageNoDeps = SwiftPackage "6.0" []

-- | A minimal, valid Package.swift declaring the given package dependencies.
manifestWithDependencies :: [Text] -> Text
manifestWithDependencies deps =
Text.unlines $
[ "// swift-tools-version:5.7"
, "import PackageDescription"
, ""
, "let package = Package("
, " name: \"Example\","
, " dependencies: ["
]
<> map (\dep -> " " <> dep <> ",") deps
<> [ " ],"
, " targets: [.target(name: \"Example\")]"
, ")"
]

spec :: Spec
spec = do
packageDotSwiftFile <- runIO (TIO.readFile "test/Swift/testdata/Package.swift")
Expand All @@ -109,6 +129,43 @@ spec = do
Left failCode -> expectationFailure $ show failCode
Right result -> result `shouldBe` expectedSwiftPackageNoDeps

-- Package-registry dependencies (SwiftPM 5.7+) are declared with a scoped
-- identifier instead of a url: `.package(id: "scope.name", ...)`. They used to
-- fail the whole analysis with `unexpected "id: "" expecting "name:", "path:", or "url:"`.
describe "Parses package-registry dependencies" $ do
let registryForms :: [(Text, SwiftPackageGitDep)]
registryForms =
[ (".package(id: \"mona.LinkedList\", from: \"1.0.0\")", gitDepFrom "mona.LinkedList" "1.0.0")
, (".package(id: \"mona.LinkedList\", exact: \"1.2.3\")", gitDepExactly "mona.LinkedList" "1.2.3")
, (".package(id: \"mona.LinkedList\", .upToNextMajor(from: \"1.0.0\"))", gitDepUpToNextMajor "mona.LinkedList" "1.0.0")
, (".package(id: \"mona.LinkedList\", .upToNextMinor(from: \"1.0.0\"))", gitDepUpToNextMinor "mona.LinkedList" "1.0.0")
, (".package(id: \"mona.LinkedList\", \"1.0.0\"..<\"2.0.0\")", gitDepWithRhsHalfOpenInterval "mona.LinkedList" "1.0.0" "2.0.0")
, (".package(id: \"mona.LinkedList\", \"1.0.0\"...\"1.5.0\")", gitDepWithClosedRange "mona.LinkedList" "1.0.0" "1.5.0")
]
for_ registryForms $ \(form, expected) ->
it ("should parse " <> toString form) $ do
case runParser parsePackageSwiftFile "" (manifestWithDependencies [form]) of
Left failCode -> expectationFailure $ show failCode
Right result -> result `shouldBe` SwiftPackage "5.7" [GitSource expected]

it "should parse registry dependencies alongside url and path dependencies" $ do
let manifest =
manifestWithDependencies
[ ".package(url: \"https://github.com/apple/swift-argument-parser\", from: \"1.0.0\")"
, ".package(id: \"mona.LinkedList\", from: \"1.0.0\")"
, ".package(path: \"../local\")"
]
case runParser parsePackageSwiftFile "" manifest of
Left failCode -> expectationFailure $ show failCode
Right result ->
result
`shouldBe` SwiftPackage
"5.7"
[ GitSource $ gitDepFrom "https://github.com/apple/swift-argument-parser" "1.0.0"
, GitSource $ gitDepFrom "mona.LinkedList" "1.0.0"
, PathSource "../local"
]

describe "buildGraph, when no resolved content is discovered" $ do
it "should use git dependency type, when constraint is of branch, revision, or exact type" $ do
let expectedDeps =
Expand Down
Loading