mini_portile2-2.8.7/0000755000004100000410000000000014630451726014344 5ustar www-datawww-datamini_portile2-2.8.7/.gitignore0000644000004100000410000000005414630451726016333 0ustar www-datawww-data.bundle Gemfile.lock pkg ports tmp mkmf.log mini_portile2-2.8.7/SECURITY.md0000644000004100000410000000174314630451726016142 0ustar www-datawww-data# Security and Vulnerability Reporting The mini_portile core contributors take security very seriously and investigate all reported vulnerabilities. If you would like to report a vulnerablity or have a security concern regarding mini_portile, please [report it via Tidelift](https://tidelift.com/security). Your report will be acknowledged within 48 hours, and you'll receive a more detailed response within 96 hours indicating next steps in handling your report. If you have not received a reply to your submission within 96 hours, Contact the current security coordinator, Mike Dalessio . The information you share with the mini_portile core contributors as part of this process will be kept confidential within the team, unless or until we need to share information upstream with our dependent libraries' core teams, at which point we will notify you. If a vulnerability is first reported by you, we will credit you with the discovery in the public disclosure. mini_portile2-2.8.7/.github/0000755000004100000410000000000014630451726015704 5ustar www-datawww-datamini_portile2-2.8.7/.github/workflows/0000755000004100000410000000000014630451726017741 5ustar www-datawww-datamini_portile2-2.8.7/.github/workflows/downstream.yml0000644000004100000410000000401614630451726022650 0ustar www-datawww-dataname: downstream concurrency: group: "${{github.workflow}}-${{github.ref}}" cancel-in-progress: true on: workflow_dispatch: schedule: - cron: "0 7 * * 1,3,5" # At 07:00 on Monday, Wednesday, and Friday # https://crontab.guru/#0_7_*_*_1,3,5 push: branches: - main - "v*.*.x" tags: - v*.*.* pull_request: types: [opened, synchronize] branches: - '*' jobs: downstream: name: downstream-${{matrix.name}}-${{matrix.platform}} strategy: fail-fast: false matrix: name: [re2, nokogiri, sqlite3] platform: [ubuntu-latest, windows-latest, macos-latest] include: - name: re2 url: https://github.com/mudge/re2 command: "bundle exec rake compile spec" ruby: "3.3" - name: nokogiri url: https://github.com/sparklemotion/nokogiri command: "bundle exec rake compile test" ruby: "3.3" - name: sqlite3 url: https://github.com/sparklemotion/sqlite3-ruby command: "bundle exec rake compile test" ruby: "3.3" runs-on: ${{matrix.platform}} steps: - name: configure git crlf if: ${{ startsWith(matrix.platform, 'windows') }} run: | git config --system core.autocrlf false git config --system core.eol lf - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true bundler: latest - run: git clone --depth=1 ${{matrix.url}} ${{matrix.name}} - uses: actions/cache@v4 with: path: ${{matrix.name}}/ports/archives key: tarballs-${{matrix.name}} enableCrossOsArchive: true - name: ${{matrix.name}} test suite working-directory: ${{matrix.name}} run: | bundle remove mini_portile2 || true bundle add mini_portile2 --path=".." bundle install --local || bundle install ${{matrix.command}} mini_portile2-2.8.7/.github/workflows/ci.yml0000644000004100000410000001235314630451726021063 0ustar www-datawww-dataname: Continuous Integration concurrency: group: "${{github.workflow}}-${{github.ref}}" cancel-in-progress: true on: workflow_dispatch: push: branches: - main - v*.*.x tags: - v*.*.* pull_request: types: [opened, synchronize] branches: - "*" schedule: - cron: "0 8 * * 5" # At 08:00 on Friday # https://crontab.guru/#0_8_*_*_5 jobs: test-unit: env: MAKEFLAGS: -j2 strategy: fail-fast: false matrix: platform: [ubuntu-latest, windows-latest, macos-latest] ruby: ["2.3", "2.4", "2.5", "2.6", "2.7", "3.0", "3.1", "3.2", "3.3", "head"] exclude: # I can't figure out how to install these on macos through setup-ruby - ruby: "2.3" platform: "macos-latest" - ruby: "2.4" platform: "macos-latest" - ruby: "2.5" platform: "macos-latest" runs-on: ${{ matrix.platform }} steps: - name: configure git crlf on windows if: matrix.platform == 'windows-latest' run: | git config --system core.autocrlf false git config --system core.eol lf - uses: actions/checkout@v4 - uses: MSP-Greg/setup-ruby-pkgs@v1 with: apt-get: _update_ build-essential cmake mingw: _upgrade_ cmake ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: bundle exec rake test:unit test-examples: env: MAKEFLAGS: -j2 strategy: fail-fast: false matrix: # use macos-13 (not 14) because libyaml 0.2.5 doesn't have up-to-date config.guess and config.sub platform: [ubuntu-latest, windows-latest, macos-13] ruby: ["3.1"] runs-on: ${{ matrix.platform }} steps: - name: configure git crlf on windows if: matrix.platform == 'windows-latest' run: | git config --system core.autocrlf false git config --system core.eol lf - uses: actions/checkout@v4 - uses: MSP-Greg/setup-ruby-pkgs@v1 with: apt-get: _update_ build-essential cmake mingw: _upgrade_ cmake ruby-version: ${{ matrix.ruby }} bundler-cache: true - uses: actions/cache@v4 with: path: examples/ports/archives key: examples-${{ hashFiles('examples/Rakefile') }} - run: bundle exec rake test:examples fedora: # see https://github.com/flavorjones/mini_portile/issues/118 strategy: fail-fast: false matrix: task: ["test:unit", "test:examples"] runs-on: ubuntu-latest container: image: fedora:35 steps: - run: | dnf group install -y "C Development Tools and Libraries" dnf install -y ruby ruby-devel libyaml-devel git-all patch cmake xz - uses: actions/checkout@v4 - uses: actions/cache@v4 with: path: examples/ports/archives key: examples-${{ hashFiles('examples/Rakefile') }} - run: bundle install - run: bundle exec rake ${{ matrix.task }} freebsd: strategy: fail-fast: false matrix: task: ["test:unit", "test:examples"] runs-on: ubuntu-latest env: MAKE: gmake steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 with: path: examples/ports/archives key: examples-${{ hashFiles('examples/Rakefile') }} - uses: vmactions/freebsd-vm@v1 with: envs: MAKE usesh: true copyback: false prepare: pkg install -y ruby devel/ruby-gems pkgconf git cmake devel/gmake textproc/libyaml security/gnupg run: | git config --global --add safe.directory /home/runner/work/mini_portile/mini_portile gem install bundler bundle install bundle exec rake ${{ matrix.task }} openbsd: strategy: fail-fast: false matrix: task: ["test:unit", "test:examples"] runs-on: ubuntu-latest env: MAKE: gmake steps: - uses: actions/checkout@v4 - uses: vmactions/openbsd-vm@v1 with: envs: MAKE usesh: true copyback: false prepare: | pkg_add ruby%3.1 gmake cmake git pkgconf security/gnupg ln -sf /usr/local/bin/ruby31 /usr/local/bin/ruby ln -sf /usr/local/bin/bundle31 /usr/local/bin/bundle ln -sf /usr/local/bin/bundler31 /usr/local/bin/bundler ln -sf /usr/local/bin/erb31 /usr/local/bin/erb ln -sf /usr/local/bin/gem31 /usr/local/bin/gem ln -sf /usr/local/bin/irb31 /usr/local/bin/irb ln -sf /usr/local/bin/racc31 /usr/local/bin/racc ln -sf /usr/local/bin/rake31 /usr/local/bin/rake ln -sf /usr/local/bin/rbs31 /usr/local/bin/rbs ln -sf /usr/local/bin/rdbg31 /usr/local/bin/rdbg ln -sf /usr/local/bin/rdoc31 /usr/local/bin/rdoc ln -sf /usr/local/bin/ri31 /usr/local/bin/ri ln -sf /usr/local/bin/syntax_suggest31 /usr/local/bin/syntax_suggest ln -sf /usr/local/bin/typeprof31 /usr/local/bin/typeprof run: | git config --global --add safe.directory /home/runner/work/mini_portile/mini_portile gem install bundler bundle install bundle exec rake ${{ matrix.task }} mini_portile2-2.8.7/.github/FUNDING.yml0000644000004100000410000000006514630451726017522 0ustar www-datawww-datagithub: flavorjones tidelift: rubygems/mini_portile2 mini_portile2-2.8.7/lib/0000755000004100000410000000000014630451726015112 5ustar www-datawww-datamini_portile2-2.8.7/lib/mini_portile2.rb0000644000004100000410000000016014630451726020210 0ustar www-datawww-datarequire "mini_portile2/version" require "mini_portile2/mini_portile" require "mini_portile2/mini_portile_cmake" mini_portile2-2.8.7/lib/mini_portile2/0000755000004100000410000000000014630451726017666 5ustar www-datawww-datamini_portile2-2.8.7/lib/mini_portile2/mini_portile.rb0000644000004100000410000005616014630451726022715 0ustar www-datawww-datarequire 'rbconfig' require 'net/http' require 'net/https' require 'fileutils' require 'tempfile' require 'digest' require 'open-uri' require 'cgi' require 'rbconfig' require 'shellwords' require 'open3' # Monkey patch for Net::HTTP by ruby open-uri fix: # https://github.com/ruby/ruby/commit/58835a9 class Net::HTTP private remove_method(:edit_path) def edit_path(path) if proxy? if path.start_with?("ftp://") || use_ssl? path else "http://#{addr_port}#{path}" end else path end end end $MINI_PORTILE_STATIC_LIBS = {} class MiniPortile DEFAULT_TIMEOUT = 10 attr_reader :name, :version, :original_host, :source_directory attr_writer :configure_options attr_accessor :host, :files, :patch_files, :target, :logger def self.windows? target_os =~ /mswin|mingw/ end # GNU MinGW compiled Ruby? def self.mingw? target_os =~ /mingw/ end # MS Visual-C compiled Ruby? def self.mswin? target_os =~ /mswin/ end def self.darwin? target_os =~ /darwin/ end def self.freebsd? target_os =~ /freebsd/ end def self.openbsd? target_os =~ /openbsd/ end def self.linux? target_os =~ /linux/ end def self.solaris? target_os =~ /solaris/ end def self.target_os RbConfig::CONFIG['target_os'] end def self.target_cpu RbConfig::CONFIG['target_cpu'] end def self.native_path(path) path = File.expand_path(path) if File::ALT_SEPARATOR path.tr(File::SEPARATOR, File::ALT_SEPARATOR) else path end end def self.posix_path(path) path = File.expand_path(path) if File::ALT_SEPARATOR "/" + path.tr(File::ALT_SEPARATOR, File::SEPARATOR).tr(":", File::SEPARATOR) else path end end def initialize(name, version, **kwargs) @name = name @version = version @target = 'ports' @files = [] @patch_files = [] @log_files = {} @logger = kwargs[:logger] || STDOUT @source_directory = nil @cc_command = kwargs[:cc_command] || kwargs[:gcc_command] @cxx_command = kwargs[:cxx_command] @make_command = kwargs[:make_command] @open_timeout = kwargs[:open_timeout] || DEFAULT_TIMEOUT @read_timeout = kwargs[:read_timeout] || DEFAULT_TIMEOUT @original_host = @host = detect_host end def source_directory=(path) @source_directory = posix_path(path) end def prepare_build_directory raise "source_directory is not set" if source_directory.nil? output "Building #{@name} from source at '#{source_directory}'" FileUtils.mkdir_p(File.join(tmp_path, [name, version].join("-"))) FileUtils.rm_rf(port_path) # make sure we always re-install end def download files_hashs.each do |file| download_file(file[:url], file[:local_path]) verify_file(file) end end def extract files_hashs.each do |file| verify_file(file) extract_file(file[:local_path], tmp_path) end end def apply_patch(patch_file) ( # Not a class variable because closures will capture self. @apply_patch ||= case when which('git') lambda { |file| message "Running git apply with #{file}... " Dir.mktmpdir do |tmp_git_dir| execute('patch', ["git", "--git-dir=#{tmp_git_dir}", "--work-tree=.", "apply", "--whitespace=warn", file], :initial_message => false) end } when which('patch') lambda { |file| message "Running patch with #{file}... " execute('patch', ["patch", "-p1", "-i", file], :initial_message => false) } else raise "Failed to complete patch task; patch(1) or git(1) is required." end ).call(patch_file) end def patch @patch_files.each do |full_path| next unless File.exist?(full_path) apply_patch(full_path) end end def configure_options @configure_options ||= configure_defaults end def configure return if configured? FileUtils.mkdir_p(tmp_path) cache_file = File.join(tmp_path, 'configure.options_cache') File.open(cache_file, "w") { |f| f.write computed_options.to_s } command = Array(File.join((source_directory || "."), "configure")) if RUBY_PLATFORM=~/mingw|mswin/ # Windows doesn't recognize the shebang. command.unshift("sh") end execute('configure', command + computed_options, altlog: "config.log") end def compile execute('compile', make_cmd) end def install return if installed? execute('install', %Q(#{make_cmd} install)) end def downloaded? missing = files_hashs.detect do |file| !File.exist?(file[:local_path]) end missing ? false : true end def configured? configure = File.join((source_directory || work_path), 'configure') makefile = File.join(work_path, 'Makefile') cache_file = File.join(tmp_path, 'configure.options_cache') stored_options = File.exist?(cache_file) ? File.read(cache_file) : "" current_options = computed_options.to_s (current_options == stored_options) && newer?(makefile, configure) end def installed? makefile = File.join(work_path, 'Makefile') target_dir = Dir.glob("#{port_path}/*").find { |d| File.directory?(d) } newer?(target_dir, makefile) end def cook if source_directory prepare_build_directory else download unless downloaded? extract patch end configure unless configured? compile install unless installed? return true end def activate vars = { 'PATH' => File.join(port_path, 'bin'), 'CPATH' => include_path, 'LIBRARY_PATH' => lib_path, }.reject { |env, path| !File.directory?(path) } output "Activating #{@name} #{@version} (from #{port_path})..." vars.each do |var, path| full_path = native_path(path) # save current variable value old_value = ENV[var] || '' unless old_value.include?(full_path) ENV[var] = "#{full_path}#{File::PATH_SEPARATOR}#{old_value}" end end # rely on LDFLAGS when cross-compiling if File.exist?(lib_path) && (@host != @original_host) full_path = native_path(lib_path) old_value = ENV.fetch("LDFLAGS", "") unless old_value.include?(full_path) ENV["LDFLAGS"] = "-L#{full_path} #{old_value}".strip end end end # pkg: the pkg-config file name (without the .pc extension) # dir: inject the directory path for the pkg-config file (probably only useful for tests) # static: the name of the static library archive (without the "lib" prefix or the file extension), or nil for dynamic linking # # we might be able to be terribly clever and infer the name of the static archive file, but # unfortunately projects have so much freedom in what they can report (for name, for libs, etc.) # that it feels unreliable to try to do so, so I'm preferring to just have the developer make it # explicit. def mkmf_config(pkg: nil, dir: nil, static: nil) require "mkmf" if pkg dir ||= File.join(lib_path, "pkgconfig") pcfile = File.join(dir, "#{pkg}.pc") unless File.exist?(pcfile) raise ArgumentError, "pkg-config file '#{pcfile}' does not exist" end output "Configuring MakeMakefile for #{File.basename(pcfile)} (in #{File.dirname(pcfile)})\n" # on macos, pkg-config will not return --cflags without this ENV["PKG_CONFIG_ALLOW_SYSTEM_CFLAGS"] = "t" # append to PKG_CONFIG_PATH as we go, so later pkg-config files can depend on earlier ones ENV["PKG_CONFIG_PATH"] = [ENV["PKG_CONFIG_PATH"], dir].compact.join(File::PATH_SEPARATOR) incflags = minimal_pkg_config(pcfile, "cflags-only-I") cflags = minimal_pkg_config(pcfile, "cflags-only-other") if static ldflags = minimal_pkg_config(pcfile, "libs-only-L", "static") libflags = minimal_pkg_config(pcfile, "libs-only-l", "static") else ldflags = minimal_pkg_config(pcfile, "libs-only-L") libflags = minimal_pkg_config(pcfile, "libs-only-l") end else output "Configuring MakeMakefile for #{@name} #{@version} (from #{path})\n" lib_name = name.sub(/\Alib/, "") # TODO: use delete_prefix when we no longer support ruby 2.4 incflags = Dir.exist?(include_path) ? "-I#{include_path}" : "" cflags = "" ldflags = Dir.exist?(lib_path) ? "-L#{lib_path}" : "" libflags = Dir.exist?(lib_path) ? "-l#{lib_name}" : "" end if static libdir = lib_path if pcfile pcfile_libdir = minimal_pkg_config(pcfile, "variable=libdir").strip libdir = pcfile_libdir unless pcfile_libdir.empty? end # # keep track of the libraries we're statically linking against, and fix up ldflags and # libflags to make sure we link statically against the recipe's libaries. # # this avoids the unintentionally dynamically linking against system libraries, and makes sure # that if multiple pkg-config files reference each other that we are able to intercept flags # from dependent packages that reference the static archive. # $MINI_PORTILE_STATIC_LIBS[static] = libdir static_ldflags = $MINI_PORTILE_STATIC_LIBS.values.map { |v| "-L#{v}" } static_libflags = $MINI_PORTILE_STATIC_LIBS.keys.map { |v| "-l#{v}" } # remove `-L#{libdir}` and `-lfoo`. we don't need them since we link against the static # archive using the full path. ldflags = ldflags.shellsplit.reject { |f| static_ldflags.include?(f) }.shelljoin libflags = libflags.shellsplit.reject { |f| static_libflags.include?(f) }.shelljoin # prepend the full path to the static archive to the linker flags static_archive = File.join(libdir, "lib#{static}.#{$LIBEXT}") libflags = [static_archive, libflags].join(" ").strip end # prefer this package by prepending to search paths and library flags # # convert the ldflags into a list of directories and append to $LIBPATH (instead of just using # $LDFLAGS) to ensure we get the `-Wl,-rpath` linker flag for re-finding shared libraries. $INCFLAGS = [incflags, $INCFLAGS].join(" ").strip libpaths = ldflags.shellsplit.map { |f| f.sub(/\A-L/, "") } $LIBPATH = libpaths | $LIBPATH $libs = [libflags, $libs].join(" ").strip # prefer this package's compiler flags by appending them to the command line $CFLAGS = [$CFLAGS, cflags].join(" ").strip $CXXFLAGS = [$CXXFLAGS, cflags].join(" ").strip end def path File.expand_path(port_path) end def include_path File.join(path, "include") end def lib_path File.join(path, "lib") end def cc_cmd (ENV["CC"] || @cc_command || RbConfig::CONFIG["CC"] || "gcc").dup end alias :gcc_cmd :cc_cmd def cxx_cmd (ENV["CXX"] || @cxx_command || RbConfig::CONFIG["CXX"] || "g++").dup end def make_cmd (ENV["MAKE"] || @make_command || ENV["make"] || "make").dup end private def native_path(path) MiniPortile.native_path(path) end def posix_path(path) MiniPortile.posix_path(path) end def tmp_path "tmp/#{@host}/ports/#{@name}/#{@version}" end def port_path "#{@target}/#{@host}/#{@name}/#{@version}" end def archives_path "#{@target}/archives" end def work_path Dir.glob("#{tmp_path}/*").find { |d| File.directory?(d) } end def configure_defaults [ "--host=#{@host}", # build for specific target (host) "--enable-static", # build static library "--disable-shared" # disable generation of shared object ] end def configure_prefix "--prefix=#{File.expand_path(port_path)}" end def computed_options [ configure_options, # customized or default options configure_prefix, # installation target ].flatten end def files_hashs @files.map do |file| hash = case file when String { :url => file } when Hash file.dup else raise ArgumentError, "files must be an Array of Stings or Hashs" end url = hash.fetch(:url){ raise ArgumentError, "no url given" } filename = File.basename(url) hash[:local_path] = File.join(archives_path, filename) hash end end KEYRING_NAME = "mini_portile_keyring.gpg" def verify_file(file) if file.has_key?(:gpg) gpg = file[:gpg] signature_url = gpg[:signature_url] || "#{file[:url]}.asc" signature_file = file[:local_path] + ".asc" # download the signature file download_file(signature_url, signature_file) gpg_exe = which('gpg2') || which('gpg') || raise("Neither GPG nor GPG2 is installed") # import the key into our own keyring gpg_error = nil gpg_status = Open3.popen3(gpg_exe, "--status-fd", "1", "--no-default-keyring", "--keyring", KEYRING_NAME, "--import") do |gpg_in, gpg_out, gpg_err, _thread| gpg_in.write gpg[:key] gpg_in.close gpg_error = gpg_err.read gpg_out.read end key_ids = gpg_status.scan(/\[GNUPG:\] IMPORT_OK \d+ (?[0-9a-f]+)/i).map(&:first) raise "invalid gpg key provided:\n#{gpg_error}" if key_ids.empty? begin # verify the signature against our keyring gpg_status, gpg_error, _status = Open3.capture3(gpg_exe, "--status-fd", "1", "--no-default-keyring", "--keyring", KEYRING_NAME, "--verify", signature_file, file[:local_path]) raise "signature mismatch:\n#{gpg_error}" unless gpg_status.match(/^\[GNUPG:\] VALIDSIG/) ensure # remove the key from our keyring key_ids.each do |key_id| IO.popen([gpg_exe, "--batch", "--yes", "--no-default-keyring", "--keyring", KEYRING_NAME, "--delete-keys", key_id], &:read) raise "unable to delete the imported key" unless $?.exitstatus==0 end end else digest = case when exp=file[:sha256] then Digest::SHA256 when exp=file[:sha1] then Digest::SHA1 when exp=file[:md5] then Digest::MD5 end if digest is = digest.file(file[:local_path]).hexdigest unless is == exp.downcase raise "Downloaded file '#{file[:local_path]}' has wrong hash: expected: #{exp} is: #{is}" end end end end def log_file(action) @log_files[action] ||= File.expand_path("#{action}.log", tmp_path).tap { |file| File.unlink(file) if File.exist?(file) } end # From: http://stackoverflow.com/a/5471032/7672 # Thanks, Mislav! # # Cross-platform way of finding an executable in the $PATH. # # which('ruby') #=> /usr/bin/ruby def which(cmd) exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| exts.each { |ext| exe = File.join(path, "#{cmd}#{ext}") return exe if File.executable? exe } end return nil end def detect_host return @detect_host if defined?(@detect_host) begin ENV["LC_ALL"], old_lc_all = "C", ENV["LC_ALL"] output = `#{gcc_cmd} -v 2>&1` if m = output.match(/^Target\: (.*)$/) @detect_host = m[1] else @detect_host = nil end @detect_host ensure ENV["LC_ALL"] = old_lc_all end end TAR_EXECUTABLES = %w[gtar bsdtar tar basic-bsdtar] def tar_exe @@tar_exe ||= begin TAR_EXECUTABLES.find { |c| which(c) } or raise("tar not found - please make sure that one of the following commands is in the PATH: #{TAR_EXECUTABLES.join(", ")}") end end def tar_command(file, target) case File.extname(file) when '.gz', '.tgz' [tar_exe, 'xzf', file, '-C', target] when '.bz2', '.tbz2' [tar_exe, 'xjf', file, '-C', target] when '.xz' # NOTE: OpenBSD's tar command does not support the -J option "xzcat #{file.shellescape} | #{tar_exe.shellescape} xf - -C #{target.shellescape}" else [tar_exe, 'xf', file, '-C', target] end end def extract_file(file, target) filename = File.basename(file) FileUtils.mkdir_p target message "Extracting #{filename} into #{target}... " execute('extract', tar_command(file, target) , {:cd => Dir.pwd, :initial_message => false}) end # command could be an array of args, or one string containing a command passed to the shell. See # Process.spawn for more information. def execute(action, command, command_opts={}) opt_message = command_opts.fetch(:initial_message, true) opt_debug = command_opts.fetch(:debug, false) opt_cd = command_opts.fetch(:cd) { work_path } opt_env = command_opts.fetch(:env) { Hash.new } opt_altlog = command_opts.fetch(:altlog, nil) log_out = log_file(action) Dir.chdir(opt_cd) do output "DEBUG: env is #{opt_env.inspect}" if opt_debug output "DEBUG: command is #{command.inspect}" if opt_debug message "Running '#{action}' for #{@name} #{@version}... " if opt_message if Process.respond_to?(:spawn) && ! RbConfig.respond_to?(:java) options = {[:out, :err]=>[log_out, "a"]} output "DEBUG: options are #{options.inspect}" if opt_debug args = [opt_env, command, options].flatten pid = spawn(*args) Process.wait(pid) else env_args = opt_env.map { |k,v| "#{k}=#{v}".shellescape }.join(" ") c = if command.kind_of?(Array) command.map(&:shellescape).join(" ") else command end redirected = %Q{env #{env_args} #{c} > #{log_out.shellescape} 2>&1} output "DEBUG: final command is #{redirected.inspect}" if opt_debug system redirected end if $?.success? output "OK" return true else output "ERROR. Please review logs to see what happened:\n" [log_out, opt_altlog].compact.each do |log| next unless File.exist?(log) output("----- contents of '#{log}' -----") output(File.read(log)) output("----- end of file -----") end raise "Failed to complete #{action} task" end end end def newer?(target, checkpoint) if (target && File.exist?(target)) && (checkpoint && File.exist?(checkpoint)) File.mtime(target) > File.mtime(checkpoint) else false end end # print out a message with the logger def message(text) @logger.print text @logger.flush end # print out a message using the logger but return to a new line def output(text = "") @logger.puts text @logger.flush end # Slighly modified from RubyInstaller uri_ext, Rubinius configure # and adaptations of Wayne's RailsInstaller def download_file(url, full_path, count = 3) return if File.exist?(full_path) uri = URI.parse(url) case uri.scheme.downcase when /ftp/ download_file_ftp(uri, full_path) when /http|https/ download_file_http(url, full_path, count) when /file/ download_file_file(uri, full_path) else raise ArgumentError.new("Unsupported protocol for #{url}") end rescue Exception => e File.unlink full_path if File.exist?(full_path) raise e end def download_file_http(url, full_path, count = 3) filename = File.basename(full_path) with_tempfile(filename, full_path) do |temp_file| total = 0 params = { "Accept-Encoding" => 'identity', :content_length_proc => lambda{|length| total = length }, :progress_proc => lambda{|bytes| if total new_progress = (bytes * 100) / total message "\rDownloading %s (%3d%%) " % [filename, new_progress] else # Content-Length is unavailable because Transfer-Encoding is chunked message "\rDownloading %s " % [filename] end }, :open_timeout => @open_timeout, :read_timeout => @read_timeout, } proxy_uri = URI.parse(url).scheme.downcase == 'https' ? ENV["https_proxy"] : ENV["http_proxy"] if proxy_uri _, userinfo, _p_host, _p_port = URI.split(proxy_uri) if userinfo proxy_user, proxy_pass = userinfo.split(/:/).map{|s| CGI.unescape(s) } params[:proxy_http_basic_authentication] = [proxy_uri, proxy_user, proxy_pass] end end begin OpenURI.open_uri(url, 'rb', params) do |io| temp_file << io.read end output rescue OpenURI::HTTPRedirect => redirect raise "Too many redirections for the original URL, halting." if count <= 0 count = count - 1 return download_file(redirect.url, full_path, count-1) rescue => e count = count - 1 @logger.puts "#{count} retrie(s) left for #{filename} (#{e.message})" if count > 0 sleep 1 return download_file_http(url, full_path, count) end output e.message return false end end end def download_file_file(uri, full_path) FileUtils.mkdir_p File.dirname(full_path) FileUtils.cp uri.path, full_path end def download_file_ftp(uri, full_path) require "net/ftp" filename = File.basename(uri.path) with_tempfile(filename, full_path) do |temp_file| total = 0 params = { :content_length_proc => lambda{|length| total = length }, :progress_proc => lambda{|bytes| new_progress = (bytes * 100) / total message "\rDownloading %s (%3d%%) " % [filename, new_progress] }, :open_timeout => @open_timeout, :read_timeout => @read_timeout, } if ENV["ftp_proxy"] _, userinfo, _p_host, _p_port = URI.split(ENV['ftp_proxy']) if userinfo proxy_user, proxy_pass = userinfo.split(/:/).map{|s| CGI.unescape(s) } params[:proxy_http_basic_authentication] = [ENV['ftp_proxy'], proxy_user, proxy_pass] end end OpenURI.open_uri(uri, 'rb', params) do |io| temp_file << io.read end output end rescue LoadError raise LoadError, "Ruby #{RUBY_VERSION} does not provide the net-ftp gem, please add it as a dependency if you need to use FTP" rescue Net::FTPError return false end def with_tempfile(filename, full_path) temp_file = Tempfile.new("download-#{filename}") temp_file.binmode yield temp_file temp_file.close File.unlink full_path if File.exist?(full_path) FileUtils.mkdir_p File.dirname(full_path) FileUtils.mv temp_file.path, full_path, :force => true end # # this minimal version of pkg_config is based on ruby 29dc9378 (2023-01-09) # # specifically with the fix from b90e56e6 to support multiple pkg-config options, and removing # code paths that aren't helpful for mini-portile's use case of parsing pc files. # def minimal_pkg_config(pkg, *pcoptions) if pcoptions.empty? raise ArgumentError, "no pkg-config options are given" end if ($PKGCONFIG ||= (pkgconfig = MakeMakefile.with_config("pkg-config") {MakeMakefile.config_string("PKG_CONFIG") || "pkg-config"}) && MakeMakefile.find_executable0(pkgconfig) && pkgconfig) pkgconfig = $PKGCONFIG else raise RuntimeError, "pkg-config is not found" end pcoptions = Array(pcoptions).map { |o| "--#{o}" } response = IO.popen([pkgconfig, *pcoptions, pkg], err:[:child, :out], &:read) raise RuntimeError, response unless $?.success? response.strip end end mini_portile2-2.8.7/lib/mini_portile2/version.rb0000644000004100000410000000005214630451726021675 0ustar www-datawww-dataclass MiniPortile VERSION = "2.8.7" end mini_portile2-2.8.7/lib/mini_portile2/mini_portile_cmake.rb0000644000004100000410000000621414630451726024050 0ustar www-datawww-datarequire 'mini_portile2/mini_portile' require 'open3' class MiniPortileCMake < MiniPortile attr_accessor :system_name def configure_prefix "-DCMAKE_INSTALL_PREFIX=#{File.expand_path(port_path)}" end def initialize(name, version, **kwargs) super(name, version, **kwargs) @cmake_command = kwargs[:cmake_command] @cmake_build_type = kwargs[:cmake_build_type] end def configure_defaults [ generator_defaults, cmake_compile_flags, ].flatten end def configure return if configured? cache_file = File.join(tmp_path, 'configure.options_cache') File.open(cache_file, "w") { |f| f.write computed_options.to_s } execute('configure', [cmake_cmd] + computed_options + ["."]) end def configured? configure = File.join(work_path, 'configure') makefile = File.join(work_path, 'CMakefile') cache_file = File.join(tmp_path, 'configure.options_cache') stored_options = File.exist?(cache_file) ? File.read(cache_file) : "" current_options = computed_options.to_s (current_options == stored_options) && newer?(makefile, configure) end def make_cmd return "nmake" if MiniPortile.mswin? super end def cmake_cmd (ENV["CMAKE"] || @cmake_command || "cmake").dup end def cmake_build_type (ENV["CMAKE_BUILD_TYPE"] || @cmake_build_type || "Release").dup end private def generator_defaults if MiniPortile.mswin? && generator_available?('NMake') ['-G', 'NMake Makefiles'] elsif MiniPortile.mingw? && generator_available?('MSYS') ['-G', 'MSYS Makefiles'] else [] end end def cmake_compile_flags # RbConfig::CONFIG['CC'] and RbConfig::CONFIG['CXX'] can contain additional flags, for example # "clang++ -std=gnu++11" or "clang -fdeclspec". CMake is just looking for the command name. cc_compiler = cc_cmd.split.first cxx_compiler = cxx_cmd.split.first # needed to ensure cross-compilation with CMake targets the right CPU and compilers [ "-DCMAKE_SYSTEM_NAME=#{cmake_system_name}", "-DCMAKE_SYSTEM_PROCESSOR=#{cpu_type}", "-DCMAKE_C_COMPILER=#{cc_compiler}", "-DCMAKE_CXX_COMPILER=#{cxx_compiler}", "-DCMAKE_BUILD_TYPE=#{cmake_build_type}", ] end # Full list: https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.4/Modules/CMakeDetermineSystem.cmake?ref_type=tags#L12-31 def cmake_system_name return system_name if system_name if MiniPortile.linux? 'Linux' elsif MiniPortile.darwin? 'Darwin' elsif MiniPortile.windows? 'Windows' elsif MiniPortile.freebsd? 'FreeBSD' elsif MiniPortile.openbsd? 'OpenBSD' elsif MiniPortile.solaris? 'SunOS' else raise "Unable to set CMAKE_SYSTEM_NAME for #{MiniPortile.target_os}" end end def generator_available?(generator_type) stdout_str, status = Open3.capture2("#{cmake_cmd} --help") raise 'Unable to determine whether CMake supports #{generator_type} Makefile generator' unless status.success? stdout_str.include?("#{generator_type} Makefiles") end def cpu_type return 'x86_64' if MiniPortile.target_cpu == 'x64' MiniPortile.target_cpu end end mini_portile2-2.8.7/LICENSE.txt0000644000004100000410000000206614630451726016173 0ustar www-datawww-dataCopyright (c) 2011-2016 Luis Lavena and Mike Dalessio Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mini_portile2-2.8.7/test/0000755000004100000410000000000014630451726015323 5ustar www-datawww-datamini_portile2-2.8.7/test/test_download.rb0000644000004100000410000000346414630451726020525 0ustar www-datawww-datarequire File.expand_path('../helper', __FILE__) describe "recipe download" do include Minitest::Hooks attr :recipe def server_must_receive_connection(connections = 3, &block) request_count = 0 server = TCPServer.open('localhost', TestCase::HTTP_PORT) thread = Thread.new do connections.times do conn = server.accept request_count += 1 conn.puts "CONNECTION SUCESSFULLY MADE" rescue SystemCallError conn.close end end begin block.call ensure thread.kill server.close end assert_operator(request_count, :>, 0) end before do @request_count = 0 @logger = StringIO.new @recipe = MiniPortile.new("test-download", "1.1.1", logger: @logger) end describe "urls" do it "ftp" do @recipe.files << "ftp://localhost:#{TestCase::HTTP_PORT}/foo" server_must_receive_connection 1 do @recipe.download end end it "handles http" do @recipe.files << "http://localhost:#{TestCase::HTTP_PORT}/foo" server_must_receive_connection 3 do @recipe.download end end it "handles https" do @recipe.files << "https://localhost:#{TestCase::HTTP_PORT}/foo" server_must_receive_connection 3 do @recipe.download end end it "file" do dest = "ports/archives/test-download-archive.tar.gz" FileUtils.rm_f dest path = File.expand_path(File.join(File.dirname(__FILE__), "assets", "test-download-archive.tar.gz")) @recipe.files << "file://#{path}" @recipe.download assert File.exist?(dest) assert_equal("ee0e9f44e72213015ef976d5ac23931d", Digest::MD5.file(dest).hexdigest) end it "other" do @recipe.files << "foo://foo" assert_raises(ArgumentError) { @recipe.download } end end end mini_portile2-2.8.7/test/assets/0000755000004100000410000000000014630451726016625 5ustar www-datawww-datamini_portile2-2.8.7/test/assets/patch 1.diff0000644000004100000410000000022214630451726020673 0ustar www-datawww-datadiff --git "a/patch 1.txt" "b/patch 1.txt" new file mode 100644 index 0000000..70885e4 --- /dev/null +++ "b/patch 1.txt" @@ -0,0 +1 @@ + change 1 mini_portile2-2.8.7/test/assets/pkgconf/0000755000004100000410000000000014630451726020254 5ustar www-datawww-datamini_portile2-2.8.7/test/assets/pkgconf/libxslt/0000755000004100000410000000000014630451726021735 5ustar www-datawww-datamini_portile2-2.8.7/test/assets/pkgconf/libxslt/libexslt.pc0000644000004100000410000000042614630451726024111 0ustar www-datawww-dataprefix=/foo/libxslt/1.1.38 exec_prefix=${prefix} libdir=/foo/libxslt/1.1.38/lib includedir=${prefix}/include Name: libexslt Version: 0.8.21 Description: EXSLT Extension library Requires: libxml-2.0, libxslt Cflags: -I${includedir} Libs: -L${libdir} -lexslt Libs.private: -lm mini_portile2-2.8.7/test/assets/pkgconf/libxslt/libxslt.pc0000644000004100000410000000045714630451726023750 0ustar www-datawww-dataprefix=/foo/libxslt/1.1.38 exec_prefix=${prefix} libdir=/foo/libxslt/1.1.38/lib includedir=${prefix}/include Name: libxslt Version: 1.1.38 Description: XSLT library version 2. Requires: libxml-2.0 Cflags: -I${includedir} -Wno-deprecated-enum-enum-conversion Libs: -L${libdir} -lxslt Libs.private: -lm mini_portile2-2.8.7/test/assets/pkgconf/libxml2/0000755000004100000410000000000014630451726021625 5ustar www-datawww-datamini_portile2-2.8.7/test/assets/pkgconf/libxml2/libxml-2.0.pc0000644000004100000410000000046514630451726023742 0ustar www-datawww-dataprefix=/foo/libxml2/2.11.5 exec_prefix=${prefix} libdir=/foo/libxml2/2.11.5/lib includedir=${prefix}/include modules=1 Name: libXML Version: 2.11.5 Description: libXML library version2. Requires: Libs: -L${libdir} -lxml2 Libs.private: -L/foo/zlib/1.3/lib -lz -lm Cflags: -I${includedir}/libxml2 -ggdb3 mini_portile2-2.8.7/test/assets/git/0000755000004100000410000000000014630451726017410 5ustar www-datawww-datamini_portile2-2.8.7/test/assets/git/config0000644000004100000410000000012014630451726020571 0ustar www-datawww-data[core] whitespace=tab-in-indent,-indent-with-non-tab [apply] whitespace=fix mini_portile2-2.8.7/test/assets/test-cmake-1.0/0000755000004100000410000000000014630451726021156 5ustar www-datawww-datamini_portile2-2.8.7/test/assets/test-cmake-1.0/hello.c0000644000004100000410000000006114630451726022422 0ustar www-datawww-dataint main(int argc, char** argv) { return 0 ; } mini_portile2-2.8.7/test/assets/test-cmake-1.0/CMakeLists.txt0000644000004100000410000000047214630451726023721 0ustar www-datawww-data# CMakeLists files in this project can # refer to the root source directory of the project as ${HELLO_SOURCE_DIR} and # to the root binary directory of the project as ${HELLO_BINARY_DIR}. cmake_minimum_required (VERSION 2.8.7) project (HELLO) add_executable (hello hello.c) install (TARGETS hello DESTINATION bin) mini_portile2-2.8.7/test/assets/test mini portile-1.0.0/0000755000004100000410000000000014630451726022612 5ustar www-datawww-datamini_portile2-2.8.7/test/assets/test mini portile-1.0.0/configure0000755000004100000410000000026414630451726024523 0ustar www-datawww-data#!/bin/sh set -e ruby -e "p ARGV" -- "$@" > configure.txt cat <Makefile all: ruby -e "p ARGV" -- "\$@" > compile.txt install: ruby -e "p ARGV" -- "\$@" > install.txt EOT mini_portile2-2.8.7/test/assets/test-download-archive.tar.gz0000644000004100000410000000017114630451726024156 0ustar www-datawww-data1 0%'y:A@[[AAp{aaOi3 噹3B.놮%buY90[Or\~Gpe(mini_portile2-2.8.7/test/assets/gpg-fixtures/0000755000004100000410000000000014630451726021251 5ustar www-datawww-datamini_portile2-2.8.7/test/assets/gpg-fixtures/data.invalid.asc0000644000004100000410000000045314630451726024301 0ustar www-datawww-data-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iJwEAQECAAYFAlcFLEgACgkQZeg+SWTDcLPVwgQAg8KTI91Ryx38YplzgWV9tUPj o7J7IEzb8faE7m2mgtq8m62DvA4h/PJzmbh1EJJ4VkO+A4O2LVh/bTgnyYXv+kMu sEmvK35PnAC8r7pv98VSbMEXyV/rK3+uGhTvnXZYkULvMVYkN/EHIh2bCQJ3R14X MY8El95QST8/dR/yBkw= =qbod -----END PGP SIGNATURE----- mini_portile2-2.8.7/test/assets/gpg-fixtures/data0000644000004100000410000000000514630451726022100 0ustar www-datawww-datatest mini_portile2-2.8.7/test/assets/gpg-fixtures/data.asc0000644000004100000410000000045314630451726022654 0ustar www-datawww-data-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iJwEAAECAAYFAlcFOD8ACgkQZeg+SWTDcLNIswP/XvVRoJ+eQ2u2v+WjXdBBKBSW pzM216aJPRBxPl98xNUUKjqga+tjKmIHJn5T4CIxHqis1toPxtE5tKnc6cVO1aqY bCUfkWyt/A3qRHQuniRUWSBKZWdk+j3AopTpd3i/r/s0pDj3bMHJ7bDOTsEskNcM KpgFfNM1ieFRQmIWPWg= =kbKc -----END PGP SIGNATURE----- mini_portile2-2.8.7/test/test_activate.rb0000644000004100000410000000660214630451726020513 0ustar www-datawww-datarequire File.expand_path('../helper', __FILE__) class TestActivate < TestCase attr_reader :recipe def setup super @save_env = %w[PATH CPATH LIBRARY_PATH LDFLAGS].inject({}) do |env, var| env.update(var => ENV[var]) end FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files @recipe = MiniPortile.new("foo", "1.0.0").tap do |recipe| recipe.logger = StringIO.new end end def teardown FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files @save_env.each do |var, val| ENV[var] = val end super end def test_PATH_env_var_when_bin_does_not_exist ENV["PATH"] = "foo" refute(Dir.exist?(bin_path)) refute_includes(path_elements('PATH'), bin_path) recipe.activate refute_includes(path_elements('PATH'), bin_path) end def test_PATH_env_var_when_bin_exists ENV["PATH"] = "foo" FileUtils.mkdir_p(bin_path) refute_includes(path_elements('PATH'), bin_path) recipe.activate assert_includes(path_elements('PATH'), bin_path) assert_equal(path_elements('PATH').first, bin_path) end def test_CPATH_env_var_when_include_does_not_exist ENV["CPATH"] = "foo" refute(Dir.exist?(include_path)) refute_includes(path_elements('CPATH'), include_path) recipe.activate refute_includes(path_elements('CPATH'), include_path) end def test_CPATH_env_var_when_include_exists ENV["CPATH"] = "foo" FileUtils.mkdir_p(include_path) refute_includes(path_elements('CPATH'), include_path) recipe.activate assert_includes(path_elements('CPATH'), include_path) assert_equal(path_elements('CPATH').first, include_path) end def test_LIBRARY_PATH_env_var_when_lib_does_not_exist ENV["LIBRARY_PATH"] = "foo" refute(Dir.exist?(lib_path)) refute_includes(path_elements('LIBRARY_PATH'), lib_path) recipe.activate refute_includes(path_elements('LIBRARY_PATH'), lib_path) end def test_LIBRARY_PATH_env_var_when_lib_exists ENV["LIBRARY_PATH"] = "foo" FileUtils.mkdir_p(lib_path) refute_includes(path_elements('LIBRARY_PATH'), lib_path) recipe.activate assert_includes(path_elements('LIBRARY_PATH'), lib_path) assert_equal(path_elements('LIBRARY_PATH').first, lib_path) end def test_LDFLAGS_env_var_when_not_cross_compiling ENV["LDFLAGS"] = "-lfoo" FileUtils.mkdir_p(lib_path) assert_equal(recipe.host, recipe.original_host) # assert on setup) refute_includes(flag_elements('LDFLAGS'), "-L#{lib_path}") recipe.activate refute_includes(flag_elements('LDFLAGS'), "-L#{lib_path}") end def test_LDFLAGS_env_var_when_cross_compiling ENV["LDFLAGS"] = "-lfoo" recipe.host = recipe.original_host + "-x" # make them not-equal FileUtils.mkdir_p(lib_path) refute_includes(flag_elements('LDFLAGS'), "-L#{lib_path}") recipe.activate assert_includes(flag_elements('LDFLAGS'), "-L#{lib_path}") assert_equal(flag_elements('LDFLAGS').first, "-L#{lib_path}") end private def path_elements(varname) ENV.fetch(varname, "").split(File::PATH_SEPARATOR) end def flag_elements(varname) ENV.fetch(varname, "").split end def bin_path MiniPortile.native_path(File.join(recipe.path, "bin")) end def include_path MiniPortile.native_path(File.join(recipe.path, "include")) end def lib_path MiniPortile.native_path(File.join(recipe.path, "lib")) end end mini_portile2-2.8.7/test/helper.rb0000644000004100000410000000334214630451726017131 0ustar www-datawww-datarequire 'minitest/autorun' require 'minitest/unit' require 'minitest/spec' require 'minitest/hooks/test' require 'webrick' require 'fileutils' require 'zlib' require 'archive/tar/minitar' require 'fileutils' require 'erb' require 'mini_portile2' require 'logger' puts "#{__FILE__}:#{__LINE__}: relevant RbConfig::CONFIG values:" %w[target_os target_cpu CC CXX].each do |key| puts "- #{key}: #{RbConfig::CONFIG[key].inspect}" end class TestCase < Minitest::Test include Minitest::Hooks HTTP_PORT = 23523 attr_accessor :webrick def start_webrick(path) @webrick = WEBrick::HTTPServer.new( :Port => HTTP_PORT, :DocumentRoot => path, :Logger => Logger.new(File::NULL), :AccessLog => [], ).tap do |w| Thread.new do w.start end until w.status==:Running sleep 0.1 end end end def stop_webrick if w=@webrick w.shutdown until w.status==:Stop sleep 0.1 end end end def create_tar(tar_path, assets_path, directory) FileUtils.mkdir_p(File.dirname(tar_path)) Zlib::GzipWriter.open(tar_path) do |fdtgz| Dir.chdir(assets_path) do Archive::Tar::Minitar.pack(directory, fdtgz) end end end def work_dir(r=recipe) "tmp/#{r.host}/ports/#{r.name}/#{r.version}/#{r.name}-#{r.version}" end def with_custom_git_dir(dir) old = ENV['GIT_DIR'] ENV['GIT_DIR'] = dir yield ensure ENV['GIT_DIR'] = old end def with_env(env) before = ENV.to_h.dup env.each { |k, v| ENV[k] = v } yield ensure ENV.replace(before) end def without_env(*keys, &blk) before = ENV.to_h.dup keys.flatten.each { |k| ENV.delete(k) } yield ensure ENV.replace(before) end end mini_portile2-2.8.7/test/test_cook.rb0000644000004100000410000001500014630451726017636 0ustar www-datawww-datarequire File.expand_path('../helper', __FILE__) class TestCook < TestCase attr_accessor :assets_path, :tar_path, :recipe def before_all super @assets_path = File.expand_path("../assets", __FILE__) @tar_path = File.expand_path("../../tmp/test mini portile-1.0.0.tar.gz", __FILE__) FileUtils.rm_rf("tmp") # remove any previous test files create_tar(@tar_path, @assets_path, "test mini portile-1.0.0") start_webrick(File.dirname(@tar_path)) @logger = StringIO.new # IO to keep recipe logs in case we need to debug @recipe = MiniPortile.new("test mini portile", "1.0.0").tap do |recipe| recipe.logger = @logger recipe.files << "http://localhost:#{HTTP_PORT}/#{ERB::Util.url_encode(File.basename(@tar_path))}" recipe.patch_files << File.join(@assets_path, "patch 1.diff") recipe.configure_options << "--option=\"path with 'space'\"" git_dir = File.join(@assets_path, "git") with_custom_git_dir(git_dir) do recipe.cook end end rescue => e puts @logger.string raise e end def after_all super stop_webrick FileUtils.rm_rf("tmp") # remove test files end def test_download download = "ports/archives/test%20mini%20portile-1.0.0.tar.gz" assert File.exist?(download), download end def test_untar configure = File.join(work_dir, "configure") assert File.exist?(configure), configure assert_match( /^#!\/bin\/sh/, IO.read(configure) ) end def test_patch patch1 = File.join(work_dir, "patch 1.txt") assert File.exist?(patch1), patch1 assert_match( /^\tchange 1/, IO.read(patch1) ) end def test_configure txt = File.join(work_dir, "configure.txt") assert File.exist?(txt), txt opts = recipe.configure_options + ["--prefix=#{recipe.path}"] assert_equal( opts.inspect, IO.read(txt).chomp ) end def test_compile txt = File.join(work_dir, "compile.txt") assert File.exist?(txt), txt assert_equal( ["all"].inspect, IO.read(txt).chomp ) end def test_install txt = File.join(work_dir, "install.txt") assert File.exist?(txt), txt assert_equal( ["install"].inspect, IO.read(txt).chomp ) end end class TestCookConfiguration < TestCase def test_make_command_configuration without_env("MAKE") do assert_equal("make", MiniPortile.new("test", "1.0.0").make_cmd) assert_equal("xyzzy", MiniPortile.new("test", "1.0.0", make_command: "xyzzy").make_cmd) end with_env("MAKE"=>"asdf") do assert_equal("asdf", MiniPortile.new("test", "1.0.0").make_cmd) assert_equal("asdf", MiniPortile.new("test", "1.0.0", make_command: "xyzzy").make_cmd) end end def test_cc_command_configuration without_env("CC") do expected_compiler = RbConfig::CONFIG["CC"] || "gcc" assert_equal(expected_compiler, MiniPortile.new("test", "1.0.0").cc_cmd) assert_equal(expected_compiler, MiniPortile.new("test", "1.0.0").gcc_cmd) assert_equal("xyzzy", MiniPortile.new("test", "1.0.0", cc_command: "xyzzy").cc_cmd) assert_equal("xyzzy", MiniPortile.new("test", "1.0.0", gcc_command: "xyzzy").cc_cmd) assert_equal("xyzzy", MiniPortile.new("test", "1.0.0", cc_command: "xyzzy").gcc_cmd) assert_equal("xyzzy", MiniPortile.new("test", "1.0.0", gcc_command: "xyzzy").gcc_cmd) end with_env("CC"=>"asdf") do assert_equal("asdf", MiniPortile.new("test", "1.0.0").cc_cmd) assert_equal("asdf", MiniPortile.new("test", "1.0.0").gcc_cmd) assert_equal("asdf", MiniPortile.new("test", "1.0.0", cc_command: "xyzzy").cc_cmd) assert_equal("asdf", MiniPortile.new("test", "1.0.0", gcc_command: "xyzzy").cc_cmd) assert_equal("asdf", MiniPortile.new("test", "1.0.0", cc_command: "xyzzy").gcc_cmd) assert_equal("asdf", MiniPortile.new("test", "1.0.0", gcc_command: "xyzzy").gcc_cmd) end end def test_cxx_command_configuration without_env("CXX") do expected_compiler = RbConfig::CONFIG["CXX"] || "g++" assert_equal(expected_compiler, MiniPortile.new("test", "1.0.0").cxx_cmd) assert_equal("xyzzy", MiniPortile.new("test", "1.0.0", cxx_command: "xyzzy").cxx_cmd) end with_env("CXX"=>"asdf") do assert_equal("asdf", MiniPortile.new("test", "1.0.0").cxx_cmd) assert_equal("asdf", MiniPortile.new("test", "1.0.0", cxx_command: "xyzzy").cxx_cmd) end end end class TestCookWithBrokenGitDir < TestCase # # this is a test for #69 # https://github.com/flavorjones/mini_portile/issues/69 # attr_accessor :assets_path, :tar_path, :recipe def before_all super @assets_path = File.expand_path("../assets", __FILE__) @tar_path = File.expand_path("../../tmp/test-mini-portile-1.0.0.tar.gz", __FILE__) @git_dir = File.join(@assets_path, "git-broken") FileUtils.rm_rf @git_dir FileUtils.mkdir_p @git_dir Dir.chdir(@git_dir) do File.open ".git", "w" do |f| f.write "gitdir: /nonexistent" end end create_tar(@tar_path, @assets_path, "test mini portile-1.0.0") @logger = StringIO.new # IO to keep recipe logs in case we need to debug @recipe = MiniPortile.new("test mini portile", "1.0.0").tap do |recipe| recipe.logger = @logger recipe.files << "file://#{@tar_path}" recipe.patch_files << File.join(@assets_path, "patch 1.diff") recipe.configure_options << "--option=\"path with 'space'\"" end Dir.chdir(@git_dir) do @recipe.cook end end def after_all FileUtils.rm_rf @git_dir end def test_patch Dir.chdir(@git_dir) do patch1 = File.join(work_dir, "patch 1.txt") assert File.exist?(patch1), patch1 assert_match( /^\tchange 1/, IO.read(patch1) ) end end end class TestCookAgainstSourceDirectory < TestCase attr_accessor :recipe def setup super @logger = StringIO.new # IO to keep recipe logs in case we need to debug @recipe ||= MiniPortile.new("test mini portile", "1.0.0").tap do |recipe| recipe.logger = @logger recipe.source_directory = File.expand_path("../assets/test mini portile-1.0.0", __FILE__) end end def test_source_directory recipe.cook path = File.join(work_dir, "configure.txt") assert(File.exist?(path)) assert_equal((recipe.configure_options + ["--prefix=#{recipe.path}"]).inspect, File.read(path).chomp); path = File.join(work_dir, "compile.txt") assert(File.exist?(path)) assert_equal("[\"all\"]", File.read(path).chomp); path = File.join(work_dir, "install.txt") assert(File.exist?(path)) assert_equal("[\"install\"]", File.read(path).chomp); end end mini_portile2-2.8.7/test/test_mkmf_config.rb0000644000004100000410000001525514630451726021176 0ustar www-datawww-datarequire File.expand_path('../helper', __FILE__) require "mkmf" # initialize $LDFLAGS et al here, instead of in the middle of a test class TestMkmfConfig < TestCase attr_reader :recipe LIBXML_PCP = File.join(__dir__, "assets", "pkgconf", "libxml2") LIBXSLT_PCP = File.join(__dir__, "assets", "pkgconf", "libxslt") def make_recipe(name, version) MiniPortile.new(name, version).tap do |recipe| recipe.logger = StringIO.new # hush output end end def setup super @save_env = %w[PATH CPATH LIBRARY_PATH LDFLAGS PKG_CONFIG_PATH].inject({}) do |env, var| env.update(var => ENV[var]) end $INCFLAGS = "-I/xxx" $LIBPATH = ["xxx"] $CFLAGS = "-xxx" $CXXFLAGS = "-xxx" $libs = "-lxxx" $MINI_PORTILE_STATIC_LIBS = {} FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files @recipe = make_recipe("libfoo", "1.0.0") end def teardown FileUtils.rm_rf(["tmp", "ports"]) # remove any previous test files $INCFLAGS = "" $LIBPATH = [] $CFLAGS = "" $CXXFLAGS = "" $libs = "" $MINI_PORTILE_STATIC_LIBS = {} @save_env.each do |var, val| ENV[var] = val end super end def test_mkmf_config_recipe_LIBPATH_global_lib_dir_does_not_exist recipe.mkmf_config refute_includes($LIBPATH, recipe.lib_path) refute_includes($libs.shellsplit, "-lfoo") end def test_mkmf_config_recipe_LIBPATH_global_not_static FileUtils.mkdir_p(recipe.lib_path) recipe.mkmf_config assert_includes($LIBPATH, recipe.lib_path) assert_operator($LIBPATH.index(recipe.lib_path), :<, $LIBPATH.index("xxx")) # prepend assert_includes($libs.shellsplit, "-lfoo") # note the recipe name is "libfoo" assert_match(%r{-lfoo.*-lxxx}, $libs) # prepend end def test_mkmf_config_recipe_LIBPATH_global_static FileUtils.mkdir_p(recipe.lib_path) static_lib_path = File.join(recipe.lib_path, "libfoo.#{$LIBEXT}") recipe.mkmf_config(static: "foo") refute_includes($LIBPATH, recipe.lib_path) refute_includes($libs.shellsplit, "-lfoo") # note the recipe name is "libfoo" assert_includes($libs.shellsplit, static_lib_path) assert_match(%r{#{static_lib_path}.*-lxxx}, $libs) # prepend end def test_mkmf_config_recipe_INCFLAGS_global_include_dir_does_not_exist recipe.mkmf_config refute_includes($INCFLAGS.shellsplit, "-I#{recipe.include_path}") end def test_mkmf_config_recipe_INCFLAGS_global FileUtils.mkdir_p(recipe.include_path) recipe.mkmf_config assert_includes($INCFLAGS.shellsplit, "-I#{recipe.include_path}") assert_match(%r{-I#{recipe.include_path}.*-I/xxx}, $INCFLAGS) # prepend end def test_mkmf_config_pkgconf_does_not_exist assert_raises(ArgumentError) do recipe.mkmf_config(pkg: "foo") end end def test_mkmf_config_pkgconf_LIBPATH_global_not_static # can't get the pkgconf utility to install on windows with ruby 2.3 in CI skip if MiniPortile.windows? && RUBY_VERSION < "2.4" recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP) assert_includes($LIBPATH, "/foo/libxml2/2.11.5/lib") assert_operator($LIBPATH.index("/foo/libxml2/2.11.5/lib"), :<, $LIBPATH.index("xxx")) # prepend refute_includes($LIBPATH, "/foo/zlib/1.3/lib") assert_includes($libs.shellsplit, "-lxml2") assert_match(%r{-lxml2.*-lxxx}, $libs) # prepend refute_includes($libs.shellsplit, "-lz") end def test_mkmf_config_pkgconf_LIBPATH_global_static # can't get the pkgconf utility to install on windows with ruby 2.3 in CI skip if MiniPortile.windows? && RUBY_VERSION < "2.4" static_lib_path = "/foo/libxml2/2.11.5/lib/libxml2.#{$LIBEXT}" recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP, static: "xml2") refute_includes($LIBPATH, "/foo/libxml2/2.11.5/lib") refute_includes($libs.shellsplit, "-lxml2") assert_includes($libs.shellsplit, static_lib_path) assert_match(%r{#{static_lib_path}.*-lxxx}, $libs) # prepend assert_includes($LIBPATH, "/foo/zlib/1.3/lib") # from --static assert_includes($libs.shellsplit, "-lz") # from --static end def test_mkmf_config_pkgconf_CFLAGS_global # can't get the pkgconf utility to install on windows with ruby 2.3 in CI skip if MiniPortile.windows? && RUBY_VERSION < "2.4" recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP) assert_includes($INCFLAGS.shellsplit, "-I/foo/libxml2/2.11.5/include/libxml2") assert_match(%r{-I/foo/libxml2/2.11.5/include/libxml2.*-I/xxx}, $INCFLAGS) # prepend assert_includes($CFLAGS.shellsplit, "-ggdb3") assert_match(%r{-xxx.*-ggdb3}, $CFLAGS) # append assert_includes($CXXFLAGS.shellsplit, "-ggdb3") assert_match(%r{-xxx.*-ggdb3}, $CXXFLAGS) # append end def test_mkmf_config_pkgconf_path_accumulation # can't get the pkgconf utility to install on windows with ruby 2.3 in CI skip if MiniPortile.windows? && RUBY_VERSION < "2.4" (ENV["PKG_CONFIG_PATH"] || "").split(File::PATH_SEPARATOR).tap do |pcpaths| refute_includes(pcpaths, LIBXML_PCP) refute_includes(pcpaths, LIBXSLT_PCP) end make_recipe("libxml2", "2.11.5").tap do |recipe| recipe.mkmf_config(pkg: "libxml-2.0", dir: LIBXML_PCP, static: "xml2") ENV["PKG_CONFIG_PATH"].split(File::PATH_SEPARATOR).tap do |pcpaths| assert_includes(pcpaths, LIBXML_PCP) refute_includes(pcpaths, LIBXSLT_PCP) end end make_recipe("libxslt", "1.13.8").tap do |recipe| recipe.mkmf_config(pkg: "libxslt", dir: LIBXSLT_PCP, static: "xslt") ENV["PKG_CONFIG_PATH"].split(File::PATH_SEPARATOR).tap do |pcpaths| assert_includes(pcpaths, LIBXML_PCP) assert_includes(pcpaths, LIBXSLT_PCP) end recipe.mkmf_config(pkg: "libexslt", dir: LIBXSLT_PCP, static: "exslt") end $INCFLAGS.shellsplit.tap do |incflags| assert_includes(incflags, "-I/foo/libxml2/2.11.5/include/libxml2") assert_includes(incflags, "-I/foo/libxslt/1.1.38/include") end $CFLAGS.shellsplit.tap do |cflags| assert_includes(cflags, "-ggdb3") assert_includes(cflags, "-Wno-deprecated-enum-enum-conversion") end refute_includes($LIBPATH, "/foo/libxml2/2.11.5/lib") refute_includes($LIBPATH, "/foo/libxslt/1.1.38/lib") assert_includes($LIBPATH, "/foo/zlib/1.3/lib") # from `--static` $libs.shellsplit.tap do |libflags| refute_includes(libflags, "-lxml2") assert_includes(libflags, "/foo/libxml2/2.11.5/lib/libxml2.#{$LIBEXT}") refute_includes(libflags, "-lxslt") assert_includes(libflags, "/foo/libxslt/1.1.38/lib/libxslt.#{$LIBEXT}") refute_includes(libflags, "-lexslt") assert_includes(libflags, "/foo/libxslt/1.1.38/lib/libexslt.#{$LIBEXT}") assert_includes(libflags, "-lz") # from `--static` end end end mini_portile2-2.8.7/test/test_execute.rb0000644000004100000410000000224414630451726020353 0ustar www-datawww-datarequire_relative "helper" class TestExecute < TestCase def setup super @env = {"TEST_ENV_VAR1" => "VAR1_VALUE", "TEST_ENV_VAR2" => "VAR2_VALUE"} @logger = StringIO.new @recipe = MiniPortile.new("test_execute", "1.0.0", logger: @logger) @log_path = @recipe.send(:tmp_path) FileUtils.mkdir_p File.join(@log_path, "subdir") # normally created by `download` end def test_execute_one_big_string_arg class << @recipe def execute_with_env(env) execute("testenv1", %Q(ruby -e "puts ENV['TEST_ENV_VAR1'].inspect ; exit 0"), {:env => env, :initial_message => false}) end end @recipe.execute_with_env(@env) assert_equal("VAR1_VALUE".inspect, IO.read(File.join(@log_path, "testenv1.log")).chomp) end def test_execute_array_args class << @recipe def execute_with_env(env) execute("testenv2", ["ruby", "-e", "puts ENV['TEST_ENV_VAR2'].inspect"], {:env => env, :initial_message => false}) end end @recipe.execute_with_env(@env) assert_equal("VAR2_VALUE".inspect, IO.read(File.join(@log_path, "testenv2.log")).chomp) end end mini_portile2-2.8.7/test/test_proxy.rb0000644000004100000410000000715414630451726020077 0ustar www-datawww-data# Encoding: utf-8 require File.expand_path('../helper', __FILE__) require 'socket' class TestProxy < TestCase def with_dummy_proxy(username=nil, password=nil) gs = TCPServer.open('localhost', 0) th = Thread.new do s = gs.accept gs.close begin req = ''.dup while (l=s.gets) && !l.chomp.empty? req << l end req ensure s.close end end if username && password yield "http://#{ERB::Util.url_encode(username)}:#{ERB::Util.url_encode(password)}@localhost:#{gs.addr[1]}" else yield "http://localhost:#{gs.addr[1]}" end # Set timeout for reception of the request Thread.new do sleep 1 th.kill end th.value end def setup # remove any download files FileUtils.rm_rf("port/archives") @logger = StringIO.new end def assert_proxy_auth(expected, request) if request =~ /^Proxy-Authorization: Basic (.*)/ assert_equal 'user: @name:@12: üMp', $1.unpack("m")[0].force_encoding(__ENCODING__) else flunk "No authentication request" end end def test_http_proxy recipe = MiniPortile.new("test http_proxy", "1.0.0", logger: @logger) recipe.files << "http://myserver/path/to/tar.gz" request = with_dummy_proxy do |url, thread| ENV['http_proxy'] = url recipe.download rescue RuntimeError ENV.delete('http_proxy') end assert_match(/GET http:\/\/myserver\/path\/to\/tar.gz/, request) end def test_http_proxy_with_basic_auth recipe = MiniPortile.new("test http_proxy", "1.0.0", logger: @logger) recipe.files << "http://myserver/path/to/tar.gz" request = with_dummy_proxy('user: @name', '@12: üMp') do |url, thread| ENV['http_proxy'] = url recipe.download rescue RuntimeError ENV.delete('http_proxy') end assert_match(/GET http:\/\/myserver\/path\/to\/tar.gz/, request) assert_proxy_auth 'user: @name:@12: üMp', request end def test_https_proxy recipe = MiniPortile.new("test https_proxy", "1.0.0", logger: @logger) recipe.files << "https://myserver/path/to/tar.gz" request = with_dummy_proxy do |url, thread| ENV['https_proxy'] = url recipe.download rescue RuntimeError ENV.delete('https_proxy') end assert_match(/CONNECT myserver:443/, request) end def test_https_proxy_with_basic_auth recipe = MiniPortile.new("test https_proxy", "1.0.0", logger: @logger) recipe.files << "https://myserver/path/to/tar.gz" request = with_dummy_proxy('user: @name', '@12: üMp') do |url, thread| ENV['https_proxy'] = url recipe.download rescue RuntimeError ENV.delete('https_proxy') end assert_match(/CONNECT myserver:443/, request) assert_proxy_auth 'user: @name:@12: üMp', request end def test_ftp_proxy recipe = MiniPortile.new("test ftp_proxy", "1.0.0", logger: @logger) recipe.files << "ftp://myserver/path/to/tar.gz" request = with_dummy_proxy do |url, thread| ENV['ftp_proxy'] = url recipe.download rescue RuntimeError ENV.delete('ftp_proxy') end assert_match(/GET ftp:\/\/myserver\/path\/to\/tar.gz/, request) end def test_ftp_proxy_with_basic_auth recipe = MiniPortile.new("test ftp_proxy", "1.0.0", logger: @logger) recipe.files << "ftp://myserver/path/to/tar.gz" request = with_dummy_proxy('user: @name', '@12: üMp') do |url, thread| ENV['ftp_proxy'] = url recipe.download rescue RuntimeError ENV.delete('ftp_proxy') end assert_match(/GET ftp:\/\/myserver\/path\/to\/tar.gz/, request) assert_proxy_auth 'user: @name:@12: üMp', request end end mini_portile2-2.8.7/test/test_digest.rb0000644000004100000410000001735114630451726020175 0ustar www-datawww-datarequire File.expand_path('../helper', __FILE__) class TestDigest < TestCase attr :assets_path, :tar_path, :recipe def before_all super @assets_path = File.expand_path("../assets", __FILE__) @tar_path = File.expand_path("../../tmp/test-digest-1.0.0.tar.gz", __FILE__) # remove any previous test files FileUtils.rm_rf("tmp") create_tar(@tar_path, @assets_path, "test mini portile-1.0.0") start_webrick(File.dirname(@tar_path)) end def after_all super stop_webrick # leave test files for inspection end def setup super FileUtils.rm_rf("ports/archives") @logger = StringIO.new # IO to keep recipe logs in case we need to debug @recipe = MiniPortile.new("test-digest", "1.0.0", logger: @logger) end def download_with_digest(key, klass) @recipe.files << { :url => "http://localhost:#{webrick.config[:Port]}/#{ERB::Util.url_encode(File.basename(tar_path))}", key => klass.file(tar_path).hexdigest, } @recipe.download end def download_with_wrong_digest(key) @recipe.files << { :url => "http://localhost:#{webrick.config[:Port]}/#{ERB::Util.url_encode(File.basename(tar_path))}", key => "0011223344556677", } assert_raises(RuntimeError){ @recipe.download } end def test_sha256 download_with_digest(:sha256, Digest::SHA256) end def test_wrong_sha256 download_with_wrong_digest(:sha256) end def test_sha1 download_with_digest(:sha1, Digest::SHA1) end def test_wrong_sha1 download_with_wrong_digest(:sha1) end def test_md5 download_with_digest(:md5, Digest::MD5) end def test_wrong_md5 download_with_wrong_digest(:md5) end def public_key <<~KEY -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mI0EVwUhJQEEAMYxFhgaAdM2Ul5r+XfpqAaI7SOxB14eRjhFjhchy4ylgVxetyLq di3zeANXBIHsLBl7quYTlnmhJr/+GQRkCnXWiUp0tJsBVzGM3puK7c534gakEUH6 AlDtj5p3IeygzSyn8u7KORv+ainXfhwkvTO04mJmxAb2uT8ngKYFdPa1ABEBAAG0 J1Rlc3QgTWluaXBvcnRpbGUgPHRlc3RAbWluaXBvcnRpbGUub3JnPoi4BBMBAgAi BQJXBSElAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBl6D5JZMNwswAK A/90Cdb+PX21weBR2Q6uR06M/alPexuXXyJL8ZcwbQMJ/pBBgcS5/h1+rQkBI/CN qpXdDlw2Xys2k0sNwdjIw3hmYRzBrddXlCSW3Sifq/hS+kfPZ1snQmIjCgy1Xky5 QGCcPUxBUxzmra88LakkDO+euKK3hcrfeFIi611lTum1NLiNBFcFISUBBADoyY6z 2PwH3RWUbqv0VX1s3/JO3v3xMjCRKPlFwsNwLTBtZoWfR6Ao1ajeCuZKfzNKIQ2I rn86Rcqyrq4hTj+7BTWjkIPOBthjiL1YqbEBtX7jcYRkYvdQz/IG2F4zVV6X4AAR Twx7qaXNt67ArzbHCe5gLNRUK6e6OArkahMv7QARAQABiJ8EGAECAAkFAlcFISUC GwwACgkQZeg+SWTDcLNFiwP/TR33ClqWOz0mpjt0xPEoZ0ORmV6fo4sjjzgQoHH/ KTdsabJbGp8oLQGW/mx3OxgbsAkyZymb5H5cjaF4HtSd4cxI5t1C9ZS/ytN8pqfR e29SBje8DAAJn2l57s2OddXLPQ0DUwCcdNEaqgHwSk/Swxc7K+IpfvjLKHKUZZBP 4Ko= =SVWi -----END PGP PUBLIC KEY BLOCK----- KEY end def test_with_valid_gpg_signature data_file = File.expand_path(File.join(File.dirname(__FILE__), 'assets', 'gpg-fixtures', 'data')) @recipe.files << { :url => "file://#{data_file}", :gpg => { :key => public_key, :signature_url => "file://#{data_file}.asc" } } @recipe.download end def test_optional_gpg_signature_url data_file = File.expand_path(File.join(File.dirname(__FILE__), 'assets', 'gpg-fixtures', 'data')) @recipe.files << { :url => "file://#{data_file}", :gpg => { :key => public_key } } @recipe.download end def test_with_invalid_gpg_signature data_file = File.expand_path(File.join(File.dirname(__FILE__), 'assets', 'gpg-fixtures', 'data')) @recipe.files << { :url => "file://#{data_file}", :gpg => { :key => public_key, :signature_url => "file://#{data_file}.invalid.asc" } } exception = assert_raises(RuntimeError){ @recipe.download } assert_includes(exception.message, "signature mismatch") end def test_with_invalid_key data_file = File.expand_path(File.join(File.dirname(__FILE__), 'assets', 'gpg-fixtures', 'data')) @recipe.files << { :url => "file://#{data_file}", :gpg => { :key => "thisisaninvalidkey", :signature_url => "file://#{data_file}.asc" } } exception = assert_raises(RuntimeError){ @recipe.download } assert_includes(exception.message, "invalid gpg key provided") end def test_with_different_key_than_one_used_to_sign key = <<~KEY -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQENBE7SKu8BCADQo6x4ZQfAcPlJMLmL8zBEBUS6GyKMMMDtrTh3Yaq481HB54oR 0cpKL05Ff9upjrIzLD5TJUCzYYM9GQOhguDUP8+ZU9JpSz3yO2TvH7WBbUZ8FADf hblmmUBLNgOWgLo3W+FYhl3mz1GFS2Fvid6Tfn02L8CBAj7jxbjL1Qj/OA/WmLLc m6BMTqI7IBlYW2vyIOIHasISGiAwZfp0ucMeXXvTtt14LGa8qXVcFnJTdwbf03AS ljhYrQnKnpl3VpDAoQt8C68YCwjaNJW59hKqWB+XeIJ9CW98+EOAxLAFszSyGanp rCqPd0numj9TIddjcRkTA/ZbmCWK+xjpVBGXABEBAAG0IU1heGltIERvdW5pbiA8 bWRvdW5pbkBtZG91bmluLnJ1PohGBBARAgAGBQJO01Y/AAoJEOzw6QssFyCDVyQA n3qwTZlcZgyyzWu9Cs8gJ0CXREaSAJ92QjGLT9DijTcbB+q9OS/nl16Z/IhGBBAR AgAGBQJO02JDAAoJEKk3YTmlJMU+P64AnjCKEXFelSVMtgefJk3+vpyt3QX1AKCH 9M3MbTWPeDUL+MpULlfdyfvjj4heBBARCAAGBQJRCTwgAAoJEFGFCWhsfl6CzF0B AJsQ3DJbtGcZ+0VIcM2a06RRQfBvIHqm1A/1WSYmObLGAP90lxWlNjSugvUUlqTk YEEgRTGozgixSyMWGJrNwqgMYokBOAQTAQIAIgUCTtIq7wIbAwYLCQgHAwIGFQgC CQoLBBYCAwECHgECF4AACgkQUgqZk6HAUvj+iwf/b4FS6zVzJ5T0v1vcQGD4ZzXe D5xMC4BJW414wVMU15rfX7aCdtoCYBNiApPxEd7SwiyxWRhRA9bikUq87JEgmnyV 0iYbHZvCvc1jOkx4WR7E45t1Mi29KBoPaFXA9X5adZkYcOQLDxa2Z8m6LGXnlF6N tJkxQ8APrjZsdrbDvo3HxU9muPcq49ydzhgwfLwpUs11LYkwB0An9WRPuv3jporZ /XgI6RfPMZ5NIx+FRRCjn6DnfHboY9rNF6NzrOReJRBhXCi6I+KkHHEnMoyg8XET 9lVkfHTOl81aIZqrAloX3/00TkYWyM2zO9oYpOg6eUFCX/Lw4MJZsTcT5EKVxIkC HAQQAQIABgUCVJ1r4wAKCRDrF/Z0x5pAovwnD/9m8aiSDoUo9IbDSx0345a7IsmN KlEqtz4AQxbqxXV3yTANBbhWWnsX6e7PLbJfzpNE9aoa72upwTcStpk6vlPea0AV ed83FdVsfxwXm/Sf5iySZKy93PexAZfw7KvXu0ETWxi1YZjFNtNsdUIiuJ4upLNo h3urG8NC9uIQYgZef9NPTztmj77saerUrdXt3PQmnYp8ti0NWElE3KzgjoC1fIEZ Na4LZSbEnzdadtuWDehQs1JFxuX/lZhHuVdKgagaMn35j4xubDgy6S9iqRsgJ2Jo U5o/4B+n5h53uAek4eXAEi0MX3k3RxgAf+ofKiri+oG6zIZcoSpUzj+bOUtVSZwt 3lsOahDNx5Hd+Atx9iZsylqa/l9iowb+lHfzFAx/58jFhBumn69rNpe9JnJa+vCb YIsKTiKoJirFSGEgAkcTVXAvo/aD+XiWzc/QP/l+B2X4e5mqR7dF7xLZ5uFbXA0j AfWMyBtvy/XwBT1SxROXpmCt7J0C9wX5l+3vmTpo6BH6S78BYM+eN/NNZW6eJwAG km0y3hI1um7pwmzsaE9Pi1xCYEhn6lcLrwPaGXUBCeoTDnO47mrBMAFOmSe8uoRf 6nYd/TPvXV2Zw0YhjvBzlIfkl5MlJ+j4AZy1hn7Mqe1O//bRd0KKLjjhMQ6tjR6Y sbUJgKqfgA+W9qxUcLkBDQRO0irvAQgA0LjCc8S6oZzjiap2MjRNhRFA5BYjXZRZ BdKF2VP74avt2/RELq8GW0n7JWmKn6vvrXabEGLyfkCngAhTq9tJ/K7LPx/bmlO5 +jboO/1inH2BTtLiHjAXvicXZk3oaZt2Sotx5mMI3yzpFQRVqZXsi0LpUTPJEh3o S8IdYRjslQh1A7P5hfCZwtzwb/hKm8upODe/ITUMuXeWfLuQj/uEU6wMzmfMHb+j lYMWtb+v98aJa2FODeKPmWCXLa7bliXp1SSeBOEfIgEAmjM6QGlDx5sZhr2Ss2xS PRdZ8DqD7oiRVzmstX1YoxEzC0yXfaefC7SgM0nMnaTvYEOYJ9CH3wARAQABiQEf BBgBAgAJBQJO0irvAhsMAAoJEFIKmZOhwFL4844H/jo8icCcS6eOWvnen7lg0FcC o1fIm4wW3tEmkQdchSHECJDq7pgTloN65pwB5tBoT47cyYNZA9eTfJVgRc74q5ce xKOYrMC3KuAqWbwqXhkVs0nkWxnOIidTHSXvBZfDFA4Idwte94Thrzf8Pn8UESud TiqrWoCBXk2UyVsl03gJblSJAeJGYPPeo+Yj6m63OWe2+/S2VTgmbPS/RObn0Aeg 7yuff0n5+ytEt2KL51gOQE2uIxTCawHr12PsllPkbqPk/PagIttfEJqn9b0CrqPC 3HREePb2aMJ/Ctw/76COwn0mtXeIXLCTvBmznXfaMKllsqbsy2nCJ2P2uJjOntw= =4JAR -----END PGP PUBLIC KEY BLOCK----- KEY data_file = File.expand_path(File.join(File.dirname(__FILE__), 'assets', 'gpg-fixtures', 'data')) @recipe.files << { :url => "file://#{data_file}", :gpg => { :key => key, :signature_url => "file://#{data_file}.asc" } } exception = assert_raises(RuntimeError){ @recipe.download } assert_includes(exception.message, "signature mismatch") end end mini_portile2-2.8.7/test/test_cmake.rb0000644000004100000410000001773414630451726020003 0ustar www-datawww-datarequire File.expand_path('../helper', __FILE__) class TestCMake < TestCase attr_accessor :assets_path, :tar_path, :recipe def before_all super @assets_path = File.expand_path("../assets", __FILE__) @tar_path = File.expand_path("../../tmp/test-cmake-1.0.tar.gz", __FILE__) # remove any previous test files FileUtils.rm_rf("tmp") create_tar(@tar_path, @assets_path, "test-cmake-1.0") start_webrick(File.dirname(@tar_path)) @logger = StringIO.new # IO to keep recipe logs in case we need to debug @recipe = init_recipe git_dir = File.join(@assets_path, "git") with_custom_git_dir(git_dir) do recipe.cook end rescue => e puts @logger.string raise e end def after_all super stop_webrick # leave test files for inspection end def exe_name case when MiniPortile.windows? then "hello.exe" else "hello" end end def test_cmake_inherits_from_base assert(MiniPortileCMake <= MiniPortile) end def test_configure cmakecache = File.join(work_dir, "CMakeCache.txt") assert File.exist?(cmakecache), cmakecache assert_includes(IO.read(cmakecache), "CMAKE_INSTALL_PREFIX:PATH=#{recipe.path}") end def test_compile binary = File.join(work_dir, exe_name) assert File.exist?(binary), binary end def test_install binary = File.join(recipe.path, "bin", exe_name) assert File.exist?(binary), binary end def init_recipe MiniPortileCMake.new("test-cmake", "1.0").tap do |recipe| recipe.logger = @logger recipe.files << "http://localhost:#{HTTP_PORT}/#{ERB::Util.url_encode(File.basename(@tar_path))}" recipe.patch_files << File.join(@assets_path, "patch 1.diff") end end end class TestCMakeConfig < TestCMake def test_make_command_configuration MiniPortile.stub(:mswin?, false) do without_env("MAKE") do assert_equal("make", MiniPortileCMake.new("test", "1.0.0").make_cmd) assert_equal("xyzzy", MiniPortileCMake.new("test", "1.0.0", make_command: "xyzzy").make_cmd) end with_env("MAKE"=>"asdf") do assert_equal("asdf", MiniPortileCMake.new("test", "1.0.0").make_cmd) assert_equal("asdf", MiniPortileCMake.new("test", "1.0.0", make_command: "xyzzy").make_cmd) end end MiniPortile.stub(:mswin?, true) do assert_equal("nmake", MiniPortileCMake.new("test", "1.0.0").make_cmd) end end def test_configure_defaults_with_macos with_env({ "CC" => nil, "CXX" => nil }) do MiniPortile.stub(:darwin?, true) do with_stubbed_target(os: 'darwin22', cpu: 'arm64') do with_compilers(c_compiler: 'clang', cxx_compiler: 'clang++') do Open3.stub(:capture2, cmake_help_mock('Unix')) do assert_equal( [ "-DCMAKE_SYSTEM_NAME=Darwin", "-DCMAKE_SYSTEM_PROCESSOR=arm64", "-DCMAKE_C_COMPILER=clang", "-DCMAKE_CXX_COMPILER=clang++", "-DCMAKE_BUILD_TYPE=Release" ], @recipe.configure_defaults) end end end end end end def test_configure_defaults_with_freebsd with_env({ "CC" => nil, "CXX" => nil }) do with_stubbed_target(os: 'freebsd14') do with_compilers(c_compiler: 'cc', cxx_compiler: 'c++') do Open3.stub(:capture2, cmake_help_mock('Unix')) do assert_equal( [ "-DCMAKE_SYSTEM_NAME=FreeBSD", "-DCMAKE_SYSTEM_PROCESSOR=x86_64", "-DCMAKE_C_COMPILER=cc", "-DCMAKE_CXX_COMPILER=c++", "-DCMAKE_BUILD_TYPE=Release" ], @recipe.configure_defaults) end end end end end def test_configure_defaults_with_manual_system_name MiniPortile.stub(:darwin?, false) do with_stubbed_target do with_compilers do Open3.stub(:capture2, cmake_help_mock('Unix')) do @recipe.stub(:system_name, 'Custom') do assert_equal( [ "-DCMAKE_SYSTEM_NAME=Custom", "-DCMAKE_SYSTEM_PROCESSOR=x86_64", "-DCMAKE_C_COMPILER=gcc", "-DCMAKE_CXX_COMPILER=g++", "-DCMAKE_BUILD_TYPE=Release" ], @recipe.configure_defaults) end end end end end end def test_configure_defaults_with_unix_makefiles MiniPortile.stub(:linux?, true) do MiniPortile.stub(:darwin?, false) do with_stubbed_target do with_compilers do Open3.stub(:capture2, cmake_help_mock('Unix')) do MiniPortile.stub(:mingw?, true) do assert_equal(default_x86_compile_flags, @recipe.configure_defaults) end end end end end end end def test_configure_defaults_with_msys_makefiles MiniPortile.stub(:linux?, true) do MiniPortile.stub(:darwin?, false) do with_stubbed_target do with_compilers do Open3.stub(:capture2, cmake_help_mock('MSYS')) do MiniPortile.stub(:mingw?, true) do assert_equal(['-G', 'MSYS Makefiles'] + default_x86_compile_flags, @recipe.configure_defaults) end end end end end end end def test_configure_defaults_with_nmake_makefiles MiniPortile.stub(:linux?, true) do MiniPortile.stub(:darwin?, false) do with_stubbed_target do with_compilers do Open3.stub(:capture2, cmake_help_mock('NMake')) do MiniPortile.stub(:mswin?, true) do assert_equal(['-G', 'NMake Makefiles'] + default_x86_compile_flags, @recipe.configure_defaults) end end end end end end end def test_cmake_command_configuration without_env("CMAKE") do assert_equal("cmake", MiniPortileCMake.new("test", "1.0.0").cmake_cmd) assert_equal("xyzzy", MiniPortileCMake.new("test", "1.0.0", cmake_command: "xyzzy").cmake_cmd) end with_env("CMAKE"=>"asdf") do assert_equal("asdf", MiniPortileCMake.new("test", "1.0.0").cmake_cmd) assert_equal("asdf", MiniPortileCMake.new("test", "1.0.0", cmake_command: "xyzzy").cmake_cmd) end end def test_cmake_build_type_configuration without_env("CMAKE_BUILD_TYPE") do assert_equal("Release", MiniPortileCMake.new("test", "1.0.0").cmake_build_type) assert_equal("xyzzy", MiniPortileCMake.new("test", "1.0.0", cmake_build_type: "xyzzy").cmake_build_type) end with_env("CMAKE_BUILD_TYPE"=>"Debug") do assert_equal("Debug", MiniPortileCMake.new("test", "1.0.0").cmake_build_type) assert_equal("Debug", MiniPortileCMake.new("test", "1.0.0", cmake_build_type: "xyzzy").cmake_build_type) end end private def with_stubbed_target(os: 'linux', cpu: 'x86_64') MiniPortile.stub(:target_os, os) do MiniPortile.stub(:target_cpu, cpu) do yield end end end def with_compilers(c_compiler: 'gcc', cxx_compiler: 'g++') @recipe.stub(:cc_cmd, c_compiler) do @recipe.stub(:cxx_cmd, cxx_compiler) do yield end end end def default_x86_compile_flags [ "-DCMAKE_SYSTEM_NAME=Linux", "-DCMAKE_SYSTEM_PROCESSOR=x86_64", "-DCMAKE_C_COMPILER=gcc", "-DCMAKE_CXX_COMPILER=g++", "-DCMAKE_BUILD_TYPE=Release" ] end def cmake_help_mock(generator_type) open3_mock = MiniTest::Mock.new cmake_script = <<~SCRIPT echo "The following generators are available on this platform (* marks default):" echo "* #{generator_type} Makefiles = Generates standard #{generator_type.upcase} makefiles." SCRIPT exit_status = MiniTest::Mock.new exit_status.expect(:success?, true) expected_output = [cmake_script, exit_status] open3_mock.expect(:call, expected_output, ['cmake --help']) open3_mock end end mini_portile2-2.8.7/test/test_recipe.rb0000644000004100000410000000105714630451726020161 0ustar www-datawww-datarequire File.expand_path('../helper', __FILE__) class TestRecipe < TestCase def test_path recipe = MiniPortile.new("libfoo", "1.0.0") assert_equal(File.expand_path(File.join(recipe.target, recipe.host, recipe.name, recipe.version)), recipe.path) end def test_lib_path recipe = MiniPortile.new("libfoo", "1.0.0") assert_equal(File.join(recipe.path, "lib"), recipe.lib_path) end def test_include_path recipe = MiniPortile.new("libfoo", "1.0.0") assert_equal(File.join(recipe.path, "include"), recipe.include_path) end end mini_portile2-2.8.7/Rakefile0000644000004100000410000000070314630451726016011 0ustar www-datawww-datarequire "rake/clean" require "bundler/gem_tasks" require "rake/testtask" Rake::TestTask.new("test:unit") namespace :test do desc "Test MiniPortile by compiling examples" task :examples do Dir.chdir("examples") do sh "rake ports:all" end end end task :clean do FileUtils.rm_rf ["examples/ports", "examples/tmp"], :verbose => true end desc "Run all tests" task :test => ["test:unit", "test:examples"] task :default => [:test] mini_portile2-2.8.7/Gemfile0000644000004100000410000000030614630451726015636 0ustar www-datawww-datasource 'https://rubygems.org' gem "net-ftp" if Gem::Requirement.new("> 3.1.0.dev").satisfied_by?(Gem::Version.new(RUBY_VERSION)) # Specify your gem's dependencies in mini_portile2.gemspec gemspec mini_portile2-2.8.7/README.md0000644000004100000410000002602414630451726015627 0ustar www-datawww-data# MiniPortile This documents versions 2 and up, for which the require file was renamed to `mini_portile2`. For mini_portile versions 0.6.x and previous, please visit [the v0.6.x branch](https://github.com/flavorjones/mini_portile/tree/v0.6.x). [![Continuous Integration](https://github.com/flavorjones/mini_portile/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/flavorjones/mini_portile/actions/workflows/ci.yml) [![Tidelift dependencies](https://tidelift.com/badges/package/rubygems/mini_portile2)](https://tidelift.com/subscription/pkg/rubygems-mini.portile2?utm_source=undefined&utm_medium=referral&utm_campaign=readme) * Documentation: http://www.rubydoc.info/github/flavorjones/mini_portile * Source Code: https://github.com/flavorjones/mini_portile * Bug Reports: https://github.com/flavorjones/mini_portile/issues This project is a minimalistic implementation of a port/recipe system **for developers**. Because _"Works on my machine"_ is unacceptable for a library maintainer. ## Not Another Package Management System `mini_portile2` is not a general package management system. It is not aimed to replace apt, macports or homebrew. It's intended primarily to make sure that you, as the developer of a library, can reproduce a user's dependencies and environment by specifying a specific version of an underlying dependency that you'd like to use. So, if a user says, "This bug happens on my system that uses libiconv 1.13.1", `mini_portile2` should make it easy for you to download, compile and link against libiconv 1.13.1; and run your test suite against it. This scenario might be simplified with something like this: ``` rake compile LIBICONV_VERSION=1.13.1 ``` (For your homework, you can make libiconv version be taken from the appropriate `ENV` variables.) ## Sounds easy, but where's the catch? At this time `mini_portile2` only supports **autoconf**- or **configure**-based projects. (That is, it assumes the library you want to build contains a `configure` script, which all the autoconf-based libraries do.) As of v2.2.0, there is experimental support for **CMake**-based projects. We welcome your feedback on this, particularly for Windows platforms. ### How to use (for autoconf projects) Now that you know the catch, and you're still reading this, here is a quick example: ```ruby gem "mini_portile2", "~> 2.0.0" # NECESSARY if used in extconf.rb. see below. require "mini_portile2" recipe = MiniPortile.new("libiconv", "1.13.1") recipe.files = ["http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz"] recipe.cook recipe.activate ``` The gem version constraint makes sure that your extconf.rb is protected against possible backwards-incompatible changes to `mini_portile2`. This constraint is REQUIRED if you're using `mini_portile2` within a gem installation process (e.g., extconf.rb), because Bundler doesn't enforce gem version constraints at install-time (only at run-time. `#cook` will download, extract, patch, configure and compile the library into a namespaced structure. `#activate` ensures GCC will find this library and prefer it over a system-wide installation. Some keyword arguments can be passed to the constructor to configure the commands used: #### `cc_command` and `cxx_command` The C compiler command that is used is configurable, and in order of preference will use: - the `CC` environment variable (if present) - the `:cc_command` keyword argument passed in to the constructor - `RbConfig::CONFIG["CC"]` - `"gcc"` The C++ compiler is similarly configuratble, and in order of preference will use: - the `CXX` environment variable (if present) - the `:cxx_command` keyword argument passed in to the constructor - `RbConfig::CONFIG["CXX"]` - `"g++"` You can pass your compiler commands to the MiniPortile constructor: ``` ruby MiniPortile.new("libiconv", "1.13.1", cc_command: "clang", cxx_command: "clang++") ``` (For backwards compatibility, the constructor also supports a keyword argument `:gcc_command` for the C compiler.) #### `make_command` The configuration/make command that is used is configurable, and in order of preference will use: - the `MAKE` environment variable (if present) - the `make_command` value passed in to the constructor - the `make` environment variable (if present) - `"make"` You can pass it in like so: ``` ruby MiniPortile.new("libiconv", "1.13.1", make_command: "nmake") ``` #### `open_timeout`, `read_timeout` By default, when downloading source archives, MiniPortile will use a timeout value of 10 seconds. This can be overridden by passing a different value (in seconds): ``` ruby MiniPortile.new("libiconv", "1.13.1", open_timeout: 99, read_timeout: 2) ``` ### How to use (for cmake projects) Same as above, but instead of `MiniPortile.new`, call `MiniPortileCMake.new`. #### `make_command` This is configurable as above, except for Windows systems where it's hardcoded to `"nmake"`. #### `cmake_command` The cmake command used is configurable, and in order of preference will use: - the `CMAKE` environment variable (if present) - the `:cmake_command` keyword argument passed into the constructor - `"cmake"` (the default) You can pass it in like so: ``` ruby MiniPortileCMake.new("libfoobar", "1.3.5", cmake_command: "cmake3") ``` #### `cmake_build_type` The cmake build type is configurable as of v2.8.5, and in order of preference will use: - the `CMAKE_BUILD_TYPE` environment variable (if present) - the `:cmake_build_type` keyword argument passed into the constructor - `"Release"` (the default) You can pass it in like so: ``` ruby MiniPortileCMake.new("libfoobar", "1.3.5", cmake_build_type: "Debug") ``` ### Local source directories Instead of downloading a remote file, you can also point mini_portile2 at a local source directory. In particular, this may be useful for testing or debugging: ``` ruby gem "mini_portile2", "~> 2.0.0" # NECESSARY if used in extconf.rb. see below. require "mini_portile2" recipe = MiniPortile.new("libiconv", "1.13.1") recipe.source_directory = "/path/to/local/source/for/library-1.2.3" ``` ### Directory Structure Conventions `mini_portile2` follows the principle of **convention over configuration** and established a folder structure where is going to place files and perform work. Take the above example, and let's draw some picture: ``` mylib |-- ports | |-- archives | | `-- libiconv-1.13.1.tar.gz | `-- | `-- libiconv | `-- 1.13.1 | |-- bin | |-- include | `-- lib `-- tmp `-- `-- ports ``` In above structure, `` refers to the architecture that represents the operating system you're using (e.g. i686-linux, i386-mingw32, etc). Inside the platform folder, `mini_portile2` will store the artifacts that result from the compilation process. The library is versioned so you can keep multiple versions around on disk without clobbering anything. `archives` is where downloaded source files are cached. It is recommended you avoid trashing that folder to avoid downloading the same file multiple times (save bandwidth, save the world). `tmp` is where compilation is performed and can be safely discarded. Use the recipe's `#path` to obtain the full path to the installation directory: ```ruby recipe.cook recipe.path # => /home/luis/projects/myapp/ports/i686-linux/libiconv/1.13.1 ``` ### How can I combine this with my compilation task? In the simplest case, your rake `compile` task will depend on `mini_portile2` compilation and most important, activation. Example: ```ruby task :libiconv do recipe = MiniPortile.new("libiconv", "1.13.1") recipe.files << { url: "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz"], sha256: "55a36168306089009d054ccdd9d013041bfc3ab26be7033d107821f1c4949a49" } checkpoint = ".#{recipe.name}-#{recipe.version}.installed" unless File.exist?(checkpoint) recipe.cook touch checkpoint end recipe.activate end task :compile => [:libiconv] do # ... your library's compilation task ... end ``` The above example will: * **download** and verify integrity the sources only once * **compile** the library only once (using a timestamp file) * ensure compiled library is **activated** * make the compile task depend upon compiled library activation As an exercise for the reader, you could specify the libiconv version in an environment variable or a configuration file. ### Download verification MiniPortile supports HTTPS, HTTP, FTP and FILE sources for download. The integrity of the downloaded file can be verified per hash value or PGP signature. This is particular important for untrusted sources (non-HTTPS). #### Hash digest verification MiniPortile can verify the integrity of the downloaded file per SHA256, SHA1 or MD5 hash digest. ```ruby recipe.files << { url: "http://your.host/file.tar.bz2", sha256: "<32 byte hex value>", } ``` #### PGP signature verification MiniPortile can also verify the integrity of the downloaded file per PGP signature. ```ruby public_key = <<-EOT -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQENBE7SKu8BCADQo6x4ZQfAcPlJMLmL8zBEBUS6GyKMMMDtrTh3Yaq481HB54oR [...] -----END PGP PUBLIC KEY BLOCK----- EOT recipe.files << { url: "http://your.host/file.tar.bz2", gpg: { key: public_key, signature_url: "http://your.host/file.tar.bz2.sig" } } ``` Please note, that the `gpg` executable is required to verify the signature. It is therefore recommended to use the hash verification method instead of PGP, when used in `extconf.rb` while `gem install`. ### Native and/or Cross Compilation The above example covers the normal use case: compiling dependencies natively. `MiniPortile` also covers another use case, which is the cross-compilation of the dependencies to be used as part of a binary gem compilation. It is the perfect complementary tool for [`rake-compiler`](https://github.com/rake-compiler/rake-compiler) and its `cross` rake task. Depending on your usage of `rake-compiler`, you will need to use `host` to match the installed cross-compiler toolchain. Please refer to the examples directory for simplified and practical usage. ### Supported Scenarios As mentioned before, `MiniPortile` requires a GCC compiler toolchain. This has been tested against Ubuntu, OSX and even Windows (RubyInstaller with DevKit) ## Support The bug tracker is available here: * https://github.com/flavorjones/mini_portile/issues Consider subscribing to [Tidelift][tidelift] which provides license assurances and timely security notifications for your open source dependencies, including Loofah. [Tidelift][tidelift] subscriptions also help the Loofah maintainers fund our [automated testing](https://ci.nokogiri.org) which in turn allows us to ship releases, bugfixes, and security updates more often. [tidelift]: https://tidelift.com/subscription/pkg/rubygems-mini.portile2?utm_source=rubygems-mini.portile2&utm_medium=referral&utm_campaign=enterprise ## Security See [`SECURITY.md`](SECURITY.md) for vulnerability reporting details. ## License This library is licensed under MIT license. Please see LICENSE.txt for details. mini_portile2-2.8.7/mini_portile2.gemspec0000644000004100000410000000312414630451726020465 0ustar www-datawww-datarequire_relative "lib/mini_portile2/version" Gem::Specification.new do |spec| spec.name = "mini_portile2" spec.version = MiniPortile::VERSION spec.authors = ["Luis Lavena", "Mike Dalessio", "Lars Kanis"] spec.email = "mike.dalessio@gmail.com" spec.summary = "Simple autoconf and cmake builder for developers" spec.description = <<~TEXT Simple autoconf and cmake builder for developers. It provides a standard way to compile against dependency libraries without requiring system-wide installation. It also simplifies vendoring and cross-compilation by providing a consistent build interface. TEXT spec.homepage = "https://github.com/flavorjones/mini_portile" spec.licenses = ["MIT"] begin spec.files = `git ls-files -z`.split("\x0") rescue Exception => e warn "WARNING: could not set spec.files: #{e.class}: #{e}" end # omit the `examples` directory from the gem, because it's large and # not necessary to be packaged in the gem. example_files = spec.files.grep(%r{^examples/}) spec.files -= example_files spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features|examples)/}) spec.require_paths = ["lib"] spec.required_ruby_version = ">= 2.3.0" spec.add_development_dependency "bundler", "~> 2.2" spec.add_development_dependency "minitar", "~> 0.9" spec.add_development_dependency "minitest", "~> 5.15" spec.add_development_dependency "minitest-hooks", "~> 1.5" spec.add_development_dependency "rake", "~> 13.0" spec.add_development_dependency "webrick", "~> 1.7" end mini_portile2-2.8.7/CHANGELOG.md0000644000004100000410000002556414630451726016171 0ustar www-datawww-data## mini_portile changelog ### 2.8.7 / 2024-05-31 #### Added - When setting the C compiler through the `MiniPortile` constructor, the preferred keyword argument is now `:cc_command`. The original `:gcc_command` is still supported. (#144 by @flavorjones) - Add support for extracting xz-compressed tarballs on OpenBSD. (#141 by @postmodern) - Add OpenBSD support to the experimental method `MakeMakefile#mkmf_config`. (#141 by @flavorjones) #### Changed - `MiniPortileCMake` now detects the C and C++ compiler the same way `MiniPortile` does: by examining environment variables, then using kwargs, then looking in RbConfig (in that order). (#144 by @flavorjones) - GPG file verification error messages are captured in the raised exception. Previously these errors went to `stderr`. (#145 by @flavorjones) ### 2.8.6 / 2024-04-14 #### Added - When using CMake on FreeBSD, default to clang's "cc" and "c++" compilers. (#139 by @mudge) ### 2.8.5 / 2023-10-22 #### Added - New methods `#lib_path` and `#include_path` which point at the installed directories under `ports`. (by @flavorjones) - Add config param for CMAKE_BUILD_TYPE, which now defaults to `Release`. (#136 by @Watson1978) #### Experimental Introduce experimental support for `MiniPortile#mkmf_config` which sets up MakeMakefile variables to properly link against the recipe. This should make it easier for C extensions to package third-party libraries. (by @flavorjones) - With no arguments, will set up just `$INCFLAGS`, `$libs`, and `$LIBPATH`. - Optionally, if provided a pkg-config file, will use that config to more precisely set `$INCFLAGS`, `$libs`, `$LIBPATH`, and `$CFLAGS`/`$CXXFLAGS`. - Optionally, if provided the name of a static archive, will rewrite linker flags to ensure correct linkage. Note that the behavior may change slightly before official support is announced. Please comment on [#118](https://github.com/flavorjones/mini_portile/issues/118) if you have feedback. ### 2.8.4 / 2023-07-18 - cmake: set CMAKE compile flags to configure cross-compilation similarly to `autotools` `--host` flag: `SYSTEM_NAME`, `SYSTEM_PROCESSOR`, `C_COMPILER`, and `CXX_COMPILER`. [#130] (Thanks, @stanhu!) ### 2.8.3 / 2023-07-18 #### Fixed - cmake: only use MSYS/NMake generators when available. [#129] (Thanks, @stanhu!) ### 2.8.2 / 2023-04-30 #### Fixed - Ensure that the `source_directory` option will work when given a Windows path to an autoconf directory. [#126] ### 2.8.1 / 2022-12-24 #### Fixed - Support applying patches via `git apply` even when the working directory resembles a git directory. [#119] (Thanks, @h0tw1r3!) ### 2.8.0 / 2022-02-20 #### Added - Support xz-compressed archives (recognized by an `.xz` file extension). - When downloading a source archive, default open_timeout and read_timeout to 10 seconds, but allow configuration via open_timeout and read_timeout config parameters. ### 2.7.1 / 2021-10-20 #### Packaging A test artifact that has been included in the gem was being flagged by some users' security scanners because it wasn't a real tarball. That artifact has been updated to be a real tarball. [#108] ### 2.7.0 / 2021-08-31 #### Added The commands used for "make", "compile", and "cmake" are configurable via keyword arguments. [#107] (Thanks, @cosmo0920!) ### 2.6.1 / 2021-05-31 #### Dependencies Make `net-ftp` an optional dependency, since requiring it as a hard dependency in v2.5.2 caused warnings to be emitted by Ruby 2.7 and earlier. A warning message is emitted if FTP functionality is called and `net-ftp` isn't available; this should only happen in Ruby 3.1 and later. ### 2.5.3 / 2021-05-31 #### Dependencies Make `net-ftp` an optional dependency, since requiring it as a hard dependency in v2.5.2 caused warnings to be emitted by Ruby 2.7 and earlier. A warning message is emitted if FTP functionality is called and `net-ftp` isn't available; this should only happen in Ruby 3.1 and later. ### 2.6.0 / 2021-05-31 ### Added Recipes may build against a local directory by specifying `source_directory` instead of `files`. In particular, this may be useful for debugging problems with the upstream dependency (e.g., use `git bisect` in a local clone) or for continuous integration with upstream HEAD. ### 2.5.2 / 2021-05-28 #### Dependencies Add `net-ftp` as an explicit dependency to accommodate the upcoming Ruby 3.1 changes that move this and other gems out of the "default" gem set and into the "bundled" gem set. See https://bugs.ruby-lang.org/issues/17873 [#101] ### 2.5.1 / 2021-04-28 #### Dependencies This release ends support for ruby < 2.3.0. If you're on 2.2.x or earlier, we strongly suggest that you find the time to upgrade, because [official support for Ruby 2.2 ended on 2018-03-31](https://www.ruby-lang.org/en/news/2018/06/20/support-of-ruby-2-2-has-ended/). #### Enhancements * `MiniPortile.execute` now takes an optional `:env` hash, which is merged into the environment variables for the subprocess. Likely this is only useful for specialized use cases. [#99] * Experimental support for cmake-based projects extended to Windows. (Thanks, @larskanis!) ### 2.5.0 / 2020-02-24 #### Enhancements * When verifying GPG signatures, remove all imported pubkeys from keyring [#90] (Thanks, @hanazuki!) ### 2.4.0 / 2018-12-02 #### Enhancements * Skip progress report when Content-Length is unavailable. [#85] (Thanks, @eagletmt!) ### 2.3.0 / 2017-09-13 #### Enhancements * Verify checksums of files at extraction time (in addition to at download time). (#56) * Clarify error message if a `tar` command can't be found. (#81) ### 2.2.0 / 2017-06-04 #### Enhancements * Remove MD5 hashing of configure options, not avialbale in FIPS mode. (#78) * Add experimental support for cmake-based projects. * Retry on HTTP failures during downloads. [#63] (Thanks, @jtarchie and @jvshahid!) * Support Ruby 2.4 frozen string literals. * Support applying patches for users with misconfigured git worktree. [#69] * Support gpg signature verification of download resources. ### 2.1.0 / 2016-01-06 #### Enhancements * Add support for `file:` protocol for tarballs #### Bugfixes * Raise exception on unsupported URI protocols * Ignore git whitespace config when patching (Thanks, @e2!) (#67) ### 2.0.0 / 2015-11-30 Many thanks to @larskanis, @knu, and @kirikak2, who all contributed code, ideas, or both to this release. Note that the 0.7.0.rc* series was not released as 0.7.0 final, and instead became 2.0.0 due to backwards-incompatible behavioral changes which can appear because rubygems doesn't enforce loading the declared dependency version at installation-time (only run-time). If you use MiniPortile in an `extconf.rb` file, please make sure you're setting a gem version constraint before `require "mini_portile2"` . Note also that 2.0.0 doesn't include the backwards-compatible "escaped string" behavior from 0.7.0.rc3. #### Enhancements * In patch task, use git(1) or patch(1), whichever is available. * Append outputs to patch.log instead of clobbering it for every patch command. * Take `configure_options` literally without running a subshell. This changes allows for embedded spaces in a path, among other things. Please unescape `configure_options` where you have been doing it yourself. * Print last 20 lines of the given log file, for convenience. * Allow SHA1, SHA256 and MD5 hash verification of downloads #### Bugfixes * Fix issue when proxy username/password use escaped characters. * Fix use of https and ftp proxy. ### 0.7.0.rc4 / 2015-08-24 * Updated tests for Windows. No functional change. Final release candidate? ### 0.7.0.rc3 / 2015-08-24 * Restore backwards-compatible behavior with respect to escaped strings. ### 0.7.0.rc2 / 2015-08-24 * Restore support for Ruby 1.9.2 * Add Ruby 2.0.0 and Ruby 2.1.x to Appveyor suite ### 0.7.0.rc1 / 2015-08-24 Many thanks to @larskanis, @knu, and @kirikak2, who all contributed code, ideas, or both to this release. #### Enhancements * In patch task, use git(1) or patch(1), whichever is available. * Append outputs to patch.log instead of clobbering it for every patch command. * Take `configure_options` literally without running a subshell. This changes allows for embedded spaces in a path, among other things. Please unescape `configure_options` where you have been doing it yourself. * Print last 20 lines of the given log file, for convenience. * Allow SHA1, SHA256 and MD5 hash verification of downloads #### Bugfixes * Fix issue when proxy username/password use escaped characters. * Fix use of https and ftp proxy. ### 0.6.2 / 2014-12-30 * Updated gemspec, license and README to reflect new maintainer. ### 0.6.1 / 2014-08-03 * Enhancements: * Expand path to logfile to easier debugging on failures. Pull #33 [marvin2k] ### 0.6.0 / 2014-04-18 * Enhancements: * Add default cert store and custom certs from `SSL_CERT_FILE` if present. This increases compatibility with Ruby 1.8.7. * Bugfixes: * Specify Accept-Encoding to make sure a raw file content is downloaded. Pull #30. [knu] * Internal: * Improve examples and use them as test harness. ### 0.5.3 / 2014-03-24 * Bugfixes: * Shell escape paths in tar command. Pull #29. [quickshiftin] * Support older versions of tar that cannot auto-detect the compression type. Pull #27. Closes #21. [b-dean] * Try RbConfig's CC before fall back to 'gcc'. Ref #28. ### 0.5.2 / 2013-10-23 * Bugfixes: * Change tar detection order to support NetBSD 'gtar'. Closes #24 * Trick 'git-apply' when applying patches on nested Git checkouts. [larskanis] * Respect ENV's MAKE before fallback to 'make'. [larskanis] * Respect ENV's CC variable before fallback to 'gcc'. * Avoid non-ASCII output of GCC cause host detection issues. Closes #22 ### 0.5.1 / 2013-07-07 * Bugfixes: * Detect tar executable without shelling out. [jtimberman] ### 0.5.0 / 2012-11-17 * Enhancements: * Allow patching extracted files using `git apply`. [metaskills] ### 0.4.1 / 2012-10-24 * Bugfixes: * Syntax to process FTp binary chunks differs between Ruby 1.8.7 and 1.9.x ### 0.4.0 / 2012-10-24 * Enhancements: * Allow fetching of FTP URLs along HTTP ones. [metaskills] ### 0.3.0 / 2012-03-23 * Enhancements: * Use `gcc -v` to determine original host (platform) instead of Ruby one. * Deprecations: * Dropped support for Rubies older than 1.8.7 ### 0.2.2 / 2011-04-11 * Minor enhancements: * Use LDFLAGS when activating recipes for cross-compilation. Closes #6 * Bugfixes: * Remove memoization of *_path helpers. Closes #7 ### 0.2.1 / 2011-04-06 * Minor enhancements: * Provide MiniPortile#path to obtain full path to installation directory. Closes GH-5 ### 0.2.0 / 2011-04-05 * Enhancements: * Improve tar detection * Improve and refactor configure_options * Detect configure_options changes. Closes GH-1 * Add recipe examples * Bugfixes: * MiniPortile#target can be changed now. Closes GH-2 * Always redirect tar output properly ### 0.1.0 / 2011-03-08 * Initial release. Welcome to this world!