diff --git a/.github/labeler.yml b/.github/labeler.yml index 1584a17af32..cb9d03e280d 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -45,3 +45,6 @@ "L: terraform": - terraform/**/* + +"L: swift": + - swift/**/* diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c23cc61a83..113635ce30c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,6 +46,8 @@ jobs: - { path: python, name: python, ci_node_total: 2, ci_node_index: 1, ecosystem: pip } - { path: python, name: python_slow, ci_node_total: 2, ci_node_index: 0, ecosystem: pip } - { path: python, name: python_slow, ci_node_total: 2, ci_node_index: 1, ecosystem: pip } + - { path: swift, name: swift, ci_node_total: 2, ci_node_index: 0, ecosystem: swift } + - { path: swift, name: swift, ci_node_total: 2, ci_node_index: 1, ecosystem: swift } - { path: terraform, name: terraform, ecosystem: terraform } steps: @@ -164,6 +166,13 @@ jobs: - 'omnibus/**' - 'python/**' - '.github/workflows/ci.yml' + swift: + - Dockerfile.updater-core + - 'common/**' + - 'updater/Gemfil*' + - 'omnibus/**' + - 'swift/**' + - '.github/workflows/ci.yml' terraform: - Dockerfile.updater-core - 'common/**' diff --git a/.github/workflows/images-branch.yml b/.github/workflows/images-branch.yml index 794fee44e2a..08e85c2613d 100644 --- a/.github/workflows/images-branch.yml +++ b/.github/workflows/images-branch.yml @@ -40,6 +40,7 @@ jobs: - { name: nuget, ecosystem: nuget } - { name: pub, ecosystem: pub } - { name: python, ecosystem: pip } + - { name: swift, ecosystem: swift } - { name: terraform, ecosystem: terraform } permissions: contents: read diff --git a/.github/workflows/images-latest.yml b/.github/workflows/images-latest.yml index e011a6c095d..fbf5e2f14cd 100644 --- a/.github/workflows/images-latest.yml +++ b/.github/workflows/images-latest.yml @@ -47,6 +47,7 @@ jobs: - { name: nuget, ecosystem: nuget } - { name: pub, ecosystem: pub } - { name: python, ecosystem: pip } + - { name: swift, ecosystem: swift } - { name: terraform, ecosystem: terraform } env: COMMIT_SHA: ${{ github.sha }} diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index e63b6bccb27..8de532f24cc 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -54,6 +54,7 @@ jobs: - { path: python, name: pipenv, ecosystem: pip} - { path: python, name: pip-compile, ecosystem: pip } - { path: python, name: poetry, ecosystem: pip } + - { path: swift, name: swift, ecosystem: swift } - { path: terraform, name: terraform, ecosystem: terraform } steps: - uses: actions/checkout@v3 @@ -212,6 +213,12 @@ jobs: - 'common/**' - 'updater/**' - 'git_submodules/**' + swift: + - .github/workflows/smoke.yml + - Dockerfile.updater-core + - 'common/**' + - 'updater/**' + - 'swift/**' terraform: - .github/workflows/smoke.yml - Dockerfile.updater-core diff --git a/Dockerfile.development b/Dockerfile.development index d22d8693536..ded93d760be 100644 --- a/Dockerfile.development +++ b/Dockerfile.development @@ -44,6 +44,7 @@ COPY --chown=dependabot:dependabot npm_and_yarn/Gemfile npm_and_yarn/dependabot- COPY --chown=dependabot:dependabot nuget/Gemfile nuget/dependabot-nuget.gemspec ${CODE_DIR}/nuget/ COPY --chown=dependabot:dependabot python/Gemfile python/dependabot-python.gemspec ${CODE_DIR}/python/ COPY --chown=dependabot:dependabot pub/Gemfile pub/dependabot-pub.gemspec ${CODE_DIR}/pub/ +COPY --chown=dependabot:dependabot swift/Gemfile swift/dependabot-swift.gemspec ${CODE_DIR}/swift/ COPY --chown=dependabot:dependabot terraform/Gemfile terraform/dependabot-terraform.gemspec ${CODE_DIR}/terraform/ # Prepare the updater project diff --git a/Dockerfile.updater-core b/Dockerfile.updater-core index c8c0d1d1bae..34afd17b51d 100644 --- a/Dockerfile.updater-core +++ b/Dockerfile.updater-core @@ -79,10 +79,11 @@ COPY --chown=dependabot:dependabot npm_and_yarn/Gemfile npm_and_yarn/dependabot- COPY --chown=dependabot:dependabot nuget/Gemfile nuget/dependabot-nuget.gemspec nuget/ COPY --chown=dependabot:dependabot pub/Gemfile pub/dependabot-pub.gemspec pub/ COPY --chown=dependabot:dependabot python/Gemfile python/dependabot-python.gemspec python/ +COPY --chown=dependabot:dependabot swift/Gemfile swift/dependabot-swift.gemspec swift/ COPY --chown=dependabot:dependabot terraform/Gemfile terraform/dependabot-terraform.gemspec terraform/ # prevent having all the source in every ecosystem image -RUN for ecosystem in git_submodules terraform github_actions hex elm docker nuget maven gradle cargo composer go_modules python pub npm_and_yarn bundler; do \ +RUN for ecosystem in git_submodules terraform github_actions hex elm docker nuget maven gradle cargo composer go_modules python pub npm_and_yarn bundler swift; do \ mkdir -p $ecosystem/lib/dependabot; \ touch $ecosystem/lib/dependabot/$ecosystem.rb; \ done diff --git a/Rakefile b/Rakefile index 0a16d248c5e..5d668dbdeb3 100644 --- a/Rakefile +++ b/Rakefile @@ -31,6 +31,7 @@ GEMSPECS = %w( python/dependabot-python.gemspec pub/dependabot-pub.gemspec omnibus/dependabot-omnibus.gemspec + swift/dependabot-swift.gemspec ).freeze def run_command(command) diff --git a/bin/docker-dev-shell b/bin/docker-dev-shell index 6a889d56e49..7742b8685d8 100755 --- a/bin/docker-dev-shell +++ b/bin/docker-dev-shell @@ -226,6 +226,12 @@ docker run --rm -ti \ -v "$(pwd)/python/lib:$CODE_DIR/python/lib" \ -v "$(pwd)/python/script:$CODE_DIR/python/script" \ -v "$(pwd)/python/spec:$CODE_DIR/python/spec" \ + -v "$(pwd)/swift/.rubocop.yml:$CODE_DIR/swift/.rubocop.yml" \ + -v "$(pwd)/swift/Gemfile:$CODE_DIR/swift/Gemfile" \ + -v "$(pwd)/swift/dependabot-swift.gemspec:$CODE_DIR/swift/dependabot-swift.gemspec" \ + -v "$(pwd)/swift/lib:$CODE_DIR/swift/lib" \ + -v "$(pwd)/swift/script:$CODE_DIR/swift/script" \ + -v "$(pwd)/swift/spec:$CODE_DIR/swift/spec" \ -v "$(pwd)/terraform/.rubocop.yml:$CODE_DIR/terraform/.rubocop.yml" \ -v "$(pwd)/terraform/Gemfile:$CODE_DIR/terraform/Gemfile" \ -v "$(pwd)/terraform/dependabot-terraform.gemspec:$CODE_DIR/terraform/dependabot-terraform.gemspec" \ diff --git a/bin/dry-run.rb b/bin/dry-run.rb index 7020df2dbce..2cb5d6b4c73 100755 --- a/bin/dry-run.rb +++ b/bin/dry-run.rb @@ -33,6 +33,7 @@ # - docker # - terraform # - pub +# - swift # rubocop:disable Style/GlobalVars @@ -62,6 +63,7 @@ $LOAD_PATH << "./nuget/lib" $LOAD_PATH << "./python/lib" $LOAD_PATH << "./pub/lib" +$LOAD_PATH << "./swift/lib" $LOAD_PATH << "./terraform/lib" require "bundler" @@ -100,6 +102,7 @@ require "dependabot/nuget" require "dependabot/python" require "dependabot/pub" +require "dependabot/swift" require "dependabot/terraform" # GitHub credentials with write permission to the repo you want to update diff --git a/common/lib/dependabot/config/file.rb b/common/lib/dependabot/config/file.rb index e5d446c1374..3f4f2d80e91 100644 --- a/common/lib/dependabot/config/file.rb +++ b/common/lib/dependabot/config/file.rb @@ -53,6 +53,7 @@ def self.parse(config) "npm" => "npm_and_yarn", "pip" => "pip", "pub" => "pub", + "swift" => "swift", "terraform" => "terraform" }.freeze diff --git a/omnibus/Gemfile b/omnibus/Gemfile index a330f0516b0..9ce89ed4d71 100644 --- a/omnibus/Gemfile +++ b/omnibus/Gemfile @@ -18,6 +18,7 @@ gemspec path: "../npm_and_yarn" gemspec path: "../nuget" gemspec path: "../pub" gemspec path: "../python" +gemspec path: "../swift" gemspec path: "../terraform" # Visual Studio Code integration diff --git a/omnibus/dependabot-omnibus.gemspec b/omnibus/dependabot-omnibus.gemspec index 79760d579b5..3fdda0368e7 100644 --- a/omnibus/dependabot-omnibus.gemspec +++ b/omnibus/dependabot-omnibus.gemspec @@ -42,6 +42,7 @@ Gem::Specification.new do |spec| spec.add_dependency "dependabot-nuget", Dependabot::VERSION spec.add_dependency "dependabot-pub", Dependabot::VERSION spec.add_dependency "dependabot-python", Dependabot::VERSION + spec.add_dependency "dependabot-swift", Dependabot::VERSION spec.add_dependency "dependabot-terraform", Dependabot::VERSION common_gemspec.development_dependencies.each do |dep| diff --git a/omnibus/lib/dependabot/omnibus.rb b/omnibus/lib/dependabot/omnibus.rb index 215a08bc449..58b29d37c92 100644 --- a/omnibus/lib/dependabot/omnibus.rb +++ b/omnibus/lib/dependabot/omnibus.rb @@ -16,3 +16,4 @@ require "dependabot/npm_and_yarn" require "dependabot/bundler" require "dependabot/pub" +require "dependabot/swift" diff --git a/script/dependabot b/script/dependabot index 2b857442f3d..df0dc7e100a 100755 --- a/script/dependabot +++ b/script/dependabot @@ -21,5 +21,6 @@ dependabot \ -v "$(pwd)"/nuget:/home/dependabot/nuget \ -v "$(pwd)"/pub:/home/dependabot/pub \ -v "$(pwd)"/python:/home/dependabot/python \ + -v "$(pwd)"/swift:/home/dependabot/swift \ -v "$(pwd)"/terraform:/home/dependabot/terraform \ "$@" diff --git a/swift/.gitignore b/swift/.gitignore new file mode 100644 index 00000000000..06845bd78c0 --- /dev/null +++ b/swift/.gitignore @@ -0,0 +1,5 @@ +/.bundle/ +/.env +/tmp +/dependabot-*.gem +Gemfile.lock diff --git a/swift/.rubocop.yml b/swift/.rubocop.yml new file mode 100644 index 00000000000..a9f364a37fa --- /dev/null +++ b/swift/.rubocop.yml @@ -0,0 +1 @@ +inherit_from: ../omnibus/.rubocop.yml diff --git a/swift/Dockerfile b/swift/Dockerfile new file mode 100644 index 00000000000..0bf0fbbe975 --- /dev/null +++ b/swift/Dockerfile @@ -0,0 +1,44 @@ +FROM ghcr.io/dependabot/dependabot-updater-core +ARG TARGETARCH + +ENV PATH="${PATH}:/opt/swift/usr/bin" + +# OS dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + binutils \ + libc6-dev \ + libcurl4 \ + libedit2 \ + libgcc-9-dev \ + libpython2.7 \ + libsqlite3-0 \ + libstdc++-9-dev \ + libxml2 \ + libz3-dev \ + pkg-config \ + tzdata \ + uuid-dev \ + && rm -rf /var/lib/apt/lists/* + +USER dependabot + +# https://www.swift.org/download/ +ARG SWIFT_VERSION=5.8.1 +ARG SWIFT_UBUNTU_VERSION=ubuntu20.04 + +RUN if [ "$TARGETARCH" = "arm64" ]; then SWIFT_UBUNTU_VERSION="${SWIFT_UBUNTU_VERSION}-aarch64"; fi \ + && SWIFT_SHORT_UBUNTU_VERSION=$(echo $SWIFT_UBUNTU_VERSION | tr -d .) \ + && SWIFT_TARBALL="swift-${SWIFT_VERSION}-RELEASE-${SWIFT_UBUNTU_VERSION}.tar.gz" \ + && DOWNLOAD_URL=https://download.swift.org/swift-${SWIFT_VERSION}-release/${SWIFT_SHORT_UBUNTU_VERSION}/swift-${SWIFT_VERSION}-RELEASE/${SWIFT_TARBALL} \ + && curl --connect-timeout 15 --retry 5 "${DOWNLOAD_URL}" > "/tmp/${SWIFT_TARBALL}" \ + && curl --connect-timeout 15 --retry 5 "${DOWNLOAD_URL}.sig" > "/tmp/${SWIFT_TARBALL}.sig" \ + && sh -c 'curl --connect-timeout 15 --retry 5 https://www.swift.org/keys/all-keys.asc | gpg --import -' \ + && gpg --keyserver hkp://keyserver.ubuntu.com --refresh-keys Swift \ + && gpg --verify /tmp/${SWIFT_TARBALL}.sig \ + && mkdir /opt/swift \ + && tar -C /opt/swift -xzf /tmp/${SWIFT_TARBALL} --strip-components 1 + +COPY --chown=dependabot:dependabot swift $DEPENDABOT_HOME/swift +COPY --chown=dependabot:dependabot common $DEPENDABOT_HOME/common +COPY --chown=dependabot:dependabot updater $DEPENDABOT_HOME/dependabot-updater diff --git a/swift/Gemfile b/swift/Gemfile new file mode 100644 index 00000000000..430599a9e1b --- /dev/null +++ b/swift/Gemfile @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "dependabot-common", path: "../common" + +gemspec diff --git a/swift/README.md b/swift/README.md new file mode 100644 index 00000000000..2b3a2f13f31 --- /dev/null +++ b/swift/README.md @@ -0,0 +1,18 @@ +## `dependabot-swift` + +Swift Package Manager support for [`dependabot-core`][core-repo]. + +### Running locally + +1. Start a development shell + + ``` + $ bin/docker-dev-shell swift + ``` + +2. Run tests + ``` + [dependabot-core-dev] ~/dependabot-core $ cd swift && rspec + ``` + +[core-repo]: https://github.com/dependabot/dependabot-core diff --git a/swift/dependabot-swift.gemspec b/swift/dependabot-swift.gemspec new file mode 100644 index 00000000000..29f02441cf3 --- /dev/null +++ b/swift/dependabot-swift.gemspec @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +Gem::Specification.new do |spec| + common_gemspec = + Bundler.load_gemspec_uncached("../common/dependabot-common.gemspec") + + spec.name = "dependabot-swift" + spec.summary = "Provides Dependabot support for Swift" + spec.description = "Dependabot-Swift provides support for bumping Swift packages via Dependabot. " \ + "If you want support for multiple package managers, you probably want the meta-gem " \ + "dependabot-omnibus." + + spec.author = common_gemspec.author + spec.email = common_gemspec.email + spec.homepage = common_gemspec.homepage + spec.license = common_gemspec.license + + spec.metadata = { + "bug_tracker_uri" => common_gemspec.metadata["bug_tracker_uri"], + "changelog_uri" => common_gemspec.metadata["changelog_uri"] + } + + spec.version = common_gemspec.version + spec.required_ruby_version = common_gemspec.required_ruby_version + spec.required_rubygems_version = common_gemspec.required_ruby_version + + spec.require_path = "lib" + spec.files = Dir["lib/**/*"] + + spec.add_dependency "dependabot-common", Dependabot::VERSION + + common_gemspec.development_dependencies.each do |dep| + spec.add_development_dependency dep.name, *dep.requirement.as_list + end +end diff --git a/swift/lib/dependabot/swift.rb b/swift/lib/dependabot/swift.rb new file mode 100644 index 00000000000..4a84352f197 --- /dev/null +++ b/swift/lib/dependabot/swift.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +# These all need to be required so the various classes can be registered in a +# lookup table of package manager names to concrete classes. +require "dependabot/swift/file_fetcher" +require "dependabot/swift/file_parser" +require "dependabot/swift/update_checker" +require "dependabot/swift/file_updater" +require "dependabot/swift/metadata_finder" +require "dependabot/swift/requirement" +require "dependabot/swift/version" + +require "dependabot/pull_request_creator/labeler" +Dependabot::PullRequestCreator::Labeler. + register_label_details("swift", name: "swift_package_manager", colour: "F05138") + +require "dependabot/dependency" +Dependabot::Dependency. + register_production_check("swift", ->(_) { true }) + +require "dependabot/utils" +Dependabot::Utils.register_always_clone("swift") diff --git a/swift/lib/dependabot/swift/file_fetcher.rb b/swift/lib/dependabot/swift/file_fetcher.rb new file mode 100644 index 00000000000..8d548f9cda0 --- /dev/null +++ b/swift/lib/dependabot/swift/file_fetcher.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require "dependabot/file_fetchers" +require "dependabot/file_fetchers/base" + +module Dependabot + module Swift + class FileFetcher < Dependabot::FileFetchers::Base + def self.required_files_in?(filenames) + filenames.include?("Package.swift") + end + + def self.required_files_message + "Repo must contain a Package.swift configuration file." + end + + private + + def fetch_files + check_required_files_present + + fetched_files = [] + fetched_files << package_manifest + fetched_files << package_resolved if package_resolved + fetched_files + end + + def package_manifest + @package_manifest ||= fetch_file_from_host("Package.swift") + end + + def package_resolved + return @package_resolved if defined?(@package_resolved) + + @package_resolved = fetch_file_if_present("Package.resolved") + end + + def check_required_files_present + return if package_manifest + + path = Pathname.new(File.join(directory, "Package.swift")). + cleanpath.to_path + raise Dependabot::DependencyFileNotFound, path + end + end + end +end + +Dependabot::FileFetchers. + register("swift", Dependabot::Swift::FileFetcher) diff --git a/swift/lib/dependabot/swift/file_parser.rb b/swift/lib/dependabot/swift/file_parser.rb new file mode 100644 index 00000000000..53ab668502c --- /dev/null +++ b/swift/lib/dependabot/swift/file_parser.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require "dependabot/dependency" +require "dependabot/file_parsers" +require "dependabot/file_parsers/base" +require "dependabot/swift/file_parser/dependency_parser" +require "dependabot/swift/file_parser/manifest_parser" + +module Dependabot + module Swift + class FileParser < Dependabot::FileParsers::Base + require "dependabot/file_parsers/base/dependency_set" + + def parse + dependency_set = DependencySet.new + + dependency_parser.parse.map do |dep| + if dep.top_level? + source = dep.requirements.first[:source] + + requirements = ManifestParser.new(package_manifest_file, source: source).requirements + + dependency_set << Dependency.new( + name: dep.name, + version: dep.version, + package_manager: dep.package_manager, + requirements: requirements + ) + else + dependency_set << dep + end + end + + dependency_set.dependencies + end + + private + + def dependency_parser + DependencyParser.new( + dependency_files: dependency_files, + repo_contents_path: repo_contents_path, + credentials: credentials + ) + end + + def check_required_files + raise "No Package.swift!" unless package_manifest_file + end + + def package_manifest_file + # TODO: Select version-specific manifest + @package_manifest_file ||= get_original_file("Package.swift") + end + end + end +end + +Dependabot::FileParsers. + register("swift", Dependabot::Swift::FileParser) diff --git a/swift/lib/dependabot/swift/file_parser/dependency_parser.rb b/swift/lib/dependabot/swift/file_parser/dependency_parser.rb new file mode 100644 index 00000000000..1dd6a28ccc8 --- /dev/null +++ b/swift/lib/dependabot/swift/file_parser/dependency_parser.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require "dependabot/file_parsers/base" +require "dependabot/shared_helpers" +require "dependabot/dependency" +require "json" + +module Dependabot + module Swift + class FileParser < Dependabot::FileParsers::Base + class DependencyParser + def initialize(dependency_files:, repo_contents_path:, credentials:) + @dependency_files = dependency_files + @repo_contents_path = repo_contents_path + @credentials = credentials + end + + def parse + SharedHelpers.in_a_temporary_repo_directory(dependency_files.first.directory, repo_contents_path) do + write_temporary_dependency_files + + SharedHelpers.with_git_configured(credentials: credentials) do + subdependencies(formatted_deps) + end + end + end + + private + + def write_temporary_dependency_files + dependency_files.each do |file| + File.write(file.name, file.content) + end + end + + def formatted_deps + deps = SharedHelpers.run_shell_command( + "swift package show-dependencies --format json", + stderr_to_stdout: false + ) + + JSON.parse(deps) + end + + def subdependencies(data, level: 0) + data["dependencies"].flat_map { |root| all_dependencies(root, level: level) } + end + + def all_dependencies(data, level: 0) + name = data["identity"] + url = data["url"] + version = data["version"] + + source = { type: "git", url: url, ref: version, branch: nil } + args = { name: name, version: version, package_manager: "swift", requirements: [] } + + if level.zero? + args[:requirements] << { requirement: nil, groups: ["dependencies"], file: nil, source: source } + else + args[:subdependency_metadata] = [{ source: source }] + end + + dep = Dependency.new(**args) if data["version"] != "unspecified" + + [dep, *subdependencies(data, level: level + 1)].compact + end + + attr_reader :dependency_files, :repo_contents_path, :credentials + end + end + end +end diff --git a/swift/lib/dependabot/swift/file_parser/manifest_parser.rb b/swift/lib/dependabot/swift/file_parser/manifest_parser.rb new file mode 100644 index 00000000000..b8703284d66 --- /dev/null +++ b/swift/lib/dependabot/swift/file_parser/manifest_parser.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require "dependabot/file_parsers/base" +require "dependabot/swift/native_requirement" + +module Dependabot + module Swift + class FileParser < Dependabot::FileParsers::Base + class ManifestParser + DEPENDENCY = /(?\.package\(\s*(?:name: "[^"]+",\s*)?url: "(?[^"]+)",\s*(?.*)\))/ + + def initialize(manifest, source:) + @manifest = manifest + @source = source + end + + def requirements + found = manifest.content.scan(DEPENDENCY).find do |_declaration, url, requirement| + # TODO: Support pinning to specific revisions + next if requirement.start_with?("branch:", ".branch(", "revision:", ".revision(") + + url == source[:url] + end + + return [] unless found + + declaration = found.first + requirement = NativeRequirement.new(found.last) + + [ + { + requirement: requirement.to_s, + groups: ["dependencies"], + file: manifest.name, + source: source, + metadata: { declaration_string: declaration, requirement_string: requirement.declaration } + } + ] + end + + private + + attr_reader :manifest, :source + end + end + end +end diff --git a/swift/lib/dependabot/swift/file_updater.rb b/swift/lib/dependabot/swift/file_updater.rb new file mode 100644 index 00000000000..6bdcdaea858 --- /dev/null +++ b/swift/lib/dependabot/swift/file_updater.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require "dependabot/file_updaters" +require "dependabot/file_updaters/base" +require "dependabot/swift/file_updater/lockfile_updater" +require "dependabot/swift/file_updater/manifest_updater" + +module Dependabot + module Swift + class FileUpdater < Dependabot::FileUpdaters::Base + def self.updated_files_regex + [ + /Package(@swift-\d(\.\d){0,2})?\.swift/, + /^Package\.resolved$/ + ] + end + + def updated_dependency_files + updated_files = [] + + SharedHelpers.in_a_temporary_repo_directory(manifest.directory, repo_contents_path) do + updated_manifest = nil + + if file_changed?(manifest) + updated_manifest = updated_file(file: manifest, content: updated_manifest_content) + updated_files << updated_manifest + end + + updated_files << updated_file(file: lockfile, content: updated_lockfile_content(updated_manifest)) if lockfile + end + + updated_files + end + + private + + def dependency + # For now we will be updating a single dependency. + # TODO: Revisit when/if implementing full unlocks + dependencies.first + end + + def check_required_files + raise "A Package.swift file must be provided!" unless manifest + end + + def updated_manifest_content + ManifestUpdater.new( + manifest.content, + old_requirements: dependency.previous_requirements, + new_requirements: dependency.requirements + ).updated_manifest_content + end + + def updated_lockfile_content(updated_manifest) + LockfileUpdater.new( + dependencies: dependencies, + manifest: updated_manifest || manifest, + repo_contents_path: repo_contents_path, + credentials: credentials + ).updated_lockfile_content + end + + def manifest + @manifest ||= get_original_file("Package.swift") + end + + def lockfile + return @lockfile if defined?(@lockfile) + + @lockfile = get_original_file("Package.resolved") + end + end + end +end + +Dependabot::FileUpdaters. + register("swift", Dependabot::Swift::FileUpdater) diff --git a/swift/lib/dependabot/swift/file_updater/lockfile_updater.rb b/swift/lib/dependabot/swift/file_updater/lockfile_updater.rb new file mode 100644 index 00000000000..b0f45f9c7c2 --- /dev/null +++ b/swift/lib/dependabot/swift/file_updater/lockfile_updater.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require "dependabot/file_updaters/base" +require "dependabot/shared_helpers" + +module Dependabot + module Swift + class FileUpdater < Dependabot::FileUpdaters::Base + class LockfileUpdater + def initialize(dependencies:, manifest:, repo_contents_path:, credentials:) + @dependencies = dependencies + @manifest = manifest + @repo_contents_path = repo_contents_path + @credentials = credentials + end + + def updated_lockfile_content + SharedHelpers.in_a_temporary_repo_directory(manifest.directory, repo_contents_path) do + File.write(manifest.name, manifest.content) + + SharedHelpers.with_git_configured(credentials: credentials) do + SharedHelpers.run_shell_command( + "swift package update #{dependencies.map(&:name).join(' ')}", + fingerprint: "swift package update " + ) + + File.read("Package.resolved") + end + end + end + + private + + attr_reader :dependencies, :manifest, :repo_contents_path, :credentials + end + end + end +end diff --git a/swift/lib/dependabot/swift/file_updater/manifest_updater.rb b/swift/lib/dependabot/swift/file_updater/manifest_updater.rb new file mode 100644 index 00000000000..5137550f5d1 --- /dev/null +++ b/swift/lib/dependabot/swift/file_updater/manifest_updater.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require "dependabot/file_updaters/base" +require "dependabot/swift/file_updater/requirement_replacer" + +module Dependabot + module Swift + class FileUpdater < FileUpdaters::Base + class ManifestUpdater + def initialize(content, old_requirements:, new_requirements:) + @content = content + @old_requirements = old_requirements + @new_requirements = new_requirements + end + + def updated_manifest_content + updated_content = content + + old_requirements.zip(new_requirements).each do |old, new| + updated_content = RequirementReplacer.new( + content: updated_content, + declaration: old[:metadata][:declaration_string], + old_requirement: old[:metadata][:requirement_string], + new_requirement: new[:metadata][:requirement_string] + ).updated_content + end + + updated_content + end + + private + + attr_reader :content, :old_requirements, :new_requirements + end + end + end +end diff --git a/swift/lib/dependabot/swift/file_updater/requirement_replacer.rb b/swift/lib/dependabot/swift/file_updater/requirement_replacer.rb new file mode 100644 index 00000000000..6f1311cfded --- /dev/null +++ b/swift/lib/dependabot/swift/file_updater/requirement_replacer.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require "dependabot/file_updaters/base" + +module Dependabot + module Swift + class FileUpdater < Dependabot::FileUpdaters::Base + class RequirementReplacer + def initialize(content:, declaration:, old_requirement:, new_requirement:) + @content = content + @declaration = declaration + @old_requirement = old_requirement + @new_requirement = new_requirement + end + + def updated_content + content.gsub(declaration) do |match| + match.to_s.sub(old_requirement, new_requirement) + end + end + + private + + attr_reader :content, :declaration, :old_requirement, :new_requirement + end + end + end +end diff --git a/swift/lib/dependabot/swift/metadata_finder.rb b/swift/lib/dependabot/swift/metadata_finder.rb new file mode 100644 index 00000000000..1c472e47b42 --- /dev/null +++ b/swift/lib/dependabot/swift/metadata_finder.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require "dependabot/metadata_finders" +require "dependabot/metadata_finders/base" + +module Dependabot + module Swift + class MetadataFinder < Dependabot::MetadataFinders::Base + private + + def look_up_source + case new_source_type + when "git" then find_source_from_git_url + when "registry" then find_source_from_registry + else raise "Unexpected source type: #{new_source_type}" + end + end + + def new_source_type + dependency.source_type + end + + def find_source_from_git_url + info = dependency.source_details + + url = info[:url] || info.fetch("url") + Source.from_url(url) + end + + def find_source_from_registry + raise NotImplementedError + end + end + end +end + +Dependabot::MetadataFinders. + register("swift", Dependabot::Swift::MetadataFinder) diff --git a/swift/lib/dependabot/swift/native_requirement.rb b/swift/lib/dependabot/swift/native_requirement.rb new file mode 100644 index 00000000000..211334b574b --- /dev/null +++ b/swift/lib/dependabot/swift/native_requirement.rb @@ -0,0 +1,159 @@ +# frozen_string_literal: true + +require "dependabot/utils" +require "dependabot/swift/requirement" + +module Dependabot + module Swift + class NativeRequirement + attr_reader :declaration + + def self.map_requirements(requirements) + requirements.map do |requirement| + declaration = new(requirement[:metadata][:requirement_string]) + + new_declaration = yield(declaration) + new_requirement = new(new_declaration) + + requirement.merge( + requirement: new_requirement.to_s, + metadata: { requirement_string: new_declaration } + ) + end + end + + def initialize(declaration) + @declaration = declaration + + min, max = parse_declaration(declaration) + + constraint = if min == max + ["= #{min}"] + elsif closed_range? + [">= #{min}", "<= #{max}"] + else + [">= #{min}", "< #{max}"] + end + + @min = min + @max = max + @requirement = Requirement.new(constraint) + end + + def to_s + requirement.to_s + end + + def update_if_needed(version) + return declaration if requirement.satisfied_by?(version) + + update(version) + end + + def update(version) + if single_version_declaration? + declaration.sub(min, version.to_s) + elsif closed_range? + declaration.sub(max, version.to_s) + elsif range? + declaration.sub(max, bump_major(version.to_s)) + end + end + + private + + def parse_declaration(declaration) + if up_to_next_major? + min = declaration.gsub(/\Afrom\s*:\s*"(\S+)"\s*\z/, '\1') + max = bump_major(min) + elsif up_to_next_major_deprecated? + min = declaration.gsub(/\A\.upToNextMajor\s*\(\s*from\s*:\s*"(\S+)"\s*\)\z/, '\1') + max = bump_major(min) + elsif up_to_next_minor_deprecated? + min = declaration.gsub(/\A\.upToNextMinor\s*\(\s*from\s*:\s*"(\S+)"\s*\)\z/, '\1') + max = bump_minor(min) + elsif closed_range? + min, max = parse_range("...") + elsif range? + min, max = parse_range("..<") + elsif exact_version? + min = declaration.gsub(/\Aexact\s*:\s*"(\S+)"\s*\z/, '\1') + max = min + elsif exact_version_deprecated? + min = declaration.gsub(/\A\.exact\s*\(\s*"(\S+)"\s*\)\z/, '\1') + max = min + else + raise "Unsupported constraint: #{declaration}" + end + + [min, max] + end + + def parse_range(separator) + declaration.split(separator).map { |str| unquote(str) } + end + + def single_version_declaration? + up_to_next_major? || up_to_next_major_deprecated? || up_to_next_minor? || + exact_version? || exact_version_deprecated? + end + + def bump_major(str) + transform_version(str) do |s, i| + i.zero? ? s.to_i + 1 : 0 + end + end + + def bump_minor(str) + transform_version(str) do |s, i| + if i.zero? + s + else + (i == 1 ? s.to_i + 1 : 0) + end + end + end + + def transform_version(str, &block) + str.split(".").map.with_index(&block).join(".") + end + + def up_to_next_major? + declaration.start_with?("from") + end + + def up_to_next_major_deprecated? + declaration.start_with?(".upToNextMajor") + end + + def up_to_next_minor_deprecated? + declaration.start_with?(".upToNextMinor") + end + + def exact_version? + declaration.start_with?("exact") + end + + def exact_version_deprecated? + declaration.start_with?(".exact") + end + + def closed_range? + declaration.include?("...") + end + + def range? + declaration.include?("..<") + end + + attr_reader :min, :max, :requirement + + def unquote(declaration) + declaration[1..-2] + end + end + end +end + +Dependabot::Utils. + register_requirement_class("swift", Dependabot::Swift::Requirement) diff --git a/swift/lib/dependabot/swift/requirement.rb b/swift/lib/dependabot/swift/requirement.rb new file mode 100644 index 00000000000..aa9e20c46d9 --- /dev/null +++ b/swift/lib/dependabot/swift/requirement.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require "dependabot/utils" + +module Dependabot + module Swift + class Requirement < Gem::Requirement + # For consistency with other languages, we define a requirements array. + # Swift doesn't have an `OR` separator for requirements, so it + # always contains a single element. + def self.requirements_array(requirement_string) + [new(requirement_string)] + end + + # Patches Gem::Requirement to make it accept requirement strings like + # "~> 4.2.5, >= 4.2.5.1" without first needing to split them. + def initialize(*requirements) + requirements = requirements.flatten.flat_map do |req_string| + req_string.split(",").map(&:strip) + end + + super(requirements) + end + end + end +end + +Dependabot::Utils. + register_requirement_class("swift", Dependabot::Swift::Requirement) diff --git a/swift/lib/dependabot/swift/update_checker.rb b/swift/lib/dependabot/swift/update_checker.rb new file mode 100644 index 00000000000..b3589f95442 --- /dev/null +++ b/swift/lib/dependabot/swift/update_checker.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true + +require "dependabot/update_checkers" +require "dependabot/update_checkers/base" +require "dependabot/git_commit_checker" +require "dependabot/swift/native_requirement" +require "dependabot/swift/file_updater/manifest_updater" + +module Dependabot + module Swift + class UpdateChecker < Dependabot::UpdateCheckers::Base + require_relative "update_checker/requirements_updater" + require_relative "update_checker/version_resolver" + + def latest_version + @latest_version ||= fetch_latest_version + end + + def latest_resolvable_version + @latest_resolvable_version ||= fetch_latest_resolvable_version + end + + def latest_resolvable_version_with_no_unlock + raise NotImplementedError + end + + def updated_requirements + RequirementsUpdater.new( + requirements: old_requirements, + target_version: preferred_resolvable_version + ).updated_requirements + end + + private + + def old_requirements + dependency.requirements + end + + def fetch_latest_version + return unless git_commit_checker.pinned_ref_looks_like_version? && latest_version_tag + + latest_version_tag.fetch(:version) + end + + def fetch_latest_resolvable_version + Version.new(version_resolver.latest_resolvable_version) + end + + def version_resolver + VersionResolver.new( + dependency: dependency, + manifest: prepared_manifest, + repo_contents_path: repo_contents_path, + credentials: credentials + ) + end + + def unlocked_requirements + NativeRequirement.map_requirements(old_requirements) do |_old_requirement| + "\"#{dependency.version}\"...\"#{latest_version}\"" + end + end + + def prepared_manifest + DependencyFile.new( + name: manifest.name, + content: FileUpdater::ManifestUpdater.new( + manifest.content, + old_requirements: old_requirements, + new_requirements: unlocked_requirements + ).updated_manifest_content + ) + end + + def manifest + dependency_files.find { |file| file.name == "Package.swift" } + end + + def latest_version_resolvable_with_full_unlock? + # Full unlock checks aren't implemented for Swift (yet) + false + end + + def updated_dependencies_after_full_unlock + raise NotImplementedError + end + + def git_commit_checker + @git_commit_checker ||= Dependabot::GitCommitChecker.new( + dependency: dependency, + credentials: credentials, + ignored_versions: ignored_versions, + raise_on_ignored: raise_on_ignored, + consider_version_branches_pinned: true + ) + end + + def latest_version_tag + git_commit_checker.local_tag_for_latest_version + end + end + end +end + +Dependabot::UpdateCheckers. + register("swift", Dependabot::Swift::UpdateChecker) diff --git a/swift/lib/dependabot/swift/update_checker/requirements_updater.rb b/swift/lib/dependabot/swift/update_checker/requirements_updater.rb new file mode 100644 index 00000000000..b0dac6ab44b --- /dev/null +++ b/swift/lib/dependabot/swift/update_checker/requirements_updater.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require "dependabot/update_checkers/base" +require "dependabot/swift/native_requirement" +require "dependabot/swift/version" + +module Dependabot + module Swift + class UpdateChecker < Dependabot::UpdateCheckers::Base + class RequirementsUpdater + def initialize(requirements:, target_version:) + @requirements = requirements + + return unless target_version && Version.correct?(target_version) + + @target_version = Version.new(target_version) + end + + def updated_requirements + NativeRequirement.map_requirements(requirements) do |requirement| + requirement.update_if_needed(target_version) + end + end + + private + + attr_reader :requirements, :target_version + end + end + end +end diff --git a/swift/lib/dependabot/swift/update_checker/version_resolver.rb b/swift/lib/dependabot/swift/update_checker/version_resolver.rb new file mode 100644 index 00000000000..7bde4018e0e --- /dev/null +++ b/swift/lib/dependabot/swift/update_checker/version_resolver.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require "dependabot/update_checkers/base" +require "dependabot/swift/file_parser/dependency_parser" +require "dependabot/swift/file_updater/lockfile_updater" + +module Dependabot + module Swift + class UpdateChecker < Dependabot::UpdateCheckers::Base + class VersionResolver + def initialize(dependency:, manifest:, repo_contents_path:, credentials:) + @dependency = dependency + @manifest = manifest + @credentials = credentials + @repo_contents_path = repo_contents_path + end + + def latest_resolvable_version + @latest_resolvable_version ||= fetch_latest_resolvable_version + end + + private + + def fetch_latest_resolvable_version + updated_lockfile_content = FileUpdater::LockfileUpdater.new( + dependencies: [dependency], + manifest: manifest, + repo_contents_path: repo_contents_path, + credentials: credentials + ).updated_lockfile_content + + lockfile = DependencyFile.new( + name: "Package.resolved", + content: updated_lockfile_content + ) + + dependency_parser(manifest, lockfile).parse.find do |parsed_dep| + parsed_dep.name == dependency.name + end.version + end + + def dependency_parser(manifest, lockfile) + FileParser::DependencyParser.new( + dependency_files: [manifest, lockfile], + repo_contents_path: repo_contents_path, + credentials: credentials + ) + end + + attr_reader :dependency, :manifest, :repo_contents_path, :credentials + end + end + end +end diff --git a/swift/lib/dependabot/swift/version.rb b/swift/lib/dependabot/swift/version.rb new file mode 100644 index 00000000000..c3ef4520587 --- /dev/null +++ b/swift/lib/dependabot/swift/version.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Dependabot + module Swift + class Version < Dependabot::Version + end + end +end + +Dependabot::Utils. + register_version_class("swift", Dependabot::Swift::Version) diff --git a/swift/script/ci-test b/swift/script/ci-test new file mode 100755 index 00000000000..8ba165bea47 --- /dev/null +++ b/swift/script/ci-test @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e + +bundle install +bundle exec parallel_test spec/ -n "$CI_NODE_TOTAL" --only-group "$CI_NODE_INDEX" --group-by filesize --type rspec diff --git a/swift/spec/dependabot/swift/file_fetcher_spec.rb b/swift/spec/dependabot/swift/file_fetcher_spec.rb new file mode 100644 index 00000000000..6aeecb35188 --- /dev/null +++ b/swift/spec/dependabot/swift/file_fetcher_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/swift/file_fetcher" +require_common_spec "file_fetchers/shared_examples_for_file_fetchers" + +RSpec.describe Dependabot::Swift::FileFetcher do + it_behaves_like "a dependency file fetcher" + + let(:source) do + Dependabot::Source.new( + provider: "github", + repo: "mona/swift-example", + directory: directory + ) + end + + let(:file_fetcher_instance) do + described_class.new(source: source, credentials: [], repo_contents_path: repo_contents_path) + end + + let(:repo_contents_path) { build_tmp_repo(project_name) } + + context "with Package.swift and Package.resolved" do + let(:project_name) { "standard" } + let(:directory) { "/" } + + it "fetches the manifest and resolved files" do + expect(file_fetcher_instance.files.map(&:name)). + to match_array(%w(Package.swift Package.resolved)) + end + end + + context "with Package.swift and Package.resolved" do + let(:project_name) { "manifest-only" } + let(:directory) { "/" } + + it "fetches the manifest and resolved files" do + expect(file_fetcher_instance.files.map(&:name)). + to match_array(%w(Package.swift)) + end + end + + context "with a directory that doesn't exist" do + let(:project_name) { "standard" } + let(:directory) { "/nonexistent" } + + it "raises a helpful error" do + expect { file_fetcher_instance.files }. + to raise_error(Dependabot::DependencyFileNotFound) + end + end +end diff --git a/swift/spec/dependabot/swift/file_parser_spec.rb b/swift/spec/dependabot/swift/file_parser_spec.rb new file mode 100644 index 00000000000..0299f5af2c3 --- /dev/null +++ b/swift/spec/dependabot/swift/file_parser_spec.rb @@ -0,0 +1,199 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/dependency_file" +require "dependabot/source" +require "dependabot/swift/file_parser" +require_common_spec "file_parsers/shared_examples_for_file_parsers" + +RSpec.describe Dependabot::Swift::FileParser do + it_behaves_like "a dependency file parser" + + let(:parser) do + described_class.new(dependency_files: files, source: source, repo_contents_path: repo_contents_path) + end + + let(:source) do + Dependabot::Source.new( + provider: "github", + repo: "mona/Example", + directory: "/" + ) + end + + let(:files) do + [ + package_manifest_file, + package_resolved_file + ] + end + + let(:repo_contents_path) { build_tmp_repo(project_name, path: "projects") } + + let(:package_manifest_file) do + Dependabot::DependencyFile.new( + name: "Package.swift", + content: fixture("projects", project_name, "Package.swift") + ) + end + + let(:package_resolved_file) do + Dependabot::DependencyFile.new( + name: "Package.resolved", + content: fixture("projects", project_name, "Package.resolved") + ) + end + + let(:dependencies) { parser.parse } + + shared_examples_for "parse" do + it "parses dependencies fine" do + expectations.each.with_index do |expected, index| + url = expected[:url] + version = expected[:version] + name = expected[:name] + source = { type: "git", url: url, ref: version, branch: nil } + + dependency = dependencies[index] + + expect(dependency).to be_a(Dependabot::Dependency) + expect(dependency.name).to eq(name) + expect(dependency.version).to eq(version) + + if expected[:requirement] + expect(dependency.requirements).to eq([ + { + requirement: expected[:requirement], + groups: ["dependencies"], + file: "Package.swift", + source: source, + metadata: { + declaration_string: expected[:declaration_string], + requirement_string: expected[:requirement_string] + } + } + ]) + else # subdependency + expect(dependency.subdependency_metadata).to eq([ + { + source: source + } + ]) + end + end + end + end + + context "with supported declarations" do + let(:project_name) { "Example" } + + let(:expectations) do + [ + { + name: "reactiveswift", + url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", + version: "7.1.0", + requirement: "= 7.1.0", + declaration_string: + ".package(url: \"https://github.com/ReactiveCocoa/ReactiveSwift.git\",\n exact: \"7.1.0\")", + requirement_string: "exact: \"7.1.0\"" + }, + { + name: "swift-docc-plugin", + url: "https://github.com/apple/swift-docc-plugin", + version: "1.0.0", + requirement: ">= 1.0.0, < 2.0.0", + declaration_string: + ".package(\n url: \"https://github.com/apple/swift-docc-plugin\",\n from: \"1.0.0\")", + requirement_string: "from: \"1.0.0\"" + }, + { + name: "swift-benchmark", + url: "https://github.com/google/swift-benchmark", + version: "0.1.1", + requirement: ">= 0.1.0, < 0.1.2", + declaration_string: ".package(url: \"https://github.com/google/swift-benchmark\", \"0.1.0\"..<\"0.1.2\")", + requirement_string: "\"0.1.0\"..<\"0.1.2\"" + }, + { + name: "swift-argument-parser", + url: "https://github.com/apple/swift-argument-parser", + version: "0.5.0" + }, + { + name: "combine-schedulers", + url: "https://github.com/pointfreeco/combine-schedulers", + version: "0.10.0", + requirement: ">= 0.9.2, <= 0.10.0", + declaration_string: + ".package(url: \"https://github.com/pointfreeco/combine-schedulers\", \"0.9.2\"...\"0.10.0\")", + requirement_string: "\"0.9.2\"...\"0.10.0\"" + }, + { + name: "xctest-dynamic-overlay", + url: "https://github.com/pointfreeco/xctest-dynamic-overlay", + version: "0.8.5" + } + ] + end + + it_behaves_like "parse" + end + + context "with deprecated declarations" do + let(:project_name) { "Example-Deprecated" } + + let(:expectations) do + [ + { + name: "quick", + url: "https://github.com/Quick/Quick.git", + version: "7.0.2", + requirement: ">= 7.0.0, < 8.0.0", + declaration_string: + ".package(url: \"https://github.com/Quick/Quick.git\",\n .upToNextMajor(from: \"7.0.0\"))", + requirement_string: ".upToNextMajor(from: \"7.0.0\")" + }, + { + name: "nimble", + url: "https://github.com/Quick/Nimble.git", + version: "9.0.1", + requirement: ">= 9.0.0, < 9.1.0", + declaration_string: + ".package(url: \"https://github.com/Quick/Nimble.git\",\n .upToNextMinor(from: \"9.0.0\"))", + requirement_string: ".upToNextMinor(from: \"9.0.0\")" + }, + { + name: "swift-docc-plugin", + url: "https://github.com/apple/swift-docc-plugin", + version: "1.0.0", + requirement: "= 1.0.0", + declaration_string: + ".package(\n url: \"https://github.com/apple/swift-docc-plugin\",\n .exact(\"1.0.0\"))", + requirement_string: ".exact(\"1.0.0\")" + }, + { + name: "swift-benchmark", + url: "https://github.com/google/swift-benchmark", + version: "0.1.1", + requirement: ">= 0.1.0, < 0.1.2", + declaration_string: + ".package(name: \"foo\", url: \"https://github.com/google/swift-benchmark\", \"0.1.0\"..<\"0.1.2\")", + requirement_string: "\"0.1.0\"..<\"0.1.2\"" + }, + { + name: "swift-argument-parser", + url: "https://github.com/apple/swift-argument-parser", + version: "0.5.0" + }, + { + name: "xctest-dynamic-overlay", + url: "https://github.com/pointfreeco/xctest-dynamic-overlay", + version: "0.8.5" + } + ] + end + + it_behaves_like "parse" + end +end diff --git a/swift/spec/dependabot/swift/file_updater_spec.rb b/swift/spec/dependabot/swift/file_updater_spec.rb new file mode 100644 index 00000000000..5c55b6d9b2f --- /dev/null +++ b/swift/spec/dependabot/swift/file_updater_spec.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/dependency" +require "dependabot/dependency_file" +require "dependabot/swift/file_updater" +require_common_spec "file_updaters/shared_examples_for_file_updaters" + +RSpec.describe Dependabot::Swift::FileUpdater do + it_behaves_like "a dependency file updater" + + subject(:updater) do + described_class.new( + dependency_files: files, + dependencies: dependencies, + credentials: credentials, + repo_contents_path: repo_contents_path + ) + end + + let(:project_name) { "Example" } + let(:repo_contents_path) { build_tmp_repo(project_name) } + + let(:files) { project_dependency_files(project_name) } + let(:dependencies) { [] } + let(:credentials) do + [{ "type" => "git_source", "host" => "github.com", "username" => "x-access-token", "password" => "token" }] + end + + describe "#updated_dependency_files" do + subject { updater.updated_dependency_files } + + let(:dependencies) do + [ + Dependabot::Dependency.new( + name: "reactiveswift", + version: "7.1.1", + previous_version: "7.1.0", + requirements: [{ + requirement: "= 7.1.1", + groups: [], + file: "Package.swift", + source: { + type: "git", + url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", + ref: "7.1.0", + branch: nil + }, + metadata: { + requirement_string: "exact: \"7.1.1\"" + } + }], + previous_requirements: [{ + requirement: "= 7.1.0", + groups: [], + file: "Package.swift", + source: { + type: "git", + url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", + ref: "7.1.0", + branch: nil + }, + metadata: { + declaration_string: + ".package(url: \"https://github.com/ReactiveCocoa/ReactiveSwift.git\",\n exact: \"7.1.0\")", + requirement_string: "exact: \"7.1.0\"" + } + }], + package_manager: "swift" + ) + ] + end + + it "updates the version in manifest and lockfile" do + manifest = subject.find { |file| file.name == "Package.swift" } + + expect(manifest.content).to include( + ".package(url: \"https://github.com/ReactiveCocoa/ReactiveSwift.git\",\n exact: \"7.1.1\")" + ) + + lockfile = subject.find { |file| file.name == "Package.resolved" } + + expect(lockfile.content.gsub(/^ {4}/, "")).to include <<~RESOLVED + { + "identity" : "reactiveswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ReactiveCocoa/ReactiveSwift.git", + "state" : { + "revision" : "40c465af19b993344e84355c00669ba2022ca3cd", + "version" : "7.1.1" + } + }, + RESOLVED + end + end +end diff --git a/swift/spec/dependabot/swift/metadata_finder_spec.rb b/swift/spec/dependabot/swift/metadata_finder_spec.rb new file mode 100644 index 00000000000..12f9abacd4e --- /dev/null +++ b/swift/spec/dependabot/swift/metadata_finder_spec.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/dependency" +require "dependabot/swift/metadata_finder" +require_common_spec "metadata_finders/shared_examples_for_metadata_finders" + +RSpec.describe Dependabot::Swift::MetadataFinder do + it_behaves_like "a dependency metadata finder" + + let(:credentials) do + [{ + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + }] + end + + let(:finder) do + described_class.new(dependency: dependency, credentials: credentials) + end + + describe "#source_url" do + context "with a direct dependency" do + let(:dependency) do + Dependabot::Dependency.new( + name: "reactiveswift", + version: "7.1.1", + requirements: [{ + file: "package.swfit", + requirement: "= 7.1.1", + groups: [], + source: { + "type" => "git", + "url" => "https://github.com/reactivecocoa/reactiveswift", + "ref" => "7.1.1", + "branch" => nil + } + }], + package_manager: "swift" + ) + end + + it "works" do + expect(finder.source_url).to eq "https://github.com/reactivecocoa/reactiveswift" + end + end + + context "with an indirect dependency" do + let(:dependency) do + Dependabot::Dependency.new( + name: "reactiveswift", + version: "7.1.1", + requirements: [], + subdependency_metadata: [ + { + source: { + "type" => "git", + "url" => "https://github.com/reactivecocoa/reactiveswift", + "ref" => "7.1.1", + "branch" => nil + } + } + ], + package_manager: "swift" + ) + end + + it "works" do + expect(finder.source_url).to eq "https://github.com/reactivecocoa/reactiveswift" + end + end + end +end diff --git a/swift/spec/dependabot/swift/native_requirement_spec.rb b/swift/spec/dependabot/swift/native_requirement_spec.rb new file mode 100644 index 00000000000..744ef3da85b --- /dev/null +++ b/swift/spec/dependabot/swift/native_requirement_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/swift/native_requirement" + +RSpec.describe Dependabot::Swift::NativeRequirement do + RSpec::Matchers.define :parse_as do |requirement| + match do |declaration| + described_class.new(declaration).to_s == requirement + end + end + + describe ".new" do + it "parses different ways of declaring requirements" do + expect('from: "1.0.0"').to parse_as(">= 1.0.0, < 2.0.0") + expect('from : "1.0.0"').to parse_as(">= 1.0.0, < 2.0.0") + + expect('exact: "1.0.0"').to parse_as("= 1.0.0") + expect('exact : "1.0.0"').to parse_as("= 1.0.0") + + expect('.upToNextMajor(from: "1.0.0")').to parse_as(">= 1.0.0, < 2.0.0") + expect('.upToNextMajor (from: "1.0.0")').to parse_as(">= 1.0.0, < 2.0.0") + expect('.upToNextMajor( from: "1.0.0" )').to parse_as(">= 1.0.0, < 2.0.0") + expect('.upToNextMajor (from : "1.0.0")').to parse_as(">= 1.0.0, < 2.0.0") + + expect('.upToNextMinor(from: "1.0.0")').to parse_as(">= 1.0.0, < 1.1.0") + expect('.upToNextMinor (from: "1.0.0")').to parse_as(">= 1.0.0, < 1.1.0") + expect('.upToNextMinor( from: "1.0.0" )').to parse_as(">= 1.0.0, < 1.1.0") + expect('.upToNextMinor (from : "1.0.0")').to parse_as(">= 1.0.0, < 1.1.0") + + expect('.exact("1.0.0")').to parse_as("= 1.0.0") + expect('.exact ("1.0.0")').to parse_as("= 1.0.0") + expect('.exact( "1.0.0" )').to parse_as("= 1.0.0") + + expect('"1.0.0"..<"2.0.0"').to parse_as(">= 1.0.0, < 2.0.0") + expect('"1.0.0"..."2.0.0"').to parse_as(">= 1.0.0, <= 2.0.0") + end + end +end diff --git a/swift/spec/dependabot/swift/update_checker_spec.rb b/swift/spec/dependabot/swift/update_checker_spec.rb new file mode 100644 index 00000000000..74e9aef5233 --- /dev/null +++ b/swift/spec/dependabot/swift/update_checker_spec.rb @@ -0,0 +1,132 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/dependency" +require "dependabot/swift/file_parser" +require "dependabot/swift/update_checker" +require_common_spec "update_checkers/shared_examples_for_update_checkers" + +RSpec.describe Dependabot::Swift::UpdateChecker do + it_behaves_like "an update checker" + + let(:checker) do + described_class.new( + dependency: dependency, + dependency_files: dependency_files, + repo_contents_path: repo_contents_path, + credentials: github_credentials, + security_advisories: security_advisories, + ignored_versions: ignored_versions, + raise_on_ignored: raise_on_ignored + ) + end + let(:project_name) { "ReactiveCocoa" } + let(:repo_contents_path) { build_tmp_repo(project_name, path: "projects") } + let(:dependency_files) { project_dependency_files(project_name) } + let(:security_advisories) { [] } + let(:ignored_versions) { [] } + let(:raise_on_ignored) { false } + + let(:dependencies) do + file_parser.parse + end + + let(:file_parser) do + Dependabot::Swift::FileParser.new( + dependency_files: dependency_files, + repo_contents_path: repo_contents_path, + source: nil + ) + end + + let(:dependency) { dependencies.find { |dep| dep.name == name } } + + let(:stub_upload_pack) do + stub_request(:get, "#{url}.git/info/refs?service=git-upload-pack"). + to_return( + status: 200, + body: fixture("git", "upload_packs", upload_pack_fixture), + headers: { + "content-type" => "application/x-git-upload-pack-advertisement" + } + ) + end + + context "with an up to date dependency" do + let(:name) { "reactiveswift" } + let(:url) { "https://github.com/ReactiveCocoa/ReactiveSwift" } + let(:upload_pack_fixture) { "reactive-swift" } + + before { stub_upload_pack } + + describe "#can_update?" do + subject { checker.can_update?(requirements_to_unlock: :own) } + + it { is_expected.to be_falsey } + end + + describe "#latest_version" do + subject { checker.latest_version } + + it { is_expected.to eq(dependency.version) } + end + + describe "#latest_resolvable_version" do + subject { checker.latest_resolvable_version } + + it { is_expected.to eq(dependency.version) } + end + end + + context "with a dependency that needs only lockfile changes to get updated" do + let(:name) { "quick" } + let(:url) { "https://github.com/Quick/Quick" } + let(:upload_pack_fixture) { "quick" } + + before { stub_upload_pack } + + describe "#can_update?" do + subject { checker.can_update?(requirements_to_unlock: :own) } + + it { is_expected.to be_truthy } + end + + describe "#latest_version" do + subject { checker.latest_version } + + it { is_expected.to eq("7.0.2") } + end + + describe "#latest_resolvable_version" do + subject { checker.latest_resolvable_version } + + it { is_expected.to eq("7.0.2") } + end + end + + context "with a dependency that needs manifest changes to get updated" do + let(:name) { "nimble" } + let(:url) { "https://github.com/Quick/Nimble" } + let(:upload_pack_fixture) { "nimble" } + + before { stub_upload_pack } + + describe "#can_update?" do + subject { checker.can_update?(requirements_to_unlock: :own) } + + it { is_expected.to be_truthy } + end + + describe "#latest_version" do + subject { checker.latest_version } + + it { is_expected.to eq("12.0.1") } + end + + describe "#latest_resolvable_version" do + subject { checker.latest_resolvable_version } + + it { is_expected.to eq("12.0.1") } + end + end +end diff --git a/swift/spec/dependabot/swift_spec.rb b/swift/spec/dependabot/swift_spec.rb new file mode 100644 index 00000000000..76b6458a32d --- /dev/null +++ b/swift/spec/dependabot/swift_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/swift" +require_common_spec "shared_examples_for_autoloading" + +RSpec.describe Dependabot::Swift do + it_behaves_like "it registers the required classes", "swift" +end diff --git a/swift/spec/fixtures/git/upload_packs/nimble b/swift/spec/fixtures/git/upload_packs/nimble new file mode 100644 index 00000000000..822a0352e8f Binary files /dev/null and b/swift/spec/fixtures/git/upload_packs/nimble differ diff --git a/swift/spec/fixtures/git/upload_packs/quick b/swift/spec/fixtures/git/upload_packs/quick new file mode 100644 index 00000000000..1ae83992851 Binary files /dev/null and b/swift/spec/fixtures/git/upload_packs/quick differ diff --git a/swift/spec/fixtures/git/upload_packs/reactive-swift b/swift/spec/fixtures/git/upload_packs/reactive-swift new file mode 100644 index 00000000000..770a82ca3f5 Binary files /dev/null and b/swift/spec/fixtures/git/upload_packs/reactive-swift differ diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Nimble/Package.resolved b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Nimble/Package.resolved new file mode 100644 index 00000000000..e79774ff50e --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Nimble/Package.resolved @@ -0,0 +1,25 @@ +{ + "object": { + "pins": [ + { + "package": "CwlCatchException", + "repositoryURL": "https://github.com/mattgallagher/CwlCatchException.git", + "state": { + "branch": null, + "revision": "f809deb30dc5c9d9b78c872e553261a61177721a", + "version": "2.0.0" + } + }, + { + "package": "CwlPreconditionTesting", + "repositoryURL": "https://github.com/mattgallagher/CwlPreconditionTesting.git", + "state": { + "branch": null, + "revision": "02b7a39a99c4da27abe03cab2053a9034379639f", + "version": "2.0.0" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Nimble/Package.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Nimble/Package.swift new file mode 100644 index 00000000000..105cc93fd9e --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Nimble/Package.swift @@ -0,0 +1,21 @@ +// swift-tools-version:5.2 +import PackageDescription + +let package = Package( + name: "Nimble", + platforms: [ + .macOS(.v10_10), .iOS(.v9), .tvOS(.v9) + ], + products: [ + .library(name: "Nimble", targets: ["Nimble"]), + ], + dependencies: [ + .package(url: "https://github.com/mattgallagher/CwlPreconditionTesting.git", .upToNextMajor(from: "2.0.0")), + ], + targets: [ + .target( + name: "Nimble" + ) + ], + swiftLanguageVersions: [.v5] +) diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Nimble/Sources/Nimble/DSL.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Nimble/Sources/Nimble/DSL.swift new file mode 100644 index 00000000000..3ea5f9e7517 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Nimble/Sources/Nimble/DSL.swift @@ -0,0 +1 @@ +/// Placeholder diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Quick/Package.resolved b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Quick/Package.resolved new file mode 100644 index 00000000000..7178b7aa1b5 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Quick/Package.resolved @@ -0,0 +1,32 @@ +{ + "pins" : [ + { + "identity" : "cwlcatchexception", + "kind" : "remoteSourceControl", + "location" : "https://github.com/mattgallagher/CwlCatchException.git", + "state" : { + "revision" : "f809deb30dc5c9d9b78c872e553261a61177721a", + "version" : "2.0.0" + } + }, + { + "identity" : "cwlpreconditiontesting", + "kind" : "remoteSourceControl", + "location" : "https://github.com/mattgallagher/CwlPreconditionTesting.git", + "state" : { + "revision" : "c21f7bab5ca8eee0a9998bbd17ca1d0eb45d4688", + "version" : "2.1.0" + } + }, + { + "identity" : "nimble", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Quick/Nimble.git", + "state" : { + "revision" : "ecade0f20e58e55ba3e5f110b701dad88fd40170", + "version" : "12.0.0" + } + } + ], + "version" : 2 +} diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Quick/Package.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Quick/Package.swift new file mode 100644 index 00000000000..d18103cc558 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Quick/Package.swift @@ -0,0 +1,64 @@ +// swift-tools-version:5.7 + +import PackageDescription + +let package = Package( + name: "Quick", + platforms: [ + .macOS(.v10_15), .iOS(.v13), .tvOS(.v13) + ], + products: [ + .library(name: "Quick", targets: ["Quick"]), + ], + dependencies: [ + .package(url: "https://github.com/Quick/Nimble.git", from: "12.0.0"), + ], + targets: { + var targets: [Target] = [ + .testTarget( + name: "QuickTests", + dependencies: [ "Quick", "Nimble" ], + exclude: [ + "QuickAfterSuiteTests/AfterSuiteTests+ObjC.m", + "QuickFocusedTests/FocusedTests+ObjC.m", + "QuickTests/FunctionalTests/ObjC", + "QuickTests/Helpers/QCKSpecRunner.h", + "QuickTests/Helpers/QCKSpecRunner.m", + "QuickTests/Helpers/QuickTestsBridgingHeader.h", + "QuickTests/QuickConfigurationTests.m", + "QuickFocusedTests/Info.plist", + "QuickTests/Info.plist", + "QuickAfterSuiteTests/Info.plist", + ] + ), + .testTarget( + name: "QuickIssue853RegressionTests", + dependencies: [ "Quick" ] + ), + ] +#if os(macOS) + targets.append(contentsOf: [ + .target(name: "QuickObjCRuntime", dependencies: []), + .target( + name: "Quick", + dependencies: [ "QuickObjCRuntime" ], + exclude: [ + "Info.plist", + ] + ), + ]) +#else + targets.append(contentsOf: [ + .target( + name: "Quick", + dependencies: [], + exclude: [ + "Info.plist" + ] + ), + ]) +#endif + return targets + }(), + swiftLanguageVersions: [.v5] +) diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Quick/Sources/Quick/QuickMain.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Quick/Sources/Quick/QuickMain.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/Quick/Sources/Quick/QuickMain.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-argument-parser/Package.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-argument-parser/Package.swift new file mode 100644 index 00000000000..e1b21874cb1 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-argument-parser/Package.swift @@ -0,0 +1,70 @@ +// swift-tools-version:5.2 +//===----------------------------------------------------------*- swift -*-===// +// +// This source file is part of the Swift Argument Parser open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import PackageDescription + +var package = Package( + name: "swift-argument-parser", + products: [ + .library( + name: "ArgumentParser", + targets: ["ArgumentParser"]), + ], + dependencies: [], + targets: [ + .target( + name: "ArgumentParser", + dependencies: ["ArgumentParserToolInfo"]), + .target( + name: "ArgumentParserTestHelpers", + dependencies: ["ArgumentParser", "ArgumentParserToolInfo"]), + .target( + name: "ArgumentParserToolInfo", + dependencies: []), + + .target( + name: "roll", + dependencies: ["ArgumentParser"], + path: "Examples/roll"), + .target( + name: "math", + dependencies: ["ArgumentParser"], + path: "Examples/math"), + .target( + name: "repeat", + dependencies: ["ArgumentParser"], + path: "Examples/repeat"), + + .target( + name: "changelog-authors", + dependencies: ["ArgumentParser"], + path: "Tools/changelog-authors"), + + .testTarget( + name: "ArgumentParserEndToEndTests", + dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"]), + .testTarget( + name: "ArgumentParserUnitTests", + dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"]), + .testTarget( + name: "ArgumentParserExampleTests", + dependencies: ["ArgumentParserTestHelpers"]), + ] +) + +#if swift(>=5.2) +// Skip if < 5.2 to avoid issue with nested type synthesized 'CodingKeys' +package.targets.append( + .testTarget( + name: "ArgumentParserPackageManagerTests", + dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"])) +#endif diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-argument-parser/Sources/ArgumentParser/Parsing/Name.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-argument-parser/Sources/ArgumentParser/Parsing/Name.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-argument-parser/Sources/ArgumentParser/Parsing/Name.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-argument-parser/Sources/ArgumentParserToolInfo/ToolInfo.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-argument-parser/Sources/ArgumentParserToolInfo/ToolInfo.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-argument-parser/Sources/ArgumentParserToolInfo/ToolInfo.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-benchmark/Package.resolved b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-benchmark/Package.resolved new file mode 100644 index 00000000000..4520bbb27f0 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-benchmark/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "swift-argument-parser", + "repositoryURL": "https://github.com/apple/swift-argument-parser", + "state": { + "branch": null, + "revision": "6b2aa2748a7881eebb9f84fb10c01293e15b52ca", + "version": "0.5.0" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-benchmark/Package.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-benchmark/Package.swift new file mode 100644 index 00000000000..fa8bd50e5de --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-benchmark/Package.swift @@ -0,0 +1,46 @@ +// swift-tools-version:5.1 + +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import PackageDescription + +let package = Package( + name: "Benchmark", + products: [ + .library( + name: "Benchmark", + targets: ["Benchmark"]) + ], + dependencies: [ + .package(url: "https://github.com/apple/swift-argument-parser", from: "0.5.0"), + ], + targets: [ + .target( + name: "Benchmark", + dependencies: [.product(name: "ArgumentParser", package: "swift-argument-parser")]), + .target( + name: "BenchmarkMinimalExample", + dependencies: ["Benchmark"]), + .target( + name: "BenchmarkSuiteExample", + dependencies: ["Benchmark"]), + .target( + name: "BenchmarkSuiteExampleMain", + dependencies: ["Benchmark", "BenchmarkSuiteExample"]), + .testTarget( + name: "BenchmarkTests", + dependencies: ["Benchmark", "BenchmarkSuiteExample"]), + ] +) diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-benchmark/Sources/Benchmark/Benchmark.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-benchmark/Sources/Benchmark/Benchmark.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-benchmark/Sources/Benchmark/Benchmark.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Package.resolved b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Package.resolved new file mode 100644 index 00000000000..6a606789d35 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Package.resolved @@ -0,0 +1,43 @@ +{ + "object": { + "pins": [ + { + "package": "swift-argument-parser", + "repositoryURL": "https://github.com/apple/swift-argument-parser", + "state": { + "branch": null, + "revision": "986d191f94cec88f6350056da59c2e59e83d1229", + "version": "0.4.3" + } + }, + { + "package": "Benchmark", + "repositoryURL": "https://github.com/google/swift-benchmark", + "state": { + "branch": null, + "revision": "8e0ef8bb7482ab97dcd2cd1d6855bd38921c345d", + "version": "0.1.0" + } + }, + { + "package": "SwiftDocCPlugin", + "repositoryURL": "https://github.com/apple/swift-docc-plugin", + "state": { + "branch": null, + "revision": "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "version": "1.0.0" + } + }, + { + "package": "xctest-dynamic-overlay", + "repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay.git", + "state": { + "branch": null, + "revision": "a9daebf0bf65981fd159c885d504481a65a75f02", + "version": "0.8.0" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Package.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Package.swift new file mode 100644 index 00000000000..5c0a7fecf90 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Package.swift @@ -0,0 +1,49 @@ +// swift-tools-version:5.5 + +import PackageDescription + +let package = Package( + name: "swift-case-paths", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .tvOS(.v13), + .watchOS(.v6), + ], + products: [ + .library( + name: "CasePaths", + targets: ["CasePaths"] + ) + ], + dependencies: [ + .package(name: "Benchmark", url: "https://github.com/google/swift-benchmark", from: "0.1.0"), + .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.8.0"), + ], + targets: [ + .target( + name: "CasePaths", + dependencies: [ + .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay") + ] + ), + .testTarget( + name: "CasePathsTests", + dependencies: ["CasePaths"] + ), + .executableTarget( + name: "swift-case-paths-benchmark", + dependencies: [ + "CasePaths", + .product(name: "Benchmark", package: "Benchmark"), + ] + ), + ] +) + +#if swift(>=5.6) + // Add the documentation compiler plugin if possible + package.dependencies.append( + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") + ) +#endif diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Package@swift-5.1.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Package@swift-5.1.swift new file mode 100644 index 00000000000..996ce04f8c4 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Package@swift-5.1.swift @@ -0,0 +1,22 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "swift-case-paths", + products: [ + .library( + name: "CasePaths", + targets: ["CasePaths"] + ) + ], + targets: [ + .target( + name: "CasePaths" + ), + .testTarget( + name: "CasePathsTests", + dependencies: ["CasePaths"] + ), + ] +) diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Sources/CasePaths/CasePaths.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Sources/CasePaths/CasePaths.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-case-paths/Sources/CasePaths/CasePaths.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-custom-dump/Package.resolved b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-custom-dump/Package.resolved new file mode 100644 index 00000000000..76b883171b2 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-custom-dump/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "xctest-dynamic-overlay", + "repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state": { + "branch": null, + "revision": "30314f1ece684dd60679d598a9b89107557b67d9", + "version": "0.4.1" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-custom-dump/Package.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-custom-dump/Package.swift new file mode 100644 index 00000000000..b1aa1b2555d --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-custom-dump/Package.swift @@ -0,0 +1,36 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "swift-custom-dump", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .tvOS(.v13), + .watchOS(.v6), + ], + products: [ + .library( + name: "CustomDump", + targets: ["CustomDump"] + ) + ], + dependencies: [ + .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.2.0") + ], + targets: [ + .target( + name: "CustomDump", + dependencies: [ + .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay") + ] + ), + .testTarget( + name: "CustomDumpTests", + dependencies: [ + "CustomDump" + ] + ), + ] +) diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-custom-dump/Sources/CustomDump/Dump.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-custom-dump/Sources/CustomDump/Dump.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-custom-dump/Sources/CustomDump/Dump.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-docc-plugin/Package.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-docc-plugin/Package.swift new file mode 100644 index 00000000000..551d02074d9 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-docc-plugin/Package.swift @@ -0,0 +1,21 @@ +// swift-tools-version:5.6 +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for Swift project authors + +import PackageDescription + +let package = Package( + name: "SwiftDocCPlugin", + platforms: [ + .macOS("10.15.4"), + ], + targets: [ + .target(name: "SwiftDocCPluginUtilities") + ] +) diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-docc-plugin/Sources/SwiftDocCPluginUtilities/HelpInformation.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-docc-plugin/Sources/SwiftDocCPluginUtilities/HelpInformation.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/swift-docc-plugin/Sources/SwiftDocCPluginUtilities/HelpInformation.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/xctest-dynamic-overlay/Package.resolved b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/xctest-dynamic-overlay/Package.resolved new file mode 100644 index 00000000000..3b6d58b80c8 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/xctest-dynamic-overlay/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "SwiftDocCPlugin", + "repositoryURL": "https://github.com/apple/swift-docc-plugin", + "state": { + "branch": null, + "revision": "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "version": "1.0.0" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/xctest-dynamic-overlay/Package.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/xctest-dynamic-overlay/Package.swift new file mode 100644 index 00000000000..33a9349d2f6 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/xctest-dynamic-overlay/Package.swift @@ -0,0 +1,30 @@ +// swift-tools-version:5.5 + +import PackageDescription + +let package = Package( + name: "xctest-dynamic-overlay", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .tvOS(.v13), + .watchOS(.v6), + ], + products: [ + .library(name: "XCTestDynamicOverlay", targets: ["XCTestDynamicOverlay"]) + ], + targets: [ + .target(name: "XCTestDynamicOverlay"), + .testTarget( + name: "XCTestDynamicOverlayTests", + dependencies: ["XCTestDynamicOverlay"] + ), + ] +) + +#if swift(>=5.6) + // Add the documentation compiler plugin if possible + package.dependencies.append( + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") + ) +#endif diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/xctest-dynamic-overlay/Sources/XCTestDynamicOverlay/XCTFail.swift b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/xctest-dynamic-overlay/Sources/XCTestDynamicOverlay/XCTFail.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/checkouts/xctest-dynamic-overlay/Sources/XCTestDynamicOverlay/XCTFail.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example-Deprecated/.build/workspace-state.json b/swift/spec/fixtures/projects/Example-Deprecated/.build/workspace-state.json new file mode 100644 index 00000000000..b1f7de0beee --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/.build/workspace-state.json @@ -0,0 +1,145 @@ +{ + "object" : { + "artifacts" : [ + + ], + "dependencies" : [ + { + "basedOn" : null, + "packageRef" : { + "identity" : "nimble", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Quick/Nimble.git", + "name" : "Nimble" + }, + "state" : { + "checkoutState" : { + "revision" : "7a54aaf19a8ef16f67787c260fda81ead7ba4d67", + "version" : "9.0.1" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "Nimble" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "quick", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Quick/Quick.git", + "name" : "Quick" + }, + "state" : { + "checkoutState" : { + "revision" : "91132c0fe9a98e76f3d7381a608685aa41770706", + "version" : "7.0.2" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "Quick" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser", + "name" : "swift-argument-parser" + }, + "state" : { + "checkoutState" : { + "revision" : "6b2aa2748a7881eebb9f84fb10c01293e15b52ca", + "version" : "0.5.0" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-argument-parser" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-benchmark", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/swift-benchmark", + "name" : "Benchmark" + }, + "state" : { + "checkoutState" : { + "revision" : "a0564bf88df5f94eec81348a2f089494c6b28d80", + "version" : "0.1.1" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-benchmark" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-case-paths", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-case-paths", + "name" : "swift-case-paths" + }, + "state" : { + "checkoutState" : { + "branch" : "main", + "revision" : "fc45e7b2cfece9dd80b5a45e6469ffe67fe67984" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-case-paths" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-custom-dump", + "kind" : "remoteSourceControl", + "location" : "https://github.com:443/pointfreeco/swift-custom-dump", + "name" : "swift-custom-dump" + }, + "state" : { + "checkoutState" : { + "revision" : "3a35f7892e7cf6ba28a78cd46a703c0be4e0c6dc" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-custom-dump" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-plugin", + "name" : "SwiftDocCPlugin" + }, + "state" : { + "checkoutState" : { + "revision" : "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "version" : "1.0.0" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-docc-plugin" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "name" : "xctest-dynamic-overlay" + }, + "state" : { + "checkoutState" : { + "revision" : "4af50b38daf0037cfbab15514a241224c3f62f98", + "version" : "0.8.5" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "xctest-dynamic-overlay" + } + ] + }, + "version" : 6 +} \ No newline at end of file diff --git a/swift/spec/fixtures/projects/Example-Deprecated/Package.resolved b/swift/spec/fixtures/projects/Example-Deprecated/Package.resolved new file mode 100644 index 00000000000..ae7a888e973 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/Package.resolved @@ -0,0 +1,76 @@ +{ + "pins" : [ + { + "identity" : "nimble", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Quick/Nimble.git", + "state" : { + "revision" : "7a54aaf19a8ef16f67787c260fda81ead7ba4d67", + "version" : "9.0.1" + } + }, + { + "identity" : "quick", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Quick/Quick.git", + "state" : { + "revision" : "91132c0fe9a98e76f3d7381a608685aa41770706", + "version" : "7.0.2" + } + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser", + "state" : { + "revision" : "6b2aa2748a7881eebb9f84fb10c01293e15b52ca", + "version" : "0.5.0" + } + }, + { + "identity" : "swift-benchmark", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/swift-benchmark", + "state" : { + "revision" : "a0564bf88df5f94eec81348a2f089494c6b28d80", + "version" : "0.1.1" + } + }, + { + "identity" : "swift-case-paths", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-case-paths", + "state" : { + "branch" : "main", + "revision" : "fc45e7b2cfece9dd80b5a45e6469ffe67fe67984" + } + }, + { + "identity" : "swift-custom-dump", + "kind" : "remoteSourceControl", + "location" : "https://github.com:443/pointfreeco/swift-custom-dump", + "state" : { + "revision" : "3a35f7892e7cf6ba28a78cd46a703c0be4e0c6dc" + } + }, + { + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-plugin", + "state" : { + "revision" : "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "version" : "1.0.0" + } + }, + { + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state" : { + "revision" : "4af50b38daf0037cfbab15514a241224c3f62f98", + "version" : "0.8.5" + } + } + ], + "version" : 2 +} diff --git a/swift/spec/fixtures/projects/Example-Deprecated/Package.swift b/swift/spec/fixtures/projects/Example-Deprecated/Package.swift new file mode 100644 index 00000000000..44a79015eb6 --- /dev/null +++ b/swift/spec/fixtures/projects/Example-Deprecated/Package.swift @@ -0,0 +1,25 @@ +// swift-tools-version:5.6 +import PackageDescription + +let package = Package( + name: "Example", + dependencies: [ + .package(url: "https://github.com/Quick/Quick.git", + .upToNextMajor(from: "7.0.0")), + + .package(url: "https://github.com/Quick/Nimble.git", + .upToNextMinor(from: "9.0.0")), + + .package( + url: "https://github.com/apple/swift-docc-plugin", + .exact("1.0.0")), + + .package(name: "foo", url: "https://github.com/google/swift-benchmark", "0.1.0"..<"0.1.2"), + + .package(url: "https://github.com/pointfreeco/swift-case-paths", + .branch("main")), + + .package(url: "https://github.com:443/pointfreeco/swift-custom-dump", + .revision("3a35f7892e7cf6ba28a78cd46a703c0be4e0c6dc")) + ] +) diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/ReactiveSwift/Package.resolved b/swift/spec/fixtures/projects/Example/.build/checkouts/ReactiveSwift/Package.resolved new file mode 100644 index 00000000000..f99c9004623 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/ReactiveSwift/Package.resolved @@ -0,0 +1,43 @@ +{ + "object": { + "pins": [ + { + "package": "CwlCatchException", + "repositoryURL": "https://github.com/mattgallagher/CwlCatchException.git", + "state": { + "branch": null, + "revision": "682841464136f8c66e04afe5dbd01ab51a3a56f2", + "version": "2.1.0" + } + }, + { + "package": "CwlPreconditionTesting", + "repositoryURL": "https://github.com/mattgallagher/CwlPreconditionTesting.git", + "state": { + "branch": null, + "revision": "02b7a39a99c4da27abe03cab2053a9034379639f", + "version": "2.0.0" + } + }, + { + "package": "Nimble", + "repositoryURL": "https://github.com/Quick/Nimble.git", + "state": { + "branch": null, + "revision": "af1730dde4e6c0d45bf01b99f8a41713ce536790", + "version": "9.2.0" + } + }, + { + "package": "Quick", + "repositoryURL": "https://github.com/Quick/Quick.git", + "state": { + "branch": null, + "revision": "bd86ca0141e3cfb333546de5a11ede63f0c4a0e6", + "version": "4.0.0" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/ReactiveSwift/Package.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/ReactiveSwift/Package.swift new file mode 100644 index 00000000000..ba9124b09e3 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/ReactiveSwift/Package.swift @@ -0,0 +1,17 @@ +// swift-tools-version:5.2 +import PackageDescription + +let package = Package( + name: "ReactiveSwift", + platforms: [ + .macOS(.v10_13), .iOS(.v11), .tvOS(.v11), .watchOS(.v4) + ], + dependencies: [ + .package(url: "https://github.com/Quick/Quick.git", from: "4.0.0"), + .package(url: "https://github.com/Quick/Nimble.git", from: "9.0.0"), + ], + targets: [ + .target(name: "ReactiveSwift", dependencies: [], path: "Sources"), + ], + swiftLanguageVersions: [.v5] +) diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/ReactiveSwift/Sources/Reactive.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/ReactiveSwift/Sources/Reactive.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/ReactiveSwift/Sources/Reactive.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/combine-schedulers/Package.resolved b/swift/spec/fixtures/projects/Example/.build/checkouts/combine-schedulers/Package.resolved new file mode 100644 index 00000000000..0e45736d216 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/combine-schedulers/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "xctest-dynamic-overlay", + "repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state": { + "branch": null, + "revision": "f821dcbac7cb6913f8e0d1a80496d0ba0199fa81", + "version": "0.3.0" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/combine-schedulers/Package.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/combine-schedulers/Package.swift new file mode 100644 index 00000000000..8102fa61149 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/combine-schedulers/Package.swift @@ -0,0 +1,30 @@ +// swift-tools-version:5.5 + +import PackageDescription + +let package = Package( + name: "combine-schedulers", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .tvOS(.v13), + .watchOS(.v6), + ], + products: [ + .library( + name: "CombineSchedulers", + targets: ["CombineSchedulers"] + ) + ], + dependencies: [ + .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.3.0") + ], + targets: [ + .target( + name: "CombineSchedulers", + dependencies: [ + .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay") + ] + ) + ] +) diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/combine-schedulers/Sources/CombineSchedulers/SwiftUI.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/combine-schedulers/Sources/CombineSchedulers/SwiftUI.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/combine-schedulers/Sources/CombineSchedulers/SwiftUI.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-argument-parser/Package.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-argument-parser/Package.swift new file mode 100644 index 00000000000..2956b10b848 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-argument-parser/Package.swift @@ -0,0 +1,31 @@ +// swift-tools-version:5.2 +//===----------------------------------------------------------*- swift -*-===// +// +// This source file is part of the Swift Argument Parser open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import PackageDescription + +var package = Package( + name: "swift-argument-parser", + products: [ + .library( + name: "ArgumentParser", + targets: ["ArgumentParser"]), + ], + dependencies: [], + targets: [ + .target( + name: "ArgumentParser", + dependencies: ["ArgumentParserToolInfo"]), + .target( + name: "ArgumentParserToolInfo", + dependencies: []) + ] +) diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-argument-parser/Sources/ArgumentParser/Parsing/Name.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-argument-parser/Sources/ArgumentParser/Parsing/Name.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-argument-parser/Sources/ArgumentParser/Parsing/Name.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-argument-parser/Sources/ArgumentParserToolInfo/ToolInfo.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-argument-parser/Sources/ArgumentParserToolInfo/ToolInfo.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-argument-parser/Sources/ArgumentParserToolInfo/ToolInfo.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-benchmark/Package.resolved b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-benchmark/Package.resolved new file mode 100644 index 00000000000..4520bbb27f0 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-benchmark/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "swift-argument-parser", + "repositoryURL": "https://github.com/apple/swift-argument-parser", + "state": { + "branch": null, + "revision": "6b2aa2748a7881eebb9f84fb10c01293e15b52ca", + "version": "0.5.0" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-benchmark/Package.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-benchmark/Package.swift new file mode 100644 index 00000000000..dbcadfe1e9a --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-benchmark/Package.swift @@ -0,0 +1,34 @@ +// swift-tools-version:5.1 + +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import PackageDescription + +let package = Package( + name: "Benchmark", + products: [ + .library( + name: "Benchmark", + targets: ["Benchmark"]) + ], + dependencies: [ + .package(url: "https://github.com/apple/swift-argument-parser", from: "0.5.0"), + ], + targets: [ + .target( + name: "Benchmark", + dependencies: [.product(name: "ArgumentParser", package: "swift-argument-parser")]) + ] +) diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-benchmark/Sources/Benchmark/Benchmark.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-benchmark/Sources/Benchmark/Benchmark.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-benchmark/Sources/Benchmark/Benchmark.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Package.resolved b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Package.resolved new file mode 100644 index 00000000000..6a606789d35 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Package.resolved @@ -0,0 +1,43 @@ +{ + "object": { + "pins": [ + { + "package": "swift-argument-parser", + "repositoryURL": "https://github.com/apple/swift-argument-parser", + "state": { + "branch": null, + "revision": "986d191f94cec88f6350056da59c2e59e83d1229", + "version": "0.4.3" + } + }, + { + "package": "Benchmark", + "repositoryURL": "https://github.com/google/swift-benchmark", + "state": { + "branch": null, + "revision": "8e0ef8bb7482ab97dcd2cd1d6855bd38921c345d", + "version": "0.1.0" + } + }, + { + "package": "SwiftDocCPlugin", + "repositoryURL": "https://github.com/apple/swift-docc-plugin", + "state": { + "branch": null, + "revision": "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "version": "1.0.0" + } + }, + { + "package": "xctest-dynamic-overlay", + "repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay.git", + "state": { + "branch": null, + "revision": "a9daebf0bf65981fd159c885d504481a65a75f02", + "version": "0.8.0" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Package.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Package.swift new file mode 100644 index 00000000000..fd4d99412b7 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Package.swift @@ -0,0 +1,38 @@ +// swift-tools-version:5.5 + +import PackageDescription + +let package = Package( + name: "swift-case-paths", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .tvOS(.v13), + .watchOS(.v6), + ], + products: [ + .library( + name: "CasePaths", + targets: ["CasePaths"] + ) + ], + dependencies: [ + .package(name: "Benchmark", url: "https://github.com/google/swift-benchmark", from: "0.1.0"), + .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.8.0"), + ], + targets: [ + .target( + name: "CasePaths", + dependencies: [ + .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay") + ] + ) + ] +) + +#if swift(>=5.6) + // Add the documentation compiler plugin if possible + package.dependencies.append( + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") + ) +#endif diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Package@swift-5.1.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Package@swift-5.1.swift new file mode 100644 index 00000000000..c0b6ebd4c9b --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Package@swift-5.1.swift @@ -0,0 +1,18 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "swift-case-paths", + products: [ + .library( + name: "CasePaths", + targets: ["CasePaths"] + ) + ], + targets: [ + .target( + name: "CasePaths" + ) + ] +) diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Sources/CasePaths/CasePath.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Sources/CasePaths/CasePath.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-case-paths/Sources/CasePaths/CasePath.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-custom-dump/Package.resolved b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-custom-dump/Package.resolved new file mode 100644 index 00000000000..76b883171b2 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-custom-dump/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "xctest-dynamic-overlay", + "repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state": { + "branch": null, + "revision": "30314f1ece684dd60679d598a9b89107557b67d9", + "version": "0.4.1" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-custom-dump/Package.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-custom-dump/Package.swift new file mode 100644 index 00000000000..96553f3bfc2 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-custom-dump/Package.swift @@ -0,0 +1,30 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "swift-custom-dump", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .tvOS(.v13), + .watchOS(.v6), + ], + products: [ + .library( + name: "CustomDump", + targets: ["CustomDump"] + ) + ], + dependencies: [ + .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.2.0") + ], + targets: [ + .target( + name: "CustomDump", + dependencies: [ + .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay") + ] + ) + ] +) diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-custom-dump/Sources/CustomDump/Dump.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-custom-dump/Sources/CustomDump/Dump.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-custom-dump/Sources/CustomDump/Dump.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-docc-plugin/Package.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-docc-plugin/Package.swift new file mode 100644 index 00000000000..551d02074d9 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-docc-plugin/Package.swift @@ -0,0 +1,21 @@ +// swift-tools-version:5.6 +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for Swift project authors + +import PackageDescription + +let package = Package( + name: "SwiftDocCPlugin", + platforms: [ + .macOS("10.15.4"), + ], + targets: [ + .target(name: "SwiftDocCPluginUtilities") + ] +) diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/swift-docc-plugin/Sources/SwiftDocCPluginUtilities/Arguments.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-docc-plugin/Sources/SwiftDocCPluginUtilities/Arguments.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/swift-docc-plugin/Sources/SwiftDocCPluginUtilities/Arguments.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/xctest-dynamic-overlay/Package.resolved b/swift/spec/fixtures/projects/Example/.build/checkouts/xctest-dynamic-overlay/Package.resolved new file mode 100644 index 00000000000..3b6d58b80c8 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/xctest-dynamic-overlay/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "SwiftDocCPlugin", + "repositoryURL": "https://github.com/apple/swift-docc-plugin", + "state": { + "branch": null, + "revision": "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "version": "1.0.0" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/xctest-dynamic-overlay/Package.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/xctest-dynamic-overlay/Package.swift new file mode 100644 index 00000000000..53d59e647fe --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/xctest-dynamic-overlay/Package.swift @@ -0,0 +1,26 @@ +// swift-tools-version:5.5 + +import PackageDescription + +let package = Package( + name: "xctest-dynamic-overlay", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .tvOS(.v13), + .watchOS(.v6), + ], + products: [ + .library(name: "XCTestDynamicOverlay", targets: ["XCTestDynamicOverlay"]) + ], + targets: [ + .target(name: "XCTestDynamicOverlay"), + ] +) + +#if swift(>=5.6) + // Add the documentation compiler plugin if possible + package.dependencies.append( + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") + ) +#endif diff --git a/swift/spec/fixtures/projects/Example/.build/checkouts/xctest-dynamic-overlay/Sources/XCTestDynamicOverlay/XCTFail.swift b/swift/spec/fixtures/projects/Example/.build/checkouts/xctest-dynamic-overlay/Sources/XCTestDynamicOverlay/XCTFail.swift new file mode 100644 index 00000000000..10051c76805 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/checkouts/xctest-dynamic-overlay/Sources/XCTestDynamicOverlay/XCTFail.swift @@ -0,0 +1 @@ +// Placeholder diff --git a/swift/spec/fixtures/projects/Example/.build/workspace-state.json b/swift/spec/fixtures/projects/Example/.build/workspace-state.json new file mode 100644 index 00000000000..4110a5304b0 --- /dev/null +++ b/swift/spec/fixtures/projects/Example/.build/workspace-state.json @@ -0,0 +1,145 @@ +{ + "object" : { + "artifacts" : [ + + ], + "dependencies" : [ + { + "basedOn" : null, + "packageRef" : { + "identity" : "combine-schedulers", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/combine-schedulers", + "name" : "combine-schedulers" + }, + "state" : { + "checkoutState" : { + "revision" : "0625932976b3ae23949f6b816d13bd97f3b40b7c", + "version" : "0.10.0" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "combine-schedulers" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "reactiveswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ReactiveCocoa/ReactiveSwift.git", + "name" : "ReactiveSwift" + }, + "state" : { + "checkoutState" : { + "revision" : "509916c99f49a5e6c8196c968b8b7e3dbd48db04", + "version" : "7.1.0" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "ReactiveSwift" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser", + "name" : "swift-argument-parser" + }, + "state" : { + "checkoutState" : { + "revision" : "6b2aa2748a7881eebb9f84fb10c01293e15b52ca", + "version" : "0.5.0" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-argument-parser" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-benchmark", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/swift-benchmark", + "name" : "Benchmark" + }, + "state" : { + "checkoutState" : { + "revision" : "a0564bf88df5f94eec81348a2f089494c6b28d80", + "version" : "0.1.1" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-benchmark" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-case-paths", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-case-paths", + "name" : "swift-case-paths" + }, + "state" : { + "checkoutState" : { + "branch" : "main", + "revision" : "fc45e7b2cfece9dd80b5a45e6469ffe67fe67984" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-case-paths" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-custom-dump", + "kind" : "remoteSourceControl", + "location" : "https://github.com:443/pointfreeco/swift-custom-dump", + "name" : "swift-custom-dump" + }, + "state" : { + "checkoutState" : { + "revision" : "3a35f7892e7cf6ba28a78cd46a703c0be4e0c6dc" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-custom-dump" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-plugin", + "name" : "SwiftDocCPlugin" + }, + "state" : { + "checkoutState" : { + "revision" : "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "version" : "1.0.0" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "swift-docc-plugin" + }, + { + "basedOn" : null, + "packageRef" : { + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "name" : "xctest-dynamic-overlay" + }, + "state" : { + "checkoutState" : { + "revision" : "4af50b38daf0037cfbab15514a241224c3f62f98", + "version" : "0.8.5" + }, + "name" : "sourceControlCheckout" + }, + "subpath" : "xctest-dynamic-overlay" + } + ] + }, + "version" : 6 +} \ No newline at end of file diff --git a/swift/spec/fixtures/projects/Example/Package.resolved b/swift/spec/fixtures/projects/Example/Package.resolved new file mode 100644 index 00000000000..f36793708bf --- /dev/null +++ b/swift/spec/fixtures/projects/Example/Package.resolved @@ -0,0 +1,76 @@ +{ + "pins" : [ + { + "identity" : "combine-schedulers", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/combine-schedulers", + "state" : { + "revision" : "0625932976b3ae23949f6b816d13bd97f3b40b7c", + "version" : "0.10.0" + } + }, + { + "identity" : "reactiveswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ReactiveCocoa/ReactiveSwift.git", + "state" : { + "revision" : "509916c99f49a5e6c8196c968b8b7e3dbd48db04", + "version" : "7.1.0" + } + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser", + "state" : { + "revision" : "6b2aa2748a7881eebb9f84fb10c01293e15b52ca", + "version" : "0.5.0" + } + }, + { + "identity" : "swift-benchmark", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/swift-benchmark", + "state" : { + "revision" : "a0564bf88df5f94eec81348a2f089494c6b28d80", + "version" : "0.1.1" + } + }, + { + "identity" : "swift-case-paths", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-case-paths", + "state" : { + "branch" : "main", + "revision" : "fc45e7b2cfece9dd80b5a45e6469ffe67fe67984" + } + }, + { + "identity" : "swift-custom-dump", + "kind" : "remoteSourceControl", + "location" : "https://github.com:443/pointfreeco/swift-custom-dump", + "state" : { + "revision" : "3a35f7892e7cf6ba28a78cd46a703c0be4e0c6dc" + } + }, + { + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-plugin", + "state" : { + "revision" : "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "version" : "1.0.0" + } + }, + { + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state" : { + "revision" : "4af50b38daf0037cfbab15514a241224c3f62f98", + "version" : "0.8.5" + } + } + ], + "version" : 2 +} diff --git a/swift/spec/fixtures/projects/Example/Package.swift b/swift/spec/fixtures/projects/Example/Package.swift new file mode 100644 index 00000000000..c07fe9d4edc --- /dev/null +++ b/swift/spec/fixtures/projects/Example/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version:5.6 +import PackageDescription + +let package = Package( + name: "Example", + dependencies: [ + .package(url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", + exact: "7.1.0"), + + .package( + url: "https://github.com/apple/swift-docc-plugin", + from: "1.0.0"), + + .package(url: "https://github.com/google/swift-benchmark", "0.1.0"..<"0.1.2"), + .package(url: "https://github.com/pointfreeco/combine-schedulers", "0.9.2"..."0.10.0"), + + .package(url: "https://github.com/pointfreeco/swift-case-paths", + branch: "main"), + + .package(url: "https://github.com:443/pointfreeco/swift-custom-dump", + revision: "3a35f7892e7cf6ba28a78cd46a703c0be4e0c6dc") + ] +) diff --git a/swift/spec/fixtures/projects/ReactiveCocoa/Package.resolved b/swift/spec/fixtures/projects/ReactiveCocoa/Package.resolved new file mode 100644 index 00000000000..7298b48475b --- /dev/null +++ b/swift/spec/fixtures/projects/ReactiveCocoa/Package.resolved @@ -0,0 +1,52 @@ +{ + "object": { + "pins": [ + { + "package": "CwlCatchException", + "repositoryURL": "https://github.com/mattgallagher/CwlCatchException.git", + "state": { + "branch": null, + "revision": "35f9e770f54ce62dd8526470f14c6e137cef3eea", + "version": "2.1.1" + } + }, + { + "package": "CwlPreconditionTesting", + "repositoryURL": "https://github.com/mattgallagher/CwlPreconditionTesting.git", + "state": { + "branch": null, + "revision": "c21f7bab5ca8eee0a9998bbd17ca1d0eb45d4688", + "version": "2.1.0" + } + }, + { + "package": "Nimble", + "repositoryURL": "https://github.com/Quick/Nimble.git", + "state": { + "branch": null, + "revision": "c93f16c25af5770f0d3e6af27c9634640946b068", + "version": "9.2.1" + } + }, + { + "package": "Quick", + "repositoryURL": "https://github.com/Quick/Quick.git", + "state": { + "branch": null, + "revision": "e206b8deba0d01fce70388a6d9dc66cba5603958", + "version": "7.0.0" + } + }, + { + "package": "ReactiveSwift", + "repositoryURL": "https://github.com/ReactiveCocoa/ReactiveSwift", + "state": { + "branch": null, + "revision": "40c465af19b993344e84355c00669ba2022ca3cd", + "version": "7.1.1" + } + } + ] + }, + "version": 1 +} diff --git a/swift/spec/fixtures/projects/ReactiveCocoa/Package.swift b/swift/spec/fixtures/projects/ReactiveCocoa/Package.swift new file mode 100644 index 00000000000..711e41cd0c8 --- /dev/null +++ b/swift/spec/fixtures/projects/ReactiveCocoa/Package.swift @@ -0,0 +1,16 @@ +// swift-tools-version:5.2 +// The swift-tools-version declares the minimum version of Swift required to build this package. +import PackageDescription + +let package = Package( + name: "ReactiveCocoa", + platforms: [ + .macOS(.v10_13), .iOS(.v11), .tvOS(.v11), .watchOS(.v4) + ], + dependencies: [ + .package(url: "https://github.com/ReactiveCocoa/ReactiveSwift", from: "7.0.0"), + .package(url: "https://github.com/Quick/Quick.git", from: "7.0.0"), + .package(url: "https://github.com/Quick/Nimble.git", from: "9.0.0"), + ], + swiftLanguageVersions: [.v5] +) diff --git a/swift/spec/fixtures/projects/manifest-only/Package.swift b/swift/spec/fixtures/projects/manifest-only/Package.swift new file mode 100644 index 00000000000..f13e4bc1179 --- /dev/null +++ b/swift/spec/fixtures/projects/manifest-only/Package.swift @@ -0,0 +1,10 @@ +// swift-tools-version:5.8.0 + +import PackageDescription + +let package = Package( + name: "tuist", + dependencies: [ + .package(url: "https://github.com/apple/swift-nio-http2.git", exact: "1.19.2") + ] +) diff --git a/swift/spec/fixtures/projects/standard/Package.resolved b/swift/spec/fixtures/projects/standard/Package.resolved new file mode 100644 index 00000000000..206dd3e4ede --- /dev/null +++ b/swift/spec/fixtures/projects/standard/Package.resolved @@ -0,0 +1,41 @@ +{ + "pins" : [ + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "6c89474e62719ddcc1e9614989fff2f68208fe10", + "version" : "1.1.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections", + "state" : { + "revision" : "937e904258d22af6e447a0b72c0bc67583ef64a2", + "version" : "1.0.4" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "6213ba7a06febe8fef60563a4a7d26a4085783cf", + "version" : "2.54.0" + } + }, + { + "identity" : "swift-nio-http2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-http2.git", + "state" : { + "revision" : "000ca94f9de92c95b9ac85d44600b7b0fe25a3e5", + "version" : "1.19.2" + } + } + ], + "version" : 2 +} diff --git a/swift/spec/fixtures/projects/standard/Package.swift b/swift/spec/fixtures/projects/standard/Package.swift new file mode 100644 index 00000000000..f13e4bc1179 --- /dev/null +++ b/swift/spec/fixtures/projects/standard/Package.swift @@ -0,0 +1,10 @@ +// swift-tools-version:5.8.0 + +import PackageDescription + +let package = Package( + name: "tuist", + dependencies: [ + .package(url: "https://github.com/apple/swift-nio-http2.git", exact: "1.19.2") + ] +) diff --git a/swift/spec/spec_helper.rb b/swift/spec/spec_helper.rb new file mode 100644 index 00000000000..6dcb854b37c --- /dev/null +++ b/swift/spec/spec_helper.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +def common_dir + @common_dir ||= Gem::Specification.find_by_name("dependabot-common").gem_dir +end + +def require_common_spec(path) + require "#{common_dir}/spec/dependabot/#{path}" +end + +require "#{common_dir}/spec/spec_helper.rb" diff --git a/updater/Gemfile b/updater/Gemfile index 10af28f837c..75714e611bb 100644 --- a/updater/Gemfile +++ b/updater/Gemfile @@ -18,6 +18,7 @@ gem "dependabot-npm_and_yarn", path: "../npm_and_yarn" gem "dependabot-nuget", path: "../nuget" gem "dependabot-pub", path: "../pub" gem "dependabot-python", path: "../python" +gem "dependabot-swift", path: "../swift" gem "dependabot-terraform", path: "../terraform" gem "http", "~> 5.1" diff --git a/updater/Gemfile.lock b/updater/Gemfile.lock index 26ae6d29c52..b5e32a45d13 100644 --- a/updater/Gemfile.lock +++ b/updater/Gemfile.lock @@ -109,6 +109,12 @@ PATH dependabot-python (0.221.0) dependabot-common (= 0.221.0) +PATH + remote: ../swift + specs: + dependabot-swift (0.221.0) + dependabot-common (= 0.221.0) + PATH remote: ../terraform specs: @@ -309,6 +315,7 @@ DEPENDENCIES dependabot-nuget! dependabot-pub! dependabot-python! + dependabot-swift! dependabot-terraform! http (~> 5.1) licensed (~> 4.3) diff --git a/updater/lib/dependabot/setup.rb b/updater/lib/dependabot/setup.rb index d9fa805ad97..d9395bffaf9 100644 --- a/updater/lib/dependabot/setup.rb +++ b/updater/lib/dependabot/setup.rb @@ -34,7 +34,8 @@ go_modules| npm_and_yarn| bundler| - pub + pub| + swift )}x config.processors += [ExceptionSanitizer] @@ -59,3 +60,4 @@ require "dependabot/npm_and_yarn" require "dependabot/bundler" require "dependabot/pub" +require "dependabot/swift" diff --git a/updater/lib/dependabot/updater.rb b/updater/lib/dependabot/updater.rb index 30830842bfd..846d6463051 100644 --- a/updater/lib/dependabot/updater.rb +++ b/updater/lib/dependabot/updater.rb @@ -27,6 +27,7 @@ require "dependabot/npm_and_yarn" require "dependabot/bundler" require "dependabot/pub" +require "dependabot/swift" # Updater components require "dependabot/updater/error_handler"