cjohansen-juicer 0.2.0 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|