class Dapp::Dimg::Build::Stage::ArtifactDefault

Protected Instance Methods

apply_artifact(artifact, image) click to toggle source
# File lib/dapp/dimg/build/stage/artifact_default.rb, line 8
def apply_artifact(artifact, image)
  return if dimg.dapp.dry_run?

  artifact_dimg = artifact[:dimg]
  cwd = artifact[:options][:cwd]
  include_paths = artifact[:options][:include_paths]
  exclude_paths = artifact[:options][:exclude_paths]
  owner = artifact[:options][:owner]
  group = artifact[:options][:group]
  to = artifact[:options][:to]

  export_folder_name = SecureRandom.uuid

  command = safe_cp(cwd, artifact_dimg.container_tmp_path(artifact_dimg.name, export_folder_name).to_s, nil, nil, include_paths, exclude_paths)
  run_artifact_dimg(artifact_dimg, command)

  command = safe_cp(dimg.container_tmp_path('artifact', artifact_dimg.name, export_folder_name).to_s, to, owner, group, include_paths, exclude_paths)
  image.add_command command
  image.add_volume "#{dimg.tmp_path('artifact', artifact_dimg.name)}:#{dimg.container_tmp_path('artifact', artifact_dimg.name)}:ro"
end

Private Instance Methods

safe_cp(from, to, owner, group, include_paths = [], exclude_paths = []) click to toggle source

rubocop:disable Metrics/ParameterLists

# File lib/dapp/dimg/build/stage/artifact_default.rb, line 33
def safe_cp(from, to, owner, group, include_paths = [], exclude_paths = [])
  ''.tap do |cmd|
    cmd << "#{dimg.dapp.mkdir_bin} -p #{File.dirname(to)}"
    cmd << ' && '
    cmd << dimg.dapp.rsync_bin
    cmd << ' --archive --links --inplace'
    cmd << " --chown=#{owner}:#{group}" if owner or group

    if include_paths.any?
      # Если указали include_paths — это означает, что надо копировать
      # только указанные пути. Поэтому exclude_paths в приоритете, т.к. в данном режиме
      # exclude_paths может относится только к путям, указанным в include_paths.
      # При этом случай, когда в include_paths указали более специальный путь, чем в exclude_paths,
      # будет обрабатываться в пользу exclude, этот путь не скопируется.
      exclude_paths.each do |p|
        cmd << " --filter='-/ #{File.join(from, p)}'"
      end

      include_paths.each do |p|
        target_path = File.join(from, p)

        # Генерируем разрешающее правило для каждого элемента пути
        Pathname.new(target_path).descend do |path_part|
          cmd << " --filter='+/ #{path_part}'"
        end

        # * На данный момент не знаем директорию или файл имел в виду пользователь,
        #   поэтому подставляем фильтры для обоих возможных случаев.
        # * Автоматом подставляем паттерн ** для включения файлов, содержащихся в
        #   директории, которую пользователь указал в include_paths.
        cmd << " --filter='+/ #{target_path}'"
        cmd << " --filter='+/ #{File.join(target_path, '**')}'"
      end

      # Все что не подошло по include — исключается
      cmd << " --filter='-/ #{File.join(from, '**')}'"
    else
      exclude_paths.each do |p|
        cmd << " --filter='-/ #{File.join(from, p)}'"
      end
    end

    # Слэш после from — это инструкция rsync'у для копирования
    # содержимого директории from, а не самой директории.
    cmd << " $(if [ -d #{from} ] ; then echo #{from}/ ; else echo #{from} ; fi) #{to}"
  end
end