Class: Forge::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/forge/builder.rb

Instance Method Summary collapse

Constructor Details

#initialize(project) ⇒ Builder

Returns a new instance of Builder.



10
11
12
13
14
15
16
17
18
19
20
# File 'lib/forge/builder.rb', line 10

def initialize(project)
  @project = project
  @task    = project.task
  @templates_path = @project.templates_path
  @assets_path = @project.assets_path
  @functions_path = @project.functions_path
  @includes_path = @project.includes_path
  @package_path = @project.package_path

  init_sprockets
end

Instance Method Details

#buildObject

Runs all the methods necessary to build a completed project



23
24
25
26
27
28
29
# File 'lib/forge/builder.rb', line 23

def build
  clean_build_directory
  copy_templates
  copy_functions
  copy_includes
  build_assets
end

#build_assetsObject



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/forge/builder.rb', line 145

def build_assets
  [['style.css'], ['javascripts', 'theme.js'], ['javascripts', 'admin.js']].each do |asset|
    destination = File.join(@project.build_path, asset)

    sprocket = @sprockets.find_asset(asset.last)

    # Catch any sprockets errors and continue the process
    begin
      @task.shell.mute do
        FileUtils.mkdir_p(File.dirname(destination)) unless File.directory?(File.dirname(destination))
        sprocket.write_to(destination) unless sprocket.nil?

        if @project.config[:compress_js] && destination.end_with?('.js')
          require "yui/compressor"

          # Grab the initial sprockets output
          sprockets_output = File.open(destination, 'r').read

          # Re-write the file, minified
          File.open(destination, 'w') do |file|
            file.write(YUI::JavaScriptCompressor.new.compress(sprockets_output))
          end
        end

        if asset.last == 'style.css'
          @task.prepend_file destination, @project.parse_erb(stylesheet_header)
        end
      end
    rescue Exception => e
      @task.say "Error while building #{asset.last}:"
      @task.say e.message, Thor::Shell::Color::RED
      File.open(destination, 'w') do |file|
        file.puts(e.message)
      end

      # Re-initializing sprockets to prevent further errors
      # TODO: This is done for lack of a better solution
      init_sprockets
    end
  end

  # Copy the images directory over
  FileUtils.cp_r(File.join(@assets_path, 'images'), @project.build_path) if File.exists?(File.join(@assets_path, 'images'))

  # Check for screenshot and move it into main build directory
  Dir.glob(File.join(@project.build_path, 'images', '*')).each do |filename|
    if filename.index(/screenshot\.(png|jpg|jpeg|gif)/)
      FileUtils.mv(filename, @project.build_path + File::SEPARATOR )
    end
  end
end

#clean_build_directoryObject

Empty out the build directory



67
68
69
# File 'lib/forge/builder.rb', line 67

def clean_build_directory
  FileUtils.rm_rf Dir.glob(File.join(@project.build_path, '*'))
end

#clean_functionsObject



95
96
97
98
# File 'lib/forge/builder.rb', line 95

def clean_functions
  FileUtils.rm File.join(@project.build_path, 'functions.php')
  FileUtils.rm_rf File.join(@project.build_path, 'functions')
end

#clean_imagesObject



141
142
143
# File 'lib/forge/builder.rb', line 141

def clean_images
  FileUtils.rm_rf File.join(@project.build_path, 'images')
end

#clean_includesObject



126
127
128
# File 'lib/forge/builder.rb', line 126

def clean_includes
  FileUtils.rm_rf File.join(@project.build_path, 'includes')
end

#clean_templatesObject



71
72
73
74
75
76
# File 'lib/forge/builder.rb', line 71

def clean_templates
  # TODO: cleaner way of removing templates only?
  Dir.glob(File.join(@project.build_path, '*.php')).each do |path|
    FileUtils.rm path unless path.include?('functions.php')
  end
end

#copy_functionsObject



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
# File 'lib/forge/builder.rb', line 100

def copy_functions
  functions_erb_path = File.join(@functions_path, 'functions.php.erb')
  functions_php_path = File.join(@functions_path, 'functions.php')

  if File.exists?(functions_erb_path)
    destination = File.join(@project.build_path, 'functions.php')
    write_erb(functions_erb_path, destination)
  elsif File.exists?(functions_php_path)
    FileUtils.cp functions_php_path, @project.build_path
  end

  functions_paths = Dir.glob(File.join(@functions_path, '*')).reject do |filename|
    [functions_erb_path, functions_php_path].include?(filename)
  end

  unless functions_paths.empty?
    # Create the includes folder in the build directory
    FileUtils.mkdir_p(File.join(@project.build_path, 'functions'))

    # Iterate over all files in source/functions, skipping the actual functions.php file
    paths = Dir.glob(File.join(@functions_path, '**', '*')).reject {|filename| [functions_erb_path, functions_php_path].include?(filename) }

    copy_paths_with_erb(paths, @functions_path, File.join(@project.build_path, 'functions'))
  end
end

#copy_includesObject



130
131
132
133
134
135
136
137
138
139
# File 'lib/forge/builder.rb', line 130

def copy_includes
  unless Dir.glob(File.join(@includes_path, '*')).empty?
    # Create the includes folder in the build directory
    FileUtils.mkdir(File.join(@project.build_path, 'includes'))

    # Iterate over all files in source/includes, so we can exclude if necessary
    paths = Dir.glob(File.join(@includes_path, '**', '*'))
    copy_paths_with_erb(paths, @includes_path, File.join(@project.build_path, 'includes'))
  end
end

#copy_templatesObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/forge/builder.rb', line 78

def copy_templates
  template_paths.each do |template_path|
    # Skip directories
    next if File.directory?(template_path)

    if template_path.end_with?('.erb')
      # Chop the .erb extension off the filename
      destination = File.join(@project.build_path, File.basename(template_path).slice(0..-5))

      write_erb(template_path, destination)
    else
      # Regular old copy of PHP-only files
      FileUtils.cp template_path, @project.build_path
    end
  end
end

#zip(filename = nil) ⇒ Object

Use the rubyzip library to build a zip from the generated source



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/forge/builder.rb', line 32

def zip(filename=nil)
  filename = filename || File.basename(@project.root)
  project_base = File.basename(@project.root)

  zip_filename = File.join(File.basename(@package_path), "#{filename}.zip")
  # Create a temporary file for RubyZip to write to
  temp_filename = "#{zip_filename}.tmp"

  File.delete(temp_filename) if File.exists?(temp_filename)

  # Wrapping the zip creation in Thor's create_file to get "overwrite" prompts
  # Note: I could be overcomplicating this
  @task.create_file(zip_filename) do
    Zip::ZipFile.open(temp_filename, Zip::ZipFile::CREATE) do |zip|
      # Get all filenames in the build directory recursively
      filenames = Dir[File.join(@project.build_path, '**', '*')]

      # Remove the build directory path from the filename
      filenames.collect! {|path| path.gsub(/#{@project.build_path}\//, '')}

      # Add each file in the build directory to the zip file
      filenames.each do |filename|
        zip.add File.join(project_base, filename), File.join(@project.build_path, filename)
      end
    end

    # Give Thor contents of zip file for "overwrite" prompt
    File.open(temp_filename, 'rb') { |f| f.read }
  end

  # Clean up the temp file
  File.delete(temp_filename)
end