jim 0.1.2 → 0.2.0

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.
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