diff --git a/.circleci/config.yml b/.circleci/config.yml index 35464355ae4..a041ff2f46f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: build: docker: - - image: dependabot/dependabot-core:0.1.21 + - image: dependabot/dependabot-core:0.1.22 working_directory: ~/dependabot-core steps: - checkout diff --git a/Dockerfile b/Dockerfile index 90365b84b95..c32590beb08 100644 --- a/Dockerfile +++ b/Dockerfile @@ -79,6 +79,17 @@ RUN echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu bionic main" >> /etc/ap && mv composer.phar /usr/local/bin/composer +### GO + +RUN curl -O https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz \ + && tar xvf go1.10.3.linux-amd64.tar.gz \ + && wget https://github.com/golang/dep/releases/download/v0.4.1/dep-linux-amd64 \ + && mv dep-linux-amd64 go/bin/dep \ + && chmod +x go/bin/dep \ + && mv go /root +ENV PATH=/root/go/bin:$PATH + + ### Elixir # Install Erlang, Elixir and Hex diff --git a/lib/dependabot/file_fetchers.rb b/lib/dependabot/file_fetchers.rb index 652887558f4..26fcc1bc820 100644 --- a/lib/dependabot/file_fetchers.rb +++ b/lib/dependabot/file_fetchers.rb @@ -11,6 +11,7 @@ require "dependabot/file_fetchers/elixir/hex" require "dependabot/file_fetchers/rust/cargo" require "dependabot/file_fetchers/dotnet/nuget" +require "dependabot/file_fetchers/go/dep" module Dependabot module FileFetchers @@ -28,6 +29,7 @@ def self.for_package_manager(package_manager) when "hex" then FileFetchers::Elixir::Hex when "cargo" then FileFetchers::Rust::Cargo when "nuget" then FileFetchers::Dotnet::Nuget + when "dep" then FileFetchers::Go::Dep else raise "Unsupported package_manager #{package_manager}" end end diff --git a/lib/dependabot/file_fetchers/go/dep.rb b/lib/dependabot/file_fetchers/go/dep.rb new file mode 100644 index 00000000000..732efa194bc --- /dev/null +++ b/lib/dependabot/file_fetchers/go/dep.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require "dependabot/file_fetchers/base" + +module Dependabot + module FileFetchers + module Go + class Dep < Dependabot::FileFetchers::Base + def self.required_files_in?(filenames) + (%w(Gopkg.toml Gopkg.lock) - filenames).empty? + end + + def self.required_files_message + "Repo must contain a Gopkg.toml and Gopkg.lock." + end + + private + + def fetch_files + fetched_files = [] + fetched_files << manifest + fetched_files << lockfile + fetched_files + end + + def manifest + @manifest ||= fetch_file_from_host("Gopkg.toml") + end + + def lockfile + @lockfile ||= fetch_file_from_host("Gopkg.lock") + end + end + end + end +end diff --git a/lib/dependabot/file_parsers.rb b/lib/dependabot/file_parsers.rb index 01361295edc..ef74d900f53 100644 --- a/lib/dependabot/file_parsers.rb +++ b/lib/dependabot/file_parsers.rb @@ -11,6 +11,7 @@ require "dependabot/file_parsers/elixir/hex" require "dependabot/file_parsers/rust/cargo" require "dependabot/file_parsers/dotnet/nuget" +require "dependabot/file_parsers/go/dep" module Dependabot module FileParsers @@ -28,6 +29,7 @@ def self.for_package_manager(package_manager) when "hex" then FileParsers::Elixir::Hex when "cargo" then FileParsers::Rust::Cargo when "nuget" then FileParsers::Dotnet::Nuget + when "dep" then FileParsers::Go::Dep else raise "Unsupported package_manager #{package_manager}" end end diff --git a/lib/dependabot/file_parsers/go/dep.rb b/lib/dependabot/file_parsers/go/dep.rb new file mode 100644 index 00000000000..6ca25e7ba32 --- /dev/null +++ b/lib/dependabot/file_parsers/go/dep.rb @@ -0,0 +1,134 @@ +# frozen_string_literal: true + +require "toml-rb" + +require "dependabot/errors" +require "dependabot/dependency" +require "dependabot/file_parsers/base" + +# Relevant dep docs can be found at: +# - https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# - https://github.com/golang/dep/blob/master/docs/Gopkg.lock.md +module Dependabot + module FileParsers + module Go + class Dep < Dependabot::FileParsers::Base + require "dependabot/file_parsers/base/dependency_set" + + REQUIREMENT_TYPES = %w(constraint override).freeze + + def parse + dependency_set = DependencySet.new + dependency_set += manifest_dependencies + dependency_set += lockfile_dependencies + dependency_set.dependencies + end + + private + + def manifest_dependencies + dependency_set = DependencySet.new + + REQUIREMENT_TYPES.each do |type| + parsed_file(manifest).fetch(type, []).each do |details| + dependency_set << Dependency.new( + name: details.fetch("name"), + version: nil, + package_manager: "dep", + requirements: [{ + requirement: requirement_from_declaration(details), + file: manifest.name, + groups: [], + source: source_from_declaration(details) + }] + ) + end + end + + dependency_set + end + + def lockfile_dependencies + dependency_set = DependencySet.new + + parsed_file(lockfile).fetch("projects", []).each do |details| + dependency_set << Dependency.new( + name: details.fetch("name"), + version: version_from_lockfile(details), + package_manager: "dep", + requirements: [] + ) + end + + dependency_set + end + + def version_from_lockfile(details) + details["version"]&.sub(/^v?/, "") || details.fetch("revision") + end + + def requirement_from_declaration(declaration) + unless declaration.is_a?(Hash) + raise "Unexpected dependency declaration: #{declaration}" + end + + declaration["version"] + end + + def source_from_declaration(declaration) + unless declaration.is_a?(Hash) + raise "Unexpected dependency declaration: #{declaration}" + end + + source = declaration["source"] || declaration["name"] + + git_source = git_source(source) + + if git_source && (declaration["branch"] || declaration["revision"]) + { + type: "git", + url: git_source.url, + branch: declaration["branch"], + ref: declaration["revision"] + } + else + { + type: "default", + source: source + } + end + end + + def git_source(path) + updated_path = path.gsub(%r{^golang\.org/x}, "github.com/golang") + + # Currently, Dependabot::Source.new will return `nil` if it can't find + # a git SCH associated with a path. If it is ever extended to handle + # non-git sources we'll need to add an additional check here. + Source.from_url(updated_path) + end + + def parsed_file(file) + @parsed_file ||= {} + @parsed_file[file.name] ||= TomlRB.parse(file.content) + rescue TomlRB::ParseError + raise Dependabot::DependencyFileNotParseable, file.path + end + + def manifest + @manifest ||= get_original_file("Gopkg.toml") + end + + def lockfile + @lockfile ||= get_original_file("Gopkg.lock") + end + + def check_required_files + %w(Gopkg.toml Gopkg.lock).each do |filename| + raise "No #{filename}!" unless get_original_file(filename) + end + end + end + end + end +end diff --git a/lib/dependabot/file_updaters.rb b/lib/dependabot/file_updaters.rb index f4376b4dfd1..57a78780981 100644 --- a/lib/dependabot/file_updaters.rb +++ b/lib/dependabot/file_updaters.rb @@ -11,6 +11,7 @@ require "dependabot/file_updaters/elixir/hex" require "dependabot/file_updaters/rust/cargo" require "dependabot/file_updaters/dotnet/nuget" +require "dependabot/file_updaters/go/dep" module Dependabot module FileUpdaters @@ -28,6 +29,7 @@ def self.for_package_manager(package_manager) when "hex" then FileUpdaters::Elixir::Hex when "cargo" then FileUpdaters::Rust::Cargo when "nuget" then FileUpdaters::Dotnet::Nuget + when "dep" then FileUpdaters::Go::Dep else raise "Unsupported package_manager #{package_manager}" end end diff --git a/lib/dependabot/file_updaters/go/dep.rb b/lib/dependabot/file_updaters/go/dep.rb new file mode 100644 index 00000000000..6c1f9ffd17a --- /dev/null +++ b/lib/dependabot/file_updaters/go/dep.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require "dependabot/shared_helpers" +require "dependabot/file_updaters/base" + +module Dependabot + module FileUpdaters + module Go + class Dep < Dependabot::FileUpdaters::Base + require_relative "dep/manifest_updater" + require_relative "dep/lockfile_updater" + + def self.updated_files_regex + [ + /^Gopkg\.toml$/, + /^Gopkg\.lock$/ + ] + end + + def updated_dependency_files + updated_files = [] + + if file_changed?(manifest) + updated_files << + updated_file( + file: manifest, + content: updated_manifest_content + ) + end + + if lockfile + updated_files << + updated_file(file: lockfile, content: updated_lockfile_content) + end + + raise "No files changed!" if updated_files.none? + + updated_files + end + + private + + def check_required_files + raise "No Gopkg.toml!" unless get_original_file("Gopkg.toml") + end + + def manifest + @manifest ||= get_original_file("Gopkg.toml") + end + + def lockfile + @lockfile ||= get_original_file("Gopkg.lock") + end + + def updated_manifest_content + ManifestUpdater.new( + dependencies: dependencies, + manifest: manifest + ).updated_manifest_content + end + + def updated_lockfile_content + LockfileUpdater.new( + dependencies: dependencies, + dependency_files: dependency_files, + credentials: credentials + ).updated_lockfile_content + end + end + end + end +end diff --git a/lib/dependabot/file_updaters/go/dep/lockfile_updater.rb b/lib/dependabot/file_updaters/go/dep/lockfile_updater.rb new file mode 100644 index 00000000000..3ebe66c7ff0 --- /dev/null +++ b/lib/dependabot/file_updaters/go/dep/lockfile_updater.rb @@ -0,0 +1,187 @@ +# frozen_string_literal: true + +require "toml-rb" + +require "dependabot/shared_helpers" +require "dependabot/dependency_file" +require "dependabot/file_updaters/go/dep" +require "dependabot/file_parsers/go/dep" + +module Dependabot + module FileUpdaters + module Go + class Dep + class LockfileUpdater + def initialize(dependencies:, dependency_files:, credentials:) + @dependencies = dependencies + @dependency_files = dependency_files + @credentials = credentials + end + + def updated_lockfile_content + updated_content = + Dir.chdir(go_dir) do + write_temporary_dependency_files + + SharedHelpers.with_git_configured(credentials: credentials) do + # Shell out to dep, which handles everything for us, and does + # so without doing an install (so it's fast). + command = "dep ensure -update --no-vendor "\ + "#{dependencies.map(&:name).join(' ')}" + run_shell_command(command) + end + + File.read("Gopkg.lock") + end + + FileUtils.rm_rf(go_dir) + updated_content + end + + private + + attr_reader :dependencies, :dependency_files, :credentials + + def run_shell_command(command) + raw_response = nil + IO.popen(command, err: %i(child out)) do |process| + raw_response = process.read + end + + # Raise an error with the output from the shell session if dep + # returns a non-zero status + return if $CHILD_STATUS.success? + raise SharedHelpers::HelperSubprocessFailed.new( + raw_response, + command + ) + end + + def write_temporary_dependency_files + dependency_files.each do |file| + path = file.name + FileUtils.mkdir_p(Pathname.new(path).dirname) + File.write(file.name, file.content) + end + + # Overwrite the manifest with our custom prepared one + File.write(prepared_manifest.name, prepared_manifest.content) + + File.write("hello.go", dummy_app_content) + end + + def prepared_manifest + DependencyFile.new( + name: manifest.name, + content: prepared_manifest_content + ) + end + + def prepared_manifest_content + parsed_manifest = TomlRB.parse(manifest.content) + + dependencies.each do |dep| + req = dep.requirements.find { |r| r[:file] == manifest.name } + + if req + update_constraint!(parsed_manifest, dep) + else + create_constraint!(parsed_manifest, dep) + end + end + + TomlRB.dump(parsed_manifest) + end + + # Used to lock the version when updating a top-level dependency + def update_constraint!(parsed_manifest, dep) + details = + parsed_manifest. + values_at(*FileParsers::Go::Dep::REQUIREMENT_TYPES). + flatten.compact.find { |d| d["name"] == dep.name } + + req = dep.requirements.find { |r| r[:file] == manifest.name } + + details.delete("branch") + + if req.fetch(:source).fetch(:type) == "git" + details.delete("version") + details["revision"] = dep.version + else + details.delete("revision") + details["version"] = dep.version + end + end + + # Used to lock the version when updating a subdependency + def create_constraint!(parsed_manifest, dep) + details = { "name" => dep.name } + + # Fetch the details from the lockfile to check whether this + # sub-dependency needs a git revision or a version. + original_details = + parsed_file(lockfile).fetch("projects"). + find { |p| p["name"] == dep.name } + + if original_details["source"] + details["source"] = original_details["source"] + end + + if original_details["version"] + details["version"] = dep.version + else + details["revision"] = dep.version + end + + parsed_manifest["constraint"] << details + end + + def go_dir + # Work in a directory called "$HOME/go/src/dependabot-tmp". + # TODO: This should pick up what the user's actual GOPATH is. + go_dir = File.join(Dir.home, "go", "src", "dependabot-tmp") + FileUtils.mkdir_p(go_dir) + go_dir + end + + def dummy_app_content + base = "package main\n\n"\ + "import \"fmt\"\n\n" + + dependencies_to_import.each { |nm| base += "import \"#{nm}\"\n\n" } + + base + "func main() {\n fmt.Printf(\"hello, world\\n\")\n}" + end + + def dependencies_to_import + # There's no way to tell whether dependencies that appear in the + # lockfile are there because they're imported themselves or because + # they're sub-dependencies of something else. v0.5.0 will fix that + # problem, but for now we just have to import everything. + # + # NOTE: This means the `inputs-digest` we generate will be wrong. + # That's a pity, but we'd have to iterate through too many + # possibilities to get it right. Again, this is fixed in v0.5.0. + return [] unless lockfile + TomlRB.parse(lockfile.content).fetch("projects").map do |detail| + detail["name"] + end + end + + def parsed_file(file) + @parsed_file ||= {} + @parsed_file[file.name] ||= TomlRB.parse(file.content) + end + + def manifest + @manifest ||= dependency_files.find { |f| f.name == "Gopkg.toml" } + end + + def lockfile + @lockfile ||= dependency_files.find { |f| f.name == "Gopkg.lock" } + end + end + end + end + end +end diff --git a/lib/dependabot/file_updaters/go/dep/manifest_updater.rb b/lib/dependabot/file_updaters/go/dep/manifest_updater.rb new file mode 100644 index 00000000000..824d6e07678 --- /dev/null +++ b/lib/dependabot/file_updaters/go/dep/manifest_updater.rb @@ -0,0 +1,155 @@ +# frozen_string_literal: true + +require "dependabot/file_updaters/go/dep" + +module Dependabot + module FileUpdaters + module Go + class Dep + class ManifestUpdater + def initialize(dependencies:, manifest:) + @dependencies = dependencies + @manifest = manifest + end + + def updated_manifest_content + dependencies. + select { |dep| requirement_changed?(manifest, dep) }. + reduce(manifest.content.dup) do |content, dep| + updated_content = content + + updated_content = update_requirements( + content: updated_content, + filename: manifest.name, + dependency: dep + ) + updated_content = update_git_pin( + content: updated_content, + filename: manifest.name, + dependency: dep + ) + + if content == updated_content + raise "Expected content to change!" + end + + updated_content + end + end + + private + + attr_reader :dependencies, :manifest + + def requirement_changed?(file, dependency) + changed_requirements = + dependency.requirements - dependency.previous_requirements + + changed_requirements.any? { |f| f[:file] == file.name } + end + + def update_requirements(content:, filename:, dependency:) + updated_content = content.dup + + # The UpdateChecker ensures the order of requirements is preserved + # when updating, so we can zip them together in new/old pairs. + reqs = dependency.requirements. + zip(dependency.previous_requirements). + reject { |new_req, old_req| new_req == old_req } + + # Loop through each changed requirement + reqs.each do |new_req, old_req| + raise "Bad req match" unless new_req[:file] == old_req[:file] + next if new_req[:requirement] == old_req[:requirement] + next unless new_req[:file] == filename + + updated_content = update_manifest_req( + content: updated_content, + dep: dependency, + old_req: old_req.fetch(:requirement), + new_req: new_req.fetch(:requirement) + ) + end + + updated_content + end + + def update_git_pin(content:, filename:, dependency:) + updated_pin = + dependency.requirements. + find { |r| r[:file] == filename }&. + dig(:source, :ref) + + old_pin = + dependency.previous_requirements. + find { |r| r[:file] == filename }&. + dig(:source, :ref) + + return content unless old_pin + + update_manifest_pin( + content: content, + dep: dependency, + old_pin: old_pin, + new_pin: updated_pin + ) + end + + # rubocop:disable Metrics/CyclomaticComplexity + # rubocop:disable Metrics/PerceivedComplexity + def update_manifest_req(content:, dep:, old_req:, new_req:) + declaration = content.scan(declaration_regex(dep)). + find { |m| old_req.nil? || m.include?(old_req) } + + return content unless declaration + + if old_req && new_req + content.gsub(declaration) do |line| + line.gsub(old_req, new_req) + end + elsif old_req && new_req.nil? + content.gsub(declaration) do |line| + line.gsub(/\R+.*version\s*=.*/, "") + end + elsif old_req.nil? && new_req + content.gsub(declaration) do |line| + indent = line.match(/(?\s*)name/). + named_captures.fetch("indent") + version_declaration = indent + "version = \"#{new_req}\"" + line.gsub(/name\s*=.*/) { |nm_ln| nm_ln + version_declaration } + end + end + end + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/PerceivedComplexity + + def update_manifest_pin(content:, dep:, old_pin:, new_pin:) + declaration = content.scan(declaration_regex(dep)). + find { |m| m.include?(old_pin) } + + return content unless declaration + + if old_pin && new_pin + content.gsub(declaration) do |line| + line.gsub(old_pin, new_pin) + end + elsif old_pin && new_pin.nil? + content.gsub(declaration) do |line| + line.gsub(/\R+.*(revision|branch)\s*=.*/, "") + end + end + end + + def declaration_regex(dep) + / + (?<=\]\]) + (?:(?!^\[).)* + name\s*=\s*["']#{Regexp.escape(dep.name)}["'] + (?:(?!^\[).)* + /mx + end + end + end + end + end +end diff --git a/lib/dependabot/git_commit_checker.rb b/lib/dependabot/git_commit_checker.rb index 70430312423..9f8341e5b02 100644 --- a/lib/dependabot/git_commit_checker.rb +++ b/lib/dependabot/git_commit_checker.rb @@ -8,14 +8,16 @@ require "dependabot/utils" require "dependabot/source" +# rubocop:disable Metrics/ClassLength module Dependabot class GitCommitChecker VERSION_REGEX = /(?[0-9]+\.[0-9]+(?:\.[a-zA-Z0-9\-]+)*)$/ KNOWN_HOSTS = /github\.com|bitbucket\.org|gitlab.com/ - def initialize(dependency:, credentials:) + def initialize(dependency:, credentials:, ignored_versions: []) @dependency = dependency @credentials = credentials + @ignored_versions = ignored_versions end def git_dependency? @@ -58,14 +60,19 @@ def head_commit_for_current_branch end def local_tag_for_latest_version - tag = + tags = local_tags. select { |t| t.name.match?(VERSION_REGEX) }. - max_by do |t| + reject do |t| version = t.name.match(VERSION_REGEX).named_captures.fetch("version") - version_class.new(version) + ignore_reqs.any? { |r| r.satisfied_by?(version_class.new(version)) } end + tag = tags.max_by do |t| + version = t.name.match(VERSION_REGEX).named_captures.fetch("version") + version_class.new(version) + end + return unless tag { tag: tag.name, @@ -76,7 +83,7 @@ def local_tag_for_latest_version private - attr_reader :dependency, :credentials + attr_reader :dependency, :credentials, :ignored_versions def pinned_ref_in_release?(version) raise "Not a git dependency!" unless git_dependency? @@ -322,12 +329,21 @@ def listing_upload_pack @listing_upload_pack ||= fetch_upload_pack_for(listing_source_url) end + def ignore_reqs + ignored_versions.map { |req| requirement_class.new(req.split(",")) } + end + def version_class Utils.version_class_for_package_manager(dependency.package_manager) end + def requirement_class + Utils.requirement_class_for_package_manager(dependency.package_manager) + end + def sha_for_update_pack_line(line) line.split(" ").first.chars.last(40).join end end end +# rubocop:enable Metrics/ClassLength diff --git a/lib/dependabot/metadata_finders.rb b/lib/dependabot/metadata_finders.rb index c55e9775deb..3fa4eebc6f8 100644 --- a/lib/dependabot/metadata_finders.rb +++ b/lib/dependabot/metadata_finders.rb @@ -10,6 +10,7 @@ require "dependabot/metadata_finders/elixir/hex" require "dependabot/metadata_finders/rust/cargo" require "dependabot/metadata_finders/dotnet/nuget" +require "dependabot/metadata_finders/go/dep" module Dependabot module MetadataFinders @@ -26,6 +27,7 @@ def self.for_package_manager(package_manager) when "hex" then MetadataFinders::Elixir::Hex when "cargo" then MetadataFinders::Rust::Cargo when "nuget" then MetadataFinders::Dotnet::Nuget + when "dep" then MetadataFinders::Go::Dep else raise "Unsupported package_manager #{package_manager}" end end diff --git a/lib/dependabot/metadata_finders/go/dep.rb b/lib/dependabot/metadata_finders/go/dep.rb new file mode 100644 index 00000000000..5fd114d6e2a --- /dev/null +++ b/lib/dependabot/metadata_finders/go/dep.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require "dependabot/metadata_finders/base" + +module Dependabot + module MetadataFinders + module Go + class Dep < Dependabot::MetadataFinders::Base + private + + def look_up_source + # TODO: A more general way to do this? + source_string = specified_source_string. + gsub(%r{^golang\.org/x}, "github.com/golang") + + Source.from_url(source_string) + end + + def specified_source_string + sources = dependency.requirements. + map { |r| r.fetch(:source) }.uniq.compact + + raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1 + + sources.first&.fetch(:source, nil) || + sources.first&.fetch("source") || + dependency.name + end + end + end + end +end diff --git a/lib/dependabot/update_checkers.rb b/lib/dependabot/update_checkers.rb index d02adb264ce..903501cdc23 100644 --- a/lib/dependabot/update_checkers.rb +++ b/lib/dependabot/update_checkers.rb @@ -11,6 +11,7 @@ require "dependabot/update_checkers/elixir/hex" require "dependabot/update_checkers/rust/cargo" require "dependabot/update_checkers/dotnet/nuget" +require "dependabot/update_checkers/go/dep" module Dependabot module UpdateCheckers @@ -28,6 +29,7 @@ def self.for_package_manager(package_manager) when "hex" then UpdateCheckers::Elixir::Hex when "cargo" then UpdateCheckers::Rust::Cargo when "nuget" then UpdateCheckers::Dotnet::Nuget + when "dep" then UpdateCheckers::Go::Dep else raise "Unsupported package_manager #{package_manager}" end end diff --git a/lib/dependabot/update_checkers/go/dep.rb b/lib/dependabot/update_checkers/go/dep.rb new file mode 100644 index 00000000000..ad69850d397 --- /dev/null +++ b/lib/dependabot/update_checkers/go/dep.rb @@ -0,0 +1,232 @@ +# frozen_string_literal: true + +require "toml-rb" +require "dependabot/update_checkers/base" + +module Dependabot + module UpdateCheckers + module Go + class Dep < Dependabot::UpdateCheckers::Base + require_relative "dep/file_preparer" + require_relative "dep/latest_version_finder" + require_relative "dep/requirements_updater" + require_relative "dep/version_resolver" + + def latest_version + @latest_version ||= + LatestVersionFinder.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials, + ignored_versions: ignored_versions + ).latest_version + end + + def latest_resolvable_version + @latest_resolvable_version ||= + if git_dependency? + latest_resolvable_version_for_git_dependency + else + latest_resolvable_released_version(unlock_requirement: true) + end + end + + def latest_resolvable_version_with_no_unlock + @latest_resolvable_version_with_no_unlock ||= + if git_dependency? + latest_resolvable_commit_with_unchanged_git_source + else + latest_resolvable_released_version(unlock_requirement: false) + end + end + + def updated_requirements + @updated_requirements ||= + RequirementsUpdater.new( + requirements: dependency.requirements, + updated_source: updated_source, + latest_version: latest_version&.to_s, + latest_resolvable_version: latest_resolvable_version&.to_s + ).updated_requirements + end + + private + + def latest_version_resolvable_with_full_unlock? + # Full unlock checks aren't implemented for Go (yet) + false + end + + def updated_dependencies_after_full_unlock + raise NotImplementedError + end + + def latest_resolvable_version_for_git_dependency + latest_release = + latest_resolvable_released_version(unlock_requirement: true) + + # If there's a resolvable release that includes the current pinned + # ref or that the current branch is behind, we switch to that release. + return latest_release if git_branch_or_ref_in_release?(latest_release) + + # Otherwise, if the gem isn't pinned, the latest version is just the + # latest commit for the specified branch. + unless git_commit_checker.pinned? + return latest_resolvable_commit_with_unchanged_git_source + end + + # If the dependency is pinned to a tag that looks like a version then + # we want to update that tag. The latest version will be the + # tag name (NOT the tag SHA, unlike in other package managers). + if git_commit_checker.pinned_ref_looks_like_version? && + latest_git_tag_is_resolvable? + new_tag = git_commit_checker.local_tag_for_latest_version + return new_tag.fetch(:tag) + end + + # If the dependency is pinned to a tag that doesn't look like a + # version then there's nothing we can do. + nil + end + + def latest_resolvable_commit_with_unchanged_git_source + @latest_resolvable_commit_with_unchanged_git_source ||= + begin + prepared_files = FilePreparer.new( + dependency_files: dependency_files, + dependency: dependency, + unlock_requirement: false, + remove_git_source: false, + latest_allowable_version: latest_version + ).prepared_dependency_files + + VersionResolver.new( + dependency: dependency, + dependency_files: prepared_files, + credentials: credentials + ).latest_resolvable_version + end + end + + def latest_resolvable_released_version(unlock_requirement:) + @latest_resolvable_released_version ||= {} + @latest_resolvable_released_version[unlock_requirement] ||= + begin + prepared_files = FilePreparer.new( + dependency_files: dependency_files, + dependency: dependency, + unlock_requirement: unlock_requirement, + remove_git_source: git_dependency?, + latest_allowable_version: latest_version + ).prepared_dependency_files + + VersionResolver.new( + dependency: dependency, + dependency_files: prepared_files, + credentials: credentials + ).latest_resolvable_version + end + end + + def latest_git_tag_is_resolvable? + return @git_tag_resolvable if @latest_git_tag_is_resolvable_checked + @latest_git_tag_is_resolvable_checked = true + + return false if git_commit_checker.local_tag_for_latest_version.nil? + replacement_tag = git_commit_checker.local_tag_for_latest_version + + prepared_files = FilePreparer.new( + dependency: dependency, + dependency_files: dependency_files, + unlock_requirement: false, + remove_git_source: false, + replacement_git_pin: replacement_tag.fetch(:tag) + ).prepared_dependency_files + + VersionResolver.new( + dependency: dependency, + dependency_files: prepared_files, + credentials: credentials + ).latest_resolvable_version + + @git_tag_resolvable = true + rescue Dependabot::DependencyFileNotResolvable + @git_tag_resolvable = false + end + + def updated_source + # Never need to update source, unless a git_dependency + return dependency_source_details unless git_dependency? + + # Source becomes `nil` if switching to default rubygems + return default_source if should_switch_source_from_ref_to_release? + + # Update the git tag if updating a pinned version + if git_commit_checker.pinned_ref_looks_like_version? && + latest_git_tag_is_resolvable? + new_tag = git_commit_checker.local_tag_for_latest_version + return dependency_source_details.merge(ref: new_tag.fetch(:tag)) + end + + # Otherwise return the original source + dependency_source_details + end + + def dependency_source_details + sources = + dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact + + raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1 + + sources.first + end + + def should_switch_source_from_ref_to_release? + return false unless git_dependency? + return false if latest_resolvable_version_for_git_dependency.nil? + Gem::Version.correct?(latest_resolvable_version_for_git_dependency) + end + + def git_dependency? + git_commit_checker.git_dependency? + end + + def default_source + original_declaration = + parsed_file(manifest). + values_at(*FileParsers::Go::Dep::REQUIREMENT_TYPES). + flatten.compact. + find { |d| d["name"] == dependency.name } + + { + type: "default", + source: original_declaration["source"] || dependency.name + } + end + + def git_branch_or_ref_in_release?(release) + return false unless release + git_commit_checker.branch_or_ref_in_release?(release) + end + + def parsed_file(file) + @parsed_file ||= {} + @parsed_file[file.name] ||= TomlRB.parse(file.content) + end + + def manifest + @manifest ||= dependency_files.find { |f| f.name == "Gopkg.toml" } + end + + def git_commit_checker + @git_commit_checker ||= + GitCommitChecker.new( + dependency: dependency, + credentials: credentials, + ignored_versions: ignored_versions + ) + end + end + end + end +end diff --git a/lib/dependabot/update_checkers/go/dep/file_preparer.rb b/lib/dependabot/update_checkers/go/dep/file_preparer.rb new file mode 100644 index 00000000000..f73a63ab560 --- /dev/null +++ b/lib/dependabot/update_checkers/go/dep/file_preparer.rb @@ -0,0 +1,195 @@ +# frozen_string_literal: true + +require "toml-rb" +require "dependabot/dependency_file" +require "dependabot/file_parsers/go/dep" +require "dependabot/update_checkers/go/dep" + +module Dependabot + module UpdateCheckers + module Go + class Dep + # This class takes a set of dependency files and prepares them for use + # in UpdateCheckers::Go::Dep. + class FilePreparer + def initialize(dependency_files:, dependency:, + remove_git_source: false, + unlock_requirement: true, + replacement_git_pin: nil, + latest_allowable_version: nil) + @dependency_files = dependency_files + @dependency = dependency + @unlock_requirement = unlock_requirement + @remove_git_source = remove_git_source + @replacement_git_pin = replacement_git_pin + @latest_allowable_version = latest_allowable_version + end + + def prepared_dependency_files + files = [] + + files << manifest_for_update_check + files << lockfile if lockfile + + files + end + + private + + attr_reader :dependency_files, :dependency, :replacement_git_pin, + :latest_allowable_version + + def unlock_requirement? + @unlock_requirement + end + + def remove_git_source? + @remove_git_source + end + + def replace_git_pin? + !replacement_git_pin.nil? + end + + def manifest_for_update_check + DependencyFile.new( + name: manifest.name, + content: manifest_content_for_update_check(manifest), + directory: manifest.directory + ) + end + + def manifest_content_for_update_check(file) + content = file.content + + content = remove_git_source(content) if remove_git_source? + content = replace_git_pin(content) if replace_git_pin? + content = replace_version_constraint(content, file.name) + + content + end + + def remove_git_source(content) + parsed_manifest = TomlRB.parse(content) + + FileParsers::Go::Dep::REQUIREMENT_TYPES.each do |type| + (parsed_manifest[type] || []).each do |details| + next unless details["name"] == dependency.name + + unless details["branch"] || details["revision"] + raise "No git source to remove! #{details}" + end + details.delete("revision") + details.delete("branch") + end + end + + TomlRB.dump(parsed_manifest) + end + + # Note: We don't need to care about formatting in this method, since + # we're only using the manifest to find the latest resolvable version + def replace_version_constraint(content, filename) + parsed_manifest = TomlRB.parse(content) + + FileParsers::Go::Dep::REQUIREMENT_TYPES.each do |type| + (parsed_manifest[type] || []).each do |details| + next unless details["name"] == dependency.name + next if details["revision"] || details["branch"] + updated_req = temporary_requirement_for_resolution(filename) + + details["version"] = updated_req + end + end + + TomlRB.dump(parsed_manifest) + end + + def replace_git_pin(content) + parsed_manifest = TomlRB.parse(content) + + FileParsers::Go::Dep::REQUIREMENT_TYPES.each do |type| + (parsed_manifest[type] || []).each do |details| + next unless details["name"] == dependency.name + + if details["branch"] || details["version"] + raise "Invalid details! #{details}" + end + details["revision"] = replacement_git_pin + end + end + + TomlRB.dump(parsed_manifest) + end + + def temporary_requirement_for_resolution(filename) + original_req = dependency.requirements. + find { |r| r.fetch(:file) == filename }&. + fetch(:requirement) + + lower_bound_req = + if original_req && !unlock_requirement? + original_req + else + ">= #{lower_bound_version}" + end + + unless version_class.correct?(latest_allowable_version) && + version_class.new(latest_allowable_version) >= + version_class.new(lower_bound_version) + return lower_bound_req + end + + lower_bound_req + ", <= #{latest_allowable_version}" + end + + def lower_bound_version + @lower_bound_version ||= + if version_from_lockfile + version_from_lockfile + else + version_from_requirement = + dependency.requirements.map { |r| r.fetch(:requirement) }. + compact. + flat_map { |req_str| requirement_class.new(req_str) }. + flat_map(&:requirements). + reject { |req_array| req_array.first.start_with?("<") }. + map(&:last). + max&.to_s + + version_from_requirement || 0 + end + end + + def version_from_lockfile + return unless lockfile + + TomlRB.parse(lockfile.content). + fetch("projects", []). + find { |p| p["name"] == dependency.name }&. + fetch("version", nil)&. + sub(/^v?/, "") + end + + def version_class + Utils.version_class_for_package_manager(dependency.package_manager) + end + + def requirement_class + Utils.requirement_class_for_package_manager( + dependency.package_manager + ) + end + + def manifest + @manifest ||= dependency_files.find { |f| f.name == "Gopkg.toml" } + end + + def lockfile + @lockfile ||= dependency_files.find { |f| f.name == "Gopkg.lock" } + end + end + end + end + end +end diff --git a/lib/dependabot/update_checkers/go/dep/latest_version_finder.rb b/lib/dependabot/update_checkers/go/dep/latest_version_finder.rb new file mode 100644 index 00000000000..a3c899bb3c6 --- /dev/null +++ b/lib/dependabot/update_checkers/go/dep/latest_version_finder.rb @@ -0,0 +1,155 @@ +# frozen_string_literal: true + +require "toml-rb" + +require "dependabot/source" +require "dependabot/update_checkers/go/dep" +require "dependabot/git_commit_checker" + +module Dependabot + module UpdateCheckers + module Go + class Dep + class LatestVersionFinder + def initialize(dependency:, dependency_files:, credentials:, + ignored_versions:) + @dependency = dependency + @dependency_files = dependency_files + @credentials = credentials + @ignored_versions = ignored_versions + end + + def latest_version + @latest_version ||= + if git_dependency? then latest_version_for_git_dependency + else latest_release_tag_version + end + end + + private + + attr_reader :dependency, :dependency_files, :credentials, + :ignored_versions + + def latest_release_tag_version + if @latest_release_tag_lookup_attempted + return @latest_release_tag_version + end + + @latest_release_tag_lookup_attempted = true + + latest_release_str = fetch_latest_release_tag&.sub(/^v?/, "") + return unless latest_release_str + return unless version_class.correct?(latest_release_str) + + @latest_release_tag_version = + version_class.new(latest_release_str) + end + + def fetch_latest_release_tag + # If this is a git dependency then getting the latest tag is trivial + if git_dependency? + return git_commit_checker. + local_tag_for_latest_version&.fetch(:tag) + end + + # If not, we need to find the URL for the source code. + path = dependency.requirements. + map { |r| r.dig(:source, :source) }.compact.first + path ||= dependency.name + + updated_path = path.gsub(%r{^golang\.org/x}, "github.com/golang") + # Currently, Dependabot::Source.new will return `nil` if it can't + # find a git SCH associated with a path. If it is ever extended to + # handle non-git sources we'll need to add an additional check here. + source = Source.from_url(updated_path) + return unless source + + # Given a source, we want to find the latest tag. Piggy-back off the + # logic in GitCommitChecker to do so. + git_dep = Dependency.new( + name: dependency.name, + version: dependency.version, + requirements: [{ + file: "Gopkg.toml", + groups: [], + requirement: nil, + source: { type: "git", url: source.url } + }], + package_manager: dependency.package_manager + ) + + GitCommitChecker. + new(dependency: git_dep, credentials: credentials). + local_tag_for_latest_version&.fetch(:tag) + end + + def latest_version_for_git_dependency + latest_release = latest_release_tag_version + + # If there's been a release that includes the current pinned ref or + # that the current branch is behind, we switch to that release. + return latest_release if branch_or_ref_in_release?(latest_release) + + # Otherwise, if the gem isn't pinned, the latest version is just the + # latest commit for the specified branch. + unless git_commit_checker.pinned? + return git_commit_checker.head_commit_for_current_branch + end + + # If the dependency is pinned to a tag that looks like a version + # then we want to update that tag. The latest version will be the + # tag name (NOT the tag SHA, unlike in other package managers). + if git_commit_checker.pinned_ref_looks_like_version? + latest_tag = git_commit_checker.local_tag_for_latest_version + return latest_tag&.fetch(:tag) + end + + # If the dependency is pinned to a tag that doesn't look like a + # version then there's nothing we can do. + nil + end + + def branch_or_ref_in_release?(release) + return false unless release + git_commit_checker.branch_or_ref_in_release?(release) + end + + def git_dependency? + git_commit_checker.git_dependency? + end + + def git_commit_checker + @git_commit_checker ||= + GitCommitChecker.new( + dependency: dependency, + credentials: credentials, + ignored_versions: ignored_versions + ) + end + + def parsed_file(file) + @parsed_file ||= {} + @parsed_file[file.name] ||= TomlRB.parse(file.content) + end + + def version_class + Utils.version_class_for_package_manager(dependency.package_manager) + end + + def manifest + @manifest ||= dependency_files.find { |f| f.name == "Gopkg.toml" } + raise "No Gopkg.lock!" unless @manifest + @manifest + end + + def lockfile + @lockfile = dependency_files.find { |f| f.name == "Gopkg.lock" } + raise "No Gopkg.lock!" unless @lockfile + @lockfile + end + end + end + end + end +end diff --git a/lib/dependabot/update_checkers/go/dep/requirements_updater.rb b/lib/dependabot/update_checkers/go/dep/requirements_updater.rb new file mode 100644 index 00000000000..c2af5241126 --- /dev/null +++ b/lib/dependabot/update_checkers/go/dep/requirements_updater.rb @@ -0,0 +1,169 @@ +# frozen_string_literal: true + +require "dependabot/update_checkers/go/dep" +require "dependabot/utils/go/requirement" +require "dependabot/utils/go/version" + +module Dependabot + module UpdateCheckers + module Go + class Dep + class RequirementsUpdater + class UnfixableRequirement < StandardError; end + + VERSION_REGEX = /[0-9]+(?:\.[A-Za-z0-9\-*]+)*/ + + def initialize(requirements:, updated_source:, + latest_version:, latest_resolvable_version:) + @requirements = requirements + @updated_source = updated_source + + if latest_version && version_class.correct?(latest_version) + @latest_version = version_class.new(latest_version) + end + + return unless latest_resolvable_version + return unless version_class.correct?(latest_resolvable_version) + @latest_resolvable_version = + version_class.new(latest_resolvable_version) + end + + def updated_requirements + requirements.map do |req| + req = req.merge(source: updated_source) + next req unless latest_resolvable_version + next initial_req_after_source_change(req) unless req[:requirement] + + # In future we'll write logic to update apps differently, but + # for now we can't tell them apart + updated_library_requirement(req) + end + end + + private + + attr_reader :requirements, :updated_source, + :latest_version, :latest_resolvable_version + + def updating_from_git_to_version? + return false unless updated_source&.fetch(:type) == "default" + original_source = requirements.map { |r| r[:source] }.compact.first + original_source&.fetch(:type) == "git" + end + + def initial_req_after_source_change(req) + return req unless updating_from_git_to_version? + return req unless req[:requirement].nil? + req.merge(requirement: "^#{latest_resolvable_version}") + end + + def updated_library_requirement(req) + current_requirement = req[:requirement] + version = latest_resolvable_version + + ruby_reqs = ruby_requirements(current_requirement) + return req if ruby_reqs.any? { |r| r.satisfied_by?(version) } + + reqs = current_requirement.strip.split(",").map(&:strip) + + updated_requirement = + if current_requirement.include?("||") + # Further widen the range by adding another OR condition + current_requirement + " || ^#{version}" + elsif reqs.any? { |r| r.match?(/(<|-\s)/) } + # Further widen the range by updating the upper bound + update_range_requirement(current_requirement) + else + # Convert existing requirement to a range + create_new_range_requirement(reqs) + end + + req.merge(requirement: updated_requirement) + end + + def ruby_requirements(requirement_string) + requirement_class.requirements_array(requirement_string) + end + + def update_range_requirement(req_string) + range_requirement = req_string.split(","). + find { |r| r.match?(/<|(\s+-\s+)/) } + + versions = range_requirement.scan(VERSION_REGEX) + upper_bound = versions.map { |v| version_class.new(v) }.max + new_upper_bound = update_greatest_version( + upper_bound, + latest_resolvable_version + ) + + req_string.sub( + upper_bound.to_s, + new_upper_bound.to_s + ) + end + + def create_new_range_requirement(string_reqs) + version = latest_resolvable_version + + lower_bound = + string_reqs. + map { |req| requirement_class.new(req) }. + flat_map { |req| req.requirements.map(&:last) }. + min.to_s + + upper_bound = + if string_reqs.first.start_with?("~") && + version.to_s.split(".").count > 1 + create_upper_bound_for_tilda_req(string_reqs.first) + else + upper_bound_parts = [version.to_s.split(".").first.to_i + 1] + upper_bound_parts. + fill("0", 1..(lower_bound.split(".").count - 1)). + join(".") + end + + ">= #{lower_bound}, < #{upper_bound}" + end + + def create_upper_bound_for_tilda_req(string_req) + tilda_version = requirement_class.new(string_req). + requirements.map(&:last). + min.to_s + + upper_bound_parts = latest_resolvable_version.to_s.split(".") + upper_bound_parts.slice(0, tilda_version.to_s.split(".").count) + upper_bound_parts[-1] = "0" + upper_bound_parts[-2] = (upper_bound_parts[-2].to_i + 1).to_s + + upper_bound_parts.join(".") + end + + def update_greatest_version(old_version, version_to_be_permitted) + version = version_class.new(old_version) + version = version.release if version.prerelease? + + index_to_update = + version.segments.map.with_index { |seg, i| seg.zero? ? 0 : i }.max + + version.segments.map.with_index do |_, index| + if index < index_to_update + version_to_be_permitted.segments[index] + elsif index == index_to_update + version_to_be_permitted.segments[index] + 1 + else 0 + end + end.join(".") + end + + def version_class + Utils::Go::Version + end + + def requirement_class + Utils::Go::Requirement + end + end + end + end + end +end diff --git a/lib/dependabot/update_checkers/go/dep/version_resolver.rb b/lib/dependabot/update_checkers/go/dep/version_resolver.rb new file mode 100644 index 00000000000..7255830dc34 --- /dev/null +++ b/lib/dependabot/update_checkers/go/dep/version_resolver.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +require "toml-rb" +require "dependabot/shared_helpers" +require "dependabot/update_checkers/go/dep" +require "dependabot/errors" + +module Dependabot + module UpdateCheckers + module Go + class Dep + class VersionResolver + def initialize(dependency:, dependency_files:, credentials:) + @dependency = dependency + @dependency_files = dependency_files + @credentials = credentials + end + + def latest_resolvable_version + @latest_resolvable_version ||= fetch_latest_resolvable_version + end + + private + + attr_reader :dependency, :dependency_files, :credentials + + def fetch_latest_resolvable_version + updated_version = + Dir.chdir(go_dir) do + write_temporary_dependency_files + + SharedHelpers.with_git_configured(credentials: credentials) do + # Shell out to dep, which handles everything for us, and does + # so without doing an install (so it's fast). + command = "dep ensure -update --no-vendor #{dependency.name}" + run_shell_command(command) + end + + new_lockfile_content = File.read("Gopkg.lock") + + get_version_from_lockfile(new_lockfile_content) + end + + FileUtils.rm_rf(go_dir) + updated_version + end + + def get_version_from_lockfile(lockfile_content) + package = TomlRB.parse(lockfile_content).fetch("projects"). + find { |p| p["name"] == dependency.name } + + if package["version"] + version_class.new(package["version"].sub(/^v?/, "")) + else + package.fetch("revision") + end + end + + def run_shell_command(command) + raw_response = nil + IO.popen(command, err: %i(child out)) do |process| + raw_response = process.read + end + + # Raise an error with the output from the shell session if dep + # returns a non-zero status + return if $CHILD_STATUS.success? + raise SharedHelpers::HelperSubprocessFailed.new( + raw_response, + command + ) + end + + def write_temporary_dependency_files + dependency_files.each do |file| + path = file.name + FileUtils.mkdir_p(Pathname.new(path).dirname) + File.write(file.name, file.content) + end + + File.write("hello.go", dummy_app_content) + end + + def go_dir + # Work in a directory called "$HOME/go/src/dependabot-tmp". + # TODO: This should pick up what the user's actual GOPATH is. + go_dir = File.join(Dir.home, "go", "src", "dependabot-tmp") + FileUtils.mkdir_p(go_dir) + go_dir + end + + def dummy_app_content + base = "package main\n\n"\ + "import \"fmt\"\n\n" + + dependencies_to_import.each { |nm| base += "import \"#{nm}\"\n\n" } + + base + "func main() {\n fmt.Printf(\"hello, world\\n\")\n}" + end + + def dependencies_to_import + # There's no way to tell whether dependencies that appear in the + # lockfile are there because they're imported themselves or because + # they're sub-dependencies of something else. v0.5.0 will fix that + # problem, but for now we just have to import everything. + # + # NOTE: This means the `inputs-digest` we generate will be wrong. + # That's a pity, but we'd have to iterate through too many + # possibilities to get it right. Again, this is fixed in v0.5.0. + return [] unless lockfile + TomlRB.parse(lockfile.content).fetch("projects").map do |detail| + detail["name"] + end + end + + def lockfile + @lockfile = dependency_files.find { |f| f.name == "Gopkg.lock" } + end + + def version_class + Utils.version_class_for_package_manager(dependency.package_manager) + end + end + end + end + end +end diff --git a/lib/dependabot/update_checkers/rust/cargo.rb b/lib/dependabot/update_checkers/rust/cargo.rb index ca106367d09..5a42af9a218 100644 --- a/lib/dependabot/update_checkers/rust/cargo.rb +++ b/lib/dependabot/update_checkers/rust/cargo.rb @@ -143,7 +143,7 @@ def latest_git_tag_is_resolvable? def latest_resolvable_commit_with_unchanged_git_source fetch_latest_resolvable_version(unlock_requirement: false) rescue SharedHelpers::HelperSubprocessFailed => error - # Resolution may fail, as Elixir updates straight to the tip of the + # Resolution may fail, as Cargo updates straight to the tip of the # branch. Just return `nil` if it does (so no update). return if error.message.include?("versions conflict") raise error diff --git a/lib/dependabot/update_checkers/rust/cargo/requirements_updater.rb b/lib/dependabot/update_checkers/rust/cargo/requirements_updater.rb index 4e1f1b7c915..59b7608d0f4 100644 --- a/lib/dependabot/update_checkers/rust/cargo/requirements_updater.rb +++ b/lib/dependabot/update_checkers/rust/cargo/requirements_updater.rb @@ -94,7 +94,7 @@ def updated_library_requirement(req) return req if ruby_reqs.all? { |r| r.satisfied_by?(target_version) } # TODO: In future, we might want to treat libraries differently to - # applications. Fo now, since Rust allows multiple versions of the + # applications. For now, since Rust allows multiple versions of the # same dependeny, it's fine to upgrade them like apps if required updated_app_requirement(req) end diff --git a/lib/dependabot/utils.rb b/lib/dependabot/utils.rb index 216023bee47..3b084408925 100644 --- a/lib/dependabot/utils.rb +++ b/lib/dependabot/utils.rb @@ -7,6 +7,7 @@ require "dependabot/utils/php/version" require "dependabot/utils/python/version" require "dependabot/utils/rust/version" +require "dependabot/utils/go/version" require "dependabot/utils/dotnet/requirement" require "dependabot/utils/elixir/requirement" @@ -16,6 +17,7 @@ require "dependabot/utils/python/requirement" require "dependabot/utils/ruby/requirement" require "dependabot/utils/rust/requirement" +require "dependabot/utils/go/requirement" # rubocop:disable Metrics/CyclomaticComplexity module Dependabot @@ -31,6 +33,7 @@ def self.version_class_for_package_manager(package_manager) when "composer" then Utils::Php::Version when "hex" then Utils::Elixir::Version when "cargo" then Utils::Rust::Version + when "dep" then Utils::Go::Version else raise "Unsupported package_manager #{package_manager}" end end @@ -46,6 +49,7 @@ def self.requirement_class_for_package_manager(package_manager) when "composer" then Utils::Php::Requirement when "hex" then Utils::Elixir::Requirement when "cargo" then Utils::Rust::Requirement + when "dep" then Utils::Go::Requirement else raise "Unsupported package_manager #{package_manager}" end end diff --git a/lib/dependabot/utils/go/requirement.rb b/lib/dependabot/utils/go/requirement.rb new file mode 100644 index 00000000000..5dc7177dcff --- /dev/null +++ b/lib/dependabot/utils/go/requirement.rb @@ -0,0 +1,149 @@ +# frozen_string_literal: true + +################################################################################ +# For more details on Go version constraints, see: # +# - https://github.com/Masterminds/semver # +# - https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md # +################################################################################ + +require "dependabot/utils/go/version" + +module Dependabot + module Utils + module Go + class Requirement < Gem::Requirement + WILDCARD_REGEX = /(?:\.|^)[xX*]/ + OR_SEPARATOR = /(?<=[a-zA-Z0-9*])\s*\|{2}/ + + # Override the version pattern to allow a 'v' prefix + quoted = OPS.keys.map { |k| Regexp.quote(k) }.join("|") + version_pattern = "v?#{Gem::Version::VERSION_PATTERN}" + + PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{version_pattern})\\s*" + PATTERN = /\A#{PATTERN_RAW}\z/ + + # Use Utils::Go::Version rather than Gem::Version to ensure that + # pre-release versions aren't transformed. + def self.parse(obj) + if obj.is_a?(Gem::Version) + return ["=", Utils::Go::Version.new(obj.to_s)] + end + + unless (matches = PATTERN.match(obj.to_s)) + msg = "Illformed requirement [#{obj.inspect}]" + raise BadRequirementError, msg + end + + return DefaultRequirement if matches[1] == ">=" && matches[2] == "0" + [matches[1] || "=", Utils::Go::Version.new(matches[2])] + end + + # Returns an array of requirements. At least one requirement from the + # returned array must be satisfied for a version to be valid. + def self.requirements_array(requirement_string) + return [new(nil)] if requirement_string.nil? + requirement_string.strip.split(OR_SEPARATOR).map do |req_string| + new(req_string) + end + end + + def initialize(*requirements) + requirements = requirements.flatten.flat_map do |req_string| + req_string.split(",").map do |r| + convert_go_constraint_to_ruby_constraint(r.strip) + end + end + + super(requirements) + end + + private + + def convert_go_constraint_to_ruby_constraint(req_string) + req_string = req_string + req_string = convert_wildcard_characters(req_string) + + if req_string.match?(WILDCARD_REGEX) + ruby_range(req_string.gsub(WILDCARD_REGEX, "").gsub(/^[^\d]/, "")) + elsif req_string.match?(/^~[^>]/) then convert_tilde_req(req_string) + elsif req_string.include?(" - ") then convert_hyphen_req(req_string) + elsif req_string.match?(/^[\dv^]/) then convert_caret_req(req_string) + elsif req_string.match?(/[<=>]/) then req_string + else ruby_range(req_string) + end + end + + def convert_wildcard_characters(req_string) + if req_string.match?(/^[\dv^>~]/) + replace_wildcard_in_lower_bound(req_string) + elsif req_string.start_with?("<") + parts = req_string.split(".") + parts.map.with_index do |part, index| + next "0" if part.match?(WILDCARD_REGEX) + next part.to_i + 1 if parts[index + 1]&.match?(WILDCARD_REGEX) + part + end.join(".") + else + req_string + end + end + + def replace_wildcard_in_lower_bound(req_string) + after_wildcard = false + + if req_string.start_with?("~") + req_string = req_string.gsub(/(?:(?:\.|^)[xX*])(\.[xX*])+/, "") + end + + req_string.split("."). + map do |part| + part.split("-").map.with_index do |p, i| + # Before we hit a wildcard we just return the existing part + next p unless p.match?(WILDCARD_REGEX) || after_wildcard + + # On or after a wildcard we replace the version part with zero + after_wildcard = true + i.zero? ? "0" : "a" + end.join("-") + end.join(".") + end + + def convert_tilde_req(req_string) + version = req_string.gsub(/^~/, "") + parts = version.split(".") + parts << "0" if parts.count < 3 + "~> #{parts.join('.')}" + end + + def convert_hyphen_req(req_string) + lower_bound, upper_bound = req_string.split(/\s+-\s+/) + [">= #{lower_bound}", "<= #{upper_bound}"] + end + + def ruby_range(req_string) + parts = req_string.split(".") + + # If we have three or more parts then this is an exact match + return req_string if parts.count >= 3 + + # If we have no parts then the version is completely unlocked + return ">= 0" if parts.count.zero? + + # If we have fewer than three parts we do a partial match + parts << "0" + "~> #{parts.join('.')}" + end + + # Note: Dep's caret notation implementation doesn't distinguish between + # pre and post-1.0.0 requirements (unlike in JS) + def convert_caret_req(req_string) + version = req_string.gsub(/^\^?v?/, "") + parts = version.split(".") + upper_bound = [parts.first.to_i + 1, 0, 0, "a"].map(&:to_s).join(".") + + [">= #{version}", "< #{upper_bound}"] + end + end + end + end +end diff --git a/lib/dependabot/utils/go/version.rb b/lib/dependabot/utils/go/version.rb new file mode 100644 index 00000000000..b7ac7d12013 --- /dev/null +++ b/lib/dependabot/utils/go/version.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +# Go pre-release versions use 1.0.1-rc1 syntax, which Gem::Version +# converts into 1.0.1.pre.rc1. We override the `to_s` method to stop that +# alteration. +# Best docs are at https://github.com/Masterminds/semver + +module Dependabot + module Utils + module Go + class Version < Gem::Version + def self.correct?(version) + version = version.gsub(/^v/, "") if version.is_a?(String) + super(version) + end + + def initialize(version) + @version_string = version.to_s + version = version.gsub(/^v/, "") if version.is_a?(String) + super + end + + def to_s + @version_string + end + end + end + end +end diff --git a/spec/dependabot/file_fetchers/go/dep_spec.rb b/spec/dependabot/file_fetchers/go/dep_spec.rb new file mode 100644 index 00000000000..b14ef751644 --- /dev/null +++ b/spec/dependabot/file_fetchers/go/dep_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require "dependabot/file_fetchers/go/dep" +require_relative "../shared_examples_for_file_fetchers" + +RSpec.describe Dependabot::FileFetchers::Go::Dep do + it_behaves_like "a dependency file fetcher" + + let(:source) do + Dependabot::Source.new( + provider: "github", + repo: "gocardless/bump", + directory: directory + ) + end + let(:file_fetcher_instance) do + described_class.new(source: source, credentials: credentials) + end + let(:directory) { "/" } + let(:url) { "https://api.github.com/repos/gocardless/bump/contents/" } + let(:credentials) do + [{ + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + }] + end + + before do + allow(file_fetcher_instance).to receive(:commit).and_return("sha") + + stub_request(:get, url + "Gopkg.toml?ref=sha"). + with(headers: { "Authorization" => "token token" }). + to_return( + status: 200, + body: fixture("github", "contents_gopkg_toml.json"), + headers: { "content-type" => "application/json" } + ) + stub_request(:get, url + "Gopkg.lock?ref=sha"). + with(headers: { "Authorization" => "token token" }). + to_return( + status: 200, + body: fixture("github", "contents_gopkg_lock.json"), + headers: { "content-type" => "application/json" } + ) + end + + it "fetches the Gopkg.toml and Gopkg.lock" do + expect(file_fetcher_instance.files.map(&:name)). + to match_array(%w(Gopkg.toml Gopkg.lock)) + end + + context "without a Gopkg.lock" do + before do + stub_request(:get, url + "Gopkg.lock?ref=sha"). + with(headers: { "Authorization" => "token token" }). + to_return(status: 404) + end + + it "raises a helpful error" do + expect { file_fetcher_instance.files }. + to raise_error(Dependabot::DependencyFileNotFound) + end + end + + context "without a Gopkg.toml" do + before do + stub_request(:get, url + "Gopkg.toml?ref=sha"). + with(headers: { "Authorization" => "token token" }). + to_return(status: 404) + end + + it "raises a helpful error" do + expect { file_fetcher_instance.files }. + to raise_error(Dependabot::DependencyFileNotFound) + end + end +end diff --git a/spec/dependabot/file_parsers/go/dep_spec.rb b/spec/dependabot/file_parsers/go/dep_spec.rb new file mode 100644 index 00000000000..eb3c8787759 --- /dev/null +++ b/spec/dependabot/file_parsers/go/dep_spec.rb @@ -0,0 +1,170 @@ +# frozen_string_literal: true + +require "dependabot/dependency_file" +require "dependabot/source" +require "dependabot/file_parsers/go/dep" +require_relative "../shared_examples_for_file_parsers" + +RSpec.describe Dependabot::FileParsers::Go::Dep do + it_behaves_like "a dependency file parser" + + let(:parser) { described_class.new(dependency_files: files, source: source) } + + let(:files) { [manifest, lockfile] } + let(:manifest) do + Dependabot::DependencyFile.new( + name: "Gopkg.toml", + content: fixture("go", "gopkg_tomls", manifest_fixture_name) + ) + end + let(:lockfile) do + Dependabot::DependencyFile.new( + name: "Gopkg.lock", + content: fixture("go", "gopkg_locks", lockfile_fixture_name) + ) + end + let(:manifest_fixture_name) { "cockroach.toml" } + let(:lockfile_fixture_name) { "cockroach.lock" } + let(:source) do + Dependabot::Source.new( + provider: "github", + repo: "gocardless/bump", + directory: "/" + ) + end + + describe "parse" do + subject(:dependencies) { parser.parse } + + its(:length) { is_expected.to eq(149) } + + describe "top level dependencies" do + subject(:dependencies) { parser.parse.select(&:top_level?) } + + its(:length) { is_expected.to eq(11) } + + describe "a regular version dependency" do + subject(:dependency) do + dependencies.find { |d| d.name == "github.com/satori/go.uuid" } + end + + it "has the right details" do + expect(dependency).to be_a(Dependabot::Dependency) + expect(dependency.name).to eq("github.com/satori/go.uuid") + expect(dependency.version).to eq("1.2.0") + expect(dependency.requirements).to eq( + [{ + requirement: "v1.2.0", + file: "Gopkg.toml", + groups: [], + source: { + type: "default", + source: "github.com/satori/go.uuid" + } + }] + ) + end + + context "that doesn't declare a version" do + subject(:dependency) do + dependencies.find { |d| d.name == "github.com/dgrijalva/jwt-go" } + end + let(:manifest_fixture_name) { "no_version.toml" } + let(:lockfile_fixture_name) { "no_version.lock" } + + it "has the right details" do + expect(dependency).to be_a(Dependabot::Dependency) + expect(dependency.name).to eq("github.com/dgrijalva/jwt-go") + expect(dependency.version).to eq("1.0.1") + expect(dependency.requirements).to eq( + [{ + requirement: nil, + file: "Gopkg.toml", + groups: [], + source: { + type: "default", + source: "github.com/dgrijalva/jwt-go" + } + }] + ) + end + end + end + + describe "a git version dependency" do + subject(:dependency) do + dependencies.find { |d| d.name == "golang.org/x/text" } + end + + it "has the right details" do + expect(dependency).to be_a(Dependabot::Dependency) + expect(dependency.name).to eq("golang.org/x/text") + expect(dependency.version). + to eq("470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4") + expect(dependency.requirements).to eq( + [{ + requirement: nil, + file: "Gopkg.toml", + groups: [], + source: { + type: "git", + url: "https://github.com/golang/text", + branch: nil, + ref: "470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4" + } + }] + ) + end + + context "that specifies a tag as its revision" do + let(:manifest_fixture_name) { "tag_as_revision.toml" } + let(:lockfile_fixture_name) { "tag_as_revision.lock" } + + it "has the right details" do + expect(dependency).to be_a(Dependabot::Dependency) + expect(dependency.name).to eq("golang.org/x/text") + expect(dependency.version).to eq("v0.2.0") + expect(dependency.requirements).to eq( + [{ + requirement: nil, + file: "Gopkg.toml", + groups: [], + source: { + type: "git", + url: "https://github.com/golang/text", + branch: nil, + ref: "v0.2.0" + } + }] + ) + end + end + end + + describe "a dependency with an unrecognised name" do + let(:manifest_fixture_name) { "unknown_source.toml" } + let(:lockfile_fixture_name) { "unknown_source.lock" } + subject(:dependency) do + dependencies.find { |d| d.name == "unknownhost.com/dgrijalva/jwt-go" } + end + + it "has the right details" do + expect(dependency).to be_a(Dependabot::Dependency) + expect(dependency.name).to eq("unknownhost.com/dgrijalva/jwt-go") + expect(dependency.version).to eq("3.2.0") + expect(dependency.requirements).to eq( + [{ + requirement: "^3.2.0", + file: "Gopkg.toml", + groups: [], + source: { + type: "default", + source: "unknownhost.com/dgrijalva/jwt-go" + } + }] + ) + end + end + end + end +end diff --git a/spec/dependabot/file_updaters/go/dep/manifest_updater_spec.rb b/spec/dependabot/file_updaters/go/dep/manifest_updater_spec.rb new file mode 100644 index 00000000000..24393f2f214 --- /dev/null +++ b/spec/dependabot/file_updaters/go/dep/manifest_updater_spec.rb @@ -0,0 +1,192 @@ +# frozen_string_literal: true + +require "dependabot/dependency" +require "dependabot/dependency_file" +require "dependabot/file_updaters/go/dep/manifest_updater" + +RSpec.describe Dependabot::FileUpdaters::Go::Dep::ManifestUpdater do + let(:updater) do + described_class.new( + manifest: manifest, + dependencies: [dependency] + ) + end + + let(:manifest) do + Dependabot::DependencyFile.new(name: "Gopkg.toml", content: manifest_body) + end + let(:manifest_body) { fixture("go", "gopkg_tomls", manifest_fixture_name) } + let(:manifest_fixture_name) { "bare_version.toml" } + + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: dependency_version, + requirements: requirements, + previous_version: dependency_previous_version, + previous_requirements: previous_requirements, + package_manager: "dep" + ) + end + let(:dependency_name) { "github.com/dgrijalva/jwt-go" } + let(:dependency_version) { "3.2.0" } + let(:dependency_previous_version) { "1.0.1" } + let(:requirements) { previous_requirements } + let(:previous_requirements) do + [{ + file: "Gopkg.toml", + requirement: "1.0.0", + groups: [], + source: { + type: "default", + source: "github.com/dgrijalva/jwt-go" + } + }] + end + + describe "#updated_manifest_content" do + subject(:updated_manifest_content) { updater.updated_manifest_content } + + context "if no files have changed" do + it { is_expected.to eq(manifest.content) } + end + + context "when the requirement has changed" do + let(:requirements) do + [{ + file: "Gopkg.toml", + requirement: ">= 1.0.0, < 4.0.0", + groups: [], + source: { + type: "default", + source: "github.com/dgrijalva/jwt-go" + } + }] + end + + it { is_expected.to include(%(version = ">= 1.0.0, < 4.0.0")) } + end + + context "when the requirement in the manifest has been deleted" do + let(:requirements) do + [{ + file: "Gopkg.toml", + requirement: nil, + groups: [], + source: { + type: "default", + source: "github.com/dgrijalva/jwt-go" + } + }] + end + + it { is_expected.to end_with(%(name = "github.com/dgrijalva/jwt-go"\n)) } + end + + context "when a requirement is being added" do + let(:manifest_fixture_name) { "no_version.toml" } + let(:previous_requirements) do + [{ + file: "Gopkg.toml", + requirement: nil, + groups: [], + source: { + type: "default", + source: "github.com/dgrijalva/jwt-go" + } + }] + end + let(:requirements) do + [{ + file: "Gopkg.toml", + requirement: ">= 1.0.0, < 4.0.0", + groups: [], + source: { + type: "default", + source: "github.com/dgrijalva/jwt-go" + } + }] + end + + it "includes the new requirement" do + expect(updated_manifest_content). + to end_with(" name = \"github.com/dgrijalva/jwt-go\"\n"\ + " version = \">= 1.0.0, < 4.0.0\"\n") + end + end + + context "when the tag in the manifest has changed" do + let(:manifest_fixture_name) { "tag_as_revision.toml" } + let(:dependency_name) { "golang.org/x/text" } + let(:dependency_version) { "v0.3.0" } + let(:dependency_previous_version) { "v0.2.0" } + let(:requirements) do + [{ + requirement: nil, + file: "Gopkg.toml", + groups: [], + source: { + type: "git", + url: "https://github.com/golang/text", + branch: nil, + ref: "v0.3.0" + } + }] + end + let(:previous_requirements) do + [{ + requirement: nil, + file: "Gopkg.toml", + groups: [], + source: { + type: "git", + url: "https://github.com/golang/text", + branch: nil, + ref: "v0.2.0" + } + }] + end + + it "includes the new tag" do + expect(updated_manifest_content).to include(%(revision = "v0.3.0")) + end + end + + context "when switching from a git revision to a release" do + let(:manifest_fixture_name) { "tag_as_revision.toml" } + let(:dependency_name) { "golang.org/x/text" } + let(:dependency_version) { "0.3.0" } + let(:dependency_previous_version) { "v0.2.0" } + let(:requirements) do + [{ + requirement: "^0.3.0", + file: "Gopkg.toml", + groups: [], + source: { + type: "default", + source: "golang.org/x/text" + } + }] + end + let(:previous_requirements) do + [{ + requirement: nil, + file: "Gopkg.toml", + groups: [], + source: { + type: "git", + url: "https://github.com/golang/text", + branch: nil, + ref: "v0.2.0" + } + }] + end + + it "includes the new tag" do + expect(updated_manifest_content). + to end_with(" name = \"golang.org/x/text\"\n"\ + " version = \"^0.3.0\"\n") + end + end + end +end diff --git a/spec/dependabot/file_updaters/go/dep_spec.rb b/spec/dependabot/file_updaters/go/dep_spec.rb new file mode 100644 index 00000000000..f1d0a34b5a6 --- /dev/null +++ b/spec/dependabot/file_updaters/go/dep_spec.rb @@ -0,0 +1,118 @@ +# frozen_string_literal: true + +require "dependabot/dependency" +require "dependabot/dependency_file" +require "dependabot/file_updaters/go/dep" +require_relative "../shared_examples_for_file_updaters" + +RSpec.describe Dependabot::FileUpdaters::Go::Dep do + it_behaves_like "a dependency file updater" + + let(:updater) do + described_class.new( + dependency_files: files, + dependencies: [dependency], + credentials: [{ + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + }] + ) + end + + let(:files) { [manifest, lockfile] } + let(:manifest) do + Dependabot::DependencyFile.new(name: "Gopkg.toml", content: manifest_body) + end + let(:lockfile) do + Dependabot::DependencyFile.new(name: "Gopkg.lock", content: lockfile_body) + end + let(:manifest_body) { fixture("go", "gopkg_tomls", manifest_fixture_name) } + let(:lockfile_body) { fixture("go", "gopkg_locks", lockfile_fixture_name) } + let(:manifest_fixture_name) { "bare_version.toml" } + let(:lockfile_fixture_name) { "bare_version.lock" } + + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: dependency_version, + requirements: requirements, + previous_version: dependency_previous_version, + previous_requirements: previous_requirements, + package_manager: "dep" + ) + end + let(:dependency_name) { "github.com/dgrijalva/jwt-go" } + let(:dependency_version) { "3.2.0" } + let(:dependency_previous_version) { "1.0.1" } + let(:requirements) { previous_requirements } + let(:previous_requirements) do + [{ + file: "Gopkg.toml", + requirement: "1.0.0", + groups: [], + source: { + type: "default", + source: "github.com/dgrijalva/jwt-go" + } + }] + end + let(:tmp_path) { Dependabot::SharedHelpers::BUMP_TMP_DIR_PATH } + + before { Dir.mkdir(tmp_path) unless Dir.exist?(tmp_path) } + + describe "#updated_dependency_files" do + subject(:updated_files) { updater.updated_dependency_files } + + it "doesn't store the files permanently, and returns DependencyFiles" do + expect { updated_files }.to_not(change { Dir.entries(tmp_path) }) + updated_files.each { |f| expect(f).to be_a(Dependabot::DependencyFile) } + end + + it { expect { updated_files }.to_not output.to_stdout } + + context "without a lockfile" do + let(:files) { [manifest] } + + context "if no files have changed" do + it "raises a helpful error" do + expect { updater.updated_dependency_files }. + to raise_error("No files changed!") + end + end + + context "when the requirement in the manifest has changed" do + let(:requirements) do + [{ + file: "Gopkg.toml", + requirement: ">= 1.0.0, < 4.0.0", + groups: [], + source: { + type: "default", + source: "github.com/dgrijalva/jwt-go" + } + }] + end + + its(:length) { is_expected.to eq(1) } + + describe "the updated manifest" do + subject(:updated_manifest_content) do + updated_files.find { |f| f.name == "Gopkg.toml" }.content + end + + it "includes the new requirement" do + expect(described_class::ManifestUpdater). + to receive(:new). + with(dependencies: [dependency], manifest: manifest). + and_call_original + + expect(updated_manifest_content). + to include(%(version = ">= 1.0.0, < 4.0.0")) + end + end + end + end + end +end diff --git a/spec/dependabot/git_commit_checker_spec.rb b/spec/dependabot/git_commit_checker_spec.rb index 91da12ab8e6..b1a7bb3c630 100644 --- a/spec/dependabot/git_commit_checker_spec.rb +++ b/spec/dependabot/git_commit_checker_spec.rb @@ -8,7 +8,8 @@ let(:checker) do described_class.new( dependency: dependency, - credentials: credentials + credentials: credentials, + ignored_versions: ignored_versions ) end @@ -20,6 +21,7 @@ package_manager: "bundler" ) end + let(:ignored_versions) { [] } let(:requirements) do [{ file: "Gemfile", requirement: ">= 0", groups: [], source: source }] @@ -703,6 +705,11 @@ its([:tag_sha]) do is_expected.to eq("37f41032a0f191507903ebbae8a5c0cb945d7585") end + + context "and an ignore condition" do + let(:ignored_versions) { [">= 1.12.0"] } + its([:tag]) { is_expected.to eq("v1.11.1") } + end end end end diff --git a/spec/dependabot/metadata_finders/go/dep_spec.rb b/spec/dependabot/metadata_finders/go/dep_spec.rb new file mode 100644 index 00000000000..444590b1cbe --- /dev/null +++ b/spec/dependabot/metadata_finders/go/dep_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require "dependabot/dependency" +require "dependabot/metadata_finders/go/dep" +require_relative "../shared_examples_for_metadata_finders" + +RSpec.describe Dependabot::MetadataFinders::Go::Dep do + it_behaves_like "a dependency metadata finder" + + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "2.1.0", + requirements: requirements, + package_manager: "dep" + ) + end + let(:requirements) do + [{ + file: "Gopkg.toml", + requirement: "v2.1.0", + groups: [], + source: source + }] + end + subject(:finder) do + described_class.new(dependency: dependency, credentials: credentials) + end + let(:credentials) do + [{ + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + }] + end + let(:dependency_name) { "github.com/satori/go.uuid" } + let(:source) { nil } + + describe "#source_url" do + subject(:source_url) { finder.source_url } + + context "with a github name" do + it { is_expected.to eq("https://github.com/satori/go.uuid") } + + context "and no requirements" do + it { is_expected.to eq("https://github.com/satori/go.uuid") } + end + + context "that uses golang.org" do + let(:dependency_name) { "golang.org/x/text" } + it { is_expected.to eq("https://github.com/golang/text") } + end + end + + context "with a source" do + let(:source) do + { + type: "default", + source: "github.com/alias/go.uuid", + branch: nil, + ref: nil + } + end + + it { is_expected.to eq("https://github.com/alias/go.uuid") } + end + end +end diff --git a/spec/dependabot/update_checkers/go/dep/file_preparer_spec.rb b/spec/dependabot/update_checkers/go/dep/file_preparer_spec.rb new file mode 100644 index 00000000000..300537301a8 --- /dev/null +++ b/spec/dependabot/update_checkers/go/dep/file_preparer_spec.rb @@ -0,0 +1,234 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/dependency" +require "dependabot/update_checkers/go/dep/file_preparer" + +RSpec.describe Dependabot::UpdateCheckers::Go::Dep::FilePreparer do + let(:preparer) do + described_class.new( + dependency_files: dependency_files, + dependency: dependency, + unlock_requirement: unlock_requirement, + remove_git_source: remove_git_source, + replacement_git_pin: replacement_git_pin, + latest_allowable_version: latest_allowable_version + ) + end + + let(:dependency_files) { [manifest, lockfile] } + let(:unlock_requirement) { true } + let(:remove_git_source) { false } + let(:replacement_git_pin) { nil } + let(:latest_allowable_version) { nil } + + let(:manifest) do + Dependabot::DependencyFile.new( + name: "Gopkg.toml", + content: fixture("go", "gopkg_tomls", manifest_fixture_name) + ) + end + let(:lockfile) do + Dependabot::DependencyFile.new( + name: "Gopkg.lock", + content: fixture("go", "gopkg_locks", lockfile_fixture_name) + ) + end + let(:manifest_fixture_name) { "bare_version.toml" } + let(:lockfile_fixture_name) { "bare_version.lock" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: dependency_version, + requirements: requirements, + package_manager: "dep" + ) + end + let(:requirements) do + [{ + file: "Gopkg.toml", + requirement: string_req, + groups: [], + source: source + }] + end + let(:dependency_name) { "github.com/dgrijalva/jwt-go" } + let(:source) { { type: "default", source: "github.com/dgrijalva/jwt-go" } } + let(:dependency_version) { "1.0.1" } + let(:string_req) { "1.0.0" } + + describe "#prepared_dependency_files" do + subject(:prepared_dependency_files) { preparer.prepared_dependency_files } + + its(:length) { is_expected.to eq(2) } + + describe "the updated Gopkg.toml" do + subject(:prepared_manifest_file) do + prepared_dependency_files.find { |f| f.name == "Gopkg.toml" } + end + + context "with unlock_requirement set to false" do + let(:unlock_requirement) { false } + + it "doesn't update the requirement" do + expect(prepared_manifest_file.content).to include('version = "1.0.0"') + end + end + + context "with unlock_requirement set to true" do + let(:unlock_requirement) { true } + + it "updates the requirement" do + expect(prepared_manifest_file.content). + to include('version = ">= 1.0.1"') + end + + context "without a lockfile" do + let(:dependency_files) { [manifest] } + let(:dependency_version) { nil } + let(:string_req) { "1.0.0" } + + it "updates the requirement" do + expect(prepared_manifest_file.content). + to include('version = ">= 1.0.0"') + end + end + + context "with a blank requirement" do + let(:manifest_fixture_name) { "no_version.toml" } + let(:lockfile_fixture_name) { "no_version.lock" } + let(:string_req) { nil } + + it "updates the requirement" do + expect(prepared_manifest_file.content). + to include('version = ">= 1.0.1"') + end + + context "and a latest_allowable_version" do + let(:latest_allowable_version) { Gem::Version.new("1.6.0") } + + it "updates the requirement" do + expect(prepared_manifest_file.content). + to include('version = ">= 1.0.1, <= 1.6.0"') + end + + context "that is lower than the current lower bound" do + let(:latest_allowable_version) { Gem::Version.new("0.1.0") } + + it "updates the requirement" do + expect(prepared_manifest_file.content). + to include('version = ">= 1.0.1"') + end + end + end + + context "without a lockfile" do + let(:dependency_files) { [manifest] } + let(:dependency_version) { nil } + let(:string_req) { nil } + + it "updates the requirement" do + expect(prepared_manifest_file.content). + to include('version = ">= 0"') + end + end + end + + context "with a git requirement" do + context "with a branch" do + let(:manifest_fixture_name) { "branch.toml" } + let(:lockfile_fixture_name) { "branch.lock" } + let(:dependency_name) { "golang.org/x/text" } + let(:dependency_version) do + "7dd2c8130f5e924233f5543598300651c386d431" + end + let(:string_req) { nil } + let(:source) do + { + type: "git", + url: "https://github.com/golang/text", + branch: "master", + ref: nil + } + end + + it "doesn't update the manifest" do + expect(prepared_manifest_file.content). + to_not include("version =") + end + + context "that we want to remove" do + let(:remove_git_source) { true } + + it "removes the git source" do + expect(prepared_manifest_file.content). + to include('version = ">= 0"') + expect(prepared_manifest_file.content). + to_not include("branch = ") + end + end + end + + context "with a tag" do + let(:manifest_fixture_name) { "tag_as_revision.toml" } + let(:lockfile_fixture_name) { "tag_as_revision.lock" } + let(:dependency_version) { "v0.2.0" } + let(:dependency_name) { "golang.org/x/text" } + let(:string_req) { nil } + let(:source) do + { + type: "git", + url: "https://github.com/golang/text", + branch: nil, + ref: "v0.2.0" + } + end + + context "without a replacement tag" do + let(:replacement_git_pin) { nil } + + it "doesn't update the tag" do + expect(prepared_manifest_file.content). + to include('revision = "v0.2.0"') + expect(prepared_manifest_file.content). + to_not include("version =") + end + + context "when we want to remove the tag" do + let(:remove_git_source) { true } + + it "removes the git source" do + expect(prepared_manifest_file.content). + to include('version = ">= 0"') + expect(prepared_manifest_file.content). + to_not include("revision = ") + end + end + end + + context "with a replacement tag" do + let(:replacement_git_pin) { "v1.0.0" } + + it "updates the requirement" do + expect(prepared_manifest_file.content). + to include('revision = "v1.0.0"') + expect(prepared_manifest_file.content). + to_not include("version =") + end + end + end + end + end + end + + describe "the updated lockfile" do + subject { prepared_dependency_files.find { |f| f.name == "Gopkg.lock" } } + it { is_expected.to eq(lockfile) } + end + + context "without a lockfile" do + let(:dependency_files) { [manifest] } + its(:length) { is_expected.to eq(1) } + end + end +end diff --git a/spec/dependabot/update_checkers/go/dep/latest_version_finder_spec.rb b/spec/dependabot/update_checkers/go/dep/latest_version_finder_spec.rb new file mode 100644 index 00000000000..3e40ab42385 --- /dev/null +++ b/spec/dependabot/update_checkers/go/dep/latest_version_finder_spec.rb @@ -0,0 +1,170 @@ +# frozen_string_literal: true + +require "dependabot/update_checkers/go/dep/latest_version_finder" + +RSpec.describe Dependabot::UpdateCheckers::Go::Dep::LatestVersionFinder do + let(:finder) do + described_class.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials, + ignored_versions: ignored_versions + ) + end + + let(:ignored_versions) { [] } + let(:credentials) do + [{ + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + }] + end + let(:dependency_files) do + [ + Dependabot::DependencyFile.new( + name: "Gopkg.toml", + content: fixture("go", "gopkg_tomls", manifest_fixture_name) + ), + Dependabot::DependencyFile.new( + name: "Gopkg.lock", + content: fixture("go", "gopkg_locks", lockfile_fixture_name) + ) + ] + end + let(:manifest_fixture_name) { "no_version.toml" } + let(:lockfile_fixture_name) { "no_version.lock" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: dependency_version, + requirements: requirements, + package_manager: "dep" + ) + end + let(:requirements) do + [{ file: "Gopkg.toml", requirement: req_str, groups: [], source: source }] + end + let(:dependency_name) { "golang.org/x/text" } + let(:dependency_version) { "0.2.0" } + let(:req_str) { nil } + let(:source) { { type: "default", source: "golang.org/x/text" } } + + let(:service_pack_url) do + "https://github.com/golang/text.git/info/refs"\ + "?service=git-upload-pack" + end + before do + stub_request(:get, service_pack_url). + to_return( + status: 200, + body: fixture("git", "upload_packs", upload_pack_fixture), + headers: { + "content-type" => "application/x-git-upload-pack-advertisement" + } + ) + end + let(:upload_pack_fixture) { "text" } + + describe "#latest_version" do + subject { finder.latest_version } + it { is_expected.to eq(Gem::Version.new("0.3.0")) } + + context "with a sub-dependency" do + let(:requirements) { [] } + it { is_expected.to eq(Gem::Version.new("0.3.0")) } + end + + context "with a git source" do + context "that specifies a branch" do + let(:manifest_fixture_name) { "branch.toml" } + let(:lockfile_fixture_name) { "branch.lock" } + + let(:source) do + { + type: "git", + url: "https://github.com/golang/text", + branch: "master", + ref: nil + } + end + + before do + repo_url = "https://api.github.com/repos/golang/text" + stub_request(:get, repo_url + "/compare/v0.3.0...master"). + to_return( + status: 200, + body: commit_compare_response, + headers: { "Content-Type" => "application/json" } + ) + end + + context "that is behind the latest release" do + let(:commit_compare_response) do + fixture("github", "commit_compare_behind.json") + end + + it { is_expected.to eq(Gem::Version.new("0.3.0")) } + end + + context "that is diverged from the latest release" do + let(:commit_compare_response) do + fixture("github", "commit_compare_diverged.json") + end + + it { is_expected.to eq("0605a8320aceb4207a5fb3521281e17ec2075476") } + end + end + + context "that specifies a tag" do + let(:manifest_fixture_name) { "tag_as_revision.toml" } + let(:lockfile_fixture_name) { "tag_as_revision.lock" } + + let(:source) do + { + type: "git", + url: "https://github.com/golang/text", + branch: nil, + ref: "v0.2.0" + } + end + + before do + repo_url = "https://api.github.com/repos/golang/text" + stub_request(:get, repo_url + "/compare/v0.3.0...v0.2.0"). + to_return( + status: 200, + body: commit_compare_response, + headers: { "Content-Type" => "application/json" } + ) + end + let(:commit_compare_response) do + fixture("github", "commit_compare_behind.json") + end + + it { is_expected.to eq(Gem::Version.new("0.3.0")) } + + context "that is up-to-date" do + let(:commit_compare_response) do + fixture("github", "commit_compare_identical.json") + end + + # Still make an update as we wish to switch source declaration style. + # (Could decide not to do this if it causes trouble.) + it { is_expected.to eq(Gem::Version.new("0.3.0")) } + end + + context "when the new version isn't a direct update to the old one" do + let(:commit_compare_response) do + fixture("github", "commit_compare_diverged.json") + end + + # Still make an update as we wish to switch source declaration style. + # (Could decide not to do this if it causes trouble.) + it { is_expected.to eq("v0.3.0") } + end + end + end + end +end diff --git a/spec/dependabot/update_checkers/go/dep/requirements_updater_spec.rb b/spec/dependabot/update_checkers/go/dep/requirements_updater_spec.rb new file mode 100644 index 00000000000..bccff650d18 --- /dev/null +++ b/spec/dependabot/update_checkers/go/dep/requirements_updater_spec.rb @@ -0,0 +1,366 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/update_checkers/go/dep/requirements_updater" + +RSpec.describe Dependabot::UpdateCheckers::Go::Dep::RequirementsUpdater do + let(:updater) do + described_class.new( + requirements: requirements, + updated_source: updated_source, + latest_version: latest_version, + latest_resolvable_version: latest_resolvable_version + ) + end + + let(:requirements) { [manifest_req] } + let(:updated_source) { nil } + let(:manifest_req) do + { + file: "Gopkg.toml", + requirement: manifest_req_string, + groups: [], + source: nil + } + end + let(:manifest_req_string) { "^1.4.0" } + + let(:latest_version) { "1.8.0" } + let(:latest_resolvable_version) { "1.5.0" } + let(:version_class) { Dependabot::Utils::Go::Version } + + describe "#updated_requirements" do + subject { updater.updated_requirements.first } + + specify { expect(updater.updated_requirements.count).to eq(1) } + + let(:manifest_req_string) { "^1.0.0" } + let(:latest_resolvable_version) { nil } + + context "when there is no resolvable version" do + let(:latest_resolvable_version) { nil } + its([:requirement]) { is_expected.to eq(manifest_req_string) } + end + + context "with a git dependency" do + let(:latest_resolvable_version) { Gem::Version.new("1.5.0") } + let(:manifest_req) do + { + file: "Gopkg.toml", + requirement: manifest_req_string, + groups: [], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "2.0.0" + } + } + end + let(:updated_source) do + { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "2.1.0" + } + end + + context "with no requirement" do + let(:manifest_req_string) { nil } + + it "updates the source" do + expect(updater.updated_requirements). + to eq( + [{ + file: "Gopkg.toml", + requirement: nil, + groups: [], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "2.1.0" + } + }] + ) + end + + context "updating to use releases" do + let(:updated_source) do + { + type: "default", + source: "golang.org/x/text" + } + end + + it "updates the source and requirement" do + expect(updater.updated_requirements). + to eq( + [{ + file: "Gopkg.toml", + requirement: "^1.5.0", + groups: [], + source: { + type: "default", + source: "golang.org/x/text" + } + }] + ) + end + end + end + end + + context "for a library-style update" do + context "when there is a resolvable version" do + let(:latest_resolvable_version) { Gem::Version.new("1.5.0") } + + context "and a full version was previously specified" do + let(:manifest_req_string) { "1.2.3" } + its([:requirement]) { is_expected.to eq("1.2.3") } + + context "that needs to be updated" do + let(:manifest_req_string) { "0.1.3" } + its([:requirement]) { is_expected.to eq(">= 0.1.3, < 2.0.0") } + end + end + + context "and v-prefix was previously used" do + let(:manifest_req_string) { "v1.2.3" } + its([:requirement]) { is_expected.to eq("v1.2.3") } + + context "that needs to be updated" do + let(:manifest_req_string) { "v0.1.3" } + its([:requirement]) { is_expected.to eq(">= 0.1.3, < 2.0.0") } + end + end + + context "and a partial version was previously specified" do + let(:manifest_req_string) { "0.1" } + its([:requirement]) { is_expected.to eq(">= 0.1, < 2.0") } + end + + context "and only the major part was previously specified" do + let(:manifest_req_string) { "1" } + let(:latest_resolvable_version) { Gem::Version.new("4.5.0") } + its([:requirement]) { is_expected.to eq(">= 1, < 5") } + end + + context "and the new version has fewer digits than the old one" do + let(:manifest_req_string) { "1.1.0.1" } + its([:requirement]) { is_expected.to eq("1.1.0.1") } + end + + context "and the new version has much fewer digits than the old one" do + let(:manifest_req_string) { "1.1.0.1" } + let(:latest_resolvable_version) { Gem::Version.new("4") } + its([:requirement]) { is_expected.to eq(">= 1.1.0.1, < 5.0.0.0") } + end + + context "with a < condition" do + let(:manifest_req_string) { "< 1.2.0" } + its([:requirement]) { is_expected.to eq("< 1.6.0") } + end + + context "and a - was previously specified" do + let(:manifest_req_string) { "1.2.3 - 1.4.0" } + its([:requirement]) { is_expected.to eq("1.2.3 - 1.6.0") } + + context "with a pre-release version" do + let(:manifest_req_string) { "1.2.3-rc1 - 1.4.0" } + its([:requirement]) { is_expected.to eq("1.2.3-rc1 - 1.6.0") } + end + end + + context "and a pre-release was previously specified" do + let(:manifest_req_string) { "1.2.3-rc1" } + its([:requirement]) { is_expected.to eq("1.2.3-rc1") } + + context "when the version needs updating" do + let(:latest_resolvable_version) { Gem::Version.new("2.5.0") } + its([:requirement]) { is_expected.to eq(">= 1.2.3-rc1, < 3.0.0") } + end + end + + context "and a caret was previously specified" do + context "that the latest version satisfies" do + let(:manifest_req_string) { "^1.2.3" } + its([:requirement]) { is_expected.to eq("^1.2.3") } + end + + context "that the latest version does not satisfy" do + let(:manifest_req_string) { "^0.8.0" } + its([:requirement]) { is_expected.to eq(">= 0.8.0, < 2.0.0") } + end + + context "including a pre-release" do + let(:manifest_req_string) { "^1.2.3-rc1" } + its([:requirement]) { is_expected.to eq("^1.2.3-rc1") } + end + + context "updating to a pre-release of a new major version" do + let(:manifest_req_string) { "^1.0.0-beta1" } + let(:latest_resolvable_version) { version_class.new("2.0.0-alpha") } + its([:requirement]) do + is_expected.to eq(">= 1.0.0-beta1, < 3.0.0") + end + end + + context "including an x" do + let(:latest_resolvable_version) { Gem::Version.new("0.0.2") } + let(:manifest_req_string) { "^0.0.x" } + its([:requirement]) { is_expected.to eq("^0.0.x") } + + context "when the range isn't covered" do + let(:latest_resolvable_version) { Gem::Version.new("1.2.0") } + its([:requirement]) { is_expected.to eq(">= 0.0.0, < 2.0.0") } + end + end + + context "on a version that is all zeros" do + let(:latest_resolvable_version) { Gem::Version.new("0.0.2") } + let(:manifest_req_string) { "^0.0.0" } + its([:requirement]) { is_expected.to eq("^0.0.0") } + end + end + + context "and an x.x was previously specified" do + let(:manifest_req_string) { "0.x.x" } + its([:requirement]) { is_expected.to eq(">= 0.0.0, < 2.0.0") } + + context "four places" do + let(:manifest_req_string) { "0.x.x-rc1" } + its([:requirement]) { is_expected.to eq(">= 0.0.0-a, < 2.0.0") } + end + end + + context "with just *" do + let(:manifest_req_string) { "*" } + its([:requirement]) { is_expected.to eq("*") } + end + + context "and a tilda was previously specified" do + let(:latest_resolvable_version) { Gem::Version.new("2.5.3") } + + context "that the latest version satisfies" do + let(:manifest_req_string) { "~2.5.1" } + its([:requirement]) { is_expected.to eq("~2.5.1") } + end + + context "that the latest version does not satisfy" do + let(:manifest_req_string) { "~2.4.1" } + its([:requirement]) { is_expected.to eq(">= 2.4.1, < 2.6.0") } + end + + context "including a pre-release" do + let(:manifest_req_string) { "~2.5.1-rc1" } + its([:requirement]) { is_expected.to eq("~2.5.1-rc1") } + end + + context "including an x" do + let(:manifest_req_string) { "~2.x.x" } + its([:requirement]) { is_expected.to eq("~2.x.x") } + + context "when the range isn't covered" do + let(:manifest_req_string) { "~2.4.x" } + its([:requirement]) { is_expected.to eq(">= 2.4.0, < 2.6.0") } + end + end + end + + context "and there were multiple specifications" do + let(:manifest_req_string) { "> 1.0.0, < 1.2.0" } + its([:requirement]) { is_expected.to eq("> 1.0.0, < 1.6.0") } + + context "already valid" do + let(:manifest_req_string) { "> 1.0.0, < 1.7.0" } + its([:requirement]) { is_expected.to eq(manifest_req_string) } + end + + context "specified with || and valid" do + let(:manifest_req_string) { "^1.0.0 || ^2.0.0" } + its([:requirement]) { is_expected.to eq(manifest_req_string) } + end + + context "that include a pre-release" do + let(:manifest_req_string) { ">=1.2.0, <1.4.0-dev" } + its([:requirement]) { is_expected.to eq(">=1.2.0, <1.6.0") } + end + end + + context "and there were multiple requirements" do + let(:requirements) { [manifest_req, other_manifest_req] } + + let(:other_manifest_req) do + { + file: "another/Gopkg.toml", + requirement: other_requirement_string, + groups: [], + source: nil + } + end + let(:manifest_req_string) { "^1.2.3" } + let(:other_requirement_string) { "^0.x.x" } + + it "updates the requirement that needs to be updated" do + expect(updater.updated_requirements).to match_array( + [ + { + file: "Gopkg.toml", + requirement: "^1.2.3", + groups: [], + source: nil + }, + { + file: "another/Gopkg.toml", + requirement: ">= 0.0.0, < 2.0.0", + groups: [], + source: nil + } + ] + ) + end + + context "for the same file" do + let(:requirements) do + [ + { + requirement: "0.1.x", + file: "Gopkg.toml", + groups: ["dependencies"], + source: nil + }, + { + requirement: "^0.1.0", + file: "Gopkg.toml", + groups: ["devDependencies"], + source: nil + } + ] + end + + it "updates both requirements" do + expect(updater.updated_requirements).to match_array( + [ + { + requirement: ">= 0.1.0, < 2.0.0", + file: "Gopkg.toml", + groups: ["dependencies"], + source: nil + }, + { + requirement: ">= 0.1.0, < 2.0.0", + file: "Gopkg.toml", + groups: ["devDependencies"], + source: nil + } + ] + ) + end + end + end + end + end + end +end diff --git a/spec/dependabot/update_checkers/go/dep/version_resolver_spec.rb b/spec/dependabot/update_checkers/go/dep/version_resolver_spec.rb new file mode 100644 index 00000000000..364eddee5fb --- /dev/null +++ b/spec/dependabot/update_checkers/go/dep/version_resolver_spec.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/dependency_file" +require "dependabot/update_checkers/go/dep/version_resolver" + +RSpec.describe Dependabot::UpdateCheckers::Go::Dep::VersionResolver do + subject(:resolver) do + described_class.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials + ) + end + + let(:credentials) do + [{ + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + }] + end + let(:dependency_files) do + [ + Dependabot::DependencyFile.new( + name: "Gopkg.toml", + content: fixture("go", "gopkg_tomls", manifest_fixture_name) + ), + Dependabot::DependencyFile.new( + name: "Gopkg.lock", + content: fixture("go", "gopkg_locks", lockfile_fixture_name) + ) + ] + end + let(:manifest_fixture_name) { "no_version.toml" } + let(:lockfile_fixture_name) { "no_version.lock" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: dependency_version, + requirements: requirements, + package_manager: "cargo" + ) + end + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: dependency_version, + requirements: requirements, + package_manager: "dep" + ) + end + let(:requirements) do + [{ file: "Gopkg.toml", requirement: req_str, groups: [], source: source }] + end + let(:dependency_name) { "github.com/dgrijalva/jwt-go" } + let(:dependency_version) { "1.0.1" } + let(:req_str) { nil } + let(:source) { { type: "default", source: "github.com/dgrijalva/jwt-go" } } + + describe "latest_resolvable_version" do + subject(:latest_resolvable_version) { resolver.latest_resolvable_version } + + it { is_expected.to be >= Gem::Version.new("0.3.0") } + + context "with a git dependency" do + context "that specifies a branch" do + let(:manifest_fixture_name) { "branch.toml" } + let(:lockfile_fixture_name) { "branch.lock" } + let(:dependency_name) { "golang.org/x/text" } + let(:source) do + { + type: "git", + url: "https://github.com/golang/text", + branch: "master", + ref: nil + } + end + + it { is_expected.to eq("0605a8320aceb4207a5fb3521281e17ec2075476") } + end + + context "that specifies a tag as a revision" do + let(:manifest_fixture_name) { "tag_as_revision.toml" } + let(:lockfile_fixture_name) { "tag_as_revision.lock" } + let(:dependency_name) { "golang.org/x/text" } + let(:source) do + { + type: "git", + url: "https://github.com/golang/text", + branch: nil, + ref: "v0.2.0" + } + end + + it { is_expected.to eq("v0.2.0") } + end + end + end +end diff --git a/spec/dependabot/update_checkers/go/dep_spec.rb b/spec/dependabot/update_checkers/go/dep_spec.rb new file mode 100644 index 00000000000..e630e33bed2 --- /dev/null +++ b/spec/dependabot/update_checkers/go/dep_spec.rb @@ -0,0 +1,364 @@ +# frozen_string_literal: true + +require "dependabot/update_checkers/go/dep" +require_relative "../shared_examples_for_update_checkers" + +RSpec.describe Dependabot::UpdateCheckers::Go::Dep do + it_behaves_like "an update checker" + + let(:checker) do + described_class.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials, + ignored_versions: ignored_versions + ) + end + + let(:ignored_versions) { [] } + let(:credentials) do + [{ + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + }] + end + let(:dependency_files) do + [ + Dependabot::DependencyFile.new( + name: "Gopkg.toml", + content: fixture("go", "gopkg_tomls", manifest_fixture_name) + ), + Dependabot::DependencyFile.new( + name: "Gopkg.lock", + content: fixture("go", "gopkg_locks", lockfile_fixture_name) + ) + ] + end + let(:manifest_fixture_name) { "no_version.toml" } + let(:lockfile_fixture_name) { "no_version.lock" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: dependency_version, + requirements: requirements, + package_manager: "dep" + ) + end + let(:requirements) do + [{ file: "Gopkg.toml", requirement: req_str, groups: [], source: source }] + end + let(:dependency_name) { "github.com/dgrijalva/jwt-go" } + let(:dependency_version) { "1.0.1" } + let(:req_str) { nil } + let(:source) { { type: "default", source: "github.com/dgrijalva/jwt-go" } } + + before do + jwt_service_pack_url = + "https://github.com/dgrijalva/jwt-go.git/info/refs"\ + "?service=git-upload-pack" + stub_request(:get, jwt_service_pack_url). + to_return( + status: 200, + body: fixture("git", "upload_packs", "jwt-go"), + headers: { + "content-type" => "application/x-git-upload-pack-advertisement" + } + ) + + text_service_pack_url = + "https://github.com/golang/text.git/info/refs"\ + "?service=git-upload-pack" + stub_request(:get, text_service_pack_url). + to_return( + status: 200, + body: fixture("git", "upload_packs", "text"), + headers: { + "content-type" => "application/x-git-upload-pack-advertisement" + } + ) + end + + describe "#latest_version" do + subject { checker.latest_version } + + it "delegates to LatestVersionFinder" do + expect(described_class::LatestVersionFinder).to receive(:new).with( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials, + ignored_versions: ignored_versions + ).and_call_original + + expect(checker.latest_version).to eq(Gem::Version.new("3.2.0")) + end + end + + describe "#latest_resolvable_version" do + subject(:latest_resolvable_version) { checker.latest_resolvable_version } + + it "delegates to VersionResolver" do + prepped_files = described_class::FilePreparer.new( + dependency_files: dependency_files, + dependency: dependency, + unlock_requirement: true, + remove_git_source: false, + latest_allowable_version: Gem::Version.new("3.2.0") + ).prepared_dependency_files + + expect(described_class::VersionResolver).to receive(:new).with( + dependency: dependency, + dependency_files: prepped_files, + credentials: credentials + ).and_call_original + + expect(latest_resolvable_version).to eq(Gem::Version.new("3.2.0")) + end + + context "with a manifest file that needs unlocking" do + let(:manifest_fixture_name) { "bare_version.toml" } + let(:lockfile_fixture_name) { "bare_version.lock" } + let(:req_str) { "1.0.0" } + + it "unlocks the manifest and gets the correct version" do + expect(latest_resolvable_version).to eq(Gem::Version.new("3.2.0")) + end + end + + context "with a git dependency" do + let(:dependency_name) { "golang.org/x/text" } + let(:source) do + { + type: "git", + url: "https://github.com/golang/text", + branch: branch, + ref: ref + } + end + + before do + repo_url = "https://api.github.com/repos/golang/text" + stub_request(:get, repo_url + "/compare/v0.3.0...#{branch || ref}"). + to_return( + status: 200, + body: commit_compare_response, + headers: { "Content-Type" => "application/json" } + ) + end + let(:commit_compare_response) do + fixture("github", "commit_compare_behind.json") + end + + context "that specifies a branch" do + let(:manifest_fixture_name) { "branch.toml" } + let(:lockfile_fixture_name) { "branch.lock" } + let(:req_str) { nil } + let(:dependency_version) { "7dd2c8130f5e924233f5543598300651c386d431" } + let(:branch) { "master" } + let(:ref) { nil } + + context "that has diverged" do + let(:commit_compare_response) do + fixture("github", "commit_compare_diverged.json") + end + + it "updates the commit" do + expect(latest_resolvable_version). + to eq("0605a8320aceb4207a5fb3521281e17ec2075476") + end + end + + context "that is behind" do + let(:commit_compare_response) do + fixture("github", "commit_compare_behind.json") + end + + it "updates to a released version" do + expect(latest_resolvable_version).to eq(Gem::Version.new("0.3.0")) + end + end + end + + context "that specifies a tag" do + let(:manifest_fixture_name) { "tag_as_revision.toml" } + let(:lockfile_fixture_name) { "tag_as_revision.lock" } + let(:req_str) { nil } + let(:dependency_version) { "v0.2.0" } + let(:branch) { nil } + let(:ref) { "v0.2.0" } + + it "updates to a released version" do + expect(latest_resolvable_version).to eq(Gem::Version.new("0.3.0")) + end + end + end + end + + describe "#latest_resolvable_version_with_no_unlock" do + subject { checker.latest_resolvable_version_with_no_unlock } + + it "delegates to VersionResolver" do + prepped_files = described_class::FilePreparer.new( + dependency_files: dependency_files, + dependency: dependency, + unlock_requirement: true, + remove_git_source: false, + latest_allowable_version: Gem::Version.new("3.2.0") + ).prepared_dependency_files + + expect(described_class::VersionResolver).to receive(:new).with( + dependency: dependency, + dependency_files: prepped_files, + credentials: credentials + ).and_call_original + + expect(checker.latest_resolvable_version_with_no_unlock). + to eq(Gem::Version.new("3.2.0")) + end + + context "with a manifest file that needs unlocking" do + let(:manifest_fixture_name) { "bare_version.toml" } + let(:lockfile_fixture_name) { "bare_version.lock" } + let(:req_str) { "1.0.0" } + + it "doesn't unlock the manifest" do + expect(checker.latest_resolvable_version_with_no_unlock). + to eq(Gem::Version.new("1.0.2")) + end + end + + context "with a git dependency" do + let(:source) do + { + type: "git", + url: "https://github.com/golang/text", + branch: branch, + ref: ref + } + end + let(:dependency_name) { "golang.org/x/text" } + + before do + repo_url = "https://api.github.com/repos/golang/text" + stub_request(:get, repo_url + "/compare/v0.3.0...#{branch || ref}"). + to_return( + status: 200, + body: commit_compare_response, + headers: { "Content-Type" => "application/json" } + ) + end + let(:commit_compare_response) do + fixture("github", "commit_compare_behind.json") + end + + context "that specifies a branch" do + let(:manifest_fixture_name) { "branch.toml" } + let(:lockfile_fixture_name) { "branch.lock" } + let(:req_str) { nil } + let(:dependency_version) { "7dd2c8130f5e924233f5543598300651c386d431" } + let(:branch) { "master" } + let(:ref) { nil } + + it "updates the commit" do + expect(checker.latest_resolvable_version_with_no_unlock). + to eq("0605a8320aceb4207a5fb3521281e17ec2075476") + end + end + + context "that specifies a tag" do + let(:manifest_fixture_name) { "tag_as_revision.toml" } + let(:lockfile_fixture_name) { "tag_as_revision.lock" } + let(:req_str) { nil } + let(:dependency_version) { "v0.2.0" } + let(:branch) { nil } + let(:ref) { "v0.2.0" } + + it "doesn't unpin the commit" do + expect(checker.latest_resolvable_version_with_no_unlock). + to eq("v0.2.0") + end + end + end + end + + describe "#updated_requirements" do + subject { checker.updated_requirements } + + it "delegates to RequirementsUpdater" do + expect(described_class::RequirementsUpdater).to receive(:new).with( + requirements: dependency.requirements, + updated_source: source, + latest_version: "3.2.0", + latest_resolvable_version: "3.2.0" + ).and_call_original + + expect(checker.updated_requirements).to eq( + [{ + file: "Gopkg.toml", + requirement: nil, + groups: [], + source: { type: "default", source: "github.com/dgrijalva/jwt-go" } + }] + ) + end + + context "with a manifest file that needs unlocking" do + let(:manifest_fixture_name) { "bare_version.toml" } + let(:lockfile_fixture_name) { "bare_version.lock" } + let(:req_str) { "1.0.0" } + + it "updates the requirements for the new version range" do + expect(checker.updated_requirements).to eq( + [{ + file: "Gopkg.toml", + requirement: ">= 1.0.0, < 4.0.0", + groups: [], + source: { type: "default", source: "github.com/dgrijalva/jwt-go" } + }] + ) + end + end + + context "with a git dependency we should switch" do + let(:manifest_fixture_name) { "tag_as_revision.toml" } + let(:lockfile_fixture_name) { "tag_as_revision.lock" } + + let(:dependency_name) { "golang.org/x/text" } + let(:req_str) { nil } + let(:dependency_version) { "v0.2.0" } + let(:source) do + { + type: "git", + url: "https://github.com/golang/text", + branch: nil, + ref: "v0.2.0" + } + end + + before do + repo_url = "https://api.github.com/repos/golang/text" + stub_request(:get, repo_url + "/compare/v0.3.0...v0.2.0"). + to_return( + status: 200, + body: commit_compare_response, + headers: { "Content-Type" => "application/json" } + ) + end + let(:commit_compare_response) do + fixture("github", "commit_compare_behind.json") + end + + it "updates the requirements for the new version range" do + expect(checker.updated_requirements).to eq( + [{ + file: "Gopkg.toml", + requirement: "^0.3.0", + groups: [], + source: { type: "default", source: "golang.org/x/text" } + }] + ) + end + end + end +end diff --git a/spec/dependabot/utils/go/requirement_spec.rb b/spec/dependabot/utils/go/requirement_spec.rb new file mode 100644 index 00000000000..3d9dcc2ad3a --- /dev/null +++ b/spec/dependabot/utils/go/requirement_spec.rb @@ -0,0 +1,223 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/utils/go/requirement" + +RSpec.describe Dependabot::Utils::Go::Requirement do + subject(:requirement) { described_class.new(requirement_string) } + let(:requirement_string) { ">=1.0.0" } + + describe ".new" do + it { is_expected.to be_a(described_class) } + + context "with a blank string" do + let(:requirement_string) { "" } + it { is_expected.to eq(described_class.new(">= 0")) } + end + + context "with a 'v' prefix" do + let(:requirement_string) { ">=v1.0.0" } + it { is_expected.to eq(described_class.new(">= v1.0.0")) } + end + + context "with a pre-release" do + let(:requirement_string) { "4.0.0-beta3" } + it "preserves the pre-release formatting" do + expect(requirement.requirements.first.last.to_s).to eq("4.0.0-beta3") + end + end + + describe "wildcards" do + context "with only a *" do + let(:requirement_string) { "*" } + it { is_expected.to eq(described_class.new(">= 0")) } + end + + context "with a 1.*" do + let(:requirement_string) { "1.*" } + it { is_expected.to eq(described_class.new(">= 1.0, < 2.0.0.a")) } + + context "with two wildcards" do + let(:requirement_string) { "1.*.*" } + it { is_expected.to eq(described_class.new(">= 1.0.0, < 2.0.0.a")) } + end + + context "for a pre-1.0.0 release" do + let(:requirement_string) { "0.*" } + it { is_expected.to eq(described_class.new(">= 0.0, < 1.0.0.a")) } + end + end + + context "with a 1.*.1" do + let(:requirement_string) { "1.*.1" } + it { is_expected.to eq(described_class.new(">= 1.0.0, < 2.0.0.a")) } + end + + context "with a 1.1.*" do + let(:requirement_string) { "1.1.*" } + it { is_expected.to eq(described_class.new(">= 1.1.0", "< 2.0.0.a")) } + + context "prefixed with a caret" do + let(:requirement_string) { "^1.1.*" } + it { is_expected.to eq(described_class.new(">= 1.1.0", "< 2.0.0.a")) } + + context "for a pre-1.0.0 release" do + let(:requirement_string) { "^0.0.*" } + it do + is_expected.to eq(described_class.new(">= 0.0.0", "< 1.0.0.a")) + end + + context "with a pre-release specifier" do + let(:requirement_string) { "^0.0.*-alpha" } + + it "maintains a pre-release specifier" do + expect(requirement). + to eq(described_class.new(">= 0.0.0-a", "< 1.0.0.a")) + end + end + end + end + + context "prefixed with a ~" do + let(:requirement_string) { "~1.1.x" } + it { is_expected.to eq(described_class.new("~> 1.1.0")) } + + context "with two wildcards" do + let(:requirement_string) { "~1.x.x" } + it { is_expected.to eq(described_class.new("~> 1.0")) } + end + end + + context "prefixed with a <" do + let(:requirement_string) { "<1.1.X" } + it { is_expected.to eq(described_class.new("< 1.2.0")) } + end + end + end + + context "with no specifier" do + let(:requirement_string) { "1.1.0" } + it { is_expected.to eq(described_class.new(">= 1.1.0", "< 2.0.0.a")) } + + context "and a v prefix" do + let(:requirement_string) { "v1.1.0" } + it { is_expected.to eq(described_class.new(">= 1.1.0", "< 2.0.0.a")) } + end + end + + context "with a caret version" do + context "specified to 3 dp" do + let(:requirement_string) { "^1.2.3" } + it { is_expected.to eq(described_class.new(">= 1.2.3", "< 2.0.0.a")) } + + context "with a zero major" do + let(:requirement_string) { "^0.2.3" } + it { is_expected.to eq(described_class.new(">= 0.2.3", "< 1.0.0.a")) } + + context "and a zero minor" do + let(:requirement_string) { "^0.0.3" } + it do + is_expected.to eq(described_class.new(">= 0.0.3", "< 1.0.0.a")) + end + end + end + end + + context "specified to 2 dp" do + let(:requirement_string) { "^1.2" } + it { is_expected.to eq(described_class.new(">= 1.2", "< 2.0.0.a")) } + + context "with a zero major" do + let(:requirement_string) { "^0.2" } + it { is_expected.to eq(described_class.new(">= 0.2", "< 1.0.0.a")) } + + context "and a zero minor" do + let(:requirement_string) { "^0.0" } + it { is_expected.to eq(described_class.new(">= 0.0", "< 1.0.0.a")) } + end + end + end + + context "specified to 1 dp" do + let(:requirement_string) { "^1" } + it { is_expected.to eq(described_class.new(">= 1", "< 2.0.0.a")) } + + context "with a zero major" do + let(:requirement_string) { "^0" } + it { is_expected.to eq(described_class.new(">= 0", "< 1.0.0.a")) } + end + end + end + + context "with a ~ version" do + context "specified to 3 dp" do + let(:requirement_string) { "~1.5.1" } + it { is_expected.to eq(described_class.new("~> 1.5.1")) } + end + + context "specified to 2 dp" do + let(:requirement_string) { "~1.5" } + it { is_expected.to eq(described_class.new("~> 1.5.0")) } + end + + context "specified to 1 dp" do + let(:requirement_string) { "~1" } + it { is_expected.to eq(described_class.new("~> 1.0")) } + end + end + + context "with a > version specified" do + let(:requirement_string) { ">1.5.1" } + it { is_expected.to eq(Gem::Requirement.new("> 1.5.1")) } + end + + context "with a range literal specified" do + let(:requirement_string) { "1.1.1 - 1.2.0" } + it { is_expected.to eq(Gem::Requirement.new(">= 1.1.1", "<= 1.2.0")) } + end + + context "with an = version specified" do + let(:requirement_string) { "=1.5" } + it { is_expected.to eq(Gem::Requirement.new("1.5")) } + end + + context "with a != version specified" do + let(:requirement_string) { "!=1.5" } + it { is_expected.to eq(Gem::Requirement.new("!=1.5")) } + end + + context "with an ~> version specified" do + let(:requirement_string) { "~> 1.5.1" } + it { is_expected.to eq(Gem::Requirement.new("~> 1.5.1")) } + end + + context "with a comma separated list" do + let(:requirement_string) { ">1.5.1, < 2.0.0" } + it { is_expected.to eq(Gem::Requirement.new("> 1.5.1", "< 2.0.0")) } + end + end + + describe ".requirements_array" do + subject(:requirements) do + described_class.requirements_array(requirement_string) + end + + context "with a single requirement" do + let(:requirement_string) { ">=1.0.0" } + it { is_expected.to eq([described_class.new(">= 1.0.0")]) } + end + + context "with an OR requirement" do + let(:requirement_string) { "^1.1.0 || ^2.1.0" } + + it "returns an array of requirements" do + expect(requirements).to match_array( + [ + described_class.new(">= 1.1.0", "< 2.0.0.a"), + described_class.new(">= 2.1.0", "< 3.0.0.a") + ] + ) + end + end + end +end diff --git a/spec/dependabot/utils/go/version_spec.rb b/spec/dependabot/utils/go/version_spec.rb new file mode 100644 index 00000000000..c1776c456cf --- /dev/null +++ b/spec/dependabot/utils/go/version_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/utils/go/version" + +RSpec.describe Dependabot::Utils::Go::Version do + subject(:version) { described_class.new(version_string) } + let(:version_string) { "1.0.0" } + + describe ".correct?" do + subject { described_class.correct?(version_string) } + + context "with a string prefixed with a 'v'" do + let(:version_string) { "v1.0.0" } + it { is_expected.to eq(true) } + end + + context "with a string not prefixed with a 'v'" do + let(:version_string) { "1.0.0" } + it { is_expected.to eq(true) } + end + + context "with an invalid string" do + let(:version_string) { "va1.0.0" } + it { is_expected.to eq(false) } + end + end + + describe "#to_s" do + subject { version.to_s } + + context "with a non-prerelease" do + let(:version_string) { "1.0.0" } + it { is_expected.to eq "1.0.0" } + end + + context "with a normal prerelease" do + let(:version_string) { "1.0.0.pre1" } + it { is_expected.to eq "1.0.0.pre1" } + end + + context "with a PHP-style prerelease" do + let(:version_string) { "1.0.0-pre1" } + it { is_expected.to eq "1.0.0-pre1" } + end + end + + describe "compatibility with Gem::Requirement" do + subject { requirement.satisfied_by?(version) } + let(:requirement) { Gem::Requirement.new(">= 1.0.0") } + + context "with a valid version" do + let(:version_string) { "1.0.0" } + it { is_expected.to eq(true) } + end + + context "with an invalid version" do + let(:version_string) { "0.9.0" } + it { is_expected.to eq(false) } + end + + context "with a valid prerelease version" do + let(:version_string) { "1.1.0-pre" } + it { is_expected.to eq(true) } + end + + context "prefixed with a 'v'" do + context "with a greater version" do + let(:version_string) { "v1.1.0" } + it { is_expected.to eq(true) } + end + + context "with an lesser version" do + let(:version_string) { "v0.9.0" } + it { is_expected.to eq(false) } + end + end + end +end diff --git a/spec/fixtures/git/upload_packs/jwt-go b/spec/fixtures/git/upload_packs/jwt-go new file mode 100644 index 00000000000..f46f4edb830 Binary files /dev/null and b/spec/fixtures/git/upload_packs/jwt-go differ diff --git a/spec/fixtures/git/upload_packs/text b/spec/fixtures/git/upload_packs/text new file mode 100644 index 00000000000..ba8fa5d1db1 Binary files /dev/null and b/spec/fixtures/git/upload_packs/text differ diff --git a/spec/fixtures/github/commit_compare_identical.json b/spec/fixtures/github/commit_compare_identical.json new file mode 100644 index 00000000000..38dfe81fb89 --- /dev/null +++ b/spec/fixtures/github/commit_compare_identical.json @@ -0,0 +1,175 @@ +{ + "url": "https://api.github.com/repos/golang/text/compare/v0.3.0...v0.3.0", + "html_url": "https://github.com/golang/text/compare/v0.3.0...v0.3.0", + "permalink_url": "https://github.com/golang/text/compare/golang:f21a4df...golang:f21a4df", + "diff_url": "https://github.com/golang/text/compare/v0.3.0...v0.3.0.diff", + "patch_url": "https://github.com/golang/text/compare/v0.3.0...v0.3.0.patch", + "base_commit": { + "sha": "f21a4dfb5e38f5895301dc265a8def02365cc3d0", + "node_id": "MDY6Q29tbWl0Mjc1MjIyOTU6ZjIxYTRkZmI1ZTM4ZjU4OTUzMDFkYzI2NWE4ZGVmMDIzNjVjYzNkMA==", + "commit": { + "author": { + "name": "Marcel van Lohuizen", + "email": "mpvl@golang.org", + "date": "2017-12-09T17:05:50Z" + }, + "committer": { + "name": "Marcel van Lohuizen", + "email": "mpvl@golang.org", + "date": "2017-12-14T13:08:43Z" + }, + "message": "all: upgrade to CLDR 32\n\nChange-Id: I80ba02e97f8c9a6bc364cf8679b90aee13a1ce23\nReviewed-on: https://go-review.googlesource.com/82905\nRun-TryBot: Marcel van Lohuizen \nTryBot-Result: Gobot Gobot \nReviewed-by: Nigel Tao ", + "tree": { + "sha": "d495a1fe53fe3fd1794be36b4a4c8d835254db7b", + "url": "https://api.github.com/repos/golang/text/git/trees/d495a1fe53fe3fd1794be36b4a4c8d835254db7b" + }, + "url": "https://api.github.com/repos/golang/text/git/commits/f21a4dfb5e38f5895301dc265a8def02365cc3d0", + "comment_count": 0, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null + } + }, + "url": "https://api.github.com/repos/golang/text/commits/f21a4dfb5e38f5895301dc265a8def02365cc3d0", + "html_url": "https://github.com/golang/text/commit/f21a4dfb5e38f5895301dc265a8def02365cc3d0", + "comments_url": "https://api.github.com/repos/golang/text/commits/f21a4dfb5e38f5895301dc265a8def02365cc3d0/comments", + "author": { + "login": "mpvl", + "id": 6445383, + "node_id": "MDQ6VXNlcjY0NDUzODM=", + "avatar_url": "https://avatars2.githubusercontent.com/u/6445383?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/mpvl", + "html_url": "https://github.com/mpvl", + "followers_url": "https://api.github.com/users/mpvl/followers", + "following_url": "https://api.github.com/users/mpvl/following{/other_user}", + "gists_url": "https://api.github.com/users/mpvl/gists{/gist_id}", + "starred_url": "https://api.github.com/users/mpvl/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/mpvl/subscriptions", + "organizations_url": "https://api.github.com/users/mpvl/orgs", + "repos_url": "https://api.github.com/users/mpvl/repos", + "events_url": "https://api.github.com/users/mpvl/events{/privacy}", + "received_events_url": "https://api.github.com/users/mpvl/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "mpvl", + "id": 6445383, + "node_id": "MDQ6VXNlcjY0NDUzODM=", + "avatar_url": "https://avatars2.githubusercontent.com/u/6445383?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/mpvl", + "html_url": "https://github.com/mpvl", + "followers_url": "https://api.github.com/users/mpvl/followers", + "following_url": "https://api.github.com/users/mpvl/following{/other_user}", + "gists_url": "https://api.github.com/users/mpvl/gists{/gist_id}", + "starred_url": "https://api.github.com/users/mpvl/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/mpvl/subscriptions", + "organizations_url": "https://api.github.com/users/mpvl/orgs", + "repos_url": "https://api.github.com/users/mpvl/repos", + "events_url": "https://api.github.com/users/mpvl/events{/privacy}", + "received_events_url": "https://api.github.com/users/mpvl/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "d5f0155fc124972d018bea023348f2bd9e1d341e", + "url": "https://api.github.com/repos/golang/text/commits/d5f0155fc124972d018bea023348f2bd9e1d341e", + "html_url": "https://github.com/golang/text/commit/d5f0155fc124972d018bea023348f2bd9e1d341e" + } + ] + }, + "merge_base_commit": { + "sha": "f21a4dfb5e38f5895301dc265a8def02365cc3d0", + "node_id": "MDY6Q29tbWl0Mjc1MjIyOTU6ZjIxYTRkZmI1ZTM4ZjU4OTUzMDFkYzI2NWE4ZGVmMDIzNjVjYzNkMA==", + "commit": { + "author": { + "name": "Marcel van Lohuizen", + "email": "mpvl@golang.org", + "date": "2017-12-09T17:05:50Z" + }, + "committer": { + "name": "Marcel van Lohuizen", + "email": "mpvl@golang.org", + "date": "2017-12-14T13:08:43Z" + }, + "message": "all: upgrade to CLDR 32\n\nChange-Id: I80ba02e97f8c9a6bc364cf8679b90aee13a1ce23\nReviewed-on: https://go-review.googlesource.com/82905\nRun-TryBot: Marcel van Lohuizen \nTryBot-Result: Gobot Gobot \nReviewed-by: Nigel Tao ", + "tree": { + "sha": "d495a1fe53fe3fd1794be36b4a4c8d835254db7b", + "url": "https://api.github.com/repos/golang/text/git/trees/d495a1fe53fe3fd1794be36b4a4c8d835254db7b" + }, + "url": "https://api.github.com/repos/golang/text/git/commits/f21a4dfb5e38f5895301dc265a8def02365cc3d0", + "comment_count": 0, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null + } + }, + "url": "https://api.github.com/repos/golang/text/commits/f21a4dfb5e38f5895301dc265a8def02365cc3d0", + "html_url": "https://github.com/golang/text/commit/f21a4dfb5e38f5895301dc265a8def02365cc3d0", + "comments_url": "https://api.github.com/repos/golang/text/commits/f21a4dfb5e38f5895301dc265a8def02365cc3d0/comments", + "author": { + "login": "mpvl", + "id": 6445383, + "node_id": "MDQ6VXNlcjY0NDUzODM=", + "avatar_url": "https://avatars2.githubusercontent.com/u/6445383?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/mpvl", + "html_url": "https://github.com/mpvl", + "followers_url": "https://api.github.com/users/mpvl/followers", + "following_url": "https://api.github.com/users/mpvl/following{/other_user}", + "gists_url": "https://api.github.com/users/mpvl/gists{/gist_id}", + "starred_url": "https://api.github.com/users/mpvl/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/mpvl/subscriptions", + "organizations_url": "https://api.github.com/users/mpvl/orgs", + "repos_url": "https://api.github.com/users/mpvl/repos", + "events_url": "https://api.github.com/users/mpvl/events{/privacy}", + "received_events_url": "https://api.github.com/users/mpvl/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "mpvl", + "id": 6445383, + "node_id": "MDQ6VXNlcjY0NDUzODM=", + "avatar_url": "https://avatars2.githubusercontent.com/u/6445383?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/mpvl", + "html_url": "https://github.com/mpvl", + "followers_url": "https://api.github.com/users/mpvl/followers", + "following_url": "https://api.github.com/users/mpvl/following{/other_user}", + "gists_url": "https://api.github.com/users/mpvl/gists{/gist_id}", + "starred_url": "https://api.github.com/users/mpvl/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/mpvl/subscriptions", + "organizations_url": "https://api.github.com/users/mpvl/orgs", + "repos_url": "https://api.github.com/users/mpvl/repos", + "events_url": "https://api.github.com/users/mpvl/events{/privacy}", + "received_events_url": "https://api.github.com/users/mpvl/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "d5f0155fc124972d018bea023348f2bd9e1d341e", + "url": "https://api.github.com/repos/golang/text/commits/d5f0155fc124972d018bea023348f2bd9e1d341e", + "html_url": "https://github.com/golang/text/commit/d5f0155fc124972d018bea023348f2bd9e1d341e" + } + ] + }, + "status": "identical", + "ahead_by": 0, + "behind_by": 0, + "total_commits": 0, + "commits": [ + + ], + "files": [ + + ] +} diff --git a/spec/fixtures/github/contents_gopkg_lock.json b/spec/fixtures/github/contents_gopkg_lock.json new file mode 100644 index 00000000000..07b370ce448 --- /dev/null +++ b/spec/fixtures/github/contents_gopkg_lock.json @@ -0,0 +1,18 @@ +{ + "name": "Gopkg.lock", + "path": "Gopkg.lock", + "sha": "816ac07074ab08023f4fea593888b1f87dd774b3", + "size": 29707, + "url": "https://api.github.com/repos/cockroachdb/cockroach/contents/Gopkg.lock?ref=master", + "html_url": "https://github.com/cockroachdb/cockroach/blob/master/Gopkg.lock", + "git_url": "https://api.github.com/repos/cockroachdb/cockroach/git/blobs/816ac07074ab08023f4fea593888b1f87dd774b3", + "download_url": "https://raw.githubusercontent.com/cockroachdb/cockroach/master/Gopkg.lock", + "type": "file", + "content": "IyBUaGlzIGZpbGUgaXMgYXV0b2dlbmVyYXRlZCwgZG8gbm90IGVkaXQ7IGNo\nYW5nZXMgbWF5IGJlIHVuZG9uZSBieSB0aGUgbmV4dCAnZGVwIGVuc3VyZScu\nCgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJjbG91ZC5nb29nbGUuY29tL2dv\nIgogIHBhY2thZ2VzID0gWwogICAgImNvbXB1dGUvbWV0YWRhdGEiLAogICAg\nImlhbSIsCiAgICAiaW50ZXJuYWwiLAogICAgImludGVybmFsL29wdGlvbmFs\nIiwKICAgICJpbnRlcm5hbC90cmFjZSIsCiAgICAiaW50ZXJuYWwvdmVyc2lv\nbiIsCiAgICAic3RvcmFnZSIsCiAgXQogIHJldmlzaW9uID0gIjBmZDcyMzBi\nMmE3NTA1ODMzZDVmNjliNzVjYmQ2Yzk1ODI0MDE0NzkiCiAgdmVyc2lvbiA9\nICJ2MC4yMy4wIgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29t\nL0F6dXJlL2F6dXJlLXNkay1mb3ItZ28iCiAgcGFja2FnZXMgPSBbCiAgICAi\nc3RvcmFnZSIsCiAgICAidmVyc2lvbiIsCiAgXQogIHJldmlzaW9uID0gImU2\nN2NkMzllOTQyYzQxN2FlNWU5YWUxMTY1Zjc3OGQ5ZmU4OTk2ZTAiCiAgdmVy\nc2lvbiA9ICJ2MTQuNS4wIgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1h\nc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vQXp1cmUvZ28tYW5zaXRlcm0i\nCiAgcGFja2FnZXMgPSBbCiAgICAiLiIsCiAgICAid2ludGVybSIsCiAgXQog\nIHJldmlzaW9uID0gImQ2ZTNiMzMyOGI3ODNmMjM3MzFiYzRkMDU4ODc1YjAz\nNzFmZjgxMDkiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20v\nQXp1cmUvZ28tYXV0b3Jlc3QiCiAgcGFja2FnZXMgPSBbCiAgICAiYXV0b3Jl\nc3QiLAogICAgImF1dG9yZXN0L2FkYWwiLAogICAgImF1dG9yZXN0L2F6dXJl\nIiwKICAgICJhdXRvcmVzdC9kYXRlIiwKICBdCiAgcmV2aXNpb24gPSAiMGFl\nMzZhOWU1NDQ2OTZkZTQ2ZmRhZGI3YjBkNWZiMzhhZjQ4YzA2MyIKICB2ZXJz\naW9uID0gInYxMC4yLjAiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAicGFy\nc2UtY29uc3RyYWludHMtd2l0aC1kYXNoLWluLXByZSIKICBuYW1lID0gImdp\ndGh1Yi5jb20vTWFzdGVybWluZHMvc2VtdmVyIgogIHBhY2thZ2VzID0gWyIu\nIl0KICByZXZpc2lvbiA9ICJhOTNlNTFiNWE1N2VmNDE2ZGFjOGJiMDJkMTE0\nMDdiNmY1NWQ4OTI5IgogIHNvdXJjZSA9ICJodHRwczovL2dpdGh1Yi5jb20v\nY2Fyb2x5bnZzL3NlbXZlci5naXQiCgpbW3Byb2plY3RzXV0KICBuYW1lID0g\nImdpdGh1Yi5jb20vTWFzdGVybWluZHMvdmNzIgogIHBhY2thZ2VzID0gWyIu\nIl0KICByZXZpc2lvbiA9ICI2ZjFjNmQxNTA1MDBlNDUyNzA0ZTk4NjNmNjhj\nMjU1OWY1ODYxNmJmIgogIHZlcnNpb24gPSAidjEuMTIuMCIKCltbcHJvamVj\ndHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIuY29t\nL01pY2hhZWxUSm9uZXMvd2FsayIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2\naXNpb24gPSAiNDc0OGUyOWQ1NzE4YzJkZjQwMjhhNjU0M2VkZjg2ZmQ4Y2Mw\nZjg4MSIKCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9NaWNy\nb3NvZnQvZ28td2luaW8iCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9u\nID0gIjc4NDM5OTY2YjM4ZDY5YmYzODIyN2ZiZjU3YWM4YTZmZWU3MGY2OWEi\nCiAgdmVyc2lvbiA9ICJ2MC40LjUiCgpbW3Byb2plY3RzXV0KICBicmFuY2gg\nPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9OdnZlZW4vR290dHki\nCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gImNkNTI3Mzc0ZjFl\nNWJmZjQ5MzgyMDc2MDRhMTRmMmUzOGE5Y2Y1MTIiCgpbW3Byb2plY3RzXV0K\nICBuYW1lID0gImdpdGh1Yi5jb20vUHVlcmtpdG9CaW8vZ29xdWVyeSIKICBw\nYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiZTEyNzFlZTM0YzZhMzA1\nZTM4NTY2ZWNkMjdhZTM3NDk0NDkwN2VlOSIKICB2ZXJzaW9uID0gInYxLjEu\nMCIKCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9TaG9waWZ5\nL3NhcmFtYSIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiYmJk\nYmU2NDQwOTliN2ZkYzgzMjdkNWNjNjljMDMwOTQ1MTg4YjJlOSIKICB2ZXJz\naW9uID0gInYxLjEzLjAiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFz\ndGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9TdGFja0V4Y2hhbmdlL3dtaSIK\nICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiZWEzODNjZjNiYTZl\nYzk1MDg3NGI4NDg2Y2Q3MjM1NmQwMDdjNzY4ZiIKCltbcHJvamVjdHNdXQog\nIG5hbWUgPSAiZ2l0aHViLmNvbS9WaXZpZENvcnRleC9ld21hIgogIHBhY2th\nZ2VzID0gWyIuIl0KICByZXZpc2lvbiA9ICJiMjRlYjM0NmE5NGMzYmExMmMx\nZGExZTU2NGRiYWMxYjQ5OGE3N2NlIgogIHZlcnNpb24gPSAidjEuMS4xIgoK\nW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdp\ndGh1Yi5jb20vYWJvdXJnZXQvdGVhbWNpdHkiCiAgcGFja2FnZXMgPSBbIi4i\nXQogIHJldmlzaW9uID0gImUyNDExMDQzOTRmOTFiZjRlNjUwNDhmOWVhNWQw\nYzBmM2MyNWIzNWUiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFzdGVy\nIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9hbmR5LWtpbWJhbGwvYXJlbmFza2wi\nCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gIjIyNDc2MWU1NTJh\nZmU2NGRiOWQ5MzAwNGY4ZDVkM2E2ODZiODk3NzEiCgpbW3Byb2plY3RzXV0K\nICBicmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9hbmR5\nYmFsaG9sbS9jYXNjYWRpYSIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNp\nb24gPSAiMzQ5ZGQwMjA5NDcwZWFiZDk1MTQyNDJjNjg4YzQwM2MwOTI2ZDI2\nNiIKCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9hcGFjaGUv\ndGhyaWZ0IgogIHBhY2thZ2VzID0gWyJsaWIvZ28vdGhyaWZ0Il0KICByZXZp\nc2lvbiA9ICIzMjdlYmI2YzJiNmRmOGJmMDc1ZGEwMmVmNDVhMmEwMzRlOWI3\nOWJhIgogIHZlcnNpb24gPSAiMC4xMS4wIgoKW1twcm9qZWN0c11dCiAgYnJh\nbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vYXJtb24vZ28t\ncmFkaXgiCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gIjFmY2Ex\nNDVkZmZiY2FhOGZlOTE0MzA5YjFlYzBjZmM2NzUwMGZlNjEiCgpbW3Byb2pl\nY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20vYXdzL2F3cy1zZGstZ28iCiAg\ncGFja2FnZXMgPSBbCiAgICAiYXdzIiwKICAgICJhd3MvYXdzZXJyIiwKICAg\nICJhd3MvYXdzdXRpbCIsCiAgICAiYXdzL2NsaWVudCIsCiAgICAiYXdzL2Ns\naWVudC9tZXRhZGF0YSIsCiAgICAiYXdzL2NvcmVoYW5kbGVycyIsCiAgICAi\nYXdzL2NyZWRlbnRpYWxzIiwKICAgICJhd3MvY3JlZGVudGlhbHMvZWMycm9s\nZWNyZWRzIiwKICAgICJhd3MvY3JlZGVudGlhbHMvZW5kcG9pbnRjcmVkcyIs\nCiAgICAiYXdzL2NyZWRlbnRpYWxzL3N0c2NyZWRzIiwKICAgICJhd3MvZGVm\nYXVsdHMiLAogICAgImF3cy9lYzJtZXRhZGF0YSIsCiAgICAiYXdzL2VuZHBv\naW50cyIsCiAgICAiYXdzL3JlcXVlc3QiLAogICAgImF3cy9zZXNzaW9uIiwK\nICAgICJhd3Mvc2lnbmVyL3Y0IiwKICAgICJpbnRlcm5hbC9zaGFyZWRkZWZh\ndWx0cyIsCiAgICAicHJpdmF0ZS9wcm90b2NvbCIsCiAgICAicHJpdmF0ZS9w\ncm90b2NvbC9xdWVyeSIsCiAgICAicHJpdmF0ZS9wcm90b2NvbC9xdWVyeS9x\ndWVyeXV0aWwiLAogICAgInByaXZhdGUvcHJvdG9jb2wvcmVzdCIsCiAgICAi\ncHJpdmF0ZS9wcm90b2NvbC9yZXN0eG1sIiwKICAgICJwcml2YXRlL3Byb3Rv\nY29sL3htbC94bWx1dGlsIiwKICAgICJzZXJ2aWNlL3MzIiwKICAgICJzZXJ2\naWNlL3MzL3MzaWZhY2UiLAogICAgInNlcnZpY2UvczMvczNtYW5hZ2VyIiwK\nICAgICJzZXJ2aWNlL3N0cyIsCiAgXQogIHJldmlzaW9uID0gImVlMWYxNzk4\nNzdiMmRhZjJhYWFiZjcxZmE5MDA3NzNiZjg4NDIyNTMiCiAgdmVyc2lvbiA9\nICJ2MS4xMi4xOSIKCltbcHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIi\nCiAgbmFtZSA9ICJnaXRodWIuY29tL2F4aW9taHEvaHlwZXJsb2dsb2ciCiAg\ncGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gImJhYmE4MDBiZTA5OGQ5\nZjQzMDMzNTJmYTYyMTRhOTMzZTM3MWUzZGEiCgpbW3Byb2plY3RzXV0KICBi\ncmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9iYWNrdHJh\nY2UtbGFicy9nby1iY2QiCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9u\nID0gIjVkOGUwMWIyZjA0Mzg5MjIyODkyMzhmZDNiYTA0Mzc2MWRhZjExMDIi\nCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAi\nZ2l0aHViLmNvbS9iZW5lc2NoL2Nnb3N5bWJvbGl6ZXIiCiAgcGFja2FnZXMg\nPSBbIi4iXQogIHJldmlzaW9uID0gIjcwZTFlZTJiMzlkM2I2MTZhNmFiOTk5\nNjgyMGRkZTIyNGMyN2YzNTEiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAi\nbWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9iZW9ybjcvcGVya3MiCiAg\ncGFja2FnZXMgPSBbInF1YW50aWxlIl0KICByZXZpc2lvbiA9ICIzYTc3MWQ5\nOTI5NzNmMjRhYTcyNWQwNzg2OGI0NjdkMWRkZmNlYWZiIgoKW1twcm9qZWN0\nc11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20v\nYmlvZ28vc3RvcmUiCiAgcGFja2FnZXMgPSBbImxscmIiXQogIHJldmlzaW9u\nID0gIjkxMzQyN2ExZDVlODk2MDRlNTBlYTFkYjBmMjhmMzQ5NjZkNjE2MDIi\nCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20vYm9sdGRiL2Jv\nbHQiCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gIjJmMWNlN2E4\nMzdkY2I4ZGEzZWM1OTViMWRhYzlkMDYzMmYwZjk5ZTgiCiAgdmVyc2lvbiA9\nICJ2MS4zLjEiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20v\nY2Vuay9iYWNrb2ZmIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZpc2lvbiA9\nICI2MTE1M2M3NjhmMzFlZTVmMTMwMDcxZDA4ZmM4MmI4NTIwODUyOGRlIgog\nIHZlcnNpb24gPSAidjEuMS4wIgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJn\naXRodWIuY29tL2NlcnRpZmkvZ29jZXJ0aWZpIgogIHBhY2thZ2VzID0gWyIu\nIl0KICByZXZpc2lvbiA9ICIzZmQ5ZTFhZGIxMmI3MmQyZjNmODIxOTFkNDli\nZTliOTNjNjlmNjdjIgogIHZlcnNpb24gPSAiMjAxNy4wNy4yNyIKCltbcHJv\namVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9jbGllbnQ5L21pc3NwZWxs\nIgogIHBhY2thZ2VzID0gWwogICAgIi4iLAogICAgImNtZC9taXNzcGVsbCIs\nCiAgXQogIHJldmlzaW9uID0gIjU5ODk0YWJkZTkzMWEzMjYzMGQ0ZTg4NGEw\nOWM2ODJlZDIwYzVjN2MiCiAgdmVyc2lvbiA9ICJ2MC4zLjAiCgpbW3Byb2pl\nY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20vY29ja3JvYWNoZGIvYXBkIgog\nIHBhY2thZ2VzID0gWyIuIl0KICByZXZpc2lvbiA9ICJiMWNlNDljYjJhNDc0\nZjQ0MTY1MzFlNzM5NTM3M2VhYWZhYTRmYmUyIgogIHZlcnNpb24gPSAidjEu\nMC4wIgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1l\nID0gImdpdGh1Yi5jb20vY29ja3JvYWNoZGIvY211eCIKICBwYWNrYWdlcyA9\nIFsiLiJdCiAgcmV2aXNpb24gPSAiMzBkMTBiZTQ5MjkyN2UyZGNhZTAwODlj\nMzc0YzQ1NWQ0MjQxNGZjYiIKCltbcHJvamVjdHNdXQogIGJyYW5jaCA9ICJt\nYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIuY29tL2NvY2tyb2FjaGRiL2NvY2ty\nb2FjaC1nbyIKICBwYWNrYWdlcyA9IFsiY3JkYiJdCiAgcmV2aXNpb24gPSAi\nNTljMDU2MDQ3OGI3MDViZjliZDEyZjkyNTIyMjRhMGZhZDdjODdkZiIKCltb\ncHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRo\ndWIuY29tL2NvY2tyb2FjaGRiL2NybGZtdCIKICBwYWNrYWdlcyA9IFsiLiJd\nCiAgcmV2aXNpb24gPSAiNTg5NTYwN2U1ZWE3OTBmY2JiNjQwMjYwMTI5YTEy\nZDI3N2IzNGU0NiIKCltbcHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIi\nCiAgbmFtZSA9ICJnaXRodWIuY29tL2NvY2tyb2FjaGRiL3JldHVybmNoZWNr\nIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZpc2lvbiA9ICJlOTFiYjI4YmFm\nOWRlNGE1MzBkM2FlN2YwNDE5NTNiMjNkY2NlOWJlIgoKW1twcm9qZWN0c11d\nCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vY29j\na3JvYWNoZGIvc3RyZXNzIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZpc2lv\nbiA9ICIyOWI1ZDMxYjRjM2E5NDljYjNhNzI2NzUwYmMzNGM0ZDU4ZWMxNWU4\nIgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0g\nImdpdGh1Yi5jb20vY29ja3JvYWNoZGIvdHR5Y29sb3IiCiAgcGFja2FnZXMg\nPSBbIi4iXQogIHJldmlzaW9uID0gIjViZWQyYjVhODc1Yzg4YTlkODdkMGYx\nMmIyMWJhMTU2ZTJmOTk1ZjciCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAi\nbWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9jb2RhaGFsZS9oZHJoaXN0\nb2dyYW0iCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gIjNhMGJi\nNzc0MjliZDNhNjE1OTZmNWU4YTMxNzI0NDU4NDQzNDIxMjAiCgpbW3Byb2pl\nY3RzXV0KICBicmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNv\nbS9jb3Jlb3MvZXRjZCIKICBwYWNrYWdlcyA9IFsKICAgICJyYWZ0IiwKICAg\nICJyYWZ0L3JhZnRwYiIsCiAgXQogIHJldmlzaW9uID0gImNlMGFkMzc3ZDIx\nODE5NTkyYzNkOGMyOTQxN2Q5ZDdhNWFjNTNmMmYiCgpbW3Byb2plY3RzXV0K\nICBuYW1lID0gImdpdGh1Yi5jb20vY3B1Z3V5ODMvZ28tbWQybWFuIgogIHBh\nY2thZ2VzID0gWyJtZDJtYW4iXQogIHJldmlzaW9uID0gIjFkOTAzZGNiNzQ5\nOTkyZjM3NDFkNzQ0YzBmODM3NmI0YmQ3ZWIzZTEiCiAgdmVyc2lvbiA9ICJ2\nMS4wLjciCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20vZGF2\nZWNnaC9nby1zcGV3IgogIHBhY2thZ2VzID0gWyJzcGV3Il0KICByZXZpc2lv\nbiA9ICIzNDY5MzhkNjQyZjJlYzM1OTRlZDgxZDg3NDQ2MTk2MWNkMGZhYTc2\nIgogIHZlcnNpb24gPSAidjEuMS4wIgoKW1twcm9qZWN0c11dCiAgbmFtZSA9\nICJnaXRodWIuY29tL2RncmlqYWx2YS9qd3QtZ28iCiAgcGFja2FnZXMgPSBb\nIi4iXQogIHJldmlzaW9uID0gImRiZWFhOTMzMmYxOWE5NDRhY2I1NzM2YjQ0\nNTZjZmNjMDIxNDBlMjkiCiAgdmVyc2lvbiA9ICJ2My4xLjAiCgpbW3Byb2pl\nY3RzXV0KICBicmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNv\nbS9kZ3J5c2tpL2dvLW1ldHJvIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZp\nc2lvbiA9ICIyODBmNjA2MmI1YmM5N2VlOWI5YWZlN2YyY2NiMzYxZTU5ODQ1\nYmFhIgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1l\nID0gImdpdGh1Yi5jb20vZG9ja2VyL2Rpc3RyaWJ1dGlvbiIKICBwYWNrYWdl\ncyA9IFsKICAgICJkaWdlc3RzZXQiLAogICAgInJlZmVyZW5jZSIsCiAgXQog\nIHJldmlzaW9uID0gIjM4MDAwNTZiODgzMmNmNjA3NWU3OGIyODJhYzAxMDEz\nMWQ4Njg3YmMiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFzdGVyIgog\nIG5hbWUgPSAiZ2l0aHViLmNvbS9kb2NrZXIvZG9ja2VyIgogIHBhY2thZ2Vz\nID0gWwogICAgImFwaSIsCiAgICAiYXBpL3R5cGVzIiwKICAgICJhcGkvdHlw\nZXMvYmxraW9kZXYiLAogICAgImFwaS90eXBlcy9jb250YWluZXIiLAogICAg\nImFwaS90eXBlcy9ldmVudHMiLAogICAgImFwaS90eXBlcy9maWx0ZXJzIiwK\nICAgICJhcGkvdHlwZXMvaW1hZ2UiLAogICAgImFwaS90eXBlcy9tb3VudCIs\nCiAgICAiYXBpL3R5cGVzL25ldHdvcmsiLAogICAgImFwaS90eXBlcy9yZWdp\nc3RyeSIsCiAgICAiYXBpL3R5cGVzL3N0cnNsaWNlIiwKICAgICJhcGkvdHlw\nZXMvc3dhcm0iLAogICAgImFwaS90eXBlcy9zd2FybS9ydW50aW1lIiwKICAg\nICJhcGkvdHlwZXMvdGltZSIsCiAgICAiYXBpL3R5cGVzL3ZlcnNpb25zIiwK\nICAgICJhcGkvdHlwZXMvdm9sdW1lIiwKICAgICJjbGllbnQiLAogICAgInBr\nZy9qc29ubWVzc2FnZSIsCiAgICAicGtnL3N0ZGNvcHkiLAogICAgInBrZy90\nZXJtIiwKICAgICJwa2cvdGVybS93aW5kb3dzIiwKICBdCiAgcmV2aXNpb24g\nPSAiM2FiMjBhODdmYTEwMzYwZGY4OTFhNjdiODMwNzM5OWNkZjFhYjQyOSIK\nCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9kb2NrZXIvZ28t\nY29ubmVjdGlvbnMiCiAgcGFja2FnZXMgPSBbCiAgICAibmF0IiwKICAgICJz\nb2NrZXRzIiwKICAgICJ0bHNjb25maWciLAogIF0KICByZXZpc2lvbiA9ICIz\nZWRlMzJlMjAzM2RlNzUwNWU2NTAwZDZjODY4YzJiOWVkOWYxNjlkIgogIHZl\ncnNpb24gPSAidjAuMy4wIgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRo\ndWIuY29tL2RvY2tlci9nby11bml0cyIKICBwYWNrYWdlcyA9IFsiLiJdCiAg\ncmV2aXNpb24gPSAiMGRhZGJiMDM0NWIzNWVjN2VmMzVlMjI4ZGFiYjhkZTg5\nYTY1YmY1MiIKICB2ZXJzaW9uID0gInYwLjMuMiIKCltbcHJvamVjdHNdXQog\nIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIuY29tL2R1c3Rp\nbi9nby1odW1hbml6ZSIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24g\nPSAiNzdlZDgwNzgzMGI0ZGY1ODE0MTdlN2Y4OWViODFkNDg3MjgzMmI3MiIK\nCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9lYXBhY2hlL2dv\nLXJlc2lsaWVuY3kiCiAgcGFja2FnZXMgPSBbImJyZWFrZXIiXQogIHJldmlz\naW9uID0gIjY4MDA0ODJmMmM4MTNlNjg5Yzg4YjdlZDMyODIyNjIzODUwMTE4\nOTAiCiAgdmVyc2lvbiA9ICJ2MS4wLjAiCgpbW3Byb2plY3RzXV0KICBicmFu\nY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9lYXBhY2hlL2dv\nLXhlcmlhbC1zbmFwcHkiCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9u\nID0gImJiOTU1ZTAxYjkzNDZhYzE5ZGMyOWViMTY1ODZjOTBkZWQ5OWE5OGMi\nCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20vZWFwYWNoZS9x\ndWV1ZSIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiZGVkNTk1\nOWMwZDRlMzYwNjQ2ZGM5ZTk5MDhjZmY0ODY2Njc4MTM2NyIKICB2ZXJzaW9u\nID0gInYxLjAuMiIKCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNv\nbS9lbGFzdGljL2dvc2lnYXIiCiAgcGFja2FnZXMgPSBbCiAgICAiLiIsCiAg\nICAic3lzL3dpbmRvd3MiLAogIF0KICByZXZpc2lvbiA9ICIzMDZkNTE5ODE3\nODljY2M2NWU1ZjE0MzFkNWMwZDc4ZDhjMzY4ZjFiIgogIHZlcnNpb24gPSAi\ndjAuNS4wIgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29tL2Vs\nYXphcmwvZ28tYmluZGF0YS1hc3NldGZzIgogIHBhY2thZ2VzID0gWyIuIl0K\nICByZXZpc2lvbiA9ICIzMGY4MmZhMjNmZDg0NGJkNWJiMWU1ZjIxNmRiODdm\nZDc3YjVlYjQzIgogIHZlcnNpb24gPSAidjEuMC4wIgoKW1twcm9qZWN0c11d\nCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vZmFj\nZWJvb2tnby9jbG9jayIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24g\nPSAiNjAwZDg5OGFmNDBhYTA5YTdhOTNlY2I5MjY1ZDg3YjA1MDRiNmYwMyIK\nCltbcHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJn\naXRodWIuY29tL2dldHNlbnRyeS9yYXZlbi1nbyIKICBwYWNrYWdlcyA9IFsi\nLiJdCiAgcmV2aXNpb24gPSAiMjIxYjJiNDRmYjMzZjg0ZWQzZWExM2YzYWVk\nNjJmZjQ4Yzg1NjM2YiIKICBzb3VyY2UgPSAiaHR0cHM6Ly9naXRodWIuY29t\nL2NvY2tyb2FjaGRiL3JhdmVuLWdvIgoKW1twcm9qZWN0c11dCiAgYnJhbmNo\nID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vZ2hlbWF3YXQvc3Ry\nZWFtIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZpc2lvbiA9ICI3OGU2ODJh\nYmNhZTRmOTZhYzdkZGJlMzk5MTI5NjdhNWY3Y2JiYWE2IgoKW1twcm9qZWN0\nc11dCiAgbmFtZSA9ICJnaXRodWIuY29tL2dvLWluaS9pbmkiCiAgcGFja2Fn\nZXMgPSBbIi4iXQogIHJldmlzaW9uID0gImYyODBiM2JhNTE3YmY1ZmM5ODky\nMjYyNGYyMWZiMGU3YTkyYWRhZWMiCiAgdmVyc2lvbiA9ICJ2MS4zMC4zIgoK\nW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29tL2dvLWxvZ2ZtdC9s\nb2dmbXQiCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gIjM5MGFi\nNzkzNWVlMjhlYzZiMjg2MzY0YmJhOWI0ZGQ2NDEwY2IzZDUiCiAgdmVyc2lv\nbiA9ICJ2MC4zLjAiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1Yi5j\nb20vZ28tb2xlL2dvLW9sZSIKICBwYWNrYWdlcyA9IFsKICAgICIuIiwKICAg\nICJvbGV1dGlsIiwKICBdCiAgcmV2aXNpb24gPSAiYTQxZTNjNGI3MDZmNmFl\nOGRmYmZmMzQyYjA2ZTQwZmE0ZDJkMDUwNiIKICB2ZXJzaW9uID0gInYxLjIu\nMSIKCltbcHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9\nICJnaXRodWIuY29tL2dvLXNxbC1kcml2ZXIvbXlzcWwiCiAgcGFja2FnZXMg\nPSBbIi4iXQogIHJldmlzaW9uID0gImZhZGUyMTAwOTc5NzE1OGU3Yjc5ZTA0\nYzM0MDExOGE5MjIwYzZmOWUiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAi\ndjIiCiAgbmFtZSA9ICJnaXRodWIuY29tL2dvLXlhbWwveWFtbCIKICBwYWNr\nYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiZWIzNzMzZDE2MGU3NGE5Yzdl\nNDQyZjQzNWViM2JlYTQ1OGUxZDE5ZiIKCltbcHJvamVjdHNdXQogIG5hbWUg\nPSAiZ2l0aHViLmNvbS9nb2dvL3Byb3RvYnVmIgogIHBhY2thZ2VzID0gWwog\nICAgImdvZ29wcm90byIsCiAgICAianNvbnBiIiwKICAgICJwbHVnaW4vY29t\ncGFyZSIsCiAgICAicGx1Z2luL2RlZmF1bHRjaGVjayIsCiAgICAicGx1Z2lu\nL2Rlc2NyaXB0aW9uIiwKICAgICJwbHVnaW4vZW1iZWRjaGVjayIsCiAgICAi\ncGx1Z2luL2VudW1zdHJpbmdlciIsCiAgICAicGx1Z2luL2VxdWFsIiwKICAg\nICJwbHVnaW4vZmFjZSIsCiAgICAicGx1Z2luL2dvc3RyaW5nIiwKICAgICJw\nbHVnaW4vbWFyc2hhbHRvIiwKICAgICJwbHVnaW4vb25lb2ZjaGVjayIsCiAg\nICAicGx1Z2luL3BvcHVsYXRlIiwKICAgICJwbHVnaW4vc2l6ZSIsCiAgICAi\ncGx1Z2luL3N0cmluZ2VyIiwKICAgICJwbHVnaW4vdGVzdGdlbiIsCiAgICAi\ncGx1Z2luL3VuaW9uIiwKICAgICJwbHVnaW4vdW5tYXJzaGFsIiwKICAgICJw\ncm90byIsCiAgICAicHJvdG9jLWdlbi1nb2dvL2Rlc2NyaXB0b3IiLAogICAg\nInByb3RvYy1nZW4tZ29nby9nZW5lcmF0b3IiLAogICAgInByb3RvYy1nZW4t\nZ29nby9ncnBjIiwKICAgICJwcm90b2MtZ2VuLWdvZ28vcGx1Z2luIiwKICAg\nICJzb3J0a2V5cyIsCiAgICAidHlwZXMiLAogICAgInZhbml0eSIsCiAgICAi\ndmFuaXR5L2NvbW1hbmQiLAogIF0KICByZXZpc2lvbiA9ICIxYWRmYzEyNmI0\nMTUxM2NjNjk2YjIwOTY2N2M4NjU2ZWE3YWFjNjdjIgogIHZlcnNpb24gPSAi\ndjEuMC4wIgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBu\nYW1lID0gImdpdGh1Yi5jb20vZ29sYW5nLWNvbW1vbm1hcmsvbWFya2Rvd24i\nCiAgcGFja2FnZXMgPSBbCiAgICAiLiIsCiAgICAiYnl0ZXV0aWwiLAogICAg\nImh0bWwiLAogICAgImxpbmtpZnkiLAogIF0KICByZXZpc2lvbiA9ICIxMWE3\nYTgzOWU3MjNhYTI5M2NjY2RjMzUzYjM5NGRiZmNlN2MxMzFlIgoKW1twcm9q\nZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29tL2dvbGFuZy9kZXAiCiAgcGFj\na2FnZXMgPSBbCiAgICAiLiIsCiAgICAiY21kL2RlcCIsCiAgICAiZ3BzIiwK\nICAgICJncHMvaW50ZXJuYWwvcGIiLAogICAgImdwcy9wYXRocyIsCiAgICAi\nZ3BzL3BrZ3RyZWUiLAogICAgImludGVybmFsL2ZlZWRiYWNrIiwKICAgICJp\nbnRlcm5hbC9mcyIsCiAgICAiaW50ZXJuYWwvaW1wb3J0ZXJzIiwKICAgICJp\nbnRlcm5hbC9pbXBvcnRlcnMvYmFzZSIsCiAgICAiaW50ZXJuYWwvaW1wb3J0\nZXJzL2dsaWRlIiwKICAgICJpbnRlcm5hbC9pbXBvcnRlcnMvZ2xvY2siLAog\nICAgImludGVybmFsL2ltcG9ydGVycy9nb2RlcCIsCiAgICAiaW50ZXJuYWwv\naW1wb3J0ZXJzL2dvdmVuZCIsCiAgICAiaW50ZXJuYWwvaW1wb3J0ZXJzL2dv\ndmVuZG9yIiwKICAgICJpbnRlcm5hbC9pbXBvcnRlcnMvZ3Z0IiwKICAgICJp\nbnRlcm5hbC9pbXBvcnRlcnMvdm5kciIsCiAgXQogIHJldmlzaW9uID0gIjM3\nZDllYTBhYzE2ZjBlMGEwNWFmYzNiNjBlMWFjOGMzNjRiNmMzMjkiCiAgdmVy\nc2lvbiA9ICJ2MC40LjEiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFz\ndGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9nb2xhbmcvZ2xvZyIKICBwYWNr\nYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiMjNkZWY0ZTZjMTRiNGRhOGFj\nMmVkODAwNzMzN2JjNWViNTAwNzk5OCIKCltbcHJvamVjdHNdXQogIGJyYW5j\naCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIuY29tL2dvbGFuZy9sZXZl\nbGRiIgogIHBhY2thZ2VzID0gWwogICAgImNyYyIsCiAgICAiZGIiLAogICAg\nIm1lbWZzIiwKICAgICJ0YWJsZSIsCiAgXQogIHJldmlzaW9uID0gIjI1OWQ5\nMjUzZDcxOTk2Yjc3NzhhM2VmYjQxNDRmZTQ4OTIzNDJiMTgiCgpbW3Byb2pl\nY3RzXV0KICBicmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNv\nbS9nb2xhbmcvbGludCIKICBwYWNrYWdlcyA9IFsKICAgICIuIiwKICAgICJn\nb2xpbnQiLAogIF0KICByZXZpc2lvbiA9ICI2YWFmN2MzNGFmMGY0YzM2YTU3\nZTBjNDI5YmFjZTRkNzA2ZDhlOTMxIgoKW1twcm9qZWN0c11dCiAgYnJhbmNo\nID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vZ29sYW5nL3Byb3Rv\nYnVmIgogIHBhY2thZ2VzID0gWwogICAgImpzb25wYiIsCiAgICAicHJvdG8i\nLAogICAgInByb3RvYy1nZW4tZ28vZGVzY3JpcHRvciIsCiAgICAicHJvdG9j\nLWdlbi1nby9nZW5lcmF0b3IiLAogICAgInByb3RvYy1nZW4tZ28vZ2VuZXJh\ndG9yL2ludGVybmFsL3JlbWFwIiwKICAgICJwcm90b2MtZ2VuLWdvL3BsdWdp\nbiIsCiAgICAicHR5cGVzIiwKICAgICJwdHlwZXMvYW55IiwKICAgICJwdHlw\nZXMvZHVyYXRpb24iLAogICAgInB0eXBlcy9zdHJ1Y3QiLAogICAgInB0eXBl\ncy90aW1lc3RhbXAiLAogIF0KICByZXZpc2lvbiA9ICJiNGRlZGEwOTczZmI0\nYzcwYjUwZDIyNmIxYWY0OWYzZGE1OWY1MjY1IgoKW1twcm9qZWN0c11dCiAg\nYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vZ29sYW5n\nL3NuYXBweSIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiNTUz\nYTY0MTQ3MDQ5NmIyMzI3YWJjYWMxMGIzNjM5NmJkOThlNDVjOSIKCltbcHJv\namVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIu\nY29tL2dvb2dsZS9idHJlZSIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNp\nb24gPSAiZTg5MzczZmU2YjRhNzQxM2Q3YWNkNmRhMTcyNWI4M2VmNzEzZTZl\nNCIKCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9nb29nbGUv\nZ28tZ2l0aHViIgogIHBhY2thZ2VzID0gWyJnaXRodWIiXQogIHJldmlzaW9u\nID0gImU0ODA2MGEyOGZhYzUyZDBmMWNiNzU4YmM4Yjg3YzA3YmFjNGE4N2Qi\nCiAgdmVyc2lvbiA9ICJ2MTUuMC4wIgoKW1twcm9qZWN0c11dCiAgYnJhbmNo\nID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vZ29vZ2xlL2dvLXF1\nZXJ5c3RyaW5nIgogIHBhY2thZ2VzID0gWyJxdWVyeSJdCiAgcmV2aXNpb24g\nPSAiNTNlNmNlMTE2MTM1YjgwZDAzNzkyMWE3ZmRkNTEzOGNmMzJkN2E4YSIK\nCltbcHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJn\naXRodWIuY29tL2dvb2dsZS9wcHJvZiIKICBwYWNrYWdlcyA9IFsKICAgICIu\nIiwKICAgICJkcml2ZXIiLAogICAgImludGVybmFsL2JpbnV0aWxzIiwKICAg\nICJpbnRlcm5hbC9kcml2ZXIiLAogICAgImludGVybmFsL2VsZmV4ZWMiLAog\nICAgImludGVybmFsL2dyYXBoIiwKICAgICJpbnRlcm5hbC9tZWFzdXJlbWVu\ndCIsCiAgICAiaW50ZXJuYWwvcGx1Z2luIiwKICAgICJpbnRlcm5hbC9yZXBv\ncnQiLAogICAgImludGVybmFsL3N5bWJvbGl6ZXIiLAogICAgImludGVybmFs\nL3N5bWJvbHoiLAogICAgInByb2ZpbGUiLAogICAgInRoaXJkX3BhcnR5L2Qz\nIiwKICAgICJ0aGlyZF9wYXJ0eS9kM2ZsYW1lZ3JhcGgiLAogICAgInRoaXJk\nX3BhcnR5L2QzdGlwIiwKICAgICJ0aGlyZF9wYXJ0eS9zdmdwYW4iLAogIF0K\nICByZXZpc2lvbiA9ICI2MDg0MDg5OTYzOGJmYWYzZmQ2ZjJiMTdiOTc4NWYx\nZGFjNjdhNGE0IgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29t\nL2dvb2dsZWFwaXMvZ2F4LWdvIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZp\nc2lvbiA9ICIzMTdlMDAwNjI1NGM0NGEwYWM0MjdjYzUyYTBlMDgzZmYwYjk2\nMjJmIgogIHZlcnNpb24gPSAidjIuMC4wIgoKW1twcm9qZWN0c11dCiAgbmFt\nZSA9ICJnaXRodWIuY29tL2dvcmlsbGEvd2Vic29ja2V0IgogIHBhY2thZ2Vz\nID0gWyIuIl0KICByZXZpc2lvbiA9ICJlYTRkMWY2ODFiYWJiY2U5NTQ1Yzlj\nNWYzZDUxOTRhNzg5Yzg5ZjViIgogIHZlcnNpb24gPSAidjEuMi4wIgoKW1tw\ncm9qZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29tL2dycGMtZWNvc3lzdGVt\nL2dycGMtZ2F0ZXdheSIKICBwYWNrYWdlcyA9IFsKICAgICJwcm90b2MtZ2Vu\nLWdycGMtZ2F0ZXdheSIsCiAgICAicHJvdG9jLWdlbi1ncnBjLWdhdGV3YXkv\nZGVzY3JpcHRvciIsCiAgICAicHJvdG9jLWdlbi1ncnBjLWdhdGV3YXkvZ2Vu\nZXJhdG9yIiwKICAgICJwcm90b2MtZ2VuLWdycGMtZ2F0ZXdheS9nZW5nYXRl\nd2F5IiwKICAgICJwcm90b2MtZ2VuLWdycGMtZ2F0ZXdheS9odHRwcnVsZSIs\nCiAgICAicnVudGltZSIsCiAgICAicnVudGltZS9pbnRlcm5hbCIsCiAgICAi\ndXRpbGl0aWVzIiwKICBdCiAgcmV2aXNpb24gPSAiMDdmNWU3OTc2ODAyMmY5\nYTMyNjUyMzVmMGRiNGFjOGMzZjY3NWZlYyIKICB2ZXJzaW9uID0gInYxLjMu\nMSIKCltbcHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9\nICJnaXRodWIuY29tL2dycGMtZWNvc3lzdGVtL2dycGMtb3BlbnRyYWNpbmci\nCiAgcGFja2FnZXMgPSBbImdvL290Z3JwYyJdCiAgcmV2aXNpb24gPSAiYTU3\nMGFmMzk3MDRiOWYzZDRiYjUzMGQ4MzE5MmE5OWVhNjMzN2Q1YSIKCltbcHJv\namVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIu\nY29tL2hhc2hpY29ycC9nby12ZXJzaW9uIgogIHBhY2thZ2VzID0gWyIuIl0K\nICByZXZpc2lvbiA9ICJmYzYxMzg5ZTI3YzcxZDEyMGY4NzAzMWNhOGM4OGEz\nNDI4ZjM3MmRkIgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIK\nICBuYW1lID0gImdpdGh1Yi5jb20vaWFubGFuY2V0YXlsb3IvY2dvc3ltYm9s\naXplciIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiZjUwNzJk\nZjljNTUwZGM2ODcxNTdlNWQ3ZWZiNTA4MjVjZGY4ZjBlYiIKCltbcHJvamVj\ndHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIuY29t\nL2lhbmxhbmNldGF5bG9yL2RlbWFuZ2xlIgogIHBhY2thZ2VzID0gWyIuIl0K\nICByZXZpc2lvbiA9ICI0ODgzMjI3ZjY2MzcxZTAyYzQ5NDg5MzdkM2UyYmUx\nNjY0ZDliZTM4IgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29t\nL2luY29uc2hyZXZlYWJsZS9tb3VzZXRyYXAiCiAgcGFja2FnZXMgPSBbIi4i\nXQogIHJldmlzaW9uID0gIjc2NjI2YWU5YzkxYzRmMmExMGYzNGNhZDhjZTgz\nZWE0MmM5M2JiNzUiCiAgdmVyc2lvbiA9ICJ2MS4wIgoKW1twcm9qZWN0c11d\nCiAgbmFtZSA9ICJnaXRodWIuY29tL2phY2tjL3BneCIKICBwYWNrYWdlcyA9\nIFsKICAgICIuIiwKICAgICJjaHVua3JlYWRlciIsCiAgICAiaW50ZXJuYWwv\nc2FuaXRpemUiLAogICAgInBnaW8iLAogICAgInBncHJvdG8zIiwKICAgICJw\nZ3R5cGUiLAogIF0KICByZXZpc2lvbiA9ICJkYTMyMzFiMGI2NmUyZTc0Y2Ri\nNzc5ZjFkNDZjNWU5NThiYThiZTI3IgogIHZlcnNpb24gPSAidjMuMS4wIgoK\nW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29tL2ptYW5rODgvbnV0\ncyIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiOGIyODE0NWRm\nZmM4NzEwNGU2NmQwNzRmNjJlYTgwODBlZGZhZDdjOCIKICB2ZXJzaW9uID0g\nInYwLjMuMCIKCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9q\nbWVzcGF0aC9nby1qbWVzcGF0aCIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2\naXNpb24gPSAiMGIxMmQ2YjUiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAi\nbWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9qdGVldXdlbi9nby1iaW5k\nYXRhIgogIHBhY2thZ2VzID0gWwogICAgIi4iLAogICAgImdvLWJpbmRhdGEi\nLAogIF0KICByZXZpc2lvbiA9ICI2YjY2N2Y4NTE5NmU4MGQ4NDIwZDYzNGNh\nM2ZlY2NhMzg5YTUzMjA3IgogIHNvdXJjZSA9ICJodHRwczovL2dpdGh1Yi5j\nb20vZGltMTMvZ28tYmluZGF0YSIKCltbcHJvamVjdHNdXQogIGJyYW5jaCA9\nICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIuY29tL2tpc2llbGsvZXJyY2hl\nY2siCiAgcGFja2FnZXMgPSBbCiAgICAiLiIsCiAgICAiaW50ZXJuYWwvZXJy\nY2hlY2siLAogIF0KICByZXZpc2lvbiA9ICJiMTQ0NWE5ZGQ4Mjg1YTUwYzZk\nMTY2MWQxNmYwYTljZWIwODEyNWY3IgoKW1twcm9qZWN0c11dCiAgYnJhbmNo\nID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20va2lzaWVsay9nb3Rv\nb2wiCiAgcGFja2FnZXMgPSBbCiAgICAiLiIsCiAgICAiaW50ZXJuYWwvbG9h\nZCIsCiAgXQogIHJldmlzaW9uID0gImQ2Y2U2MjYyZDg3ZTNhNGUxNTNlODYw\nMjNmZjU2YWU3NzE1NTRhNDEiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdp\ndGh1Yi5jb20va256L2dvLWxpYmVkaXQiCiAgcGFja2FnZXMgPSBbCiAgICAi\nLiIsCiAgICAiY29tbW9uIiwKICAgICJvdGhlciIsCiAgICAidW5peCIsCiAg\nICAidW5peC9zaWd0cmFtcCIsCiAgXQogIHJldmlzaW9uID0gIjY5Yjc1OWQ2\nZmY4NGRmNmJiZDM5ODQ2ZGFlMzY3MDYyNWNjMDM2MWIiCiAgdmVyc2lvbiA9\nICJ2MS43IgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBu\nYW1lID0gImdpdGh1Yi5jb20va256L3N0cnRpbWUiCiAgcGFja2FnZXMgPSBb\nIi4iXQogIHJldmlzaW9uID0gIjgxMzcyNWE3YzE4M2FjMzA0ZDFlZDhmYjdl\nMzdhNTY3NzMzZTljMDUiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFz\ndGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9rci9sb2dmbXQiCiAgcGFja2Fn\nZXMgPSBbIi4iXQogIHJldmlzaW9uID0gImI4NGUzMGFjZDUxNWFhZGM0Yjc4\nM2FkNGZmODNhZmYzMjk5YmRmZTAiCgpbW3Byb2plY3RzXV0KICBicmFuY2gg\nPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9rci9wcmV0dHkiCiAg\ncGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gImNmYjU1YWFmZGFmM2Vj\nMDhmMGRiMjI2OTlhYjgyMmM1MDA5MWIxYzQiCgpbW3Byb2plY3RzXV0KICBi\ncmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9rci90ZXh0\nIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZpc2lvbiA9ICI3Y2FmY2Q4Mzc4\nNDRlNzg0YjUyNjM2OWM5YmNlMjYyODA0YWViYzYwIgoKW1twcm9qZWN0c11d\nCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vbGli\nL3BxIgogIHBhY2thZ2VzID0gWwogICAgIi4iLAogICAgIm9pZCIsCiAgXQog\nIHJldmlzaW9uID0gIjI3ZWE1ZDkyZGUzMDA2MGU3MTIxZGRkNTQzZmUxNGU5\nYTMyN2UwY2MiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20v\nbGlnaHRzdGVwL2xpZ2h0c3RlcC10cmFjZXItZ28iCiAgcGFja2FnZXMgPSBb\nCiAgICAiLiIsCiAgICAiY29sbGVjdG9ycGIiLAogICAgImxpZ2h0c3RlcF90\naHJpZnQiLAogICAgImxpZ2h0c3RlcHBiIiwKICAgICJ0aHJpZnRfMF85XzIv\nbGliL2dvL3RocmlmdCIsCiAgXQogIHJldmlzaW9uID0gImJhMzhiYWUxZjBl\nYzFlY2U5MDkyZDM1YmJlY2JiNDk3ZWUzNDRjYmMiCiAgdmVyc2lvbiA9ICJ2\nMC4xNS4wIgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29tL21h\ncnN0ci9ndWlkIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZpc2lvbiA9ICI4\nYmQ5YTY0YmYzN2ViMjk3YjQ5MmE0MTAxZmIyOGU4MGFjMGIyOTBmIgogIHZl\ncnNpb24gPSAidjEuMS4wIgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRo\ndWIuY29tL21hcnVzYW1hL3NlbWFwaG9yZSIKICBwYWNrYWdlcyA9IFsiLiJd\nCiAgcmV2aXNpb24gPSAiNTY3ZjE3MjA2ZWFhM2YyOGJkNzNlMjA5NjIwZTJh\nYmFhNjVkNzQwNSIKICB2ZXJzaW9uID0gIjIuMS4xIgoKW1twcm9qZWN0c11d\nCiAgbmFtZSA9ICJnaXRodWIuY29tL21hdHRuL2dvLWlzYXR0eSIKICBwYWNr\nYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiMDM2MGIyYWY0ZjM4ZThkMzhj\nN2ZjZTJhOWY0ZTcwMjcwMmQ3M2EzOSIKICB2ZXJzaW9uID0gInYwLjAuMyIK\nCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9tYXR0bi9nby1y\ndW5ld2lkdGgiCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gIjll\nNzc3YTgzNjZjY2U2MDUxMzBhNTMxZDJjZDYzNjNkMDdhZDczMTciCiAgdmVy\nc2lvbiA9ICJ2MC4wLjIiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1\nYi5jb20vbWF0dG4vZ292ZXJhbGxzIgogIHBhY2thZ2VzID0gWyIuIl0KICBy\nZXZpc2lvbiA9ICJiNzFhMWU0ODU1Zjg3OTkxYWZmMDFjMmM4MzNhNzVhMDcw\nNTljNjFjIgogIHZlcnNpb24gPSAidjAuMC4yIgoKW1twcm9qZWN0c11dCiAg\nbmFtZSA9ICJnaXRodWIuY29tL21hdHR0cHJvdWQvZ29sYW5nX3Byb3RvYnVm\nX2V4dGVuc2lvbnMiCiAgcGFja2FnZXMgPSBbInBidXRpbCJdCiAgcmV2aXNp\nb24gPSAiMzI0N2M4NDUwMGJmZjhkOWZiNmQ1NzlkODAwZjIwYjNlMDkxNTgy\nYyIKICB2ZXJzaW9uID0gInYxLjAuMCIKCltbcHJvamVjdHNdXQogIG5hbWUg\nPSAiZ2l0aHViLmNvbS9taWJrL2R1cGwiCiAgcGFja2FnZXMgPSBbCiAgICAi\nLiIsCiAgICAiam9iIiwKICAgICJvdXRwdXQiLAogICAgInN1ZmZpeHRyZWUi\nLAogICAgInN5bnRheCIsCiAgICAic3ludGF4L2dvbGFuZyIsCiAgXQogIHJl\ndmlzaW9uID0gImYwMDhmY2Y1ZTYyNzkzZDM4YmRhNTEwZWUzN2FhYjhiMGM2\nOGU3NmMiCiAgdmVyc2lvbiA9ICJ2MS4wLjAiCgpbW3Byb2plY3RzXV0KICBi\ncmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9taXRjaGVs\nbGgvcmVmbGVjdHdhbGsiCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9u\nID0gIjYzZDYwZTlkMGRiYzYwY2Y5MTY0ZTY1MTA4ODliMGRiNjY4M2Q5OGMi\nCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAi\nZ2l0aHViLmNvbS9tb250YW5hZmx5bm4vc3RhdHMiCiAgcGFja2FnZXMgPSBb\nIi4iXQogIHJldmlzaW9uID0gIjcyNjI1ZWMxNjkxZTQwMTgxYWM1MjgyYTdm\nMmNhNDc0NTk1MmE3YTciCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFz\ndGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9uaWdodGx5b25lL2xvY2tmaWxl\nIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZpc2lvbiA9ICI2YTE5N2Q1ZWE2\nMTE2OGYyYWM4MjFkZTJiN2YwMTFiMjUwOTA0OTAwIgoKW1twcm9qZWN0c11d\nCiAgbmFtZSA9ICJnaXRodWIuY29tL25sb3Blcy9zbGFjayIKICBwYWNrYWdl\ncyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiOGFiNGQwYjM2NGVmMWU5YWY1ZDEw\nMjUzMWRhMjBkNWVjOTAyYjZjNCIKICB2ZXJzaW9uID0gInYwLjIuMCIKCltb\ncHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRo\ndWIuY29tL29sZWt1a29ua28vdGFibGV3cml0ZXIiCiAgcGFja2FnZXMgPSBb\nIi4iXQogIHJldmlzaW9uID0gImI4YTliZTA3MGRhNDA0NDllNTAxYzNjNDcz\nMGE4ODllNDJkODdhOWUiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1\nYi5jb20vb3BlbmNvbnRhaW5lcnMvZ28tZGlnZXN0IgogIHBhY2thZ2VzID0g\nWyIuIl0KICByZXZpc2lvbiA9ICIyNzliZWQ5ODY3M2RkNWJlZjM3NGQzYjZl\nNGIwOWUyYWY3NjE4M2JmIgogIHZlcnNpb24gPSAidjEuMC4wLXJjMSIKCltb\ncHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9vcGVuY29udGFpbmVy\ncy9pbWFnZS1zcGVjIgogIHBhY2thZ2VzID0gWwogICAgInNwZWNzLWdvIiwK\nICAgICJzcGVjcy1nby92MSIsCiAgXQogIHJldmlzaW9uID0gImFiNzM4OWVm\nOWY1MDAzMGM5YjI0NWJjMTZiOTgxYzdkZGYxOTI4ODIiCiAgdmVyc2lvbiA9\nICJ2MS4wLjAiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFzdGVyIgog\nIG5hbWUgPSAiZ2l0aHViLmNvbS9vcGVubm90YS91cmxlc2MiCiAgcGFja2Fn\nZXMgPSBbIi4iXQogIHJldmlzaW9uID0gImRlNWJmMmFkNDU3ODQ2Mjk2ZTIw\nMzE0MjFhMzRlMjU2OGUzMDRlMzUiCgpbW3Byb2plY3RzXV0KICBicmFuY2gg\nPSAibWFzdGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9vcGVudHJhY2luZy1j\nb250cmliL2dvLW9ic2VydmVyIgogIHBhY2thZ2VzID0gWyIuIl0KICByZXZp\nc2lvbiA9ICJhNTJmMjM0MjQ0OTI0NmQ1YmNjMjczZTY1Y2JkY2ZhNWY3ZDZj\nNjNjIgoKW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29tL29wZW50\ncmFjaW5nL29wZW50cmFjaW5nLWdvIgogIHBhY2thZ2VzID0gWwogICAgIi4i\nLAogICAgImV4dCIsCiAgICAibG9nIiwKICBdCiAgcmV2aXNpb24gPSAiMTk0\nOWRkYmZkMTQ3YWZkNGQ5NjRhOWYwMGIyNGViMjkxZTBlN2MzOCIKICB2ZXJz\naW9uID0gInYxLjAuMiIKCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHVi\nLmNvbS9vcGVuemlwa2luL3ppcGtpbi1nby1vcGVudHJhY2luZyIKICBwYWNr\nYWdlcyA9IFsKICAgICIuIiwKICAgICJmbGFnIiwKICAgICJ0aHJpZnQvZ2Vu\nLWdvL3NjcmliZSIsCiAgICAidGhyaWZ0L2dlbi1nby96aXBraW5jb3JlIiwK\nICAgICJ0eXBlcyIsCiAgICAid2lyZSIsCiAgXQogIHJldmlzaW9uID0gIjQ1\nZTkwYjAwNzEwYTRjMzRhMWE3ZDhhNzhkOTBmOWIwMTBiMGJkNGQiCiAgdmVy\nc2lvbiA9ICJ2MC4zLjIiCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFz\ndGVyIgogIG5hbWUgPSAiZ2l0aHViLmNvbS9wZWxsZXRpZXIvZ28tdG9tbCIK\nICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiMDViY2MwZmIwZDNl\nNjBkYTRiOGRkNWJkN2UwZWE1NjNlYjRjYTk0MyIKCltbcHJvamVjdHNdXQog\nIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIuY29tL3BldGFy\nL0dvTExSQiIKICBwYWNrYWdlcyA9IFsibGxyYiJdCiAgcmV2aXNpb24gPSAi\nNTNiZTBkMzZhODRjMmE4ODZjYTA1N2QzNGI2YWE0NDY4ZGY5Y2NiNCIKCltb\ncHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRo\ndWIuY29tL3BldGVybWF0dGlzL2dvaWQiCiAgcGFja2FnZXMgPSBbIi4iXQog\nIHJldmlzaW9uID0gImIwYjE2MTViNzhlNWVlNTk3Mzk1NDViYjM4NDI2Mzgz\nYjJjZGE0YzkiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20v\ncGllcnJlYy9sejQiCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0g\nIjA4YzI3OTM5ZGYxYmQ5NWU4ODFlMmMyMzY3YTc0OTk2NGFkMWZjZWIiCiAg\ndmVyc2lvbiA9ICJ2MS4wLjEiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdp\ndGh1Yi5jb20vcGllcnJlYy94eEhhc2giCiAgcGFja2FnZXMgPSBbInh4SGFz\naDMyIl0KICByZXZpc2lvbiA9ICJmMDUxYmI3ZjFkMWFhZjFiNWE2NjVkNzRm\nYjZiMDIxNzcxMmM2OWY3IgogIHZlcnNpb24gPSAidjAuMS4xIgoKW1twcm9q\nZWN0c11dCiAgbmFtZSA9ICJnaXRodWIuY29tL3BrZy9lcnJvcnMiCiAgcGFj\na2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gIjY0NWVmMDA0NTllZDg0YTEx\nOTE5N2JmYjhkODIwNTA0MmM2ZGY2M2QiCiAgdmVyc2lvbiA9ICJ2MC44LjAi\nCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1Yi5jb20vcG1lemFyZC9n\nby1kaWZmbGliIgogIHBhY2thZ2VzID0gWyJkaWZmbGliIl0KICByZXZpc2lv\nbiA9ICI3OTI3ODZjNzQwMGExMzYyODJjMTY2NDY2NWFlMGE4ZGI5MjFjNmMy\nIgogIHZlcnNpb24gPSAidjEuMC4wIgoKW1twcm9qZWN0c11dCiAgbmFtZSA9\nICJnaXRodWIuY29tL3Byb21ldGhldXMvY2xpZW50X2dvbGFuZyIKICBwYWNr\nYWdlcyA9IFsKICAgICJwcm9tZXRoZXVzIiwKICAgICJwcm9tZXRoZXVzL2dy\nYXBoaXRlIiwKICBdCiAgcmV2aXNpb24gPSAiOTY3Nzg5MDUwYmE5NGRlY2Ew\nNGE1ZTg0Y2NlOGFkNDcyY2UzMTNjMSIKICB2ZXJzaW9uID0gInYwLjkuMC1w\ncmUxIgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1l\nID0gImdpdGh1Yi5jb20vcHJvbWV0aGV1cy9jbGllbnRfbW9kZWwiCiAgcGFj\na2FnZXMgPSBbImdvIl0KICByZXZpc2lvbiA9ICI2ZjM4MDYwMTg2MTI5MzA5\nNDExMjdmMmE3YzZjNDUzYmEyYzUyN2QyIgoKW1twcm9qZWN0c11dCiAgYnJh\nbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vcHJvbWV0aGV1\ncy9jb21tb24iCiAgcGFja2FnZXMgPSBbCiAgICAiZXhwZm10IiwKICAgICJp\nbnRlcm5hbC9iaXRidWNrZXQub3JnL3d3L2dvYXV0b25lZyIsCiAgICAibW9k\nZWwiLAogIF0KICByZXZpc2lvbiA9ICIxYmFiNTVkZDA1ZGJmZjM4NDUyNGE2\nYTFjOTkwMDZkOWViNWYxMzliIgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0g\nIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vcHJvbWV0aGV1cy9wcm9j\nZnMiCiAgcGFja2FnZXMgPSBbCiAgICAiLiIsCiAgICAiaW50ZXJuYWwvdXRp\nbCIsCiAgICAibmZzIiwKICAgICJ4ZnMiLAogIF0KICByZXZpc2lvbiA9ICI4\nYjFjMmRhMGQ1NmRlZmZkYmI5ZTQ4ZDQ0MTRiNGU2NzRiZDgwODNlIgoKW1tw\ncm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1\nYi5jb20vcmNyb3dsZXkvZ28tbWV0cmljcyIKICBwYWNrYWdlcyA9IFsKICAg\nICIuIiwKICAgICJleHAiLAogIF0KICByZXZpc2lvbiA9ICIxZjMwZmU5MDk0\nYTUxM2NlNGM3MDBiOWE1NDQ1OGJiYjBjOTY5OTZjIgoKW1twcm9qZWN0c11d\nCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vcnVi\neWlzdC9jaXJjdWl0YnJlYWtlciIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2\naXNpb24gPSAiMjA3NGFkYmE1ZGRjN2Q1Zjc1NTk0NDhhOWMzMDY2NTczNTIx\nYzViZiIKCltbcHJvamVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9ydXNz\ncm9zcy9ibGFja2ZyaWRheSIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNp\nb24gPSAiNDA0ODg3MmIxNmNjMGZjMmM1ZmQ5ZWFjZjBlZDJjMmZlZGFhMGM4\nYyIKICB2ZXJzaW9uID0gInYxLjUiCgpbW3Byb2plY3RzXV0KICBuYW1lID0g\nImdpdGh1Yi5jb20vc2FzaGEtcy9nby1kZWFkbG9jayIKICBwYWNrYWdlcyA9\nIFsiLiJdCiAgcmV2aXNpb24gPSAiMDNkNDBlNWRiZDU0ODg2NjdhMTNiM2My\nNjAwYjJmN2MyODg2ZjAyZiIKICB2ZXJzaW9uID0gInYwLjIuMCIKCltbcHJv\namVjdHNdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9zYXRvcmkvZ28udXVpZCIK\nICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiZjU4NzY4Y2MxYTdh\nN2U3N2EzYmQ0OWU5OGNkZDIxNDE5Mzk5YjZhMyIKICB2ZXJzaW9uID0gInYx\nLjIuMCIKCltbcHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFt\nZSA9ICJnaXRodWIuY29tL3NkYm95ZXIvY29uc3RleHQiCiAgcGFja2FnZXMg\nPSBbIi4iXQogIHJldmlzaW9uID0gIjgzNmExNDQ1NzM1MzNlYTRkYTRlNjky\nOWMyMzVmZDM0OGFlZDFjODAiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdp\ndGh1Yi5jb20vc2lydXBzZW4vbG9ncnVzIgogIHBhY2thZ2VzID0gWyIuIl0K\nICByZXZpc2lvbiA9ICJmMDA2YzJhYzQ3MTA4NTVjZjBmOTE2ZGQ2Yjc3YWNm\nNmIwNDhkYzZlIgogIHZlcnNpb24gPSAidjEuMC4zIgoKW1twcm9qZWN0c11d\nCiAgbmFtZSA9ICJnaXRodWIuY29tL3NwZjEzL2NvYnJhIgogIHBhY2thZ2Vz\nID0gWwogICAgIi4iLAogICAgImRvYyIsCiAgXQogIHJldmlzaW9uID0gIjdi\nMmM1YWM5ZmMwNGZjNWVmYWZiNjA3MDA3MTNkNGZhNjA5Yjc3N2IiCiAgdmVy\nc2lvbiA9ICJ2MC4wLjEiCgpbW3Byb2plY3RzXV0KICBuYW1lID0gImdpdGh1\nYi5jb20vc3BmMTMvcGZsYWciCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlz\naW9uID0gImU1N2UzZWViMzNmNzk1MjA0YzFjYTM1ZjU2YzQ0ZjgzMjI3YzZl\nNjYiCiAgdmVyc2lvbiA9ICJ2MS4wLjAiCgpbW3Byb2plY3RzXV0KICBuYW1l\nID0gImdpdGh1Yi5jb20vc3RyZXRjaHIvdGVzdGlmeSIKICBwYWNrYWdlcyA9\nIFsKICAgICJhc3NlcnQiLAogICAgInJlcXVpcmUiLAogIF0KICByZXZpc2lv\nbiA9ICI2OTQ4M2I0YmQxNGY1ODQ1YjVhMWU1NWJjYTE5ZTk1NGU4MjdmMWQw\nIgogIHZlcnNpb24gPSAidjEuMS40IgoKW1twcm9qZWN0c11dCiAgYnJhbmNo\nID0gIm1hc3RlciIKICBuYW1lID0gImdpdGh1Yi5jb20vd2FkZXkvZ29jb3Zt\nZXJnZSIKICBwYWNrYWdlcyA9IFsiLiJdCiAgcmV2aXNpb24gPSAiYjViZmE1\nOWVjMGFkYzQyMDQ3NWY5N2Y4OWI1ODA0NWM3MjFkNzYxYyIKCltbcHJvamVj\ndHNdXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnaXRodWIuY29t\nL3h3YjE5ODkvc3FscGFyc2VyIgogIHBhY2thZ2VzID0gWwogICAgIi4iLAog\nICAgImRlcGVuZGVuY3kvYnl0ZXMyIiwKICAgICJkZXBlbmRlbmN5L2hhY2si\nLAogICAgImRlcGVuZGVuY3kvcXVlcnlwYiIsCiAgICAiZGVwZW5kZW5jeS9z\ncWx0eXBlcyIsCiAgXQogIHJldmlzaW9uID0gIjZhZmY4NjE1YTMzZmFmMWYy\nNjBhM2E4ZjgwMDQ1NjUxMTUwNWQ1ZmQiCiAgc291cmNlID0gImh0dHBzOi8v\nZ2l0aHViLmNvbS9kdC9zcWxwYXJzZXIiCgpbW3Byb2plY3RzXV0KICBuYW1l\nID0gImdvLm9wZW5jZW5zdXMuaW8iCiAgcGFja2FnZXMgPSBbCiAgICAiZXhw\nb3J0ZXIvc3RhY2tkcml2ZXIvcHJvcGFnYXRpb24iLAogICAgImludGVybmFs\nIiwKICAgICJpbnRlcm5hbC90YWdlbmNvZGluZyIsCiAgICAicGx1Z2luL29j\naHR0cCIsCiAgICAicGx1Z2luL29jaHR0cC9wcm9wYWdhdGlvbi9iMyIsCiAg\nICAic3RhdHMiLAogICAgInN0YXRzL2ludGVybmFsIiwKICAgICJzdGF0cy92\naWV3IiwKICAgICJ0YWciLAogICAgInRyYWNlIiwKICAgICJ0cmFjZS9pbnRl\ncm5hbCIsCiAgICAidHJhY2UvcHJvcGFnYXRpb24iLAogIF0KICByZXZpc2lv\nbiA9ICIwMDk1YWVjNjZhZTE0ODAxYzY3MTEyMTBmNmYwNzE2NDExY2VmZGQz\nIgogIHZlcnNpb24gPSAidjAuOC4wIgoKW1twcm9qZWN0c11dCiAgYnJhbmNo\nID0gIm1hc3RlciIKICBuYW1lID0gImdvbGFuZy5vcmcveC9jcnlwdG8iCiAg\ncGFja2FnZXMgPSBbCiAgICAiYmNyeXB0IiwKICAgICJibG93ZmlzaCIsCiAg\nICAic3NoL3Rlcm1pbmFsIiwKICBdCiAgcmV2aXNpb24gPSAiYmQ2ZjI5OWZi\nMzgxZTRjMzM5M2QxYzRiMWYwYjk0ZjVlNzc2NTBjOCIKCltbcHJvamVjdHNd\nXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnb2xhbmcub3JnL3gv\nbmV0IgogIHBhY2thZ2VzID0gWwogICAgImNvbnRleHQiLAogICAgImNvbnRl\neHQvY3R4aHR0cCIsCiAgICAiaHRtbCIsCiAgICAiaHRtbC9hdG9tIiwKICAg\nICJodHRwMiIsCiAgICAiaHR0cDIvaHBhY2siLAogICAgImlkbmEiLAogICAg\nImludGVybmFsL3RpbWVzZXJpZXMiLAogICAgImxleC9odHRwbGV4IiwKICAg\nICJwcm94eSIsCiAgICAidHJhY2UiLAogIF0KICByZXZpc2lvbiA9ICJjNzM2\nMjJjNzcyODAyNjYzMDUyNzNjYjU0NWY1NDUxNmNlZDk1YjkzIgoKW1twcm9q\nZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdvbGFuZy5v\ncmcveC9vYXV0aDIiCiAgcGFja2FnZXMgPSBbCiAgICAiLiIsCiAgICAiZ29v\nZ2xlIiwKICAgICJpbnRlcm5hbCIsCiAgICAiandzIiwKICAgICJqd3QiLAog\nIF0KICByZXZpc2lvbiA9ICI2ODgxZmVlNDEwYTVkYWY4NjM3MTM3MWY5YWQ0\nNTFiOTVlMTY4YjcxIgoKW1twcm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3Rl\nciIKICBuYW1lID0gImdvbGFuZy5vcmcveC9wZXJmIgogIHBhY2thZ2VzID0g\nWwogICAgImJlbmNoc3RhdCIsCiAgICAiY21kL2JlbmNoc3RhdCIsCiAgICAi\naW50ZXJuYWwvc3RhdHMiLAogICAgInN0b3JhZ2UiLAogICAgInN0b3JhZ2Uv\nYmVuY2hmbXQiLAogIF0KICByZXZpc2lvbiA9ICI0NDY5ZTZjZThjYzM5MjBm\nMWI0MjEyOGI5ZDU1N2JlYTJlMDg2MjFhIgoKW1twcm9qZWN0c11dCiAgYnJh\nbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdvbGFuZy5vcmcveC9zeW5jIgog\nIHBhY2thZ2VzID0gWwogICAgImVycmdyb3VwIiwKICAgICJzeW5jbWFwIiwK\nICBdCiAgcmV2aXNpb24gPSAiOGUwYWE2ODhiNjU0ZWYyOGNhYTcyNTA2ZmE1\nZWM4ZGJhOWZjNzY5MCIKCltbcHJvamVjdHNdXQogIGJyYW5jaCA9ICJtYXN0\nZXIiCiAgbmFtZSA9ICJnb2xhbmcub3JnL3gvc3lzIgogIHBhY2thZ2VzID0g\nWwogICAgInVuaXgiLAogICAgIndpbmRvd3MiLAogIF0KICByZXZpc2lvbiA9\nICI5NWM2NTc2Mjk5MjU5ZGI5NjBmNmM1YjliNjllYTUyNDIyODYwZmNlIgoK\nW1twcm9qZWN0c11dCiAgbmFtZSA9ICJnb2xhbmcub3JnL3gvdGV4dCIKICBw\nYWNrYWdlcyA9IFsKICAgICJjb2xsYXRlIiwKICAgICJjb2xsYXRlL2J1aWxk\nIiwKICAgICJpbnRlcm5hbC9jb2xsdGFiIiwKICAgICJpbnRlcm5hbC9nZW4i\nLAogICAgImludGVybmFsL3RhZyIsCiAgICAiaW50ZXJuYWwvdHJpZWdlbiIs\nCiAgICAiaW50ZXJuYWwvdWNkIiwKICAgICJsYW5ndWFnZSIsCiAgICAic2Vj\ndXJlL2JpZGlydWxlIiwKICAgICJ0cmFuc2Zvcm0iLAogICAgInVuaWNvZGUv\nYmlkaSIsCiAgICAidW5pY29kZS9jbGRyIiwKICAgICJ1bmljb2RlL25vcm0i\nLAogICAgInVuaWNvZGUvcmFuZ2V0YWJsZSIsCiAgXQogIHJldmlzaW9uID0g\nIjQ3MGY0NWJmMjlmNDE0N2Q2ZmJkN2RmZDBhMDJhODQ4ZTQ5ZjViZjQiCgpb\nW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ29s\nYW5nLm9yZy94L3RpbWUiCiAgcGFja2FnZXMgPSBbInJhdGUiXQogIHJldmlz\naW9uID0gIjZkYzE3MzY4ZTA5YjBlODYzNGQ3MWNhYzgxNjhkODUzZTg2OWEw\nYzciCgpbW3Byb2plY3RzXV0KICBicmFuY2ggPSAibWFzdGVyIgogIG5hbWUg\nPSAiZ29sYW5nLm9yZy94L3Rvb2xzIgogIHBhY2thZ2VzID0gWwogICAgImNt\nZC9nb2ltcG9ydHMiLAogICAgImNtZC9nb3lhY2MiLAogICAgImNtZC9zdHJp\nbmdlciIsCiAgICAiY29udGFpbmVyL2ludHNldHMiLAogICAgImNvdmVyIiwK\nICAgICJnby9hc3QvYXN0dXRpbCIsCiAgICAiZ28vYnVpbGR1dGlsIiwKICAg\nICJnby9nY2V4cG9ydGRhdGEiLAogICAgImdvL2djaW1wb3J0ZXIxNSIsCiAg\nICAiZ28vbG9hZGVyIiwKICAgICJnby90eXBlcy90eXBldXRpbCIsCiAgICAi\naW1wb3J0cyIsCiAgXQogIHJldmlzaW9uID0gIjkwYjgwN2FkYTRjYzdhYjVk\nMTQwOWQ2MzdiMWYzYmViNWE3NzZiZTciCgpbW3Byb2plY3RzXV0KICBicmFu\nY2ggPSAibWFzdGVyIgogIG5hbWUgPSAiZ29vZ2xlLmdvbGFuZy5vcmcvYXBp\nIgogIHBhY2thZ2VzID0gWwogICAgImdlbnN1cHBvcnQiLAogICAgImdvb2ds\nZWFwaSIsCiAgICAiZ29vZ2xlYXBpL2ludGVybmFsL3VyaXRlbXBsYXRlcyIs\nCiAgICAiZ29vZ2xlYXBpL3RyYW5zcG9ydCIsCiAgICAiaW50ZXJuYWwiLAog\nICAgIml0ZXJhdG9yIiwKICAgICJvcHRpb24iLAogICAgInN0b3JhZ2UvdjEi\nLAogICAgInRyYW5zcG9ydC9odHRwIiwKICBdCiAgcmV2aXNpb24gPSAiOWM3\nOWRlZWJmNzQ5NmUzNTVkN2U5NWQ4MmQ0YWYxZmU0ZTc2OWIyZiIKCltbcHJv\namVjdHNdXQogIG5hbWUgPSAiZ29vZ2xlLmdvbGFuZy5vcmcvYXBwZW5naW5l\nIgogIHBhY2thZ2VzID0gWwogICAgIi4iLAogICAgImludGVybmFsIiwKICAg\nICJpbnRlcm5hbC9hcHBfaWRlbnRpdHkiLAogICAgImludGVybmFsL2Jhc2Ui\nLAogICAgImludGVybmFsL2RhdGFzdG9yZSIsCiAgICAiaW50ZXJuYWwvbG9n\nIiwKICAgICJpbnRlcm5hbC9tb2R1bGVzIiwKICAgICJpbnRlcm5hbC9yZW1v\ndGVfYXBpIiwKICAgICJpbnRlcm5hbC91cmxmZXRjaCIsCiAgICAidXJsZmV0\nY2giLAogIF0KICByZXZpc2lvbiA9ICIxNTBkYzU3YTFiNDMzZTY0MTU0MzAy\nYmRjNDBiNmJiOGFlZmEzMTNhIgogIHZlcnNpb24gPSAidjEuMC4wIgoKW1tw\ncm9qZWN0c11dCiAgYnJhbmNoID0gIm1hc3RlciIKICBuYW1lID0gImdvb2ds\nZS5nb2xhbmcub3JnL2dlbnByb3RvIgogIHBhY2thZ2VzID0gWwogICAgImdv\nb2dsZWFwaXMvYXBpL2Fubm90YXRpb25zIiwKICAgICJnb29nbGVhcGlzL2lh\nbS92MSIsCiAgICAiZ29vZ2xlYXBpcy9ycGMvY29kZSIsCiAgICAiZ29vZ2xl\nYXBpcy9ycGMvc3RhdHVzIiwKICBdCiAgcmV2aXNpb24gPSAiZjY3NmUwZjNh\nYzYzOTVmZjFhNTI5YWU1OWE2NjcwODc4YTgzNzFhNiIKCltbcHJvamVjdHNd\nXQogIGJyYW5jaCA9ICJtYXN0ZXIiCiAgbmFtZSA9ICJnb29nbGUuZ29sYW5n\nLm9yZy9ncnBjIgogIHBhY2thZ2VzID0gWwogICAgIi4iLAogICAgImJhbGFu\nY2VyIiwKICAgICJiYWxhbmNlci9iYXNlIiwKICAgICJiYWxhbmNlci9yb3Vu\nZHJvYmluIiwKICAgICJjaGFubmVseiIsCiAgICAiY29kZXMiLAogICAgImNv\nbm5lY3Rpdml0eSIsCiAgICAiY3JlZGVudGlhbHMiLAogICAgImVuY29kaW5n\nIiwKICAgICJlbmNvZGluZy9wcm90byIsCiAgICAiZ3JwY2xiL2dycGNfbGJf\ndjEvbWVzc2FnZXMiLAogICAgImdycGNsb2ciLAogICAgImhlYWx0aC9ncnBj\nX2hlYWx0aF92MSIsCiAgICAiaW50ZXJuYWwiLAogICAgImtlZXBhbGl2ZSIs\nCiAgICAibWV0YWRhdGEiLAogICAgIm5hbWluZyIsCiAgICAicGVlciIsCiAg\nICAicmVzb2x2ZXIiLAogICAgInJlc29sdmVyL2RucyIsCiAgICAicmVzb2x2\nZXIvcGFzc3Rocm91Z2giLAogICAgInN0YXRzIiwKICAgICJzdGF0dXMiLAog\nICAgInRhcCIsCiAgICAidHJhbnNwb3J0IiwKICBdCiAgcmV2aXNpb24gPSAi\nOGYwNmY4MmNhMzk0YjFhYzgzN2Q0YjBjMGNmYTA3MTg4YjBlOWRlZSIKCltb\ncHJvamVjdHNdXQogIGJyYW5jaCA9ICJ2MiIKICBuYW1lID0gImdvcGtnLmlu\nL3lhbWwudjIiCiAgcGFja2FnZXMgPSBbIi4iXQogIHJldmlzaW9uID0gIjI4\nN2NmMDg1NDZhYjVlN2UzN2Q1NWE4NGY3ZWQzZmQxZGIwMzZkZTUiCgpbW3By\nb2plY3RzXV0KICBuYW1lID0gImhvbm5lZi5jby9nby90b29scyIKICBwYWNr\nYWdlcyA9IFsKICAgICJjYWxsZ3JhcGgiLAogICAgImNhbGxncmFwaC9zdGF0\naWMiLAogICAgImRlcHJlY2F0ZWQiLAogICAgImZ1bmN0aW9ucyIsCiAgICAi\naW50ZXJuYWwvc2hhcmVkY2hlY2siLAogICAgImxpbnQiLAogICAgInNpbXBs\nZSIsCiAgICAic3NhIiwKICAgICJzc2Evc3NhdXRpbCIsCiAgICAic3RhdGlj\nY2hlY2siLAogICAgInN0YXRpY2NoZWNrL3ZycCIsCiAgICAidW51c2VkIiwK\nICBdCiAgcmV2aXNpb24gPSAiZDczYWI5OGU3YzM5ZmRjZjliYTY1MDYyZTQz\nZDM0MzEwZjE5ODM1MyIKICB2ZXJzaW9uID0gIjIwMTcuMi4yIgoKW3NvbHZl\nLW1ldGFdCiAgYW5hbHl6ZXItbmFtZSA9ICJkZXAiCiAgYW5hbHl6ZXItdmVy\nc2lvbiA9IDEKICBpbnB1dHMtZGlnZXN0ID0gIjgwMjI4MzYyMjMwNTlhZWFk\nODdmNmQ3ZDZiOTQ1MWE1ZDdhZDhhMjBmNDM1OGNiNzA5Y2NmMjg1OWY5Yzc0\nY2UiCiAgc29sdmVyLW5hbWUgPSAiZ3BzLWNkY2wiCiAgc29sdmVyLXZlcnNp\nb24gPSAxCg==\n", + "encoding": "base64", + "_links": { + "self": "https://api.github.com/repos/cockroachdb/cockroach/contents/Gopkg.lock?ref=master", + "git": "https://api.github.com/repos/cockroachdb/cockroach/git/blobs/816ac07074ab08023f4fea593888b1f87dd774b3", + "html": "https://github.com/cockroachdb/cockroach/blob/master/Gopkg.lock" + } +} diff --git a/spec/fixtures/github/contents_gopkg_toml.json b/spec/fixtures/github/contents_gopkg_toml.json new file mode 100644 index 00000000000..1b8320e184d --- /dev/null +++ b/spec/fixtures/github/contents_gopkg_toml.json @@ -0,0 +1,18 @@ +{ + "name": "Gopkg.toml", + "path": "Gopkg.toml", + "sha": "ad9e923036970af596b854534149b41bdc0ecfa1", + "size": 3254, + "url": "https://api.github.com/repos/cockroachdb/cockroach/contents/Gopkg.toml?ref=master", + "html_url": "https://github.com/cockroachdb/cockroach/blob/master/Gopkg.toml", + "git_url": "https://api.github.com/repos/cockroachdb/cockroach/git/blobs/ad9e923036970af596b854534149b41bdc0ecfa1", + "download_url": "https://raw.githubusercontent.com/cockroachdb/cockroach/master/Gopkg.toml", + "type": "file", + "content": "cmVxdWlyZWQgPSBbCiAiZ2l0aHViLmNvbS9jbGllbnQ5L21pc3NwZWxsL2Nt\nZC9taXNzcGVsbCIsCiAiZ2l0aHViLmNvbS9jb2Nrcm9hY2hkYi9jcmxmbXQi\nLAogImdpdGh1Yi5jb20vY29ja3JvYWNoZGIvc3RyZXNzIiwKICJnaXRodWIu\nY29tL2dvbGFuZy9kZXAvY21kL2RlcCIsCiAiZ2l0aHViLmNvbS9nb2xhbmcv\nbGludC9nb2xpbnQiLAogImdpdGh1Yi5jb20vZ29vZ2xlL3Bwcm9mIiwKICJn\naXRodWIuY29tL2dycGMtZWNvc3lzdGVtL2dycGMtZ2F0ZXdheS9wcm90b2Mt\nZ2VuLWdycGMtZ2F0ZXdheSIsCiAiZ2l0aHViLmNvbS9qdGVldXdlbi9nby1i\naW5kYXRhL2dvLWJpbmRhdGEiLAogImdpdGh1Yi5jb20va2lzaWVsay9lcnJj\naGVjayIsCiAiZ2l0aHViLmNvbS9tYXR0bi9nb3ZlcmFsbHMiLAogImdpdGh1\nYi5jb20vbWliay9kdXBsIiwKICJnaXRodWIuY29tL3dhZGV5L2dvY292bWVy\nZ2UiLAogImdvbGFuZy5vcmcveC9wZXJmL2NtZC9iZW5jaHN0YXQiLAogImdv\nbGFuZy5vcmcveC90b29scy9jbWQvZ29pbXBvcnRzIiwKICJnb2xhbmcub3Jn\nL3gvdG9vbHMvY21kL2dveWFjYyIsCiAiZ29sYW5nLm9yZy94L3Rvb2xzL2Nt\nZC9zdHJpbmdlciIsCl0KCmlnbm9yZWQgPSBbCiAgIyBOb24tZXhpc3RlbnQg\ncGFja2FnZSB1c2VkIGJ5IGEgdG95IHByb2dyYW0gaW4gYy1kZXBzL3Byb3Rv\nYnVmLgogICJnaXRodWIuY29tL2dvb2dsZS9wcm90b2J1Zi9leGFtcGxlcy90\ndXRvcmlhbCIsCl0KCiMgVGhlIGNvbGxhdGlvbiB0YWJsZXMgbXVzdCBuZXZl\nciBjaGFuZ2UuCltbY29uc3RyYWludF1dCiAgbmFtZSA9ICJnb2xhbmcub3Jn\nL3gvdGV4dCIKICByZXZpc2lvbiA9ICI0NzBmNDViZjI5ZjQxNDdkNmZiZDdk\nZmQwYTAyYTg0OGU0OWY1YmY0IgoKIyBodHRwczovL2dpdGh1Yi5jb20vY29y\nZW9zL2V0Y2QvY29tbWl0L2YwM2VkMzMKIwojIGh0dHBzOi8vZ2l0aHViLmNv\nbS9jb3Jlb3MvZXRjZC9jb21taXQvY2UwYWQzNzcKW1tjb25zdHJhaW50XV0K\nICBuYW1lID0gImdpdGh1Yi5jb20vY29yZW9zL2V0Y2QiCiAgYnJhbmNoID0g\nIm1hc3RlciIKCiMgVXNlZCBmb3IgdGhlIEFQSSBjbGllbnQ7IHdlIHdhbnQg\ndGhlIGxhdGVzdC4KW1tjb25zdHJhaW50XV0KICBuYW1lID0gImdpdGh1Yi5j\nb20vZG9ja2VyL2RvY2tlciIKICBicmFuY2ggPSAibWFzdGVyIgoKIyBodHRw\nczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3JhdmVuLWdvL3B1bGwvMTM5Cltb\nY29uc3RyYWludF1dCiAgbmFtZSA9ICJnaXRodWIuY29tL2dldHNlbnRyeS9y\nYXZlbi1nbyIKICBzb3VyY2UgPSAiaHR0cHM6Ly9naXRodWIuY29tL2NvY2ty\nb2FjaGRiL3JhdmVuLWdvIgoKIyBVc2VkIGZvciBiZW5jaG1hcmtzLCBzaG91\nbGQgYmUgcmVjZW50LgpbW2NvbnN0cmFpbnRdXQogIG5hbWUgPSAiZ2l0aHVi\nLmNvbS9nby1zcWwtZHJpdmVyL215c3FsIgogIGJyYW5jaCA9ICJtYXN0ZXIi\nCgojIGh0dHBzOi8vZ2l0aHViLmNvbS9qdGVldXdlbi9nby1iaW5kYXRhL3B1\nbGwvMTU4CltbY29uc3RyYWludF1dCiAgbmFtZSA9ICJnaXRodWIuY29tL2p0\nZWV1d2VuL2dvLWJpbmRhdGEiCiAgc291cmNlID0gImh0dHBzOi8vZ2l0aHVi\nLmNvbS9kaW0xMy9nby1iaW5kYXRhIgogIGJyYW5jaCA9ICJtYXN0ZXIiCgoj\nIGh0dHBzOi8vZ2l0aHViLmNvbS9tb250YW5hZmx5bm4vc3RhdHMvcmVsZWFz\nZXMgKGxhdGVzdCBpcyAyMDE1LTEwLTE0KQpbW2NvbnN0cmFpbnRdXQogIG5h\nbWUgPSAiZ2l0aHViLmNvbS9tb250YW5hZmx5bm4vc3RhdHMiCiAgYnJhbmNo\nID0gIm1hc3RlciIKCiMgaHR0cHM6Ly9naXRodWIuY29tL3J1Ynlpc3QvY2ly\nY3VpdGJyZWFrZXIvY29tbWl0L2FmOTU4MzAKW1tjb25zdHJhaW50XV0KICBu\nYW1lID0gImdpdGh1Yi5jb20vcnVieWlzdC9jaXJjdWl0YnJlYWtlciIKICBi\ncmFuY2ggPSAibWFzdGVyIgoKIyBodHRwczovL2dpdGh1Yi5jb20veHdiMTk4\nOS9zcWxwYXJzZXIvaXNzdWVzLzMxCiMgaHR0cHM6Ly9naXRodWIuY29tL3h3\nYjE5ODkvc3FscGFyc2VyL2lzc3Vlcy8zMgpbW2NvbnN0cmFpbnRdXQogIG5h\nbWUgPSAiZ2l0aHViLmNvbS94d2IxOTg5L3NxbHBhcnNlciIKICBzb3VyY2Ug\nPSAiaHR0cHM6Ly9naXRodWIuY29tL2R0L3NxbHBhcnNlciIKCiMgVGhlIG1h\nc3RlciB2ZXJzaW9uIG9mIGdvLnV1aWQgaGFzIGFuIGluY29tcGF0aWJsZSBp\nbnRlcmZhY2UgYW5kIChhcwojIG9mIDIwMTgtMDYtMDYpIGEgc2VyaW91cyBi\ndWcuIERvbid0IHVwZ3JhZGUgd2l0aG91dCBtYWtpbmcgc3VyZQojIHRoYXQg\nYnVnIGlzIGZpeGVkLgojIGh0dHBzOi8vZ2l0aHViLmNvbS9jb2Nrcm9hY2hk\nYi9jb2Nrcm9hY2gvaXNzdWVzLzI2MzMyCltbY29uc3RyYWludF1dCiAgbmFt\nZSA9ICJnaXRodWIuY29tL3NhdG9yaS9nby51dWlkIgogIHZlcnNpb24gPSAi\ndjEuMi4wIgoKIyBnaXRodWIuY29tL2RvY2tlci9kb2NrZXIgZGVwZW5kcyBv\nbiBhIGZldyBmdW5jdGlvbnMgbm90IGluY2x1ZGVkIGluIHRoZQojIGxhdGVz\ndCByZWxlYXNlOiByZWZlcmVuY2Uue0ZhbWlsaWFyTmFtZSxQYXJzZU5vcm1h\nbGl6ZWROYW1lZCxUYWdOYW1lT25seX0uCiMKIyBodHRwczovL2dpdGh1Yi5j\nb20vZG9ja2VyL2Rpc3RyaWJ1dGlvbi9jb21taXQvNDI5Yzc1ZgojIGh0dHBz\nOi8vZ2l0aHViLmNvbS9kb2NrZXIvZGlzdHJpYnV0aW9uL2NvbW1pdC8yY2Fl\nYjYxCltbb3ZlcnJpZGVdXQogIG5hbWUgPSAiZ2l0aHViLmNvbS9kb2NrZXIv\nZGlzdHJpYnV0aW9uIgogIGJyYW5jaCA9ICJtYXN0ZXIiCgpbcHJ1bmVdCiAg\nZ28tdGVzdHMgPSB0cnVlCiAgdW51c2VkLXBhY2thZ2VzID0gdHJ1ZQoKICAj\nIEF2b2lkIHBydW5pbmcgcHJvamVjdHMgY29udGFpbmluZyBuZWVkZWQgcHJv\ndG9zLgoKICBbW3BydW5lLnByb2plY3RdXQogICAgbmFtZSA9ICJnaXRodWIu\nY29tL2dvZ28vcHJvdG9idWYiCiAgICB1bnVzZWQtcGFja2FnZXMgPSBmYWxz\nZQoKICBbW3BydW5lLnByb2plY3RdXQogICAgbmFtZSA9ICJnaXRodWIuY29t\nL2dycGMtZWNvc3lzdGVtL2dycGMtZ2F0ZXdheSIKICAgIHVudXNlZC1wYWNr\nYWdlcyA9IGZhbHNlCgogIFtbcHJ1bmUucHJvamVjdF1dCiAgICBuYW1lID0g\nImdpdGh1Yi5jb20vcHJvbWV0aGV1cy9jbGllbnRfbW9kZWwiCiAgICB1bnVz\nZWQtcGFja2FnZXMgPSBmYWxzZQoKICAjIENvbnRhaW5zIHBhY2thZ2VzIHdp\ndGggdXNlZCBDIGZpbGVzLgogIFtbcHJ1bmUucHJvamVjdF1dCiAgICBuYW1l\nID0gImdpdGh1Yi5jb20va256L2dvLWxpYmVkaXQiCiAgICB1bnVzZWQtcGFj\na2FnZXMgPSBmYWxzZQo=\n", + "encoding": "base64", + "_links": { + "self": "https://api.github.com/repos/cockroachdb/cockroach/contents/Gopkg.toml?ref=master", + "git": "https://api.github.com/repos/cockroachdb/cockroach/git/blobs/ad9e923036970af596b854534149b41bdc0ecfa1", + "html": "https://github.com/cockroachdb/cockroach/blob/master/Gopkg.toml" + } +} diff --git a/spec/fixtures/go/gopkg_locks/bare_version.lock b/spec/fixtures/go/gopkg_locks/bare_version.lock new file mode 100644 index 00000000000..918ff4ebdb5 --- /dev/null +++ b/spec/fixtures/go/gopkg_locks/bare_version.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/dgrijalva/jwt-go" + packages = ["."] + revision = "fbcb3e4b637bdc5ef2257eb2d0fe1d914a499386" + version = "v1.0.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "eb62c15704b851f8626abe61ac342d43a2d3522af64b9c8aa89748486e3325cc" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/spec/fixtures/go/gopkg_locks/branch.lock b/spec/fixtures/go/gopkg_locks/branch.lock new file mode 100644 index 00000000000..e44d91340bf --- /dev/null +++ b/spec/fixtures/go/gopkg_locks/branch.lock @@ -0,0 +1,30 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "golang.org/x/text" + packages = [ + ".", + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/language", + "internal/language/compact", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "transform", + "unicode/cldr", + "unicode/norm" + ] + revision = "7dd2c8130f5e924233f5543598300651c386d431" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "405bb493c54786c5c6ad50e065d9d815af21e413be8ef1b592ca5333d8144eb5" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/spec/fixtures/go/gopkg_locks/cockroach.lock b/spec/fixtures/go/gopkg_locks/cockroach.lock new file mode 100644 index 00000000000..816ac07074a --- /dev/null +++ b/spec/fixtures/go/gopkg_locks/cockroach.lock @@ -0,0 +1,1309 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "cloud.google.com/go" + packages = [ + "compute/metadata", + "iam", + "internal", + "internal/optional", + "internal/trace", + "internal/version", + "storage", + ] + revision = "0fd7230b2a7505833d5f69b75cbd6c9582401479" + version = "v0.23.0" + +[[projects]] + name = "github.com/Azure/azure-sdk-for-go" + packages = [ + "storage", + "version", + ] + revision = "e67cd39e942c417ae5e9ae1165f778d9fe8996e0" + version = "v14.5.0" + +[[projects]] + branch = "master" + name = "github.com/Azure/go-ansiterm" + packages = [ + ".", + "winterm", + ] + revision = "d6e3b3328b783f23731bc4d058875b0371ff8109" + +[[projects]] + name = "github.com/Azure/go-autorest" + packages = [ + "autorest", + "autorest/adal", + "autorest/azure", + "autorest/date", + ] + revision = "0ae36a9e544696de46fdadb7b0d5fb38af48c063" + version = "v10.2.0" + +[[projects]] + branch = "parse-constraints-with-dash-in-pre" + name = "github.com/Masterminds/semver" + packages = ["."] + revision = "a93e51b5a57ef416dac8bb02d11407b6f55d8929" + source = "https://github.com/carolynvs/semver.git" + +[[projects]] + name = "github.com/Masterminds/vcs" + packages = ["."] + revision = "6f1c6d150500e452704e9863f68c2559f58616bf" + version = "v1.12.0" + +[[projects]] + branch = "master" + name = "github.com/MichaelTJones/walk" + packages = ["."] + revision = "4748e29d5718c2df4028a6543edf86fd8cc0f881" + +[[projects]] + name = "github.com/Microsoft/go-winio" + packages = ["."] + revision = "78439966b38d69bf38227fbf57ac8a6fee70f69a" + version = "v0.4.5" + +[[projects]] + branch = "master" + name = "github.com/Nvveen/Gotty" + packages = ["."] + revision = "cd527374f1e5bff4938207604a14f2e38a9cf512" + +[[projects]] + name = "github.com/PuerkitoBio/goquery" + packages = ["."] + revision = "e1271ee34c6a305e38566ecd27ae374944907ee9" + version = "v1.1.0" + +[[projects]] + name = "github.com/Shopify/sarama" + packages = ["."] + revision = "bbdbe644099b7fdc8327d5cc69c030945188b2e9" + version = "v1.13.0" + +[[projects]] + branch = "master" + name = "github.com/StackExchange/wmi" + packages = ["."] + revision = "ea383cf3ba6ec950874b8486cd72356d007c768f" + +[[projects]] + name = "github.com/VividCortex/ewma" + packages = ["."] + revision = "b24eb346a94c3ba12c1da1e564dbac1b498a77ce" + version = "v1.1.1" + +[[projects]] + branch = "master" + name = "github.com/abourget/teamcity" + packages = ["."] + revision = "e241104394f91bf4e65048f9ea5d0c0f3c25b35e" + +[[projects]] + branch = "master" + name = "github.com/andy-kimball/arenaskl" + packages = ["."] + revision = "224761e552afe64db9d93004f8d5d3a686b89771" + +[[projects]] + branch = "master" + name = "github.com/andybalholm/cascadia" + packages = ["."] + revision = "349dd0209470eabd9514242c688c403c0926d266" + +[[projects]] + name = "github.com/apache/thrift" + packages = ["lib/go/thrift"] + revision = "327ebb6c2b6df8bf075da02ef45a2a034e9b79ba" + version = "0.11.0" + +[[projects]] + branch = "master" + name = "github.com/armon/go-radix" + packages = ["."] + revision = "1fca145dffbcaa8fe914309b1ec0cfc67500fe61" + +[[projects]] + name = "github.com/aws/aws-sdk-go" + packages = [ + "aws", + "aws/awserr", + "aws/awsutil", + "aws/client", + "aws/client/metadata", + "aws/corehandlers", + "aws/credentials", + "aws/credentials/ec2rolecreds", + "aws/credentials/endpointcreds", + "aws/credentials/stscreds", + "aws/defaults", + "aws/ec2metadata", + "aws/endpoints", + "aws/request", + "aws/session", + "aws/signer/v4", + "internal/shareddefaults", + "private/protocol", + "private/protocol/query", + "private/protocol/query/queryutil", + "private/protocol/rest", + "private/protocol/restxml", + "private/protocol/xml/xmlutil", + "service/s3", + "service/s3/s3iface", + "service/s3/s3manager", + "service/sts", + ] + revision = "ee1f179877b2daf2aaabf71fa900773bf8842253" + version = "v1.12.19" + +[[projects]] + branch = "master" + name = "github.com/axiomhq/hyperloglog" + packages = ["."] + revision = "baba800be098d9f4303352fa6214a933e371e3da" + +[[projects]] + branch = "master" + name = "github.com/backtrace-labs/go-bcd" + packages = ["."] + revision = "5d8e01b2f0438922289238fd3ba043761daf1102" + +[[projects]] + branch = "master" + name = "github.com/benesch/cgosymbolizer" + packages = ["."] + revision = "70e1ee2b39d3b616a6ab9996820dde224c27f351" + +[[projects]] + branch = "master" + name = "github.com/beorn7/perks" + packages = ["quantile"] + revision = "3a771d992973f24aa725d07868b467d1ddfceafb" + +[[projects]] + branch = "master" + name = "github.com/biogo/store" + packages = ["llrb"] + revision = "913427a1d5e89604e50ea1db0f28f34966d61602" + +[[projects]] + name = "github.com/boltdb/bolt" + packages = ["."] + revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8" + version = "v1.3.1" + +[[projects]] + name = "github.com/cenk/backoff" + packages = ["."] + revision = "61153c768f31ee5f130071d08fc82b85208528de" + version = "v1.1.0" + +[[projects]] + name = "github.com/certifi/gocertifi" + packages = ["."] + revision = "3fd9e1adb12b72d2f3f82191d49be9b93c69f67c" + version = "2017.07.27" + +[[projects]] + name = "github.com/client9/misspell" + packages = [ + ".", + "cmd/misspell", + ] + revision = "59894abde931a32630d4e884a09c682ed20c5c7c" + version = "v0.3.0" + +[[projects]] + name = "github.com/cockroachdb/apd" + packages = ["."] + revision = "b1ce49cb2a474f4416531e7395373eaafaa4fbe2" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/cockroachdb/cmux" + packages = ["."] + revision = "30d10be492927e2dcae0089c374c455d42414fcb" + +[[projects]] + branch = "master" + name = "github.com/cockroachdb/cockroach-go" + packages = ["crdb"] + revision = "59c0560478b705bf9bd12f9252224a0fad7c87df" + +[[projects]] + branch = "master" + name = "github.com/cockroachdb/crlfmt" + packages = ["."] + revision = "5895607e5ea790fcbb640260129a12d277b34e46" + +[[projects]] + branch = "master" + name = "github.com/cockroachdb/returncheck" + packages = ["."] + revision = "e91bb28baf9de4a530d3ae7f041953b23dcce9be" + +[[projects]] + branch = "master" + name = "github.com/cockroachdb/stress" + packages = ["."] + revision = "29b5d31b4c3a949cb3a726750bc34c4d58ec15e8" + +[[projects]] + branch = "master" + name = "github.com/cockroachdb/ttycolor" + packages = ["."] + revision = "5bed2b5a875c88a9d87d0f12b21ba156e2f995f7" + +[[projects]] + branch = "master" + name = "github.com/codahale/hdrhistogram" + packages = ["."] + revision = "3a0bb77429bd3a61596f5e8a3172445844342120" + +[[projects]] + branch = "master" + name = "github.com/coreos/etcd" + packages = [ + "raft", + "raft/raftpb", + ] + revision = "ce0ad377d21819592c3d8c29417d9d7a5ac53f2f" + +[[projects]] + name = "github.com/cpuguy83/go-md2man" + packages = ["md2man"] + revision = "1d903dcb749992f3741d744c0f8376b4bd7eb3e1" + version = "v1.0.7" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/dgrijalva/jwt-go" + packages = ["."] + revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29" + version = "v3.1.0" + +[[projects]] + branch = "master" + name = "github.com/dgryski/go-metro" + packages = ["."] + revision = "280f6062b5bc97ee9b9afe7f2ccb361e59845baa" + +[[projects]] + branch = "master" + name = "github.com/docker/distribution" + packages = [ + "digestset", + "reference", + ] + revision = "3800056b8832cf6075e78b282ac010131d8687bc" + +[[projects]] + branch = "master" + name = "github.com/docker/docker" + packages = [ + "api", + "api/types", + "api/types/blkiodev", + "api/types/container", + "api/types/events", + "api/types/filters", + "api/types/image", + "api/types/mount", + "api/types/network", + "api/types/registry", + "api/types/strslice", + "api/types/swarm", + "api/types/swarm/runtime", + "api/types/time", + "api/types/versions", + "api/types/volume", + "client", + "pkg/jsonmessage", + "pkg/stdcopy", + "pkg/term", + "pkg/term/windows", + ] + revision = "3ab20a87fa10360df891a67b8307399cdf1ab429" + +[[projects]] + name = "github.com/docker/go-connections" + packages = [ + "nat", + "sockets", + "tlsconfig", + ] + revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d" + version = "v0.3.0" + +[[projects]] + name = "github.com/docker/go-units" + packages = ["."] + revision = "0dadbb0345b35ec7ef35e228dabb8de89a65bf52" + version = "v0.3.2" + +[[projects]] + branch = "master" + name = "github.com/dustin/go-humanize" + packages = ["."] + revision = "77ed807830b4df581417e7f89eb81d4872832b72" + +[[projects]] + name = "github.com/eapache/go-resiliency" + packages = ["breaker"] + revision = "6800482f2c813e689c88b7ed3282262385011890" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/eapache/go-xerial-snappy" + packages = ["."] + revision = "bb955e01b9346ac19dc29eb16586c90ded99a98c" + +[[projects]] + name = "github.com/eapache/queue" + packages = ["."] + revision = "ded5959c0d4e360646dc9e9908cff48666781367" + version = "v1.0.2" + +[[projects]] + name = "github.com/elastic/gosigar" + packages = [ + ".", + "sys/windows", + ] + revision = "306d51981789ccc65e5f1431d5c0d78d8c368f1b" + version = "v0.5.0" + +[[projects]] + name = "github.com/elazarl/go-bindata-assetfs" + packages = ["."] + revision = "30f82fa23fd844bd5bb1e5f216db87fd77b5eb43" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/facebookgo/clock" + packages = ["."] + revision = "600d898af40aa09a7a93ecb9265d87b0504b6f03" + +[[projects]] + branch = "master" + name = "github.com/getsentry/raven-go" + packages = ["."] + revision = "221b2b44fb33f84ed3ea13f3aed62ff48c85636b" + source = "https://github.com/cockroachdb/raven-go" + +[[projects]] + branch = "master" + name = "github.com/ghemawat/stream" + packages = ["."] + revision = "78e682abcae4f96ac7ddbe39912967a5f7cbbaa6" + +[[projects]] + name = "github.com/go-ini/ini" + packages = ["."] + revision = "f280b3ba517bf5fc98922624f21fb0e7a92adaec" + version = "v1.30.3" + +[[projects]] + name = "github.com/go-logfmt/logfmt" + packages = ["."] + revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" + version = "v0.3.0" + +[[projects]] + name = "github.com/go-ole/go-ole" + packages = [ + ".", + "oleutil", + ] + revision = "a41e3c4b706f6ae8dfbff342b06e40fa4d2d0506" + version = "v1.2.1" + +[[projects]] + branch = "master" + name = "github.com/go-sql-driver/mysql" + packages = ["."] + revision = "fade21009797158e7b79e04c340118a9220c6f9e" + +[[projects]] + branch = "v2" + name = "github.com/go-yaml/yaml" + packages = ["."] + revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f" + +[[projects]] + name = "github.com/gogo/protobuf" + packages = [ + "gogoproto", + "jsonpb", + "plugin/compare", + "plugin/defaultcheck", + "plugin/description", + "plugin/embedcheck", + "plugin/enumstringer", + "plugin/equal", + "plugin/face", + "plugin/gostring", + "plugin/marshalto", + "plugin/oneofcheck", + "plugin/populate", + "plugin/size", + "plugin/stringer", + "plugin/testgen", + "plugin/union", + "plugin/unmarshal", + "proto", + "protoc-gen-gogo/descriptor", + "protoc-gen-gogo/generator", + "protoc-gen-gogo/grpc", + "protoc-gen-gogo/plugin", + "sortkeys", + "types", + "vanity", + "vanity/command", + ] + revision = "1adfc126b41513cc696b209667c8656ea7aac67c" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/golang-commonmark/markdown" + packages = [ + ".", + "byteutil", + "html", + "linkify", + ] + revision = "11a7a839e723aa293cccdc353b394dbfce7c131e" + +[[projects]] + name = "github.com/golang/dep" + packages = [ + ".", + "cmd/dep", + "gps", + "gps/internal/pb", + "gps/paths", + "gps/pkgtree", + "internal/feedback", + "internal/fs", + "internal/importers", + "internal/importers/base", + "internal/importers/glide", + "internal/importers/glock", + "internal/importers/godep", + "internal/importers/govend", + "internal/importers/govendor", + "internal/importers/gvt", + "internal/importers/vndr", + ] + revision = "37d9ea0ac16f0e0a05afc3b60e1ac8c364b6c329" + version = "v0.4.1" + +[[projects]] + branch = "master" + name = "github.com/golang/glog" + packages = ["."] + revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" + +[[projects]] + branch = "master" + name = "github.com/golang/leveldb" + packages = [ + "crc", + "db", + "memfs", + "table", + ] + revision = "259d9253d71996b7778a3efb4144fe4892342b18" + +[[projects]] + branch = "master" + name = "github.com/golang/lint" + packages = [ + ".", + "golint", + ] + revision = "6aaf7c34af0f4c36a57e0c429bace4d706d8e931" + +[[projects]] + branch = "master" + name = "github.com/golang/protobuf" + packages = [ + "jsonpb", + "proto", + "protoc-gen-go/descriptor", + "protoc-gen-go/generator", + "protoc-gen-go/generator/internal/remap", + "protoc-gen-go/plugin", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/struct", + "ptypes/timestamp", + ] + revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "553a641470496b2327abcac10b36396bd98e45c9" + +[[projects]] + branch = "master" + name = "github.com/google/btree" + packages = ["."] + revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4" + +[[projects]] + name = "github.com/google/go-github" + packages = ["github"] + revision = "e48060a28fac52d0f1cb758bc8b87c07bac4a87d" + version = "v15.0.0" + +[[projects]] + branch = "master" + name = "github.com/google/go-querystring" + packages = ["query"] + revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a" + +[[projects]] + branch = "master" + name = "github.com/google/pprof" + packages = [ + ".", + "driver", + "internal/binutils", + "internal/driver", + "internal/elfexec", + "internal/graph", + "internal/measurement", + "internal/plugin", + "internal/report", + "internal/symbolizer", + "internal/symbolz", + "profile", + "third_party/d3", + "third_party/d3flamegraph", + "third_party/d3tip", + "third_party/svgpan", + ] + revision = "60840899638bfaf3fd6f2b17b9785f1dac67a4a4" + +[[projects]] + name = "github.com/googleapis/gax-go" + packages = ["."] + revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f" + version = "v2.0.0" + +[[projects]] + name = "github.com/gorilla/websocket" + packages = ["."] + revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b" + version = "v1.2.0" + +[[projects]] + name = "github.com/grpc-ecosystem/grpc-gateway" + packages = [ + "protoc-gen-grpc-gateway", + "protoc-gen-grpc-gateway/descriptor", + "protoc-gen-grpc-gateway/generator", + "protoc-gen-grpc-gateway/gengateway", + "protoc-gen-grpc-gateway/httprule", + "runtime", + "runtime/internal", + "utilities", + ] + revision = "07f5e79768022f9a3265235f0db4ac8c3f675fec" + version = "v1.3.1" + +[[projects]] + branch = "master" + name = "github.com/grpc-ecosystem/grpc-opentracing" + packages = ["go/otgrpc"] + revision = "a570af39704b9f3d4bb530d83192a99ea6337d5a" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/go-version" + packages = ["."] + revision = "fc61389e27c71d120f87031ca8c88a3428f372dd" + +[[projects]] + branch = "master" + name = "github.com/ianlancetaylor/cgosymbolizer" + packages = ["."] + revision = "f5072df9c550dc687157e5d7efb50825cdf8f0eb" + +[[projects]] + branch = "master" + name = "github.com/ianlancetaylor/demangle" + packages = ["."] + revision = "4883227f66371e02c4948937d3e2be1664d9be38" + +[[projects]] + name = "github.com/inconshreveable/mousetrap" + packages = ["."] + revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" + version = "v1.0" + +[[projects]] + name = "github.com/jackc/pgx" + packages = [ + ".", + "chunkreader", + "internal/sanitize", + "pgio", + "pgproto3", + "pgtype", + ] + revision = "da3231b0b66e2e74cdb779f1d46c5e958ba8be27" + version = "v3.1.0" + +[[projects]] + name = "github.com/jmank88/nuts" + packages = ["."] + revision = "8b28145dffc87104e66d074f62ea8080edfad7c8" + version = "v0.3.0" + +[[projects]] + name = "github.com/jmespath/go-jmespath" + packages = ["."] + revision = "0b12d6b5" + +[[projects]] + branch = "master" + name = "github.com/jteeuwen/go-bindata" + packages = [ + ".", + "go-bindata", + ] + revision = "6b667f85196e80d8420d634ca3fecca389a53207" + source = "https://github.com/dim13/go-bindata" + +[[projects]] + branch = "master" + name = "github.com/kisielk/errcheck" + packages = [ + ".", + "internal/errcheck", + ] + revision = "b1445a9dd8285a50c6d1661d16f0a9ceb08125f7" + +[[projects]] + branch = "master" + name = "github.com/kisielk/gotool" + packages = [ + ".", + "internal/load", + ] + revision = "d6ce6262d87e3a4e153e86023ff56ae771554a41" + +[[projects]] + name = "github.com/knz/go-libedit" + packages = [ + ".", + "common", + "other", + "unix", + "unix/sigtramp", + ] + revision = "69b759d6ff84df6bbd39846dae3670625cc0361b" + version = "v1.7" + +[[projects]] + branch = "master" + name = "github.com/knz/strtime" + packages = ["."] + revision = "813725a7c183ac304d1ed8fb7e37a567733e9c05" + +[[projects]] + branch = "master" + name = "github.com/kr/logfmt" + packages = ["."] + revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" + +[[projects]] + branch = "master" + name = "github.com/kr/pretty" + packages = ["."] + revision = "cfb55aafdaf3ec08f0db22699ab822c50091b1c4" + +[[projects]] + branch = "master" + name = "github.com/kr/text" + packages = ["."] + revision = "7cafcd837844e784b526369c9bce262804aebc60" + +[[projects]] + branch = "master" + name = "github.com/lib/pq" + packages = [ + ".", + "oid", + ] + revision = "27ea5d92de30060e7121ddd543fe14e9a327e0cc" + +[[projects]] + name = "github.com/lightstep/lightstep-tracer-go" + packages = [ + ".", + "collectorpb", + "lightstep_thrift", + "lightsteppb", + "thrift_0_9_2/lib/go/thrift", + ] + revision = "ba38bae1f0ec1ece9092d35bbecbb497ee344cbc" + version = "v0.15.0" + +[[projects]] + name = "github.com/marstr/guid" + packages = ["."] + revision = "8bd9a64bf37eb297b492a4101fb28e80ac0b290f" + version = "v1.1.0" + +[[projects]] + name = "github.com/marusama/semaphore" + packages = ["."] + revision = "567f17206eaa3f28bd73e209620e2abaa65d7405" + version = "2.1.1" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + name = "github.com/mattn/go-runewidth" + packages = ["."] + revision = "9e777a8366cce605130a531d2cd6363d07ad7317" + version = "v0.0.2" + +[[projects]] + name = "github.com/mattn/goveralls" + packages = ["."] + revision = "b71a1e4855f87991aff01c2c833a75a07059c61c" + version = "v0.0.2" + +[[projects]] + name = "github.com/matttproud/golang_protobuf_extensions" + packages = ["pbutil"] + revision = "3247c84500bff8d9fb6d579d800f20b3e091582c" + version = "v1.0.0" + +[[projects]] + name = "github.com/mibk/dupl" + packages = [ + ".", + "job", + "output", + "suffixtree", + "syntax", + "syntax/golang", + ] + revision = "f008fcf5e62793d38bda510ee37aab8b0c68e76c" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/mitchellh/reflectwalk" + packages = ["."] + revision = "63d60e9d0dbc60cf9164e6510889b0db6683d98c" + +[[projects]] + branch = "master" + name = "github.com/montanaflynn/stats" + packages = ["."] + revision = "72625ec1691e40181ac5282a7f2ca4745952a7a7" + +[[projects]] + branch = "master" + name = "github.com/nightlyone/lockfile" + packages = ["."] + revision = "6a197d5ea61168f2ac821de2b7f011b250904900" + +[[projects]] + name = "github.com/nlopes/slack" + packages = ["."] + revision = "8ab4d0b364ef1e9af5d102531da20d5ec902b6c4" + version = "v0.2.0" + +[[projects]] + branch = "master" + name = "github.com/olekukonko/tablewriter" + packages = ["."] + revision = "b8a9be070da40449e501c3c4730a889e42d87a9e" + +[[projects]] + name = "github.com/opencontainers/go-digest" + packages = ["."] + revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf" + version = "v1.0.0-rc1" + +[[projects]] + name = "github.com/opencontainers/image-spec" + packages = [ + "specs-go", + "specs-go/v1", + ] + revision = "ab7389ef9f50030c9b245bc16b981c7ddf192882" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/opennota/urlesc" + packages = ["."] + revision = "de5bf2ad457846296e2031421a34e2568e304e35" + +[[projects]] + branch = "master" + name = "github.com/opentracing-contrib/go-observer" + packages = ["."] + revision = "a52f2342449246d5bcc273e65cbdcfa5f7d6c63c" + +[[projects]] + name = "github.com/opentracing/opentracing-go" + packages = [ + ".", + "ext", + "log", + ] + revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38" + version = "v1.0.2" + +[[projects]] + name = "github.com/openzipkin/zipkin-go-opentracing" + packages = [ + ".", + "flag", + "thrift/gen-go/scribe", + "thrift/gen-go/zipkincore", + "types", + "wire", + ] + revision = "45e90b00710a4c34a1a7d8a78d90f9b010b0bd4d" + version = "v0.3.2" + +[[projects]] + branch = "master" + name = "github.com/pelletier/go-toml" + packages = ["."] + revision = "05bcc0fb0d3e60da4b8dd5bd7e0ea563eb4ca943" + +[[projects]] + branch = "master" + name = "github.com/petar/GoLLRB" + packages = ["llrb"] + revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" + +[[projects]] + branch = "master" + name = "github.com/petermattis/goid" + packages = ["."] + revision = "b0b1615b78e5ee59739545bb38426383b2cda4c9" + +[[projects]] + name = "github.com/pierrec/lz4" + packages = ["."] + revision = "08c27939df1bd95e881e2c2367a749964ad1fceb" + version = "v1.0.1" + +[[projects]] + name = "github.com/pierrec/xxHash" + packages = ["xxHash32"] + revision = "f051bb7f1d1aaf1b5a665d74fb6b0217712c69f7" + version = "v0.1.1" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/prometheus/client_golang" + packages = [ + "prometheus", + "prometheus/graphite", + ] + revision = "967789050ba94deca04a5e84cce8ad472ce313c1" + version = "v0.9.0-pre1" + +[[projects]] + branch = "master" + name = "github.com/prometheus/client_model" + packages = ["go"] + revision = "6f3806018612930941127f2a7c6c453ba2c527d2" + +[[projects]] + branch = "master" + name = "github.com/prometheus/common" + packages = [ + "expfmt", + "internal/bitbucket.org/ww/goautoneg", + "model", + ] + revision = "1bab55dd05dbff384524a6a1c99006d9eb5f139b" + +[[projects]] + branch = "master" + name = "github.com/prometheus/procfs" + packages = [ + ".", + "internal/util", + "nfs", + "xfs", + ] + revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e" + +[[projects]] + branch = "master" + name = "github.com/rcrowley/go-metrics" + packages = [ + ".", + "exp", + ] + revision = "1f30fe9094a513ce4c700b9a54458bbb0c96996c" + +[[projects]] + branch = "master" + name = "github.com/rubyist/circuitbreaker" + packages = ["."] + revision = "2074adba5ddc7d5f7559448a9c3066573521c5bf" + +[[projects]] + name = "github.com/russross/blackfriday" + packages = ["."] + revision = "4048872b16cc0fc2c5fd9eacf0ed2c2fedaa0c8c" + version = "v1.5" + +[[projects]] + name = "github.com/sasha-s/go-deadlock" + packages = ["."] + revision = "03d40e5dbd5488667a13b3c2600b2f7c2886f02f" + version = "v0.2.0" + +[[projects]] + name = "github.com/satori/go.uuid" + packages = ["."] + revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3" + version = "v1.2.0" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/constext" + packages = ["."] + revision = "836a144573533ea4da4e6929c235fd348aed1c80" + +[[projects]] + name = "github.com/sirupsen/logrus" + packages = ["."] + revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e" + version = "v1.0.3" + +[[projects]] + name = "github.com/spf13/cobra" + packages = [ + ".", + "doc", + ] + revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" + version = "v0.0.1" + +[[projects]] + name = "github.com/spf13/pflag" + packages = ["."] + revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require", + ] + revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0" + version = "v1.1.4" + +[[projects]] + branch = "master" + name = "github.com/wadey/gocovmerge" + packages = ["."] + revision = "b5bfa59ec0adc420475f97f89b58045c721d761c" + +[[projects]] + branch = "master" + name = "github.com/xwb1989/sqlparser" + packages = [ + ".", + "dependency/bytes2", + "dependency/hack", + "dependency/querypb", + "dependency/sqltypes", + ] + revision = "6aff8615a33faf1f260a3a8f800456511505d5fd" + source = "https://github.com/dt/sqlparser" + +[[projects]] + name = "go.opencensus.io" + packages = [ + "exporter/stackdriver/propagation", + "internal", + "internal/tagencoding", + "plugin/ochttp", + "plugin/ochttp/propagation/b3", + "stats", + "stats/internal", + "stats/view", + "tag", + "trace", + "trace/internal", + "trace/propagation", + ] + revision = "0095aec66ae14801c6711210f6f0716411cefdd3" + version = "v0.8.0" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "bcrypt", + "blowfish", + "ssh/terminal", + ] + revision = "bd6f299fb381e4c3393d1c4b1f0b94f5e77650c8" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "context/ctxhttp", + "html", + "html/atom", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "lex/httplex", + "proxy", + "trace", + ] + revision = "c73622c77280266305273cb545f54516ced95b93" + +[[projects]] + branch = "master" + name = "golang.org/x/oauth2" + packages = [ + ".", + "google", + "internal", + "jws", + "jwt", + ] + revision = "6881fee410a5daf86371371f9ad451b95e168b71" + +[[projects]] + branch = "master" + name = "golang.org/x/perf" + packages = [ + "benchstat", + "cmd/benchstat", + "internal/stats", + "storage", + "storage/benchfmt", + ] + revision = "4469e6ce8cc3920f1b42128b9d557bea2e08621a" + +[[projects]] + branch = "master" + name = "golang.org/x/sync" + packages = [ + "errgroup", + "syncmap", + ] + revision = "8e0aa688b654ef28caa72506fa5ec8dba9fc7690" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = [ + "unix", + "windows", + ] + revision = "95c6576299259db960f6c5b9b69ea52422860fce" + +[[projects]] + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + ] + revision = "470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4" + +[[projects]] + branch = "master" + name = "golang.org/x/time" + packages = ["rate"] + revision = "6dc17368e09b0e8634d71cac8168d853e869a0c7" + +[[projects]] + branch = "master" + name = "golang.org/x/tools" + packages = [ + "cmd/goimports", + "cmd/goyacc", + "cmd/stringer", + "container/intsets", + "cover", + "go/ast/astutil", + "go/buildutil", + "go/gcexportdata", + "go/gcimporter15", + "go/loader", + "go/types/typeutil", + "imports", + ] + revision = "90b807ada4cc7ab5d1409d637b1f3beb5a776be7" + +[[projects]] + branch = "master" + name = "google.golang.org/api" + packages = [ + "gensupport", + "googleapi", + "googleapi/internal/uritemplates", + "googleapi/transport", + "internal", + "iterator", + "option", + "storage/v1", + "transport/http", + ] + revision = "9c79deebf7496e355d7e95d82d4af1fe4e769b2f" + +[[projects]] + name = "google.golang.org/appengine" + packages = [ + ".", + "internal", + "internal/app_identity", + "internal/base", + "internal/datastore", + "internal/log", + "internal/modules", + "internal/remote_api", + "internal/urlfetch", + "urlfetch", + ] + revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "google.golang.org/genproto" + packages = [ + "googleapis/api/annotations", + "googleapis/iam/v1", + "googleapis/rpc/code", + "googleapis/rpc/status", + ] + revision = "f676e0f3ac6395ff1a529ae59a6670878a8371a6" + +[[projects]] + branch = "master" + name = "google.golang.org/grpc" + packages = [ + ".", + "balancer", + "balancer/base", + "balancer/roundrobin", + "channelz", + "codes", + "connectivity", + "credentials", + "encoding", + "encoding/proto", + "grpclb/grpc_lb_v1/messages", + "grpclog", + "health/grpc_health_v1", + "internal", + "keepalive", + "metadata", + "naming", + "peer", + "resolver", + "resolver/dns", + "resolver/passthrough", + "stats", + "status", + "tap", + "transport", + ] + revision = "8f06f82ca394b1ac837d4b0c0cfa07188b0e9dee" + +[[projects]] + branch = "v2" + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "287cf08546ab5e7e37d55a84f7ed3fd1db036de5" + +[[projects]] + name = "honnef.co/go/tools" + packages = [ + "callgraph", + "callgraph/static", + "deprecated", + "functions", + "internal/sharedcheck", + "lint", + "simple", + "ssa", + "ssa/ssautil", + "staticcheck", + "staticcheck/vrp", + "unused", + ] + revision = "d73ab98e7c39fdcf9ba65062e43d34310f198353" + version = "2017.2.2" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "8022836223059aead87f6d7d6b9451a5d7ad8a20f4358cb709ccf2859f9c74ce" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/spec/fixtures/go/gopkg_locks/custom_source.lock b/spec/fixtures/go/gopkg_locks/custom_source.lock new file mode 100644 index 00000000000..8d026e4e5fe --- /dev/null +++ b/spec/fixtures/go/gopkg_locks/custom_source.lock @@ -0,0 +1,22 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/bsm/ratelimit" + packages = ["."] + revision = "4a38dca83ebadb017e83301642fab61b1c17edb7" + version = "v2.0.0" + +[[projects]] + branch = "master" + name = "github.com/some/thing" + packages = ["."] + revision = "0b96aaa707760d6ab28d9b9d1913ff5993328bae" + source = "https://github.com/dgrijalva/jwt-go" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "677a622bfbc921ebb12df377c21012ff65974214b5d13a8fe77b2156c8d2f832" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/spec/fixtures/go/gopkg_locks/fider.lock b/spec/fixtures/go/gopkg_locks/fider.lock new file mode 100644 index 00000000000..3e1ec9742b6 --- /dev/null +++ b/spec/fixtures/go/gopkg_locks/fider.lock @@ -0,0 +1,136 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "cloud.google.com/go" + packages = ["compute/metadata"] + revision = "5a9e19d4e1e41a734154e44a2132b358afb49a03" + version = "v0.13.0" + +[[projects]] + name = "github.com/dgrijalva/jwt-go" + packages = ["."] + revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" + version = "v3.2.0" + +[[projects]] + branch = "master" + name = "github.com/goenning/letteravatar" + packages = ["."] + revision = "553181ed4055278e356ce21812adb34ae487f88e" + +[[projects]] + branch = "master" + name = "github.com/golang/freetype" + packages = [ + ".", + "raster", + "truetype" + ] + revision = "e2365dfdc4a05e4b8299a783240d4a7d5a65d4e4" + +[[projects]] + branch = "master" + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "ae59567b9aab61b50b2590679a62c3c044030b61" + +[[projects]] + name = "github.com/gosimple/slug" + packages = ["."] + revision = "e9f42fa127660e552d0ad2b589868d403a9be7c6" + version = "v1.1.1" + +[[projects]] + branch = "master" + name = "github.com/julienschmidt/httprouter" + packages = ["."] + revision = "adbc77eec0d91467376ca515bc3a14b8434d0f18" + +[[projects]] + branch = "master" + name = "github.com/lib/pq" + packages = [ + ".", + "oid" + ] + revision = "90697d60dd844d5ef6ff15135d0203f65d2f53b8" + +[[projects]] + branch = "master" + name = "github.com/rainycape/unidecode" + packages = ["."] + revision = "cb7f23ec59bec0d61b19c56cd88cee3d0cc1870c" + +[[projects]] + name = "github.com/russross/blackfriday" + packages = ["."] + revision = "55d61fa8aa702f59229e6cff85793c22e580eaf5" + version = "v1.5.1" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "acme", + "acme/autocert" + ] + revision = "2c241ca3045ddc354463c376a9515d9f1f1390a4" + +[[projects]] + branch = "master" + name = "golang.org/x/image" + packages = [ + "draw", + "font", + "math/f64", + "math/fixed" + ] + revision = "e20db36d77bd0cb36cea8fe49d5c37d82d21591f" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "context/ctxhttp" + ] + revision = "8351a756f30f1297fe94bbf4b767ec589c6ea6d0" + +[[projects]] + branch = "master" + name = "golang.org/x/oauth2" + packages = [ + ".", + "facebook", + "github", + "google", + "internal", + "jws", + "jwt" + ] + revision = "ef147856a6ddbb60760db74283d2424e98c87bff" + +[[projects]] + name = "google.golang.org/appengine" + packages = [ + ".", + "internal", + "internal/app_identity", + "internal/base", + "internal/datastore", + "internal/log", + "internal/modules", + "internal/remote_api", + "internal/urlfetch", + "urlfetch" + ] + revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "01ff2ef749623d2bc5d0d46238992ffb3385f10d53ff2345ef6898b29fbb4bfd" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/spec/fixtures/go/gopkg_locks/flagr.lock b/spec/fixtures/go/gopkg_locks/flagr.lock new file mode 100644 index 00000000000..a938ccf8e14 --- /dev/null +++ b/spec/fixtures/go/gopkg_locks/flagr.lock @@ -0,0 +1,434 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/DataDog/datadog-go" + packages = ["statsd"] + revision = "e67964b4021ad3a334e748e8811eb3cd6becbc6e" + version = "2.1.0" + +[[projects]] + name = "github.com/PuerkitoBio/purell" + packages = ["."] + revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/PuerkitoBio/urlesc" + packages = ["."] + revision = "de5bf2ad457846296e2031421a34e2568e304e35" + +[[projects]] + name = "github.com/Shopify/sarama" + packages = ["."] + revision = "35324cf48e33d8260e1c7c18854465a904ade249" + version = "v1.17.0" + +[[projects]] + name = "github.com/asaskevich/govalidator" + packages = ["."] + revision = "ccb8e960c48f04d6935e72476ae4a51028f9e22f" + version = "v9" + +[[projects]] + branch = "master" + name = "github.com/auth0/go-jwt-middleware" + packages = ["."] + revision = "5493cabe49f7bfa6e2ec444a09d334d90cd4e2bd" + +[[projects]] + branch = "master" + name = "github.com/bouk/monkey" + packages = ["."] + revision = "5df1f207ff77e025801505ae4d903133a0b4353f" + +[[projects]] + branch = "master" + name = "github.com/brandur/simplebox" + packages = ["."] + revision = "84e9865bb03ad38c464043bf5382ce8c68ca5f0c" + +[[projects]] + name = "github.com/bsm/ratelimit" + packages = ["."] + revision = "4a38dca83ebadb017e83301642fab61b1c17edb7" + version = "v2.0.0" + +[[projects]] + name = "github.com/caarlos0/env" + packages = ["."] + revision = "1cddc31c48c56ecd700d873edb9fd5b6f5df922a" + version = "v3.3.0" + +[[projects]] + name = "github.com/certifi/gocertifi" + packages = ["."] + revision = "deb3ae2ef2610fde3330947281941c562861188b" + version = "2018.01.18" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/dgrijalva/jwt-go" + packages = ["."] + revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" + version = "v3.2.0" + +[[projects]] + name = "github.com/docker/go-units" + packages = ["."] + revision = "47565b4f722fb6ceae66b95f853feed578a4a51c" + version = "v0.3.3" + +[[projects]] + name = "github.com/eapache/go-resiliency" + packages = ["breaker"] + revision = "ea41b0fad31007accc7f806884dcdf3da98b79ce" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/eapache/go-xerial-snappy" + packages = ["."] + revision = "bb955e01b9346ac19dc29eb16586c90ded99a98c" + +[[projects]] + name = "github.com/eapache/queue" + packages = ["."] + revision = "44cc805cf13205b55f69e14bcb69867d1ae92f98" + version = "v1.1.0" + +[[projects]] + name = "github.com/evalphobia/logrus_sentry" + packages = ["."] + revision = "b78b27461c8163c45abf4ab3a8330d2b1ee9456a" + version = "v0.4.6" + +[[projects]] + branch = "master" + name = "github.com/getsentry/raven-go" + packages = ["."] + revision = "ed7bcb39ff10f39ab08e317ce16df282845852fa" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/analysis" + packages = ["."] + revision = "5957818e100395077187fb7ef3b8a28227af06c6" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/errors" + packages = ["."] + revision = "b2b2befaf267d082d779bcef52d682a47c779517" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/jsonpointer" + packages = ["."] + revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/jsonreference" + packages = ["."] + revision = "3fb327e6747da3043567ee86abd02bb6376b6be2" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/loads" + packages = ["."] + revision = "2a2b323bab96e6b1fdee110e57d959322446e9c9" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/runtime" + packages = [ + ".", + "flagext", + "logger", + "middleware", + "middleware/denco", + "middleware/header", + "middleware/untyped", + "security" + ] + revision = "90c7afbb4bd8b22431e1c32d65caf405abf170c3" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/spec" + packages = ["."] + revision = "bcff419492eeeb01f76e77d2ebc714dc97b607f5" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/strfmt" + packages = ["."] + revision = "481808443b00a14745fada967cb5eeff0f9b1df2" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/swag" + packages = ["."] + revision = "811b1089cde9dad18d4d0c2d09fbdbf28dbd27a5" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/validate" + packages = ["."] + revision = "b0a3ed684d0fdd3e1eda00433382188ce8aa7169" + +[[projects]] + name = "github.com/go-sql-driver/mysql" + packages = ["."] + revision = "d523deb1b23d913de5bdada721a6071e71283618" + version = "v1.4.0" + +[[projects]] + branch = "master" + name = "github.com/gohttp/pprof" + packages = ["."] + revision = "c9d246cbb3ba6407f8b1decdfff558f0fe8f07e8" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" + +[[projects]] + name = "github.com/jessevdk/go-flags" + packages = ["."] + revision = "c6ca198ec95c841fdb89fc0de7496fed11ab854e" + version = "v1.4.0" + +[[projects]] + name = "github.com/jinzhu/gorm" + packages = [ + ".", + "dialects/mysql", + "dialects/postgres", + "dialects/sqlite" + ] + revision = "6ed508ec6a4ecb3531899a69cbc746ccf65a4166" + version = "v1.9.1" + +[[projects]] + branch = "master" + name = "github.com/jinzhu/inflection" + packages = ["."] + revision = "04140366298a54a039076d798123ffa108fff46c" + +[[projects]] + branch = "master" + name = "github.com/lib/pq" + packages = [ + ".", + "hstore", + "oid" + ] + revision = "90697d60dd844d5ef6ff15135d0203f65d2f53b8" + +[[projects]] + branch = "master" + name = "github.com/mailru/easyjson" + packages = [ + "buffer", + "jlexer", + "jwriter" + ] + revision = "3fdea8d05856a0c8df22ed4bc71b3219245e4485" + +[[projects]] + name = "github.com/mattn/go-sqlite3" + packages = ["."] + revision = "25ecb14adfc7543176f7d85291ec7dba82c6f7e4" + version = "v1.9.0" + +[[projects]] + branch = "master" + name = "github.com/meatballhat/negroni-logrus" + packages = ["."] + revision = "31067281800f66f57548a7a32d9c6c5f963fef83" + +[[projects]] + branch = "master" + name = "github.com/mitchellh/mapstructure" + packages = ["."] + revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b" + +[[projects]] + name = "github.com/newrelic/go-agent" + packages = [ + ".", + "internal", + "internal/cat", + "internal/jsonx", + "internal/logger", + "internal/sysinfo", + "internal/utilization" + ] + revision = "a5d75f2b4787aa1bbc76688187b2353f8ff581a6" + version = "v2.0.0" + +[[projects]] + name = "github.com/pierrec/lz4" + packages = [ + ".", + "internal/xxh32" + ] + revision = "6b9367c9ff401dbc54fabce3fb8d972e799b702d" + version = "v2.0.2" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/prashantv/gostub" + packages = ["."] + revision = "5c68b99bb08825598e70739c40603c901ee58dba" + +[[projects]] + branch = "master" + name = "github.com/rcrowley/go-metrics" + packages = ["."] + revision = "e2704e165165ec55d062f5919b4b29494e9fa790" + +[[projects]] + name = "github.com/rs/cors" + packages = ["."] + revision = "ca016a06a5753f8ba03029c0aa5e54afb1bf713f" + version = "v1.4.0" + +[[projects]] + name = "github.com/sirupsen/logrus" + packages = ["."] + revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" + version = "v1.0.5" + +[[projects]] + name = "github.com/spf13/cast" + packages = ["."] + revision = "8965335b8c7107321228e3e3702cab9832751bac" + version = "v1.2.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = ["assert"] + revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" + version = "v1.2.2" + +[[projects]] + name = "github.com/urfave/negroni" + packages = ["."] + revision = "5dbbc83f748fc3ad38585842b0aedab546d0ea1e" + version = "v0.3.0" + +[[projects]] + branch = "master" + name = "github.com/yadvendar/negroni-newrelic-go-agent" + packages = ["."] + revision = "3dc58758cb67abc45ae91e8e7bb3d90bdc254dfb" + +[[projects]] + branch = "master" + name = "github.com/zhouzhuojie/conditions" + packages = ["."] + revision = "34882afc2ef77651b9e10ec8148ac7f95887f822" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "internal/subtle", + "nacl/secretbox", + "poly1305", + "salsa20/salsa", + "ssh/terminal" + ] + revision = "027cca12c2d63e3d62b670d901e8a2c95854feec" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "idna", + "netutil" + ] + revision = "db08ff08e8622530d9ed3a0e8ac279f6d4c02196" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = [ + "unix", + "windows" + ] + revision = "6c888cc515d3ed83fc103cf1d84468aad274b0a7" + +[[projects]] + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + "width" + ] + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + name = "google.golang.org/appengine" + packages = ["cloudsql"] + revision = "b1f26356af11148e710935ed1ac8a7f5702c7612" + version = "v1.1.0" + +[[projects]] + branch = "v2" + name = "gopkg.in/mgo.v2" + packages = [ + "bson", + "internal/json" + ] + revision = "3f83fa5005286a7fe593b055f0d7771a7dce4655" + +[[projects]] + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" + version = "v2.2.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "a462c9ef93c43ec0d3e02c3a988cef9a4b411d5db504c79ed6372a23724c2124" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/spec/fixtures/go/gopkg_locks/no_version.lock b/spec/fixtures/go/gopkg_locks/no_version.lock new file mode 100644 index 00000000000..918ff4ebdb5 --- /dev/null +++ b/spec/fixtures/go/gopkg_locks/no_version.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/dgrijalva/jwt-go" + packages = ["."] + revision = "fbcb3e4b637bdc5ef2257eb2d0fe1d914a499386" + version = "v1.0.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "eb62c15704b851f8626abe61ac342d43a2d3522af64b9c8aa89748486e3325cc" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/spec/fixtures/go/gopkg_locks/tag_as_revision.lock b/spec/fixtures/go/gopkg_locks/tag_as_revision.lock new file mode 100644 index 00000000000..f7ba7ae3ae3 --- /dev/null +++ b/spec/fixtures/go/gopkg_locks/tag_as_revision.lock @@ -0,0 +1,27 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "golang.org/x/text" + packages = [ + ".", + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "transform", + "unicode/cldr", + "unicode/norm" + ] + revision = "v0.2.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "2405704ac7a0b793021a0a72d2ff705b4a2c503b07b1e50382eecf14e46f2012" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/spec/fixtures/go/gopkg_locks/unknown_source.lock b/spec/fixtures/go/gopkg_locks/unknown_source.lock new file mode 100644 index 00000000000..f05d88813d7 --- /dev/null +++ b/spec/fixtures/go/gopkg_locks/unknown_source.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "unknownhost.com/dgrijalva/jwt-go" + packages = ["."] + revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" + version = "v3.2.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "01ff2ef749623d2bc5d0d46238992ffb3385f10d53ff2345ef6898b29fbb4bfd" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/spec/fixtures/go/gopkg_tomls/bare_version.toml b/spec/fixtures/go/gopkg_tomls/bare_version.toml new file mode 100644 index 00000000000..d7be5f37cec --- /dev/null +++ b/spec/fixtures/go/gopkg_tomls/bare_version.toml @@ -0,0 +1,7 @@ +required = [ + "github.com/dgrijalva/jwt-go", + ] + +[[constraint]] + name = "github.com/dgrijalva/jwt-go" + version = "1.0.0" diff --git a/spec/fixtures/go/gopkg_tomls/branch.toml b/spec/fixtures/go/gopkg_tomls/branch.toml new file mode 100644 index 00000000000..86bb1d26fb4 --- /dev/null +++ b/spec/fixtures/go/gopkg_tomls/branch.toml @@ -0,0 +1,8 @@ +required = [ + "golang.org/x/text", + ] + +# The collation tables must never change. +[[constraint]] + name = "golang.org/x/text" + branch = "master" diff --git a/spec/fixtures/go/gopkg_tomls/cockroach.toml b/spec/fixtures/go/gopkg_tomls/cockroach.toml new file mode 100644 index 00000000000..ad9e9230369 --- /dev/null +++ b/spec/fixtures/go/gopkg_tomls/cockroach.toml @@ -0,0 +1,112 @@ +required = [ + "github.com/client9/misspell/cmd/misspell", + "github.com/cockroachdb/crlfmt", + "github.com/cockroachdb/stress", + "github.com/golang/dep/cmd/dep", + "github.com/golang/lint/golint", + "github.com/google/pprof", + "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway", + "github.com/jteeuwen/go-bindata/go-bindata", + "github.com/kisielk/errcheck", + "github.com/mattn/goveralls", + "github.com/mibk/dupl", + "github.com/wadey/gocovmerge", + "golang.org/x/perf/cmd/benchstat", + "golang.org/x/tools/cmd/goimports", + "golang.org/x/tools/cmd/goyacc", + "golang.org/x/tools/cmd/stringer", +] + +ignored = [ + # Non-existent package used by a toy program in c-deps/protobuf. + "github.com/google/protobuf/examples/tutorial", +] + +# The collation tables must never change. +[[constraint]] + name = "golang.org/x/text" + revision = "470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4" + +# https://github.com/coreos/etcd/commit/f03ed33 +# +# https://github.com/coreos/etcd/commit/ce0ad377 +[[constraint]] + name = "github.com/coreos/etcd" + branch = "master" + +# Used for the API client; we want the latest. +[[constraint]] + name = "github.com/docker/docker" + branch = "master" + +# https://github.com/getsentry/raven-go/pull/139 +[[constraint]] + name = "github.com/getsentry/raven-go" + source = "https://github.com/cockroachdb/raven-go" + +# Used for benchmarks, should be recent. +[[constraint]] + name = "github.com/go-sql-driver/mysql" + branch = "master" + +# https://github.com/jteeuwen/go-bindata/pull/158 +[[constraint]] + name = "github.com/jteeuwen/go-bindata" + source = "https://github.com/dim13/go-bindata" + branch = "master" + +# https://github.com/montanaflynn/stats/releases (latest is 2015-10-14) +[[constraint]] + name = "github.com/montanaflynn/stats" + branch = "master" + +# https://github.com/rubyist/circuitbreaker/commit/af95830 +[[constraint]] + name = "github.com/rubyist/circuitbreaker" + branch = "master" + +# https://github.com/xwb1989/sqlparser/issues/31 +# https://github.com/xwb1989/sqlparser/issues/32 +[[constraint]] + name = "github.com/xwb1989/sqlparser" + source = "https://github.com/dt/sqlparser" + +# The master version of go.uuid has an incompatible interface and (as +# of 2018-06-06) a serious bug. Don't upgrade without making sure +# that bug is fixed. +# https://github.com/cockroachdb/cockroach/issues/26332 +[[constraint]] + name = "github.com/satori/go.uuid" + version = "v1.2.0" + +# github.com/docker/docker depends on a few functions not included in the +# latest release: reference.{FamiliarName,ParseNormalizedNamed,TagNameOnly}. +# +# https://github.com/docker/distribution/commit/429c75f +# https://github.com/docker/distribution/commit/2caeb61 +[[override]] + name = "github.com/docker/distribution" + branch = "master" + +[prune] + go-tests = true + unused-packages = true + + # Avoid pruning projects containing needed protos. + + [[prune.project]] + name = "github.com/gogo/protobuf" + unused-packages = false + + [[prune.project]] + name = "github.com/grpc-ecosystem/grpc-gateway" + unused-packages = false + + [[prune.project]] + name = "github.com/prometheus/client_model" + unused-packages = false + + # Contains packages with used C files. + [[prune.project]] + name = "github.com/knz/go-libedit" + unused-packages = false diff --git a/spec/fixtures/go/gopkg_tomls/custom_source.toml b/spec/fixtures/go/gopkg_tomls/custom_source.toml new file mode 100644 index 00000000000..11c372a7088 --- /dev/null +++ b/spec/fixtures/go/gopkg_tomls/custom_source.toml @@ -0,0 +1,14 @@ +required = [ + "github.com/some/thing", + "github.com/bsm/ratelimit" + ] + +[[constraint]] + name = "github.com/some/thing" + branch = "master" + source = "https://github.com/dgrijalva/jwt-go" + +[[constraint]] + name = "github.com/bsm/ratelimit" + version = "2.0.0" + diff --git a/spec/fixtures/go/gopkg_tomls/fider.toml b/spec/fixtures/go/gopkg_tomls/fider.toml new file mode 100644 index 00000000000..c3f72148435 --- /dev/null +++ b/spec/fixtures/go/gopkg_tomls/fider.toml @@ -0,0 +1,32 @@ + +[[constraint]] + name = "github.com/dgrijalva/jwt-go" + version = "^3.2.0" + +[[constraint]] + name = "github.com/gosimple/slug" + version = "^1.1.1" + +[[constraint]] + branch = "master" + name = "github.com/lib/pq" + +[[constraint]] + name = "github.com/russross/blackfriday" + version = "^1.5.1" + +[[constraint]] + branch = "master" + name = "golang.org/x/oauth2" + +[[constraint]] + branch = "master" + name = "github.com/goenning/letteravatar" + +[[constraint]] + branch = "master" + name = "github.com/julienschmidt/httprouter" + +[[constraint]] + branch = "master" + name = "golang.org/x/crypto" diff --git a/spec/fixtures/go/gopkg_tomls/flagr.toml b/spec/fixtures/go/gopkg_tomls/flagr.toml new file mode 100644 index 00000000000..a0c0535f591 --- /dev/null +++ b/spec/fixtures/go/gopkg_tomls/flagr.toml @@ -0,0 +1,154 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/DataDog/datadog-go" + version = "2.1.0" + +[[constraint]] + name = "github.com/Shopify/sarama" + version = "1.17.0" + +[[constraint]] + branch = "master" + name = "github.com/auth0/go-jwt-middleware" + +[[constraint]] + branch = "master" + name = "github.com/brandur/simplebox" + +[[constraint]] + name = "github.com/bsm/ratelimit" + version = "2.0.0" + +[[constraint]] + name = "github.com/caarlos0/env" + version = "3.3.0" + +[[constraint]] + name = "github.com/davecgh/go-spew" + version = "1.1.0" + +[[constraint]] + name = "github.com/dgrijalva/jwt-go" + version = "3.2.0" + +[[constraint]] + name = "github.com/evalphobia/logrus_sentry" + version = "0.4.6" + +[[constraint]] + branch = "master" + name = "github.com/getsentry/raven-go" + +[[constraint]] + branch = "master" + name = "github.com/go-openapi/errors" + +[[constraint]] + branch = "master" + name = "github.com/go-openapi/loads" + +[[constraint]] + branch = "master" + name = "github.com/go-openapi/runtime" + +[[constraint]] + branch = "master" + name = "github.com/go-openapi/spec" + +[[constraint]] + branch = "master" + name = "github.com/go-openapi/strfmt" + +[[constraint]] + branch = "master" + name = "github.com/go-openapi/swag" + +[[constraint]] + branch = "master" + name = "github.com/go-openapi/validate" + +[[constraint]] + branch = "master" + name = "github.com/gohttp/pprof" + +[[constraint]] + name = "github.com/jessevdk/go-flags" + version = "1.4.0" + +[[constraint]] + name = "github.com/jinzhu/gorm" + version = "1.9.1" + +[[constraint]] + branch = "master" + name = "github.com/meatballhat/negroni-logrus" + +[[constraint]] + name = "github.com/newrelic/go-agent" + version = "2.0.0" + +[[constraint]] + branch = "master" + name = "github.com/prashantv/gostub" + +[[constraint]] + name = "github.com/rs/cors" + version = "1.4.0" + +[[constraint]] + name = "github.com/sirupsen/logrus" + version = "1.0.5" + +[[constraint]] + name = "github.com/spf13/cast" + version = "1.2.0" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.2" + +[[constraint]] + name = "github.com/urfave/negroni" + version = "0.3.0" + +[[constraint]] + branch = "master" + name = "github.com/yadvendar/negroni-newrelic-go-agent" + +[[constraint]] + branch = "master" + name = "github.com/zhouzhuojie/conditions" + +[[constraint]] + branch = "master" + name = "golang.org/x/net" + +[prune] + go-tests = true + unused-packages = true diff --git a/spec/fixtures/go/gopkg_tomls/no_version.toml b/spec/fixtures/go/gopkg_tomls/no_version.toml new file mode 100644 index 00000000000..b35ab646978 --- /dev/null +++ b/spec/fixtures/go/gopkg_tomls/no_version.toml @@ -0,0 +1,6 @@ +required = [ + "github.com/dgrijalva/jwt-go", + ] + +[[constraint]] + name = "github.com/dgrijalva/jwt-go" diff --git a/spec/fixtures/go/gopkg_tomls/tag_as_revision.toml b/spec/fixtures/go/gopkg_tomls/tag_as_revision.toml new file mode 100644 index 00000000000..c785976ea32 --- /dev/null +++ b/spec/fixtures/go/gopkg_tomls/tag_as_revision.toml @@ -0,0 +1,8 @@ +required = [ + "golang.org/x/text", + ] + +# The collation tables must never change. +[[constraint]] + name = "golang.org/x/text" + revision = "v0.2.0" diff --git a/spec/fixtures/go/gopkg_tomls/unknown_source.toml b/spec/fixtures/go/gopkg_tomls/unknown_source.toml new file mode 100644 index 00000000000..d579dbdba4a --- /dev/null +++ b/spec/fixtures/go/gopkg_tomls/unknown_source.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "unknownhost.com/dgrijalva/jwt-go" + version = "^3.2.0"