jim 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/HISTORY +28 -0
  2. data/README.rdoc +1 -1
  3. data/Rakefile +2 -1
  4. data/jim.gemspec +67 -9
  5. data/lib/jim/bundler.rb +14 -11
  6. data/lib/jim/cli.rb +51 -9
  7. data/lib/jim/index.rb +3 -7
  8. data/lib/jim/installer.rb +140 -22
  9. data/lib/jim/templates/commands +21 -6
  10. data/lib/jim/version_parser.rb +2 -3
  11. data/lib/jim.rb +19 -2
  12. data/test/fixtures/jimfile +3 -3
  13. data/test/fixtures/sammy-0.5.0/HISTORY.md +135 -0
  14. data/test/fixtures/sammy-0.5.0/LICENSE +22 -0
  15. data/test/fixtures/sammy-0.5.0/README.md +81 -0
  16. data/test/fixtures/sammy-0.5.0/Rakefile +174 -0
  17. data/test/fixtures/sammy-0.5.0/examples/backend/README.md +23 -0
  18. data/test/fixtures/sammy-0.5.0/examples/backend/Rakefile +15 -0
  19. data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +17 -0
  20. data/test/fixtures/sammy-0.5.0/examples/backend/app.ru +3 -0
  21. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +106 -0
  22. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +840 -0
  23. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +19 -0
  24. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +1013 -0
  25. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/index.html.erb +11 -0
  26. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +4 -0
  27. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +4 -0
  28. data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +63 -0
  29. data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +18 -0
  30. data/test/fixtures/sammy-0.5.0/examples/form_handling/files/form.html +12 -0
  31. data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +65 -0
  32. data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +50 -0
  33. data/test/fixtures/sammy-0.5.0/examples/location_override/README.md +15 -0
  34. data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +110 -0
  35. data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +79 -0
  36. data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +121 -0
  37. data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +5 -0
  38. data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +5 -0
  39. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +117 -0
  40. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +539 -0
  41. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +362 -0
  42. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +415 -0
  43. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +118 -0
  44. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +515 -0
  45. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +117 -0
  46. data/test/fixtures/sammy-0.5.0/lib/sammy.js +1367 -0
  47. data/test/fixtures/sammy-0.5.0/test/fixtures/partial +1 -0
  48. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -0
  49. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.noengine +1 -0
  50. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.template +1 -0
  51. data/test/fixtures/sammy-0.5.0/test/index.html +84 -0
  52. data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +953 -0
  53. data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +252 -0
  54. data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +91 -0
  55. data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +296 -0
  56. data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +175 -0
  57. data/test/fixtures/sammy-0.5.0/test/test_server +27 -0
  58. data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.js +6078 -0
  59. data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.min.js +152 -0
  60. data/test/fixtures/sammy-0.5.0/vendor/jsdoc/doc.haml +58 -0
  61. data/test/fixtures/sammy-0.5.0/vendor/jsdoc/jsdoc.rb +143 -0
  62. data/test/fixtures/sammy-0.5.0/vendor/jslitmus.js +670 -0
  63. data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.css +119 -0
  64. data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.js +1043 -0
  65. data/test/fixtures/sammy-0.5.0/vendor/qunit-spec.js +127 -0
  66. data/test/helper.rb +23 -3
  67. data/test/test_jim_bundler.rb +9 -8
  68. data/test/test_jim_cli.rb +21 -12
  69. data/test/test_jim_installer.rb +152 -35
  70. data/test/test_jim_version_parser.rb +4 -0
  71. metadata +117 -27
  72. data/.document +0 -5
data/HISTORY ADDED
@@ -0,0 +1,28 @@
1
+ == 0.2.0 [03-16-10]
2
+
3
+ * Major rewrite of the installer and version parser
4
+ * Each file in a package is installed separately
5
+ * Each file is installed with a package.json file that describes the install
6
+ and is merged with any existing package.json files
7
+ * version parser was rewritten and handles many different formats
8
+ * Existing JIMHOMEs are probably now invalid (SORRY!!)
9
+ * The install, specify, vendor, bundle workflow works from start to finish
10
+ * passing the -o option to bundle or compress outputs to STDOUT
11
+ * New commands:
12
+ * available
13
+ * pack
14
+
15
+
16
+ == 0.1.2 [02-21-10]
17
+
18
+ * Added remove command
19
+ * list returns versions
20
+ * more tests and documentation
21
+
22
+ == 0.1.1 [02-20-10]
23
+
24
+ * Fixed dev dependencies and requirements [Thanks jimeh]
25
+
26
+ == 0.1.0 [02-19-10]
27
+
28
+ * Initial release
data/README.rdoc CHANGED
@@ -47,7 +47,7 @@ In your project run:
47
47
 
48
48
  $ jim init
49
49
 
50
- Which create an empty "Jimfile". Open it up and add your requirements:
50
+ Which creates an empty "Jimfile". Open it up and add your requirements:
51
51
 
52
52
  // bundled_path: public/javascripts/bundled.js
53
53
  // compressed_path: public/javascripts/compressed.js
data/Rakefile CHANGED
@@ -16,8 +16,9 @@ begin
16
16
  gem.homepage = "http://github.com/quirkey/jim"
17
17
  gem.authors = ["Aaron Quint"]
18
18
 
19
- gem.add_dependency "downlow", ">= 0.1.2"
19
+ gem.add_dependency "downlow", ">= 0.1.3"
20
20
  gem.add_dependency "yajl-ruby"
21
+ gem.add_dependency "version_sorter", ">= 1.1.0"
21
22
 
22
23
  gem.add_development_dependency "shoulda", ">= 0"
23
24
  gem.add_development_dependency "fakeweb", ">= 1.2.8"
data/jim.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{jim}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Aaron Quint"]
12
- s.date = %q{2010-02-21}
12
+ s.date = %q{2010-03-16}
13
13
  s.default_executable = %q{jim}
14
14
  s.description = %q{jim is your friendly javascript library manager. He downloads, stores, bundles, vendors and compresses.}
15
15
  s.email = %q{aaron@quirkey.com}
@@ -19,8 +19,8 @@ Gem::Specification.new do |s|
19
19
  "README.rdoc"
20
20
  ]
21
21
  s.files = [
22
- ".document",
23
- ".gitignore",
22
+ ".gitignore",
23
+ "HISTORY",
24
24
  "LICENSE",
25
25
  "README.rdoc",
26
26
  "Rakefile",
@@ -43,6 +43,59 @@ Gem::Specification.new do |s|
43
43
  "test/fixtures/mustache.js/mustache.js",
44
44
  "test/fixtures/mustache.js/package.json",
45
45
  "test/fixtures/noversion.js",
46
+ "test/fixtures/sammy-0.5.0/HISTORY.md",
47
+ "test/fixtures/sammy-0.5.0/LICENSE",
48
+ "test/fixtures/sammy-0.5.0/README.md",
49
+ "test/fixtures/sammy-0.5.0/Rakefile",
50
+ "test/fixtures/sammy-0.5.0/examples/backend/README.md",
51
+ "test/fixtures/sammy-0.5.0/examples/backend/Rakefile",
52
+ "test/fixtures/sammy-0.5.0/examples/backend/app.rb",
53
+ "test/fixtures/sammy-0.5.0/examples/backend/app.ru",
54
+ "test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js",
55
+ "test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js",
56
+ "test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js",
57
+ "test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js",
58
+ "test/fixtures/sammy-0.5.0/examples/backend/public/templates/index.html.erb",
59
+ "test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb",
60
+ "test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb",
61
+ "test/fixtures/sammy-0.5.0/examples/backend/views/app.sass",
62
+ "test/fixtures/sammy-0.5.0/examples/backend/views/index.haml",
63
+ "test/fixtures/sammy-0.5.0/examples/form_handling/files/form.html",
64
+ "test/fixtures/sammy-0.5.0/examples/form_handling/index.html",
65
+ "test/fixtures/sammy-0.5.0/examples/hello_world/index.html",
66
+ "test/fixtures/sammy-0.5.0/examples/location_override/README.md",
67
+ "test/fixtures/sammy-0.5.0/examples/location_override/data.html",
68
+ "test/fixtures/sammy-0.5.0/examples/location_override/index.html",
69
+ "test/fixtures/sammy-0.5.0/examples/location_override/test.html",
70
+ "test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js",
71
+ "test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js",
72
+ "test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js",
73
+ "test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js",
74
+ "test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js",
75
+ "test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js",
76
+ "test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js",
77
+ "test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js",
78
+ "test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js",
79
+ "test/fixtures/sammy-0.5.0/lib/sammy.js",
80
+ "test/fixtures/sammy-0.5.0/test/fixtures/partial",
81
+ "test/fixtures/sammy-0.5.0/test/fixtures/partial.html",
82
+ "test/fixtures/sammy-0.5.0/test/fixtures/partial.noengine",
83
+ "test/fixtures/sammy-0.5.0/test/fixtures/partial.template",
84
+ "test/fixtures/sammy-0.5.0/test/index.html",
85
+ "test/fixtures/sammy-0.5.0/test/test_sammy_application.js",
86
+ "test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js",
87
+ "test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js",
88
+ "test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js",
89
+ "test/fixtures/sammy-0.5.0/test/test_sammy_storage.js",
90
+ "test/fixtures/sammy-0.5.0/test/test_server",
91
+ "test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.js",
92
+ "test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.min.js",
93
+ "test/fixtures/sammy-0.5.0/vendor/jsdoc/doc.haml",
94
+ "test/fixtures/sammy-0.5.0/vendor/jsdoc/jsdoc.rb",
95
+ "test/fixtures/sammy-0.5.0/vendor/jslitmus.js",
96
+ "test/fixtures/sammy-0.5.0/vendor/qunit-spec.js",
97
+ "test/fixtures/sammy-0.5.0/vendor/qunit/qunit.css",
98
+ "test/fixtures/sammy-0.5.0/vendor/qunit/qunit.js",
46
99
  "test/helper.rb",
47
100
  "test/test_jim_bundler.rb",
48
101
  "test/test_jim_cli.rb",
@@ -53,10 +106,12 @@ Gem::Specification.new do |s|
53
106
  s.homepage = %q{http://github.com/quirkey/jim}
54
107
  s.rdoc_options = ["--charset=UTF-8"]
55
108
  s.require_paths = ["lib"]
56
- s.rubygems_version = %q{1.3.5}
109
+ s.rubygems_version = %q{1.3.6}
57
110
  s.summary = %q{jim is your friendly javascript library manager}
58
111
  s.test_files = [
59
- "test/helper.rb",
112
+ "test/fixtures/sammy-0.5.0/examples/backend/app.rb",
113
+ "test/fixtures/sammy-0.5.0/vendor/jsdoc/jsdoc.rb",
114
+ "test/helper.rb",
60
115
  "test/test_jim_bundler.rb",
61
116
  "test/test_jim_cli.rb",
62
117
  "test/test_jim_index.rb",
@@ -69,21 +124,24 @@ Gem::Specification.new do |s|
69
124
  s.specification_version = 3
70
125
 
71
126
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
72
- s.add_runtime_dependency(%q<downlow>, [">= 0.1.2"])
127
+ s.add_runtime_dependency(%q<downlow>, [">= 0.1.3"])
73
128
  s.add_runtime_dependency(%q<yajl-ruby>, [">= 0"])
129
+ s.add_runtime_dependency(%q<version_sorter>, [">= 1.1.0"])
74
130
  s.add_development_dependency(%q<shoulda>, [">= 0"])
75
131
  s.add_development_dependency(%q<fakeweb>, [">= 1.2.8"])
76
132
  s.add_development_dependency(%q<mocha>, [">= 0"])
77
133
  else
78
- s.add_dependency(%q<downlow>, [">= 0.1.2"])
134
+ s.add_dependency(%q<downlow>, [">= 0.1.3"])
79
135
  s.add_dependency(%q<yajl-ruby>, [">= 0"])
136
+ s.add_dependency(%q<version_sorter>, [">= 1.1.0"])
80
137
  s.add_dependency(%q<shoulda>, [">= 0"])
81
138
  s.add_dependency(%q<fakeweb>, [">= 1.2.8"])
82
139
  s.add_dependency(%q<mocha>, [">= 0"])
83
140
  end
84
141
  else
85
- s.add_dependency(%q<downlow>, [">= 0.1.2"])
142
+ s.add_dependency(%q<downlow>, [">= 0.1.3"])
86
143
  s.add_dependency(%q<yajl-ruby>, [">= 0"])
144
+ s.add_dependency(%q<version_sorter>, [">= 1.1.0"])
87
145
  s.add_dependency(%q<shoulda>, [">= 0"])
88
146
  s.add_dependency(%q<fakeweb>, [">= 1.2.8"])
89
147
  s.add_dependency(%q<mocha>, [">= 0"])
data/lib/jim/bundler.rb CHANGED
@@ -23,15 +23,18 @@ module Jim
23
23
 
24
24
  # create a new bundler instance passing in the Jimfile as a `Pathname` or a
25
25
  # string. `index` is a Jim::Index
26
- def initialize(jimfile, index = nil, options = {})
26
+ def initialize(jimfile, index = nil, extra_options = {})
27
27
  self.jimfile = jimfile.is_a?(Pathname) ? jimfile.read : jimfile
28
28
  self.index = index || Jim::Index.new
29
29
  self.options = {}
30
30
  self.requirements = []
31
31
  parse_jimfile
32
- self.options.merge(options)
33
- self.add(options[:vendor_dir]) if options[:vendor_dir]
32
+ self.options = options.merge(extra_options)
34
33
  self.paths = []
34
+ if options[:vendor_dir]
35
+ logger.debug "adding vendor dir to index #{options[:vendor_dir]}"
36
+ self.index.add(options[:vendor_dir])
37
+ end
35
38
  end
36
39
 
37
40
  # resove the requirements specified into Jimfile or raise a MissingFile error
@@ -43,7 +46,7 @@ module Jim
43
46
  raise(MissingFile,
44
47
  "Could not find #{name} #{version} in any of these paths #{index.directories.join(':')}")
45
48
  end
46
- self.paths << path
49
+ self.paths << [path, name, version]
47
50
  end
48
51
  paths
49
52
  end
@@ -54,8 +57,8 @@ module Jim
54
57
  resolve! if paths.empty?
55
58
  to = options[:bundled_path] if to.nil? && options[:bundled_path]
56
59
  io = io_for_path(to)
57
- logger.info "bundling to #{to}" if to
58
- paths.each do |path|
60
+ logger.info "Bundling to #{to}" if to
61
+ paths.each do |path, name, version|
59
62
  io << path.read << "\n"
60
63
  end
61
64
  io
@@ -67,20 +70,20 @@ module Jim
67
70
  def compress!(to = nil)
68
71
  to = options[:compressed_path] if to.nil? && options[:compressed_path]
69
72
  io = io_for_path(to)
70
- logger.info "compressing to #{to}"
73
+ logger.info "Compressing to #{to}"
71
74
  io << compress_js(bundle!(false))
72
75
  io
73
76
  end
74
77
 
75
78
  # copy each of the requirements into the dir specified with `dir` or the path
76
79
  # specified with the :vendor_dir option
77
- def vendor!(dir = nil)
80
+ def vendor!(dir = nil, force = false)
78
81
  resolve! if paths.empty?
79
82
  dir ||= options[:vendor_dir]
80
83
  dir ||= 'vendor' # default
81
- logger.info "vendoring to #{dir}"
82
- paths.each do |path|
83
- Jim::Installer.new(path, dir, :shallow => true).install
84
+ logger.info "Vendoring to #{dir}"
85
+ paths.each do |path, name, version|
86
+ Jim::Installer.new(path, dir, :shallow => true, :force => force).install
84
87
  end
85
88
  end
86
89
 
data/lib/jim/cli.rb CHANGED
@@ -8,7 +8,7 @@ module Jim
8
8
  # the different public methods represent 1-1 the commands provided by the bin.
9
9
  class CLI
10
10
 
11
- attr_accessor :jimfile, :jimhome, :force
11
+ attr_accessor :jimfile, :jimhome, :force, :stdout
12
12
 
13
13
  # create a new instance with the args passed from the command line i.e. ARGV
14
14
  def initialize(args)
@@ -32,6 +32,8 @@ module Jim
32
32
  @output << "No action found for #{command}. Run -h for help."
33
33
  end
34
34
  @output
35
+ rescue ArgumentError => e
36
+ @output << "#{e.message} for #{command}"
35
37
  rescue Jim::FileExists => e
36
38
  @output << "#{e.message} already exists, bailing. Use --force if you're sure"
37
39
  rescue => e
@@ -49,19 +51,20 @@ module Jim
49
51
  def cheat
50
52
  logger.info "Usage: jim [options] [command] [args]\n"
51
53
  logger.info "Commands:"
52
- logger.info template('commands').find_all {|l| l.match(/^\w/) }.join("")
54
+ logger.info [*template('commands')].grep(/^\w/).join
53
55
  logger.info "run commands for details"
54
56
  end
57
+ alias :help :cheat
55
58
 
56
59
  # initialize the current dir with a new Jimfile
57
60
  def init(dir = nil)
58
61
  dir = Pathname.new(dir || '')
59
62
  jimfile_path = dir + 'Jimfile'
60
63
  if jimfile_path.readable? && !force
61
- raise Jim::FileExists(jimfile_path)
64
+ raise Jim::FileExists.new(jimfile_path)
62
65
  else
63
66
  File.open(jimfile_path, 'w') do |f|
64
- f << template('Jimfile')
67
+ f << template('jimfile')
65
68
  end
66
69
  logger.info "wrote Jimfile to #{jimfile_path}"
67
70
  end
@@ -74,24 +77,39 @@ module Jim
74
77
 
75
78
  # bundle the files specified in Jimfile into `to`
76
79
  def bundle(to = nil)
80
+ to = STDOUT if stdout
77
81
  path = bundler.bundle!(to)
82
+ logger.info "Wrote #{File.size(path) / 1024}kb"
78
83
  end
79
84
 
80
85
  # compress the files specified in Jimfile into `to`
81
86
  def compress(to = nil)
87
+ to = STDOUT if stdout
82
88
  path = bundler.compress!(to)
89
+ logger.info "Wrote #{File.size(path) / 1024}kb"
83
90
  end
84
91
 
85
92
  # copy/vendor all the files specified in Jimfile to `dir`
86
93
  def vendor(dir = nil)
87
- bundler.vendor!(dir)
94
+ bundler.vendor!(dir, force)
88
95
  end
89
96
 
90
- # list the installed projects and versions
97
+ # list the only the _installed_ projects and versions
91
98
  def list
92
- logger.info "Getting list of installed files in #{index.directories.join(':')}"
99
+ logger.info "Getting list of installed files in\n#{installed_index.directories.join(':')}"
100
+ list = installed_index.list
101
+ logger.info "Installed:"
102
+ print_version_list(list)
103
+ end
104
+ alias :installed :list
105
+
106
+ # list all available projects and versions including those in the local path, or
107
+ # paths specified in a jimfile
108
+ def available
109
+ logger.info "Getting list of all available files in\n#{index.directories.join("\n")}"
93
110
  list = index.list
94
- logger.info "Installed:\n#{list.collect {|i| "#{i[0]} (#{i[1].join(', ')})"}.join("\n")}"
111
+ logger.info "Available:"
112
+ print_version_list(list)
95
113
  end
96
114
 
97
115
  # Iterates over matching files and prompts for removal
@@ -116,13 +134,25 @@ module Jim
116
134
  logger.info "No installed files matched."
117
135
  end
118
136
  end
137
+ alias :uninstall :remove
119
138
 
120
139
  # list the files and their resolved paths specified in the Jimfile
121
140
  def resolve
122
141
  resolved = bundler.resolve!
123
- logger.info "Files:\n#{resolved.join("\n")}"
142
+ logger.info "Files:"
143
+ resolved.each do |r|
144
+ logger.info r.join(" | ")
145
+ end
124
146
  resolved
125
147
  end
148
+
149
+ # vendor to dir, then bundle and compress the Jimfile contents
150
+ def pack(dir = nil)
151
+ logger.info "packing the Jimfile for this project"
152
+ vendor(dir)
153
+ bundle
154
+ compress
155
+ end
126
156
 
127
157
  private
128
158
  def parse_options(runtime_args)
@@ -148,10 +178,16 @@ module Jim
148
178
  logger.level = Logger::DEBUG
149
179
  }
150
180
 
181
+ opts.on("-o", "--stdout", "write output of commands (like bundle and compress to STDOUT)") {|o|
182
+ logger.level = Logger::ERROR
183
+ self.stdout = true
184
+ }
185
+
151
186
  opts.on("-v", "--version", "print version") {|d|
152
187
  puts "jim #{Jim::VERSION}"
153
188
  exit
154
189
  }
190
+
155
191
 
156
192
  opts.on_tail("-h", "--help", "Show this message. Run jim commands for list of commands.") do
157
193
  puts opts.help
@@ -188,5 +224,11 @@ module Jim
188
224
  Jim.logger
189
225
  end
190
226
 
227
+ def print_version_list(list)
228
+ list.each do |file, versions|
229
+ logger.info "#{file} (#{VersionSorter.rsort(versions.collect {|v| v[0] }).join(',')})"
230
+ end
231
+ end
232
+
191
233
  end
192
234
  end
data/lib/jim/index.rb CHANGED
@@ -4,7 +4,7 @@ module Jim
4
4
  attr_reader :directories
5
5
 
6
6
  def initialize(*directories)
7
- @directories = directories.flatten
7
+ @directories = directories.flatten.compact
8
8
  end
9
9
 
10
10
  def add(directory)
@@ -14,7 +14,7 @@ module Jim
14
14
  def list
15
15
  list = {}
16
16
  each_file_in_index('.js') do |filename|
17
- if /lib\/([^\/]+)-([\d\w\.\-]+)\/.+/.match filename
17
+ if /lib\/([^\/\-]+)-([\d\w\.\-]+)\/.+/.match filename
18
18
  name = $1
19
19
  version = $2
20
20
  else
@@ -63,11 +63,7 @@ module Jim
63
63
  end
64
64
 
65
65
  def each_file_in_index(ext, &block)
66
- @directories.each do |dir|
67
- Dir.glob(Pathname.new(dir) + '**' + "*#{ext}") do |filename|
68
- yield Pathname.new(filename)
69
- end
70
- end
66
+ Jim.each_path_in_directories(@directories, ext, [], &block)
71
67
  end
72
68
 
73
69
  end
data/lib/jim/installer.rb CHANGED
@@ -1,73 +1,148 @@
1
1
  module Jim
2
+ # Installer is the workhorse of Jim. It handles taking an install path
3
+ # (a url, a local path, anything that Downlow.get can handle), staging it
4
+ # into a temporary directory and extracting the file(s) into a path for the
5
+ # specific name and version of the lib. names and versions are determined
6
+ # automatically or can be passed in as options.
2
7
  class Installer
3
8
 
9
+ IGNORE_DIRS = %w{
10
+ vendor
11
+ external
12
+ test
13
+ tests
14
+ unit
15
+ site
16
+ examples
17
+ demo
18
+ min
19
+ \_([^\/]+)
20
+ \.([^\/]+)
21
+ }
22
+
23
+ # get the tmp_root where files are staged
4
24
  def self.tmp_root
5
25
  @tmp_root ||= Pathname.new('/tmp/jim')
6
26
  end
7
27
 
28
+ # set the tmp_root where files are staged. Default: '/tmp/jim'
8
29
  def self.tmp_root=(new_tmp_root)
9
30
  @tmp_root = Pathname.new(new_tmp_root)
10
31
  end
32
+
33
+ attr_reader :fetch_path, :install_path, :options, :fetched_path, :name, :version, :package_json
11
34
 
12
- attr_reader :fetch_path, :install_path, :options,
13
- :fetched_path, :name, :version
14
-
35
+ # create an installer. fetch_path is anything that Downlow can understand.
36
+ # install path is the final directory
15
37
  def initialize(fetch_path, install_path, options = {})
16
38
  @fetch_path = Pathname.new(fetch_path)
17
39
  @install_path = Pathname.new(install_path)
18
40
  @options = options
19
41
  end
20
42
 
43
+ # fetch the file at fetch_path with and stage into a tmp directory.
44
+ # returns the staged directory of fetched file(s).
21
45
  def fetch
22
46
  logger.info "fetching #{fetch_path}"
23
- @fetched_path = Downlow.get(fetch_path, tmp_path)
47
+ @fetched_path = Downlow.get(fetch_path, tmp_path, :tmp_dir => tmp_root)
24
48
  logger.debug "fetched #{@fetched_path}"
25
49
  @fetched_path
26
50
  end
27
51
 
52
+ # fetch and install the files determining their name and version if not provided.
53
+ # if the fetch_path contains a directory of files, it itterates over the directory
54
+ # installing each file that isn't in IGNORE_DIRS and a name and version can be
55
+ # determined for. It also installs a package.json file along side the JS file
56
+ # that contains meta data including the name and version, also merging with the
57
+ # original package.json if found.
58
+ #
59
+ # If options[:shallow] == true it will just copy the single file without any leading
60
+ # directories or a package.json. 'shallow' installation is used for Bundle#vendor
28
61
  def install
29
62
  fetch
63
+ parse_package_json
30
64
  determine_name_and_version
65
+
66
+ if !name || name.to_s =~ /^\s*$/ # blank
67
+ raise(Jim::InstallError, "could not determine name for #{@fetched_path}")
68
+ end
69
+
31
70
  logger.info "installing #{name} #{version}"
32
71
  logger.debug "fetched_path #{@fetched_path}"
72
+
33
73
  if options[:shallow]
34
- final_path = install_path + "#{name}#{fetched_path.extname}"
74
+ shallow_filename = [name, (version == "0" ? nil : version)].compact.join('-')
75
+ final_path = install_path + "#{shallow_filename}#{fetched_path.extname}"
35
76
  else
36
- final_dir = install_path + 'lib' + "#{name}-#{version}"
37
- final_path = (fetched_path.to_s =~ /\.js$/) ? final_dir + "#{name}.js" : final_dir
77
+ final_path = install_path + 'lib' + "#{name}-#{version}" + "#{name}.js"
38
78
  end
79
+
80
+ if @fetched_path.directory?
81
+ # install every js file
82
+ installed_paths = []
83
+ sub_options = options.merge({
84
+ :name => nil,
85
+ :version => nil,
86
+ :parent_version => version,
87
+ :package_json => package_json.merge("name" => nil)
88
+ })
89
+ Jim.each_path_in_directories([@fetched_path], '.js', IGNORE_DIRS) do |subfile|
90
+ logger.info "found file #{subfile}"
91
+ installed_paths << Jim::Installer.new(subfile, install_path, sub_options).install
92
+ end
93
+ logger.info "extracted to #{install_path}, #{installed_paths.length} file(s)"
94
+ return installed_paths
95
+ end
96
+
39
97
  logger.debug "installing to #{final_path}"
40
98
  if final_path.exist?
41
99
  logger.debug "#{final_path} already exists"
42
- options[:force] ? FileUtils.rm_rf(final_path) : raise(Jim::FileExists.new(final_path))
100
+ if options[:force]
101
+ FileUtils.rm_rf(final_path)
102
+ elsif Digest::MD5.hexdigest(File.read(final_path)) == Digest::MD5.hexdigest(File.read(@fetched_path))
103
+ logger.info "duplicate file, skipping"
104
+ return final_path
105
+ else
106
+ raise(Jim::FileExists.new(final_path))
107
+ end
43
108
  end
44
- Downlow.extract(@fetched_path, :destination => final_path)
109
+
110
+ Downlow.extract(@fetched_path, :destination => final_path, :tmp_dir => tmp_root)
111
+ # install json
112
+ install_package_json(final_path.dirname + 'package.json') if !options[:shallow]
45
113
  installed = final_path.directory? ? Dir.glob(final_path + '**/*').length : 1
46
- logger.info "Extracted to #{final_path}, #{installed} file(s)"
114
+ logger.info "extracted to #{final_path}, #{installed} file(s)"
47
115
  final_path
48
116
  ensure
49
- FileUtils.rm_rf(fetched_path) if fetched_path.exist?
117
+ FileUtils.rm_rf(@fetched_path) if @fetched_path && @fetched_path.exist?
50
118
  final_path
51
119
  end
52
-
120
+
121
+ # determine the name and version of the @fetched_path. Tries a number of
122
+ # strategies in order until both name and version are found:
123
+ #
124
+ # * from options (options[:name] ...)
125
+ # * from comments (// name: )
126
+ # * from a package.json ({"name": })
127
+ # * from the filename (name-1.0.js)
128
+ #
129
+ # If no version can be found, version is set as "0"
53
130
  def determine_name_and_version
54
131
  (name && version) ||
55
132
  name_and_version_from_options ||
56
133
  name_and_version_from_comments ||
57
134
  name_and_version_from_package_json ||
58
135
  name_and_version_from_filename
59
- @version ||= '0'
136
+ @version = (version == "0" && options[:parent_version]) ? options[:parent_version] : version
60
137
  end
61
138
 
62
139
  private
63
140
  def tmp_root
64
- self.class.tmp_root
141
+ @tmp_root ||= make_tmp_root
65
142
  end
66
143
 
67
144
  def tmp_dir
68
- dir = tmp_root + fetch_path.stem
69
- dir.mkpath
70
- dir
145
+ @tmp_dir ||= make_tmp_dir
71
146
  end
72
147
 
73
148
  def tmp_path
@@ -77,10 +152,51 @@ module Jim
77
152
  def logger
78
153
  Jim.logger
79
154
  end
155
+
156
+ def make_tmp_root
157
+ self.class.tmp_root + (Time.now.to_i + rand(10000)).to_s
158
+ end
159
+
160
+ def make_tmp_dir
161
+ dir = tmp_root + fetch_path.stem
162
+ dir.mkpath
163
+ dir
164
+ end
165
+
166
+ def parse_package_json
167
+ @package_json = @options[:package_json] || {}
168
+ package_json_path = if fetched_path.directory?
169
+ fetched_path + 'package.json'
170
+ elsif options[:shallow] && fetch_path.file?
171
+ fetch_path.dirname + 'package.json'
172
+ else
173
+ fetched_path.dirname + 'package.json'
174
+ end
175
+ logger.debug "package.json path: #{package_json_path}"
176
+ if package_json_path.readable?
177
+ @package_json = Yajl::Parser.parse(package_json_path.read)
178
+ end
179
+ end
180
+
181
+ def install_package_json(to_path, options = {})
182
+ hash = @package_json.merge({
183
+ "name" => name,
184
+ "version" => version,
185
+ "install" => {
186
+ "at" => Time.now.httpdate,
187
+ "from" => fetch_path,
188
+ "with" => "jim #{Jim::VERSION}"
189
+ }
190
+ }).merge(options)
191
+ Pathname.new(to_path).open('w') do |f|
192
+ Yajl::Encoder.encode(hash, f, :pretty => true)
193
+ end
194
+ end
80
195
 
81
196
  def name_and_version_from_options
82
197
  @name = options[:name] if options[:name] && !name
83
198
  @version = options[:version] if options[:version] && !version
199
+ logger.debug "name and version from options: #{name} #{version}"
84
200
  name && version
85
201
  end
86
202
 
@@ -97,15 +213,16 @@ module Jim
97
213
  end
98
214
  end
99
215
  end
216
+ logger.debug "name and version from comments: #{name} #{version}"
100
217
  name && version
101
218
  end
102
219
 
103
220
  def name_and_version_from_package_json
104
- if !fetched_path.file? && (fetched_path + 'package.json').readable?
105
- sname, sversion = VersionParser.parse_package_json((fetched_path + "package.json").read)
106
- @name ||= sname
107
- @version ||= sversion
108
- end
221
+ parse_package_json if !@package_json
222
+ sname, sversion = @package_json['name'], @package_json['version']
223
+ @name ||= sname
224
+ @version ||= sversion
225
+ logger.debug "name and version from package.json: #{name} #{version}"
109
226
  name && version
110
227
  end
111
228
 
@@ -113,6 +230,7 @@ module Jim
113
230
  fname, fversion = VersionParser.parse_filename(fetched_path.basename.to_s)
114
231
  @name ||= fname
115
232
  @version ||= fversion
233
+ logger.debug "name and version from filename: #{name} #{version}"
116
234
  name && version
117
235
  end
118
236