def license_map
      @license_map ||= begin
        map = {}

        project.library.each do |component|
          # Some of the components do not bundle any software but contain
          # some logic that we use during the build. These components are
          # covered under the project's license and they do not need specific
          # license files.
          next if component.license == :project_license

          map[component.name] = {
            license: component.license,
            license_files: component.license_files,
            version: component.version,
            project_dir: component.project_dir,
          }
        end

        map
      end
    end

def license_map @license_map ||= begin map = { } project . library . each do | component | next if component . license == :project_license map [ component . name ] = { license : component . license , license_files : component . license_files , version : component . version , project_dir : component . project_dir , } end map end end

Map that collects information about the licenses of the softwares
 included in the project.

 @example
 {
   ...
   "python" => {
     "license" => "Python",
     "license_files" => "LICENSE",
     "version" => "2.7.9",
     "project_dir" => "/var/cache/omnibus/src/python/Python-2.7.9/"
   },
   ...
 }

 @return [Hash]

Map that collects information about the licenses of the softwares included in the project .


def process_transitive_dependency_licensing_info
      Dir.glob("#{cache_dir}/*/*-dependency-licenses.json").each do |license_manifest_path|
        license_manifest_data = FFI_Yajl::Parser.parse(File.read(license_manifest_path))
        project_name = license_manifest_data["project_name"]
        dependency_license_dir = File.dirname(license_manifest_path)

        license_manifest_data["dependency_managers"].each do |dep_mgr_name, dependencies|
          dep_license_map[dep_mgr_name] ||= {}

          dependencies.each do |dependency|
            # Copy dependency files
            dependency["license_files"].each do |f|
              license_path = File.join(dependency_license_dir, f)
              output_path = File.join(output_dir, f)
              FileUtils.cp(license_path, output_path)
            end

            dep_name = dependency["name"]
            dep_version = dependency["version"]

            # If we already have this dependency we do not need to add it again.
            if dep_license_map[dep_mgr_name][dep_name] && dep_license_map[dep_mgr_name][dep_name][dep_version]
              dep_license_map[dep_mgr_name][dep_name][dep_version]["dependency_of"] << project_name
            else
              dep_license_map[dep_mgr_name][dep_name] ||= {}
              dep_license_map[dep_mgr_name][dep_name][dep_version] = {
                "license" => dependency["license"],
                "license_files" => dependency["license_files"],
                "dependency_of" => [ project_name ],
              }
            end
          end
        end
      end

      FileUtils.rm_rf(cache_dir)
    end

0. Translate all transitive dependency licensing issues into omnibus warnings
 1. Parse all the licensing information for all software from 'cache_dir'
 2. Merge and drop the duplicates
 3. Add these licenses to the main manifest, to be merged with the main
 licensing information from software definitions.

0 . Translate all transitive dependency licensing issues into omnibus warnings 1 . Parse all the licensing information for all software from cache_dir 2 . Merge and drop the duplicates 3 . Add these licenses to the main manifest to be merged with the main licensing information from software definitions .


def collect_licenses_for(software)
      return nil if software.license == :project_license

      software_name = software.name
      license_data = license_map[software_name]
      license_files = license_data[:license_files]

      license_files.each do |license_file|
        if license_file
          output_file = license_package_location(software_name, license_file)

          if local?(license_file)
            input_file = File.expand_path(license_file, license_data[:project_dir])
            if File.exist?(input_file)
              FileUtils.cp(input_file, output_file)
              File.chmod 0644, output_file unless windows?
            else
              licensing_warning("License file '#{input_file}' does not exist for software '#{software_name}'.")
              # If we got here, we need to fail now so we don't take a git
              # cache snapshot, or else the software build could be restored
              # from cache without fixing the license issue.
              raise_if_warnings_fatal!
            end
          else
            begin
              download_file!(license_file, output_file, enable_progress_bar: false)
              File.chmod 0644, output_file unless windows?
            rescue SocketError,
                   Errno::ECONNREFUSED,
                   Errno::ECONNRESET,
                   Errno::ENETUNREACH,
                   Timeout::Error,
                   OpenURI::HTTPError,
                   OpenSSL::SSL::SSLError
              licensing_warning("Can not download license file '#{license_file}' for software '#{software_name}'.")
              # If we got here, we need to fail now so we don't take a git
              # cache snapshot, or else the software build could be restored
              # from cache without fixing the license issue.
              raise_if_warnings_fatal!
            end
          end
        end
      end
    end

Collect the license files for the software.

Collect the license files for the software .


def write_prototype_file
      shellout! "cd #{install_dirname} && find #{install_basename} -print > #{staging_dir_path('files')}"

      File.open staging_dir_path("files.clean"), "w+" do |fout|
        File.open staging_dir_path("files") do |fin|
          fin.each_line do |line|
            if line.chomp =~ /\s/
              log.warn(log_key) { "Skipping packaging '#{line}' file due to whitespace in filename" }
            else
              fout.write(line)
            end
          end
        end
      end

      # generate list of control files
      File.open staging_dir_path("Prototype"), "w+" do |f|
        f.write <<-EOF.gsub(/^ {10}/, "")
          i pkginfo
          i postinstall
          i postremove
        EOF
      end

      # generate the prototype's file list
      shellout! "cd #{install_dirname} && pkgproto < #{staging_dir_path('files.clean')} > #{staging_dir_path('Prototype.files')}"

      # fix up the user and group in the file list to root
      shellout! "awk '{ $5 = \"root\"; $6 = \"root\"; print }' < #{staging_dir_path('Prototype.files')} >> #{staging_dir_path('Prototype')}"
    end

Generate a Prototype file for solaris build


def content
      @content ||= IO.read(path)
    rescue Errno::ENOENT
      raise NoPackageFile.new(path)
    end

def content @content ||= IO . read ( path ) rescue Errno :: ENOENT raise NoPackageFile . new ( path ) end

The actual contents of the package.

 @return [String]


def validate!
      unless File.exist?(path)
        raise NoPackageFile.new(path)
      end

      unless File.exist?(metadata.path)
        raise NoPackageMetadataFile.new(metadata.path)
      end

      true
    end

def validate! unless File . exist? ( path ) raise NoPackageFile . new ( path ) end unless File . exist? ( metadata . path ) raise NoPackageMetadataFile . new ( metadata . path ) end true end

Validate the presence of the required components for the package.

 @raise [NoPackageFile] if the package is not present
 @raise [NoPackageMetadataFile] if the metadata file is not present

 @return [true]

Validate the presence of the required components for the package .


def key_for(package, *stuff)
      File.join(
        Config.s3_publish_pattern % package.metadata,
        *stuff
      )
    end

def key_for ( package , * stuff ) File . join ( Config . s3_publish_pattern % package . metadata , * stuff ) end

The unique upload key for this package. The additional "stuff" is
 postfixed to the end of the path.

 @example
   'el/6/x86_64/chef-11.6.0-1.el6.x86_64.rpm/chef-11.6.0-1.el6.x86_64.rpm'

 @param [Package] package
   the package this key is for
 @param [Array<String>] stuff
   the additional things to append

 @return [String]

The unique upload key for this package . The additional stuff is postfixed to the end of the path .


def semver
      build_tag = version_tag

      # PRERELEASE VERSION
      if prerelease_version?
        # ensure all dashes are dots per precedence rules (#12) in Semver
        # 2.0.0-rc.1
        prerelease = prerelease_tag.tr("-", ".")
        build_tag << "-" << prerelease
      end

      # BUILD VERSION
      # Follows SemVer conventions and the build version begins with a '+'.
      build_version_items = []

      # By default we will append a timestamp to every build. This behavior can
      # be overriden by setting the OMNIBUS_APPEND_TIMESTAMP environment
      # variable to a 'falsey' value (ie false, f, no, n or 0).
      #
      # format: YYYYMMDDHHMMSS example: 20130131123345
      if Config.append_timestamp
        build_version_items << build_start_time
      end

      # We'll append the git describe information unless we are sitting right
      # on an annotated tag.
      #
      # format: git.COMMITS_SINCE_TAG.GIT_SHA example: git.207.694b062
      unless commits_since_tag == 0
        build_version_items << ["git", commits_since_tag, git_sha_tag].join(".")
      end

      unless build_version_items.empty?
        build_tag << "+" << build_version_items.join(".")
      end

      build_tag
    end

def semver build_tag = version_tag if prerelease_version? prerelease = prerelease_tag . tr ( "-" , "." ) build_tag << "-" << prerelease end build_version_items = [ ] if Config . append_timestamp build_version_items << build_start_time end unless commits_since_tag == 0 build_version_items << [ "git" , commits_since_tag , git_sha_tag ] . join ( "." ) end unless build_version_items . empty? build_tag << "+" << build_version_items . join ( "." ) end build_tag end

Create a new BuildVersion

 @param [String] path
   Path from which to read git version information
 @!group Version Generator Methods
 Generate a {http://semver.org/ SemVer 2.0.0-rc.1 compliant}
 version string for an Omnibus project.

 This relies on the Omnibus project being a Git repository, as
 well as having tags named according to SemVer conventions
 (specifically, the `MAJOR.MINOR.PATCH-PRERELEASE` aspects)

 The specific format of the version string is:

     MAJOR.MINOR.PATCH-PRERELEASE+TIMESTAMP.git.COMMITS_SINCE.GIT_SHA

 By default, a timestamp is incorporated into the build component of
 version string (see {Omnibus::BuildVersion::TIMESTAMP_FORMAT}). This
 option is configurable via the {Config}.

 @example 11.0.0-alpha.1+20121218164140.git.207.694b062
 @return [String]
 @see #git_describe
 @todo Issue a warning or throw an exception if the tags of the
   repository are not themselves SemVer-compliant?
 @todo Consider making the {#build_start_time} method public, as
   its function influences how build timestamps are generated,
   and can be influenced by users.


def build_start_time
      @build_start_time ||= begin
                              if ENV["BUILD_TIMESTAMP"]
                                begin
                                  Time.strptime(ENV["BUILD_TIMESTAMP"], "%Y-%m-%d_%H-%M-%S")
                                rescue ArgumentError
                                  error_message =  "BUILD_TIMESTAMP environment variable "
                                  error_message << "should be in YYYY-MM-DD_hh-mm-ss "
                                  error_message << "format."
                                  raise ArgumentError, error_message
                                end
                              elsif ENV["BUILD_ID"]
                                begin
                                  Time.strptime(ENV["BUILD_ID"], "%Y-%m-%d_%H-%M-%S")
                                rescue ArgumentError
                                  error_message =  "BUILD_ID environment variable "
                                  error_message << "should be in YYYY-MM-DD_hh-mm-ss "
                                  error_message << "format."
                                  raise ArgumentError, error_message
                                end
                              else
                                Time.now.utc
                              end
                            end.strftime(TIMESTAMP_FORMAT)
    end

def
build_start_time
@build_start_time
||=
begin
if
ENV
[
"BUILD_TIMESTAMP"
]
begin
Time
.
strptime
(
ENV
[
"BUILD_TIMESTAMP"
]
,
"%Y-%m-%d_%H-%M-%S"
)
rescue
ArgumentError
error_message
=
"BUILD_TIMESTAMP environment variable "
error_message
<<
"should be in YYYY-MM-DD_hh-mm-ss "
error_message
<<
"format."
raise
ArgumentError
,
error_message
end
elsif
ENV
[
"BUILD_ID"
]
begin
Time
.
strptime
(
ENV
[
"BUILD_ID"
]
,
"%Y-%m-%d_%H-%M-%S"
)
rescue
ArgumentError
error_message
=
"BUILD_ID environment variable "
error_message
<<
"should be in YYYY-MM-DD_hh-mm-ss "
error_message
<<
"format."
raise
ArgumentError
,
error_message
end
else
Time
.
now
.
utc
end
end
.
strftime
(
TIMESTAMP_FORMAT
)
end

We'll attempt to retrieve the timestamp from the Jenkin's set BUILD_TIMESTAMP
 or fall back to BUILD_ID environment variable. This will ensure platform specfic
 packages for the same build will share the same timestamp.

We ll attempt to retrieve the timestamp from the Jenkin s set BUILD_TIMESTAMP or fall back to BUILD_ID environment variable . This will ensure platform specfic packages for the same build will share the same timestamp .


def save
      File.open(path, "w+") do |f|
        f.write(FFI_Yajl::Encoder.encode(to_hash, pretty: true))
      end

      true
    end

def save File . open ( path , "w+" ) do | f | f . write ( FFI_Yajl :: Encoder . encode ( to_hash , pretty : true ) ) end true end


def vendor(val = NULL)
      if null?(val)
        @vendor || "Omnibus <omnibus@getchef.com>"
      else
        unless val.is_a?(String)
          raise InvalidValue.new(:vendor, "be a String")
        end

        @vendor = val
      end
    end

def
vendor
(
val
=
)
if
null?
(
val
)
@vendor
||
"Omnibus <omnibus@getchef.com>"
else
unless
val
.
is_a?
(
String
)
raise
InvalidValue
.
new
(
:vendor
,
"be a String"
)
end
@vendor
=
val
end
end

Set or return the vendor who made this package.

 @example
   vendor "Seth Vargo <sethvargo@gmail.com>"

 @param [String] val
   the vendor who make this package

 @return [String]
   the vendor who make this package

Set or return the vendor who made this package .


def license(val = NULL)
      if null?(val)
        @license || project.license
      else
        unless val.is_a?(String)
          raise InvalidValue.new(:license, "be a String")
        end

        @license = val
      end
    end

def
license
(
val
=
)
if
null?
(
val
)
@license
||
project
.
license
else
unless
val
.
is_a?
(
String
)
raise
InvalidValue
.
new
(
:license
,
"be a String"
)
end
@license
=
val
end
end

Set or return the license for this package.

 @example
   license "Apache 2.0"

 @param [String] val
   the license for this package

 @return [String]
   the license for this package

Set or return the license for this package .


def build_filepath(path)
      filepath = rpm_safe("/" + path.gsub("#{build_dir}/", ""))
      return if config_files.include?(filepath)
      full_path = build_dir + filepath.gsub("[%]", "%")
      # FileSyncer.glob quotes pathnames that contain spaces, which is a problem on el7
      full_path.delete!('"')
      # Mark directories with the %dir directive to prevent rpmbuild from counting their contents twice.
      return mark_filesystem_directories(filepath) if !File.symlink?(full_path) && File.directory?(full_path)
      filepath
    end

def build_filepath ( path ) filepath = rpm_safe ( "/" + path . gsub ( "#{build_dir}/" , "" ) ) return if config_files . include? ( filepath ) full_path = build_dir + filepath . gsub ( "[%]" , "%" ) full_path . delete! ( '"' ) return mark_filesystem_directories ( filepath ) if ! File . symlink? ( full_path ) && File . directory? ( full_path ) filepath end

Convert the path of a file in the staging directory to an entry for use in the spec file.

 @return [String]

Convert the path of a file in the staging directory to an entry for use in the spec file .


def with_rpm_signing(&block)
      directory   = Dir.mktmpdir
      destination = "#{directory}/sign-rpm"

      render_template(resource_path("signing.erb"),
        destination: destination,
        mode: 0700,
        variables: {
          passphrase: signing_passphrase,
        }
      )

      # Yield the destination to the block
      yield(destination)
    ensure
      remove_file(destination)
      remove_directory(directory)
    end

def with_rpm_signing ( & block ) directory = Dir . mktmpdir destination = "#{directory}/sign-rpm" render_template ( resource_path ( "signing.erb" ) , destination : destination , mode : 0700 , variables : { passphrase : signing_passphrase , } ) yield ( destination ) ensure remove_file ( destination ) remove_directory ( directory ) end

Render the rpm signing script with secure permissions, call the given
 block with the path to the script, and ensure deletion of the script from
 disk since it contains sensitive information.

 @param [Proc] block
   the block to call

 @return [String]

Render the rpm signing script with secure permissions call the given block with the path to the script and ensure deletion of the script from disk since it contains sensitive information .


def publish(klass, pattern, options)
      if options[:platform_mappings]
        options[:platform_mappings] = FFI_Yajl::Parser.parse(File.read(File.expand_path(options[:platform_mappings])))
      end

      klass.publish(pattern, options) do |package|
        say("Published '#{package.name}' for #{package.metadata[:platform]}-#{package.metadata[:platform_version]}", :green)
      end
    end

Shortcut method for executing a publisher.

 @return [void]

Shortcut method for executing a publisher .


def build_version(val = NULL, &block)
      if block && !null?(val)
        raise Error, "You cannot specify additional parameters to " \
          "#build_version when a block is given!"
      end

      if block
        @build_version_dsl = BuildVersionDSL.new(&block)
      else
        if null?(val)
          @build_version_dsl.build_version
        else
          @build_version_dsl = BuildVersionDSL.new(val)
        end
      end
    end

Set or retrieve the version of the project.

 @example Using a string
   build_version '1.0.0'

 @example From git
   build_version do
     source :git
   end

 @example From the version of a dependency
   build_version do
     source :version, from_dependency: 'chef'
   end

 @example From git of a dependency
   build_version do
     source :git, from_dependency: 'chef'
   end

 When using the +:git+ source, by default the output format of the
 +build_version+ is semver. This can be modified using the +:output_format+
 parameter to any of the methods of +BuildVersion+. For example:

   build version do
     source :git, from_dependency: 'chef'
     output_format :git_describe
   end

 @see Omnibus::BuildVersion
 @see Omnibus::BuildVersionDSL

 @param [String] val
   the build version to set
 @param [Proc] block
   the block to run when constructing the +build_version+

 @return [String]

Set or retrieve the version of the project .


def package(id, &block)
      unless block
        raise InvalidValue.new(:package, "have a block")
      end

      packagers[id] << block
    end

def
package
(
id
,
&
block
)
unless
block
raise
InvalidValue
.
new
(
:package
,
"have a block"
)
end
packagers
[
id
]
<<
block
end

Add or override a customization for the packager with the given +id+. When
 given multiple blocks with the same +id+, they are evaluated _in order_,
 so the last block evaluated will take precedence over the previous ones.

 @example
   package :id do
     key 'value'
   end

 @param [Symbol] id
   the id of the packager to customize

Add or override a customization for the packager with the given + id + . When given multiple blocks with the same + id + they are evaluated _in order_ so the last block evaluated will take precedence over the previous ones .


def compress(id, &block)
      if block
        compressors[id] << block
      else
        compressors[id] << Proc.new {}
      end
    end

def compress ( id , & block ) if block compressors [ id ] << block else compressors [ id ] << Proc . new { } end end

Add or override a customization for the compressor with the given +id+.
 When given multiple blocks with the same +id+, they are evaluated
 _in order_, so the last block evaluated will take precedence over the
 previous ones.

 @example With customization
   compress :dmg do
     window_bounds '10, 20, 30, 40'
   end

 @example Without customization
   compress :tgz

 If multiple +compress+ blocks are specified, the "most prefered" one for
 the current system will be used.

 @param [Symbol] id
   the id of the compressor to customize

Add or override a customization for the compressor with the given + id + . When given multiple blocks with the same + id + they are evaluated _in order_ so the last block evaluated will take precedence over the previous ones .


def override(name, val = NULL)
      if null?(val)
        overrides[name.to_sym]
      else
        overrides[name.to_sym] = val
      end
    end

def override ( name , val = NULL ) if null? ( val ) overrides [ name . to_sym ] else overrides [ name . to_sym ] = val end end

Set or retrieve the overrides hash for one piece of software being
 overridden. Calling it as a setter does not merge hash entries and it will
 set all the overrides for a given software definition.

 @example
   override 'chef', version: '1.2.3'

 @param [Hash] val
   the value to override

 @return [Hash]

Set or retrieve the overrides hash for one piece of software being overridden . Calling it as a setter does not merge hash entries and it will set all the overrides for a given software definition .


def license_file_path(path = NULL)
      if null?(path)
        @license_file_path || File.join(install_dir, "LICENSE")
      else
        @license_file_path = File.join(install_dir, path)
      end
    end

def license_file_path ( path = NULL ) if null? ( path ) @license_file_path || File . join ( install_dir , "LICENSE" ) else @license_file_path = File . join ( install_dir , path ) end end

Location of license file that omnibus will create and that will contain
 the information about the license of the project plus the details about
 the licenses of the software components included in the project.

 If no path is specified  install_dir/LICENSE is used.

 @example
   license_file_path

 @return [String]

Location of license file that omnibus will create and that will contain the information about the license of the project plus the details about the licenses of the software components included in the project .


def dependency?(software)
      name = software.is_a?(Software) ? software.name : software
      dependencies.include?(name)
    end

def dependency? ( software ) name = software . is_a? ( Software ) ? software . name : software dependencies . include? ( name ) end

Indicates whether the given  +software+ is defined as a software component
 of this project.

 @param [String, Software] software
   the software or name of the software to find

 @return [true, false]

Indicates whether the given + software + is defined as a software component of this project .


def built_manifest
      log.info(log_key) { "Building version manifest" }
      m = Omnibus::Manifest.new(build_version, build_git_revision, license)
      softwares.each do |software|
        m.add(software.name, software.manifest_entry)
      end
      m
    end

def
built_manifest
log
.
info
(
log_key
)
{
"Building version manifest"
}
m
=
Omnibus
::
Manifest
.
new
(
build_version
,
build_git_revision
,
license
)
softwares
.
each
do
|
software
|
m
.
add
(
software
.
name
,
software
.
manifest_entry
)
end
m
end

Generate a version manifest of the loaded software sources.

 @returns [Omnibus::Manifest]

Generate a version manifest of the loaded software sources .


def write_text_manifest
      File.open(text_manifest_path, "w") do |f|
        f.puts "#{name} #{build_version}"
        f.puts ""
        f.puts Omnibus::Reports.pretty_version_map(self)
      end
    end

def
write_text_manifest
File
.
open
(
text_manifest_path
,
"w"
)
do
|
f
|
f
.
puts
"#{name} #{build_version}"
f
.
puts
""
f
.
puts
Omnibus
::
Reports
.
pretty_version_map
(
self
)
end
end

Writes a text manifest to the text_manifest_path.  This uses the
 same method as the "version-manifest" software definition in
 omnibus-software.

Writes a text manifest to the text_manifest_path . This uses the same method as the version - manifest software definition in omnibus - software .


def write_conffiles_file
      return if project.config_files.empty?

      render_template(resource_path("conffiles.erb"),
        destination: File.join(debian_dir, "conffiles"),
        variables: {
          config_files: project.config_files,
        }
      )
    end

def write_conffiles_file return if project . config_files . empty? render_template ( resource_path ( "conffiles.erb" ) , destination : File . join ( debian_dir , "conffiles" ) , variables : { config_files : project . config_files , } ) end

Render the list of config files into the conffile.

 @return [void]

Render the list of config files into the conffile .


def package_size
      @package_size ||= begin
        path  = "#{project.install_dir}/**/*"
        total = FileSyncer.glob(path).inject(0) do |size, path|
          unless File.directory?(path) || File.symlink?(path)
            size += File.size(path)
          end

          size
        end

        # Per http://www.debian.org/doc/debian-policy/ch-controlfields.html, the
        # disk space is given as the integer value of the estimated installed
        # size in bytes, divided by 1024 and rounded up.
        total / 1024
      end
    end

def package_size @package_size ||= begin path = "#{project.install_dir}/**/*" total = FileSyncer . glob ( path ) . inject ( 0 ) do | size , path | unless File . directory? ( path ) || File . symlink? ( path ) size += File . size ( path ) end size end total / 1024 end end

The size of this Debian package. This is dynamically calculated.

 @return [Fixnum]

The size of this Debian package . This is dynamically calculated .


def dir_empty?(dir)
      Dir.entries(dir).reject { |d| [".", ".."].include?(d) }.empty?
    end

def dir_empty? ( dir ) Dir . entries ( dir ) . reject { | d | [ "." , ".." ] . include? ( d ) } . empty? end

Determine if a directory is empty

 @return [true, false]


def force_recreate_project_dir!
      log.warn(log_key) { "Removing existing directory #{project_dir} before cloning" }
      FileUtils.rm_rf(project_dir)
      Dir.mkdir(project_dir)
    end

Forcibly remove and recreate the project directory


def current_revision
      cmd = git("rev-parse HEAD")
      cmd.stdout.strip
    rescue CommandFailed
      log.debug(log_key) { "unable to determine current revision" }
      nil
    end

def
current_revision
cmd
=
git
(
"rev-parse HEAD"
)
cmd
.
stdout
.
strip
rescue
CommandFailed
log
.
debug
(
log_key
)
{
"unable to determine current revision"
}
end

The current revision for the cloned checkout.

 @return [String]

The current revision for the cloned checkout .


def contains_revision?(rev)
      cmd = git("cat-file -t #{rev}")
      cmd.stdout.strip == "commit"
    rescue CommandFailed
      log.debug(log_key) { "unable to determine presence of commit #{rev}" }
      false
    end

Check if the current clone has the requested commit id.

 @return [true, false]

Check if the current clone has the requested commit id .


def to_ssh
      if zero?
        return [0].pack("N")
      else
        buf = to_s(2)
        if buf.getbyte(0)[7] == 1
          return [buf.length + 1, 0, buf].pack("NCA*")
        else
          return [buf.length, buf].pack("NA*")
        end
      end
    end

def to_ssh if zero? return [ 0 ] . pack ( "N" ) else buf = to_s ( 2 ) if buf . getbyte ( 0 ) [ 7 ] == 1 return [ buf . length + 1 , 0 , buf ] . pack ( "NCA*" ) else return [ buf . length , buf ] . pack ( "NA*" ) end end end

Converts a BN object to a string. The format used is that which is
 required by the SSH2 protocol.

Converts a BN object to a string . The format used is that which is required by the SSH2 protocol .


def compute_need_bits
      # for Compatibility: OpenSSH requires (need_bits * 2 + 1) length of parameter
      need_bits = data[:need_bytes] * 8 * 2 + 1

      data[:minimum_dh_bits] ||= MINIMUM_BITS

      if need_bits < data[:minimum_dh_bits]
        need_bits = data[:minimum_dh_bits]
      elsif need_bits > MAXIMUM_BITS
        need_bits = MAXIMUM_BITS
      end

      data[:need_bits] = need_bits
      data[:need_bytes] = need_bits / 8
    end

Compute the number of bits needed for the given number of bytes.

Compute the number of bits needed for the given number of bytes .


def get_parameters
      compute_need_bits

      # request the DH key parameters for the given number of bits.
      buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, data[:minimum_dh_bits],
        :long, data[:need_bits], :long, MAXIMUM_BITS)
      connection.send_message(buffer)

      buffer = connection.next_message
      raise Net::SSH::Exception, "expected KEXDH_GEX_GROUP, got #{buffer.type}" unless buffer.type == KEXDH_GEX_GROUP

      p = buffer.read_bignum
      g = buffer.read_bignum

      [p, g]
    end

Returns the DH key parameters for the given session.

Returns the DH key parameters for the given session .


def build_signature_buffer(result)
      response = Net::SSH::Buffer.new
      response.write_string data[:client_version_string],
                            data[:server_version_string],
                            data[:client_algorithm_packet],
                            data[:server_algorithm_packet],
                            result[:key_blob]
      response.write_long MINIMUM_BITS,
                          data[:need_bits],
                          MAXIMUM_BITS
      response.write_bignum dh.p, dh.g, dh.pub_key,
                            result[:server_dh_pubkey],
                            result[:shared_secret]
      response
    end

def build_signature_buffer ( result ) response = Net :: SSH :: Buffer . new response . write_string data [ :client_version_string ] , data [ :server_version_string ] , data [ :client_algorithm_packet ] , data [ :server_algorithm_packet ] , result [ :key_blob ] response . write_long MINIMUM_BITS , data [ :need_bits ] , MAXIMUM_BITS response . write_bignum dh . p , dh . g , dh . pub_key , result [ :server_dh_pubkey ] , result [ :shared_secret ] response end

Build the signature buffer to use when verifying a signature from
 the server.

Build the signature buffer to use when verifying a signature from the server .


def when_loaded
      # Get original loaded value, in case we are nested
      # inside another when_loaded block.
      previously_loaded = loaded

      # Within the block, check (and cache) loaded?, to see whether the
      # page has indeed loaded according to the rules defined by the user.
      self.loaded = loaded?

      # If the page hasn't loaded. Then crash and return the error message.
      # If one isn't defined, just return the Error code.
      raise SitePrism::FailedLoadValidationError, load_error unless loaded

      # Return the yield value of the block if one was supplied.
      yield self if block_given?
    ensure
      self.loaded = previously_loaded
    end

def when_loaded previously_loaded = loaded self . loaded = loaded? raise SitePrism :: FailedLoadValidationError , load_error unless loaded yield self if block_given? ensure self . loaded = previously_loaded end

Executes the given block after the page is loaded.

 The loadable object instance is yielded into the block.

Executes the given block after the page is loaded .


def load_validations_pass?
      self.class.load_validations.all? do |validation|
        passed, message = instance_eval(&validation)

        self.load_error = message if message && !passed
        passed
      end
    end

def load_validations_pass? self . class . load_validations . all? do | validation | passed , message = instance_eval ( & validation ) self . load_error = message if message && ! passed passed end end

If any load validations from page subclasses returns false,
 immediately return false.

If any load validations from page subclasses returns false immediately return false .


def raise_if_block(obj, name, has_block, type)
      return unless has_block

      SitePrism.logger.debug("Type passed in: #{type}")
      SitePrism.logger.warn('section / iFrame can only accept blocks.')
      SitePrism.logger.error("#{obj.class}##{name} does not accept blocks")

      raise SitePrism::UnsupportedBlockError
    end

Prevent users from calling methods with blocks when they shouldn't be.

 Example (Triggering error):

       class MyPage
         element :sample, '.css-locator' do
           puts "This won't be output"
         end
       end

 At runtime this will generate a `SitePrism::UnsupportedBlockError`

 The only DSL keywords that can use blocks are :section and :iframe

Prevent users from calling methods with blocks when they shouldn t be .


def merge_args(find_args, runtime_args, visibility_args = {})
      find_args = find_args.dup
      runtime_args = runtime_args.dup
      options = visibility_args.dup
      SitePrism.logger.debug("Initial args: #{find_args}, #{runtime_args}.")

      recombine_args(find_args, runtime_args, options)

      return [*find_args, *runtime_args] if options.empty?

      [*find_args, *runtime_args, options]
    end

Sanitize method called before calling any SitePrism DSL method or
 meta-programmed method. This ensures that the Capybara query is correct.

 Accepts any combination of arguments sent at DSL definition or runtime
 and combines them in such a way that Capybara can operate with them.

Sanitize method called before calling any SitePrism DSL method or meta - programmed method . This ensures that the Capybara query is correct .


def recombine_args(find_args, runtime_args, options)
      options.merge!(find_args.pop) if find_args.last.is_a? Hash
      options.merge!(runtime_args.pop) if runtime_args.last.is_a? Hash
      options[:wait] = wait_time unless wait_key_present?(options)
    end

def recombine_args ( find_args , runtime_args , options ) options . merge! ( find_args . pop ) if find_args . last . is_a? Hash options . merge! ( runtime_args . pop ) if runtime_args . last . is_a? Hash options [ :wait ] = wait_time unless wait_key_present? ( options ) end

Options re-combiner. This takes the original inputs and combines
 them such that there is only one hash passed as a final argument
 to Capybara.

 If the hash is empty, then the hash is omitted from the payload sent
 to Capybara, and the find / runtime arguments are sent alone.

Options re - combiner . This takes the original inputs and combines them such that there is only one hash passed as a final argument to Capybara .


def elements_to_check
      if _expected_items
        SitePrism.logger.debug('Expected Items has been set.')
        _mapped_items.select { |item_name| _expected_items.include?(item_name) }
      else
        _mapped_items
      end
    end

def
elements_to_check
if
_expected_items
SitePrism
.
logger
.
debug
(
'Expected Items has been set.'
)
_mapped_items
.
select
{
|
item_name
|
_expected_items
.
include?
(
item_name
)
}
else
_mapped_items
end
end

If the page or section has expected_items set, return expected_items
 that are mapped; otherwise just return the list of all mapped_items

If the page or section has expected_items set return expected_items that are mapped ; otherwise just return the list of all mapped_items


def matches?(url, expected_mappings = {})
      actual_mappings = mappings(url)
      return false unless actual_mappings

      expected_mappings.empty? ||
        all_expected_mappings_match?(expected_mappings, actual_mappings)
    end

def matches? ( url , expected_mappings = { } ) actual_mappings = mappings ( url ) return false unless actual_mappings expected_mappings . empty? || all_expected_mappings_match? ( expected_mappings , actual_mappings ) end

Determine whether URL matches our pattern, and
 optionally whether the extracted mappings match
 a hash of expected values.  You can specify values
 as strings, numbers or regular expressions.

Determine whether URL matches our pattern and optionally whether the extracted mappings match a hash of expected values . You can specify values as strings numbers or regular expressions .


def component_matches(component, uri)
      component_template = component_templates[component]
      return {} unless component_template

      component_url = uri.public_send(component).to_s
      mappings = component_template.extract(component_url)
      return mappings if mappings

      # to support Addressable's expansion of queries
      # ensure it's parsing the fragment as appropriate (e.g. {?params*})
      prefix = component_prefixes[component]
      return nil unless prefix

      component_template.extract(prefix + component_url)
    end

def component_matches ( component , uri ) component_template = component_templates [ component ] return { } unless component_template component_url = uri . public_send ( component ) . to_s mappings = component_template . extract ( component_url ) return mappings if mappings prefix = component_prefixes [ component ] return nil unless prefix component_template . extract ( prefix + component_url ) end

Returns empty hash if the template omits the component or a set of
 substitutions if the provided URI component matches the template
 component or nil if the match fails.

Returns empty hash if the template omits the component or a set of substitutions if the provided URI component matches the template component or nil if the match fails .


def to_substituted_uri
      url = pattern
      substitutions.each_pair { |slug, value| url = url.sub(slug, value) }
      begin
        Addressable::URI.parse(url)
      rescue Addressable::URI::InvalidURIError
        SitePrism.logger.warn("Ensure you don't use templated port numbers.")
        raise SitePrism::InvalidUrlMatcherError
      end
    end

Convert the pattern into an Addressable URI by substituting
 the template slugs with nonsense strings.

Convert the pattern into an Addressable URI by substituting the template slugs with nonsense strings .


def substitution_value(index)
      sha = Digest::SHA1.digest(index.to_s)
      Base64.urlsafe_encode64(sha).gsub(/[^A-Za-z]/, '')[0..5]
    end

def substitution_value ( index ) sha = Digest :: SHA1 . digest ( index . to_s ) Base64 . urlsafe_encode64 ( sha ) . gsub ( / / , '' ) [ 0 .. 5 ] end

Generate a repeatable 5 character uniform alphabetical nonsense string
 to allow parsing as a URI


def build_times_enumerator(number, cursor:)
      raise ArgumentError, "First argument must be an Integer" unless number.is_a?(Integer)
      wrap(self, build_array_enumerator(number.times.to_a, cursor: cursor))
    end

def
build_times_enumerator
(
number
,
cursor
:
)
raise
ArgumentError
,
"First argument must be an Integer"
unless
number
.
is_a?
(
Integer
)
wrap
(
self
,
build_array_enumerator
(
number
.
times
.
to_a
,
cursor
:
cursor
)
)
end

Builds Enumerator objects that iterates N times and yields number starting from zero.

Builds Enumerator objects that iterates N times and yields number starting from zero .


def build_array_enumerator(enumerable, cursor:)
      unless enumerable.is_a?(Array)
        raise ArgumentError, "enumerable must be an Array"
      end
      if enumerable.any? { |i| defined?(ActiveRecord) && i.is_a?(ActiveRecord::Base) }
        raise ArgumentError, "array cannot contain ActiveRecord objects"
      end
      drop =
        if cursor.nil?
          0
        else
          cursor + 1
        end

      wrap(self, enumerable.each_with_index.drop(drop).to_enum { enumerable.size })
    end

Builds Enumerator object from a given array, using +cursor+ as an offset.

Builds Enumerator object from a given array using + cursor + as an offset .


def build_lock_queue_enumerator(lock_queue, at_most_once:)
      unless lock_queue.is_a?(BackgroundQueue::LockQueue::RedisQueue) ||
          lock_queue.is_a?(BackgroundQueue::LockQueue::RolloutRedisQueue)
        raise ArgumentError, "an argument to #build_lock_queue_enumerator must be a LockQueue"
      end
      wrap(self, BackgroundQueue::LockQueueEnumerator.new(lock_queue, at_most_once: at_most_once).to_enum)
    end

Builds Enumerator from a lock queue instance that belongs to a job.
 The helper is only to be used from jobs that use LockQueue module.

Builds Enumerator from a lock queue instance that belongs to a job . The helper is only to be used from jobs that use LockQueue module .


def build_active_record_enumerator_on_records(scope, cursor:, **args)
      enum = build_active_record_enumerator(
        scope,
        cursor: cursor,
        **args
      ).records
      wrap(self, enum)
    end

Builds Enumerator from Active Record Relation. Each Enumerator tick moves the cursor one row forward.

 +columns:+ argument is used to build the actual query for iteration. +columns+: defaults to primary key:

   1) SELECT * FROM users ORDER BY id LIMIT 100

 When iteration is resumed, +cursor:+ and +columns:+ values will be used to continue from the point
 where iteration stopped:

   2) SELECT * FROM users WHERE id > $CURSOR ORDER BY id LIMIT 100

 +columns:+ can also take more than one column. In that case, +cursor+ will contain serialized values
 of all columns at the point where iteration stopped.

 Consider this example with +columns: [:created_at, :id]+. Here's the query will use on the first iteration:

   1) SELECT * FROM `products` ORDER BY created_at, id LIMIT 100

 And the query on the next iteration:

   2) SELECT * FROM `products`
        WHERE (created_at > '$LAST_CREATED_AT_CURSOR'
          OR (created_at = '$LAST_CREATED_AT_CURSOR' AND (id > '$LAST_ID_CURSOR')))
        ORDER BY created_at, id LIMIT 100

Builds Enumerator from Active Record Relation . Each Enumerator tick moves the cursor one row forward .


def build_active_record_enumerator_on_batches(scope, cursor:, **args)
      enum = build_active_record_enumerator(
        scope,
        cursor: cursor,
        **args
      ).batches
      wrap(self, enum)
    end

Builds Enumerator from Active Record Relation and enumerates on batches.
 Each Enumerator tick moves the cursor +batch_size+ rows forward.

 +batch_size:+ sets how many records will be fetched in one batch. Defaults to 100.

 For the rest of arguments, see documentation for #build_active_record_enumerator_on_records

Builds Enumerator from Active Record Relation and enumerates on batches . Each Enumerator tick moves the cursor + batch_size + rows forward .


def batches(batch_size:, cursor:)
      @csv.lazy
        .each_slice(batch_size)
        .each_with_index
        .drop(cursor.to_i)
        .to_enum { (count_rows_in_file.to_f / batch_size).ceil }
    end

def batches ( batch_size : , cursor : ) @csv . lazy . each_slice ( batch_size ) . each_with_index . drop ( cursor . to_i ) . to_enum { ( count_rows_in_file . to_f / batch_size ) . ceil } end

Constructs a enumerator on batches of CSV rows
 @return [Enumerator] Enumerator instance


def reify(options = {})
      unless self.class.column_names.include? "object"
        raise "reify can't be called without an object column"
      end
      return nil if object.nil?
      ::PaperTrail::Reifier.reify(self, options)
    end

Restore the item from this version.

 Optionally this can also restore all :has_one and :has_many (including
 has_many :through) associations as they were "at the time", if they are
 also being versioned by PaperTrail.

 Options:

 - :has_one
   - `true` - Also reify has_one associations.
   - `false - Default.
 - :has_many
   - `true` - Also reify has_many and has_many :through associations.
   - `false` - Default.
 - :mark_for_destruction
   - `true` - Mark the has_one/has_many associations that did not exist in
     the reified version for destruction, instead of removing them.
   - `false` - Default. Useful for persisting the reified version.
 - :dup
   - `false` - Default.
   - `true` - Always create a new object instance. Useful for
     comparing two versions of the same object.
 - :unversioned_attributes
   - `:nil` - Default. Attributes undefined in version record are set to
     nil in reified record.
   - `:preserve` - Attributes undefined in version record are not modified.


def version_limit
      if self.class.item_subtype_column_present?
        klass = (item_subtype || item_type).constantize
        if klass&.paper_trail_options&.key?(:limit)
          return klass.paper_trail_options[:limit]
        end
      end
      PaperTrail.config.version_limit
    end

def version_limit if self . class . item_subtype_column_present? klass = ( item_subtype || item_type ) . constantize if klass &. paper_trail_options &. key? ( :limit ) return klass . paper_trail_options [ :limit ] end end PaperTrail . config . version_limit end

See docs section 2.e. Limiting the Number of Versions Created.
 The version limit can be global or per-model.

 @api private

 TODO: Duplication: similar `constantize` in Reifier#version_reification_class

See docs section 2 . e . Limiting the Number of Versions Created . The version limit can be global or per - model .


def on_create
      @model_class.after_create { |r|
        r.paper_trail.record_create if r.paper_trail.save_version?
      }
      return if @model_class.paper_trail_options[:on].include?(:create)
      @model_class.paper_trail_options[:on] << :create
    end

def on_create @model_class . after_create { | r | r . paper_trail . record_create if r . paper_trail . save_version? } return if @model_class . paper_trail_options [ :on ] . include? ( :create ) @model_class . paper_trail_options [ :on ] << :create end

Adds a callback that records a version after a "create" event.

 @api public

Adds a callback that records a version after a create event .


def on_destroy(recording_order = "before")
      unless %w[after before].include?(recording_order.to_s)
        raise ArgumentError, 'recording order can only be "after" or "before"'
      end

      if recording_order.to_s == "after" && cannot_record_after_destroy?
        raise E_CANNOT_RECORD_AFTER_DESTROY
      end

      @model_class.send(
        "#{recording_order}_destroy",
        lambda do |r|
          return unless r.paper_trail.save_version?
          r.paper_trail.record_destroy(recording_order)
        end
      )

      return if @model_class.paper_trail_options[:on].include?(:destroy)
      @model_class.paper_trail_options[:on] << :destroy
    end

Adds a callback that records a version before or after a "destroy" event.

 @api public

Adds a callback that records a version before or after a destroy event .


def on_update
      @model_class.before_save { |r|
        r.paper_trail.reset_timestamp_attrs_for_update_if_needed
      }
      @model_class.after_update { |r|
        if r.paper_trail.save_version?
          r.paper_trail.record_update(
            force: false,
            in_after_callback: true,
            is_touch: false
          )
        end
      }
      @model_class.after_update { |r|
        r.paper_trail.clear_version_instance
      }
      return if @model_class.paper_trail_options[:on].include?(:update)
      @model_class.paper_trail_options[:on] << :update
    end

Adds a callback that records a version after an "update" event.

 @api public

Adds a callback that records a version after an update event .


def on_touch
      @model_class.after_touch { |r|
        r.paper_trail.record_update(
          force: true,
          in_after_callback: true,
          is_touch: true
        )
      }
    end

def on_touch @model_class . after_touch { | r | r . paper_trail . record_update ( force : true , in_after_callback : true , is_touch : true ) } end

Adds a callback that records a version after a "touch" event.
 @api public

Adds a callback that records a version after a touch event .


def check_presence_of_item_subtype_column(options)
      return unless options.key?(:limit)
      return if version_class.item_subtype_column_present?
      raise format(E_MODEL_LIMIT_REQUIRES_ITEM_SUBTYPE, @model_class.name)
    end

def check_presence_of_item_subtype_column ( options ) return unless options . key? ( :limit ) return if version_class . item_subtype_column_present? raise format ( E_MODEL_LIMIT_REQUIRES_ITEM_SUBTYPE , @model_class . name ) end

Some options require the presence of the `item_subtype` column. Currently
 only `limit`, but in the future there may be others.

 @api private

Some options require the presence of the item_subtype column . Currently only limit but in the future there may be others .


def save_version?
      if_condition = @record.paper_trail_options[:if]
      unless_condition = @record.paper_trail_options[:unless]
      (if_condition.blank? || if_condition.call(@record)) && !unless_condition.try(:call, @record)
    end

def save_version? if_condition = @record . paper_trail_options [ :if ] unless_condition = @record . paper_trail_options [ :unless ] ( if_condition . blank? || if_condition . call ( @record ) ) && ! unless_condition . try ( :call , @record ) end


def _squash_changes(changes)
      # We combine here for backward compatibility
      # Newer clients should receive dir and path separately
      changes = changes.map { |change, dir, path| [change, dir + path] }

      actions = changes.group_by(&:last).map do |path, action_list|
        [_logical_action_for(path, action_list.map(&:first)), path.to_s]
      end

      config.debug("listen: raw changes: #{actions.inspect}")

      { modified: [], added: [], removed: [] }.tap do |squashed|
        actions.each do |type, path|
          squashed[type] << path unless type.nil?
        end
        config.debug("listen: final changes: #{squashed.inspect}")
      end
    end

groups changes into the expected structure expected by
 clients


def to_node object
      if object.is_a?(self.ancestry_base_class) then object else unscoped_where{|scope| scope.find object} end
    end

def to_node object if object . is_a? ( self . ancestry_base_class ) then object else unscoped_where { | scope | scope . find object } end end


def scope_depth depth_options, depth
      depth_options.inject(self.ancestry_base_class) do |scope, option|
        scope_name, relative_depth = option
        if [:before_depth, :to_depth, :at_depth, :from_depth, :after_depth].include? scope_name
          scope.send scope_name, depth + relative_depth
        else
          raise Ancestry::AncestryException.new("Unknown depth option: #{scope_name}.")
        end
      end
    end

def
scope_depth
depth_options
,
depth
depth_options
.
inject
(
self
.
ancestry_base_class
)
do
|
scope
,
option
|
scope_name
,
relative_depth
=
option
if
[
:before_depth
,
:to_depth
,
:at_depth
,
:from_depth
,
:after_depth
]
.
include?
scope_name
scope
.
send
scope_name
,
depth
+
relative_depth
else
raise
Ancestry
::
AncestryException
.
new
(
"Unknown depth option: #{scope_name}."
)
end
end
end


def orphan_strategy= orphan_strategy
      # Check value of orphan strategy, only rootify, adopt, restrict or destroy is allowed
      if [:rootify, :adopt, :restrict, :destroy].include? orphan_strategy
        class_variable_set :@@orphan_strategy, orphan_strategy
      else
        raise Ancestry::AncestryException.new("Invalid orphan strategy, valid ones are :rootify,:adopt, :restrict and :destroy.")
      end
    end


def arrange options = {}
      if (order = options.delete(:order))
        arrange_nodes self.ancestry_base_class.order(order).where(options)
      else
        arrange_nodes self.ancestry_base_class.where(options)
      end
    end

def arrange options = { } if ( order = options . delete ( :order ) ) arrange_nodes self . ancestry_base_class . order ( order ) . where ( options ) else arrange_nodes self . ancestry_base_class . where ( options ) end end

Get all nodes and sorting them into an empty hash


def arrange_serializable options={}, nodes=nil, &block
      nodes = arrange(options) if nodes.nil?
      nodes.map do |parent, children|
        if block_given?
          yield parent, arrange_serializable(options, children, &block)
        else
          parent.serializable_hash.merge 'children' => arrange_serializable(options, children)
        end
      end
    end

def arrange_serializable options = { } , nodes = nil , & block nodes = arrange ( options ) if nodes . nil? nodes . map do | parent , children | if block_given? yield parent , arrange_serializable ( options , children , & block ) else parent . serializable_hash . merge 'children' => arrange_serializable ( options , children ) end end end


def build_ancestry_from_parent_ids! parent_id = nil, ancestry = nil
      unscoped_where do |scope|
        scope.where(:parent_id => parent_id).find_each do |node|
          node.without_ancestry_callbacks do
            node.update_attribute ancestry_column, ancestry
          end
          build_ancestry_from_parent_ids! node.id, if ancestry.nil? then "#{node.id}" else "#{ancestry}/#{node.id}" end
        end
      end
    end

def build_ancestry_from_parent_ids! parent_id = nil , ancestry = nil unscoped_where do | scope | scope . where ( :parent_id => parent_id ) . find_each do | node | node . without_ancestry_callbacks do node . update_attribute ancestry_column , ancestry end build_ancestry_from_parent_ids! node . id , if ancestry . nil? then "#{node.id}" else "#{ancestry}/#{node.id}" end end end end

Build ancestry from parent id's for migration purposes

Build ancestry from parent id s for migration purposes


def rebuild_depth_cache!
      raise Ancestry::AncestryException.new("Cannot rebuild depth cache for model without depth caching.") unless respond_to? :depth_cache_column

      self.ancestry_base_class.transaction do
        unscoped_where do |scope|
          scope.find_each do |node|
            node.update_attribute depth_cache_column, node.depth
          end
        end
      end
    end

Rebuild depth cache if it got corrupted or if depth caching was just turned on


def indirect_conditions(object)
      t = arel_table
      node = to_node(object)
      # rails has case sensitive matching.
      if ActiveRecord::VERSION::MAJOR >= 5
        t[ancestry_column].matches("#{node.child_ancestry}/%", nil, true)
      else
        t[ancestry_column].matches("#{node.child_ancestry}/%")
      end
    end

def indirect_conditions ( object ) t = arel_table node = to_node ( object ) if ActiveRecord :: VERSION :: MAJOR >= 5 t [ ancestry_column ] . matches ( "#{node.child_ancestry}/%" , nil , true ) else t [ ancestry_column ] . matches ( "#{node.child_ancestry}/%" ) end end

indirect = anyone who is a descendant, but not a child

indirect = anyone who is a descendant but not a child


def request_defaults(sudo = nil)
      self.class.default_params sudo: sudo
      raise Error::MissingCredentials, 'Please set an endpoint to API' unless @endpoint

      self.class.default_params.delete(:sudo) if sudo.nil?
    end

def
request_defaults
(
sudo
=
)
self
.
class
.
default_params
sudo
:
sudo
raise
Error
::
MissingCredentials
,
'Please set an endpoint to API'
unless
@endpoint
self
.
class
.
default_params
.
delete
(
:sudo
)
if
sudo
.
nil?
end

Sets a base_uri and default_params for requests.
 @raise [Error::MissingCredentials] if endpoint not set.

Sets a base_uri and default_params for requests .


def options
      VALID_OPTIONS_KEYS.inject({}) do |option, key|
        option.merge!(key => send(key))
      end
    end

def options VALID_OPTIONS_KEYS . inject ( { } ) do | option , key | option . merge! ( key => send ( key ) ) end end

Creates a hash of options and their values.

Creates a hash of options and their values .


def reset
      self.endpoint       = ENV['GITLAB_API_ENDPOINT']
      self.private_token  = ENV['GITLAB_API_PRIVATE_TOKEN'] || ENV['GITLAB_API_AUTH_TOKEN']
      self.httparty       = get_httparty_config(ENV['GITLAB_API_HTTPARTY_OPTIONS'])
      self.sudo           = nil
      self.user_agent     = DEFAULT_USER_AGENT
    end

def reset self . endpoint = ENV [ 'GITLAB_API_ENDPOINT' ] self . private_token = ENV [ 'GITLAB_API_PRIVATE_TOKEN' ] || ENV [ 'GITLAB_API_AUTH_TOKEN' ] self . httparty = get_httparty_config ( ENV [ 'GITLAB_API_HTTPARTY_OPTIONS' ] ) self . sudo = nil self . user_agent = DEFAULT_USER_AGENT end

Resets all configuration options to the defaults.

Resets all configuration options to the defaults .


def get_httparty_config(options)
      return if options.nil?

      httparty = Gitlab::CLI::Helpers.yaml_load(options)
      raise ArgumentError, 'HTTParty config should be a Hash.' unless httparty.is_a? Hash

      Gitlab::CLI::Helpers.symbolize_keys httparty
    end

def
get_httparty_config
(
options
)
return
if
options
.
nil?
httparty
=
Gitlab
::
CLI
::
Helpers
.
yaml_load
(
options
)
raise
ArgumentError
,
'HTTParty config should be a Hash.'
unless
httparty
.
is_a?
Hash
Gitlab
::
CLI
::
Helpers
.
symbolize_keys
httparty
end

Allows HTTParty config to be specified in ENV using YAML hash.

Allows HTTParty config to be specified in ENV using YAML hash .


def start_timer(timer = DEFAULT_TIMER.new)
      raise Socketry::InternalError, "timer already started" if defined?(@timer)
      raise Socketry::InternalError, "deadline already set"  if defined?(@deadline)

      @deadline = nil
      @timer = timer
      @timer.start
      true
    end

def
start_timer
(
timer
=
DEFAULT_TIMER
.
new
)
raise
Socketry
::
InternalError
,
"timer already started"
if
defined?
(
@timer
)
raise
Socketry
::
InternalError
,
"deadline already set"
if
defined?
(
@deadline
)
@deadline
=
@timer
=
timer
@timer
.
start
true
end

Start a timer in the included object

 @param timer [#start, #to_f] a timer object (ideally monotonic)
 @return [true] timer started successfully
 @raise [Socketry::InternalError] if timer is already started


def set_timeout(timeout)
      raise Socketry::InternalError, "deadline already set" if @deadline
      return unless timeout
      raise Socketry::TimeoutError, "time expired" if timeout < 0

      @deadline = lifetime + timeout
    end

def
set_timeout
(
timeout
)
raise
Socketry
::
InternalError
,
"deadline already set"
if
@deadline
return
unless
timeout
raise
Socketry
::
TimeoutError
,
"time expired"
if
timeout
<
0
@deadline
=
lifetime
+
timeout
end

Set a timeout. Only one timeout may be active at a given time for a given object.

 @param timeout [Numeric] number of seconds until the timeout is reached
 @return [Float] deadline (relative to #lifetime) at which the timeout is reached
 @raise [Socketry::InternalError] if timeout is already set

Set a timeout . Only one timeout may be active at a given time for a given object .


def time_remaining(timeout)
      return unless timeout
      raise Socketry::InternalError, "no deadline set" unless @deadline

      remaining = @deadline - lifetime
      raise Socketry::TimeoutError, "time expired" if remaining <= 0

      remaining
    end

def
time_remaining
(
timeout
)
return
unless
timeout
raise
Socketry
::
InternalError
,
"no deadline set"
unless
@deadline
remaining
=
@deadline
lifetime
raise
Socketry
::
TimeoutError
,
"time expired"
if
remaining
<=
0
remaining
end

Calculate number of seconds remaining until we hit the timeout

 @param timeout [Numeric] to gauge whether a timeout needs to be calculated
 @return [Float] number of seconds remaining until we hit the timeout
 @raise [Socketry::TimeoutError] if we've already hit the timeout
 @raise [Socketry::InternalError] if timeout has not been set


def build_schemas(parent_schema)
      schema = parent_schema.schema

      # Build ref schemas if they exist
      if schema["$ref"]
        load_ref_schema(parent_schema, schema["$ref"])
      end

      case schema["extends"]
      when String
        load_ref_schema(parent_schema, schema["extends"])
      when Array
        schema['extends'].each do |type|
          handle_schema(parent_schema, type)
        end
      end

      # Check for schemas in union types
      ["type", "disallow"].each do |key|
        if schema[key].is_a?(Array)
          schema[key].each do |type|
            if type.is_a?(Hash)
              handle_schema(parent_schema, type)
            end
          end
        end
      end

      # Schema properties whose values are objects, the values of which
      # are themselves schemas.
      %w[definitions properties patternProperties].each do |key|
        next unless value = schema[key]
        value.each do |k, inner_schema|
          handle_schema(parent_schema, inner_schema)
        end
      end

      # Schema properties whose values are themselves schemas.
      %w[additionalProperties additionalItems dependencies extends].each do |key|
        next unless schema[key].is_a?(Hash)
        handle_schema(parent_schema, schema[key])
      end

      # Schema properties whose values may be an array of schemas.
      %w[allOf anyOf oneOf not].each do |key|
        next unless value = schema[key]
        Array(value).each do |inner_schema|
          handle_schema(parent_schema, inner_schema)
        end
      end

      # Items are always schemas
      if schema["items"]
        items = schema["items"].clone
        items = [items] unless items.is_a?(Array)

        items.each do |item|
          handle_schema(parent_schema, item)
        end
      end

      # Convert enum to a ArraySet
      if schema["enum"].is_a?(Array)
        schema["enum"] = ArraySet.new(schema["enum"])
      end

    end

def build_schemas ( parent_schema ) schema = parent_schema . schema if schema [ "$ref" ] load_ref_schema ( parent_schema , schema [ "$ref" ] ) end case schema [ "extends" ] when String load_ref_schema ( parent_schema , schema [ "extends" ] ) when Array schema [ 'extends' ] . each do | type | handle_schema ( parent_schema , type ) end end [ "type" , "disallow" ] . each do | key | if schema [ key ] . is_a? ( Array ) schema [ key ] . each do | type | if type . is_a? ( Hash ) handle_schema ( parent_schema , type ) end end end end %w[ definitions properties patternProperties ] . each do | key | next unless value = schema [ key ] value . each do | k , inner_schema | handle_schema ( parent_schema , inner_schema ) end end %w[ additionalProperties additionalItems dependencies extends ] . each do | key | next unless schema [ key ] . is_a? ( Hash ) handle_schema ( parent_schema , schema [ key ] ) end %w[ allOf anyOf oneOf not ] . each do | key | next unless value = schema [ key ] Array ( value ) . each do | inner_schema | handle_schema ( parent_schema , inner_schema ) end end if schema [ "items" ] items = schema [ "items" ] . clone items = [ items ] unless items . is_a? ( Array ) items . each do | item | handle_schema ( parent_schema , item ) end end if schema [ "enum" ] . is_a? ( Array ) schema [ "enum" ] = ArraySet . new ( schema [ "enum" ] ) end end

Build all schemas with IDs, mapping out the namespace

Build all schemas with IDs mapping out the namespace


def handle_schema(parent_schema, obj)
      if obj.is_a?(Hash)
        schema_uri = parent_schema.uri.dup
        schema = JSON::Schema.new(obj, schema_uri, parent_schema.validator)
        if obj['id']
          self.class.add_schema(schema)
        end
        build_schemas(schema)
      end
    end

def handle_schema ( parent_schema , obj ) if obj . is_a? ( Hash ) schema_uri = parent_schema . uri . dup schema = JSON :: Schema . new ( obj , schema_uri , parent_schema . validator ) if obj [ 'id' ] self . class . add_schema ( schema ) end build_schemas ( schema ) end end

Either load a reference schema or create a new schema


def matches_conditions?(action, subject, extra_args)
      if @match_all
        call_block_with_all(action, subject, extra_args)
      elsif @block && !subject_class?(subject)
        @block.call(subject, *extra_args)
      elsif @conditions.kind_of?(Hash) && subject.class == Hash
        nested_subject_matches_conditions?(subject)
      elsif @conditions.kind_of?(Hash) && !subject_class?(subject)
        matches_conditions_hash?(subject)
      else
        # Don't stop at "cannot" definitions when there are conditions.
        @conditions.empty? ? true : @base_behavior
      end
    end

def matches_conditions? ( action , subject , extra_args ) if @match_all call_block_with_all ( action , subject , extra_args ) elsif @block && ! subject_class? ( subject ) @block . call ( subject , * extra_args ) elsif @conditions . kind_of? ( Hash ) && subject . class == Hash nested_subject_matches_conditions? ( subject ) elsif @conditions . kind_of? ( Hash ) && ! subject_class? ( subject ) matches_conditions_hash? ( subject ) else @conditions . empty? ? true : @base_behavior end end


def alias_action(*args)
      target = args.pop[:to]
      validate_target(target)
      aliased_actions[target] ||= []
      aliased_actions[target] += args
    end

def alias_action ( * args ) target = args . pop [ :to ] validate_target ( target ) aliased_actions [ target ] ||= [ ] aliased_actions [ target ] += args end

Alias one or more actions into another one.

   alias_action :update, :destroy, :to => :modify
   can :modify, Comment

 Then :modify permission will apply to both :update and :destroy requests.

   can? :update, Comment # => true
   can? :destroy, Comment # => true

 This only works in one direction. Passing the aliased action into the "can?" call
 will not work because aliases are meant to generate more generic actions.

   alias_action :update, :destroy, :to => :modify
   can :update, Comment
   can? :modify, Comment # => false

 Unless that exact alias is used.

   can :modify, Comment
   can? :modify, Comment # => true

 The following aliases are added by default for conveniently mapping common controller actions.

   alias_action :index, :show, :to => :read
   alias_action :new, :to => :create
   alias_action :edit, :to => :update

 This way one can use params[:action] in the controller to determine the permission.

Alias one or more actions into another one .


def expand_actions(actions)
      actions.map do |action|
        aliased_actions[action] ? [action, *expand_actions(aliased_actions[action])] : action
      end.flatten
    end

def expand_actions ( actions ) actions . map do | action | aliased_actions [ action ] ? [ action , * expand_actions ( aliased_actions [ action ] ) ] : action end . flatten end

Accepts an array of actions and returns an array of actions which match.
 This should be called before "matches?" and other checking methods since they
 rely on the actions to be expanded.

Accepts an array of actions and returns an array of actions which match . This should be called before matches? and other checking methods since they rely on the actions to be expanded .


def aliases_for_action(action)
      results = [action]
      aliased_actions.each do |aliased_action, actions|
        results += aliases_for_action(aliased_action) if actions.include? action
      end
      results
    end

def aliases_for_action ( action ) results = [ action ] aliased_actions . each do | aliased_action , actions | results += aliases_for_action ( aliased_action ) if actions . include? action end results end

Given an action, it will try to find all of the actions which are aliased to it.
 This does the opposite kind of lookup as expand_actions.

Given an action it will try to find all of the actions which are aliased to it . This does the opposite kind of lookup as expand_actions .


def relevant_rules(action, subject)
      rules.reverse.select do |rule|
        rule.expanded_actions = expand_actions(rule.actions)
        rule.relevant? action, subject
      end
    end

def relevant_rules ( action , subject ) rules . reverse . select do | rule | rule . expanded_actions = expand_actions ( rule . actions ) rule . relevant? action , subject end end

Returns an array of Rule instances which match the action and subject
 This does not take into consideration any hash conditions or block statements


def create_missing_file
      raise Errno::EISDIR, path.to_s if File.directory?(@path)

      return if File.exist?(@path) # Unnecessary check, probably.
      dirname = RealFile.dirname @path

      unless dirname == '.'
        dir = FileSystem.find dirname

        raise Errno::ENOENT, path.to_s unless dir.is_a? FakeDir
      end

      @file = FileSystem.add(path, FakeFile.new)
    end

def create_missing_file raise Errno :: EISDIR , path . to_s if File . directory? ( @path ) return if File . exist? ( @path ) dirname = RealFile . dirname @path unless dirname == '.' dir = FileSystem . find dirname raise Errno :: ENOENT , path . to_s unless dir . is_a? FakeDir end @file = FileSystem . add ( path , FakeFile . new ) end

Create a missing file if the path is valid.

Create a missing file if the path is valid .


def each_filename # :yield: filename
      return to_enum(__method__) unless block_given?
      _prefix, names = split_names(@path)
      names.each { |filename| yield filename }
      nil
    end

def each_filename return to_enum ( __method__ ) unless block_given? _prefix , names = split_names ( @path ) names . each { | filename | yield filename } nil end

Iterates over each component of the path.

   Pathname.new("/usr/bin/ruby").each_filename { |filename| ... }
     # yields "usr", "bin", and "ruby".

Iterates over each component of the path .


def descend
      vs = []
      ascend { |v| vs << v }
      vs.reverse_each { |v| yield v }
      nil
    end

def descend vs = [ ] ascend { | v | vs << v } vs . reverse_each { | v | yield v } nil end

Iterates over and yields a new Pathname object
 for each element in the given path in descending order.

  Pathname.new('/path/to/some/file.rb').descend { |v| p v}
     #<Pathname:/>
     #<Pathname:/path>
     #<Pathname:/path/to>
     #<Pathname:/path/to/some>
     #<Pathname:/path/to/some/file.rb>

  Pathname.new('path/to/some/file.rb').descend { |v| p v}
     #<Pathname:path>
     #<Pathname:path/to>
     #<Pathname:path/to/some>
     #<Pathname:path/to/some/file.rb>

 It doesn't access actual filesystem.

 This method is available since 1.8.5.

Iterates over and yields a new Pathname object for each element in the given path in descending order .


def ascend
      path = @path
      yield self
      while (r = chop_basename(path))
        path, _name = r
        break if path.empty?
        yield self.class.new(del_trailing_separator(path))
      end
    end

def ascend path = @path yield self while ( r = chop_basename ( path ) ) path , _name = r break if path . empty? yield self . class . new ( del_trailing_separator ( path ) ) end end

Iterates over and yields a new Pathname object
 for each element in the given path in ascending order.

  Pathname.new('/path/to/some/file.rb').ascend { |v| p v}
     #<Pathname:/path/to/some/file.rb>
     #<Pathname:/path/to/some>
     #<Pathname:/path/to>
     #<Pathname:/path>
     #<Pathname:/>

  Pathname.new('path/to/some/file.rb').ascend { |v| p v}
     #<Pathname:path/to/some/file.rb>
     #<Pathname:path/to/some>
     #<Pathname:path/to>
     #<Pathname:path>

 It doesn't access actual filesystem.

 This method is available since 1.8.5.

Iterates over and yields a new Pathname object for each element in the given path in ascending order .


def c_checksum
      sum = 0
      checksum_values.each_with_index do |value, index|
        sum += ((index % 20) + 1) * value
      end
      sum % 47
    end

def c_checksum sum = 0 checksum_values . each_with_index do | value , index | sum += ( ( index % 20 ) + 1 ) * value end sum % 47 end

Calculates the C checksum based on checksum_values


def k_checksum
      sum = 0
      checksum_values_with_c_checksum.each_with_index do |value, index|
        sum += ((index % 15) + 1) * value
      end
      sum % 47
    end

def k_checksum sum = 0 checksum_values_with_c_checksum . each_with_index do | value , index | sum += ( ( index % 15 ) + 1 ) * value end sum % 47 end

Calculates the K checksum based on checksum_values_with_c_checksum


def annotate_pdf(pdf, options={})
      with_options options do

        xpos, ypos = x, y
        orig_xpos = xpos

        if barcode.two_dimensional?
          boolean_groups.reverse_each do |groups|
            groups.each do |bar,amount|
              if bar
                pdf.move_to(xpos, ypos).
                  line_to(xpos, ypos+xdim).
                  line_to(xpos+(xdim*amount), ypos+xdim).
                  line_to(xpos+(xdim*amount), ypos).
                  line_to(xpos, ypos).
                  fill
              end
              xpos += (xdim*amount)
            end
            xpos = orig_xpos
            ypos += xdim
          end
        else
          boolean_groups.each do |bar,amount|
            if bar
              pdf.move_to(xpos, ypos).
                line_to(xpos, ypos+height).
                line_to(xpos+(xdim*amount), ypos+height).
                line_to(xpos+(xdim*amount), ypos).
                line_to(xpos, ypos).
                fill
            end
            xpos += (xdim*amount)
          end
        end

      end

      pdf
    end

def annotate_pdf ( pdf , options = { } ) with_options options do xpos , ypos = x , y orig_xpos = xpos if barcode . two_dimensional? boolean_groups . reverse_each do | groups | groups . each do | bar , amount | if bar pdf . move_to ( xpos , ypos ) . line_to ( xpos , ypos + xdim ) . line_to ( xpos + ( xdim * amount ) , ypos + xdim ) . line_to ( xpos + ( xdim * amount ) , ypos ) . line_to ( xpos , ypos ) . fill end xpos += ( xdim * amount ) end xpos = orig_xpos ypos += xdim end else boolean_groups . each do | bar , amount | if bar pdf . move_to ( xpos , ypos ) . line_to ( xpos , ypos + height ) . line_to ( xpos + ( xdim * amount ) , ypos + height ) . line_to ( xpos + ( xdim * amount ) , ypos ) . line_to ( xpos , ypos ) . fill end xpos += ( xdim * amount ) end end end pdf end

Annotate a PDFWriter document with the barcode

Valid options are:

x, y   - The point in the document to start rendering from
height - The height of the bars in PDF units
xdim   - The X dimension in PDF units


def characters
      chars = raw_characters
      extended ? chars.map{|c| EXTENDED_ENCODINGS[c].split(//) }.flatten : chars
    end

def characters chars = raw_characters extended ? chars . map { | c | EXTENDED_ENCODINGS [ c ] . split ( / / ) } . flatten : chars end

Returns the encodable characters. If extended mode is enabled, each character will
first be replaced by two characters from the encodable charset

Returns the encodable characters . If extended mode is enabled each character will first be replaced by two characters from the encodable charset


def characters
      chars = data.split(//n)

      if type == 'C'
        result = []
        count = 0
        while count < chars.size
          if chars[count] =~ /^\d$/
            #If encountering a digit, next char/byte *must* be second digit in pair. I.e. if chars[count] is 5,
            #chars[count+1] must be /[0-9]/, otherwise it's not valid
            result << "#{chars[count]}#{chars[count+1]}"
            count += 2
          else
            result << chars[count]
            count += 1
          end
        end
        result
      else
        chars
      end
    end

def characters chars = data . split ( / /n ) if type == 'C' result = [ ] count = 0 while count < chars . size if chars [ count ] =~ / \d / result << "#{chars[count]}#{chars[count+1]}" count += 2 else result << chars [ count ] count += 1 end end result else chars end end

Get an array of the individual characters for this barcode. Special
characters like FNC1 will be present. Characters from extras are not
present.

Get an array of the individual characters for this barcode . Special characters like FNC1 will be present . Characters from extras are not present .


def checksum
      pos = 0
      (numbers+extra_numbers).inject(start_num) do |sum,number|
        pos += 1
        sum + (number * pos)
      end % 103
    end

def checksum pos = 0 ( numbers + extra_numbers ) . inject ( start_num ) do | sum , number | pos += 1 sum + ( number * pos ) end % 103 end

Calculate the checksum for the data in this barcode. The data includes
data from extras.

Calculate the checksum for the data in this barcode . The data includes data from extras .


def encoding_for_bars(*bars)
      wide, narrow, space = wide_encoding, narrow_encoding, space_encoding
      bars.flatten.inject '' do |enc,bar|
        enc + (bar == WIDE ? wide : narrow) + space
      end
    end

def encoding_for_bars ( * bars ) wide , narrow , space = wide_encoding , narrow_encoding , space_encoding bars . flatten . inject '' do | enc , bar | enc + ( bar == WIDE ? wide : narrow ) + space end end


def render_to_cairo_context(context, options={})
      if context.respond_to?(:have_current_point?) and
          context.have_current_point?
        current_x, current_y = context.current_point
      else
        current_x = x(options) || margin(options)
        current_y = y(options) || margin(options)
      end

      _xdim = xdim(options)
      _height = height(options)
      original_current_x = current_x
      context.save do
        context.set_source_color(:black)
        context.fill do
          if barcode.two_dimensional?
            boolean_groups.each do |groups|
              groups.each do |bar,amount|
                current_width = _xdim * amount
                if bar
                  context.rectangle(current_x, current_y, current_width, _xdim)
                end
                current_x += current_width
              end
              current_x = original_current_x
              current_y += _xdim
            end
          else
            boolean_groups.each do |bar,amount|
              current_width = _xdim * amount
              if bar
                context.rectangle(current_x, current_y, current_width, _height)
              end
              current_x += current_width
            end
          end
        end
      end

      context
    end

def render_to_cairo_context ( context , options = { } ) if context . respond_to? ( :have_current_point? ) and context . have_current_point? current_x , current_y = context . current_point else current_x = x ( options ) || margin ( options ) current_y = y ( options ) || margin ( options ) end _xdim = xdim ( options ) _height = height ( options ) original_current_x = current_x context . save do context . set_source_color ( :black ) context . fill do if barcode . two_dimensional? boolean_groups . each do | groups | groups . each do | bar , amount | current_width = _xdim * amount if bar context . rectangle ( current_x , current_y , current_width , _xdim ) end current_x += current_width end current_x = original_current_x current_y += _xdim end else boolean_groups . each do | bar , amount | current_width = _xdim * amount if bar context . rectangle ( current_x , current_y , current_width , _height ) end current_x += current_width end end end end context end


def to_png(options={})
      output_to_string_io do |io|
        Cairo::ImageSurface.new(options[:format],
                                full_width(options),
                                full_height(options)) do |surface|
          render(surface, options)
          surface.write_to_png(io)
        end
      end
    end

def to_png ( options = { } ) output_to_string_io do | io | Cairo :: ImageSurface . new ( options [ :format ] , full_width ( options ) , full_height ( options ) ) do | surface | render ( surface , options ) surface . write_to_png ( io ) end end end


def to_ps(options={})
      output_to_string_io do |io|
        Cairo::PSSurface.new(io,
                             full_width(options),
                             full_height(options)) do |surface|
          surface.eps = options[:eps] if surface.respond_to?(:eps=)
          render(surface, options)
        end
      end
    end

def to_ps ( options = { } ) output_to_string_io do | io | Cairo :: PSSurface . new ( io , full_width ( options ) , full_height ( options ) ) do | surface | surface . eps = options [ :eps ] if surface . respond_to? ( :eps= ) render ( surface , options ) end end end


def to_pdf(options={})
      output_to_string_io do |io|
        Cairo::PDFSurface.new(io,
                              full_width(options),
                              full_height(options)) do |surface|
          render(surface, options)
        end
      end
    end

def to_pdf ( options = { } ) output_to_string_io do | io | Cairo :: PDFSurface . new ( io , full_width ( options ) , full_height ( options ) ) do | surface | render ( surface , options ) end end end


def to_svg(options={})
      output_to_string_io do |io|
        Cairo::SVGSurface.new(io,
                              full_width(options),
                              full_height(options)) do |surface|
          render(surface, options)
        end
      end
    end

def to_svg ( options = { } ) output_to_string_io do | io | Cairo :: SVGSurface . new ( io , full_width ( options ) , full_height ( options ) ) do | surface | render ( surface , options ) end end end


def max_threads=(number)
      @max_threads = number.to_i.positive? && throttle.zero? ? number.to_i : 1

      hydra.max_concurrency = @max_threads
    end

def max_threads = ( number ) @max_threads = number . to_i . positive? && throttle . zero? ? number . to_i : 1 hydra . max_concurrency = @max_threads end

Set the threads attribute and update hydra accordinly
 If the throttle attribute is > 0, max_threads will be forced to 1

 @param [ Integer ] number

Set the threads attribute and update hydra accordinly If the throttle attribute is > 0 max_threads will be forced to 1


def online?(path = nil)
      NS::Browser.get(url(path)).code.nonzero? ? true : false
    end

def online? ( path = nil ) NS :: Browser . get ( url ( path ) ) . code . nonzero? ? true : false end

Checks if the remote website is up.

 @param [ String ] path

 @return [ Boolean ]


def head_and_get(path, codes = [200], params = {})
      url_to_get  = url(path)
      head_params = (params[:head] || {}).merge(head_or_get_params)

      head_res = NS::Browser.forge_request(url_to_get, head_params).run

      codes.include?(head_res.code) ? NS::Browser.get(url_to_get, params[:get] || {}) : head_res
    end

def head_and_get ( path , codes = [ 200 ] , params = { } ) url_to_get = url ( path ) head_params = ( params [ :head ] || { } ) . merge ( head_or_get_params ) head_res = NS :: Browser . forge_request ( url_to_get , head_params ) . run codes . include? ( head_res . code ) ? NS :: Browser . get ( url_to_get , params [ :get ] || { } ) : head_res end

Perform a HEAD request to the path provided, then if its response code
 is in the array of codes given, a GET is done and the response returned. Otherwise the
 HEAD response is returned.

 @param [ String ] path
 @param [ Array<String> ] codes
 @param [ Hash ] params The requests params
 @option params [ Hash ] :head Request params for the HEAD
 @option params [ hash ] :get Request params for the GET

 @return [ Typhoeus::Response ]

Perform a HEAD request to the path provided then if its response code is in the array of codes given a GET is done and the response returned . Otherwise the HEAD response is returned .


def db
      return @db unless @db.nil?

      Sequel.single_threaded = true
      @db = Sequel.connect(config(:sql_url), :encoding => 'utf8')
      #@db.loggers << Logger.new(STDOUT)
      if @db.tables.empty?
        dir = File.join(File.dirname(__FILE__), 'migrations')
        puts "Database empty, running migrations from #{dir}"
        Sequel.extension :migration
        Sequel::Migrator.apply(@db, dir)
      end

      @db
    end


def ensure_commit(repo, sha, user, comments = true)
      ensure_repo(user, repo)
      c = retrieve_commit(repo, sha, user)

      if c.nil?
        warn "Commit #{user}/#{repo} -> #{sha} does not exist"
        return
      end

      stored = store_commit(c, repo, user)
      ensure_parents(c)
      if not c['commit']['comment_count'].nil? \
         and c['commit']['comment_count'] > 0
        ensure_commit_comments(user, repo, sha) if comments
      end
      ensure_repo_commit(user, repo, sha)
      stored
    end


def ensure_parents(commit)
      commits = db[:commits]
      parents = db[:commit_parents]
      commit['parents'].map do |p|
        save do
          url = p['url'].split(/\//)
          this = commits.first(:sha => commit['sha'])
          parent = commits.first(:sha => url[7])

          if parent.nil?
            c = retrieve_commit(url[5], url[7], url[4])
            if c.nil?
              warn "Could not retrieve commit_parent #{url[4]}/#{url[5]} -> #{url[7]} to #{this[:sha]}"
              next
            end
            parent = store_commit(c, url[5], url[4])
          end

          if parent.nil?
            warn "Could not find #{url[4]}/#{url[5]} -> #{url[7]}, parent to commit #{this[:sha]}"
            next
          end

          if parents.first(:commit_id => this[:id],
                           :parent_id => parent[:id]).nil?

            parents.insert(:commit_id => this[:id],
                           :parent_id => parent[:id])
            info "Added commit_parent #{parent[:sha]} to commit #{this[:sha]}"
          else
            debug "Parent #{parent[:sha]} for commit #{this[:sha]} exists"
          end
          parents.first(:commit_id => this[:id], :parent_id => parent[:id])
        end
      end.select{|x| !x.nil?}
    end

Get the parents for a specific commit. The commit must be first stored
 in the database.

Get the parents for a specific commit . The commit must be first stored in the database .


def ensure_user_followers(followed)
      curuser = ensure_user(followed, false, false)
      followers = db.from(:followers, :users).\
          where(Sequel.qualify('followers', 'follower_id') => Sequel.qualify('users', 'id')).\
          where(Sequel.qualify('followers', 'user_id') => curuser[:id]).select(:login).all

      retrieve_user_followers(followed).reduce([]) do |acc, x|
        if followers.find {|y| y[:login] == x['login']}.nil?
          acc << x
        else
          acc
        end
      end.map { |x| save{ensure_user_follower(followed, x['login']) }}.select{|x| !x.nil?}
    end

def ensure_user_followers ( followed ) curuser = ensure_user ( followed , false , false ) followers = db . from ( :followers , :users ) . where ( Sequel . qualify ( 'followers' , 'follower_id' ) => Sequel . qualify ( 'users' , 'id' ) ) . where ( Sequel . qualify ( 'followers' , 'user_id' ) => curuser [ :id ] ) . select ( :login ) . all retrieve_user_followers ( followed ) . reduce ( [ ] ) do | acc , x | if followers . find { | y | y [ :login ] == x [ 'login' ] } . nil? acc << x else acc end end . map { | x | save { ensure_user_follower ( followed , x [ 'login' ] ) } } . select { | x | ! x . nil? } end

Get all followers for a user. Since we do not know when the actual
 follow event took place, we set the created_at field to the timestamp
 of the method call.

 ==Parameters:
 [user]  The user login to find followers by

Get all followers for a user . Since we do not know when the actual follow event took place we set the created_at field to the timestamp of the method call .


def ensure_user_follower(followed, follower, date_added = nil)
      follower_user = ensure_user(follower, false, false)
      followed_user = ensure_user(followed, false, false)

      if followed_user.nil? or follower_user.nil?
        warn "Could not find follower #{follower} or user #{followed}"
        return
      end

      followers = db[:followers]
      follower_id = follower_user[:id]
      followed_id = followed_user[:id]

      follower_exists = followers.first(:user_id => followed_id,
                                        :follower_id => follower_id)
      if follower_exists.nil?
        added = if date_added.nil?
                  max(follower_user[:created_at], followed_user[:created_at])
                else
                  date_added
                end
        retrieved = retrieve_user_follower(followed, follower)

        if retrieved.nil?
          warn "Could not retrieve follower #{follower} for #{followed}"
          return
        end

        followers.insert(:user_id => followed_id,
                         :follower_id => follower_id,
                         :created_at => added)
        info "Added follower #{follower} to #{followed}"
      else
        debug "Follower #{follower} for user #{followed} exists"
      end

      unless date_added.nil?
        followers.filter(:user_id => followed_id, :follower_id => follower_id)
                 .update(:created_at => date(date_added))
        info "Updated follower #{followed} -> #{follower}, created_at -> #{date(date_added)}"
      end

      followers.first(:user_id => followed_id, :follower_id => follower_id)
    end

Make sure that a user follows another one


def ensure_user_byemail(email, name)
      users = db[:users]
      usr = users.first(:email => email)

      if usr.nil?

        u = retrieve_user_byemail(email, name)

        if u.nil? or u['login'].nil?
          warn "Could not retrieve user #{email} through search API query"
          login = (0...8).map { 65.+(rand(25)).chr }.join
          users.insert(:email => email,
                       :name => name,
                       :login => login,
                       :fake => true,
                       :deleted => false,
                       :created_at => Time.now)
          info "Added user fake #{login} -> #{email}"
          users.first(:login => login)
        else
          in_db = users.first(:login => u['login'])
          geo = geolocate(location: u['location'])
          if in_db.nil?
            users.insert(:login => u['login'],
                         :name => u['name'],
                         :company => u['company'],
                         :email => u['email'],
                         :long => geo[:long],
                         :lat => geo[:lat],
                         :country_code => geo[:country_code],
                         :state => geo[:state],
                         :city => geo[:city],
                         :fake => false,
                         :deleted => false,
                         :created_at => date(u['created_at']))
            info "Added user #{u['login']} (#{email}) through search API query"
          else
            in_db.update(:name => u['name'],
                         :company => u['company'],
                         :email => u['email'],
                         :long => geo[:long],
                         :lat => geo[:lat],
                         :country_code => geo[:country_code],
                         :state => geo[:state],
                         :city => geo[:city],
                         :fake => false,
                         :deleted => false,
                         :created_at => date(u['created_at']))
            debug "User #{u['login']} with email #{email} exists"
          end
          users.first(:login => u['login'])
        end
      else
        debug "User with email #{email} exists"
        usr
      end
    end

Try to retrieve a user by email. Search the DB first, fall back to
 Github search API if unsuccessful.

 ==Parameters:
 [email]  The email to lookup the user by
 [name]  The user's name
 == Returns:
 If the user can be retrieved, it is returned as a Hash. Otherwise,
 the result is nil

Try to retrieve a user by email . Search the DB first fall back to Github search API if unsuccessful .


def ensure_repo(user, repo, recursive = false)

      repos = db[:projects]
      curuser = ensure_user(user, false, false)

      if curuser.nil?
        warn "Could not find user #{user}"
        return
      end

      currepo = repos.first(:owner_id => curuser[:id], :name => repo)

      unless currepo.nil?
        debug "Repo #{user}/#{repo} exists"
        return refresh_repo(user, repo, currepo)
      end

      r = retrieve_repo(user, repo, true)

      if r.nil?
        warn "Could not retrieve repo #{user}/#{repo}"
        return
      end

      if r['owner']['login'] != curuser[:login]
        info "Repo changed owner from #{curuser[:login]} to #{r['owner']['login']}"
        curuser = ensure_user(r['owner']['login'], false, false)
      end

      repos.insert(:url => r['url'],
                   :owner_id => curuser[:id],
                   :name => r['name'],
                   :description => unless r['description'].nil? then r['description'][0..254] else nil end,
                   :language => r['language'],
                   :created_at => date(r['created_at']),
                   :updated_at => date(Time.now),
                   :etag => unless r['etag'].nil? then r['etag'] end)

      unless r['parent'].nil?
        parent_owner = r['parent']['owner']['login']
        parent_repo = r['parent']['name']

        parent = ensure_repo(parent_owner, parent_repo)

        if parent.nil?
          warn "Could not find repo #{parent_owner}/#{parent_repo}, parent of: #{user}/#{repo}"
          repos.filter(:owner_id => curuser[:id], :name => repo).update(:forked_from => -1)
        else
          repos.filter(:owner_id => curuser[:id], :name => repo).update(:forked_from => parent[:id])
          info "Repo #{user}/#{repo} is a fork of #{parent_owner}/#{parent_repo}"

          unless ensure_fork_point(user, repo).nil?
            warn "Could not find fork point for #{user}/#{repo}, fork of #{parent_owner}/#{parent_repo}"
          end
        end
      end

      if recursive and not ensure_repo_recursive(user, repo)
        warn "Could retrieve #{user}/#{repo} recursively"
        return nil
      end

      info "Added repo #{user}/#{repo}"
      return repos.first(:owner_id => curuser[:id], :name => repo)
    end

Ensure that a repo exists, or fetch its latest state from Github

 ==Parameters:
 [user]  The email or login name to which this repo belongs
 [repo]  The repo name

 == Returns:
  If the repo can be retrieved, it is returned as a Hash. Otherwise,
  the result is nil

Ensure that a repo exists or fetch its latest state from Github


def ensure_languages(owner, repo)
      currepo = ensure_repo(owner, repo)
      langs = retrieve_languages(owner, repo)

      if langs.nil? or langs.empty?
        warn "Could not find languages for repo #{owner}/#{repo}"
        return
      end

      ts = Time.now
      langs.keys.each do |lang|
        db[:project_languages].insert(
          :project_id => currepo[:id],
          :language   => lang.downcase,
          :bytes      => langs[lang],
          :created_at => ts
        )
        info "Added project_language #{owner}/#{repo} -> #{lang} (#{langs[lang]} bytes)"
      end
      db[:project_languages].where(:project_id => currepo[:id]).where(:created_at => ts).all
    end

Get details about the languages used in the repository


def ensure_fork_commits(owner, repo, parent_owner, parent_repo)

      currepo = ensure_repo(owner, repo)

      if currepo.nil?
        warn "Could not find repo #{owner}/#{repo}"
        return
      end

      parent = ensure_repo(parent_owner, parent_repo)

      if parent.nil?
        warn "Could not find repo #{parent_owner}/#{parent_repo}, parent of #{owner}/#{repo}"
        return
      end

      strategy = case
                   when config(:fork_commits).match(/all/i)
                     :all
                   when config(:fork_commits).match(/fork_point/i)
                     :fork_point
                   when config(:fork_commits).match(/none/i)
                     :none
                   else
                     :fork_point
                 end

      fork_commit = ensure_fork_point(owner, repo)

      if fork_commit.nil? or fork_commit.empty?
        warn "Could not find fork commit for repo #{owner}/#{repo}. Retrieving all commits."
        return ensure_commits(owner, repo, fork_all: true)
      end

      debug "Retrieving commits for fork #{owner}/#{repo}: strategy is #{strategy}"
      return if strategy == :none

      if strategy == :fork_point
        # Retrieve commits up to fork point (fork_commit strategy)
        info "Retrieving commits for #{owner}/#{repo} until fork commit #{fork_commit[:sha]}"
        master_branch = retrieve_default_branch(parent_owner, parent_repo)
        return if master_branch.nil?

        sha   = master_branch
        found = false
        while not found
          commits = retrieve_commits(repo, sha, owner, 1)

          # This means that we retrieved no commits
          if commits.size == 0
            break
          end

          # This means we retrieved the last page again
          if commits.size == 1 and commits[0]['sha'] == sha
            break
          end

          for c in commits
            ensure_commit(repo, c['sha'], owner)
            sha = c['sha']
            if c['sha'] == fork_commit[:sha]
              found = true
              break
            end
          end
        end
      end

      if strategy == :all

        shared_commit = db[:commits].first(:sha => fork_commit)
        copied        = 0
        to_copy = db.from(:project_commits, :commits).\
                  where(Sequel.qualify('project_commits', 'commit_id') => Sequel.qualify('commits', 'id')).\
                  where(Sequel.qualify('project_commits', 'project_id') => parent[:id]).\
                  where('commits.created_at < ?', shared_commit[:created_at]).\
                  select(Sequel.qualify('commits','id'))

        to_copy.each do |c|
          copied += 1
          begin
            db[:project_commits].insert(
                :project_id => currepo[:id],
                :commit_id  => c[:id]
            )
            debug "Copied commit #{c[:sha]} #{parent_owner}/#{parent_repo} -> #{owner}/#{repo} (#{copied} total)"
          rescue StandardError => e
            warn "Could not copy commit #{c[:sha]} #{parent_owner}/#{parent_repo} -> #{owner}/#{repo} : #{e.message}"
          end
        end
        info "Finished copying commits from #{parent_owner}/#{parent_repo} -> #{owner}/#{repo}: #{copied} total"
      end

    end

Fast path to project forking. Retrieve all commits page by page
 until we reach a commit that has been registered with the parent
 repository. Then, copy all remaining parent commits to this repo.

Fast path to project forking . Retrieve all commits page by page until we reach a commit that has been registered with the parent repository . Then copy all remaining parent commits to this repo .