bpm 0.1.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 (261) hide show
  1. data/.gitignore +4 -0
  2. data/.gitmodules +0 -0
  3. data/Gemfile +16 -0
  4. data/README.md +55 -0
  5. data/TODO.md +3 -0
  6. data/bin/bpm +8 -0
  7. data/bpm.gemspec +41 -0
  8. data/lib/bpm.rb +18 -0
  9. data/lib/bpm/cli.rb +6 -0
  10. data/lib/bpm/cli/base.rb +358 -0
  11. data/lib/bpm/cli/owner.rb +46 -0
  12. data/lib/bpm/credentials.rb +36 -0
  13. data/lib/bpm/default.json +9 -0
  14. data/lib/bpm/generator.rb +69 -0
  15. data/lib/bpm/init_generator.rb +43 -0
  16. data/lib/bpm/libgems_ext.rb +11 -0
  17. data/lib/bpm/libgems_ext/config_file.rb +33 -0
  18. data/lib/bpm/libgems_ext/dependency_installer.rb +150 -0
  19. data/lib/bpm/libgems_ext/installer.rb +39 -0
  20. data/lib/bpm/libgems_ext/libgems.rb +39 -0
  21. data/lib/bpm/libgems_ext/spec_fetcher.rb +11 -0
  22. data/lib/bpm/local.rb +76 -0
  23. data/lib/bpm/package.rb +277 -0
  24. data/lib/bpm/pipeline.rb +100 -0
  25. data/lib/bpm/pipeline/directive_processor.rb +47 -0
  26. data/lib/bpm/pipeline/generated_asset.rb +68 -0
  27. data/lib/bpm/pipeline/transport_processor.rb +32 -0
  28. data/lib/bpm/project.rb +427 -0
  29. data/lib/bpm/project_generator.rb +34 -0
  30. data/lib/bpm/remote.rb +104 -0
  31. data/lib/bpm/repository.rb +18 -0
  32. data/lib/bpm/server.rb +44 -0
  33. data/lib/bpm/version.rb +3 -0
  34. data/spec/cli/add_spec.rb +159 -0
  35. data/spec/cli/build_spec.rb +87 -0
  36. data/spec/cli/fetch_spec.rb +135 -0
  37. data/spec/cli/fetched_spec.rb +52 -0
  38. data/spec/cli/init_spec.rb +50 -0
  39. data/spec/cli/list_spec.rb +74 -0
  40. data/spec/cli/login_spec.rb +110 -0
  41. data/spec/cli/new_spec.rb +92 -0
  42. data/spec/cli/owner_spec.rb +114 -0
  43. data/spec/cli/push_spec.rb +73 -0
  44. data/spec/cli/remove_spec.rb +84 -0
  45. data/spec/cli/unpack_spec.rb +72 -0
  46. data/spec/cli/unyank_spec.rb +73 -0
  47. data/spec/cli/yank_spec.rb +73 -0
  48. data/spec/credentials_spec.rb +23 -0
  49. data/spec/fixtures/badrake-0.8.7.spd +0 -0
  50. data/spec/fixtures/builder-3.0.0.spd +0 -0
  51. data/spec/fixtures/bundler-1.1.pre.spd +0 -0
  52. data/spec/fixtures/coffee-1.0.1.pre.spd +0 -0
  53. data/spec/fixtures/core-test-0.4.9.spd +0 -0
  54. data/spec/fixtures/core-test/bin/cot +3 -0
  55. data/spec/fixtures/core-test/lib/main.js +1 -0
  56. data/spec/fixtures/core-test/package.json +46 -0
  57. data/spec/fixtures/core-test/resources/runner.css +1 -0
  58. data/spec/fixtures/core-test/tests/test.js +1 -0
  59. data/spec/fixtures/custom_generator-1.0.spd +0 -0
  60. data/spec/fixtures/custom_generator/lib/main.js +1 -0
  61. data/spec/fixtures/custom_generator/package.json +12 -0
  62. data/spec/fixtures/custom_generator/templates/init/project.json +19 -0
  63. data/spec/fixtures/custom_generator/templates/project/app.js +1 -0
  64. data/spec/fixtures/custom_generator/templates/project/lib/main.js +0 -0
  65. data/spec/fixtures/custom_generator/templates/project_generator.rb +20 -0
  66. data/spec/fixtures/hello_world/LICENSE +19 -0
  67. data/spec/fixtures/hello_world/README.md +21 -0
  68. data/spec/fixtures/hello_world/assets/bpm_packages.js +13 -0
  69. data/spec/fixtures/hello_world/assets/bpm_styles.css +14 -0
  70. data/spec/fixtures/hello_world/assets/papa-smurf.jpg +0 -0
  71. data/spec/fixtures/hello_world/hello_world.json +20 -0
  72. data/spec/fixtures/hello_world/lib/main.js +9 -0
  73. data/spec/fixtures/hello_world/packages/custom_package/assets/dummy.txt +1 -0
  74. data/spec/fixtures/hello_world/packages/custom_package/css/sample_styles.css +3 -0
  75. data/spec/fixtures/hello_world/packages/custom_package/custom_dir/basic-module.js +1 -0
  76. data/spec/fixtures/hello_world/packages/custom_package/lib/main.js +1 -0
  77. data/spec/fixtures/hello_world/packages/custom_package/package.json +22 -0
  78. data/spec/fixtures/hello_world/tests/main-test.js +8 -0
  79. data/spec/fixtures/highline-1.6.1.spd +0 -0
  80. data/spec/fixtures/ivory-0.0.1.spd +0 -0
  81. data/spec/fixtures/jquery-1.4.3.spd +0 -0
  82. data/spec/fixtures/optparse-1.0.1.spd +0 -0
  83. data/spec/fixtures/rake-0.8.6.spd +0 -0
  84. data/spec/fixtures/rake-0.8.7.spd +0 -0
  85. data/spec/fixtures/simple_hello/assets/bpm_packages.js +1 -0
  86. data/spec/fixtures/simple_hello/lib/main.js +1 -0
  87. data/spec/fixtures/spade-0.5.0.spd +0 -0
  88. data/spec/fixtures/src/README.txt +1 -0
  89. data/spec/fixtures/src/bundler-1.1.pre/.gitignore +22 -0
  90. data/spec/fixtures/src/bundler-1.1.pre/CHANGELOG.md +646 -0
  91. data/spec/fixtures/src/bundler-1.1.pre/ISSUES.md +47 -0
  92. data/spec/fixtures/src/bundler-1.1.pre/LICENSE +21 -0
  93. data/spec/fixtures/src/bundler-1.1.pre/README.md +29 -0
  94. data/spec/fixtures/src/bundler-1.1.pre/UPGRADING.md +103 -0
  95. data/spec/fixtures/src/bundler-1.1.pre/bin/bundle +20 -0
  96. data/spec/fixtures/src/bundler-1.1.pre/lib/bundler.js +23 -0
  97. data/spec/fixtures/src/bundler-1.1.pre/lib/bundler/definition.js +14 -0
  98. data/spec/fixtures/src/bundler-1.1.pre/lib/bundler/dependency.js +15 -0
  99. data/spec/fixtures/src/bundler-1.1.pre/lib/bundler/dsl.js +9 -0
  100. data/spec/fixtures/src/bundler-1.1.pre/lib/bundler/ui.js +6 -0
  101. data/spec/fixtures/src/bundler-1.1.pre/man/bundle-config.ronn +90 -0
  102. data/spec/fixtures/src/bundler-1.1.pre/man/bundle-exec.ronn +111 -0
  103. data/spec/fixtures/src/bundler-1.1.pre/man/bundle-install.ronn +314 -0
  104. data/spec/fixtures/src/bundler-1.1.pre/man/bundle-package.ronn +59 -0
  105. data/spec/fixtures/src/bundler-1.1.pre/man/bundle-update.ronn +176 -0
  106. data/spec/fixtures/src/bundler-1.1.pre/man/bundle.ronn +80 -0
  107. data/spec/fixtures/src/bundler-1.1.pre/man/gemfile.5.ronn +279 -0
  108. data/spec/fixtures/src/bundler-1.1.pre/man/index.txt +6 -0
  109. data/spec/fixtures/src/bundler-1.1.pre/package.json +19 -0
  110. data/spec/fixtures/src/coffee-1.0.1.pre/bin/cake +0 -0
  111. data/spec/fixtures/src/coffee-1.0.1.pre/bin/coffee +0 -0
  112. data/spec/fixtures/src/coffee-1.0.1.pre/lib/coffee.js +0 -0
  113. data/spec/fixtures/src/coffee-1.0.1.pre/lib/coffee/base.js +0 -0
  114. data/spec/fixtures/src/coffee-1.0.1.pre/lib/coffee/mocha/chai.js +0 -0
  115. data/spec/fixtures/src/coffee-1.0.1.pre/package.json +19 -0
  116. data/spec/fixtures/src/coffee-1.0.1.pre/qunit/coffee/test.js +0 -0
  117. data/spec/fixtures/src/coffee-1.0.1.pre/qunit/test.js +0 -0
  118. data/spec/fixtures/src/jquery/lib/main.js +7179 -0
  119. data/spec/fixtures/src/jquery/package.json +15 -0
  120. data/spec/fixtures/src/rake-0.8.6/CHANGES +436 -0
  121. data/spec/fixtures/src/rake-0.8.6/MIT-LICENSE +21 -0
  122. data/spec/fixtures/src/rake-0.8.6/README +196 -0
  123. data/spec/fixtures/src/rake-0.8.6/Rakefile +430 -0
  124. data/spec/fixtures/src/rake-0.8.6/TODO +20 -0
  125. data/spec/fixtures/src/rake-0.8.6/bin/rake +31 -0
  126. data/spec/fixtures/src/rake-0.8.6/doc/command_line_usage.rdoc +102 -0
  127. data/spec/fixtures/src/rake-0.8.6/doc/example/Rakefile1 +38 -0
  128. data/spec/fixtures/src/rake-0.8.6/doc/example/Rakefile2 +35 -0
  129. data/spec/fixtures/src/rake-0.8.6/doc/example/a.c +6 -0
  130. data/spec/fixtures/src/rake-0.8.6/doc/example/b.c +6 -0
  131. data/spec/fixtures/src/rake-0.8.6/doc/example/main.c +11 -0
  132. data/spec/fixtures/src/rake-0.8.6/doc/glossary.rdoc +51 -0
  133. data/spec/fixtures/src/rake-0.8.6/doc/jamis.rb +591 -0
  134. data/spec/fixtures/src/rake-0.8.6/doc/proto_rake.rdoc +127 -0
  135. data/spec/fixtures/src/rake-0.8.6/doc/rake.1.gz +0 -0
  136. data/spec/fixtures/src/rake-0.8.6/doc/rakefile.rdoc +534 -0
  137. data/spec/fixtures/src/rake-0.8.6/doc/rational.rdoc +151 -0
  138. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.4.14.rdoc +23 -0
  139. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.4.15.rdoc +35 -0
  140. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.5.0.rdoc +53 -0
  141. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.5.3.rdoc +78 -0
  142. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.5.4.rdoc +46 -0
  143. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.6.0.rdoc +141 -0
  144. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.7.0.rdoc +119 -0
  145. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.7.1.rdoc +59 -0
  146. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.7.2.rdoc +121 -0
  147. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.7.3.rdoc +47 -0
  148. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.0.rdoc +114 -0
  149. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.2.rdoc +165 -0
  150. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.3.rdoc +112 -0
  151. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.4.rdoc +147 -0
  152. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.5.rdoc +53 -0
  153. data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.6.rdoc +55 -0
  154. data/spec/fixtures/src/rake-0.8.6/install.rb +88 -0
  155. data/spec/fixtures/src/rake-0.8.6/lib/rake.rb +2502 -0
  156. data/spec/fixtures/src/rake-0.8.6/lib/rake/alt_system.rb +108 -0
  157. data/spec/fixtures/src/rake-0.8.6/lib/rake/classic_namespace.rb +8 -0
  158. data/spec/fixtures/src/rake-0.8.6/lib/rake/clean.rb +33 -0
  159. data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/compositepublisher.rb +24 -0
  160. data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/ftptools.rb +153 -0
  161. data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/publisher.rb +75 -0
  162. data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/rubyforgepublisher.rb +18 -0
  163. data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/sshpublisher.rb +47 -0
  164. data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/sys.rb +209 -0
  165. data/spec/fixtures/src/rake-0.8.6/lib/rake/gempackagetask.rb +97 -0
  166. data/spec/fixtures/src/rake-0.8.6/lib/rake/loaders/makefile.rb +42 -0
  167. data/spec/fixtures/src/rake-0.8.6/lib/rake/packagetask.rb +184 -0
  168. data/spec/fixtures/src/rake-0.8.6/lib/rake/rake_test_loader.rb +5 -0
  169. data/spec/fixtures/src/rake-0.8.6/lib/rake/rdoctask.rb +209 -0
  170. data/spec/fixtures/src/rake-0.8.6/lib/rake/ruby182_test_unit_fix.rb +23 -0
  171. data/spec/fixtures/src/rake-0.8.6/lib/rake/runtest.rb +23 -0
  172. data/spec/fixtures/src/rake-0.8.6/lib/rake/tasklib.rb +23 -0
  173. data/spec/fixtures/src/rake-0.8.6/lib/rake/testtask.rb +161 -0
  174. data/spec/fixtures/src/rake-0.8.6/lib/rake/win32.rb +55 -0
  175. data/spec/fixtures/src/rake-0.8.6/package.json +18 -0
  176. data/spec/fixtures/src/rake-0.8.6/test/capture_stdout.rb +26 -0
  177. data/spec/fixtures/src/rake-0.8.7/CHANGES +440 -0
  178. data/spec/fixtures/src/rake-0.8.7/MIT-LICENSE +21 -0
  179. data/spec/fixtures/src/rake-0.8.7/README +196 -0
  180. data/spec/fixtures/src/rake-0.8.7/Rakefile +430 -0
  181. data/spec/fixtures/src/rake-0.8.7/TODO +20 -0
  182. data/spec/fixtures/src/rake-0.8.7/bin/rake +31 -0
  183. data/spec/fixtures/src/rake-0.8.7/doc/command_line_usage.rdoc +102 -0
  184. data/spec/fixtures/src/rake-0.8.7/doc/example/Rakefile1 +38 -0
  185. data/spec/fixtures/src/rake-0.8.7/doc/example/Rakefile2 +35 -0
  186. data/spec/fixtures/src/rake-0.8.7/doc/example/a.c +6 -0
  187. data/spec/fixtures/src/rake-0.8.7/doc/example/b.c +6 -0
  188. data/spec/fixtures/src/rake-0.8.7/doc/example/main.c +11 -0
  189. data/spec/fixtures/src/rake-0.8.7/doc/glossary.rdoc +51 -0
  190. data/spec/fixtures/src/rake-0.8.7/doc/jamis.rb +591 -0
  191. data/spec/fixtures/src/rake-0.8.7/doc/proto_rake.rdoc +127 -0
  192. data/spec/fixtures/src/rake-0.8.7/doc/rake.1.gz +0 -0
  193. data/spec/fixtures/src/rake-0.8.7/doc/rakefile.rdoc +534 -0
  194. data/spec/fixtures/src/rake-0.8.7/doc/rational.rdoc +151 -0
  195. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.4.14.rdoc +23 -0
  196. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.4.15.rdoc +35 -0
  197. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.5.0.rdoc +53 -0
  198. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.5.3.rdoc +78 -0
  199. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.5.4.rdoc +46 -0
  200. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.6.0.rdoc +141 -0
  201. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.7.0.rdoc +119 -0
  202. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.7.1.rdoc +59 -0
  203. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.7.2.rdoc +121 -0
  204. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.7.3.rdoc +47 -0
  205. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.0.rdoc +114 -0
  206. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.2.rdoc +165 -0
  207. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.3.rdoc +112 -0
  208. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.4.rdoc +147 -0
  209. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.5.rdoc +53 -0
  210. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.6.rdoc +55 -0
  211. data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.7.rdoc +55 -0
  212. data/spec/fixtures/src/rake-0.8.7/install.rb +88 -0
  213. data/spec/fixtures/src/rake-0.8.7/lib/rake.rb +2506 -0
  214. data/spec/fixtures/src/rake-0.8.7/lib/rake/alt_system.rb +108 -0
  215. data/spec/fixtures/src/rake-0.8.7/lib/rake/classic_namespace.rb +8 -0
  216. data/spec/fixtures/src/rake-0.8.7/lib/rake/clean.rb +33 -0
  217. data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/compositepublisher.rb +24 -0
  218. data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/ftptools.rb +153 -0
  219. data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/publisher.rb +75 -0
  220. data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/rubyforgepublisher.rb +18 -0
  221. data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/sshpublisher.rb +47 -0
  222. data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/sys.rb +209 -0
  223. data/spec/fixtures/src/rake-0.8.7/lib/rake/gempackagetask.rb +97 -0
  224. data/spec/fixtures/src/rake-0.8.7/lib/rake/loaders/makefile.rb +42 -0
  225. data/spec/fixtures/src/rake-0.8.7/lib/rake/packagetask.rb +184 -0
  226. data/spec/fixtures/src/rake-0.8.7/lib/rake/rake_test_loader.rb +5 -0
  227. data/spec/fixtures/src/rake-0.8.7/lib/rake/rdoctask.rb +209 -0
  228. data/spec/fixtures/src/rake-0.8.7/lib/rake/ruby182_test_unit_fix.rb +23 -0
  229. data/spec/fixtures/src/rake-0.8.7/lib/rake/runtest.rb +23 -0
  230. data/spec/fixtures/src/rake-0.8.7/lib/rake/tasklib.rb +23 -0
  231. data/spec/fixtures/src/rake-0.8.7/lib/rake/testtask.rb +161 -0
  232. data/spec/fixtures/src/rake-0.8.7/lib/rake/win32.rb +55 -0
  233. data/spec/fixtures/src/rake-0.8.7/package.json +18 -0
  234. data/spec/fixtures/src/rake-0.8.7/test/capture_stdout.rb +26 -0
  235. data/spec/fixtures/src/spade/lib/main.js +1 -0
  236. data/spec/fixtures/src/spade/package.json +15 -0
  237. data/spec/fixtures/transporter/lib/main.js +3 -0
  238. data/spec/fixtures/transporter/packages/transport/lib/wrapper.js +5 -0
  239. data/spec/fixtures/transporter/packages/transport/package.json +21 -0
  240. data/spec/fixtures/transporter/transporter.json +18 -0
  241. data/spec/gauntlet_spec.rb +33 -0
  242. data/spec/package_spec.rb +319 -0
  243. data/spec/pipeline_spec.rb +213 -0
  244. data/spec/project_spec.rb +130 -0
  245. data/spec/spec_helper.rb +42 -0
  246. data/spec/support/cli.rb +93 -0
  247. data/spec/support/env.rb +18 -0
  248. data/spec/support/fake.rb +53 -0
  249. data/spec/support/fake_gem_server.rb +72 -0
  250. data/spec/support/fake_gemcutter.rb +50 -0
  251. data/spec/support/matchers.rb +32 -0
  252. data/spec/support/path.rb +63 -0
  253. data/spec/support/project.rb +43 -0
  254. data/templates/init/assets/bpm_packages.js +7 -0
  255. data/templates/init/assets/bpm_styles.css +7 -0
  256. data/templates/init/project.json +16 -0
  257. data/templates/project/LICENSE +19 -0
  258. data/templates/project/README.md +21 -0
  259. data/templates/project/app.js +1 -0
  260. data/templates/project/index.html +13 -0
  261. metadata +627 -0
@@ -0,0 +1,47 @@
1
+ require 'sprockets'
2
+
3
+ module BPM
4
+
5
+ # Like the regular directive processor but knows how to resolve directives
6
+ # as module ids, not just file paths
7
+ class DirectiveProcessor < Sprockets::DirectiveProcessor
8
+
9
+ def process_require_directive(path)
10
+ project = context.environment.project
11
+ module_path = project.path_from_module(path)
12
+ path = context.resolve(module_path) rescue path
13
+ context.require_asset(path)
14
+ end
15
+
16
+ def process_require_tree_directive(path = ".")
17
+ if relative?(path)
18
+ super path
19
+ else
20
+ project = context.environment.project
21
+ module_path = project.path_from_module path
22
+ root = module_path.sub(/^([^\/]+)\//) do |s|
23
+ project.path_from_package s
24
+ end
25
+
26
+ context.depend_on(root)
27
+
28
+ Dir["#{root}/**/*"].sort.each do |filename|
29
+ if filename == self.file
30
+ next
31
+ elsif File.directory?(filename)
32
+ context.depend_on(filename)
33
+ elsif context.asset_requirable?(filename)
34
+ context.require_asset(filename)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+ def relative?(path)
42
+ path =~ /^\.($|\.?\/)/
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,68 @@
1
+ require 'sprockets'
2
+
3
+ module BPM
4
+
5
+ class GeneratedAsset < Sprockets::BundledAsset
6
+
7
+ FORMAT_METHODS = {
8
+ 'text/css' => ['css', 'pipeline_css'],
9
+ 'application/javascript' => ['lib', 'pipeline_libs']
10
+ }
11
+
12
+ protected
13
+
14
+ def dependency_context_and_body
15
+ @dependency_context_and_body ||= build_dependency_context_and_body
16
+ end
17
+
18
+ private
19
+
20
+ def build_dependency_context_and_body
21
+
22
+ project = environment.project
23
+ if project.local_deps.size > 0
24
+ manifest = project.local_deps.map do |x|
25
+ "#{x.name} (#{x.version})"
26
+ end.join " "
27
+ else
28
+ manifest = "(none)"
29
+ end
30
+
31
+ # Add in the generated header
32
+ body = <<EOF
33
+ /* ===========================================================================
34
+ BPM Static Dependencies
35
+ MANIFEST: #{manifest}
36
+ This file is generated automatically by the bpm (http://www.bpmjs.org)
37
+ To use this file, load this file in your HTML head.
38
+ =========================================================================*/
39
+
40
+ EOF
41
+
42
+ # Prime digest cache with data, since we happen to have it
43
+ environment.file_digest(pathname, body)
44
+
45
+ # add requires for each depedency to context
46
+ context = blank_context
47
+ context.require_asset(pathname) # start with self
48
+
49
+ dir_name, dir_method = FORMAT_METHODS[content_type] || ['lib', 'pipeline_libs']
50
+
51
+ project.local_deps.map do |pkg|
52
+ pkg.load_json
53
+ pkg.send(dir_method).each do |dir|
54
+ dir_name = pkg.directories[dir] || dir
55
+ search_path = File.expand_path File.join(pkg.root_path, dir_name)
56
+
57
+ Dir[File.join(search_path, '**', '*')].sort.each do |fn|
58
+ context.depend_on File.dirname(fn)
59
+ context.require_asset(fn) if context.asset_requirable? fn
60
+ end
61
+ end
62
+ end
63
+
64
+ return context, body
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,32 @@
1
+ require 'sprockets'
2
+
3
+ module BPM
4
+
5
+ class TransportProcessor < Sprockets::Processor
6
+
7
+ def evaluate(context, locals)
8
+ project = context.environment.project
9
+ pkg, module_id = project.package_and_module_from_path file
10
+ transport_plugins = pkg.transport_plugins(project)
11
+
12
+ if transport_plugins.size > 1
13
+ raise "#{pkg.name} depends on #{transport_plugins.size} packages that define transport plugins. Select a plugin by adding a `plugin:transport` property to the package.json"
14
+ elsif transport_plugins.size == 1
15
+ transport_module = transport_plugins.first
16
+
17
+ transport_path = context.resolve project.path_from_module(transport_module)
18
+
19
+ ctx = context.environment.js_context_for transport_path
20
+ ctx["PACKAGE_INFO"] = pkg.attributes
21
+ ctx["DATA"] = data
22
+ wrapped = ctx.eval "exports.compileTransport(DATA, PACKAGE_INFO, '#{module_id}');"
23
+
24
+ wrapped
25
+ else
26
+ data
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,427 @@
1
+ require 'json'
2
+
3
+ module BPM
4
+
5
+ class Project < Package
6
+
7
+ DEFAULT_CONFIG_PATH = File.expand_path('../default.json', __FILE__)
8
+ DEFAULT_CONFIG = JSON.load File.read(DEFAULT_CONFIG_PATH)
9
+ BPM_DIR = '.bpm'
10
+
11
+ def self.project_file_path(path)
12
+ json_path = File.join path, "#{File.basename(path)}.json"
13
+ json = JSON.load(File.read(json_path)) rescue nil
14
+ return json && json["bpm"] && json_path
15
+ end
16
+
17
+ def self.is_project_root?(path)
18
+ !!project_file_path(path) ||
19
+ File.exists?(File.join(path, 'assets', 'bpm_packages.js'))
20
+ end
21
+
22
+ def self.nearest_project(path)
23
+ path = File.expand_path path
24
+
25
+ last = nil
26
+ while path != last
27
+ return new(path) if is_project_root?(path)
28
+ last = path
29
+ path = File.dirname path
30
+ end
31
+ nil
32
+ end
33
+
34
+ attr_reader :name
35
+
36
+ def initialize(root_path, name=nil)
37
+ super root_path
38
+
39
+ @name = name || File.basename(root_path)
40
+ @json_path = File.join root_path, "#{@name}.json"
41
+
42
+ load_json && validate
43
+ end
44
+
45
+ def add_dependencies(new_deps, verbose=false)
46
+
47
+ old_deps = build_local_deps(false) || []
48
+
49
+ hard_deps = dependencies.dup
50
+ new_deps.each { |pkg_name, pkg_vers| hard_deps[pkg_name] = pkg_vers }
51
+
52
+ exp_deps = expand_local_packages hard_deps, true
53
+ core_fetch_dependencies exp_deps, :runtime, true
54
+
55
+ @dependencies = hard_deps
56
+ rebuild_dependencies hard_deps, verbose
57
+
58
+ local_deps.each do |dep|
59
+ next if old_deps.find { |pkg| (pkg.name == dep.name) && (pkg.version == dep.version) }
60
+ puts "Added package '#{dep.name}' (#{dep.version})"
61
+ end
62
+
63
+ save!
64
+
65
+ end
66
+
67
+ def remove_dependencies(package_names, verbose=false)
68
+
69
+ hard_deps = dependencies.dup
70
+ old_deps = build_local_deps false
71
+
72
+ package_names.each do |pkg_name|
73
+ raise "'#{pkg_name}' is not a dependency" if hard_deps[pkg_name].nil?
74
+ hard_deps.delete pkg_name
75
+ end
76
+
77
+ @dependencies = hard_deps
78
+ rebuild_dependencies hard_deps, verbose
79
+
80
+ old_deps.each do |dep|
81
+ next if local_deps.find { |pkg| (pkg.name == dep.name) && (pkg.version == dep.version) }
82
+ puts "Removed package '#{dep.name}' (#{dep.version})"
83
+ end
84
+
85
+ save!
86
+
87
+ end
88
+
89
+ def save!
90
+ @had_changes = false
91
+ File.open @json_path, 'w+' do |fd|
92
+ fd.write JSON.pretty_generate as_json
93
+ end
94
+ end
95
+
96
+ def fetch_dependencies(verbose=false)
97
+ core_fetch_dependencies(dependencies, :runtime, verbose)
98
+ end
99
+
100
+ # Builds assets directory for dependent packages
101
+ def build(mode=:debug, verbose=false)
102
+ puts "Building static assets..." if verbose
103
+ pipeline = BPM::Pipeline.new self
104
+ asset_root = File.join root_path, 'assets'
105
+
106
+ pipeline.buildable_assets.each do |asset|
107
+ dst_path = File.join asset_root, asset.logical_path
108
+ FileUtils.mkdir_p File.dirname(dst_path)
109
+
110
+ if asset.kind_of? Sprockets::StaticAsset
111
+ puts "~ Copying #{asset.logical_path}" if verbose
112
+ FileUtils.rm dst_path if File.exists? dst_path
113
+ FileUtils.cp asset.pathname, dst_path
114
+ else
115
+ puts "~ Building #{asset.logical_path}" if verbose
116
+ File.open(dst_path, 'w+') { |fd| fd << asset.to_s }
117
+ end
118
+ end
119
+
120
+ puts "\n" if verbose
121
+ end
122
+
123
+ # Removes any built assets from the project. Usually called before a
124
+ # package is removed from the project to cleanup any assets
125
+ def unbuild(verbose=false)
126
+
127
+ puts "Removing stale assets..." if verbose
128
+
129
+ pipeline = BPM::Pipeline.new self
130
+ asset_root = File.join root_path, 'assets'
131
+ pipeline.buildable_assets.each do |asset|
132
+ next if asset.logical_path =~ /^bpm_/
133
+ asset_path = File.join asset_root, asset.logical_path
134
+ next unless File.exists? asset_path
135
+ puts "~ Removing #{asset.logical_path}" if verbose
136
+ FileUtils.rm asset_path
137
+
138
+ # cleanup empty directories
139
+ while !File.exists?(asset_path)
140
+ asset_path = File.dirname asset_path
141
+ FileUtils.rmdir(asset_path) if File.directory?(asset_path)
142
+ if verbose && !File.exists?(asset_path)
143
+ puts "~ Removed empty directory #{File.basename asset_path}"
144
+ end
145
+ end
146
+ end
147
+
148
+ puts "\n" if verbose
149
+ end
150
+
151
+ # Returns the path on disk to reach a given package name
152
+ def path_from_package(package_name)
153
+ return root_path if package_name == self.name
154
+ path = local_deps.find { |pkg| pkg.name == package_name }
155
+ path && path.root_path
156
+ end
157
+
158
+ # Returns the path on disk for a given module id (relative to the project)
159
+ def path_from_module(module_path)
160
+ path_parts = module_path.to_s.split '/'
161
+ package_name = path_parts.shift
162
+ module_path = path_from_package(package_name)
163
+ if module_path
164
+ # expand package_name => package_name/main
165
+ path_parts = ['main'] if path_parts.size == 0
166
+
167
+ # expand package_name/~dirname => package_name/mapped_dirname
168
+ if path_parts.first && path_parts.first =~ /^~/
169
+ dirname = path_parts.shift[1..-1]
170
+ else
171
+ dirname = 'lib'
172
+ end
173
+ pkg = BPM::Package.new(module_path)
174
+ pkg.load_json
175
+ dirname = (pkg && pkg.directories[dirname]) || dirname
176
+
177
+ # join the rest of the path
178
+ module_path = [package_name, dirname, *path_parts] * '/'
179
+ end
180
+
181
+ module_path
182
+ end
183
+
184
+ # Returns the package object and module id for the path. Path must match
185
+ # a package known to the project.
186
+ def package_and_module_from_path(path)
187
+ path = File.expand_path path.to_s
188
+ pkg = local_deps.find {|cur| path =~ /^#{Regexp.escape cur.root_path.to_s}/}
189
+ pkg = self if pkg.nil? && path =~ /^#{Regexp.escape root_path.to_s}/
190
+ raise "#{path} is not within a known package" if pkg.nil?
191
+
192
+ path = Pathname.new(path).relative_path_from(Pathname.new(pkg.root_path)).split.map { |x| x.to_s }
193
+
194
+ dir_name = pkg.directories.find do |dir_key, dname|
195
+ Array(dname).include?(path.first)
196
+ end
197
+
198
+ dir_name = dir_name ? dir_name.first : path.first
199
+ if dir_name == 'lib'
200
+ path.shift
201
+ else
202
+ path[0] = "~#{dir_name}"
203
+ end
204
+
205
+ path[path.size-1] = File.basename path.last, '.*'
206
+ [pkg, path.join('/')]
207
+ end
208
+
209
+ def local_deps(verbose=false)
210
+ @local_deps ||= build_local_deps
211
+ end
212
+
213
+
214
+ # Verifies that packages are available to meet all the dependencies
215
+ def rebuild_dependencies(deps=nil, verbose=false)
216
+
217
+ puts "Selecting local dependencies..." if verbose
218
+
219
+ found = locate_dependencies deps||dependencies, verbose
220
+
221
+ install_root = File.join root_path, '.bpm', 'packages'
222
+ FileUtils.rm_r install_root if File.exists? install_root
223
+ FileUtils.mkdir_p install_root
224
+
225
+ found.each do |pkg|
226
+ dst_path = File.join install_root, pkg.name
227
+ FileUtils.ln_s pkg.root_path, dst_path
228
+ end
229
+
230
+ @local_deps = nil
231
+ end
232
+
233
+ private
234
+
235
+ def read
236
+ if File.exists? @json_path
237
+ super
238
+ else
239
+ @attributes = DEFAULT_CONFIG.dup
240
+ @attributes["name"] = File.basename(@json_path, '.json')
241
+ @attributes["version"] = "0.0.1"
242
+ end
243
+ end
244
+
245
+ def validate_fields
246
+ # TODO: Define other fields that are required for projects
247
+ %w[name].all? do |field|
248
+ value = send(field)
249
+ if value.nil? || value.size.zero?
250
+ add_error "Projects requires a '#{field}' field"
251
+ else
252
+ true
253
+ end
254
+ end
255
+ end
256
+
257
+ # builds a set of dependencies that excludes locally installed packages
258
+ # and includes their dependencies instead.
259
+ def expand_local_packages(deps, verbose)
260
+ ret = {}
261
+
262
+ todo = []
263
+ seen = []
264
+
265
+ deps.each { |pkg_name, pkg_version| todo << [pkg_name, pkg_version] }
266
+
267
+ while todo.size > 0
268
+ package_name, package_version = todo.shift
269
+ next if seen.include? package_name
270
+ seen << package_name
271
+
272
+ package_root = File.join(@root_path, 'packages', package_name)
273
+
274
+ if File.exists? package_root
275
+ pkg = BPM::Package.new package_root
276
+ pkg.load_json
277
+
278
+ req = LibGems::Requirement.new(package_version)
279
+ unless req.satisfied_by? LibGems::Version.new(pkg.version)
280
+ raise "Local package '#{pkg.name}' (#{pkg.version}) is not compatible with required version #{package_version}"
281
+ end
282
+
283
+ puts "~ Using local package '#{pkg.name}' (#{pkg.version})" if verbose
284
+ pkg.dependencies.each do |pkg_name, pkg_vers|
285
+ todo << [pkg_name, pkg_vers]
286
+ end
287
+
288
+ else
289
+ ret[package_name] = package_version
290
+ end
291
+ end
292
+
293
+ ret
294
+ end
295
+
296
+ # Fetch any dependencies into local cache for the passed set of deps
297
+ def core_fetch_dependencies(deps, kind, verbose)
298
+ puts "Fetching packages from remote..." if verbose
299
+ deps.each do |pkg_name, pkg_version|
300
+ core_fetch_dependency pkg_name, pkg_version, kind, verbose
301
+ end
302
+ end
303
+
304
+ def core_fetch_dependency(package_name, vers, kind, verbose)
305
+
306
+ prerelease = false
307
+ if vers == '>= 0-pre'
308
+ prerelease = true
309
+ vers = '>= 0'
310
+ else
311
+ prerelease = vers =~ /[a-zA-Z]/
312
+ end
313
+
314
+ dep = LibGems::Dependency.new(package_name, vers, kind)
315
+ cur_installed = LibGems.source_index.search(dep)
316
+
317
+ # TODO: Why are we fetching even if we already have it? Are we looking for newer versions?
318
+ installed = BPM::Remote.new.install(package_name, vers, prerelease)
319
+
320
+ cur_installed.each do |ci|
321
+ installed.reject! { |i| ci.name == i.name && ci.version == i.version }
322
+ end
323
+
324
+ installed.each do |i|
325
+ puts "Fetched #{i.name} (#{i.version}) from remote" if verbose
326
+ end
327
+
328
+ end
329
+
330
+ def build_local_deps(force=true)
331
+ install_root = File.join root_path, '.bpm', 'packages'
332
+ unless File.exists? install_root
333
+ return nil if !force
334
+ rebuild_dependencies
335
+ end
336
+
337
+ Dir[File.join(install_root, '*')].map do |package_name|
338
+ pkg = BPM::Package.new package_name
339
+ pkg.load_json
340
+ pkg
341
+ end
342
+ end
343
+
344
+ def has_local_package?(package_name)
345
+ package_root = File.join @root_path, 'packages', package_name
346
+ File.exists? package_root
347
+ end
348
+
349
+ def satisfied_by?(req_vers, new_vers)
350
+ req = LibGems::Requirement.new req_vers
351
+ req_vers.sub(/^= /,'') == new_vers.sub(/^= /,'') ||
352
+ req.satisfied_by?(LibGems::Version.new(new_vers))
353
+ end
354
+
355
+ def clean_version(vers)
356
+ if vers == '>= 0-pre'
357
+ prerel = true
358
+ vers = '>= 0'
359
+ else
360
+ prerel = vers =~ /[a-zA-Z]/
361
+ end
362
+ [vers, prerel]
363
+ end
364
+
365
+ def locate_dependencies(deps, verbose)
366
+ todo = []
367
+ seen = []
368
+ ret = []
369
+
370
+ deps.each { |package_name, vers| todo << [package_name, vers] }
371
+
372
+ while todo.size > 0
373
+ package_name, vers = todo.shift
374
+
375
+ if seen.include? package_name
376
+
377
+ # already seen - verify requirements are not in conflict
378
+ pkg = ret.find { |p| p.name == package_name }
379
+ unless satisfied_by? vers, pkg.version
380
+ raise "Conflicting dependencies '#{package_name}' requires #{pkg.version} and #{vers}"
381
+ end
382
+
383
+ next
384
+ end
385
+
386
+ seen << package_name
387
+
388
+ # Find locally installed or fetched package
389
+ pkg = locate_package package_name, vers, verbose
390
+
391
+ if pkg.nil?
392
+ raise "Could not find eligable package for '#{package_name}' (#{vers})"
393
+ end
394
+
395
+ # Add dependencies for found package to list
396
+ pkg.dependencies.each do |dep_name, dep_vers|
397
+ todo << [dep_name, dep_vers]
398
+ end
399
+
400
+ ret << pkg
401
+ end
402
+
403
+ ret
404
+ end
405
+
406
+ def locate_package(package_name, vers, verbose)
407
+ if has_local_package? package_name
408
+ src_path = File.join root_path, 'packages', package_name
409
+ pkg = BPM::Package.new src_path
410
+ pkg.load_json
411
+ puts "~ Using local package '#{pkg.name}' (#{pkg.version})" if verbose
412
+ else
413
+ vers, prerel = clean_version vers
414
+ src_path = BPM::Local.new.source_root package_name, vers, prerel
415
+ if src_path
416
+ pkg = BPM::Package.new src_path
417
+ pkg.load_json
418
+ puts "~ Using fetched package '#{pkg.name}' (#{pkg.version})" if verbose
419
+ end
420
+ end
421
+
422
+ pkg
423
+ end
424
+
425
+ end
426
+
427
+ end