├── .circleci └── config.yml ├── .codeclimate.yml ├── .github └── CONTRIBUTING.md ├── .gitignore ├── .rspec ├── .rubocop.yml ├── .ruby-version ├── .tidelift ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bibliothecary.gemspec ├── bin ├── bibliothecary ├── console └── setup ├── lib ├── bibliothecary.rb ├── bibliothecary │ ├── analyser.rb │ ├── analyser │ │ ├── analysis.rb │ │ ├── determinations.rb │ │ └── matchers.rb │ ├── cli.rb │ ├── configuration.rb │ ├── dependency.rb │ ├── exceptions.rb │ ├── file_info.rb │ ├── multi_parsers │ │ ├── bundler_like_manifest.rb │ │ ├── cyclonedx.rb │ │ ├── dependencies_csv.rb │ │ ├── json_runtime.rb │ │ └── spdx.rb │ ├── parsers │ │ ├── bower.rb │ │ ├── cargo.rb │ │ ├── cocoapods.rb │ │ ├── conda.rb │ │ ├── cpan.rb │ │ ├── cran.rb │ │ ├── dub.rb │ │ ├── elm.rb │ │ ├── go.rb │ │ ├── haxelib.rb │ │ ├── julia.rb │ │ ├── maven.rb │ │ ├── meteor.rb │ │ ├── npm.rb │ │ ├── nuget.rb │ │ ├── packagist.rb │ │ ├── pub.rb │ │ ├── pypi.rb │ │ ├── rubygems.rb │ │ └── shard.rb │ ├── purl_util.rb │ ├── related_files_info.rb │ ├── runner.rb │ ├── runner │ │ └── multi_manifest_filter.rb │ └── version.rb └── sdl_parser.rb └── spec ├── bibliothecary ├── configuration_spec.rb ├── dependency_spec.rb ├── file_info_spec.rb ├── multi_manifest_filter_spec.rb ├── purl_util_spec.rb └── runner_spec.rb ├── bibliothecary_spec.rb ├── fixtures ├── 2018-package-lock │ └── package-lock.json ├── Cargo.lock ├── Cargo.toml ├── Cartfile ├── Cartfile.private ├── Cartfile.resolved ├── DESCRIPTION ├── DESCRIPTION2 ├── Gemfile ├── Gemfile.lock ├── GemfileLineEndings.lock ├── GemfileWithBundler.lock ├── Godeps ├── Godeps.json ├── Gopkg.lock ├── Gopkg.toml ├── META.json ├── META.yml ├── Package.swift ├── Pipfile ├── Pipfile.lock ├── Podfile ├── Podfile.lock ├── Project.json ├── Project.lock.json ├── REQUIRE ├── bower.json ├── broken │ └── pom.xml ├── build.gradle ├── build.gradle.kts ├── build.sbt ├── bun.lock ├── cabal.config ├── composer.json ├── composer.lock ├── composer2.json ├── conda_with_pip │ └── environment.yml ├── cpanfile ├── cpanfile.snapshot ├── cyclonedx-nested.json ├── cyclonedx-nested.xml ├── cyclonedx.json ├── cyclonedx.xml ├── dependencies.csv ├── devise.gemspec ├── dist.ini ├── dpkg ├── dub.json ├── dub.sdl ├── elm-package.json ├── elm_dependencies.json ├── empty_manifests │ ├── Gemfile │ └── package.json ├── environment.yml ├── exact-dependencies.json ├── example-no-version.csproj ├── example-update.csproj ├── example.cabal ├── example.csproj ├── example.nuspec ├── example.podspec ├── example.podspec.json ├── gb_manifest ├── gems.rb ├── github-payloads.js ├── glide.lock ├── glide.yaml ├── go-resolved-dependencies.json ├── go.mod ├── go.single-require.mod ├── go.sum ├── gradle-dependencies-q.txt ├── gradle_with_kotlin │ └── gradle-dependencies-q.txt ├── haxelib.json ├── ivy.xml ├── ivy_reports │ ├── com.example-hello_2.12-compile.xml │ ├── com.example-hello_2.12-test.xml │ ├── com.example-subproject_2.12-compile.xml │ ├── com.example-subproject_2.12-test.xml │ ├── invalid_syntax.xml │ ├── missing_info.xml │ └── non_ivy_report.xml ├── maven-dependency-tree.dot ├── maven-dependency-tree.txt ├── maven-resolved-dependencies.txt ├── maven_parent_deps │ ├── jaxb-bom-2.3.1.pom.xml │ └── jaxb-runtime-2.3.1.pom.xml ├── mix.exs ├── mix.lock ├── multimanifest_dir │ ├── Gemfile │ ├── Gemfile.lock │ ├── com.example-hello_2.12-compile.xml │ ├── package-lock.json │ ├── package.json │ ├── pom.xml │ ├── setup.py │ ├── subdir │ │ ├── Gemfile │ │ └── Gemfile.lock │ ├── unknown_non_manifest.txt │ └── yarn.lock ├── multiple_versions │ ├── package-lock.json │ └── yarn.lock ├── npm-local-file │ ├── package-lock.json │ ├── package.json │ └── yarn.lock ├── npm-lockfile-version-1 │ └── package-lock.json ├── npm-lockfile-version-2 │ └── package-lock.json ├── npm-lockfile-version-3 │ └── package-lock.json ├── npm-ls.json ├── npm-shrinkwrap.json ├── nuget_project.assets.json ├── package-lock.json ├── package.json ├── packages.config ├── packages.lock.json ├── paket.lock ├── pip-compile │ ├── requirements-extras.in │ ├── requirements.frozen │ ├── requirements.in │ └── requirements.txt ├── pip-dependency-graph.json ├── pip-resolved-dependencies.txt ├── pnpm-lockfile-version-5 │ ├── package.json │ └── pnpm-lock.yaml ├── pnpm-lockfile-version-6 │ ├── package.json │ └── pnpm-lock.yaml ├── pnpm-lockfile-version-9 │ ├── package.json │ └── pnpm-lock.yaml ├── poetry.lock ├── pom-spaces-in-artifact-and-group.xml ├── pom.xml ├── pom2.xml ├── pom_dependencies_no_requirement.xml ├── pom_missing_props.xml ├── pom_no_props.xml ├── project.clj ├── pubspec.lock ├── pubspec.yaml ├── pyproject.toml ├── requirements-dev.txt ├── requirements-git.txt ├── requirements.frozen ├── requirements.txt ├── requirements │ └── test.txt ├── sbt-update-full.txt ├── setup.py ├── setup2.py ├── shard.lock ├── shard.yml ├── spdx2.2.json ├── vendor.json ├── versions.json ├── yarn-v4-lockfile │ ├── package.json │ └── yarn.lock ├── yarn-with-git-repo │ ├── package.json │ └── yarn.lock └── yarn.lock ├── multi_parsers ├── cyclonedx_spec.rb ├── dependencies_csv_spec.rb └── spdx_spec.rb ├── parsers ├── bower_spec.rb ├── cargo_spec.rb ├── cocoapods_spec.rb ├── conda_spec.rb ├── cpan_spec.rb ├── cran_spec.rb ├── dub_spec.rb ├── elm_spec.rb ├── go_spec.rb ├── haxelib_spec.rb ├── julia_spec.rb ├── maven_spec.rb ├── meteor_spec.rb ├── npm_spec.rb ├── nuget_spec.rb ├── packagist_spec.rb ├── pub_spec.rb ├── pypi_spec.rb ├── rubygems_spec.rb └── shard_spec.rb ├── shared_examples ├── cyclonedx.rb └── dependencies_csv.rb └── spec_helper.rb /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | orbs: 3 | ruby: circleci/ruby@2.1.3 4 | 5 | executors: 6 | bibliothecary: 7 | docker: 8 | - image: cimg/ruby:3.2.6 9 | working_directory: ~/bibliothecary 10 | 11 | 12 | commands: 13 | setup-ruby-env: 14 | description: "Some requirements to ensure that the ruby orb install-deps works" 15 | steps: 16 | - run: 17 | name: Prep ruby 18 | command: | 19 | touch /tmp/ruby-project-lockfile 20 | bundle lock --add-platform x86_64-linux 21 | - ruby/install-deps: 22 | bundler-version: "2.3" 23 | key: gems-v3 24 | 25 | 26 | jobs: 27 | test: 28 | executor: bibliothecary 29 | steps: 30 | - checkout 31 | - setup-ruby-env 32 | - run: 33 | name: Run specs 34 | command: bundle exec rake spec 35 | - run: 36 | name: CodeClimate 37 | command: bundle exec codeclimate-test-reporter 38 | 39 | lint: 40 | executor: bibliothecary 41 | steps: 42 | - checkout 43 | - setup-ruby-env 44 | - run: 45 | name: Run specs 46 | command: bundle exec rake lint 47 | 48 | workflows: 49 | version: 2.1 50 | circleci_build: 51 | jobs: 52 | - test 53 | - lint 54 | 55 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | duplication: 4 | enabled: true 5 | config: 6 | languages: 7 | - ruby 8 | - javascript 9 | - python 10 | - php 11 | fixme: 12 | enabled: true 13 | rubocop: 14 | enabled: true 15 | ratings: 16 | paths: 17 | - "**.inc" 18 | - "**.js" 19 | - "**.jsx" 20 | - "**.module" 21 | - "**.php" 22 | - "**.py" 23 | - "**.rb" 24 | exclude_paths: 25 | - spec/ 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.gem 11 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Without this, CI might pickup nested dep's rubocop files in vendor/ 4 | inherit_mode: 5 | merge: 6 | - Exclude 7 | 8 | AllCops: 9 | NewCops: enable 10 | TargetRubyVersion: 3.2.6 11 | Exclude: 12 | - spec/fixtures/**/* 13 | - vendor/bundle/**/* # This is actually needed for CI, not for biblio itself 14 | 15 | 16 | Metrics/BlockLength: 17 | Max: 100 18 | Exclude: 19 | - config/routes.rb 20 | - config/initializers/* 21 | - spec/**/*_spec.rb 22 | - spec/factories.rb 23 | - lib/tasks/*.rake 24 | 25 | # metrics and documentation. code is complex as it needs to be, 26 | # and docs shouldn't be required. add them when needed. 27 | Metrics/AbcSize: 28 | Enabled: false 29 | Layout/LineLength: 30 | Enabled: false 31 | Metrics/ClassLength: 32 | Enabled: false 33 | Metrics/MethodLength: 34 | Enabled: false 35 | Metrics/ModuleLength: 36 | Enabled: false 37 | Metrics/CyclomaticComplexity: 38 | Enabled: false 39 | Metrics/PerceivedComplexity: 40 | Enabled: false 41 | Metrics/ParameterLists: 42 | Max: 7 43 | CountKeywordArgs: false 44 | Style/Documentation: 45 | Enabled: false 46 | 47 | # differences from standard ruby style guide. 48 | Style/RegexpLiteral: 49 | Enabled: false 50 | Style/StringLiterals: 51 | EnforcedStyle: double_quotes 52 | Style/TrailingCommaInArrayLiteral: 53 | EnforcedStyleForMultiline: comma 54 | Style/TrailingCommaInHashLiteral: 55 | EnforcedStyleForMultiline: comma 56 | Layout/FirstArrayElementIndentation: 57 | Enabled: false 58 | Layout/MultilineMethodCallIndentation: 59 | EnforcedStyle: indented 60 | Style/NumericPredicate: 61 | Enabled: false 62 | Style/FormatStringToken: 63 | Enabled: false 64 | Style/MultilineBlockChain: 65 | Enabled: false 66 | Style/IfUnlessModifier: 67 | Enabled: false 68 | Layout/BlockAlignment: 69 | EnforcedStyleAlignWith: start_of_block 70 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.2.6 2 | -------------------------------------------------------------------------------- /.tidelift: -------------------------------------------------------------------------------- 1 | TIDELIFT_EXCLUDED_MANIFESTS=spec/fixtures 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at andrew@libraries.io. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # Specify your gem's dependencies in bibliothecary.gemspec 6 | gemspec 7 | 8 | group :development do 9 | gem "pry" 10 | end 11 | 12 | group :development, :test do 13 | gem "rake", "~> 12.0" 14 | gem "rubocop", "~> 1.71" 15 | gem "rubocop-rails" 16 | gem "rubocop-rake" # This is needed by packageurl-ruby, until it reclassifies it as a dev dependency. 17 | end 18 | 19 | group :test do 20 | gem "codeclimate-test-reporter", "~> 1.0.0" 21 | gem "rspec", "~> 3.0" 22 | gem "simplecov" 23 | gem "super_diff", "~> 0.15.0" 24 | gem "webmock" 25 | end 26 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bundler/gem_tasks" 4 | require "rspec/core/rake_task" 5 | 6 | RSpec::Core::RakeTask.new(:spec) 7 | 8 | task default: :spec 9 | 10 | desc "Run the linter" 11 | task :lint do 12 | sh "bundle exec rubocop -P" 13 | end 14 | 15 | desc "Run the linter with autofix" 16 | task :fix do 17 | sh "bundle exec rubocop -A" 18 | end 19 | -------------------------------------------------------------------------------- /bibliothecary.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path("lib", __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require "bibliothecary/version" 6 | 7 | Gem::Specification.new do |spec| 8 | spec.required_ruby_version = ">= 3.2.0" 9 | 10 | spec.name = "bibliothecary" 11 | spec.version = Bibliothecary::VERSION 12 | spec.authors = ["Andrew Nesbitt"] 13 | spec.email = ["andrewnez@gmail.com"] 14 | 15 | spec.summary = "Find and parse manifests" 16 | spec.homepage = "https://github.com/librariesio/bibliothecary" 17 | spec.license = "AGPL-3.0" 18 | 19 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } 20 | spec.bindir = "bin" 21 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 22 | spec.require_paths = ["lib"] 23 | 24 | spec.add_dependency "commander" 25 | spec.add_dependency "deb_control" 26 | spec.add_dependency "json", "~> 2.8" 27 | spec.add_dependency "librariesio-gem-parser" 28 | spec.add_dependency "ox", ">= 2.8.1" 29 | spec.add_dependency "packageurl-ruby" 30 | spec.add_dependency "sdl4r" 31 | spec.add_dependency "tomlrb", "~> 2.0" 32 | spec.add_dependency "typhoeus" 33 | 34 | spec.metadata["rubygems_mfa_required"] = "true" 35 | end 36 | -------------------------------------------------------------------------------- /bin/bibliothecary: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | lib = File.expand_path("../lib", __dir__) 5 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 6 | 7 | require "bibliothecary/cli" 8 | 9 | Bibliothecary::CLI.new.run 10 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "bundler/setup" 5 | require "bibliothecary" 6 | 7 | # You can add fixtures and/or initialization code here to make experimenting 8 | # with your gem easier. You can also use a different console, if you like. 9 | 10 | # (If you use this, don't forget to add pry to your Gemfile!) 11 | # require "pry" 12 | # Pry.start 13 | 14 | require "pry" 15 | Pry.start 16 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /lib/bibliothecary.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bibliothecary/version" 4 | require "bibliothecary/dependency" 5 | require "bibliothecary/analyser" 6 | require "bibliothecary/configuration" 7 | require "bibliothecary/runner" 8 | require "bibliothecary/exceptions" 9 | require "bibliothecary/file_info" 10 | require "bibliothecary/related_files_info" 11 | require "bibliothecary/purl_util" 12 | require "find" 13 | require "tomlrb" 14 | 15 | Dir[File.expand_path("bibliothecary/multi_parsers/*.rb", __dir__)].each do |file| 16 | require file 17 | end 18 | Dir[File.expand_path("bibliothecary/parsers/*.rb", __dir__)].each do |file| 19 | require file 20 | end 21 | 22 | module Bibliothecary 23 | VERSION_OPERATORS = /[~^<>*"]/ 24 | INVALID_UTF8_ERROR_REGEXP = /invalid byte sequence/ 25 | 26 | def self.analyse(path, ignore_unparseable_files: true) 27 | runner.analyse(path, ignore_unparseable_files: ignore_unparseable_files) 28 | end 29 | 30 | # deprecated; use load_file_info_list. 31 | def self.load_file_list(path) 32 | runner.load_file_list(path) 33 | end 34 | 35 | def self.applicable_package_managers(info) 36 | runner.applicable_package_managers(info) 37 | end 38 | 39 | def self.load_file_info_list(path) 40 | runner.load_file_info_list(path) 41 | end 42 | 43 | def self.load_file_info_list_from_paths(paths) 44 | runner.load_file_info_list_from_paths(paths) 45 | end 46 | 47 | def self.load_file_info_list_from_contents(file_path_contents_hash) 48 | runner.load_file_info_list_from_contents(file_path_contents_hash) 49 | end 50 | 51 | def self.analyse_file(file_path, contents) 52 | runner.analyse_file(file_path, contents) 53 | end 54 | 55 | def self.identify_manifests(file_list) 56 | runner.identify_manifests(file_list) 57 | end 58 | 59 | def self.package_managers 60 | runner.package_managers 61 | end 62 | 63 | def self.find_manifests(path) 64 | runner.find_manifests(path) 65 | end 66 | 67 | def self.find_manifests_from_paths(paths) 68 | runner.find_manifests_from_paths(paths) 69 | end 70 | 71 | def self.find_manifests_from_contents(file_path_contents_hash) 72 | runner.find_manifests_from_contents(file_path_contents_hash) 73 | end 74 | 75 | def self.ignored_dirs 76 | configuration.ignored_dirs 77 | end 78 | 79 | def self.ignored_files 80 | configuration.ignored_files 81 | end 82 | 83 | def self.utf8_string(string) 84 | string 85 | .dup # ensure we don't have a frozen string 86 | .force_encoding("UTF-8") # treat all strings as utf8 87 | .sub(/^\xEF\xBB\xBF/, "") # remove any Byte Order Marks so JSON, etc don't fail while parsing them. 88 | rescue ArgumentError => e 89 | # Bibliothecary doesn't need to analyze non-UTF8 files like binary files, so just return blank. 90 | return "" if e.message.match?(INVALID_UTF8_ERROR_REGEXP) 91 | 92 | raise e 93 | end 94 | 95 | class << self 96 | attr_writer :configuration 97 | alias analyze analyse 98 | alias analyze_file analyse_file 99 | end 100 | 101 | def self.runner 102 | configuration 103 | @runner 104 | end 105 | 106 | def self.configuration 107 | @configuration ||= Configuration.new 108 | @runner = Runner.new(@configuration) 109 | @configuration 110 | end 111 | 112 | def self.reset 113 | @configuration = Configuration.new 114 | @runner = Runner.new(@configuration) 115 | end 116 | 117 | def self.configure 118 | yield(configuration) 119 | end 120 | end 121 | -------------------------------------------------------------------------------- /lib/bibliothecary/analyser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "analyser/matchers" 4 | require_relative "analyser/determinations" 5 | require_relative "analyser/analysis" 6 | 7 | module Bibliothecary 8 | module Analyser 9 | def self.create_error_analysis(platform_name, relative_path, kind, message, location = nil) 10 | { 11 | platform: platform_name, 12 | path: relative_path, 13 | dependencies: nil, 14 | kind: kind, 15 | success: false, 16 | error_message: message, 17 | error_location: location, 18 | } 19 | end 20 | 21 | def self.create_analysis(platform_name, relative_path, kind, dependencies) 22 | { 23 | platform: platform_name, 24 | path: relative_path, 25 | dependencies: dependencies, 26 | kind: kind, 27 | success: true, 28 | } 29 | end 30 | 31 | def self.included(base) 32 | base.extend(ClassMethods) 33 | 34 | # Group like-methods into separate modules for easier comprehension. 35 | base.extend(Bibliothecary::Analyser::Matchers) 36 | base.extend(Bibliothecary::Analyser::Determinations) 37 | base.extend(Bibliothecary::Analyser::Analysis) 38 | end 39 | 40 | module TryCache 41 | def try_cache(options, key) 42 | if options[:cache] 43 | options[:cache][key] ||= yield 44 | 45 | options[:cache][key] 46 | else 47 | yield 48 | end 49 | end 50 | end 51 | 52 | module ClassMethods 53 | def generic? 54 | platform_name == "generic" 55 | end 56 | 57 | def platform_name 58 | name.to_s.split("::").last.downcase 59 | end 60 | 61 | def map_dependencies(hash, key, type, source = nil) 62 | hash.fetch(key, []).map do |name, requirement| 63 | Dependency.new( 64 | name: name, 65 | requirement: requirement, 66 | type: type, 67 | source: source 68 | ) 69 | end 70 | end 71 | 72 | # Add a MultiParser module to a Parser class. This extends the 73 | # self.mapping method on the parser to include the multi parser's 74 | # files to watch for, and it extends the Parser class with 75 | # the multi parser for you. 76 | # 77 | # @param klass [Class] A Bibliothecary::MultiParsers class 78 | def add_multi_parser(klass) 79 | raise "No mapping found! You should place the add_multi_parser call below def self.mapping." unless respond_to?(:mapping) 80 | 81 | original_mapping = mapping 82 | 83 | define_singleton_method(:mapping) do 84 | original_mapping.merge(klass.mapping) 85 | end 86 | 87 | send(:extend, klass) 88 | end 89 | end 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /lib/bibliothecary/analyser/determinations.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | module Analyser 5 | module Determinations 6 | # calling this with contents=nil can produce less-informed 7 | # results, but kept for back compat 8 | def determine_kind(filename, contents = nil) 9 | determine_kind_from_info(FileInfo.new(nil, filename, contents)) 10 | end 11 | 12 | def determine_kind_from_info(info) 13 | first_matching_mapping_details(info) 14 | .fetch(:kind, nil) 15 | end 16 | 17 | # calling this with contents=nil can produce less-informed 18 | # results, but kept for back compat 19 | def determine_can_have_lockfile(filename, contents = nil) 20 | determine_can_have_lockfile_from_info(FileInfo.new(nil, filename, contents)) 21 | end 22 | 23 | def determine_can_have_lockfile_from_info(info) 24 | first_matching_mapping_details(info) 25 | .fetch(:can_have_lockfile, true) 26 | end 27 | 28 | def groupable?(info) 29 | # More package managers are groupable than ungroupable, but the methods 30 | # to get this information should be positive. 31 | !first_matching_mapping_details(info).fetch(:ungroupable, false) 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/bibliothecary/analyser/matchers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | module Analyser 5 | module Matchers 6 | def match_filename(filename, case_insensitive: false) 7 | if case_insensitive 8 | ->(path) { path.downcase == filename.downcase || path.downcase.end_with?("/#{filename.downcase}") } 9 | else 10 | ->(path) { path == filename || path.end_with?("/#{filename}") } 11 | end 12 | end 13 | 14 | def match_filenames(*filenames) 15 | lambda do |path| 16 | filenames.any? { |f| path == f } || 17 | filenames.any? { |f| path.end_with?("/#{f}") } 18 | end 19 | end 20 | 21 | def match_extension(filename, case_insensitive: false) 22 | if case_insensitive 23 | ->(path) { path.downcase.end_with?(filename.downcase) } 24 | else 25 | ->(path) { path.end_with?(filename) } 26 | end 27 | end 28 | 29 | def mapping_entry_match?(matcher, details, info) 30 | return false unless matcher.call(info.relative_path) 31 | # we only want to load contents if we don't have them already 32 | # and there's a content_matcher method to use 33 | return true if details[:content_matcher].nil? 34 | # this is the libraries.io case where we won't load all .xml 35 | # files (for example) just to look at their contents, we'll 36 | # assume they are not manifests. 37 | return false if info.contents.nil? 38 | 39 | send(details[:content_matcher], info.contents) 40 | end 41 | 42 | # this is broken with contents=nil because it can't look at file 43 | # contents, so skips manifests that are ambiguously a 44 | # manifest considering only the filename. However, those are 45 | # the semantics that libraries.io uses since it doesn't have 46 | # the files locally. 47 | def match?(filename, contents = nil) 48 | match_info?(FileInfo.new(nil, filename, contents)) 49 | end 50 | 51 | def match_info?(info) 52 | first_matching_mapping_details(info).any? 53 | end 54 | 55 | private 56 | 57 | def first_matching_mapping_details(info) 58 | mapping 59 | .find { |matcher, details| mapping_entry_match?(matcher, details, info) } 60 | &.last || {} 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/bibliothecary/cli.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bibliothecary/version" 4 | require "bibliothecary" 5 | require "commander" 6 | 7 | module Bibliothecary 8 | class CLI 9 | include Commander::Methods 10 | 11 | def run 12 | program :name, "Bibliothecary" 13 | program :version, Bibliothecary::VERSION 14 | program :description, "Parse dependency information from a file or folder of code" 15 | 16 | command(:list) do |c| 17 | c.syntax = "bibliothecary list" 18 | c.description = "List dependencies" 19 | c.option("--path FILENAME", String, "Path to file/folder to analyse") 20 | c.action do |_args, options| 21 | options.default path: "./" 22 | output = Bibliothecary.analyse(options.path) 23 | output.each do |file_contents| 24 | puts "#{file_contents[:path]} (#{file_contents[:platform]})" 25 | file_contents[:dependencies].group_by { |d| d[:type] }.each do |type, deps| 26 | puts " #{type}" 27 | deps.each do |dep| 28 | puts " #{dep[:name]} #{dep[:requirement]}" 29 | end 30 | puts 31 | end 32 | puts 33 | end 34 | end 35 | end 36 | 37 | run! 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/bibliothecary/configuration.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | class Configuration 5 | attr_accessor :ignored_dirs, :ignored_files, :carthage_parser_host, :clojars_parser_host, :mix_parser_host, :conda_parser_host, :swift_parser_host, :cabal_parser_host 6 | 7 | def initialize 8 | @ignored_dirs = [".git", "node_modules", "bower_components", "vendor", "dist"] 9 | @ignored_files = [] 10 | @carthage_parser_host = "https://carthage.libraries.io" 11 | @clojars_parser_host = "https://clojars.libraries.io" 12 | @mix_parser_host = "https://mix.libraries.io" 13 | @swift_parser_host = "http://swift.libraries.io" 14 | @cabal_parser_host = "http://cabal.libraries.io" 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/bibliothecary/dependency.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | # Dependency represents a single unique dependency that was parsed out of a manifest. 5 | # 6 | # @attr_reader [String] name The name of the package, e.g. "ansi-string-colors" 7 | # @attr_reader [String] requirement The version requirement of the release, e.g. "1.0.0" or "^1.0.0" 8 | # @attr_reader [String] platform The platform of the package, e.g. "maven". This is optional because 9 | # it's implicit in most parser results, and the analyzer returns the platform name itself. One 10 | # exception are multi-parsers like DependenciesCSV, because they may return deps from multiple platforms. 11 | # Bibliothecary could start returning this field for *all* deps in future, and make it required. (default: nil) 12 | # @attr_reader [String] type The type of dependency, e.g. "runtime" or "test" 13 | # @attr_reader [Boolean] direct Is this dependency a direct dependency (vs transitive dependency)? (default: nil) 14 | # @attr_reader [Boolean] deprecated Is this dependency deprecated? (default: nil) 15 | # @attr_reader [Boolean] local Is this dependency local? (default: nil) 16 | # @attr_reader [Boolean] optional Is this dependency optional? (default: nil) 17 | # @attr_reader [String] original_name The original name used to require the dependency, for cases 18 | # where it did not match the resolved name. This can be used for features like aliasing. 19 | # @attr_reader [String] original_requirement The original requirement used to require the dependency, 20 | # for cases where it did not match the resolved name. This can be used for features like aliasing. 21 | # @source [String] source An optional string to store the location of the manifest that contained this 22 | # dependency, e.g. "src/package.json". 23 | class Dependency 24 | FIELDS = %i[ 25 | name 26 | requirement 27 | original_requirement 28 | platform 29 | type 30 | direct 31 | deprecated 32 | local 33 | optional 34 | original_name 35 | source 36 | ].freeze 37 | 38 | attr_reader(*FIELDS) 39 | 40 | def initialize( 41 | name:, 42 | requirement:, 43 | original_requirement: nil, 44 | platform: nil, 45 | type: nil, 46 | direct: nil, 47 | deprecated: nil, 48 | local: nil, 49 | optional: nil, 50 | original_name: nil, 51 | source: nil 52 | ) 53 | @name = name 54 | @platform = platform 55 | @requirement = requirement || "*" 56 | @original_requirement = original_requirement 57 | @type = type 58 | @direct = direct 59 | @deprecated = deprecated 60 | @local = local 61 | @optional = optional 62 | @original_name = original_name 63 | @source = source 64 | end 65 | 66 | def eql?(other) 67 | FIELDS.all? { |f| public_send(f) == other.public_send(f) } 68 | end 69 | alias == eql? 70 | 71 | def [](key) 72 | public_send(key) 73 | end 74 | 75 | def to_h 76 | FIELDS.to_h { |f| [f, public_send(f)] } 77 | end 78 | 79 | def hash 80 | FIELDS.map { |f| public_send(f) }.hash 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/bibliothecary/exceptions.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | class RemoteParsingError < StandardError 5 | attr_accessor :code 6 | 7 | def initialize(msg, code) 8 | @code = code 9 | super(msg) 10 | end 11 | end 12 | 13 | class FileParsingError < StandardError 14 | attr_accessor :filename, :location 15 | 16 | def initialize(msg, filename, location = nil) 17 | @filename = filename 18 | @location = location # source code location of the error, e.g. "lib/hi.rb:34" 19 | msg = "#{filename}: #{msg}" unless msg.include?(filename) 20 | super(msg.to_s) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/bibliothecary/file_info.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "pathname" 4 | 5 | module Bibliothecary 6 | # A representation of a file on the filesystem, with location information 7 | # and package manager information if needed. 8 | class FileInfo 9 | attr_reader :folder_path, :relative_path, :full_path 10 | attr_accessor :package_manager 11 | 12 | def contents 13 | @contents ||= 14 | if @folder_path.nil? 15 | # if we have no folder_path then we aren't dealing with a 16 | # file that's actually on the filesystem 17 | nil 18 | else 19 | Bibliothecary.utf8_string(File.read(@full_path)) 20 | end 21 | end 22 | 23 | # If the FileInfo represents an actual file on disk, 24 | # the contents can be nil and lazy-loaded; we allow 25 | # contents to be passed in here to allow pulling them 26 | # from somewhere other than the disk. 27 | def initialize(folder_path, full_path, contents = nil) 28 | # Note that cleanpath does NOT touch the filesystem, 29 | # leaving the lazy-load of file contents as the only 30 | # time we touch the filesystem. 31 | 32 | full_pathname = Pathname.new(full_path) 33 | @full_path = full_pathname.cleanpath.to_path 34 | 35 | if folder_path.nil? 36 | # this is the case where we e.g. have filenames from the GitHub API 37 | # and don't have a local folder 38 | @folder_path = nil 39 | @relative_path = @full_path 40 | else 41 | folder_pathname = Pathname.new(folder_path) 42 | @folder_path = folder_pathname.cleanpath.to_path 43 | @relative_path = full_pathname.relative_path_from(folder_pathname).cleanpath.to_path 44 | end 45 | 46 | @contents = contents 47 | 48 | @package_manager = nil 49 | end 50 | 51 | def groupable? 52 | @package_manager&.groupable?(self) 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/bibliothecary/multi_parsers/bundler_like_manifest.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | module MultiParsers 5 | module BundlerLikeManifest 6 | # this takes parsed Bundler and Bundler-like (CocoaPods) 7 | # manifests and turns them into a list of dependencies. 8 | def parse_ruby_manifest(manifest, source = nil) 9 | manifest.dependencies.inject([]) do |deps, dep| 10 | deps.push(Dependency.new( 11 | name: dep.name, 12 | requirement: dep 13 | .requirement 14 | .requirements 15 | .sort_by(&:last) 16 | .map { |op, version| "#{op} #{version}" } 17 | .join(", "), 18 | type: dep.type.to_s, 19 | source: source 20 | )) 21 | end.uniq 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/bibliothecary/multi_parsers/json_runtime.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | module MultiParsers 5 | # Provide JSON Runtime Manifest parsing 6 | module JSONRuntime 7 | def parse_json_runtime_manifest(file_contents, options: {}) 8 | JSON.parse(file_contents).fetch("dependencies", []).map do |name, requirement| 9 | Dependency.new( 10 | name: name, 11 | requirement: requirement, 12 | type: "runtime", 13 | source: options.fetch(:filename, nil) 14 | ) 15 | end 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/bower.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class Bower 8 | include Bibliothecary::Analyser 9 | 10 | def self.mapping 11 | { 12 | match_filename("bower.json") => { 13 | kind: "manifest", 14 | parser: :parse_manifest, 15 | }, 16 | } 17 | end 18 | 19 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 20 | 21 | def self.parse_manifest(file_contents, options: {}) 22 | json = JSON.parse(file_contents) 23 | map_dependencies(json, "dependencies", "runtime", options.fetch(:filename, nil)) + 24 | map_dependencies(json, "devDependencies", "development", options.fetch(:filename, nil)) 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/cargo.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | module Parsers 5 | class Cargo 6 | include Bibliothecary::Analyser 7 | 8 | def self.mapping 9 | { 10 | match_filename("Cargo.toml") => { 11 | kind: "manifest", 12 | parser: :parse_manifest, 13 | }, 14 | match_filename("Cargo.lock") => { 15 | kind: "lockfile", 16 | parser: :parse_lockfile, 17 | }, 18 | } 19 | end 20 | 21 | add_multi_parser(Bibliothecary::MultiParsers::CycloneDX) 22 | add_multi_parser(Bibliothecary::MultiParsers::Spdx) 23 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 24 | 25 | def self.parse_manifest(file_contents, options: {}) 26 | manifest = Tomlrb.parse(file_contents) 27 | 28 | parsed_dependencies = [] 29 | 30 | manifest.fetch_values("dependencies", "dev-dependencies").each_with_index do |deps, index| 31 | parsed_dependencies << deps.map do |name, requirement| 32 | if requirement.respond_to?(:fetch) 33 | requirement = requirement["version"] or next 34 | end 35 | 36 | Dependency.new( 37 | name: name, 38 | requirement: requirement, 39 | type: index.zero? ? "runtime" : "development", 40 | source: options.fetch(:filename, nil) 41 | ) 42 | end 43 | end 44 | 45 | parsed_dependencies.flatten.compact 46 | end 47 | 48 | def self.parse_lockfile(file_contents, options: {}) 49 | manifest = Tomlrb.parse(file_contents) 50 | manifest.fetch("package", []).map do |dependency| 51 | next if !dependency["source"] || !dependency["source"].start_with?("registry+") 52 | 53 | Dependency.new( 54 | name: dependency["name"], 55 | requirement: dependency["version"], 56 | type: "runtime", 57 | source: options.fetch(:filename, nil) 58 | ) 59 | end 60 | .compact 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/cocoapods.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "gemnasium/parser" 4 | require "yaml" 5 | 6 | module Bibliothecary 7 | module Parsers 8 | class CocoaPods 9 | include Bibliothecary::Analyser 10 | extend Bibliothecary::MultiParsers::BundlerLikeManifest 11 | 12 | NAME_VERSION = '(?! )(.*?)(?: \(([^-]*)(?:-(.*))?\))?' 13 | NAME_VERSION_4 = /^ {4}#{NAME_VERSION}$/ 14 | 15 | def self.mapping 16 | { 17 | match_filename("Podfile") => { 18 | kind: "manifest", 19 | parser: :parse_podfile, 20 | }, 21 | match_extension(".podspec") => { 22 | kind: "manifest", 23 | parser: :parse_podspec, 24 | can_have_lockfile: false, 25 | }, 26 | match_filename("Podfile.lock") => { 27 | kind: "lockfile", 28 | parser: :parse_podfile_lock, 29 | }, 30 | match_extension(".podspec.json") => { 31 | kind: "manifest", 32 | parser: :parse_json_manifest, 33 | can_have_lockfile: false, 34 | }, 35 | } 36 | end 37 | 38 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 39 | 40 | def self.parse_podfile_lock(file_contents, options: {}) 41 | manifest = YAML.load file_contents 42 | manifest["PODS"].map do |row| 43 | pod = row.is_a?(String) ? row : row.keys.first 44 | match = pod.match(/(.+?)\s\((.+?)\)/i) 45 | Dependency.new( 46 | name: match[1].split("/").first, 47 | requirement: match[2], 48 | type: "runtime", 49 | source: options.fetch(:filename, nil) 50 | ) 51 | end.compact 52 | end 53 | 54 | def self.parse_podspec(file_contents, options: {}) 55 | manifest = Gemnasium::Parser.send(:podspec, file_contents) 56 | parse_ruby_manifest(manifest, options.fetch(:filename, nil)) 57 | end 58 | 59 | def self.parse_podfile(file_contents, options: {}) 60 | manifest = Gemnasium::Parser.send(:podfile, file_contents) 61 | parse_ruby_manifest(manifest, options.fetch(:filename, nil)) 62 | end 63 | 64 | def self.parse_json_manifest(file_contents, options: {}) 65 | manifest = JSON.parse(file_contents) 66 | manifest["dependencies"].inject([]) do |deps, dep| 67 | deps.push(Dependency.new( 68 | name: dep[0], 69 | requirement: dep[1], 70 | type: "runtime", 71 | source: options.fetch(:filename, nil) 72 | )) 73 | end.uniq 74 | end 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/conda.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "yaml" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class Conda 8 | include Bibliothecary::Analyser 9 | 10 | def self.mapping 11 | { 12 | match_filename("environment.yml") => { 13 | parser: :parse_conda, 14 | kind: "manifest", 15 | }, 16 | match_filename("environment.yaml") => { 17 | parser: :parse_conda, 18 | kind: "manifest", 19 | }, 20 | } 21 | end 22 | 23 | add_multi_parser(Bibliothecary::MultiParsers::CycloneDX) 24 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 25 | add_multi_parser(Bibliothecary::MultiParsers::Spdx) 26 | 27 | def self.parse_conda(file_contents, options: {}) 28 | manifest = YAML.load(file_contents) 29 | deps = manifest["dependencies"] 30 | deps.map do |dep| 31 | next unless dep.is_a? String # only deal with strings to skip parsing pip stuff 32 | 33 | parsed = parse_name_requirement_from_matchspec(dep) 34 | Dependency.new(**parsed, type: "runtime", source: options.fetch(:filename, nil)) 35 | end.compact 36 | end 37 | 38 | def self.parse_name_requirement_from_matchspec(matchspec) 39 | # simplified version of the implementation in conda to handle what we care about 40 | # https://github.com/conda/conda/blob/main/conda/models/match_spec.py#L598 41 | # (channel(/subdir):(namespace):)name(version(build))[key1=value1,key2=value2] 42 | return if matchspec.end_with?("@") 43 | 44 | # strip off comments and optional features 45 | matchspec = matchspec.split("#", 2).first 46 | matchspec = matchspec.split(" if ", 2).first 47 | 48 | # strip off brackets 49 | matchspec = matchspec.match(/^(.*)(?:\[(.*)\])?$/)[1] 50 | 51 | # strip off any parens 52 | matchspec = matchspec.match(/^(.*)(?:(\(.*\)))?$/)[1] 53 | 54 | # deal with channel and namespace, I wish there was rsplit in ruby 55 | split = matchspec.reverse.split(":", 2) 56 | matchspec = split.last.reverse 57 | 58 | # split the name from the version/build combo 59 | matches = matchspec.match(/([^ =<>!~]+)?([>~])(?:[ =])([^-=,|<>~]+?))?$/) 68 | version = if matches 69 | matches[1].strip 70 | else 71 | version_build.strip 72 | end 73 | end 74 | # if it's an exact requirement, lose the = 75 | if version&.start_with?("==") 76 | version = version[2..] 77 | elsif version&.start_with?("=") 78 | version = version[1..] 79 | end 80 | 81 | { 82 | name: name, 83 | requirement: version || "", # NOTE: this ignores build info 84 | } 85 | end 86 | end 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/cpan.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "yaml" 4 | require "json" 5 | 6 | module Bibliothecary 7 | module Parsers 8 | class CPAN 9 | include Bibliothecary::Analyser 10 | 11 | def self.mapping 12 | { 13 | match_filename("META.json", case_insensitive: true) => { 14 | kind: "manifest", 15 | parser: :parse_json_manifest, 16 | }, 17 | match_filename("META.yml", case_insensitive: true) => { 18 | kind: "manifest", 19 | parser: :parse_yaml_manifest, 20 | }, 21 | } 22 | end 23 | 24 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 25 | 26 | def self.parse_json_manifest(file_contents, options: {}) 27 | manifest = JSON.parse file_contents 28 | manifest["prereqs"].map do |_group, deps| 29 | map_dependencies(deps, "requires", "runtime", options.fetch(:filename, nil)) 30 | end.flatten 31 | end 32 | 33 | def self.parse_yaml_manifest(file_contents, options: {}) 34 | manifest = YAML.load file_contents 35 | map_dependencies(manifest, "requires", "runtime", options.fetch(:filename, nil)) 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/cran.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "deb_control" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class CRAN 8 | include Bibliothecary::Analyser 9 | 10 | REQUIRE_REGEXP = /([a-zA-Z0-9\-_\.]+)\s?\(?([><=\s\d\.,]+)?\)?/ 11 | 12 | def self.mapping 13 | { 14 | match_filename("DESCRIPTION", case_insensitive: true) => { 15 | kind: "manifest", 16 | parser: :parse_description, 17 | }, 18 | } 19 | end 20 | 21 | add_multi_parser(Bibliothecary::MultiParsers::CycloneDX) 22 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 23 | add_multi_parser(Bibliothecary::MultiParsers::Spdx) 24 | 25 | def self.parse_description(file_contents, options: {}) 26 | manifest = DebControl::ControlFileBase.parse(file_contents) 27 | parse_section(manifest, "Depends", options.fetch(:filename, nil)) + 28 | parse_section(manifest, "Imports", options.fetch(:filename, nil)) + 29 | parse_section(manifest, "Suggests", options.fetch(:filename, nil)) + 30 | parse_section(manifest, "Enhances", options.fetch(:filename, nil)) 31 | end 32 | 33 | def self.parse_section(manifest, name, source = nil) 34 | return [] unless manifest.first[name] 35 | 36 | deps = manifest.first[name].delete("\n").split(",").map(&:strip) 37 | deps.map do |dependency| 38 | dep = dependency.match(REQUIRE_REGEXP) 39 | Dependency.new( 40 | name: dep[1], 41 | requirement: dep[2], 42 | type: name.downcase, 43 | source: source 44 | ) 45 | end 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/dub.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | require "sdl_parser" 5 | 6 | module Bibliothecary 7 | module Parsers 8 | class Dub 9 | include Bibliothecary::Analyser 10 | extend Bibliothecary::MultiParsers::JSONRuntime 11 | 12 | def self.mapping 13 | { 14 | match_filename("dub.json") => { 15 | kind: "manifest", 16 | parser: :parse_json_runtime_manifest, 17 | }, 18 | match_filename("dub.sdl") => { 19 | kind: "manifest", 20 | parser: :parse_sdl_manifest, 21 | }, 22 | } 23 | end 24 | 25 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 26 | 27 | def self.parse_sdl_manifest(file_contents, options: {}) 28 | SdlParser.new(:runtime, file_contents, options.fetch(:filename, nil)).dependencies 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/elm.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class Elm 8 | include Bibliothecary::Analyser 9 | extend Bibliothecary::MultiParsers::JSONRuntime 10 | 11 | def self.mapping 12 | { 13 | match_filenames("elm-package.json", "elm_dependencies.json") => { 14 | kind: "manifest", 15 | parser: :parse_json_runtime_manifest, 16 | }, 17 | match_filename("elm-stuff/exact-dependencies.json") => { 18 | kind: "lockfile", 19 | parser: :parse_json_lock, 20 | }, 21 | } 22 | end 23 | 24 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 25 | 26 | def self.parse_json_lock(file_contents, options: {}) 27 | manifest = JSON.parse file_contents 28 | manifest.map do |name, requirement| 29 | Dependency.new( 30 | name: name, 31 | requirement: requirement, 32 | type: "runtime", 33 | source: options.fetch(:filename, nil) 34 | ) 35 | end 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/haxelib.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class Haxelib 8 | include Bibliothecary::Analyser 9 | extend Bibliothecary::MultiParsers::JSONRuntime 10 | 11 | def self.mapping 12 | { 13 | match_filename("haxelib.json") => { 14 | kind: "manifest", 15 | parser: :parse_json_runtime_manifest, 16 | }, 17 | } 18 | end 19 | 20 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/julia.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | module Parsers 5 | class Julia 6 | include Bibliothecary::Analyser 7 | 8 | def self.mapping 9 | { 10 | match_filename("REQUIRE", case_insensitive: true) => { 11 | kind: "manifest", 12 | parser: :parse_require, 13 | }, 14 | } 15 | end 16 | 17 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 18 | 19 | def self.parse_require(file_contents, options: {}) 20 | deps = [] 21 | file_contents.split("\n").each do |line| 22 | next if line.match(/^#/) || line.empty? 23 | 24 | split = line.split(/\s/) 25 | if line.match(/^@/) 26 | name = split[1] 27 | reqs = split[2, split.length].join(" ") 28 | else 29 | name = split[0] 30 | reqs = split[1, split.length].join(" ") 31 | end 32 | reqs = "*" if reqs.empty? 33 | next if name.empty? 34 | 35 | deps << Dependency.new( 36 | name: name, 37 | requirement: reqs, 38 | type: "runtime", 39 | source: options.fetch(:filename, nil) 40 | ) 41 | end 42 | deps 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/meteor.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class Meteor 8 | include Bibliothecary::Analyser 9 | extend Bibliothecary::MultiParsers::JSONRuntime 10 | 11 | def self.mapping 12 | { 13 | match_filename("versions.json") => { 14 | kind: "manifest", 15 | parser: :parse_json_runtime_manifest, 16 | }, 17 | } 18 | end 19 | 20 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/packagist.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class Packagist 8 | include Bibliothecary::Analyser 9 | 10 | def self.mapping 11 | { 12 | match_filename("composer.json") => { 13 | kind: "manifest", 14 | parser: :parse_manifest, 15 | }, 16 | match_filename("composer.lock") => { 17 | kind: "lockfile", 18 | parser: :parse_lockfile, 19 | }, 20 | } 21 | end 22 | 23 | add_multi_parser(Bibliothecary::MultiParsers::CycloneDX) 24 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 25 | add_multi_parser(Bibliothecary::MultiParsers::Spdx) 26 | 27 | def self.parse_lockfile(file_contents, options: {}) 28 | manifest = JSON.parse file_contents 29 | manifest.fetch("packages", []).map do |dependency| 30 | requirement = dependency["version"] 31 | 32 | # Store Drupal version if Drupal, but include the original manifest version for reference 33 | if drupal_module?(dependency) 34 | original_requirement = requirement 35 | requirement = dependency.dig("source", "reference") 36 | end 37 | 38 | Dependency.new( 39 | name: dependency["name"], 40 | requirement: requirement, 41 | type: "runtime", 42 | original_requirement: original_requirement, 43 | source: options.fetch(:filename, nil) 44 | ) 45 | end + manifest.fetch("packages-dev", []).map do |dependency| 46 | requirement = dependency["version"] 47 | 48 | # Store Drupal version if Drupal, but include the original manifest version for reference 49 | if drupal_module?(dependency) 50 | original_requirement = requirement 51 | requirement = dependency.dig("source", "reference") 52 | end 53 | 54 | Dependency.new( 55 | name: dependency["name"], 56 | requirement: requirement, 57 | type: "development", 58 | original_requirement: original_requirement, 59 | source: options.fetch(:filename, nil) 60 | ) 61 | end 62 | end 63 | 64 | def self.parse_manifest(file_contents, options: {}) 65 | manifest = JSON.parse file_contents 66 | map_dependencies(manifest, "require", "runtime", options.fetch(:filename, nil)) + 67 | map_dependencies(manifest, "require-dev", "development", options.fetch(:filename, nil)) 68 | end 69 | 70 | # Drupal hosts its own Composer repository, where its "modules" are indexed and searchable. The best way to 71 | # confirm that Drupal's repo is being used is if its in the "repositories" in composer.json 72 | # (https://support.acquia.com/hc/en-us/articles/360048081273-Using-Composer-to-manage-dependencies-in-Drupal-8-and-9), 73 | # but you may only have composer.lock, so we test if the type is "drupal-*" (e.g. "drupal-module" or "drupal-theme") 74 | # The Drupal team also setup its own mapper of Composer semver -> Drupal tool-specfic versions 75 | # (https://www.drupal.org/project/project_composer/issues/2622450), 76 | # so we return the Drupal requirement instead of semver requirement if it's here 77 | # (https://www.drupal.org/docs/develop/using-composer/using-composer-to-install-drupal-and-manage-dependencies#s-about-semantic-versioning) 78 | private_class_method def self.drupal_module?(dependency) 79 | dependency["type"] =~ /drupal/ && dependency.dig("source", "reference") 80 | end 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/pub.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "yaml" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class Pub 8 | include Bibliothecary::Analyser 9 | 10 | def self.mapping 11 | { 12 | match_filename("pubspec.yaml", case_insensitive: true) => { 13 | kind: "manifest", 14 | parser: :parse_yaml_manifest, 15 | }, 16 | match_filename("pubspec.lock", case_insensitive: true) => { 17 | kind: "lockfile", 18 | parser: :parse_yaml_lockfile, 19 | }, 20 | } 21 | end 22 | 23 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 24 | 25 | def self.parse_yaml_manifest(file_contents, options: {}) 26 | manifest = YAML.load file_contents 27 | map_dependencies(manifest, "dependencies", "runtime", options.fetch(:filename, nil)) + 28 | map_dependencies(manifest, "dev_dependencies", "development", options.fetch(:filename, nil)) 29 | end 30 | 31 | def self.parse_yaml_lockfile(file_contents, options: {}) 32 | manifest = YAML.load file_contents 33 | manifest.fetch("packages", []).map do |name, dep| 34 | Dependency.new( 35 | name: name, 36 | requirement: dep["version"], 37 | type: "runtime", 38 | source: options.fetch(:filename, nil) 39 | ) 40 | end 41 | end 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/rubygems.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "gemnasium/parser" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class Rubygems 8 | include Bibliothecary::Analyser 9 | extend Bibliothecary::MultiParsers::BundlerLikeManifest 10 | 11 | NAME_VERSION = '(?! )(.*?)(?: \(([^-]*)(?:-(.*))?\))?' 12 | NAME_VERSION_4 = /^ {4}#{NAME_VERSION}$/ 13 | BUNDLED_WITH = /BUNDLED WITH/ 14 | 15 | def self.mapping 16 | { 17 | match_filenames("Gemfile", "gems.rb") => { 18 | kind: "manifest", 19 | parser: :parse_gemfile, 20 | related_to: %w[manifest lockfile], 21 | }, 22 | match_extension(".gemspec") => { 23 | kind: "manifest", 24 | parser: :parse_gemspec, 25 | related_to: %w[manifest lockfile], 26 | }, 27 | match_filenames("Gemfile.lock", "gems.locked") => { 28 | kind: "lockfile", 29 | parser: :parse_gemfile_lock, 30 | related_to: %w[manifest lockfile], 31 | }, 32 | } 33 | end 34 | 35 | add_multi_parser(Bibliothecary::MultiParsers::CycloneDX) 36 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 37 | add_multi_parser(Bibliothecary::MultiParsers::Spdx) 38 | 39 | def self.parse_gemfile_lock(file_contents, options: {}) 40 | file_contents.lines(chomp: true).map do |line| 41 | match = line.match(NAME_VERSION_4) 42 | bundler_match = line.match(BUNDLED_WITH) 43 | next unless match || bundler_match 44 | 45 | if match 46 | name = match[1] 47 | version = match[2].gsub(/\(|\)/, "") 48 | Dependency.new( 49 | name: name, 50 | requirement: version, 51 | type: "runtime", 52 | source: options.fetch(:filename, nil) 53 | ) 54 | else 55 | parse_bundler(file_contents, options.fetch(:filename, nil)) 56 | end 57 | end.compact 58 | end 59 | 60 | def self.parse_gemfile(file_contents, options: {}) 61 | manifest = Gemnasium::Parser.send(:gemfile, file_contents) 62 | parse_ruby_manifest(manifest, options.fetch(:filename, nil)) 63 | end 64 | 65 | def self.parse_gemspec(file_contents, options: {}) 66 | manifest = Gemnasium::Parser.send(:gemspec, file_contents) 67 | parse_ruby_manifest(manifest, options.fetch(:filename, nil)) 68 | end 69 | 70 | def self.parse_bundler(file_contents, source = nil) 71 | bundled_with_index = file_contents.lines(chomp: true).find_index { |line| line.match(BUNDLED_WITH) } 72 | version = file_contents.lines(chomp: true).fetch(bundled_with_index + 1)&.strip 73 | 74 | return nil unless version 75 | 76 | Dependency.new( 77 | name: "bundler", 78 | requirement: version, 79 | type: "runtime", 80 | source: source 81 | ) 82 | end 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /lib/bibliothecary/parsers/shard.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "yaml" 4 | 5 | module Bibliothecary 6 | module Parsers 7 | class Shard 8 | include Bibliothecary::Analyser 9 | 10 | def self.mapping 11 | { 12 | match_filename("shard.yml", case_insensitive: true) => { 13 | kind: "manifest", 14 | parser: :parse_yaml_manifest, 15 | }, 16 | match_filename("shard.lock", case_insensitive: true) => { 17 | kind: "lockfile", 18 | parser: :parse_yaml_lockfile, 19 | }, 20 | } 21 | end 22 | 23 | add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV) 24 | 25 | def self.parse_yaml_lockfile(file_contents, options: {}) 26 | manifest = YAML.load file_contents 27 | map_dependencies(manifest, "shards", "runtime", options.fetch(:filename, nil)) 28 | end 29 | 30 | def self.parse_yaml_manifest(file_contents, options: {}) 31 | manifest = YAML.load file_contents 32 | map_dependencies(manifest, "dependencies", "runtime", options.fetch(:filename, nil)) + 33 | map_dependencies(manifest, "development_dependencies", "runtime", options.fetch(:filename, nil)) 34 | end 35 | 36 | def self.map_dependencies(hash, key, type, source = nil) 37 | hash.fetch(key, []).map do |name, requirement| 38 | Dependency.new( 39 | name: name, 40 | requirement: requirement["version"], 41 | type: type, 42 | source: source 43 | ) 44 | end 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/bibliothecary/purl_util.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | class PurlUtil 5 | # If a purl type (key) exists, it will be used in a manifest for 6 | # the key's value. If not, it's ignored. 7 | # 8 | # https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst 9 | PURL_TYPE_MAPPING = { 10 | "golang" => :go, 11 | "maven" => :maven, 12 | "npm" => :npm, 13 | "cargo" => :cargo, 14 | "composer" => :packagist, 15 | "conda" => :conda, 16 | "cran" => :cran, 17 | "gem" => :rubygems, 18 | "nuget" => :nuget, 19 | "pypi" => :pypi, 20 | }.freeze 21 | 22 | # @param purl [PackageURL] 23 | # @return [String] The properly namespaced package name 24 | def self.full_name(purl) 25 | return nil if purl.nil? 26 | 27 | parts = [purl.namespace, purl.name].compact 28 | 29 | case purl.type 30 | when "maven" 31 | parts.join(":") 32 | else 33 | parts.join("/") 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/bibliothecary/related_files_info.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | class RelatedFilesInfo 5 | attr_reader :path, :platform, :manifests, :lockfiles 6 | 7 | # Create a set of RelatedFilesInfo for the provided file_infos, 8 | # where each RelatedFilesInfo contains all the file_infos 9 | def self.create_from_file_infos(file_infos) 10 | returns = [] 11 | 12 | file_infos_by_directory = file_infos.group_by { |info| File.dirname(info.relative_path) } 13 | file_infos_by_directory.each_value do |file_infos_for_path| 14 | groupable, ungroupable = file_infos_for_path.partition(&:groupable?) 15 | 16 | # add ungroupable ones as separate RFIs 17 | ungroupable.each do |file_info| 18 | returns.append(RelatedFilesInfo.new([file_info])) 19 | end 20 | 21 | file_infos_by_directory_by_package_manager = groupable.group_by(&:package_manager) 22 | 23 | file_infos_by_directory_by_package_manager.each_value do |file_infos_in_directory_for_package_manager| 24 | returns.append(RelatedFilesInfo.new(file_infos_in_directory_for_package_manager)) 25 | end 26 | end 27 | 28 | returns 29 | end 30 | 31 | def initialize(file_infos) 32 | package_manager = file_infos.first.package_manager 33 | ordered_file_infos = file_infos 34 | 35 | if package_manager.respond_to?(:lockfile_preference_order) 36 | ordered_file_infos = package_manager.lockfile_preference_order(file_infos) 37 | end 38 | 39 | @platform = package_manager.platform_name 40 | @path = Pathname.new(File.dirname(file_infos.first.relative_path)).cleanpath.to_path 41 | 42 | @manifests = filter_file_infos_by_package_manager_type( 43 | file_infos: ordered_file_infos, 44 | package_manager: package_manager, 45 | type: "manifest" 46 | ) 47 | 48 | @lockfiles = filter_file_infos_by_package_manager_type( 49 | file_infos: ordered_file_infos, 50 | package_manager: package_manager, 51 | type: "lockfile" 52 | ) 53 | end 54 | 55 | private 56 | 57 | def filter_file_infos_by_package_manager_type(file_infos:, package_manager:, type:) 58 | # `package_manager.determine_kind_from_info(info)` can be an Array, so use include? which also works for string 59 | file_infos.select { |info| package_manager.determine_kind_from_info(info).include?(type) }.map(&:relative_path) 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/bibliothecary/runner/multi_manifest_filter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | class Runner 5 | class MultiManifestFilter 6 | # Wrap up a file analysis for easier validity testing 7 | class FileAnalysis 8 | def initialize(file_analysis) 9 | @file_analysis = file_analysis 10 | end 11 | 12 | # Determine if we should skip this file analysis when processing 13 | # @return [Boolean] True if we should skip processing 14 | def skip? 15 | !@file_analysis || 16 | !@file_analysis[:dependencies] || 17 | @file_analysis[:dependencies].empty? 18 | end 19 | end 20 | 21 | def initialize(path:, related_files_info_entries:, runner:) 22 | @path = path 23 | @related_files_info_entries = related_files_info_entries 24 | @runner = runner 25 | end 26 | 27 | # Standalone multi manifest files should *always* be treated as lockfiles, 28 | # since there's no human-written manifest file to go with them. 29 | def files_to_check 30 | @files_to_check ||= @related_files_info_entries.each_with_object({}) do |files_info, all| 31 | files_info.lockfiles.each do |file| 32 | all[file] ||= 0 33 | all[file] += 1 34 | end 35 | end 36 | end 37 | 38 | def results 39 | partition_file_entries! 40 | 41 | (no_lockfile_results + single_file_results + multiple_file_results).uniq 42 | end 43 | 44 | def no_lockfile_results 45 | @no_lockfile_results ||= @related_files_info_entries.find_all { |rfi| rfi.lockfiles.empty? } 46 | end 47 | 48 | def single_file_results 49 | @single_file_results ||= @single_file_entries.map do |file| 50 | @related_files_info_entries.find { |rfi| rfi.lockfiles.include?(file) } 51 | end 52 | end 53 | 54 | def multiple_file_results 55 | return @multiple_file_results if @multiple_file_results 56 | 57 | @multiple_file_results = [] 58 | 59 | each_analysis_and_rfis do |analysis, rfis_for_file| 60 | rfis_for_file.each do |rfi| 61 | file_analysis = FileAnalysis.new( 62 | analysis.find { |a| a[:platform] == rfi.platform } 63 | ) 64 | 65 | next if file_analysis.skip? 66 | 67 | @multiple_file_results << rfi 68 | end 69 | end 70 | 71 | @multiple_file_results 72 | end 73 | 74 | def each_analysis_and_rfis 75 | @multiple_file_entries.each do |file| 76 | contents = Bibliothecary.utf8_string(File.read(File.join(@path, file))) 77 | analysis = @runner.analyse_file(file, contents) 78 | rfis_for_file = @related_files_info_entries.find_all { |rfi| rfi.lockfiles.include?(file) } 79 | 80 | yield analysis, rfis_for_file 81 | end 82 | end 83 | 84 | def partition_file_entries! 85 | @single_file_entries, @multiple_file_entries = files_to_check.partition { |_file, count| count == 1 } 86 | 87 | @single_file_entries = @single_file_entries.map(&:first) 88 | @multiple_file_entries = @multiple_file_entries.map(&:first) 89 | end 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /lib/bibliothecary/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bibliothecary 4 | VERSION = "12.2.0" 5 | end 6 | -------------------------------------------------------------------------------- /lib/sdl_parser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "sdl4r" 4 | 5 | class SdlParser 6 | attr_reader :contents, :type 7 | 8 | def initialize(type, contents, source = nil) 9 | @contents = contents 10 | @type = type || "runtime" 11 | @source = source 12 | end 13 | 14 | def dependencies 15 | parse.children("dependency").inject([]) do |deps, dep| 16 | deps.push(Bibliothecary::Dependency.new( 17 | name: dep.value, 18 | requirement: dep.attribute("version") || ">= 0", 19 | type: type, 20 | source: @source 21 | )) 22 | end.uniq 23 | end 24 | 25 | def parse 26 | SDL4R.read(contents) 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/bibliothecary/configuration_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Configuration do 6 | let(:config) { described_class.new } 7 | 8 | it "should have a default list of ignored dirs" do 9 | expect(config.ignored_dirs).to eq([".git", "node_modules", "bower_components", "vendor", "dist"]) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/bibliothecary/dependency_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Dependency do 6 | describe "#new" do 7 | it "sets all properties" do 8 | dep = described_class.new( 9 | name: "foo", 10 | requirement: "1.0.0", 11 | platform: "maven", 12 | type: "runtime", 13 | direct: true, 14 | deprecated: true, 15 | local: true, 16 | optional: true, 17 | original_name: "foo-alias", 18 | original_requirement: "1.0.0.rc1", 19 | source: "package.json" 20 | ) 21 | 22 | expect(dep.name).to eq("foo") 23 | expect(dep.requirement).to eq("1.0.0") 24 | expect(dep.platform).to eq("maven") 25 | expect(dep.type).to eq("runtime") 26 | expect(dep.direct).to eq(true) 27 | expect(dep.deprecated).to eq(true) 28 | expect(dep.local).to eq(true) 29 | expect(dep.optional).to eq(true) 30 | expect(dep.original_name).to eq("foo-alias") 31 | expect(dep.original_requirement).to eq("1.0.0.rc1") 32 | expect(dep.source).to eq("package.json") 33 | end 34 | 35 | it "only requires name and requirement" do 36 | expect { subject.new }.to raise_error(ArgumentError, "missing keywords: :name, :requirement") 37 | end 38 | 39 | it "can check equality" do 40 | dep = Bibliothecary::Dependency.new(name: "foo", requirement: "1.0.0") 41 | 42 | expect(dep).to eq(Bibliothecary::Dependency.new(name: "foo", requirement: "1.0.0")) 43 | expect(dep).to_not eq(Bibliothecary::Dependency.new(name: "foo", requirement: "2.0.0")) 44 | end 45 | 46 | it "can be deduped" do 47 | dep1 = Bibliothecary::Dependency.new(name: "foo", requirement: "1.0.0") 48 | dep2 = Bibliothecary::Dependency.new(name: "foo", requirement: "2.0.0") 49 | dep3 = Bibliothecary::Dependency.new(name: "foo", requirement: "2.0.0") 50 | 51 | expect([dep1, dep2, dep3].uniq).to eq([dep1, dep2]) 52 | end 53 | 54 | it "can be serialized with to_h" do 55 | attrs = { 56 | name: "foo", 57 | requirement: "1.0.0", 58 | platform: "maven", 59 | type: "runtime", 60 | direct: true, 61 | deprecated: true, 62 | local: true, 63 | optional: true, 64 | original_name: "foo-alias", 65 | original_requirement: "1.0.0.rc1", 66 | source: "package.json", 67 | } 68 | 69 | dep = described_class.new(**attrs) 70 | 71 | expect(dep.to_h).to eq(attrs) 72 | end 73 | 74 | it "sets empty requirement to wildcard" do 75 | dependency = described_class.new(name: "foo", requirement: nil) 76 | expect(dependency.requirement).to eq("*") 77 | end 78 | 79 | it "can be read like a hash" do 80 | dependency = described_class.new(name: "foo", requirement: nil) 81 | expect(dependency[:name]).to eq("foo") 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /spec/bibliothecary/file_info_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::FileInfo do 6 | describe "#ungroupable?" do 7 | let(:file_info) { described_class.new(folder_path, full_path, contents) } 8 | let(:folder_path) { "spec/fixtures" } 9 | let(:contents) { nil } 10 | 11 | subject { file_info.groupable? } 12 | 13 | context "ungroupable" do 14 | let(:full_path) { "spec/fixtures/dependencies.csv" } 15 | 16 | it "determines if file is groupable" do 17 | file_info.package_manager = Bibliothecary::Parsers::NPM 18 | expect(subject).to eq(false) 19 | end 20 | end 21 | 22 | context "groupable" do 23 | let(:full_path) { "spec/fixtures/package.json" } 24 | 25 | it "determines if file is groupable" do 26 | file_info.package_manager = Bibliothecary::Parsers::NPM 27 | expect(subject).to eq(true) 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/bibliothecary/multi_manifest_filter_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Runner::MultiManifestFilter do 6 | describe Bibliothecary::Runner::MultiManifestFilter::FileAnalysis do 7 | describe "#skip?" do 8 | it "skips correctly" do 9 | expect(described_class.new(nil).skip?).to eq(true) 10 | expect(described_class.new({ cat: "dog" }).skip?).to eq(true) 11 | expect(described_class.new({ dependencies: nil }).skip?).to eq(true) 12 | expect(described_class.new({ dependencies: [] }).skip?).to eq(true) 13 | expect(described_class.new({ dependencies: [:cat] }).skip?).to eq(false) 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/bibliothecary/purl_util_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::PurlUtil do 6 | describe "full_name" do 7 | it "handles formats correctly" do 8 | maven_purl = PackageURL.parse("pkg:maven/cat/dog@1.2.3") 9 | expect(described_class.full_name(maven_purl)).to eq("cat:dog") 10 | 11 | npm_purl = PackageURL.parse("pkg:npm/cat/dog@1.2.3") 12 | expect(described_class.full_name(npm_purl)).to eq("cat/dog") 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/fixtures/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "update" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | local_crate = {path = "../local_crate"} 10 | rustc-serialize = "*" 11 | regex = {version = "*"} 12 | 13 | [dev-dependencies] 14 | tempdir = "0.3" 15 | -------------------------------------------------------------------------------- /spec/fixtures/Cartfile: -------------------------------------------------------------------------------- 1 | # Require version 2.3.1 or later 2 | github "ReactiveCocoa/ReactiveCocoa" >= 2.3.1 3 | 4 | # Require version 1.x 5 | github "Mantle/Mantle" ~> 1.0 # (1.0 or later, but less than 2.0) 6 | 7 | # Require exactly version 0.4.1 8 | github "jspahrsummers/libextobjc" == 0.4.1 9 | 10 | # Use the latest version 11 | github "jspahrsummers/xcconfigs" 12 | 13 | # Use the branch 14 | github "jspahrsummers/xcconfigs" "branch" 15 | 16 | # Use a project from GitHub Enterprise 17 | github "https://enterprise.local/ghe/desktop/git-error-translations" 18 | 19 | # Use a project from any arbitrary server, on the "development" branch 20 | git "https://enterprise.local/desktop/git-error-translations2.git" "development" 21 | 22 | # Use a local project 23 | git "file:///directory/to/project" "branch" 24 | -------------------------------------------------------------------------------- /spec/fixtures/Cartfile.private: -------------------------------------------------------------------------------- 1 | github "Quick/Quick" ~> 0.9 2 | github "Quick/Nimble" ~> 3.1 3 | github "jspahrsummers/xcconfigs" "ec5753493605deed7358dec5f9260f503d3ed650" 4 | -------------------------------------------------------------------------------- /spec/fixtures/Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "thoughtbot/Argo" "v2.2.0" 2 | github "Quick/Nimble" "v3.1.0" 3 | github "jdhealy/PrettyColors" "v3.0.0" 4 | github "Quick/Quick" "v0.9.1" 5 | github "antitypical/Result" "1.0.2" 6 | github "jspahrsummers/xcconfigs" "ec5753493605deed7358dec5f9260f503d3ed650" 7 | github "Carthage/Commandant" "0.8.3" 8 | github "ReactiveCocoa/ReactiveCocoa" "v4.0.1" 9 | github "Carthage/ReactiveTask" "0.9.1" 10 | -------------------------------------------------------------------------------- /spec/fixtures/DESCRIPTION2: -------------------------------------------------------------------------------- 1 | Package: data.table 2 | Version: 1.9.6 3 | Title: Extension of Data.frame 4 | Author: M Dowle, A Srinivasan, T Short, S Lianoglou with contributions from R Saporta, E Antonyan 5 | Maintainer: Matt Dowle 6 | Depends: R (>= 2.14.1) 7 | Imports: methods, chron 8 | Suggests: ggplot2 (>= 0.9.0), plyr, reshape, reshape2, testthat (>= 9 | 0.4), hexbin, fastmatch, nlme, xts, bit64, gdata, 10 | GenomicRanges, caret, knitr, curl, zoo, plm 11 | Description: Fast aggregation of large data (e.g. 100GB in RAM), fast ordered joins, fast add/modify/delete of columns by group using no copies at all, list columns and a fast file reader (fread). Offers a natural and flexible syntax, for faster development. 12 | License: GPL (>= 2) 13 | URL: https://github.com/Rdatatable/data.table/wiki 14 | BugReports: https://github.com/Rdatatable/data.table/issues 15 | MailingList: datatable-help@lists.r-forge.r-project.org 16 | VignetteBuilder: knitr 17 | ByteCompile: TRUE 18 | NeedsCompilation: yes 19 | Packaged: 2015-09-19 04:47:43.628 UTC; mdowle 20 | Repository: CRAN 21 | Date/Publication: 2015-09-19 22:13:43 22 | -------------------------------------------------------------------------------- /spec/fixtures/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | ruby "2.2.1" 3 | 4 | gem "oj" 5 | gem "rails", "4.2.0" 6 | gem "leveldb-ruby","0.15", require: "leveldb" 7 | 8 | group :development do 9 | gem "spring" 10 | gem "thin" 11 | end 12 | 13 | group :production do 14 | gem "puma" 15 | gem "rails_12factor" 16 | gem "bugsnag" 17 | end 18 | -------------------------------------------------------------------------------- /spec/fixtures/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (2.3.1) 5 | actionmailer (4.2.3) 6 | actionpack (= 4.2.3) 7 | actionview (= 4.2.3) 8 | activejob (= 4.2.3) 9 | mail (~> 2.5, >= 2.5.4) 10 | rails-dom-testing (~> 1.0, >= 1.0.5) 11 | googleauth (0.4.1) 12 | faraday (~> 0.9) 13 | jwt (~> 1.4) 14 | logging (~> 2.0) 15 | memoist (~> 0.12) 16 | multi_json (= 1.11) 17 | signet (~> 0.6) 18 | hashie (3.4.2) 19 | 20 | PLATFORMS 21 | ruby 22 | 23 | DEPENDENCIES 24 | bigquery 25 | bootstrap-sass 26 | bugsnag 27 | bundler 28 | coffee-rails 29 | counter_culture 30 | dalli 31 | dotenv-rails 32 | elasticsearch-model 33 | elasticsearch-rails 34 | faraday-http-cache 35 | fast_blank 36 | fast_xor 37 | fast_xs 38 | fog 39 | font-awesome-rails 40 | gemoji 41 | gems 42 | hiredis 43 | hirefire-resource 44 | jbuilder 45 | jquery-rails 46 | js-cookie-rails 47 | languages 48 | mime-types (~> 2.6.1) 49 | newrelic_rpm 50 | nokogiri 51 | octokit 52 | oj 53 | oj_mimic_json 54 | omniauth 55 | omniauth-github 56 | pg 57 | platform-api 58 | postgres_ext 59 | premailer-rails 60 | puma 61 | pushover 62 | rack-canonical-host 63 | rails (= 4.2.3) 64 | rails_12factor 65 | rails_safe_tasks 66 | rb-readline 67 | redis 68 | sanitize-url 69 | sass-rails 70 | sassc-rails 71 | semantic 72 | sidekiq 73 | simple-rss 74 | simple_form 75 | sinatra 76 | sitemap_generator 77 | spdx 78 | spring 79 | sprockets (~> 2.12) 80 | thin 81 | tipsy-rails 82 | turbolinks 83 | typhoeus 84 | uglifier 85 | will_paginate 86 | will_paginate-bootstrap 87 | 88 | -------------------------------------------------------------------------------- /spec/fixtures/GemfileLineEndings.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rails (5.2.3) 5 | -------------------------------------------------------------------------------- /spec/fixtures/GemfileWithBundler.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (2.3.1) 5 | actionmailer (4.2.3) 6 | actionpack (= 4.2.3) 7 | actionview (= 4.2.3) 8 | activejob (= 4.2.3) 9 | mail (~> 2.5, >= 2.5.4) 10 | rails-dom-testing (~> 1.0, >= 1.0.5) 11 | googleauth (0.4.1) 12 | faraday (~> 0.9) 13 | jwt (~> 1.4) 14 | logging (~> 2.0) 15 | memoist (~> 0.12) 16 | multi_json (= 1.11) 17 | signet (~> 0.6) 18 | hashie (3.4.2) 19 | 20 | PLATFORMS 21 | ruby 22 | 23 | DEPENDENCIES 24 | bigquery 25 | bootstrap-sass 26 | bugsnag 27 | bundler 28 | coffee-rails 29 | counter_culture 30 | dalli 31 | dotenv-rails 32 | elasticsearch-model 33 | elasticsearch-rails 34 | faraday-http-cache 35 | fast_blank 36 | fast_xor 37 | fast_xs 38 | fog 39 | font-awesome-rails 40 | gemoji 41 | gems 42 | hiredis 43 | hirefire-resource 44 | jbuilder 45 | jquery-rails 46 | js-cookie-rails 47 | languages 48 | mime-types (~> 2.6.1) 49 | newrelic_rpm 50 | nokogiri 51 | octokit 52 | oj 53 | oj_mimic_json 54 | omniauth 55 | omniauth-github 56 | pg 57 | platform-api 58 | postgres_ext 59 | premailer-rails 60 | puma 61 | pushover 62 | rack-canonical-host 63 | rails (= 4.2.3) 64 | rails_12factor 65 | rails_safe_tasks 66 | rb-readline 67 | redis 68 | sanitize-url 69 | sass-rails 70 | sassc-rails 71 | semantic 72 | sidekiq 73 | simple-rss 74 | simple_form 75 | sinatra 76 | sitemap_generator 77 | spdx 78 | spring 79 | sprockets (~> 2.12) 80 | thin 81 | tipsy-rails 82 | turbolinks 83 | typhoeus 84 | uglifier 85 | will_paginate 86 | will_paginate-bootstrap 87 | 88 | BUNDLED WITH 89 | 2.3.19 90 | -------------------------------------------------------------------------------- /spec/fixtures/Godeps: -------------------------------------------------------------------------------- 1 | # Git repos 2 | github.com/nu7hatch/gotrail v0.0.2 3 | github.com/replicon/fast-archiver v1.02 4 | 5 | # Subpackages 6 | github.com/garyburd/redigo/redis a6a0a737c00caf4d4c2bb589941ace0d688168bb 7 | 8 | # Bazaar Repo 9 | launchpad.net/gocheck r2013.03.03 #foo 10 | 11 | # Mercurial Repo 12 | code.google.com/p/go.example/hello/... ae081cd1d6cc 13 | -------------------------------------------------------------------------------- /spec/fixtures/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "gitlab.com/gitlab-org/gitlab-ci-multi-runner", 3 | "GoVersion": "go1.4.2", 4 | "Packages": [ 5 | "./..." 6 | ], 7 | "Deps": [ 8 | { 9 | "ImportPath": "github.com/BurntSushi/toml", 10 | "Comment": "v0.1.0-9-g3883ac1", 11 | "Rev": "3883ac1ce943878302255f538fce319d23226223" 12 | }, 13 | { 14 | "ImportPath": "github.com/Sirupsen/logrus", 15 | "Comment": "v0.8.7", 16 | "Rev": "418b41d23a1bf978c06faea5313ba194650ac088" 17 | }, 18 | { 19 | "ImportPath": "github.com/ayufan/golang-kardianos-service", 20 | "Rev": "9ce7ccf10c81705a8880170bbf506bd539bc69b2" 21 | }, 22 | { 23 | "ImportPath": "github.com/codegangsta/cli", 24 | "Comment": "1.2.0-139-g142e6cd", 25 | "Rev": "142e6cd241a4dfbf7f07a018f1f8225180018da4" 26 | }, 27 | { 28 | "ImportPath": "github.com/fsouza/go-dockerclient", 29 | "Rev": "163268693e2cf8be2920158b59ef438fc77b85e2" 30 | }, 31 | { 32 | "ImportPath": "github.com/golang/mock/gomock", 33 | "Rev": "06883d979f10cc178f2716846215c8cf90f9e363" 34 | }, 35 | { 36 | "ImportPath": "github.com/kardianos/osext", 37 | "Rev": "efacde03154693404c65e7aa7d461ac9014acd0c" 38 | }, 39 | { 40 | "ImportPath": "github.com/ramr/go-reaper", 41 | "Rev": "1a6cbc07ef2f7e248769ef4efd80aaa16f97ec12" 42 | }, 43 | { 44 | "ImportPath": "github.com/stretchr/objx", 45 | "Rev": "cbeaeb16a013161a98496fad62933b1d21786672" 46 | }, 47 | { 48 | "ImportPath": "github.com/stretchr/testify/assert", 49 | "Rev": "1297dc01ed0a819ff634c89707081a4df43baf6b" 50 | }, 51 | { 52 | "ImportPath": "github.com/stretchr/testify/mock", 53 | "Rev": "1297dc01ed0a819ff634c89707081a4df43baf6b" 54 | }, 55 | { 56 | "ImportPath": "gitlab.com/ayufan/golang-cli-helpers", 57 | "Rev": "0a14b63a7466ee44de4a90f998fad73afa8482bf" 58 | }, 59 | { 60 | "ImportPath": "golang.org/x/crypto/ssh", 61 | "Rev": "1351f936d976c60a0a48d728281922cf63eafb8d" 62 | }, 63 | { 64 | "ImportPath": "gopkg.in/yaml.v1", 65 | "Rev": "9f9df34309c04878acc86042b16630b0f696e1de" 66 | } 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /spec/fixtures/Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | branch = "parse-constraints-with-dash-in-pre" 6 | name = "github.com/Masterminds/semver" 7 | packages = ["."] 8 | revision = "a93e51b5a57ef416dac8bb02d11407b6f55d8929" 9 | source = "https://github.com/carolynvs/semver.git" 10 | 11 | [[projects]] 12 | name = "github.com/Masterminds/vcs" 13 | packages = ["."] 14 | revision = "3084677c2c188840777bff30054f2b553729d329" 15 | version = "v1.11.1" 16 | 17 | [[projects]] 18 | branch = "master" 19 | name = "github.com/armon/go-radix" 20 | packages = ["."] 21 | revision = "4239b77079c7b5d1243b7b4736304ce8ddb6f0f2" 22 | 23 | [[projects]] 24 | name = "github.com/boltdb/bolt" 25 | packages = ["."] 26 | revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8" 27 | version = "v1.3.1" 28 | 29 | [[projects]] 30 | branch = "v2" 31 | name = "github.com/go-yaml/yaml" 32 | packages = ["."] 33 | revision = "cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b" 34 | 35 | [[projects]] 36 | branch = "master" 37 | name = "github.com/golang/protobuf" 38 | packages = ["proto"] 39 | revision = "5afd06f9d81a86d6e3bb7dc702d6bd148ea3ff23" 40 | 41 | [[projects]] 42 | name = "github.com/jmank88/nuts" 43 | packages = ["."] 44 | revision = "a1e02c788669d022c325a8ee674f15360d7104f4" 45 | version = "v0.2.0" 46 | 47 | [[projects]] 48 | branch = "master" 49 | name = "github.com/nightlyone/lockfile" 50 | packages = ["."] 51 | revision = "e83dc5e7bba095e8d32fb2124714bf41f2a30cb5" 52 | 53 | [[projects]] 54 | branch = "master" 55 | name = "github.com/pelletier/go-toml" 56 | packages = ["."] 57 | revision = "b8b5e7696574464b2f9bf303a7b37781bb52889f" 58 | 59 | [[projects]] 60 | name = "github.com/pkg/errors" 61 | packages = ["."] 62 | revision = "645ef00459ed84a119197bfb8d8205042c6df63d" 63 | version = "v0.8.0" 64 | 65 | [[projects]] 66 | branch = "master" 67 | name = "github.com/sdboyer/constext" 68 | packages = ["."] 69 | revision = "836a144573533ea4da4e6929c235fd348aed1c80" 70 | 71 | [[projects]] 72 | branch = "master" 73 | name = "golang.org/x/net" 74 | packages = ["context"] 75 | revision = "66aacef3dd8a676686c7ae3716979581e8b03c47" 76 | 77 | [[projects]] 78 | branch = "master" 79 | name = "golang.org/x/sync" 80 | packages = ["errgroup"] 81 | revision = "f52d1811a62927559de87708c8913c1650ce4f26" 82 | 83 | [[projects]] 84 | branch = "master" 85 | name = "golang.org/x/sys" 86 | packages = ["unix"] 87 | revision = "bb24a47a89eac6c1227fbcb2ae37a8b9ed323366" 88 | 89 | [solve-meta] 90 | analyzer-name = "dep" 91 | analyzer-version = 1 92 | inputs-digest = "05c1cd69be2c917c0cc4b32942830c2acfa044d8200fdc94716aae48a8083702" 93 | solver-name = "gps-cdcl" 94 | solver-version = 1 95 | -------------------------------------------------------------------------------- /spec/fixtures/Gopkg.toml: -------------------------------------------------------------------------------- 1 | [[constraint]] 2 | branch = "parse-constraints-with-dash-in-pre" 3 | name = "github.com/Masterminds/semver" 4 | source = "https://github.com/carolynvs/semver.git" 5 | 6 | [[constraint]] 7 | name = "github.com/Masterminds/vcs" 8 | version = "1.11.0" 9 | 10 | [[constraint]] 11 | branch = "v2" 12 | name = "github.com/go-yaml/yaml" 13 | 14 | [[constraint]] 15 | branch = "master" 16 | name = "github.com/pelletier/go-toml" 17 | 18 | [[constraint]] 19 | name = "github.com/pkg/errors" 20 | version = "0.8.0" 21 | 22 | [[constraint]] 23 | name = "github.com/boltdb/bolt" 24 | version = "1.0.0" 25 | 26 | [[constraint]] 27 | name = "github.com/jmank88/nuts" 28 | version = "0.2.0" 29 | 30 | [[constraint]] 31 | name = "github.com/golang/protobuf" 32 | branch = "master" 33 | 34 | [prune] 35 | non-go = true 36 | go-tests = true 37 | unused-packages = true 38 | -------------------------------------------------------------------------------- /spec/fixtures/META.json: -------------------------------------------------------------------------------- 1 | { 2 | "abstract" : "CPU/RAM/battery stats chart bar for tmux (and GNU screen)", 3 | "author" : [ 4 | "Stanislaw Pusep " 5 | ], 6 | "dynamic_config" : 0, 7 | "generated_by" : "Module::Build version 0.4214", 8 | "license" : [ 9 | "perl_5" 10 | ], 11 | "meta-spec" : { 12 | "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", 13 | "version" : "2" 14 | }, 15 | "name" : "App-rainbarf", 16 | "prereqs" : { 17 | "build" : { 18 | "requires" : { 19 | "English" : "1.00", 20 | "Test::More" : "0.45" 21 | } 22 | }, 23 | "configure" : { 24 | "requires" : { 25 | "Module::Build" : "0.28" 26 | } 27 | }, 28 | "runtime" : { 29 | "requires" : { 30 | "Getopt::Long" : "2.32", 31 | "List::Util" : "1.07_00" 32 | } 33 | } 34 | }, 35 | "provides" : { 36 | "App::rainbarf" : { 37 | "file" : "lib/App/rainbarf.pm", 38 | "version" : "1.3" 39 | } 40 | }, 41 | "release_status" : "stable", 42 | "resources" : { 43 | "bugtracker" : { 44 | "web" : "https://github.com/creaktive/rainbarf/issues" 45 | }, 46 | "homepage" : "https://github.com/creaktive/rainbarf", 47 | "repository" : { 48 | "type" : "git", 49 | "url" : "git://github.com/creaktive/rainbarf.git" 50 | } 51 | }, 52 | "version" : "1.3", 53 | "x_contributors" : [ 54 | "Chris Knadler ", 55 | "Clemens Hammacher ", 56 | "H.Merijn Brand ", 57 | "Henrik Hodne ", 58 | "Joe Hassick ", 59 | "Josh Matthews ", 60 | "Sergey Romanov ", 61 | "Tom Cammann ", 62 | "Tuomas Jormola " 63 | ], 64 | "x_serialization_backend" : "JSON::PP version 2.27300" 65 | } 66 | -------------------------------------------------------------------------------- /spec/fixtures/META.yml: -------------------------------------------------------------------------------- 1 | --- 2 | abstract: 'Ocs-Inventory unified Agent for UNIX, Linux and MacOSX' 3 | build_requires: 4 | ExtUtils::MakeMaker: 6.59 5 | configure_requires: 6 | ExtUtils::MakeMaker: 6.59 7 | distribution_type: module 8 | dynamic_config: 1 9 | generated_by: 'Module::Install version 1.14' 10 | license: gpl 11 | meta-spec: 12 | url: http://module-build.sourceforge.net/META-spec-v1.4.html 13 | version: 1.4 14 | name: Ocsinventory-Unix-Agent 15 | no_index: 16 | directory: 17 | - inc 18 | recommends: 19 | Compress::Zlib: 0 20 | Net::IP: 0 21 | Nvidia::ml: 0 22 | Proc::Daemon: 0 23 | Proc::PID::File: 0 24 | requires: 25 | Digest::MD5: 0 26 | File::Temp: 0 27 | LWP: 0 28 | XML::Simple: 0 29 | perl: 5.6.0 30 | resources: 31 | license: http://opensource.org/licenses/gpl-license.php 32 | version: 2.2rc1 33 | -------------------------------------------------------------------------------- /spec/fixtures/Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "swift-package-converter", 5 | dependencies: [ 6 | .Package(url: "https://github.com/qutheory/vapor.git", majorVersion: 0, minor: 12), 7 | .Package(url: "https://github.com/czechboy0/Tasks.git", majorVersion: 0, minor: 2), 8 | .Package(url: "https://github.com/czechboy0/Environment.git", majorVersion: 0, minor: 4), 9 | ] 10 | ) 11 | -------------------------------------------------------------------------------- /spec/fixtures/Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = 'https://pypi.python.org/simple' 3 | verify_ssl = true 4 | 5 | [requires] 6 | python_version = '2.7' 7 | 8 | [packages] 9 | requests = { extras = ['socks'] } 10 | Django = '>1.10' 11 | pinax = { git = 'git://github.com/pinax/pinax.git', ref = '1.4', editable = true } 12 | a-local-dep = {editable = true, path = "."} 13 | 14 | [dev-packages] 15 | nose = '*' 16 | another-local-dep = {file = ".", editable = true} 17 | -------------------------------------------------------------------------------- /spec/fixtures/Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "default": { 3 | "PySocks": { 4 | "version": "==1.6.5", 5 | "hash": "sha256:7962f4d7c76e8414ae168c677a77f19cf8926143911f7e8d37a5d4c4eb910c6f" 6 | }, 7 | "requests": { 8 | "version": "==2.13.0", 9 | "hash": "sha256:1a720e8862a41aa22e339373b526f508ef0c8988baf48b84d3fc891a8e237efb" 10 | }, 11 | "Django": { 12 | "version": "==1.10.5", 13 | "hash": "sha256:4541a60834f28f308ee7b6e96400feca905fb0de473eb9dad6847e98a36d86d4" 14 | }, 15 | "pinax": { 16 | "ref": "1.4", 17 | "git": "git://github.com/pinax/pinax.git", 18 | "editable": true 19 | }, 20 | "a-local-dep": { 21 | "editable": true, 22 | "path": "." 23 | } 24 | }, 25 | "develop": { 26 | "nose": { 27 | "version": "==1.3.7", 28 | "hash": "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a" 29 | } 30 | }, 31 | "_meta": { 32 | "sources": [ 33 | { 34 | "url": "https://pypi.python.org/simple", 35 | "verify_ssl": true 36 | } 37 | ], 38 | "requires": { 39 | "python_version": "2.7" 40 | }, 41 | "Pipfile-sha256": "f7b3cb170ff903cb7d269195dd0a8212d335f3d5b7d6f907246fd580c46cf847" 42 | } 43 | } -------------------------------------------------------------------------------- /spec/fixtures/Podfile: -------------------------------------------------------------------------------- 1 | source "https://github.com/CocoaPods/Specs.git" 2 | source "https://github.com/artsy/Specs.git" 3 | 4 | plugin "cocoapods-keys", { 5 | project: "Eidolon", 6 | keys: [ 7 | "ArtsyAPIClientSecret", 8 | "ArtsyAPIClientKey", 9 | "HockeyProductionSecret", 10 | "HockeyBetaSecret", 11 | "MixpanelProductionAPIClientKey", 12 | "MixpanelStagingAPIClientKey", 13 | "CardflightProductionAPIClientKey", 14 | "CardflightProductionMerchantAccountToken", 15 | "StripeProductionPublishableKey", 16 | "CardflightStagingAPIClientKey", 17 | "CardflightStagingMerchantAccountToken", 18 | "StripeStagingPublishableKey", 19 | ], 20 | } 21 | 22 | platform :ios, "8.0" 23 | use_frameworks! 24 | 25 | # Yep. 26 | inhibit_all_warnings! 27 | 28 | # Artsy stuff 29 | pod "Artsy+UIColors" 30 | pod "Artsy+UILabels" 31 | pod "Artsy-UIButtons" 32 | 33 | if ["orta", "ash", "artsy", "Laura", "CI", "distiller", "travis"].include?(ENV["USER"]) 34 | pod "Artsy+UIFonts", "~> 1.1.0" 35 | else 36 | pod "Artsy+OSSUIFonts", "~> 1.1.0" 37 | end 38 | 39 | pod "ORStackView" 40 | pod "FLKAutoLayout" 41 | pod "ISO8601DateFormatter", "0.7" 42 | pod "ARCollectionViewMasonryLayout", "~> 2.0.0" 43 | pod "SDWebImage", "~> 3.7" 44 | pod "SVProgressHUD" 45 | 46 | pod "ARAnalytics/Mixpanel" 47 | pod "ARAnalytics/HockeyApp" 48 | 49 | pod "CardFlight" 50 | pod "Stripe" 51 | pod "ECPhoneNumberFormatter" 52 | pod "UIImageViewAligned", git: "https://github.com/ashfurrow/UIImageViewAligned.git" 53 | pod "DZNWebViewController", git: "https://github.com/orta/DZNWebViewController.git" 54 | pod "Reachability", git: "https://github.com/ashfurrow/Reachability.git", branch: "frameworks" 55 | 56 | pod "UIView+BooleanAnimations" 57 | pod "ARTiledImageView", git: "https://github.com/ashfurrow/ARTiledImageView.git" 58 | pod "XNGMarkdownParser" 59 | 60 | # Swift pods 61 | pod "SwiftyJSON", git: "https://github.com/SwiftyJSON/SwiftyJSON.git", branch: "xcode7" 62 | pod "ReactiveCocoa", "~> 4.0.1-alpha-2" 63 | pod "Moya/ReactiveCocoa" 64 | pod "Swift-RAC-Macros" 65 | 66 | target "KioskTests" do 67 | 68 | pod "FBSnapshotTestCase" 69 | pod "Nimble-Snapshots" 70 | pod "Quick" 71 | pod "Nimble", "= 2.0.0-rc.3" 72 | pod "Forgeries" 73 | 74 | end 75 | -------------------------------------------------------------------------------- /spec/fixtures/Project.json: -------------------------------------------------------------------------------- 1 | { 2 | "webroot": "wwwroot", 3 | "exclude": [ 4 | "wwwroot", 5 | "bower_components", 6 | "node_modules", 7 | "grunt" 8 | ], 9 | "publishExclude": [ 10 | "bower.json", 11 | "package.json", 12 | "gruntfile.js", 13 | "bower_components", 14 | "node_modules", 15 | "grunt" 16 | ], 17 | "authors": [ 18 | "Microsoft" 19 | ], 20 | "description": "Music store application on K as a SPA", 21 | "compilationOptions": { 22 | "define": [ 23 | "DEBUG" 24 | ] 25 | }, 26 | "dependencies": { 27 | "Microsoft.AspNet.Server.Kestrel": "1.0.0-beta7", 28 | "Microsoft.AspNet.Server.IIS": "1.0.0-beta7", 29 | "Microsoft.AspNet.Mvc": "6.0.0-beta7", 30 | "Microsoft.AspNet.Server.WebListener": "1.0.0-beta7", 31 | "Microsoft.AspNet.StaticFiles": "1.0.0-beta7", 32 | "EntityFramework.InMemory": "7.0.0-beta7", 33 | "EntityFramework.SqlServer": "7.0.0-beta7", 34 | "Microsoft.AspNet.Authentication.Cookies": "1.0.0-beta7", 35 | "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-beta7", 36 | "Microsoft.Framework.Configuration": "1.0.0-beta7", 37 | "Microsoft.Framework.Configuration.EnvironmentVariables": "1.0.0-beta7", 38 | "Microsoft.Framework.Configuration.Json": "1.0.0-beta7", 39 | "AutoMapper": "4.0.0-alpha1" 40 | }, 41 | "commands": { 42 | "WebListener": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5102", 43 | "Kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5104", 44 | "run": "run server.urls=http://localhost:5103" 45 | }, 46 | "frameworks": { 47 | "dnx451": {}, 48 | "dnxcore50": {} 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /spec/fixtures/REQUIRE: -------------------------------------------------------------------------------- 1 | julia 0.3 2 | Codecs 3 | Colors 0.3.4 4 | Compat 5 | Compose 0.3.11 6 | Contour 7 | DataFrames 0.4.2 8 | DataStructures 9 | Dates 10 | Distributions 11 | Gadfly 0.7- 12 | Hexagons 13 | @osx Homebrew 14 | Iterators 0.1.5 15 | JSON 16 | KernelDensity 17 | Loess 18 | Plots 0.12 0.15 19 | Showoff 0.0.3 20 | StatsBase 21 | @windows WinReg 22 | 23 | # The following should get ignored. 24 | - MySQL RDBMS 25 | - Oracle RDBMS 26 | - PostgreSQL 27 | - MongoDB 28 | - SQLite -------------------------------------------------------------------------------- /spec/fixtures/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": ">= 1.9.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /spec/fixtures/broken/pom.xml: -------------------------------------------------------------------------------- 1 | This is not an xml file 2 | -------------------------------------------------------------------------------- /spec/fixtures/build.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * This generated file contains a sample Kotlin application project to get you started. 5 | * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle 6 | * User Manual available at https://docs.gradle.org/7.4.2/userguide/building_java_projects.html 7 | */ 8 | 9 | plugins { 10 | // Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin. 11 | id("org.jetbrains.kotlin.jvm") version "1.5.31" 12 | 13 | // Apply the application plugin to add support for building a CLI application in Java. 14 | application 15 | } 16 | 17 | repositories { 18 | // Use Maven Central for resolving dependencies. 19 | mavenCentral() 20 | } 21 | 22 | dependencies { 23 | // Align versions of all Kotlin components 24 | implementation(platform("org.jetbrains.kotlin:kotlin-bom")) 25 | 26 | // Use the Kotlin JDK 8 standard library. 27 | implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") 28 | 29 | // This dependency is used by the application. 30 | implementation("com.google.guava:guava:30.1.1-jre") 31 | 32 | // Use the Kotlin test library. 33 | testImplementation ("org.jetbrains.kotlin:kotlin-test") 34 | 35 | // Use the Kotlin JUnit integration. 36 | testImplementation( "org.jetbrains.kotlin:kotlin-test-junit:1.0.0" ) 37 | 38 | implementation(project(":my-internal-lib")) 39 | 40 | // --- Androidx --- 41 | implementation("androidx.annotation:annotation:${rootProject.extra["androidx_annotation_version"]}") 42 | } 43 | 44 | application { 45 | // Define the main class for the application. 46 | mainClass.set("gradle_kts_single.AppKt") 47 | } 48 | -------------------------------------------------------------------------------- /spec/fixtures/build.sbt: -------------------------------------------------------------------------------- 1 | import com.typesafe.tools.mima.plugin.{MimaPlugin, MimaKeys} 2 | 3 | scalaModuleSettings 4 | 5 | name := "scala-parser-combinators" 6 | 7 | version := "1.0.5-SNAPSHOT" 8 | 9 | crossScalaVersions in ThisBuild := { 10 | val javaVersion = System.getProperty("java.version") 11 | val isJDK6Or7 = 12 | javaVersion.startsWith("1.6.") || javaVersion.startsWith("1.7.") 13 | if (isJDK6Or7) 14 | Seq("2.11.7") 15 | else 16 | Seq("2.11.7", "2.12.0-M3") 17 | } 18 | 19 | // important!! must come here (why?) 20 | scalaModuleOsgiSettings 21 | 22 | OsgiKeys.exportPackage := Seq(s"scala.util.parsing.*;version=${version.value}") 23 | 24 | // needed to fix classloader issues (see scala-xml#20) 25 | fork in Test := true 26 | 27 | libraryDependencies += "junit" % "junit" % "4.11" % "test" 28 | 29 | libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test" 30 | 31 | mimaPreviousVersion := Some("1.0.2") 32 | -------------------------------------------------------------------------------- /spec/fixtures/bun.lock: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1, 3 | "workspaces": { 4 | "": { 5 | "name": "bun-proj", 6 | "dependencies": { 7 | "alias-package": "npm:zod", 8 | "babel": "^6.23.0", 9 | "isarray": "file:../isarray", 10 | }, 11 | "devDependencies": { 12 | "@types/bun": "latest", 13 | "prettier": "^3.5.3", 14 | }, 15 | "optionalDependencies": { 16 | "lodash": "^4.17.21", 17 | }, 18 | "peerDependencies": { 19 | "typescript": "^5.8.2", 20 | }, 21 | }, 22 | }, 23 | "packages": { 24 | "@types/bun": ["@types/bun@1.2.5", "https://registry.npmjs.org/@types/bun/-/bun-1.2.5.tgz", { "dependencies": { "bun-types": "1.2.5" } }, "sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg=="], 25 | 26 | "@types/node": ["@types/node@22.13.10", "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], 27 | 28 | "@types/ws": ["@types/ws@8.5.14", "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], 29 | 30 | "alias-package": ["zod@3.24.2", "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="], 31 | 32 | "babel": ["babel@6.23.0", "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz", { "bin": { "babel": "./lib/cli.js", "babel-node": "./lib/cli.js", "babel-external-helpers": "./lib/cli.js" } }, "sha512-ZDcCaI8Vlct8PJ3DvmyqUz+5X2Ylz3ZuuItBe/74yXosk2dwyVo/aN7MCJ8HJzhnnJ+6yP4o+lDgG9MBe91DLA=="], 33 | 34 | "bun-types": ["bun-types@1.2.5", "https://registry.npmjs.org/bun-types/-/bun-types-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-3oO6LVGGRRKI4kHINx5PIdIgnLRb7l/SprhzqXapmoYkFl5m4j6EvALvbDVuuBFaamB46Ap6HCUxIXNLCGy+tg=="], 35 | 36 | "isarray": ["isarray@file:../isarray", {}], 37 | 38 | "lodash": ["lodash@4.17.21", "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], 39 | 40 | "prettier": ["prettier@3.5.3", "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], 41 | 42 | "typescript": ["typescript@5.8.2", "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], 43 | 44 | "undici-types": ["undici-types@6.20.0", "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], 45 | } 46 | } -------------------------------------------------------------------------------- /spec/fixtures/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/laravel", 3 | "description": "The Laravel Framework.", 4 | "keywords": ["framework", "laravel"], 5 | "license": "MIT", 6 | "type": "project", 7 | "require": { 8 | "laravel/framework": "5.0.*", 9 | "drupal/address": "^1.0" 10 | }, 11 | "require-dev": { 12 | "phpunit/phpunit": "~4.0", 13 | "phpspec/phpspec": "~2.1" 14 | }, 15 | "autoload": { 16 | "classmap": [ 17 | "database" 18 | ], 19 | "psr-4": { 20 | "App\\": "app/" 21 | } 22 | }, 23 | "repositories": { 24 | "drupal": { 25 | "type": "composer", 26 | "url": "https://packages.drupal.org/8" 27 | } 28 | }, 29 | "scripts": { 30 | "post-install-cmd": [ 31 | "php artisan clear-compiled", 32 | "php artisan optimize" 33 | ], 34 | "post-update-cmd": [ 35 | "php artisan clear-compiled", 36 | "php artisan optimize" 37 | ], 38 | "post-create-project-cmd": [ 39 | "php -r \"copy('.env.example', '.env');\"", 40 | "php artisan key:generate" 41 | ] 42 | }, 43 | "config": { 44 | "preferred-install": "dist" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /spec/fixtures/composer2.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "twbs/bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "authors": [ 16 | { 17 | "name": "Mark Otto", 18 | "email": "markdotto@gmail.com" 19 | }, 20 | { 21 | "name": "Jacob Thornton", 22 | "email": "jacobthornton@gmail.com" 23 | } 24 | ], 25 | "support": { 26 | "issues": "https://github.com/twbs/bootstrap/issues" 27 | }, 28 | "license": "MIT", 29 | "extra": { 30 | "branch-alias": { 31 | "dev-master": "3.3.x-dev" 32 | } 33 | }, 34 | "replace": { 35 | "twitter/bootstrap": "self.version" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /spec/fixtures/conda_with_pip/environment.yml: -------------------------------------------------------------------------------- 1 | name: testingenv 2 | channels: 3 | - defaults 4 | dependencies: 5 | - pip 6 | - pip: 7 | - urllib3 8 | - Django==2.0.0 9 | - sqlite=3.29.0=h7b6447c_0 10 | -------------------------------------------------------------------------------- /spec/fixtures/cyclonedx-nested.json: -------------------------------------------------------------------------------- 1 | { 2 | "components": [ 3 | { 4 | "type": "application", 5 | "name": "wow", 6 | "components": [ 7 | { 8 | "type": "library", 9 | "name": "1to2", 10 | "purl": "pkg:npm/1to2@1.0.0", 11 | "components": [ 12 | { 13 | "type": "library", 14 | "name": "go", 15 | "purl": "pkg:golang/cloud.google.com/go@v0.38.0", 16 | "components": [ 17 | { 18 | "type": "library", 19 | "name": "HdrHistogram", 20 | "purl": "pkg:maven/org.hdrhistogram/HdrHistogram@2.1.9" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /spec/fixtures/cyclonedx-nested.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | wow 6 | 7 | 8 | 1to2 9 | pkg:npm/1to2@1.0.0 10 | 11 | 12 | go 13 | pkg:golang/cloud.google.com/go@v0.38.0 14 | 15 | 16 | HdrHistogram 17 | pkg:maven/org.hdrhistogram/HdrHistogram@2.1.9 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /spec/fixtures/dependencies.csv: -------------------------------------------------------------------------------- 1 | platform,name,requirement,type 2 | maven,com.example:something,1.0.3,runtime 3 | maven,com.example:something-dev,1.0.4,development 4 | -------------------------------------------------------------------------------- /spec/fixtures/devise.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "devise/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "devise" 7 | s.version = Devise::VERSION.dup 8 | s.platform = Gem::Platform::RUBY 9 | s.licenses = ["MIT"] 10 | s.summary = "Flexible authentication solution for Rails with Warden" 11 | s.email = "contact@plataformatec.com.br" 12 | s.homepage = "https://github.com/plataformatec/devise" 13 | s.description = "Flexible authentication solution for Rails with Warden" 14 | s.authors = ["José Valim", "Carlos Antônio"] 15 | 16 | s.files = `git ls-files`.split("\n") 17 | s.test_files = `git ls-files -- test/*`.split("\n") 18 | s.require_paths = ["lib"] 19 | s.required_ruby_version = ">= 1.9.3" 20 | 21 | s.add_dependency("warden", "~> 1.2.3") 22 | s.add_development_dependency("orm_adapter", "~> 0.1") 23 | s.add_dependency("bcrypt", "~> 3.0") 24 | s.add_dependency("thread_safe", "~> 0.1") 25 | s.add_dependency("railties", ">= 3.2.6", "< 5") 26 | s.add_dependency("responders") 27 | end 28 | -------------------------------------------------------------------------------- /spec/fixtures/dist.ini: -------------------------------------------------------------------------------- 1 | name = PathFind 2 | author = Carla Cummins 3 | license = GPL_3 4 | copyright_holder = Wellcome Trust Sanger Institute 5 | copyright_year = 2013 6 | 7 | [MetaResources] 8 | homepage = http://www.sanger.ac.uk/ 9 | repository.web = https://github.com/sanger-pathogens/PathFind 10 | repository.url = https://github.com/sanger-pathogens/PathFind.git 11 | repository.type = git 12 | 13 | [RequiresExternal] 14 | requires = tar 15 | requires = ln 16 | 17 | [@Git] 18 | [@Basic] 19 | [PruneCruft] 20 | [ExtraTests] 21 | [AutoPrereqs] 22 | [AutoVersion] 23 | [PodWeaver] 24 | -------------------------------------------------------------------------------- /spec/fixtures/dpkg: -------------------------------------------------------------------------------- 1 | Desired=Unknown/Install/Remove/Purge/Hold 2 | | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend 3 | |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad) 4 | ||/ Name Version Description 5 | +++-================================-=================================-========================================================================== 6 | ii accountsservice 0.6.15-2ubuntu9.6 query and manipulate user account information 7 | ii acpid 1:2.0.10-1ubuntu3 Advanced Configuration and Power Interface event daemon 8 | ii adduser 3.113ubuntu2 add and remove users and groups 9 | ii apparmor 2.7.102-0ubuntu3.9 User-space parser utility for AppArmor 10 | ii apt 0.8.16~exp12ubuntu10.12 commandline package manager 11 | -------------------------------------------------------------------------------- /spec/fixtures/dub.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ddox", 3 | "description": "Powerful alternative to DMD's DDOC engine.", 4 | "homepage": "https://github.com/rejectedsoftware/ddox", 5 | "license": "MIT", 6 | "authors": [ 7 | "Sönke Ludwig" 8 | ], 9 | "dependencies": { 10 | "vibe-d": "~>0.7.22", 11 | "libdparse": {"optional": true, "version": "~>0.2.0"} 12 | }, 13 | "versions": ["JsonLineNumbers"], 14 | "configurations": [ 15 | { 16 | "name": "application", 17 | "targetType": "executable", 18 | "versions": ["VibeCustomMain"] 19 | }, 20 | { 21 | "name": "library", 22 | "excludedSourceFiles": ["source/app.d"] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /spec/fixtures/dub.sdl: -------------------------------------------------------------------------------- 1 | name "note-app" 2 | description "A simple vibe.d server application." 3 | copyright "Copyright © 2016, Michael" 4 | authors "Michael" 5 | dependency "vibe-d" version="~>0.7.23" 6 | versions "VibeDefaultMain" 7 | -------------------------------------------------------------------------------- /spec/fixtures/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "website for browsing packages and exploring documentation", 4 | "repository": "https://github.com/elm-lang/package.elm-lang.org.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "frontend" 8 | ], 9 | "exposed-modules": [], 10 | "native-modules": true, 11 | "dependencies": { 12 | "evancz/elm-markdown": "1.1.0 <= v < 2.0.0", 13 | "evancz/elm-html": "1.0.0 <= v < 2.0.0", 14 | "evancz/local-channel": "1.0.0 <= v < 2.0.0", 15 | "elm-lang/core": "1.0.0 <= v < 2.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spec/fixtures/elm_dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1", 3 | "summary": "concise, helpful summary of your project", 4 | "description": "full description of this project, describe your use case", 5 | "license": "BSD3", 6 | "exposed-modules": [], 7 | "elm-version": "0.12.3", 8 | "dependencies": { 9 | "johnpmayer/elm-webgl": "0.1.1", 10 | "johnpmayer/elm-linear-algebra": "1.0.1" 11 | }, 12 | "repository": "https://github.com/USER/PROJECT.git" 13 | } 14 | -------------------------------------------------------------------------------- /spec/fixtures/empty_manifests/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | ruby "2.2.1" 3 | -------------------------------------------------------------------------------- /spec/fixtures/empty_manifests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "librarian", 3 | "version": "1.0.0", 4 | "description": "Integrate GH webhooks with Libraries.io", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "nodemon app.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "Mauro Pompilio", 11 | "license": "MIT", 12 | "dependencies": { 13 | }, 14 | "devDependencies": { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /spec/fixtures/environment.yml: -------------------------------------------------------------------------------- 1 | name: testingenv 2 | channels: 3 | - defaults 4 | dependencies: 5 | - beautifulsoup4=4.7.1=py37_1 6 | - biopython=1.74=py37h7b6447c_0 7 | - certifi=2019.6.16=py37_1 8 | - ncurses=6.1=he6710b0_1 9 | - numpy=1.16.4=py37h7e9f1db_0 10 | - openssl=1.1.1c=h7b6447c_1 11 | - pip 12 | - python=3.7.3=h0371630_0 13 | - readline=7.0=h7b6447c_5 14 | - setuptools 15 | - sqlite=3.29.0=h7b6447c_0 -------------------------------------------------------------------------------- /spec/fixtures/exact-dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "jvoigtlaender/elm-drag-and-drop": "1.0.1", 3 | "evancz/elm-html": "2.0.0", 4 | "elm-lang/core": "1.1.1", 5 | "evancz/automaton": "1.0.0", 6 | "evancz/virtual-dom": "1.2.2" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/example-no-version.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.2 5 | InProcess 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /spec/fixtures/example-update.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp1.1 6 | win10-x64 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /spec/fixtures/example.cabal: -------------------------------------------------------------------------------- 1 | name: cabal-parser 2 | version: 0.1.0.0 3 | synopsis: Tiny Web Service for Parsing Cabal Files 4 | 5 | description: 6 | Helper service for bibliothecary to parse cabal files from various sources. 7 | Provides a fiat JSON represenation for a given cabal file posted to this HTTP API. 8 | 9 | homepage: https://github.com/alunduil/librariesio-cabal-parser 10 | bug-reports: https://github.com/alunduil/librariesio-cabal-parser/issues 11 | license: GPL-3 12 | license-file: LICENSE 13 | author: Alex Brandt 14 | maintainer: alunduil@alunduil.com 15 | copyright: (c) 2018 Alex Brandt 16 | category: Development 17 | build-type: Simple 18 | cabal-version: >= 1.10 19 | tested-with: GHC == 8.* 20 | 21 | extra-source-files: 22 | ChangeLog.md 23 | , LICENSE 24 | , README.md 25 | , Setup.hs 26 | , test/examples/*.cabal 27 | 28 | source-repository head 29 | type: git 30 | location: https://github.com/alunduil/librariesio-cabal-parser 31 | branch: develop 32 | 33 | executable cabal-parser 34 | default-language: Haskell2010 35 | main-is: Main.hs 36 | 37 | ghc-options: -Wall -fwarn-tabs -fwarn-monomorphism-restriction 38 | -fwarn-unused-do-bind 39 | 40 | hs-source-dirs: 41 | src 42 | 43 | other-modules: 44 | API 45 | , Dependencies 46 | , Dependency 47 | , Distribution.Types.GenericPackageDescription.MimeUnrender 48 | , Distribution.Types.PackageName.JSON 49 | , Distribution.Version.JSON 50 | , Environment 51 | 52 | build-depends: 53 | aeson == 1.1.* 54 | , base >= 4.9 && < 4.11 55 | , Cabal == 2.0.* 56 | , envy == 1.3.* 57 | , pretty == 1.1.* 58 | , servant-server == 0.11.* 59 | , text == 1.2.* 60 | , utf8-string == 1.0.* 61 | , warp == 3.2.* 62 | 63 | other-extensions: 64 | DataKinds 65 | , FlexibleInstances 66 | , MultiParamTypeClasses 67 | , OverloadedStrings 68 | , RecordWildCards 69 | , TypeOperators 70 | 71 | test-suite cabal-parser-tests 72 | default-language: Haskell2010 73 | type: exitcode-stdio-1.0 74 | main-is: Spec.hs 75 | 76 | ghc-options: -Wall -fwarn-tabs -fwarn-monomorphism-restriction 77 | -fwarn-unused-do-bind 78 | 79 | hs-source-dirs: 80 | src 81 | , test 82 | 83 | other-modules: 84 | Dependencies 85 | , DependenciesSpec 86 | , Dependency 87 | , Distribution.Types.PackageName.JSON 88 | , Distribution.Version.JSON 89 | , Distribution.Version.JSONSpec 90 | 91 | build-tool-depends: 92 | hspec-discover:hspec-discover == 2.4.* 93 | 94 | build-depends: 95 | aeson == 1.1.* 96 | , base >= 4.9 && < 4.11 97 | , bytestring == 0.10.* 98 | , Cabal == 2.0.* 99 | , hspec == 2.4.* 100 | , pretty == 1.1.* 101 | , text == 1.2.* 102 | 103 | other-extensions: 104 | -------------------------------------------------------------------------------- /spec/fixtures/example.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp1.1 6 | win10-x64 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 4.7.0 18 | 19 | 20 | all 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /spec/fixtures/example.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bottles 5 | 0.0.0 6 | Jeremy D. Miller, Dru Sellers, et al. 7 | Jeremy D. Miller 8 | https://github.com/DarthFubuMVC/bottles/raw/master/license.txt 9 | http://fubumvc.com 10 | https://github.com/DarthFubuMVC/bottles/raw/master/doc/logo/FubuMVC_Logo_package_icon.png 11 | false 12 | Shared libraries for runtime and deployment packaging of .Net applications 13 | packaging areas slices 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /spec/fixtures/example.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | 4 | s.name = "CocoaLumberjack" 5 | s.version = "2.2.0" 6 | s.license = "BSD" 7 | s.summary = "A fast & simple, yet powerful & flexible logging framework for Mac and iOS." 8 | s.homepage = "https://github.com/CocoaLumberjack/CocoaLumberjack" 9 | s.author = { "Robbie Hanson" => "robbiehanson@deusty.com" } 10 | s.source = { git: "https://github.com/CocoaLumberjack/CocoaLumberjack.git", 11 | tag: "#{s.version}" } 12 | 13 | s.description = "It is similar in concept to other popular logging frameworks such as log4j, " \ 14 | "yet is designed specifically for objective-c, and takes advantage of features " \ 15 | "such as multi-threading, grand central dispatch (if available), lockless " \ 16 | "atomic operations, and the dynamic nature of the objective-c runtime." 17 | 18 | s.requires_arc = true 19 | 20 | s.preserve_paths = "README.md", "Classes/CocoaLumberjack.swift", "Framework/Lumberjack/CocoaLumberjack.modulemap" 21 | s.ios.deployment_target = "5.0" 22 | s.osx.deployment_target = "10.7" 23 | s.watchos.deployment_target = "2.0" 24 | s.tvos.deployment_target = "9.0" 25 | 26 | s.public_header_files = "Classes/*.h" 27 | 28 | s.module_map = "Framework/Lumberjack/CocoaLumberjack.modulemap" 29 | s.default_subspecs = "Default", "Extensions" 30 | 31 | s.subspec "Default" do |ss| 32 | ss.source_files = "Classes/CocoaLumberjack.{h,m}" 33 | ss.dependency "CocoaLumberjack/Core" 34 | end 35 | 36 | s.subspec "Core" do |ss| 37 | ss.source_files = "Classes/DD*.{h,m}" 38 | end 39 | 40 | s.subspec "Extensions" do |ss| 41 | ss.source_files = "Classes/Extensions/*.{h,m}" 42 | ss.dependency "CocoaLumberjack/Default" 43 | end 44 | 45 | s.subspec "CLI" do |ss| 46 | ss.osx.deployment_target = "10.7" 47 | ss.source_files = "Classes/CLI/*.{h,m}" 48 | ss.dependency "CocoaLumberjack/Default" 49 | end 50 | 51 | s.subspec "Swift" do |ss| 52 | ss.ios.deployment_target = "8.0" 53 | ss.osx.deployment_target = "10.10" 54 | ss.watchos.deployment_target = "2.0" 55 | ss.tvos.deployment_target = "9.0" 56 | ss.source_files = "Classes/CocoaLumberjack.swift" 57 | ss.dependency "CocoaLumberjack/Extensions", "*" 58 | end 59 | 60 | end 61 | -------------------------------------------------------------------------------- /spec/fixtures/example.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ALOSRPAuth", 3 | "version": "0.1", 4 | "license": "MIT", 5 | "summary": "ALOSRPAuth is Obj-C implementation of Secure Remote Password protocol (SRP-6a)", 6 | "homepage": "https://github.com/AddAloner/ALOSRPAuth", 7 | "authors": { 8 | "Alexey Yachmenov": "aloner.brn@gmail.com" 9 | }, 10 | "source": { 11 | "git": "https://github.com/AddAloner/ALOSRPAuth.git", 12 | "tag": "0.1" 13 | }, 14 | "platforms": { 15 | "ios": "5.0", 16 | "osx": "10.7" 17 | }, 18 | "source_files": "*.{h,m,c}", 19 | "requires_arc": true, 20 | "dependencies": { 21 | "OpenSSL": [ 22 | "~> 1.0" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /spec/fixtures/gb_manifest: -------------------------------------------------------------------------------- 1 | { 2 | "version": 0, 3 | "dependencies": [ 4 | { 5 | "importpath": "github.com/gorilla/mux", 6 | "repository": "https://github.com/gorilla/mux", 7 | "revision": "9fa818a44c2bf1396a17f9d5a3c0f6dd39d2ff8e", 8 | "branch": "master" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /spec/fixtures/gems.rb: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | ruby "2.2.1" 3 | 4 | gem "oj" 5 | gem "rails", "4.2.0" 6 | gem "leveldb-ruby","0.15", require: "leveldb" 7 | 8 | group :development do 9 | gem "spring" 10 | gem "thin" 11 | end 12 | 13 | group :production do 14 | gem "puma" 15 | gem "rails_12factor" 16 | gem "bugsnag" 17 | end 18 | -------------------------------------------------------------------------------- /spec/fixtures/glide.lock: -------------------------------------------------------------------------------- 1 | hash: 9057b90e0cd3fac45ad563ea3d62a6e57c845e5c07e68e87b6fc14818574eb4f 2 | updated: 2016-02-17T09:11:15.318323635-05:00 3 | imports: 4 | - name: github.com/codegangsta/cli 5 | version: c31a7975863e7810c92e2e288a9ab074f9a88f29 6 | - name: github.com/Masterminds/semver 7 | version: 513f3dcb3ecfb1248831fb5cb06a23a3cd5935dc 8 | - name: github.com/Masterminds/vcs 9 | version: 9c0db6583837118d5df7c2ae38ab1c194e434b35 10 | - name: gopkg.in/yaml.v2 11 | version: f7716cbe52baa25d2e9b0d0da546fcf909fc16b4 12 | devImports: [] 13 | -------------------------------------------------------------------------------- /spec/fixtures/glide.yaml: -------------------------------------------------------------------------------- 1 | package: github.com/Masterminds/glide 2 | homepage: https://glide.sh 3 | license: MIT 4 | owners: 5 | - name: Matt Butcher 6 | email: technosophos@gmail.com 7 | homepage: http://technosophos.com/ 8 | - name: Matt Farina 9 | email: matt@mattfarina.com 10 | homepage: https://www.mattfarina.com/ 11 | import: 12 | - package: gopkg.in/yaml.v2 13 | - package: github.com/Masterminds/vcs 14 | version: ^1.4.0 15 | - package: github.com/codegangsta/cli 16 | - package: github.com/Masterminds/semver 17 | version: ^1.0.0 18 | -------------------------------------------------------------------------------- /spec/fixtures/go.mod: -------------------------------------------------------------------------------- 1 | module mod 2 | 3 | go 1.24 4 | 5 | toolchain go1.24.0 6 | 7 | // this is a comment line 8 | 9 | require ( 10 | github.com/go-check/check v0.0.0-20180628173108-788fd7840127 // indirect 11 | github.com/gomodule/redigo v2.0.0+incompatible // indirect 12 | github.com/jstemmer/go-junit-report v1.0.0 // indirect 13 | github.com/jstemmer/go-junit-report/v2 v2.1.0 // indirect 14 | github.com/kr/pretty v0.1.0 // indirect 15 | github.com/replicon/fast-archiver v0.0.0-20121220195659-060bf9adec25 // indirect 16 | gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 17 | ) 18 | 19 | require golang.org/x/net v1.2.3 // this is the single-line require directive 20 | 21 | exclude old/thing 1.2.3 // this is the single-line exclude directive 22 | 23 | exclude ( 24 | older/thing 4.5.6 // this is the multi-line exclude directive 25 | ) 26 | 27 | replace bad/thing v1.4.5 => good/thing v1.4.5 // this is the single-line exclude directive 28 | 29 | replace ( 30 | golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5 31 | golang.org/x/net => example.com/fork/net v1.4.5 32 | golang.org/x/net v1.2.3 => ./fork/net 33 | golang.org/x/net => ./fork/net 34 | ) 35 | 36 | retract v1.0.0 // this is the single-line retract directive 37 | 38 | retract [v2.0.0, v1.9.9] 39 | 40 | retract ( 41 | v1.0.0 // this is the multi-line retract directive 42 | [v1.0.0, v1.9.9] 43 | ) 44 | 45 | tool golang.org/x/tools/cmd/stringer 46 | 47 | tool ( 48 | github.com/jstemmer/go-junit-report 49 | github.com/jstemmer/go-junit-report/v2 50 | ) 51 | -------------------------------------------------------------------------------- /spec/fixtures/go.single-require.mod: -------------------------------------------------------------------------------- 1 | module mod 2 | 3 | go 1.12 4 | 5 | require github.com/go-check/check v0.0.0-20180628173108-788fd7840127 // indirect 6 | -------------------------------------------------------------------------------- /spec/fixtures/go.sum: -------------------------------------------------------------------------------- 1 | github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= 2 | github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= 3 | github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= 4 | github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= 5 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 6 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 7 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 8 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 9 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 10 | github.com/replicon/fast-archiver v0.0.0-20121220195659-060bf9adec25 h1:aq3XSz9htmdvrxpK6eBIbjs3SaN8G1D9RuKkDo4PRnw= 11 | github.com/replicon/fast-archiver v0.0.0-20121220195659-060bf9adec25/go.mod h1:R9DTtFe2IYmHTz+jzYtQmqqltTKfdZCqx4NgPIEg6oY= 12 | gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 h1:POO/ycCATvegFmVuPpQzZFJ+pGZeX22Ufu6fibxDVjU= 13 | gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= 14 | -------------------------------------------------------------------------------- /spec/fixtures/haxelib.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flixel", 3 | "url": "http://haxeflixel.com", 4 | "license": "MIT", 5 | "tags": [ 6 | "game", 7 | "openfl", 8 | "flash", 9 | "html5", 10 | "neko", 11 | "cpp", 12 | "android", 13 | "ios", 14 | "cross" 15 | ], 16 | "description": "HaxeFlixel is a 2D game engine based on OpenFL that delivers cross-platform games.", 17 | "version": "4.2.1", 18 | "releasenote": "Fixed rendering with Haxe 3.4.0 and OpenFL Next.", 19 | "contributors": [ 20 | "haxeflixel" 21 | ], 22 | "dependencies": { 23 | "lime": "2.9.1", 24 | "openfl": "3.6.1" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /spec/fixtures/ivy.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 7 | 8 | The fully integrated standalone wiki and 9 | acceptance testing framework. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /spec/fixtures/ivy_reports/com.example-hello_2.12-compile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /spec/fixtures/ivy_reports/invalid_syntax.xml: -------------------------------------------------------------------------------- 1 | 2 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /spec/fixtures/ivy_reports/non_ivy_report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /spec/fixtures/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Mixup.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [app: :mixup, 6 | version: "0.0.1", 7 | elixir: "~> 1.0", 8 | deps: deps, 9 | default_task: "server"] 10 | end 11 | 12 | # Configuration for the OTP application 13 | # 14 | # Type `mix help compile.app` for more information 15 | def application do 16 | [applications: [:logger, :cowboy, :plug]] 17 | end 18 | 19 | # defp escript_config do 20 | # [main_module: Servelet] 21 | # end 22 | 23 | # Dependencies can be Hex packages: 24 | # 25 | # {:mydep, "~> 0.3.0"} 26 | # 27 | # Or git/path repositories: 28 | # 29 | # {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"} 30 | # 31 | # Type `mix help deps` for more examples and options 32 | defp deps do 33 | [{:poison, "~> 1.3.1"}, 34 | {:plug, "~> 0.11.0"}, 35 | {:cowboy, "~> 1.0.0"}] 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/fixtures/mix.lock: -------------------------------------------------------------------------------- 1 | %{"cowboy": {:hex, :cowboy, "1.0.4", "a324a8df9f2316c833a470d918aaf73ae894278b8aa6226ce7a9bf699388f878", [:rebar, :make], [{:cowlib, "~> 1.0.0", [hex: :cowlib, optional: false]}, {:ranch, "~> 1.0", [hex: :ranch, optional: false]}]}, 2 | "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], []}, 3 | "plug": {:hex, :plug, "1.1.6", "8927e4028433fcb859e000b9389ee9c37c80eb28378eeeea31b0273350bf668b", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}]}, 4 | "poison": {:hex, :poison, "2.1.0", "f583218ced822675e484648fa26c933d621373f01c6c76bd00005d7bd4b82e27", [:mix], []}, 5 | "ranch": {:hex, :ranch, "1.2.1", "a6fb992c10f2187b46ffd17ce398ddf8a54f691b81768f9ef5f461ea7e28c762", [:make], []}} 6 | -------------------------------------------------------------------------------- /spec/fixtures/multimanifest_dir/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | ruby "2.2.1" 3 | 4 | gem "oj" 5 | gem "rails", "4.2.0" 6 | gem "leveldb-ruby","0.15", require: "leveldb" 7 | 8 | group :development do 9 | gem "spring" 10 | gem "thin" 11 | end 12 | 13 | group :production do 14 | gem "puma" 15 | gem "rails_12factor" 16 | gem "bugsnag" 17 | end 18 | -------------------------------------------------------------------------------- /spec/fixtures/multimanifest_dir/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (2.3.1) 5 | actionmailer (4.2.3) 6 | actionpack (= 4.2.3) 7 | actionview (= 4.2.3) 8 | activejob (= 4.2.3) 9 | mail (~> 2.5, >= 2.5.4) 10 | rails-dom-testing (~> 1.0, >= 1.0.5) 11 | googleauth (0.4.1) 12 | faraday (~> 0.9) 13 | jwt (~> 1.4) 14 | logging (~> 2.0) 15 | memoist (~> 0.12) 16 | multi_json (= 1.11) 17 | signet (~> 0.6) 18 | hashie (3.4.2) 19 | 20 | PLATFORMS 21 | ruby 22 | 23 | DEPENDENCIES 24 | bigquery 25 | bootstrap-sass 26 | bugsnag 27 | bundler 28 | coffee-rails 29 | counter_culture 30 | dalli 31 | dotenv-rails 32 | elasticsearch-model 33 | elasticsearch-rails 34 | faraday-http-cache 35 | fast_blank 36 | fast_xor 37 | fast_xs 38 | fog 39 | font-awesome-rails 40 | gemoji 41 | gems 42 | hiredis 43 | hirefire-resource 44 | jbuilder 45 | jquery-rails 46 | js-cookie-rails 47 | languages 48 | mime-types (~> 2.6.1) 49 | newrelic_rpm 50 | nokogiri 51 | octokit 52 | oj 53 | oj_mimic_json 54 | omniauth 55 | omniauth-github 56 | pg 57 | platform-api 58 | postgres_ext 59 | premailer-rails 60 | puma 61 | pushover 62 | rack-canonical-host 63 | rails (= 4.2.3) 64 | rails_12factor 65 | rails_safe_tasks 66 | rb-readline 67 | redis 68 | sanitize-url 69 | sass-rails 70 | sassc-rails 71 | semantic 72 | sidekiq 73 | simple-rss 74 | simple_form 75 | sinatra 76 | sitemap_generator 77 | spdx 78 | spring 79 | sprockets (~> 2.12) 80 | thin 81 | tipsy-rails 82 | turbolinks 83 | typhoeus 84 | uglifier 85 | will_paginate 86 | will_paginate-bootstrap 87 | 88 | BUNDLED WITH 89 | 1.10.5 90 | -------------------------------------------------------------------------------- /spec/fixtures/multimanifest_dir/com.example-hello_2.12-compile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /spec/fixtures/multimanifest_dir/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "librarian", 3 | "version": "1.0.0", 4 | "description": "Integrate GH webhooks with Libraries.io", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "nodemon app.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "Mauro Pompilio", 11 | "license": "MIT", 12 | "dependencies": { 13 | "babel": "^4.6.6" 14 | }, 15 | "devDependencies": { 16 | "mocha": "^2.2.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /spec/fixtures/multimanifest_dir/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup(name='political-memory', 4 | version='0.0.1', 5 | description='OpenShift App', 6 | packages=['political_memory'], 7 | package_dir={'political_memory': '.'}, 8 | author='James Pic, Laurent Peuch, Arnaud Fabre', 9 | author_email='cortex@worlddomination.be', 10 | url='http://github.com/political-memory/political_memory/', 11 | install_requires=[ 12 | # -*- Install requires: -*- 13 | 'django-bootstrap3>=6.2,<6.3', 14 | 'lesscpy', 15 | 'unicodecsv==0.14.1', 16 | 'django-coffeescript>=0.7,<0.8', 17 | 'django-compressor>=1.6,<1.7', 18 | 'django-datetime-widget>=0.9,<1.0', 19 | 'django-filter>=0.11,<0.12', 20 | 'django-representatives-votes>=0.0.13', 21 | 'django-representatives>=0.0.14', 22 | 'django-taggit>=0.17,<0.18', 23 | 'django>=1.8,<1.9', 24 | 'djangorestframework>=3.2.0,<3.3.0', 25 | 'hamlpy>=0.82,<0.83', 26 | 'ijson>=2.2,<2.3', 27 | 'python-dateutil>=2.4,<2.5', 28 | 'pytz==2015.7', 29 | 'django-suit', 30 | 'dummy==2.0beta1', 31 | ], 32 | extras_require={ 33 | 'testing': [ 34 | 'django-responsediff', 35 | 'flake8', 36 | 'pep8', 37 | 'pytest', 38 | 'pytest-django', 39 | 'pytest-cov', 40 | 'codecov', 41 | ] 42 | } 43 | ) 44 | -------------------------------------------------------------------------------- /spec/fixtures/multimanifest_dir/subdir/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | ruby "2.2.1" 3 | 4 | gem "oj" 5 | gem "rails", "4.2.0" 6 | gem "leveldb-ruby","0.15", require: "leveldb" 7 | 8 | group :development do 9 | gem "spring" 10 | gem "thin" 11 | end 12 | 13 | group :production do 14 | gem "puma" 15 | gem "rails_12factor" 16 | gem "bugsnag" 17 | end 18 | -------------------------------------------------------------------------------- /spec/fixtures/multimanifest_dir/subdir/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (2.3.1) 5 | actionmailer (4.2.3) 6 | actionpack (= 4.2.3) 7 | actionview (= 4.2.3) 8 | activejob (= 4.2.3) 9 | mail (~> 2.5, >= 2.5.4) 10 | rails-dom-testing (~> 1.0, >= 1.0.5) 11 | googleauth (0.4.1) 12 | faraday (~> 0.9) 13 | jwt (~> 1.4) 14 | logging (~> 2.0) 15 | memoist (~> 0.12) 16 | multi_json (= 1.11) 17 | signet (~> 0.6) 18 | hashie (3.4.2) 19 | 20 | PLATFORMS 21 | ruby 22 | 23 | DEPENDENCIES 24 | bigquery 25 | bootstrap-sass 26 | bugsnag 27 | bundler 28 | coffee-rails 29 | counter_culture 30 | dalli 31 | dotenv-rails 32 | elasticsearch-model 33 | elasticsearch-rails 34 | faraday-http-cache 35 | fast_blank 36 | fast_xor 37 | fast_xs 38 | fog 39 | font-awesome-rails 40 | gemoji 41 | gems 42 | hiredis 43 | hirefire-resource 44 | jbuilder 45 | jquery-rails 46 | js-cookie-rails 47 | languages 48 | mime-types (~> 2.6.1) 49 | newrelic_rpm 50 | nokogiri 51 | octokit 52 | oj 53 | oj_mimic_json 54 | omniauth 55 | omniauth-github 56 | pg 57 | platform-api 58 | postgres_ext 59 | premailer-rails 60 | puma 61 | pushover 62 | rack-canonical-host 63 | rails (= 4.2.3) 64 | rails_12factor 65 | rails_safe_tasks 66 | rb-readline 67 | redis 68 | sanitize-url 69 | sass-rails 70 | sassc-rails 71 | semantic 72 | sidekiq 73 | simple-rss 74 | simple_form 75 | sinatra 76 | sitemap_generator 77 | spdx 78 | spring 79 | sprockets (~> 2.12) 80 | thin 81 | tipsy-rails 82 | turbolinks 83 | typhoeus 84 | uglifier 85 | will_paginate 86 | will_paginate-bootstrap 87 | 88 | BUNDLED WITH 89 | 1.10.5 90 | -------------------------------------------------------------------------------- /spec/fixtures/multimanifest_dir/unknown_non_manifest.txt: -------------------------------------------------------------------------------- 1 | Ceci n'est pas un manifeste. 2 | 3 | -------------------------------------------------------------------------------- /spec/fixtures/multiple_versions/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "an-test-lib", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "an-test-lib", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "find-versions": "4.0.0", 13 | "semver-regex": "^4.0.0" 14 | } 15 | }, 16 | "node_modules/find-versions": { 17 | "version": "4.0.0", 18 | "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", 19 | "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", 20 | "dependencies": { 21 | "semver-regex": "^3.1.2" 22 | }, 23 | "engines": { 24 | "node": ">=10" 25 | }, 26 | "funding": { 27 | "url": "https://github.com/sponsors/sindresorhus" 28 | } 29 | }, 30 | "node_modules/find-versions/node_modules/semver-regex": { 31 | "version": "3.1.3", 32 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.3.tgz", 33 | "integrity": "sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==", 34 | "engines": { 35 | "node": ">=8" 36 | }, 37 | "funding": { 38 | "url": "https://github.com/sponsors/sindresorhus" 39 | } 40 | }, 41 | "node_modules/semver-regex": { 42 | "version": "4.0.2", 43 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.2.tgz", 44 | "integrity": "sha512-xyuBZk1XYqQkB687hMQqrCP+J9bdJSjPpZwdmmNjyxKW1K3LDXxqxw91Egaqkh/yheBIVtKPt4/1eybKVdCx3g==", 45 | "engines": { 46 | "node": ">=12" 47 | }, 48 | "funding": { 49 | "url": "https://github.com/sponsors/sindresorhus" 50 | } 51 | } 52 | }, 53 | "dependencies": { 54 | "find-versions": { 55 | "version": "4.0.0", 56 | "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", 57 | "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", 58 | "requires": { 59 | "semver-regex": "^3.1.2" 60 | }, 61 | "dependencies": { 62 | "semver-regex": { 63 | "version": "3.1.3", 64 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.3.tgz", 65 | "integrity": "sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==" 66 | } 67 | } 68 | }, 69 | "semver-regex": { 70 | "version": "4.0.2", 71 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.2.tgz", 72 | "integrity": "sha512-xyuBZk1XYqQkB687hMQqrCP+J9bdJSjPpZwdmmNjyxKW1K3LDXxqxw91Egaqkh/yheBIVtKPt4/1eybKVdCx3g==" 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /spec/fixtures/multiple_versions/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | find-versions@4.0.0: 6 | version "4.0.0" 7 | resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-4.0.0.tgz#3c57e573bf97769b8cb8df16934b627915da4965" 8 | integrity sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ== 9 | dependencies: 10 | semver-regex "^3.1.2" 11 | 12 | semver-regex@^3.1.2: 13 | version "3.1.3" 14 | resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.3.tgz#b2bcc6f97f63269f286994e297e229b6245d0dc3" 15 | integrity sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ== 16 | 17 | semver-regex@^4.0.0: 18 | version "4.0.2" 19 | resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-4.0.2.tgz#fd3124efe81647b33eb90a9de07cb72992424a02" 20 | integrity sha512-xyuBZk1XYqQkB687hMQqrCP+J9bdJSjPpZwdmmNjyxKW1K3LDXxqxw91Egaqkh/yheBIVtKPt4/1eybKVdCx3g== 21 | -------------------------------------------------------------------------------- /spec/fixtures/npm-local-file/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "npm-bad", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "npm-bad", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "left-pad": "^1.3.0", 13 | "other-package": "file:src/other-package", 14 | "react": "^18.3.1" 15 | } 16 | }, 17 | "node_modules/js-tokens": { 18 | "version": "4.0.0", 19 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 20 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 21 | }, 22 | "node_modules/left-pad": { 23 | "version": "1.3.0", 24 | "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", 25 | "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", 26 | "deprecated": "use String.prototype.padStart()" 27 | }, 28 | "node_modules/lodash": { 29 | "version": "4.17.21", 30 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 31 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 32 | "dev": true 33 | }, 34 | "node_modules/loose-envify": { 35 | "version": "1.4.0", 36 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 37 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 38 | "dependencies": { 39 | "js-tokens": "^3.0.0 || ^4.0.0" 40 | }, 41 | "bin": { 42 | "loose-envify": "cli.js" 43 | } 44 | }, 45 | "node_modules/other-package": { 46 | "resolved": "src/other-package", 47 | "link": true 48 | }, 49 | "node_modules/react": { 50 | "version": "18.3.1", 51 | "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", 52 | "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", 53 | "dependencies": { 54 | "loose-envify": "^1.1.0" 55 | }, 56 | "engines": { 57 | "node": ">=0.10.0" 58 | } 59 | }, 60 | "src/other-package": { 61 | "version": "1.0.0", 62 | "license": "ISC", 63 | "devDependencies": { 64 | "lodash": "^4.17.21" 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /spec/fixtures/npm-local-file/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "npm-bad", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "left-pad": "^1.3.0", 13 | "other-package": "file:src/other-package", 14 | "react": "^18.3.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /spec/fixtures/npm-local-file/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "js-tokens@^3.0.0 || ^4.0.0": 6 | version "4.0.0" 7 | resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" 8 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 9 | 10 | left-pad@^1.3.0: 11 | version "1.3.0" 12 | resolved "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz" 13 | integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== 14 | 15 | loose-envify@^1.1.0: 16 | version "1.4.0" 17 | resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" 18 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 19 | dependencies: 20 | js-tokens "^3.0.0 || ^4.0.0" 21 | 22 | "other-package@file:src/other-package": 23 | version "1.0.0" 24 | 25 | react@^18.3.1: 26 | version "18.3.1" 27 | resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" 28 | integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== 29 | dependencies: 30 | loose-envify "^1.1.0" 31 | -------------------------------------------------------------------------------- /spec/fixtures/npm-lockfile-version-1/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "an-test-lib", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "an-test-lib", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "find-versions": "4.0.0", 13 | "semver-regex": "^4.0.0" 14 | } 15 | }, 16 | "node_modules/find-versions": { 17 | "version": "4.0.0", 18 | "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", 19 | "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", 20 | "dependencies": { 21 | "semver-regex": "^3.1.2" 22 | }, 23 | "engines": { 24 | "node": ">=10" 25 | }, 26 | "funding": { 27 | "url": "https://github.com/sponsors/sindresorhus" 28 | } 29 | }, 30 | "node_modules/find-versions/node_modules/semver-regex": { 31 | "version": "3.1.4", 32 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", 33 | "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", 34 | "engines": { 35 | "node": ">=8" 36 | }, 37 | "funding": { 38 | "url": "https://github.com/sponsors/sindresorhus" 39 | } 40 | }, 41 | "node_modules/semver-regex": { 42 | "version": "4.0.5", 43 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", 44 | "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", 45 | "engines": { 46 | "node": ">=12" 47 | }, 48 | "funding": { 49 | "url": "https://github.com/sponsors/sindresorhus" 50 | } 51 | } 52 | }, 53 | "dependencies": { 54 | "find-versions": { 55 | "version": "4.0.0", 56 | "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", 57 | "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", 58 | "requires": { 59 | "semver-regex": "^3.1.2" 60 | }, 61 | "dependencies": { 62 | "semver-regex": { 63 | "version": "3.1.4", 64 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", 65 | "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==" 66 | } 67 | } 68 | }, 69 | "semver-regex": { 70 | "version": "4.0.5", 71 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", 72 | "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==" 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /spec/fixtures/npm-lockfile-version-2/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "an-test-lib", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "an-test-lib", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "find-versions": "4.0.0", 13 | "semver-regex": "^4.0.0" 14 | } 15 | }, 16 | "node_modules/find-versions": { 17 | "version": "4.0.0", 18 | "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", 19 | "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", 20 | "dependencies": { 21 | "semver-regex": "^3.1.2" 22 | }, 23 | "engines": { 24 | "node": ">=10" 25 | }, 26 | "funding": { 27 | "url": "https://github.com/sponsors/sindresorhus" 28 | } 29 | }, 30 | "node_modules/find-versions/node_modules/semver-regex": { 31 | "version": "3.1.4", 32 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", 33 | "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", 34 | "engines": { 35 | "node": ">=8" 36 | }, 37 | "funding": { 38 | "url": "https://github.com/sponsors/sindresorhus" 39 | } 40 | }, 41 | "node_modules/semver-regex": { 42 | "version": "4.0.5", 43 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", 44 | "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", 45 | "engines": { 46 | "node": ">=12" 47 | }, 48 | "funding": { 49 | "url": "https://github.com/sponsors/sindresorhus" 50 | } 51 | } 52 | }, 53 | "dependencies": { 54 | "find-versions": { 55 | "version": "4.0.0", 56 | "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", 57 | "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", 58 | "requires": { 59 | "semver-regex": "^3.1.2" 60 | }, 61 | "dependencies": { 62 | "semver-regex": { 63 | "version": "3.1.4", 64 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", 65 | "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==" 66 | } 67 | } 68 | }, 69 | "semver-regex": { 70 | "version": "4.0.5", 71 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", 72 | "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==" 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /spec/fixtures/npm-lockfile-version-3/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "an-test-lib", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "an-test-lib", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "find-versions": "4.0.0", 13 | "semver-regex": "^4.0.0" 14 | } 15 | }, 16 | "node_modules/alias-package-name": { 17 | "name": "@some-scope/actual-package", 18 | "version": "1.1.3", 19 | "resolved": "https://registry.npmjs.org/days-until-christmas/-/actual-package-1.1.3.tgz", 20 | "integrity": "sha512-Mo7Byt8jDBtk09ix3hwEYv3hASTAYYTjvyqGnZP+WpxdZHKXb+HTCiNg4tLKDXAharS36RBq8tBQ/AdPbdQn3g==", 21 | "license": "MIT" 22 | }, 23 | "node_modules/find-versions": { 24 | "version": "4.0.0", 25 | "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", 26 | "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", 27 | "dependencies": { 28 | "semver-regex": "^3.1.2" 29 | }, 30 | "engines": { 31 | "node": ">=10" 32 | }, 33 | "funding": { 34 | "url": "https://github.com/sponsors/sindresorhus" 35 | } 36 | }, 37 | "node_modules/find-versions/node_modules/semver-regex": { 38 | "version": "3.1.4", 39 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", 40 | "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", 41 | "engines": { 42 | "node": ">=8" 43 | }, 44 | "funding": { 45 | "url": "https://github.com/sponsors/sindresorhus" 46 | } 47 | }, 48 | "node_modules/semver-regex": { 49 | "version": "4.0.5", 50 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", 51 | "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", 52 | "engines": { 53 | "node": ">=12" 54 | }, 55 | "funding": { 56 | "url": "https://github.com/sponsors/sindresorhus" 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /spec/fixtures/npm-ls.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fake-npm-ls-json-output", 3 | "version": "1.0.3", 4 | "dependencies": { 5 | "ansicolor": { 6 | "version": "1.1.93", 7 | "from": "ansicolor@1.1.93", 8 | "resolved": "https://registry.npmjs.org/ansicolor/-/ansicolor-1.1.93.tgz" 9 | }, 10 | "babel-cli": { 11 | "version": "6.26.0", 12 | "from": "babel-cli@^6.26.0", 13 | "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", 14 | "dependencies": { 15 | "debug": { 16 | "version": "2.6.9", 17 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 18 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 19 | "dev": true, 20 | "requires": { 21 | "ms": "2.0.0" 22 | } 23 | }, 24 | "babel-polyfill": { 25 | "version": "6.26.0", 26 | "from": "babel-polyfill@^6.26.0", 27 | "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", 28 | "dependencies": { 29 | "core-js": { 30 | "version": "2.6.12", 31 | "from": "core-js@2.6.12", 32 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz" 33 | } 34 | } 35 | }, 36 | "lodash": { 37 | "version": "4.17.21", 38 | "from": "lodash@4.17.21", 39 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" 40 | } 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /spec/fixtures/nuget_project.assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "targets": { 4 | "empty-group-earlier-alphabetically": {}, 5 | "net2.2": { 6 | "c/1.0.0": { 7 | "type": "package" 8 | } 9 | }, 10 | "net5.0": { 11 | "a/1.0.0": { 12 | "type": "package" 13 | }, 14 | "b/1.0.0": { 15 | "type": "package", 16 | "dependencies": { 17 | "a": "1.0.0" 18 | } 19 | }, 20 | "another_project/1.0.0": { 21 | "type": "project", 22 | "framework": ".NETCoreApp,Version=v5.0", 23 | "dependencies": { 24 | "a": "1.0.0", 25 | "b": "1.0.0", 26 | "c": "1.0.0" 27 | } 28 | } 29 | }, 30 | "z-empty-group-later-alphabetically": {} 31 | } 32 | } -------------------------------------------------------------------------------- /spec/fixtures/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "librarian", 3 | "version": "1.0.0", 4 | "description": "Integrate GH webhooks with Libraries.io", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "nodemon app.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "Mauro Pompilio", 11 | "license": "MIT", 12 | "dependencies": { 13 | "// my comment": [ 14 | "This is a valid", 15 | "comment in NPM." 16 | ], 17 | "babel": "^4.6.6", 18 | "alias-package-name": "npm:@some-scope/actual-package@^1.1.3" 19 | }, 20 | "devDependencies": { 21 | "mocha": "^2.2.1" 22 | }, 23 | "packageManager": "pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531" 24 | } 25 | -------------------------------------------------------------------------------- /spec/fixtures/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /spec/fixtures/paket.lock: -------------------------------------------------------------------------------- 1 | FRAMEWORK: >= NET40 2 | NUGET 3 | remote: https://www.nuget.org/api/v2 4 | Argu (2.1) 5 | Mono.Cecil (0.9.6.1) 6 | Chessie (0.5.1) 7 | FSharp.Core 8 | FSharp.Core (4.0.0.1) - redirects: force 9 | Mono.Cecil (0.9.6.1) 10 | Newtonsoft.Json (9.0.1) - redirects: force -------------------------------------------------------------------------------- /spec/fixtures/pip-compile/requirements-extras.in: -------------------------------------------------------------------------------- 1 | urllib3[secure]==1.0.0 2 | django-dbfilestorage==1.0.0 -------------------------------------------------------------------------------- /spec/fixtures/pip-compile/requirements.frozen: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with python 3.8 3 | # To update, run: 4 | # 5 | # pip-compile requirements.in 6 | # 7 | black==21.9b0 8 | # via -r requirements.in 9 | 10 | # The following packages are considered to be unsafe in a requirements file: 11 | # pip 12 | # setuptools 13 | -------------------------------------------------------------------------------- /spec/fixtures/pip-compile/requirements.in: -------------------------------------------------------------------------------- 1 | invoke 2 | black 3 | google-cloud-storage 4 | six 5 | progress 6 | questionary 7 | pyyaml 8 | semver 9 | Jinja2 10 | pip-tools 11 | -------------------------------------------------------------------------------- /spec/fixtures/pip-compile/requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with python 3.8 3 | # To update, run: 4 | # 5 | # pip-compile requirements.in 6 | # 7 | black==21.9b0 8 | # via -r requirements.in 9 | cachetools==4.2.2 10 | # via google-auth 11 | certifi==2021.5.30 12 | # via requests 13 | charset-normalizer==2.0.6 14 | # via requests 15 | click==8.0.1 16 | # via 17 | # black 18 | # pip-tools 19 | google-api-core==2.0.1 20 | # via 21 | # google-cloud-core 22 | # google-cloud-storage 23 | google-auth==2.1.0 24 | # via 25 | # google-api-core 26 | # google-cloud-core 27 | # google-cloud-storage 28 | google-cloud-core==2.0.0 29 | # via google-cloud-storage 30 | google-cloud-storage==1.42.2 31 | # via -r requirements.in 32 | google-crc32c==1.2.0 33 | # via google-resumable-media 34 | google-resumable-media==2.0.3 35 | # via google-cloud-storage 36 | googleapis-common-protos==1.53.0 37 | # via google-api-core 38 | idna==3.2 39 | # via requests 40 | invoke==1.6.0 41 | # via -r requirements.in 42 | jinja2==3.0.1 43 | # via -r requirements.in 44 | markupsafe==2.0.1 45 | # via jinja2 46 | mypy-extensions==0.4.3 47 | # via black 48 | pathspec==0.9.0 49 | # via black 50 | pep517==0.11.0 51 | # via pip-tools 52 | pip-tools==6.2.0 53 | # via -r requirements.in 54 | platformdirs==2.3.0 55 | # via black 56 | progress==1.6 57 | # via -r requirements.in 58 | prompt-toolkit==3.0.20 59 | # via questionary 60 | protobuf==3.18.0 61 | # via 62 | # google-api-core 63 | # google-cloud-storage 64 | # googleapis-common-protos 65 | pyasn1==0.4.8 66 | # via 67 | # pyasn1-modules 68 | # rsa 69 | pyasn1-modules==0.2.8 70 | # via google-auth 71 | pyyaml==5.4.1 72 | # via -r requirements.in 73 | questionary==1.10.0 74 | # via -r requirements.in 75 | regex==2021.8.28 76 | # via black 77 | requests==2.26.0 78 | # via 79 | # google-api-core 80 | # google-cloud-storage 81 | rsa==4.7.2 82 | # via google-auth 83 | semver==2.13.0 84 | # via -r requirements.in 85 | six==1.16.0 86 | # via 87 | # -r requirements.in 88 | # google-cloud-storage 89 | tomli==1.2.1 90 | # via 91 | # black 92 | # pep517 93 | typing-extensions==3.10.0.2 94 | # via black 95 | urllib3==1.26.6 96 | # via requests 97 | wcwidth==0.2.5 98 | # via prompt-toolkit 99 | wheel==0.37.0 100 | # via pip-tools 101 | 102 | # The following packages are considered to be unsafe in a requirements file: 103 | # pip 104 | # setuptools 105 | -------------------------------------------------------------------------------- /spec/fixtures/pip-resolved-dependencies.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.2.7 2 | Django==3.0.6 3 | sqlparse==0.3.1 4 | -------------------------------------------------------------------------------- /spec/fixtures/pnpm-lockfile-version-5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "some-package", 3 | "version": "1.0.0", 4 | "description": "A fake package fixture for NPM.", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "nodemon app.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "babel": "^4.6.6", 14 | "alias-package": "npm:zod" 15 | }, 16 | "devDependencies": { 17 | "mocha": "^2.2.1" 18 | } 19 | } -------------------------------------------------------------------------------- /spec/fixtures/pnpm-lockfile-version-6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "some-package", 3 | "version": "1.0.0", 4 | "description": "A fake package fixture for NPM.", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "nodemon app.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "babel": "^4.6.6", 14 | "alias-package": "npm:zod" 15 | }, 16 | "devDependencies": { 17 | "mocha": "^2.2.1" 18 | } 19 | } -------------------------------------------------------------------------------- /spec/fixtures/pnpm-lockfile-version-9/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "some-package", 3 | "version": "1.0.0", 4 | "description": "A fake package fixture for NPM.", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "nodemon app.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "babel": "^4.6.6", 14 | "alias-package": "npm:zod" 15 | }, 16 | "devDependencies": { 17 | "mocha": "^2.2.1" 18 | } 19 | } -------------------------------------------------------------------------------- /spec/fixtures/project.clj: -------------------------------------------------------------------------------- 1 | (defproject clojars-json "0.1.0" 2 | :description "FIXME: write description" 3 | :url "http://example.com/FIXME" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | :dependencies [[org.clojure/clojure "1.6.0"] 7 | [cheshire "5.4.0"] 8 | [compojure "1.3.2"] 9 | [ring/ring-defaults "0.1.2"] 10 | [ring/ring-jetty-adapter "1.2.1"]] 11 | :plugins [[lein-ring "0.8.13"]] 12 | :min-lein-version "2.0.0" 13 | :ring {:handler clojars-json.core/app} 14 | :uberjar-name "clojars-json.jar" 15 | :profiles {:uberjar {:aot :all}} 16 | :main clojars-json.core 17 | ) 18 | -------------------------------------------------------------------------------- /spec/fixtures/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See http://pub.dartlang.org/doc/glossary.html#lockfile 3 | packages: 4 | analyzer: 5 | description: analyzer 6 | source: hosted 7 | version: "0.24.6" 8 | args: 9 | description: args 10 | source: hosted 11 | version: "0.12.2+6" 12 | barback: 13 | description: barback 14 | source: hosted 15 | version: "0.15.2+7" 16 | which: 17 | description: which 18 | source: hosted 19 | version: "0.1.3" 20 | sdk: ">=1.13.0 <2.0.0" 21 | -------------------------------------------------------------------------------- /spec/fixtures/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: angular 2 | version: '1.1.0' 3 | authors: 4 | - Misko Hevery 5 | - Pavel Jbanov 6 | - James deBoer 7 | - Chirayu Krishnappa 8 | - Matias Niemela 9 | - Paul Rohde 10 | - Victor Berchet 11 | - Rado Kirov 12 | description: Angular for dart. 13 | homepage: https://angulardart.org 14 | environment: 15 | sdk: '>=1.4.0' 16 | dependencies: 17 | analyzer: '>=0.22.0 <0.25.0' 18 | args: '>=0.12.0 <0.13.0' 19 | dev_dependencies: 20 | benchmark_harness: '>=1.0.0 <2.0.0' 21 | guinness: '>=0.1.9 <0.2.0' 22 | -------------------------------------------------------------------------------- /spec/fixtures/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "tidelift" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Tyrel Souza "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.7" 9 | django = "^3.0.7" 10 | pathlib2 = [ 11 | { version = "2.3.7.post1", python = ">=3.7" }, 12 | { version = "2.3.6", markers = "python_version < '3.7' and sys_platform == 'win32'" }, 13 | { version = "2.3.5", python = "<3.7", platform = "linux" }, 14 | # same version but from different source -- SHALL be treated as non-identical 15 | { git = "https://github.com/jazzband/pathlib2.git", tag = "2.3.5", python = "<3.7", platform = "darwin" }, 16 | ] 17 | 18 | 19 | # Old way to define development deps (<1.2.0) 20 | Zope_interface = "6.3" 21 | [tool.poetry.dev-dependencies] 22 | pytest = "^5.2" 23 | 24 | # New way to define development deps (>=1.2.0) 25 | [tool.poetry.group.dev.dependencies] 26 | wcwidth = "*" 27 | 28 | [tool.poetry.group.test.dependencies] 29 | sqlparse = "0.4.4" 30 | 31 | [build-system] 32 | requires = ["poetry>=0.12"] 33 | build-backend = "poetry.masonry.api" 34 | -------------------------------------------------------------------------------- /spec/fixtures/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with python 3.6 3 | # To update, run: 4 | # 5 | # pip-compile requirements-dev.in 6 | # 7 | astroid==2.9.0 8 | # via pylint 9 | attrs==21.4.0 10 | # via 11 | # hypothesis 12 | # pytest 13 | boto3==1.20.26 14 | # via -r requirements-dev.in 15 | botocore==1.23.26 16 | # via 17 | # boto3 18 | # s3transfer 19 | certifi==2021.10.8 20 | # via requests 21 | charset-normalizer==2.0.9 22 | # via requests 23 | coverage[toml]==6.2 24 | # via 25 | # -r requirements-dev.in 26 | # pytest-cov 27 | doc8==0.10.1 28 | # via -r requirements-dev.in 29 | docutils==0.17.1 30 | # via 31 | # -r requirements-dev.in 32 | # doc8 33 | # restructuredtext-lint 34 | flake8==4.0.1 35 | # via -r requirements-dev.in 36 | hypothesis==6.31.6 37 | # via -r requirements-dev.in 38 | idna==3.3 39 | # via requests 40 | importlib-metadata==4.2.0 41 | # via 42 | # flake8 43 | # pluggy 44 | # pytest 45 | # stevedore 46 | iniconfig==1.1.1 47 | # via pytest 48 | isort==5.10.1 49 | # via pylint 50 | jmespath==0.10.0 51 | # via 52 | # boto3 53 | # botocore 54 | lazy-object-proxy==1.7.1 55 | # via astroid 56 | mccabe==0.6.1 57 | # via 58 | # flake8 59 | # pylint 60 | mock==4.0.3 61 | # via -r requirements-dev.in 62 | mypy==0.812 63 | # via -r requirements-dev.in 64 | mypy-extensions==0.4.3 65 | # via 66 | # -r requirements-dev.in 67 | # mypy 68 | packaging==21.3 69 | # via pytest 70 | pbr==5.8.0 71 | # via stevedore 72 | platformdirs==2.4.0 73 | # via pylint 74 | pluggy==1.0.0 75 | # via pytest 76 | py==1.11.0 77 | # via pytest 78 | pycodestyle==2.8.0 79 | # via flake8 80 | pydocstyle==6.1.1 81 | # via -r requirements-dev.in 82 | pyflakes==2.4.0 83 | # via flake8 84 | pygments==2.11.0 85 | # via 86 | # -r requirements-dev.in 87 | # doc8 88 | pylint==2.12.2 89 | # via -r requirements-dev.in 90 | pyparsing==3.0.6 91 | # via packaging 92 | pytest==6.2.5 93 | # via 94 | # -r requirements-dev.in 95 | # pytest-cov 96 | pytest-cov==3.0.0 97 | # via -r requirements-dev.in 98 | python-dateutil==2.8.2 99 | # via botocore 100 | requests==2.26.0 101 | # via -r requirements-dev.in 102 | restructuredtext-lint==1.3.2 103 | # via doc8 104 | s3transfer==0.5.0 105 | # via boto3 106 | six==1.16.0 107 | # via python-dateutil 108 | snowballstemmer==2.2.0 109 | # via pydocstyle 110 | sortedcontainers==2.4.0 111 | # via hypothesis 112 | stevedore==3.5.0 113 | # via doc8 114 | toml==0.10.2 115 | # via 116 | # pylint 117 | # pytest 118 | tomli==1.2.3 119 | # via coverage 120 | typed-ast==1.4.3 121 | # via 122 | # astroid 123 | # mypy 124 | typing-extensions==4.0.1 125 | # via 126 | # astroid 127 | # importlib-metadata 128 | # mypy 129 | # pylint 130 | urllib3==1.26.7 131 | # via 132 | # botocore 133 | # requests 134 | websocket-client==1.2.3 135 | # via -r requirements-dev.in 136 | wheel==0.37.1 137 | # via -r requirements-dev.in 138 | wrapt==1.13.3 139 | # via astroid 140 | zipp==3.6.0 141 | # via importlib-metadata 142 | 143 | # The following packages are considered to be unsafe in a requirements file: 144 | # setuptools 145 | -------------------------------------------------------------------------------- /spec/fixtures/requirements-git.txt: -------------------------------------------------------------------------------- 1 | git+https://github.com/pygame/pygame@2.1.2#egg=pygame 2 | -------------------------------------------------------------------------------- /spec/fixtures/requirements.frozen: -------------------------------------------------------------------------------- 1 | asgiref==3.2.7 2 | Django==3.0.6 3 | sqlparse==0.3.1 4 | -------------------------------------------------------------------------------- /spec/fixtures/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask == 0.8 # awful comment 2 | #Jinja2==2.6 3 | zope.component==4.2.2 4 | scikit-learn==0.16.1 5 | Beaker>=1.6.5 6 | certifi==0.0.8 7 | chardet==1.0.1 8 | distribute==0.6.24 9 | gunicorn==0.14.2 10 | requests==0.11.1 11 | Django == 2.0beta1 12 | -------------------------------------------------------------------------------- /spec/fixtures/requirements/test.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with python 3.8 3 | # To update, run: 4 | # 5 | # pip-compile --output-file=requirements/test.txt hypothesis-python/setup.py requirements/test.in 6 | # 7 | attrs==21.4.0 8 | # via 9 | # hypothesis (hypothesis-python/setup.py) 10 | # pytest 11 | exceptiongroup==1.0.0rc8 ; python_version < "3.11" 12 | # via hypothesis (hypothesis-python/setup.py) 13 | execnet==1.9.0 14 | # via pytest-xdist 15 | iniconfig==1.1.1 16 | # via pytest 17 | packaging==21.3 18 | # via pytest 19 | pexpect==4.8.0 20 | # via -r requirements/test.in 21 | pluggy==1.0.0 22 | # via pytest 23 | ptyprocess==0.7.0 24 | # via pexpect 25 | py==1.11.0 26 | # via 27 | # pytest 28 | # pytest-forked 29 | pyparsing==3.0.9 30 | # via packaging 31 | pytest==7.1.2 32 | # via 33 | # -r requirements/test.in 34 | # pytest-forked 35 | # pytest-xdist 36 | pytest-forked==1.4.0 37 | # via pytest-xdist 38 | pytest-xdist==2.5.0 39 | # via -r requirements/test.in 40 | sortedcontainers==2.4.0 41 | # via hypothesis (hypothesis-python/setup.py) 42 | tomli==2.0.1 43 | # via pytest 44 | -------------------------------------------------------------------------------- /spec/fixtures/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup(name='political-memory', 4 | version='0.0.1', 5 | description='OpenShift App', 6 | packages=['political_memory'], 7 | package_dir={'political_memory': '.'}, 8 | author='James Pic, Laurent Peuch, Arnaud Fabre', 9 | author_email='cortex@worlddomination.be', 10 | url='http://github.com/political-memory/political_memory/', 11 | install_requires=[ 12 | # -*- Install requires: -*- 13 | 'django-bootstrap3>=6.2,<6.3', 14 | 'lesscpy', 15 | 'unicodecsv==0.14.1', 16 | 'django-coffeescript>=0.7,<0.8', 17 | 'django-compressor>=1.6,<1.7', 18 | 'django-datetime-widget>=0.9,<1.0', 19 | 'django-filter>=0.11,<0.12', 20 | 'django-representatives-votes>=0.0.13', 21 | 'django-representatives>=0.0.14', 22 | 'django-taggit>=0.17,<0.18', 23 | 'django>=1.8,<1.9', 24 | 'djangorestframework>=3.2.0,<3.3.0', 25 | 'hamlpy>=0.82,<0.83', 26 | 'ijson>=2.2,<2.3', 27 | 'python-dateutil>=2.4,<2.5', 28 | 'pytz==2015.7', 29 | 'django-suit', 30 | 'dummy==2.0beta1', 31 | ], 32 | extras_require={ 33 | 'testing': [ 34 | 'django-responsediff', 35 | 'flake8', 36 | 'pep8', 37 | 'pytest', 38 | 'pytest-django', 39 | 'pytest-cov', 40 | 'codecov', 41 | ] 42 | } 43 | ) 44 | -------------------------------------------------------------------------------- /spec/fixtures/setup2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup 4 | 5 | setup( 6 | name="vapprun", 7 | version="1.0.1", 8 | author="Yann Hodique", 9 | author_email="hodiquey@vmware.com", 10 | namespace_packages=['vmw'], 11 | packages=['vmw', 'vmw.vapprun'], 12 | package_data={'vmw.vapprun': ['templates/*']}, 13 | scripts=['bin/vapprun'], 14 | setup_requires=['setuptools'], 15 | install_requires=['setuptools', 'six'], 16 | ) 17 | -------------------------------------------------------------------------------- /spec/fixtures/shard.lock: -------------------------------------------------------------------------------- 1 | version: 1.0 2 | shards: 3 | common_mark: 4 | github: ysbaddaden/crystal-cmark 5 | version: 0.1.0 6 | 7 | frost: 8 | github: ysbaddaden/frost 9 | commit: 4042fc55a0865df8cbcb9a389527e9557aa8f280 10 | 11 | minitest: 12 | github: ysbaddaden/minitest.cr 13 | version: 0.3.1 14 | 15 | pg: 16 | github: will/crystal-pg 17 | version: 0.5.0 18 | 19 | pool: 20 | github: ysbaddaden/pool 21 | version: 0.2.1 22 | 23 | selenium-webdriver: 24 | github: ysbaddaden/selenium-webdriver-crystal 25 | version: 0.1.0 26 | 27 | shards: 28 | github: ysbaddaden/shards 29 | version: 0.6.0 30 | -------------------------------------------------------------------------------- /spec/fixtures/shard.yml: -------------------------------------------------------------------------------- 1 | name: registry 2 | version: 0.1.0 3 | description: Web registry for Crystal Shards 4 | 5 | authors: 6 | - Julien Portalier 7 | 8 | dependencies: 9 | frost: 10 | github: ysbaddaden/frost 11 | branch: master 12 | 13 | shards: 14 | github: ysbaddaden/shards 15 | 16 | common_mark: 17 | github: ysbaddaden/crystal-cmark 18 | 19 | development_dependencies: 20 | minitest: 21 | github: ysbaddaden/minitest.cr 22 | version: ">= 0.2.0" 23 | 24 | selenium-webdriver: 25 | github: ysbaddaden/selenium-webdriver-crystal 26 | 27 | license: Apache-2.0 28 | -------------------------------------------------------------------------------- /spec/fixtures/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "rcwA7Jmo3eZ4bEQb8mTI78haZfc=", 7 | "path": "github.com/Bowery/prompt", 8 | "revision": "d43c2707a6c5a152a344c64bb4fed657e2908a81", 9 | "revisionTime": "2016-08-08T16:52:56Z" 10 | }, 11 | { 12 | "checksumSHA1": "6VGFARaK8zd23IAiDf7a+gglC8k=", 13 | "path": "github.com/dchest/safefile", 14 | "revision": "855e8d98f1852d48dde521e0522408d1fe7e836a", 15 | "revisionTime": "2015-10-22T12:31:44+02:00" 16 | }, 17 | { 18 | "checksumSHA1": "3VJcSYFds0zeIO5opOs0AoKm3Mw=", 19 | "path": "github.com/google/shlex", 20 | "revision": "6f45313302b9c56850fc17f99e40caebce98c716", 21 | "revisionTime": "2015-01-27T13:39:51Z" 22 | }, 23 | { 24 | "checksumSHA1": "GcaTbmmzSGqTb2X6qnNtmDyew1Q=", 25 | "path": "github.com/pkg/errors", 26 | "revision": "a2d6902c6d2a2f194eb3fb474981ab7867c81505", 27 | "revisionTime": "2016-06-27T22:23:52Z" 28 | }, 29 | { 30 | "checksumSHA1": "uwKP1AVzd+lrTMlXVFjZXXHzB7U=", 31 | "path": "golang.org/x/tools/go/vcs", 32 | "revision": "1727758746e7a08feaaceb9366d1468498ac2ac2", 33 | "revisionTime": "2016-06-24T22:27:06Z" 34 | } 35 | ], 36 | "rootPath": "github.com/kardianos/govendor" 37 | } 38 | -------------------------------------------------------------------------------- /spec/fixtures/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | [ 4 | "accounts-base", 5 | "1.1.2" 6 | ], 7 | [ 8 | "application-configuration", 9 | "1.0.3" 10 | ], 11 | [ 12 | "base64", 13 | "1.0.1" 14 | ], 15 | [ 16 | "binary-heap", 17 | "1.0.1" 18 | ], 19 | [ 20 | "tracker", 21 | "1.0.3" 22 | ], 23 | [ 24 | "underscore", 25 | "1.0.1" 26 | ] 27 | ], 28 | "pluginDependencies": [], 29 | "toolVersion": "meteor-tool@1.0.35", 30 | "format": "1.0" 31 | } 32 | -------------------------------------------------------------------------------- /spec/fixtures/yarn-v4-lockfile/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yarn-lock", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "packageManager": "yarn@4.3.1", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "left-pad": "^1.3.0", 14 | "react": "^18.3.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /spec/fixtures/yarn-v4-lockfile/yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 8 6 | cacheKey: 10c0 7 | 8 | "js-tokens@npm:^3.0.0 || ^4.0.0": 9 | version: 4.0.0 10 | resolution: "js-tokens@npm:4.0.0" 11 | checksum: 10c0/e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed 12 | languageName: node 13 | linkType: hard 14 | 15 | "left-pad@npm:^1.3.0": 16 | version: 1.3.0 17 | resolution: "left-pad@npm:1.3.0" 18 | checksum: 10c0/3fb59c76e281a2f5c810ad71dbbb8eba8b10c6cf94733dc7f27b8c516a5376cacea53543e76f6ae477d866c8954b27f1e15ca349424c2542474eb5bb1d2b6955 19 | languageName: node 20 | linkType: hard 21 | 22 | "loose-envify@npm:^1.1.0": 23 | version: 1.4.0 24 | resolution: "loose-envify@npm:1.4.0" 25 | dependencies: 26 | js-tokens: "npm:^3.0.0 || ^4.0.0" 27 | bin: 28 | loose-envify: cli.js 29 | checksum: 10c0/655d110220983c1a4b9c0c679a2e8016d4b67f6e9c7b5435ff5979ecdb20d0813f4dec0a08674fcbdd4846a3f07edbb50a36811fd37930b94aaa0d9daceb017e 30 | languageName: node 31 | linkType: hard 32 | 33 | "react@npm:^18.3.1": 34 | version: 18.3.1 35 | resolution: "react@npm:18.3.1" 36 | dependencies: 37 | loose-envify: "npm:^1.1.0" 38 | checksum: 10c0/283e8c5efcf37802c9d1ce767f302dd569dd97a70d9bb8c7be79a789b9902451e0d16334b05d73299b20f048cbc3c7d288bbbde10b701fa194e2089c237dbea3 39 | languageName: node 40 | linkType: hard 41 | 42 | "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin": 43 | version: 2.3.2 44 | resolution: "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin::version=2.3.2&hash=df0bf1" 45 | dependencies: 46 | node-gyp: "npm:latest" 47 | conditions: os=darwin 48 | languageName: node 49 | linkType: hard 50 | 51 | "strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": 52 | version: 6.0.1 53 | resolution: "strip-ansi@npm:6.0.1" 54 | dependencies: 55 | ansi-regex: "npm:^5.0.1" 56 | checksum: 10/ae3b5436d34fadeb6096367626ce987057713c566e1e7768818797e00ac5d62023d0f198c4e681eae9e20701721980b26a64a8f5b91238869592a9c6800719a2 57 | languageName: node 58 | linkType: hard 59 | 60 | "yarn-lock@workspace:.": 61 | version: 0.0.0-use.local 62 | resolution: "yarn-lock@workspace:." 63 | dependencies: 64 | left-pad: "npm:^1.3.0" 65 | react: "npm:^18.3.1" 66 | languageName: unknown 67 | linkType: soft 68 | -------------------------------------------------------------------------------- /spec/fixtures/yarn-with-git-repo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fake-yarn", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "vue": "https://github.com/vuejs/vue.git#v2.6.12" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /spec/fixtures/yarn-with-git-repo/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "vue@https://github.com/vuejs/vue.git#v2.6.12": 6 | version "2.6.12" 7 | resolved "https://github.com/vuejs/vue.git#bb253db0b3e17124b6d1fe93fbf2db35470a1347" 8 | -------------------------------------------------------------------------------- /spec/multi_parsers/cyclonedx_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::MultiParsers::CycloneDX do 6 | let(:unmapped_component) { "pkg:apt/krita/5.0.5" } 7 | 8 | let!(:parser_class) do 9 | k = Class.new do 10 | def platform_name = "whatever" 11 | end 12 | 13 | k.send(:include, described_class) 14 | k 15 | end 16 | 17 | let!(:parser) { parser_class.new } 18 | 19 | it "handles malformed json" do 20 | expect { parser.parse_cyclonedx_json("{}") }.to raise_error(described_class::NoComponents) 21 | end 22 | 23 | it "handles malformed xml" do 24 | expect { parser.parse_cyclonedx_xml('') }.to raise_error(described_class::NoComponents) 25 | end 26 | 27 | it "handles empty json components" do 28 | expect(parser.parse_cyclonedx_json('{ "components": [] }')).to eq(nil) 29 | end 30 | 31 | it "handles empty xml components" do 32 | expect(parser.parse_cyclonedx_xml('')).to eq(nil) 33 | end 34 | 35 | it "handles unmapped json component" do 36 | expect(parser.parse_cyclonedx_json(%({ "components": [{ "purl": "#{unmapped_component}" }] }))).to eq(nil) 37 | end 38 | 39 | it "handles unmapped xml component" do 40 | expect(parser.parse_cyclonedx_xml(%(#{unmapped_component}))).to eq(nil) 41 | end 42 | 43 | it "handles no xml pragma" do 44 | expect(parser.parse_cyclonedx_xml(%(#{unmapped_component}))).to eq(nil) 45 | end 46 | 47 | describe "ManifestEntries#parse!" do 48 | it "should not mutate the manifest sent in" do 49 | queue = [1, 2, 3] 50 | 51 | entries = described_class::ManifestEntries.new(parse_queue: queue) 52 | 53 | entries.parse! do |_item, _parse_queue| 54 | nil 55 | end 56 | 57 | expect(queue.count).to eq(3) 58 | end 59 | end 60 | 61 | context "correct parsers implement it" do 62 | Bibliothecary::PurlUtil::PURL_TYPE_MAPPING.each_value do |parser| 63 | constant_symbol = Bibliothecary::Parsers.constants.find { |c| c.to_s.downcase.gsub(/[^a-z]/, "") == parser.to_s.downcase.gsub(/[^a-z]/, "") } 64 | constant = Bibliothecary::Parsers.const_get(constant_symbol) 65 | 66 | # only analyzers have platform_name on the class 67 | next unless constant.respond_to?(:platform_name) 68 | 69 | it "#{constant_symbol} should implement CycloneDX" do 70 | expect(constant.respond_to?(:parse_cyclonedx_xml)).to eq(true) 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /spec/parsers/bower_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Parsers::Bower do 6 | it "has a platform name" do 7 | expect(described_class.platform_name).to eq("bower") 8 | end 9 | 10 | it "parses dependencies from bower.json" do 11 | expect(described_class.analyse_contents("bower.json", load_fixture("bower.json"))).to eq({ 12 | platform: "bower", 13 | path: "bower.json", 14 | dependencies: [ 15 | Bibliothecary::Dependency.new(name: "jquery", requirement: ">= 1.9.1", type: "runtime", source: "bower.json"), 16 | ], 17 | kind: "manifest", 18 | success: true, 19 | }) 20 | end 21 | 22 | it "matches valid manifest filepaths" do 23 | expect(described_class.match?("bower.json")).to be_truthy 24 | end 25 | 26 | it "doesn't match invalid manifest filepaths" do 27 | expect(described_class.match?("test/foo/abower.json")).to be_falsey 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/parsers/cpan_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Parsers::CPAN do 6 | it "has a platform name" do 7 | expect(described_class.platform_name).to eq("cpan") 8 | end 9 | 10 | it "parses dependencies from META.yml" do 11 | expect(described_class.analyse_contents("META.yml", load_fixture("META.yml"))).to eq({ 12 | platform: "cpan", 13 | path: "META.yml", 14 | dependencies: [ 15 | Bibliothecary::Dependency.new(name: "Digest::MD5", requirement: 0, type: "runtime", source: "META.yml"), 16 | Bibliothecary::Dependency.new(name: "File::Temp", requirement: 0, type: "runtime", source: "META.yml"), 17 | Bibliothecary::Dependency.new(name: "LWP", requirement: 0, type: "runtime", source: "META.yml"), 18 | Bibliothecary::Dependency.new(name: "XML::Simple", requirement: 0, type: "runtime", source: "META.yml"), 19 | Bibliothecary::Dependency.new(name: "perl", requirement: "5.6.0", type: "runtime", source: "META.yml"), 20 | ], 21 | kind: "manifest", 22 | success: true, 23 | }) 24 | end 25 | 26 | it "parses dependencies from META.json" do 27 | expect(described_class.analyse_contents("META.json", load_fixture("META.json"))).to eq({ 28 | platform: "cpan", 29 | path: "META.json", 30 | dependencies: [ 31 | Bibliothecary::Dependency.new(name: "English", requirement: "1.00", type: "runtime", source: "META.json"), 32 | Bibliothecary::Dependency.new(name: "Test::More", requirement: "0.45", type: "runtime", source: "META.json"), 33 | Bibliothecary::Dependency.new(name: "Module::Build", requirement: "0.28", type: "runtime", source: "META.json"), 34 | Bibliothecary::Dependency.new(name: "Getopt::Long", requirement: "2.32", type: "runtime", source: "META.json"), 35 | Bibliothecary::Dependency.new(name: "List::Util", requirement: "1.07_00", type: "runtime", source: "META.json"), 36 | ], 37 | kind: "manifest", 38 | success: true, 39 | }) 40 | end 41 | 42 | it "matches valid manifest filepaths" do 43 | expect(described_class.match?("META.yml")).to be_truthy 44 | expect(described_class.match?("META.json")).to be_truthy 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/parsers/dub_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Parsers::Dub do 6 | it "has a platform name" do 7 | expect(described_class.platform_name).to eq("dub") 8 | end 9 | 10 | it "parses dependencies from dub.json" do 11 | expect(described_class.analyse_contents("dub.json", load_fixture("dub.json"))).to eq({ 12 | platform: "dub", 13 | path: "dub.json", 14 | dependencies: [ 15 | Bibliothecary::Dependency.new(name: "vibe-d", requirement: "~>0.7.22", type: "runtime", source: "dub.json"), 16 | Bibliothecary::Dependency.new(name: "libdparse", requirement: { "optional" => true, "version" => "~>0.2.0" }, type: "runtime", source: "dub.json"), 17 | ], 18 | kind: "manifest", 19 | success: true, 20 | }) 21 | end 22 | 23 | it "parses dependencies from dub.sdl" do 24 | expect(described_class.analyse_contents("dub.sdl", load_fixture("dub.sdl"))).to eq({ 25 | platform: "dub", 26 | path: "dub.sdl", 27 | dependencies: [ 28 | Bibliothecary::Dependency.new(name: "vibe-d", requirement: "~>0.7.23", type: :runtime, source: "dub.sdl"), 29 | ], 30 | kind: "manifest", 31 | success: true, 32 | }) 33 | end 34 | 35 | it "matches valid manifest filepaths" do 36 | expect(described_class.match?("dub.json")).to be_truthy 37 | expect(described_class.match?("dub.sdl")).to be_truthy 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /spec/parsers/haxelib_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Parsers::Haxelib do 6 | it "has a platform name" do 7 | expect(described_class.platform_name).to eq("haxelib") 8 | end 9 | 10 | it "parses dependencies from haxelib.json" do 11 | expect(described_class.analyse_contents("haxelib.json", load_fixture("haxelib.json"))).to eq({ 12 | platform: "haxelib", 13 | path: "haxelib.json", 14 | dependencies: [ 15 | Bibliothecary::Dependency.new(name: "lime", requirement: "2.9.1", type: "runtime", source: "haxelib.json"), 16 | Bibliothecary::Dependency.new(name: "openfl", requirement: "3.6.1", type: "runtime", source: "haxelib.json"), 17 | ], 18 | kind: "manifest", 19 | success: true, 20 | }) 21 | end 22 | 23 | it "matches valid manifest filepaths" do 24 | expect(described_class.match?("haxelib.json")).to be_truthy 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/parsers/julia_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Parsers::Julia do 6 | it "has a platform name" do 7 | expect(described_class.platform_name).to eq("julia") 8 | end 9 | 10 | it "parses dependencies from REQUIRE" do 11 | expect(described_class.analyse_contents("REQUIRE", load_fixture("REQUIRE"))).to eq({ 12 | platform: "julia", 13 | path: "REQUIRE", 14 | dependencies: [ 15 | Bibliothecary::Dependency.new(name: "julia", requirement: "0.3", type: "runtime", source: "REQUIRE"), 16 | Bibliothecary::Dependency.new(name: "Codecs", requirement: "*", type: "runtime", source: "REQUIRE"), 17 | Bibliothecary::Dependency.new(name: "Colors", requirement: "0.3.4", type: "runtime", source: "REQUIRE"), 18 | Bibliothecary::Dependency.new(name: "Compat", requirement: "*", type: "runtime", source: "REQUIRE"), 19 | Bibliothecary::Dependency.new(name: "Compose", requirement: "0.3.11", type: "runtime", source: "REQUIRE"), 20 | Bibliothecary::Dependency.new(name: "Contour", requirement: "*", type: "runtime", source: "REQUIRE"), 21 | Bibliothecary::Dependency.new(name: "DataFrames", requirement: "0.4.2", type: "runtime", source: "REQUIRE"), 22 | Bibliothecary::Dependency.new(name: "DataStructures", requirement: "*", type: "runtime", source: "REQUIRE"), 23 | Bibliothecary::Dependency.new(name: "Dates", requirement: "*", type: "runtime", source: "REQUIRE"), 24 | Bibliothecary::Dependency.new(name: "Distributions", requirement: "*", type: "runtime", source: "REQUIRE"), 25 | Bibliothecary::Dependency.new(name: "Gadfly", requirement: "0.7-", type: "runtime", source: "REQUIRE"), 26 | Bibliothecary::Dependency.new(name: "Hexagons", requirement: "*", type: "runtime", source: "REQUIRE"), 27 | Bibliothecary::Dependency.new(name: "Homebrew", requirement: "*", type: "runtime", source: "REQUIRE"), 28 | Bibliothecary::Dependency.new(name: "Iterators", requirement: "0.1.5", type: "runtime", source: "REQUIRE"), 29 | Bibliothecary::Dependency.new(name: "JSON", requirement: "*", type: "runtime", source: "REQUIRE"), 30 | Bibliothecary::Dependency.new(name: "KernelDensity", requirement: "*", type: "runtime", source: "REQUIRE"), 31 | Bibliothecary::Dependency.new(name: "Loess", requirement: "*", type: "runtime", source: "REQUIRE"), 32 | Bibliothecary::Dependency.new(name: "Plots", requirement: "0.12 0.15", type: "runtime", source: "REQUIRE"), 33 | Bibliothecary::Dependency.new(name: "Showoff", requirement: "0.0.3", type: "runtime", source: "REQUIRE"), 34 | Bibliothecary::Dependency.new(name: "StatsBase", requirement: "*", type: "runtime", source: "REQUIRE"), 35 | Bibliothecary::Dependency.new(name: "WinReg", requirement: "*", type: "runtime", source: "REQUIRE"), 36 | ], 37 | kind: "manifest", 38 | success: true, 39 | }) 40 | end 41 | 42 | it "matches valid manifest filepaths" do 43 | expect(described_class.match?("REQUIRE")).to be_truthy 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /spec/parsers/meteor_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Parsers::Meteor do 6 | it "has a platform name" do 7 | expect(described_class.platform_name).to eq("meteor") 8 | end 9 | 10 | it "parses dependencies from versions.json" do 11 | expect(described_class.analyse_contents("versions.json", load_fixture("versions.json"))).to eq({ 12 | platform: "meteor", 13 | path: "versions.json", 14 | dependencies: [ 15 | Bibliothecary::Dependency.new(name: "accounts-base", requirement: "1.1.2", type: "runtime", source: "versions.json"), 16 | Bibliothecary::Dependency.new(name: "application-configuration", requirement: "1.0.3", type: "runtime", source: "versions.json"), 17 | Bibliothecary::Dependency.new(name: "base64", requirement: "1.0.1", type: "runtime", source: "versions.json"), 18 | Bibliothecary::Dependency.new(name: "binary-heap", requirement: "1.0.1", type: "runtime", source: "versions.json"), 19 | Bibliothecary::Dependency.new(name: "tracker", requirement: "1.0.3", type: "runtime", source: "versions.json"), 20 | Bibliothecary::Dependency.new(name: "underscore", requirement: "1.0.1", type: "runtime", source: "versions.json"), 21 | ], 22 | kind: "manifest", 23 | success: true, 24 | }) 25 | end 26 | 27 | it "matches valid manifest filepaths" do 28 | expect(described_class.match?("versions.json")).to be_truthy 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/parsers/pub_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Parsers::Pub do 6 | it "has a platform name" do 7 | expect(described_class.platform_name).to eq("pub") 8 | end 9 | 10 | it "parses dependencies from pubspec.yaml" do 11 | expect(described_class.analyse_contents("pubspec.yaml", load_fixture("pubspec.yaml"))).to eq({ 12 | platform: "pub", 13 | path: "pubspec.yaml", 14 | dependencies: [ 15 | Bibliothecary::Dependency.new(name: "analyzer", requirement: ">=0.22.0 <0.25.0", type: "runtime", source: "pubspec.yaml"), 16 | Bibliothecary::Dependency.new(name: "args", requirement: ">=0.12.0 <0.13.0", type: "runtime", source: "pubspec.yaml"), 17 | Bibliothecary::Dependency.new(name: "benchmark_harness", requirement: ">=1.0.0 <2.0.0", type: "development", source: "pubspec.yaml"), 18 | Bibliothecary::Dependency.new(name: "guinness", requirement: ">=0.1.9 <0.2.0", type: "development", source: "pubspec.yaml"), 19 | ], 20 | kind: "manifest", 21 | success: true, 22 | }) 23 | end 24 | 25 | it "parses dependencies from pubspec.lock" do 26 | expect(described_class.analyse_contents("pubspec.lock", load_fixture("pubspec.lock"))).to eq({ 27 | platform: "pub", 28 | path: "pubspec.lock", 29 | dependencies: [ 30 | Bibliothecary::Dependency.new(name: "analyzer", requirement: "0.24.6", type: "runtime", source: "pubspec.lock"), 31 | Bibliothecary::Dependency.new(name: "args", requirement: "0.12.2+6", type: "runtime", source: "pubspec.lock"), 32 | Bibliothecary::Dependency.new(name: "barback", requirement: "0.15.2+7", type: "runtime", source: "pubspec.lock"), 33 | Bibliothecary::Dependency.new(name: "which", requirement: "0.1.3", type: "runtime", source: "pubspec.lock"), 34 | ], 35 | kind: "lockfile", 36 | success: true, 37 | }) 38 | end 39 | 40 | it "matches valid manifest filepaths" do 41 | expect(described_class.match?("pubspec.yaml")).to be_truthy 42 | expect(described_class.match?("pubspec.lock")).to be_truthy 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/parsers/shard_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | describe Bibliothecary::Parsers::Shard do 6 | it "has a platform name" do 7 | expect(described_class.platform_name).to eq("shard") 8 | end 9 | 10 | it "parses dependencies from shard.yml" do 11 | expect(described_class.analyse_contents("shard.yml", load_fixture("shard.yml"))).to eq({ 12 | platform: "shard", 13 | path: "shard.yml", 14 | dependencies: [ 15 | Bibliothecary::Dependency.new(name: "frost", requirement: "*", type: "runtime", source: "shard.yml"), 16 | Bibliothecary::Dependency.new(name: "shards", requirement: "*", type: "runtime", source: "shard.yml"), 17 | Bibliothecary::Dependency.new(name: "common_mark", requirement: "*", type: "runtime", source: "shard.yml"), 18 | Bibliothecary::Dependency.new(name: "minitest", requirement: ">= 0.2.0", type: "runtime", source: "shard.yml"), 19 | Bibliothecary::Dependency.new(name: "selenium-webdriver", requirement: "*", type: "runtime", source: "shard.yml"), 20 | ], 21 | kind: "manifest", 22 | success: true, 23 | }) 24 | end 25 | 26 | it "parses dependencies from shard.lock" do 27 | expect(described_class.analyse_contents("shard.lock", load_fixture("shard.lock"))).to eq({ 28 | platform: "shard", 29 | path: "shard.lock", 30 | dependencies: [ 31 | Bibliothecary::Dependency.new(name: "common_mark", requirement: "0.1.0", type: "runtime", source: "shard.lock"), 32 | Bibliothecary::Dependency.new(name: "frost", requirement: "*", type: "runtime", source: "shard.lock"), 33 | Bibliothecary::Dependency.new(name: "minitest", requirement: "0.3.1", type: "runtime", source: "shard.lock"), 34 | Bibliothecary::Dependency.new(name: "pg", requirement: "0.5.0", type: "runtime", source: "shard.lock"), 35 | Bibliothecary::Dependency.new(name: "pool", requirement: "0.2.1", type: "runtime", source: "shard.lock"), 36 | Bibliothecary::Dependency.new(name: "selenium-webdriver", requirement: "0.1.0", type: "runtime", source: "shard.lock"), 37 | Bibliothecary::Dependency.new(name: "shards", requirement: "0.6.0", type: "runtime", source: "shard.lock"), 38 | ], 39 | kind: "lockfile", 40 | success: true, 41 | }) 42 | end 43 | 44 | it "matches valid manifest filepaths" do 45 | expect(described_class.match?("shard.yml")).to be_truthy 46 | expect(described_class.match?("shard.lock")).to be_truthy 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /spec/shared_examples/dependencies_csv.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.shared_examples "dependencies.csv" do 4 | describe "dependencies.csv" do 5 | let!(:csv_dependencies) do 6 | [ 7 | { 8 | platform: "maven", 9 | name: "com.example:something", 10 | version: "1.0.3", 11 | type: "runtime", 12 | }, 13 | { 14 | platform: "maven", 15 | name: "com.example:something-dev", 16 | version: "1.0.4", 17 | type: "development", 18 | }, 19 | ] 20 | end 21 | 22 | let(:dependencies_for_platform) do 23 | csv_dependencies.find_all { |d| d[:platform] == described_class.platform_name }.tap { |o| raise "This platform is not configured for testing with CycloneDX!" if o.empty? } 24 | end 25 | 26 | it "parses dependencies from cyclonedx.json" do 27 | result = described_class.analyse_contents("dependencies.csv", load_fixture("dependencies.csv")) 28 | 29 | dependencies_for_platform.each do |dependency| 30 | expect(result[:dependencies].find { |d| d.name == dependency[:name] }).to eq(Bibliothecary::Dependency.new( 31 | platform: dependency[:platform], 32 | name: dependency[:name], 33 | requirement: dependency[:version], 34 | type: dependency[:type], 35 | source: "dependencies.csv" 36 | )) 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "simplecov" 4 | SimpleCov.start 5 | 6 | $LOAD_PATH.unshift File.expand_path("../lib", __dir__) 7 | require "bibliothecary" 8 | 9 | require_relative "shared_examples/cyclonedx" 10 | require_relative "shared_examples/dependencies_csv" 11 | 12 | require "super_diff/rspec" 13 | 14 | def fixture_path(name) 15 | "spec/fixtures/#{name}" 16 | end 17 | 18 | def load_fixture(name) 19 | File.read(fixture_path(name)) 20 | end 21 | 22 | RSpec.configure do |config| 23 | config.after(:each) do 24 | Bibliothecary.reset 25 | end 26 | end 27 | 28 | require "webmock/rspec" 29 | WebMock.disable_net_connect!(allow_localhost: true) 30 | 31 | require "pry" 32 | --------------------------------------------------------------------------------