cjohansen-juicer 0.2.0 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +17 -5
- data/Manifest.txt +33 -15
- data/Rakefile +22 -1
- data/Readme.rdoc +68 -32
- data/bin/juicer +1 -0
- data/lib/juicer.rb +26 -1
- data/lib/juicer/binary.rb +173 -0
- data/lib/juicer/cache_buster.rb +45 -0
- data/lib/juicer/chainable.rb +1 -0
- data/lib/juicer/cli.rb +13 -8
- data/lib/juicer/command/install.rb +59 -0
- data/lib/juicer/command/list.rb +50 -0
- data/lib/juicer/command/merge.rb +130 -31
- data/lib/juicer/command/util.rb +32 -0
- data/lib/juicer/command/verify.rb +60 -0
- data/lib/juicer/core.rb +61 -0
- data/lib/juicer/css_cache_buster.rb +106 -0
- data/lib/juicer/install/base.rb +186 -0
- data/lib/juicer/install/jslint_installer.rb +51 -0
- data/lib/juicer/install/rhino_installer.rb +52 -0
- data/lib/juicer/install/yui_compressor_installer.rb +66 -0
- data/lib/juicer/jslint.rb +90 -0
- data/lib/juicer/merger/base.rb +74 -72
- data/lib/juicer/merger/dependency_resolver.rb +34 -16
- data/lib/juicer/merger/stylesheet_merger.rb +71 -1
- data/lib/juicer/minifyer/yui_compressor.rb +20 -43
- data/tasks/test/setup.rake +35 -0
- data/test/juicer/command/test_install.rb +53 -0
- data/test/juicer/command/test_list.rb +69 -0
- data/test/juicer/command/test_merge.rb +160 -0
- data/test/juicer/command/test_util.rb +54 -0
- data/test/juicer/command/test_verify.rb +33 -0
- data/test/juicer/install/test_installer_base.rb +195 -0
- data/test/juicer/install/test_jslint_installer.rb +54 -0
- data/test/juicer/install/test_rhino_installer.rb +57 -0
- data/test/juicer/install/test_yui_compressor_installer.rb +56 -0
- data/test/juicer/merger/test_base.rb +2 -3
- data/test/juicer/merger/test_css_dependency_resolver.rb +8 -4
- data/test/juicer/merger/test_javascript_dependency_resolver.rb +6 -7
- data/test/juicer/merger/test_javascript_merger.rb +1 -2
- data/test/juicer/merger/test_stylesheet_merger.rb +118 -2
- data/test/juicer/minifyer/test_yui_compressor.rb +109 -29
- data/test/juicer/test_cache_buster.rb +58 -0
- data/test/juicer/test_chainable.rb +7 -0
- data/test/juicer/test_core.rb +47 -0
- data/test/juicer/test_css_cache_buster.rb +91 -0
- data/test/juicer/test_jslint.rb +33 -0
- data/test/test_helper.rb +65 -196
- metadata +77 -26
- data/.gitignore +0 -2
- data/juicer.gemspec +0 -38
- data/lib/juicer/minifyer/compressor.rb +0 -125
- data/test/juicer/minifyer/test_compressor.rb +0 -36
data/History.txt
CHANGED
@@ -1,9 +1,21 @@
|
|
1
|
-
== 0.2.
|
1
|
+
== 0.2.4 / 2009-04-29
|
2
2
|
|
3
|
-
*
|
4
|
-
*
|
5
|
-
*
|
6
|
-
*
|
3
|
+
* More robust pattern checking for url() references in CSS files
|
4
|
+
* Allow skipping verification
|
5
|
+
* Bug fix: Skip cache buster if type=none
|
6
|
+
* Bug fix: Quote JsLint command parts to allow for spaces in jar file paths
|
7
|
+
* Bug fix: cache buster type wasn't carried all the way (ie had no effect)
|
8
|
+
|
9
|
+
== 0.2.3 / 2009-03-03
|
10
|
+
|
11
|
+
* Cache busters in CSS files should only be appended once to each URL
|
12
|
+
* Output to merge target should accept directories as well as files (in case of
|
13
|
+
directories, file name is generated)
|
14
|
+
* Tests should not ship with 3rd party libraries
|
15
|
+
|
16
|
+
== 0.2.0 / 2009-02-25
|
17
|
+
|
18
|
+
* First usable release; merge, verify, install targets
|
7
19
|
|
8
20
|
== 0.1.0 / 2008-12-17
|
9
21
|
|
data/Manifest.txt
CHANGED
@@ -1,40 +1,58 @@
|
|
1
|
-
.gitignore
|
2
1
|
History.txt
|
3
2
|
Manifest.txt
|
4
3
|
Rakefile
|
5
4
|
Readme.rdoc
|
6
5
|
bin/juicer
|
7
|
-
juicer.gemspec
|
8
6
|
lib/juicer.rb
|
7
|
+
lib/juicer/binary.rb
|
8
|
+
lib/juicer/cache_buster.rb
|
9
9
|
lib/juicer/chainable.rb
|
10
10
|
lib/juicer/cli.rb
|
11
|
+
lib/juicer/command/install.rb
|
12
|
+
lib/juicer/command/list.rb
|
11
13
|
lib/juicer/command/merge.rb
|
14
|
+
lib/juicer/command/util.rb
|
15
|
+
lib/juicer/command/verify.rb
|
16
|
+
lib/juicer/core.rb
|
17
|
+
lib/juicer/css_cache_buster.rb
|
18
|
+
lib/juicer/install/base.rb
|
19
|
+
lib/juicer/install/jslint_installer.rb
|
20
|
+
lib/juicer/install/rhino_installer.rb
|
21
|
+
lib/juicer/install/yui_compressor_installer.rb
|
22
|
+
lib/juicer/jslint.rb
|
12
23
|
lib/juicer/merger/base.rb
|
13
24
|
lib/juicer/merger/css_dependency_resolver.rb
|
14
25
|
lib/juicer/merger/dependency_resolver.rb
|
15
26
|
lib/juicer/merger/javascript_dependency_resolver.rb
|
16
27
|
lib/juicer/merger/javascript_merger.rb
|
17
28
|
lib/juicer/merger/stylesheet_merger.rb
|
18
|
-
lib/juicer/minifyer/compressor.rb
|
19
29
|
lib/juicer/minifyer/yui_compressor.rb
|
20
|
-
test/
|
21
|
-
test/
|
22
|
-
test/
|
23
|
-
test/
|
24
|
-
test/
|
25
|
-
test/
|
26
|
-
test/
|
27
|
-
test/
|
28
|
-
test/
|
29
|
-
test/
|
30
|
-
test/
|
30
|
+
tasks/test/setup.rake
|
31
|
+
test/bin/jslint.js
|
32
|
+
test/bin/rhino1_7R1.zip
|
33
|
+
test/bin/rhino1_7R2-RC1.zip
|
34
|
+
test/bin/yuicompressor
|
35
|
+
test/bin/yuicompressor-2.3.5.zip
|
36
|
+
test/bin/yuicompressor-2.4.2.zip
|
37
|
+
test/juicer/command/test_install.rb
|
38
|
+
test/juicer/command/test_list.rb
|
39
|
+
test/juicer/command/test_merge.rb
|
40
|
+
test/juicer/command/test_util.rb
|
41
|
+
test/juicer/command/test_verify.rb
|
42
|
+
test/juicer/install/test_installer_base.rb
|
43
|
+
test/juicer/install/test_jslint_installer.rb
|
44
|
+
test/juicer/install/test_rhino_installer.rb
|
45
|
+
test/juicer/install/test_yui_compressor_installer.rb
|
31
46
|
test/juicer/merger/test_base.rb
|
32
47
|
test/juicer/merger/test_css_dependency_resolver.rb
|
33
48
|
test/juicer/merger/test_javascript_dependency_resolver.rb
|
34
49
|
test/juicer/merger/test_javascript_merger.rb
|
35
50
|
test/juicer/merger/test_stylesheet_merger.rb
|
36
|
-
test/juicer/minifyer/test_compressor.rb
|
37
51
|
test/juicer/minifyer/test_yui_compressor.rb
|
52
|
+
test/juicer/test_cache_buster.rb
|
38
53
|
test/juicer/test_chainable.rb
|
54
|
+
test/juicer/test_core.rb
|
55
|
+
test/juicer/test_css_cache_buster.rb
|
56
|
+
test/juicer/test_jslint.rb
|
39
57
|
test/test_helper.rb
|
40
58
|
test/test_juicer.rb
|
data/Rakefile
CHANGED
@@ -6,11 +6,16 @@ begin
|
|
6
6
|
require 'bones'
|
7
7
|
Bones.setup
|
8
8
|
rescue LoadError
|
9
|
-
|
9
|
+
begin
|
10
|
+
load 'tasks/setup.rb'
|
11
|
+
rescue LoadError
|
12
|
+
raise RuntimeError, '### please install the "bones" gem ###'
|
13
|
+
end
|
10
14
|
end
|
11
15
|
|
12
16
|
ensure_in_path 'lib'
|
13
17
|
require 'juicer'
|
18
|
+
load 'tasks/test/setup.rake'
|
14
19
|
|
15
20
|
task :default => 'test:run'
|
16
21
|
|
@@ -21,7 +26,23 @@ PROJ.url = 'http://www.cjohansen.no/en/projects/juicer'
|
|
21
26
|
PROJ.version = Juicer::VERSION
|
22
27
|
PROJ.rubyforge.name = 'juicer'
|
23
28
|
PROJ.readme_file = 'Readme.rdoc'
|
29
|
+
PROJ.exclude = %w(tmp$ bak$ ~$ CVS \.svn ^pkg ^doc \.git ^rcov ^test\/data gemspec ^test\/bin)
|
30
|
+
PROJ.rdoc.remote_dir = 'juicer'
|
24
31
|
|
25
32
|
PROJ.spec.opts << '--color'
|
26
33
|
|
34
|
+
PROJ.gem.extras[:post_install_message] = <<-MSG
|
35
|
+
Juicer does not ship with third party libraries. You probably want to install
|
36
|
+
Yui Compressor and JsLint now:
|
37
|
+
|
38
|
+
juicer install yui_compressor
|
39
|
+
juicer install jslint
|
40
|
+
|
41
|
+
Happy juicing!
|
42
|
+
MSG
|
43
|
+
|
44
|
+
CLOBBER.include "test/data"
|
45
|
+
|
27
46
|
depend_on 'cmdparse'
|
47
|
+
depend_on 'hpricot'
|
48
|
+
depend_on 'rubyzip'
|
data/Readme.rdoc
CHANGED
@@ -1,20 +1,32 @@
|
|
1
1
|
= Juicer
|
2
|
+
Official URL: http://github.com/cjohansen/juicer/tree/master
|
2
3
|
Christian Johansen (http://www.cjohansen.no)
|
3
4
|
|
4
5
|
== DESCRIPTION:
|
5
6
|
|
6
|
-
Juicer is a command line tool
|
7
|
-
|
8
|
-
|
7
|
+
Juicer is a command line tool that helps you ship frontend code for production.
|
8
|
+
|
9
|
+
High level overview; Juicer can
|
10
|
+
|
11
|
+
* figure out which files depend on each other and merge them together, reducing
|
12
|
+
the number of http requests per page view, thus improving performance
|
13
|
+
* use YUI Compressor to compress code, thus improving performance
|
14
|
+
* verify that your JavaScript is safe to minify/compress by running JsLint on it
|
15
|
+
* cycle asset hosts in CSS files
|
16
|
+
* add "cache busters" to URLs in CSS files
|
17
|
+
* recalculate relative URLs in CSS files, as well as convert them to absolute
|
18
|
+
(or convert absolute URLs to relative URLs)
|
9
19
|
|
10
20
|
== FEATURES:
|
11
21
|
|
22
|
+
=== Merging and minifying
|
23
|
+
|
12
24
|
Juicer can read @import statements in CSS files and use them to combine all your
|
13
25
|
stylesheets into a single file. This file may be minified using the YUI
|
14
26
|
Compressor. Eventually it will support other minifying tools too.
|
15
27
|
|
16
28
|
Juicer can treat your JavaScript files much the same way too, parsing a comment
|
17
|
-
switch @
|
29
|
+
switch @depend, as this example shows:
|
18
30
|
|
19
31
|
/**
|
20
32
|
* My script file
|
@@ -29,28 +41,51 @@ Running <tt>juicer merge</tt> on this file will result in a minified file
|
|
29
41
|
<tt>filename.min.js</tt> containing the file jquery-1.2.0.js (located in the
|
30
42
|
same directory) and the code above.
|
31
43
|
|
32
|
-
|
44
|
+
You can use @import (CSS files) and @depend (JavaScript) recursively, effectively
|
45
|
+
creating a dependency chain for Juicer to climb and merge.
|
46
|
+
|
47
|
+
=== Paths
|
48
|
+
|
49
|
+
When merging CSS files, you may want to merge CSS files in different directories.
|
50
|
+
You may also want the resulting CSS file to end up in another directory as well.
|
51
|
+
Juicer automatically recalculates referenced URLs to reflect this change.
|
52
|
+
|
53
|
+
Absolute URLs are not changed by default, but if you provide juicer merge with
|
54
|
+
--document-root [DIR] and --relative-urls then absolute URLs are converted to
|
55
|
+
URLs relative to output directory. You can also use --absolute-urls to convert
|
56
|
+
all URLs to absolute ones.
|
57
|
+
|
58
|
+
=== Cache busters
|
33
59
|
|
34
|
-
Juicer
|
35
|
-
|
36
|
-
|
60
|
+
Juicer supports so-called cache busters. A cache buster is a pattern in a path
|
61
|
+
whose only purpose is to "trick" browsers to redownload a file when it has
|
62
|
+
changed in cases where a far future expires header is used.
|
63
|
+
|
64
|
+
There are two types of cache busters; soft ones add a parameter to the URL, like
|
65
|
+
so: http://assets/images/1.png?cb1234567890, ie the letters "cb" (as in cache
|
66
|
+
buster) and then the timestamp of the files mtime.
|
67
|
+
|
68
|
+
Unfortunately, the popular web proxy Squid shipped for some time with a default
|
69
|
+
configuration which would not treat a URL as a "new" URL if the only thing changed
|
70
|
+
was the GET parameters. For this reason Juicer provides hard cache busters.
|
71
|
+
|
72
|
+
Hard cache busters result in URLs such as http://assets/images/1-cb1234567890.png,
|
73
|
+
ie URLs that require either renaming of files, or (more conveniently) a web
|
74
|
+
server configuration that will forward URLs to the right files anyway.
|
37
75
|
|
38
76
|
== PLANNED FEATURES:
|
39
77
|
|
40
|
-
|
78
|
+
Juicer 0.2.0 is the first usable release. Work will continue from here. Improving
|
79
|
+
documentation and APIs is one concern, but there are also new features planned:
|
41
80
|
|
42
81
|
* Support more minifiers, JsMin (Ruby port), Packer and possibly others
|
43
|
-
*
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
As you see, Juicer will mostly rely heavily on other peoples great work. Juicers
|
49
|
-
strength will be that it provides a single simple to use interface to run these
|
50
|
-
tools on your project, as well as sewing it all together.
|
82
|
+
* Add support for CssTidy to compress CSS files
|
83
|
+
* juicer build, a command that can build several files in one swoop using a
|
84
|
+
configuration file
|
85
|
+
* juicer doc, a command that produces documentation using YUI Doc or JsDoc
|
51
86
|
|
52
87
|
If you have any ideas, feature requests, want to contribute or whatever, fork
|
53
|
-
the
|
88
|
+
the project on github, or get in touch through christian (at) cjohansen.no.
|
54
89
|
|
55
90
|
== SYNOPSIS:
|
56
91
|
|
@@ -60,33 +95,34 @@ the proect on github, or get in touch through christian (at) cjohansen.no.
|
|
60
95
|
juicer merge myfile.js
|
61
96
|
-> Produces myfile.min.js, minified and combined
|
62
97
|
|
98
|
+
juicer help
|
99
|
+
|
63
100
|
== REQUIREMENTS:
|
64
101
|
|
65
|
-
In order to use YUI Compressor
|
66
|
-
available on your path.
|
102
|
+
In order to use YUI Compressor and JsMin (requires Rhino) you need Java
|
103
|
+
installed and the java executable available on your path.
|
67
104
|
|
68
105
|
== INSTALL:
|
69
106
|
|
70
|
-
$
|
71
|
-
$
|
107
|
+
$ gem install juicer
|
108
|
+
$ juicer install yui_compressor
|
109
|
+
$ juicer install jslint
|
110
|
+
|
111
|
+
You need Java installed and available on your PATH. During gem installation,
|
112
|
+
Juicer will download and install YUI Compressor, JsLint and Rhino for you.
|
72
113
|
|
73
|
-
|
74
|
-
http://developer.yahoo.com/yui/compressor/
|
114
|
+
== For developers
|
75
115
|
|
76
|
-
|
77
|
-
|
78
|
-
found, or provide the path like so:
|
79
|
-
juicer merge --path ~/sources/yuicompressor/build [...]
|
116
|
+
Before running tests you should run
|
117
|
+
rake test:setup
|
80
118
|
|
81
|
-
|
82
|
-
run the <tt>juicer</tt> command from. I imagine that would only make sense in a
|
83
|
-
testing scenario.
|
119
|
+
which brings in third party libraries (ie, requires a working network connection)
|
84
120
|
|
85
121
|
== LICENSE:
|
86
122
|
|
87
123
|
(The MIT License)
|
88
124
|
|
89
|
-
Copyright (c) 2008 Christian Johansen
|
125
|
+
Copyright (c) 2008-2009 Christian Johansen
|
90
126
|
|
91
127
|
Permission is hereby granted, free of charge, to any person obtaining
|
92
128
|
a copy of this software and associated documentation files (the
|
data/bin/juicer
CHANGED
data/lib/juicer.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
1
3
|
module Juicer
|
2
4
|
|
3
5
|
# :stopdoc:
|
4
|
-
VERSION = '0.2.
|
6
|
+
VERSION = '0.2.4'
|
5
7
|
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
6
8
|
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
9
|
+
LOGGER = Logger.new(STDOUT)
|
10
|
+
@@home = nil
|
7
11
|
# :startdoc:
|
8
12
|
|
9
13
|
# Returns the version string for the library.
|
@@ -12,6 +16,24 @@ module Juicer
|
|
12
16
|
VERSION
|
13
17
|
end
|
14
18
|
|
19
|
+
# Returns the installation directory for Juicer
|
20
|
+
#
|
21
|
+
def self.home
|
22
|
+
return @@home if @@home
|
23
|
+
return ENV['JUICER_HOME'] if ENV['JUICER_HOME']
|
24
|
+
return File.join(ENV['HOME'], ".juicer") if ENV['HOME']
|
25
|
+
return File.join(ENV['APPDATA'], "juicer") if ENV['APPDATA']
|
26
|
+
return File.join(ENV['HOMEDRIVE'], ENV['HOMEPATH'], "juicer") if ENV['HOMEDRIVE'] && ENV['HOMEPATH']
|
27
|
+
return File.join(ENV['USERPROFILE'], "juicer") if ENV['USERPROFILE']
|
28
|
+
return File.join(ENV['Personal'], "juicer") if ENV['Personal']
|
29
|
+
end
|
30
|
+
|
31
|
+
# Set home directory
|
32
|
+
#
|
33
|
+
def self.home=(home)
|
34
|
+
@@home = home
|
35
|
+
end
|
36
|
+
|
15
37
|
# Returns the library path for the module. If any arguments are given,
|
16
38
|
# they will be joined to the end of the libray path using
|
17
39
|
# <tt>File.join</tt>.
|
@@ -43,3 +65,6 @@ module Juicer
|
|
43
65
|
end
|
44
66
|
|
45
67
|
Juicer.require_all_libs_relative_to(__FILE__)
|
68
|
+
|
69
|
+
class FileNotFoundError < Exception
|
70
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "chainable"))
|
2
|
+
|
3
|
+
module Juicer
|
4
|
+
|
5
|
+
# Defines an abstract implementation of a binary that needs to be "shelled
|
6
|
+
# out" to be run. Provides a starting point when wrapping and API around a
|
7
|
+
# shell binary.
|
8
|
+
#
|
9
|
+
# The module requires the including class to define the default_options
|
10
|
+
# method. It should return a hash of options where options are keys and
|
11
|
+
# default values are the values. Only options defined in this hash will be
|
12
|
+
# allowed to set on the binary.
|
13
|
+
#
|
14
|
+
module Binary
|
15
|
+
|
16
|
+
# Initialize binary with options
|
17
|
+
# options = Hash of options, optional
|
18
|
+
#
|
19
|
+
def initialize(binary, options = {})
|
20
|
+
@options = self.respond_to?(:defualt_options) ? default_options.merge(options) : options
|
21
|
+
@opt_set = false
|
22
|
+
@command = nil
|
23
|
+
@binary = binary
|
24
|
+
@path = []
|
25
|
+
end
|
26
|
+
|
27
|
+
def path
|
28
|
+
@path
|
29
|
+
end
|
30
|
+
|
31
|
+
# Run command
|
32
|
+
#
|
33
|
+
def execute(params = nil)
|
34
|
+
#puts "#{self.command} #{params}"
|
35
|
+
cmd = IO.popen("#{self.command} #{params}", "r")
|
36
|
+
results = cmd.gets(nil)
|
37
|
+
cmd.close
|
38
|
+
results
|
39
|
+
end
|
40
|
+
|
41
|
+
# Return the value of a given option
|
42
|
+
# opt = The option to return value for
|
43
|
+
#
|
44
|
+
def get_opt(opt)
|
45
|
+
@options[opt] || nil
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return options as a cli arguments string. Optionally accepts a list of
|
49
|
+
# options to exclude from the generated string
|
50
|
+
#
|
51
|
+
def options(*excludes)
|
52
|
+
excludes = excludes.flatten.collect { |exc| exc.to_sym }
|
53
|
+
@options.inject("") do |str, opt|
|
54
|
+
if opt[1].nil? || excludes.include?(opt[0].to_sym)
|
55
|
+
str
|
56
|
+
else
|
57
|
+
val = opt[1] == true ? '' : opt[1]
|
58
|
+
option = opt[0].to_s
|
59
|
+
option = (option.length == 1 ? "-" : "--") + option.gsub('_', '-')
|
60
|
+
"#{str} #{option} #{val}".strip
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Set an option. Important: you can only set options that are predefined by the
|
66
|
+
# implementing class
|
67
|
+
# opt = The option to set
|
68
|
+
# value = The value of the option
|
69
|
+
#
|
70
|
+
def set_opt(opt, value)
|
71
|
+
opt = opt.to_sym
|
72
|
+
if @options.key?(opt)
|
73
|
+
@options[opt] = value
|
74
|
+
@opt_set = true
|
75
|
+
else
|
76
|
+
msg = "Illegal option '#{opt}', specify one of: #{@options.keys.join(', ')}"
|
77
|
+
raise ArgumentError.new(msg)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Performs simple parsing of a string of parameters. All recognized
|
82
|
+
# parameters are set, non-existent arguments raise an ArgumentError
|
83
|
+
#
|
84
|
+
def set_opts(options)
|
85
|
+
options = options.split " "
|
86
|
+
option = nil
|
87
|
+
regex = /^--?([^=]*)(=(.*))?/
|
88
|
+
|
89
|
+
while word = options.shift
|
90
|
+
if word =~ regex
|
91
|
+
if option
|
92
|
+
set_opt option, true
|
93
|
+
end
|
94
|
+
|
95
|
+
if $3
|
96
|
+
set_opt $1, $3
|
97
|
+
else
|
98
|
+
option = $1
|
99
|
+
end
|
100
|
+
else
|
101
|
+
set_opt option, word
|
102
|
+
option = nil
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Constructs the command to use
|
108
|
+
#
|
109
|
+
def command
|
110
|
+
return @command if !@opt_set && @command
|
111
|
+
@opt_set = false
|
112
|
+
@command = "#{@binary} #{options}"
|
113
|
+
end
|
114
|
+
|
115
|
+
# Locate the binary to execute. The binary is searched for in the
|
116
|
+
# following places:
|
117
|
+
#
|
118
|
+
# 1) The paths specified through my_binary.path << "/usr/bin"
|
119
|
+
# 2) The path specified by the given environment variable
|
120
|
+
# 3) Current working directory
|
121
|
+
#
|
122
|
+
# The name of the binary may be a glob pattern, resulting in +locate+
|
123
|
+
# returning an array of matches. This is useful in cases where the path
|
124
|
+
# is expected to store several versions oof a binary in the same directory,
|
125
|
+
# like /usr/bin/ruby /usr/bin/ruby1.8 /usr/bin/ruby1.9
|
126
|
+
#
|
127
|
+
# +locate+ always returns an array, or nil if no binaries where found.
|
128
|
+
# The result is always all files matching the given pattern in *one* of
|
129
|
+
# the specified paths - ie the first path where the pattern matches
|
130
|
+
# something.
|
131
|
+
#
|
132
|
+
def locate(bin_glob, env = nil)
|
133
|
+
path << ENV[env] if env && ENV.key?(env) && File.exist?(ENV[env])
|
134
|
+
|
135
|
+
(path << Dir.pwd).each do |path|
|
136
|
+
files = Dir.glob(File.expand_path(File.join(path, bin_glob)))
|
137
|
+
return files unless files.empty?
|
138
|
+
end
|
139
|
+
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
|
143
|
+
# Allows for options to be set and read directly on the object as though they were
|
144
|
+
# standard attributes. compressor.verbose translates to
|
145
|
+
# compressor.get_opt('verbose') and compressor.verbose = true to
|
146
|
+
# compressor.set_opt('verbose', true)
|
147
|
+
def method_missing(m, *args)
|
148
|
+
if @options.key?(m)
|
149
|
+
# Only hit method_missing once per option
|
150
|
+
self.class.send(:define_method, m) do # def verbose
|
151
|
+
get_opt(m) # get_opt(:verbose)
|
152
|
+
end # end
|
153
|
+
|
154
|
+
return get_opt(m)
|
155
|
+
end
|
156
|
+
|
157
|
+
return super unless m.to_s =~ /=$/
|
158
|
+
|
159
|
+
opt = m.to_s.sub(/=$/, "").to_sym
|
160
|
+
|
161
|
+
if @options.key?(opt)
|
162
|
+
# Only hit method_missing once per option
|
163
|
+
self.class.send(:define_method, m) do # def verbose=(val)
|
164
|
+
set_opt(opt, args[0]) # set_opt(:verbose, val)
|
165
|
+
end # end
|
166
|
+
|
167
|
+
return set_opt(opt, args[0])
|
168
|
+
end
|
169
|
+
|
170
|
+
super
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|