sitefuel 0.0.0a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/README +86 -0
  2. data/RELEASE_NOTES +7 -0
  3. data/bin/sitefuel +162 -0
  4. data/lib/sitefuel/Configuration.rb +35 -0
  5. data/lib/sitefuel/SiteFuelLogger.rb +128 -0
  6. data/lib/sitefuel/SiteFuelRuntime.rb +293 -0
  7. data/lib/sitefuel/extensions/ArrayComparisons.rb +34 -0
  8. data/lib/sitefuel/extensions/DynamicClassMethods.rb +19 -0
  9. data/lib/sitefuel/extensions/FileComparison.rb +24 -0
  10. data/lib/sitefuel/extensions/Silently.rb +27 -0
  11. data/lib/sitefuel/extensions/StringFormatting.rb +75 -0
  12. data/lib/sitefuel/extensions/SymbolComparison.rb +13 -0
  13. data/lib/sitefuel/external/AbstractExternalProgram.rb +616 -0
  14. data/lib/sitefuel/external/ExternalProgramTestCase.rb +67 -0
  15. data/lib/sitefuel/external/GIT.rb +9 -0
  16. data/lib/sitefuel/external/JPEGTran.rb +68 -0
  17. data/lib/sitefuel/external/PNGCrush.rb +66 -0
  18. data/lib/sitefuel/processors/AbstractExternalProgramProcessor.rb +72 -0
  19. data/lib/sitefuel/processors/AbstractProcessor.rb +378 -0
  20. data/lib/sitefuel/processors/AbstractStringBasedProcessor.rb +88 -0
  21. data/lib/sitefuel/processors/CSSProcessor.rb +84 -0
  22. data/lib/sitefuel/processors/HAMLProcessor.rb +52 -0
  23. data/lib/sitefuel/processors/HTMLProcessor.rb +211 -0
  24. data/lib/sitefuel/processors/JavaScriptProcessor.rb +57 -0
  25. data/lib/sitefuel/processors/PHPProcessor.rb +32 -0
  26. data/lib/sitefuel/processors/PNGProcessor.rb +80 -0
  27. data/lib/sitefuel/processors/RHTMLProcessor.rb +25 -0
  28. data/lib/sitefuel/processors/SASSProcessor.rb +50 -0
  29. data/test/processor_listing.rb +28 -0
  30. data/test/test_AbstractExternalProgram.rb +186 -0
  31. data/test/test_AbstractProcessor.rb +237 -0
  32. data/test/test_AbstractStringBasedProcessor.rb +48 -0
  33. data/test/test_AllProcessors.rb +65 -0
  34. data/test/test_ArrayComparisons.rb +32 -0
  35. data/test/test_CSSProcessor.rb +120 -0
  36. data/test/test_FileComparisons.rb +42 -0
  37. data/test/test_HAMLProcessor.rb.rb +60 -0
  38. data/test/test_HTMLProcessor.rb +186 -0
  39. data/test/test_JPEGTran.rb +40 -0
  40. data/test/test_JavaScriptProcessor.rb +63 -0
  41. data/test/test_PHPProcessor.rb +51 -0
  42. data/test/test_PNGCrush.rb +58 -0
  43. data/test/test_PNGProcessor.rb +32 -0
  44. data/test/test_RHTMLProcessor.rb +62 -0
  45. data/test/test_SASSProcessor.rb +68 -0
  46. data/test/test_SiteFuelLogging.rb +79 -0
  47. data/test/test_SiteFuelRuntime.rb +96 -0
  48. data/test/test_StringFormatting.rb +51 -0
  49. data/test/test_SymbolComparison.rb +27 -0
  50. data/test/test_images/sample_jpg01.jpg +0 -0
  51. data/test/test_images/sample_png01.png +0 -0
  52. data/test/test_programs/versioning.rb +26 -0
  53. data/test/test_sites/simplehtml/deployment.yml +22 -0
  54. data/test/test_sites/simplehtml/index.html +66 -0
  55. data/test/test_sites/simplehtml/style.css +40 -0
  56. data/test/ts_all.rb +39 -0
  57. metadata +165 -0
data/README ADDED
@@ -0,0 +1,86 @@
1
+ ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2
+
3
+
4
+ SiteFuel
5
+ http://sitefuel.org
6
+ v0.1.0 (initial release)
7
+
8
+
9
+ ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
10
+
11
+ A program and API for minifying websites and web applications and
12
+ deploying them from version control.
13
+
14
+ * Get started: http://sitefuel.org/getstarted
15
+ * Lists: http://sitefuel.org/mailinglists
16
+ * Report a bug: http://sitefuel.org/bug
17
+
18
+ * Contribute! http://sitefuel.org/contribute
19
+
20
+
21
+ == Table of Contents
22
+
23
+ 1. Introduction
24
+ . System Requirements
25
+ . Supported Formats
26
+ . Installation
27
+ . Getting Started
28
+ . Reporting a Bug
29
+ . A Note about the API
30
+ . Further Reading
31
+
32
+
33
+ == Introduction
34
+ SiteFuel is a Ruby program
35
+
36
+ Use SiteFuel to:
37
+ * deploy your website out of SVN or GIT
38
+ * minify your
39
+
40
+
41
+ == System Requirements
42
+
43
+ * Ruby 1.8.6 or greater.
44
+ * pngcrush (for PNG compression)
45
+ * jpegtran (for JPEG compression)
46
+ * git (for deploying sites from Git repositories)
47
+ * svn (for deploying sites from SVN repositories)
48
+
49
+ SiteFuel hasn't been tested on Windows machines.
50
+
51
+
52
+ == Installation
53
+
54
+ SiteFuel is deployed as a RubyGem through http://gemcutter.org. You
55
+ should be able to install it directly using RubyGems:
56
+
57
+ $ gem install -t sitefuel
58
+
59
+ You can also download a ZIP-file containing SiteFuel and all of the gems
60
+ it depends on from http://sitefuel.org/download/sitefuel-complete.zip
61
+
62
+ Note that for PNG and JPEG compression to be enabled you must install
63
+ the 'pngcrush' and 'jpegtran' programs.
64
+
65
+
66
+
67
+ == Getting Started
68
+
69
+ SiteFuel
70
+
71
+
72
+
73
+
74
+ == Reporting a Bug
75
+
76
+
77
+ == A Note About the API
78
+
79
+ The general API in SiteFuel should be considered unstable while SiteFuel
80
+ is <1.0. For practical reasons we can't increment the major version
81
+ number each time there is a non-backwards compatible API change....
82
+
83
+
84
+ == Further Reading
85
+ * http://sitefuel.org - main sitefuel website
86
+ * http://sitefuel.org/help - pointers to various resources
data/RELEASE_NOTES ADDED
@@ -0,0 +1,7 @@
1
+ == 0.1.0
2
+ * initial public release of the SiteFuel alpha
3
+ * support for trivial minification of HTML, RHTML, and PHP.
4
+ * uses CSSMin and JSMin to minify CSS and JavaScript; both in individual
5
+ files and embedded in HTML.
6
+ * uses pngcrush and jpegtran to minify PNG and JPEG images.
7
+ * support for the Git and SVN version control systems.
data/bin/sitefuel ADDED
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/ruby -wrubygems
2
+
3
+ # == Synopsis
4
+ #
5
+ # A lightweight ruby framework for processing and deploying websites, either
6
+ # from
7
+ #
8
+ # == Usage
9
+ #
10
+ # sitefuel deploy|process SOURCE [OPTIONS]
11
+ #
12
+ # == Introduction
13
+ # sitefuel is a lightweight ruby framework for deploying websites directly from
14
+ # version control. sitefuel includes support for compressing HTML and CSS as
15
+ # well as optimizing PNG graphics. Support is planned for SASS; compressing
16
+ # JavaScript; automatically creating sprites; and supporting more image formats.
17
+ # (and more!)
18
+ #
19
+ # TODO: add more details
20
+ #
21
+ # * More information: http://sitefuel.org
22
+ # * Getting started: http://sitefuel.org/getstarted
23
+ # * Documentation: http://sitefuel.org/documentation
24
+ #
25
+ # == Commands
26
+ #
27
+ # deploy:: Deploy a site using sitefuel.
28
+ # process:: Modify an existing website inplace.
29
+ # stage:: Simulates a deployment without actually changing anything.
30
+ # help:: Show this message.
31
+ #
32
+ # == Examples
33
+ # Process an already deployed site:
34
+ # sitefuel process /var/www/
35
+ #
36
+ # Deploy a site from SVN:
37
+ # sitefuel deploy svn+ssh://sitefuel.org/svn/tags/21 /var/www/
38
+ #
39
+ # Specify a non-default deployment file:
40
+ # sitefuel process /var/www/ -c customdeployment.yml
41
+ #
42
+ #
43
+ # == Author
44
+ # Zanoccio, LLC.
45
+ #
46
+ # == Copyright
47
+ # Copyright (c) 2009 Zanoccio.
48
+ #
49
+ # == License
50
+ # This program is free software; you can redistribute it and/or
51
+ # modify it under the terms of the GNU General Public License
52
+ # as published by the Free Software Foundation; either version 2
53
+ # of the License, or (at your option) any later version.
54
+ #
55
+ # This program is distributed in the hope that it will be useful,
56
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
57
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58
+ # GNU General Public License for more details.
59
+ #
60
+ # You should have received a copy of the GNU General Public License
61
+ # along with this program; if not, write to the Free Software
62
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
63
+ #
64
+
65
+ # add source/ to the load path
66
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
67
+
68
+ begin
69
+ require 'rubygems'
70
+ rescue LoadError
71
+ # attempt to continue running the program
72
+ end
73
+
74
+
75
+ require 'rdoc/usage'
76
+ require 'term/ansicolor'
77
+
78
+ require 'sitefuel/SiteFuelRuntime'
79
+
80
+ include Term::ANSIColor
81
+
82
+ def puts_and_exit(*args)
83
+ puts(*args)
84
+ exit
85
+ end
86
+
87
+ $HELP_HINT_LINE = "type \'#{$0} help\' for usage"
88
+
89
+ # parse command line arguments and configure a SiteFuelRuntime
90
+ def parse_command_line(runtime)
91
+
92
+ #### BUILD THE OPTIONS PARSER
93
+ opts = OptionParser.new
94
+
95
+ # the banner text comes from the header comment for this file
96
+
97
+ opts.on('-oARG', '-o=ARG', '-o PLACE', '--output=ARG', '--output PLACE', String,
98
+ 'Where to put a deployed site') do |out|
99
+ runtime.deploy_to = out
100
+ end
101
+ opts.on('-v', '--version', 'Gives the version of sitefuel') do
102
+ puts 'SiteFuel ' + VERSION_TEXT
103
+ end
104
+
105
+ opts.on('--[no-]verbose', 'List actions as they are preformed') do
106
+ puts 'cause SiteFuel to be verbose listing actions as they are preformed'
107
+ end
108
+
109
+ opts.on('--only-list-recognized-files', 'Only list summaries for files which were changed') do
110
+ runtime.only_list_recognized_files = true
111
+ end
112
+
113
+ opts.on('-h', '--help', '-?', '--about', 'Gives help for a specific command.') do
114
+ RDoc::usage_no_exit('Synopsis', 'Usage', 'Introduction')
115
+ puts opts
116
+ RDoc::usage_no_exit('Examples', 'Author', 'Copyright', 'License')
117
+ exit
118
+ end
119
+
120
+ opts.separator ''
121
+ opts.separator 'Specific options for a command can be seen with: '
122
+ opts.separator ' COMMAND --help'
123
+
124
+
125
+ #### ATTEMPT TO PARSE THE COMMAND LINE
126
+ begin
127
+ commands = opts.parse(*ARGV)
128
+ rescue OptionParser::InvalidOption => iopt
129
+ puts iopt
130
+ puts_and_exit $HELP_HINT_LINE
131
+ rescue => exception
132
+ # TODO: add better handling for the various exceptions (unnecessary
133
+ # argument, missing argument, etc.)
134
+ puts_and_exit "couldn't parse command line: #{exception}", $HELP_HINT_LINE
135
+ end
136
+
137
+
138
+ # note that --help will have already been intercepted but 'help' still needs
139
+ # special treatment
140
+ puts_and_exit 'no command given', $HELP_HINT_LINE if commands.length < 1
141
+ puts_and_exit opts if commands[0].downcase == 'help'
142
+
143
+ case commands[0].downcase
144
+ when 'deploy'
145
+ runtime.deploy_from = commands[1]
146
+ runtime.deploy
147
+
148
+ when 'stage'
149
+ runtime.deploy_from = commands[1]
150
+ runtime.stage
151
+
152
+ else
153
+ puts_and_exit "unknown command: '#{commands[0]}'", $HELP_HINT_LINE
154
+ end
155
+ end
156
+
157
+ def main
158
+ runtime = SiteFuel::SiteFuelRuntime.new
159
+ parse_command_line(runtime)
160
+ end
161
+
162
+ main()
@@ -0,0 +1,35 @@
1
+ #
2
+ # File:: configuration.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+ # Load and process SiteFuel YAML configuration files
8
+ #
9
+
10
+ module SiteFuel
11
+ require 'yaml'
12
+
13
+ class Configuration
14
+
15
+ # exception which represents that a configuration could not be found
16
+ class NotFound < StandardError
17
+ end
18
+
19
+ # given a directory path will attempt to location a configuration file
20
+ # and load it, returning a SiteFuel::Configuration class
21
+ def self.load(path)
22
+ unless File.exist?(path)
23
+ throw NotFound, path
24
+ end
25
+
26
+ yamlconfig = YAML::load_file(configfile)
27
+
28
+ Configuration.new(yamlconfig)
29
+ end
30
+
31
+ # builds a sitefuel configuration from a parsed YAML file
32
+ def initialize(yamlconfig)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,128 @@
1
+ #
2
+ # File:: SiteFuelLogger.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+
8
+ module SiteFuel
9
+
10
+ require 'logger'
11
+ require 'singleton'
12
+ require 'term/ansicolor'
13
+
14
+ include Term::ANSIColor
15
+
16
+ # Singleton abstraction around the Logger:: library, typically every processor
17
+ # will hook into using this logger while letting us control it's placement
18
+ # and display globally
19
+ class SiteFuelLogger < Logger
20
+ include Singleton
21
+
22
+ # the number of fatal messages logged so far (even if lower than #level)
23
+ attr_reader :fatal_count
24
+
25
+ # the number of error messages logged so far (even if lower than #level)
26
+ attr_reader :error_count
27
+
28
+ # the number of warning messages logged so far (even if lower than #level)
29
+ attr_reader :warn_count
30
+
31
+ # the number of info messages logged so far (even if lower than #level)
32
+ attr_reader :info_count
33
+
34
+ # the number of debug messages logged so far (even if lower than #level)
35
+ attr_reader :debug_count
36
+
37
+ # adjust the style of logging:
38
+ #
39
+ # default:: use the Logger logging style
40
+ # clean:: gives a clean logging output intended for human use
41
+ attr_accessor :log_style
42
+
43
+ def initialize(filename = STDOUT)
44
+ super(filename)
45
+
46
+ @fatal_count = 0
47
+ @error_count = 0
48
+ @warn_count = 0
49
+ @info_count = 0
50
+ @debug_count = 0
51
+
52
+ self.level = WARN
53
+ @log_style = :default
54
+ @progname = 'SiteFuel'
55
+ end
56
+
57
+ def fatal(*args)
58
+ @fatal_count += 1
59
+ super(*args)
60
+ end
61
+
62
+ def error(*args)
63
+ @error_count += 1
64
+ super(*args)
65
+ end
66
+
67
+ def warn(*args)
68
+ @warn_count += 1
69
+ super(*args)
70
+ end
71
+
72
+ def info(*args)
73
+ @info_count += 1
74
+ super(*args)
75
+ end
76
+
77
+ def debug(*args)
78
+ @debug_count += 1
79
+ super(*args)
80
+ end
81
+
82
+ # implement our own #add so we can have cleaner logs
83
+ def format_message(severity, date_time, program_name, msg)
84
+ case @log_style
85
+ when :default
86
+ super(severity, date_time, program_name, msg)
87
+
88
+ when :clean
89
+ string = "#{severity}: #{msg}\n"
90
+ case severity
91
+ when 'ERROR', 'FATAL'
92
+ string = bold(red(string))
93
+
94
+ when 'WARN'
95
+ string = yellow(string)
96
+
97
+ when 'DEBUG'
98
+ string = string
99
+ end
100
+ string
101
+ end
102
+ end
103
+ end
104
+
105
+ # mixin for adding logging functionality to any class, typically included
106
+ # by every SiteFuel class
107
+ module Logging
108
+ # sets the logger for a class
109
+ def logger=(logger)
110
+ @logger = logger
111
+ end
112
+
113
+ # adds a fatal error to the log
114
+ def fatal(*args) @logger.fatal(*args); end
115
+
116
+ # adds an error to the log
117
+ def error(*args) @logger.error(*args); end
118
+
119
+ # adds a warning to the log
120
+ def warn(*args) @logger.warn(*args); end
121
+
122
+ # adds an info message to the log
123
+ def info(*args) @logger.info(*args); end
124
+
125
+ # adds a debugging message to the log
126
+ def debug(*args) @logger.debug(*args); end
127
+ end
128
+ end
@@ -0,0 +1,293 @@
1
+ #
2
+ # File:: SiteFuelRuntime.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+ # Defines the primary interface class used by sitefuel to do actual work.
8
+ # Keeping this as a class let's us abstract away the command line interface
9
+ # while automatically having a direct API for programatically accessing
10
+ # sitefuel.
11
+ #
12
+
13
+
14
+ module SiteFuel
15
+
16
+ require 'optparse'
17
+ require 'term/ansicolor'
18
+
19
+ include Term::ANSIColor
20
+
21
+ require 'sitefuel/SiteFuelLogger'
22
+
23
+ require 'sitefuel/extensions/StringFormatting'
24
+ require 'sitefuel/extensions/FileComparison'
25
+
26
+ # we need the AbstractProcessor symbol when we go child-class hunting
27
+ require 'sitefuel/processors/AbstractProcessor'
28
+
29
+ # version of SiteFuel
30
+ VERSION = [0, 0, 1].freeze
31
+
32
+ # a human readable version
33
+ VERSION_TEXT = VERSION.join('.').freeze
34
+
35
+
36
+ class SiteFuelRuntime
37
+
38
+ include SiteFuel::Logging
39
+
40
+ # what action is the runtime supposed to preform
41
+ attr_accessor :action
42
+
43
+ # what is the source *from* which we are deploying
44
+ attr_accessor :deploy_from
45
+
46
+ # what is the source *to* which we are deploying
47
+ attr_accessor :deploy_to
48
+
49
+ # configuration loaded from a deployment.yml file
50
+ attr_accessor :deploymentconfiguration
51
+
52
+ # only lists file which have a known processor
53
+ attr_accessor :only_list_recognized_files
54
+
55
+ def initialize
56
+ @processors = SiteFuelRuntime.find_processors
57
+ self.logger = SiteFuelLogger.instance
58
+ SiteFuelLogger.instance.log_style = :clean
59
+
60
+ @only_list_recognized_files = false
61
+ end
62
+
63
+ # gives true if the given file (typically a processor) has already been
64
+ # loaded (by looking into $"). Unfortunately #require is easily tricked,
65
+ # so this function uses some heuristics to prevent processors from being
66
+ # loaded twice (by basically comparing the "core" part of the filename)
67
+ def self.processor_loaded?(file)
68
+ $".map do |f|
69
+ if File.equivalent?(file, f)
70
+ return true
71
+ end
72
+ end
73
+
74
+ return false
75
+ end
76
+
77
+ # finds all processors under processors/ and loads them. Any file matching
78
+ # *Processor.rb will be loaded
79
+ def self.load_processors
80
+ dir = File.dirname(__FILE__).split(File::SEPARATOR)
81
+ dir = File.join(*dir[0..-2]) + File::SEPARATOR
82
+
83
+ # build up the search pattern by taking this file's directory and shoving
84
+ # it onto the search pattern
85
+ patt = File.join(dir, 'sitefuel/processors/*Processor.rb')
86
+
87
+ # find all file matching that pattern
88
+ files = Dir[patt]
89
+
90
+ # rip off the path prefix eg. 'sitefuel/lib/b/foo.rb' becomes 'b/foo.rb'
91
+ files = files.map do |filename|
92
+ filename.gsub(Regexp.new("^"+Regexp.escape(dir)), '')
93
+ end
94
+
95
+ # get rid of anything we've already loaded
96
+ files = files.delete_if { |file| processor_loaded?(file) }
97
+
98
+ # load whatever files we're left with
99
+ files.each { |f| require f }
100
+ end
101
+
102
+
103
+ # returns a list of processors found by looking for all children of
104
+ # SiteFuel::Processor::AbstractProcessor
105
+ #
106
+ # for a processor to be automatically included it has to:
107
+ # * be loaded (see #load_processors)
108
+ # * be a child class of AbstractProcessor
109
+ # * the class name must end with Processor
110
+ #
111
+ def self.find_processors
112
+ Processor::AbstractProcessor.find_processors
113
+ end
114
+
115
+ # lists the actions which are possible with this runtime.
116
+ def actions
117
+ [ :deploy, :stage ]
118
+ end
119
+
120
+ # gives the array of processors available to this runtime
121
+ attr_reader :processors
122
+
123
+ # adds a processor or an array of processors to the runtime
124
+ def add_processor(proc)
125
+ case proc
126
+ when Array
127
+ proc.each { |p|
128
+ @processors << p
129
+ }
130
+ else
131
+ @processors << proc
132
+ end
133
+ end
134
+
135
+ # gives the processor to use for a given file
136
+ def choose_processor(filename)
137
+ matchingprocs = processors.clone.delete_if {|proc| not proc.processes_file?(filename) }
138
+
139
+ case
140
+ when matchingprocs.length > 1
141
+ chosen = matchingprocs.first
142
+ raise Processor::MultipleApplicableProcessors.new(filename, matchingprocs, chosen)
143
+ when matchingprocs.length == 1
144
+ return matchingprocs.first
145
+ else
146
+ return nil
147
+ end
148
+ end
149
+
150
+ # like #choose_processor but prints a message if there are clashing
151
+ # processors and returns the first of the clashing processors.
152
+ # (effectively alerting the user, but continuing to work)
153
+ def choose_processor!(filename)
154
+ begin
155
+ choose_processor(filename)
156
+ rescue Processor::MultipleApplicableProcessors => exception
157
+ # log the exception
158
+ warn exception
159
+ exception.chosen_processor
160
+ end
161
+ end
162
+
163
+
164
+ # implements the stage command. Staging, by itself, will give statistics on
165
+ # the deployment; how many bytes were saved by minification; etc.
166
+ #
167
+ # However, #stage when part of #deploy will go and create the requisite files
168
+ # in a temporary directory
169
+ def stage
170
+ return nil if @deploy_from == nil
171
+
172
+ puts '== %s '.format('Staging').ljust(80, '=')
173
+
174
+ # find all files under deploy_from
175
+ files = find_all_files @deploy_from
176
+
177
+ total_original_size = 0
178
+ total_processed_size = 0
179
+ @resource_processors = {}
180
+ @processor_statistics = Hash.new([0, 0, 0])
181
+ files.each do |filename|
182
+ processor = choose_processor!(filename)
183
+ if processor == nil
184
+ @resource_processors[filename] = nil
185
+ else
186
+ @resource_processors[filename] = processor.process_file(filename)
187
+ end
188
+
189
+ processor = @resource_processors[filename]
190
+ if processor == nil
191
+ if only_list_recognized_files == false
192
+ puts '%s %s' %['--'.ljust(8), filename.cabbrev(65)]
193
+ end
194
+ else
195
+ total_original_size += processor.original_size
196
+ total_processed_size += processor.processed_size
197
+
198
+ stats = @processor_statistics[processor.class.processor_name].clone
199
+ stats[0] += 1
200
+ stats[1] += processor.original_size
201
+ stats[2] += processor.processed_size
202
+ @processor_statistics[processor.class.processor_name] = stats
203
+
204
+ puts '%s %s %4.3f' %
205
+ [
206
+ cyan(processor.class.processor_name.ljust(8)),
207
+ filename.cabbrev(65).ljust(65),
208
+ processor.processed_size.prec_f/processor.original_size.prec_f
209
+ ]
210
+ end
211
+ end
212
+
213
+ puts '='*80
214
+ puts 'Size delta: %+5d bytes; %4.3f' %
215
+ [
216
+ total_processed_size - total_original_size,
217
+ total_processed_size.prec_f/total_original_size.prec_f
218
+ ]
219
+
220
+ staging_statistics
221
+ end
222
+
223
+ # outputs a little grid showing the number of files of each processor
224
+ # and the total savings
225
+ #
226
+ # todo: this should be computed in the staging step
227
+ def staging_statistics
228
+ puts ''
229
+ puts ' %s | %s | %s | %s' %
230
+ ['processor', '# files', 'delta', 'ratio'].map{|v| bold(v)}
231
+ puts ' -----------+----------+-------------+-------'
232
+
233
+ @processor_statistics.keys.sort.each do |key|
234
+ puts ' %s|%9d |%+12d | %4.3f' %
235
+ [
236
+ key.ljust(10),
237
+ @processor_statistics[key][0],
238
+ @processor_statistics[key][2] - @processor_statistics[key][1],
239
+ @processor_statistics[key][2].prec_f / @processor_statistics[key][1].prec_f
240
+ ]
241
+ end
242
+ puts ' -----------+----------+-------------+-------'
243
+ puts ''
244
+ end
245
+
246
+ # create a deployment
247
+ def deploy
248
+ # first we have to stage the files
249
+ stage
250
+
251
+ files = find_all_files @deploy_from
252
+
253
+ return if @deploy_to == nil
254
+ puts
255
+ puts bold('Deploying:')
256
+
257
+ unless File.exists?(@deploy_to)
258
+ Dir.mkdir(@deploy_to)
259
+ end
260
+ # write out content
261
+ files.each do |filename|
262
+ results = @resource_processors[filename]
263
+ if results == nil
264
+ putc 'I'
265
+ else
266
+ putc '.'
267
+ results.save(@deploy_to)
268
+ end
269
+ STDOUT.flush
270
+ end
271
+ puts
272
+ end
273
+
274
+ # gives an array listing of all files on a given path
275
+ #
276
+ # This is a very lightweight wrapper around Dir.
277
+ def find_all_files(path)
278
+ Dir[File.join(path, "**/*")]
279
+ end
280
+
281
+ # changes the verbosity of the runtime by adjusting the log level
282
+ def verbosity(level = 1)
283
+ case level
284
+ when 1
285
+
286
+ end
287
+ end
288
+ end
289
+
290
+
291
+ # load the various processors
292
+ SiteFuelRuntime.load_processors
293
+ end