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.
- data/.gitignore +4 -0
- data/.gitmodules +0 -0
- data/Gemfile +16 -0
- data/README.md +55 -0
- data/TODO.md +3 -0
- data/bin/bpm +8 -0
- data/bpm.gemspec +41 -0
- data/lib/bpm.rb +18 -0
- data/lib/bpm/cli.rb +6 -0
- data/lib/bpm/cli/base.rb +358 -0
- data/lib/bpm/cli/owner.rb +46 -0
- data/lib/bpm/credentials.rb +36 -0
- data/lib/bpm/default.json +9 -0
- data/lib/bpm/generator.rb +69 -0
- data/lib/bpm/init_generator.rb +43 -0
- data/lib/bpm/libgems_ext.rb +11 -0
- data/lib/bpm/libgems_ext/config_file.rb +33 -0
- data/lib/bpm/libgems_ext/dependency_installer.rb +150 -0
- data/lib/bpm/libgems_ext/installer.rb +39 -0
- data/lib/bpm/libgems_ext/libgems.rb +39 -0
- data/lib/bpm/libgems_ext/spec_fetcher.rb +11 -0
- data/lib/bpm/local.rb +76 -0
- data/lib/bpm/package.rb +277 -0
- data/lib/bpm/pipeline.rb +100 -0
- data/lib/bpm/pipeline/directive_processor.rb +47 -0
- data/lib/bpm/pipeline/generated_asset.rb +68 -0
- data/lib/bpm/pipeline/transport_processor.rb +32 -0
- data/lib/bpm/project.rb +427 -0
- data/lib/bpm/project_generator.rb +34 -0
- data/lib/bpm/remote.rb +104 -0
- data/lib/bpm/repository.rb +18 -0
- data/lib/bpm/server.rb +44 -0
- data/lib/bpm/version.rb +3 -0
- data/spec/cli/add_spec.rb +159 -0
- data/spec/cli/build_spec.rb +87 -0
- data/spec/cli/fetch_spec.rb +135 -0
- data/spec/cli/fetched_spec.rb +52 -0
- data/spec/cli/init_spec.rb +50 -0
- data/spec/cli/list_spec.rb +74 -0
- data/spec/cli/login_spec.rb +110 -0
- data/spec/cli/new_spec.rb +92 -0
- data/spec/cli/owner_spec.rb +114 -0
- data/spec/cli/push_spec.rb +73 -0
- data/spec/cli/remove_spec.rb +84 -0
- data/spec/cli/unpack_spec.rb +72 -0
- data/spec/cli/unyank_spec.rb +73 -0
- data/spec/cli/yank_spec.rb +73 -0
- data/spec/credentials_spec.rb +23 -0
- data/spec/fixtures/badrake-0.8.7.spd +0 -0
- data/spec/fixtures/builder-3.0.0.spd +0 -0
- data/spec/fixtures/bundler-1.1.pre.spd +0 -0
- data/spec/fixtures/coffee-1.0.1.pre.spd +0 -0
- data/spec/fixtures/core-test-0.4.9.spd +0 -0
- data/spec/fixtures/core-test/bin/cot +3 -0
- data/spec/fixtures/core-test/lib/main.js +1 -0
- data/spec/fixtures/core-test/package.json +46 -0
- data/spec/fixtures/core-test/resources/runner.css +1 -0
- data/spec/fixtures/core-test/tests/test.js +1 -0
- data/spec/fixtures/custom_generator-1.0.spd +0 -0
- data/spec/fixtures/custom_generator/lib/main.js +1 -0
- data/spec/fixtures/custom_generator/package.json +12 -0
- data/spec/fixtures/custom_generator/templates/init/project.json +19 -0
- data/spec/fixtures/custom_generator/templates/project/app.js +1 -0
- data/spec/fixtures/custom_generator/templates/project/lib/main.js +0 -0
- data/spec/fixtures/custom_generator/templates/project_generator.rb +20 -0
- data/spec/fixtures/hello_world/LICENSE +19 -0
- data/spec/fixtures/hello_world/README.md +21 -0
- data/spec/fixtures/hello_world/assets/bpm_packages.js +13 -0
- data/spec/fixtures/hello_world/assets/bpm_styles.css +14 -0
- data/spec/fixtures/hello_world/assets/papa-smurf.jpg +0 -0
- data/spec/fixtures/hello_world/hello_world.json +20 -0
- data/spec/fixtures/hello_world/lib/main.js +9 -0
- data/spec/fixtures/hello_world/packages/custom_package/assets/dummy.txt +1 -0
- data/spec/fixtures/hello_world/packages/custom_package/css/sample_styles.css +3 -0
- data/spec/fixtures/hello_world/packages/custom_package/custom_dir/basic-module.js +1 -0
- data/spec/fixtures/hello_world/packages/custom_package/lib/main.js +1 -0
- data/spec/fixtures/hello_world/packages/custom_package/package.json +22 -0
- data/spec/fixtures/hello_world/tests/main-test.js +8 -0
- data/spec/fixtures/highline-1.6.1.spd +0 -0
- data/spec/fixtures/ivory-0.0.1.spd +0 -0
- data/spec/fixtures/jquery-1.4.3.spd +0 -0
- data/spec/fixtures/optparse-1.0.1.spd +0 -0
- data/spec/fixtures/rake-0.8.6.spd +0 -0
- data/spec/fixtures/rake-0.8.7.spd +0 -0
- data/spec/fixtures/simple_hello/assets/bpm_packages.js +1 -0
- data/spec/fixtures/simple_hello/lib/main.js +1 -0
- data/spec/fixtures/spade-0.5.0.spd +0 -0
- data/spec/fixtures/src/README.txt +1 -0
- data/spec/fixtures/src/bundler-1.1.pre/.gitignore +22 -0
- data/spec/fixtures/src/bundler-1.1.pre/CHANGELOG.md +646 -0
- data/spec/fixtures/src/bundler-1.1.pre/ISSUES.md +47 -0
- data/spec/fixtures/src/bundler-1.1.pre/LICENSE +21 -0
- data/spec/fixtures/src/bundler-1.1.pre/README.md +29 -0
- data/spec/fixtures/src/bundler-1.1.pre/UPGRADING.md +103 -0
- data/spec/fixtures/src/bundler-1.1.pre/bin/bundle +20 -0
- data/spec/fixtures/src/bundler-1.1.pre/lib/bundler.js +23 -0
- data/spec/fixtures/src/bundler-1.1.pre/lib/bundler/definition.js +14 -0
- data/spec/fixtures/src/bundler-1.1.pre/lib/bundler/dependency.js +15 -0
- data/spec/fixtures/src/bundler-1.1.pre/lib/bundler/dsl.js +9 -0
- data/spec/fixtures/src/bundler-1.1.pre/lib/bundler/ui.js +6 -0
- data/spec/fixtures/src/bundler-1.1.pre/man/bundle-config.ronn +90 -0
- data/spec/fixtures/src/bundler-1.1.pre/man/bundle-exec.ronn +111 -0
- data/spec/fixtures/src/bundler-1.1.pre/man/bundle-install.ronn +314 -0
- data/spec/fixtures/src/bundler-1.1.pre/man/bundle-package.ronn +59 -0
- data/spec/fixtures/src/bundler-1.1.pre/man/bundle-update.ronn +176 -0
- data/spec/fixtures/src/bundler-1.1.pre/man/bundle.ronn +80 -0
- data/spec/fixtures/src/bundler-1.1.pre/man/gemfile.5.ronn +279 -0
- data/spec/fixtures/src/bundler-1.1.pre/man/index.txt +6 -0
- data/spec/fixtures/src/bundler-1.1.pre/package.json +19 -0
- data/spec/fixtures/src/coffee-1.0.1.pre/bin/cake +0 -0
- data/spec/fixtures/src/coffee-1.0.1.pre/bin/coffee +0 -0
- data/spec/fixtures/src/coffee-1.0.1.pre/lib/coffee.js +0 -0
- data/spec/fixtures/src/coffee-1.0.1.pre/lib/coffee/base.js +0 -0
- data/spec/fixtures/src/coffee-1.0.1.pre/lib/coffee/mocha/chai.js +0 -0
- data/spec/fixtures/src/coffee-1.0.1.pre/package.json +19 -0
- data/spec/fixtures/src/coffee-1.0.1.pre/qunit/coffee/test.js +0 -0
- data/spec/fixtures/src/coffee-1.0.1.pre/qunit/test.js +0 -0
- data/spec/fixtures/src/jquery/lib/main.js +7179 -0
- data/spec/fixtures/src/jquery/package.json +15 -0
- data/spec/fixtures/src/rake-0.8.6/CHANGES +436 -0
- data/spec/fixtures/src/rake-0.8.6/MIT-LICENSE +21 -0
- data/spec/fixtures/src/rake-0.8.6/README +196 -0
- data/spec/fixtures/src/rake-0.8.6/Rakefile +430 -0
- data/spec/fixtures/src/rake-0.8.6/TODO +20 -0
- data/spec/fixtures/src/rake-0.8.6/bin/rake +31 -0
- data/spec/fixtures/src/rake-0.8.6/doc/command_line_usage.rdoc +102 -0
- data/spec/fixtures/src/rake-0.8.6/doc/example/Rakefile1 +38 -0
- data/spec/fixtures/src/rake-0.8.6/doc/example/Rakefile2 +35 -0
- data/spec/fixtures/src/rake-0.8.6/doc/example/a.c +6 -0
- data/spec/fixtures/src/rake-0.8.6/doc/example/b.c +6 -0
- data/spec/fixtures/src/rake-0.8.6/doc/example/main.c +11 -0
- data/spec/fixtures/src/rake-0.8.6/doc/glossary.rdoc +51 -0
- data/spec/fixtures/src/rake-0.8.6/doc/jamis.rb +591 -0
- data/spec/fixtures/src/rake-0.8.6/doc/proto_rake.rdoc +127 -0
- data/spec/fixtures/src/rake-0.8.6/doc/rake.1.gz +0 -0
- data/spec/fixtures/src/rake-0.8.6/doc/rakefile.rdoc +534 -0
- data/spec/fixtures/src/rake-0.8.6/doc/rational.rdoc +151 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.4.14.rdoc +23 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.4.15.rdoc +35 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.5.0.rdoc +53 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.5.3.rdoc +78 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.5.4.rdoc +46 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.6.0.rdoc +141 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.7.0.rdoc +119 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.7.1.rdoc +59 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.7.2.rdoc +121 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.7.3.rdoc +47 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.0.rdoc +114 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.2.rdoc +165 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.3.rdoc +112 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.4.rdoc +147 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.5.rdoc +53 -0
- data/spec/fixtures/src/rake-0.8.6/doc/release_notes/rake-0.8.6.rdoc +55 -0
- data/spec/fixtures/src/rake-0.8.6/install.rb +88 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake.rb +2502 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/alt_system.rb +108 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/classic_namespace.rb +8 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/clean.rb +33 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/compositepublisher.rb +24 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/ftptools.rb +153 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/publisher.rb +75 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/rubyforgepublisher.rb +18 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/sshpublisher.rb +47 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/contrib/sys.rb +209 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/gempackagetask.rb +97 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/loaders/makefile.rb +42 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/packagetask.rb +184 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/rake_test_loader.rb +5 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/rdoctask.rb +209 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/ruby182_test_unit_fix.rb +23 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/runtest.rb +23 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/tasklib.rb +23 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/testtask.rb +161 -0
- data/spec/fixtures/src/rake-0.8.6/lib/rake/win32.rb +55 -0
- data/spec/fixtures/src/rake-0.8.6/package.json +18 -0
- data/spec/fixtures/src/rake-0.8.6/test/capture_stdout.rb +26 -0
- data/spec/fixtures/src/rake-0.8.7/CHANGES +440 -0
- data/spec/fixtures/src/rake-0.8.7/MIT-LICENSE +21 -0
- data/spec/fixtures/src/rake-0.8.7/README +196 -0
- data/spec/fixtures/src/rake-0.8.7/Rakefile +430 -0
- data/spec/fixtures/src/rake-0.8.7/TODO +20 -0
- data/spec/fixtures/src/rake-0.8.7/bin/rake +31 -0
- data/spec/fixtures/src/rake-0.8.7/doc/command_line_usage.rdoc +102 -0
- data/spec/fixtures/src/rake-0.8.7/doc/example/Rakefile1 +38 -0
- data/spec/fixtures/src/rake-0.8.7/doc/example/Rakefile2 +35 -0
- data/spec/fixtures/src/rake-0.8.7/doc/example/a.c +6 -0
- data/spec/fixtures/src/rake-0.8.7/doc/example/b.c +6 -0
- data/spec/fixtures/src/rake-0.8.7/doc/example/main.c +11 -0
- data/spec/fixtures/src/rake-0.8.7/doc/glossary.rdoc +51 -0
- data/spec/fixtures/src/rake-0.8.7/doc/jamis.rb +591 -0
- data/spec/fixtures/src/rake-0.8.7/doc/proto_rake.rdoc +127 -0
- data/spec/fixtures/src/rake-0.8.7/doc/rake.1.gz +0 -0
- data/spec/fixtures/src/rake-0.8.7/doc/rakefile.rdoc +534 -0
- data/spec/fixtures/src/rake-0.8.7/doc/rational.rdoc +151 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.4.14.rdoc +23 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.4.15.rdoc +35 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.5.0.rdoc +53 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.5.3.rdoc +78 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.5.4.rdoc +46 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.6.0.rdoc +141 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.7.0.rdoc +119 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.7.1.rdoc +59 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.7.2.rdoc +121 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.7.3.rdoc +47 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.0.rdoc +114 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.2.rdoc +165 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.3.rdoc +112 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.4.rdoc +147 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.5.rdoc +53 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.6.rdoc +55 -0
- data/spec/fixtures/src/rake-0.8.7/doc/release_notes/rake-0.8.7.rdoc +55 -0
- data/spec/fixtures/src/rake-0.8.7/install.rb +88 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake.rb +2506 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/alt_system.rb +108 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/classic_namespace.rb +8 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/clean.rb +33 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/compositepublisher.rb +24 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/ftptools.rb +153 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/publisher.rb +75 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/rubyforgepublisher.rb +18 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/sshpublisher.rb +47 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/contrib/sys.rb +209 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/gempackagetask.rb +97 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/loaders/makefile.rb +42 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/packagetask.rb +184 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/rake_test_loader.rb +5 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/rdoctask.rb +209 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/ruby182_test_unit_fix.rb +23 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/runtest.rb +23 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/tasklib.rb +23 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/testtask.rb +161 -0
- data/spec/fixtures/src/rake-0.8.7/lib/rake/win32.rb +55 -0
- data/spec/fixtures/src/rake-0.8.7/package.json +18 -0
- data/spec/fixtures/src/rake-0.8.7/test/capture_stdout.rb +26 -0
- data/spec/fixtures/src/spade/lib/main.js +1 -0
- data/spec/fixtures/src/spade/package.json +15 -0
- data/spec/fixtures/transporter/lib/main.js +3 -0
- data/spec/fixtures/transporter/packages/transport/lib/wrapper.js +5 -0
- data/spec/fixtures/transporter/packages/transport/package.json +21 -0
- data/spec/fixtures/transporter/transporter.json +18 -0
- data/spec/gauntlet_spec.rb +33 -0
- data/spec/package_spec.rb +319 -0
- data/spec/pipeline_spec.rb +213 -0
- data/spec/project_spec.rb +130 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/support/cli.rb +93 -0
- data/spec/support/env.rb +18 -0
- data/spec/support/fake.rb +53 -0
- data/spec/support/fake_gem_server.rb +72 -0
- data/spec/support/fake_gemcutter.rb +50 -0
- data/spec/support/matchers.rb +32 -0
- data/spec/support/path.rb +63 -0
- data/spec/support/project.rb +43 -0
- data/templates/init/assets/bpm_packages.js +7 -0
- data/templates/init/assets/bpm_styles.css +7 -0
- data/templates/init/project.json +16 -0
- data/templates/project/LICENSE +19 -0
- data/templates/project/README.md +21 -0
- data/templates/project/app.js +1 -0
- data/templates/project/index.html +13 -0
- 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
|
data/lib/bpm/project.rb
ADDED
|
@@ -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
|