Class: Pkg::Tar

Inherits:
Object
  • Object
show all
Includes:
FileUtils
Defined in:
lib/packaging/tar.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTar

Returns a new instance of Tar.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/packaging/tar.rb', line 9

def initialize
  @tar      = Pkg::Util::Tool.find_tool('tar', :required => true)
  @project  = Pkg::Config.project
  @version  = Pkg::Config.version
  @files    = Pkg::Config.files
  @target   = File.join(Pkg::Config.project_root, "pkg", "#{@project}-#{@version}.tar.gz")

  # If the user did not specify any files, then archive the entire working directory
  # instead
  @files ||= Dir.glob('*')

  # We require that the excludes list be a string (which is space
  # separated, we hope)(deprecated) or an array.
  #
  if Pkg::Config.tar_excludes
    if Pkg::Config.tar_excludes.is_a?(String)
      warn "warning: `tar_excludes` should be an array, not a string"
      @excludes = Pkg::Config.tar_excludes.split(' ')
    elsif Pkg::Config.tar_excludes.is_a?(Array)
      @excludes = Pkg::Config.tar_excludes
    else
      fail "Tarball excludes must either be an array or a string, not #{@excludes.class}"
    end
  else
    @excludes = []
  end

  # If the user has specified things to exclude via config file, they will be
  # honored by the tar class, but we also always exclude the packaging repo
  # and 'pkg' directory.
  @excludes += ['pkg', 'ext/packaging']

  # On the other hand, support for explicit templates started with Arrays,
  # so that's all we support.
  #
  if Pkg::Config.templates
    @templates = Pkg::Config.templates.dup
    fail "templates must be an array" unless @templates.is_a?(Array)
    expand_templates
  end
end

Instance Attribute Details

#excludesObject

Returns the value of attribute excludes.



7
8
9
# File 'lib/packaging/tar.rb', line 7

def excludes
  @excludes
end

#filesObject

Returns the value of attribute files.



7
8
9
# File 'lib/packaging/tar.rb', line 7

def files
  @files
end

#projectObject

Returns the value of attribute project.



7
8
9
# File 'lib/packaging/tar.rb', line 7

def project
  @project
end

#targetObject

Returns the value of attribute target.



7
8
9
# File 'lib/packaging/tar.rb', line 7

def target
  @target
end

#templatesObject

Returns the value of attribute templates.



7
8
9
# File 'lib/packaging/tar.rb', line 7

def templates
  @templates
end

#versionObject

Returns the value of attribute version.



7
8
9
# File 'lib/packaging/tar.rb', line 7

def version
  @version
end

Instance Method Details

#clean_up(workdir) ⇒ Object



147
148
149
# File 'lib/packaging/tar.rb', line 147

def clean_up(workdir)
  rm_rf workdir
end

#expand_templatesObject

The templates of a project can include globs, which may expand to an arbitrary number of files. This method expands all of the templates using Dir.glob and then filters out any templates that live in the packaging tools themselves. If the template is a source/target combination, it is returned to the array untouched.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/packaging/tar.rb', line 74

def expand_templates
  @templates.map! do |tempfile|
    if tempfile.is_a?(String)
      # Expand possible globs to all matching entries
      Dir.glob(File.join(Pkg::Config::project_root, tempfile))
    elsif tempfile.is_a?(Hash)
      tempfile
    end
  end
  @templates.flatten!

  # Reject matches that are templates from packaging itself. These will contain the packaging root.
  # These tend to come from the current tar.rake implementation.
  @templates.reject! { |temp| temp.is_a?(String) && temp.match(/#{Pkg::Config::packaging_root}/) }
end

#install_files_to(workdir) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/packaging/tar.rb', line 51

def install_files_to(workdir)
  # It is nice to use arrays in YAML to represent array content, but we used
  # to support a mode where a space-separated string was used.  Support both
  # to allow a gentle migration to a modern style...
  patterns =
    case @files
    when String
      warn "warning: `files` should be an array, not a string"
      @files.split(' ')
    when Array
      @files
    else
      raise "`files` must be a string or an array!"
    end

  Pkg::Util::File.install_files_into_dir(patterns, workdir)
end

#pkg!Object



151
152
153
154
155
156
157
158
# File 'lib/packaging/tar.rb', line 151

def pkg!
  workdir = File.join(Pkg::Util::File.mktemp, "#{@project}-#{@version}")
  mkpath workdir
  self.install_files_to workdir
  self.template(workdir)
  self.tar(@target, workdir)
  self.clean_up workdir
end

#tar(target, source) ⇒ Object



136
137
138
139
140
141
142
143
144
145
# File 'lib/packaging/tar.rb', line 136

def tar(target, source)
  mkpath File.dirname(target)
  cd File.dirname(source) do
    %x(#{@tar} #{@excludes.map { |x| " --exclude #{x} " }.join if @excludes} -zcf '#{File.basename(target)}' '#{File.basename(source)}')
    unless $?.success?
      fail "Failed to create .tar.gz archive with #{@tar}. Please ensure the tar command in your path accepts the flags '-c', '-z', and '-f'"
    end
    mv File.basename(target), target
  end
end

#template(workdir = nil) ⇒ Object

Given the tar object’s template files (assumed to be in Pkg::Config.project_root), transform them, removing the originals. If workdir is passed, assume Pkg::Config.project_root exists in workdir



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/packaging/tar.rb', line 93

def template(workdir = nil)
  workdir ||= Pkg::Config.project_root
  root = Pathname.new(Pkg::Config.project_root)

  # Templates can be either a string or a hash of source and target. If it
  # is a string, the target is assumed to be the same path as the
  # source,with the extension removed. If it is a hash, we assume nothing
  # and use the provided source and target.
  @templates.each do |cur_template|
    if cur_template.is_a?(String)
      template_file = File.expand_path(cur_template)
      target_file = template_file.sub(File.extname(template_file), "")
    elsif cur_template.is_a?(Hash)
      template_file = File.expand_path(cur_template["source"])
      target_file = File.expand_path(cur_template["target"])
    end

    #   We construct paths to the erb template and its proposed target file
    #   relative to the project root, *not* fully qualified. This allows us
    #   to, given a temporary workdir containing a copy of the project,
    #   construct the full path to the erb and target file inside the
    #   temporary workdir.
    #
    rel_path_to_template = Pathname.new(template_file).relative_path_from(root).to_s
    rel_path_to_target = Pathname.new(target_file).relative_path_from(root).to_s

    #   What we pass to Pkg::util::File.erb_file are the paths to the erb
    #   and target inside of a temporary project directory. We are, in
    #   essence, templating "in place." This is why we remove the original
    #   files - they're not the originals in the authoritative project
    #   directory, but the originals in the temporary working copy.
    if File.exist?(File.join(workdir, rel_path_to_template))
      mkpath(File.dirname(File.join(workdir, rel_path_to_target)), :verbose => false)
      Pkg::Util::File.erb_file(File.join(workdir, rel_path_to_template), File.join(workdir, rel_path_to_target), true, :binding => Pkg::Config.get_binding)
    elsif File.exist?(File.join(root, rel_path_to_template))
      mkpath(File.dirname(File.join(workdir, rel_path_to_target)), :verbose => false)
      Pkg::Util::File.erb_file(File.join(root, rel_path_to_template), File.join(workdir, rel_path_to_target), false, :binding => Pkg::Config.get_binding)
    else
      fail "Expected to find #{template_file} in #{root} for templating. But it was not there. Maybe you deleted it?"
    end
  end
end