embulk 0.6.27 → 0.7.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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/Gemfile.lock +6 -1
  4. data/README.md +4 -4
  5. data/bin/embulk +39 -17
  6. data/build.gradle +23 -8
  7. data/embulk-cli/src/main/java/org/embulk/cli/Main.java +11 -2
  8. data/embulk-core/build.gradle +9 -4
  9. data/embulk-core/src/main/java/org/embulk/EmbulkEmbed.java +160 -61
  10. data/embulk-core/src/main/java/org/embulk/EmbulkService.java +1 -0
  11. data/embulk-core/src/main/java/org/embulk/command/TablePreviewPrinter.java +0 -1
  12. data/embulk-core/src/main/java/org/embulk/config/CommitReport.java +5 -1
  13. data/embulk-core/src/main/java/org/embulk/config/ConfigLoader.java +28 -7
  14. data/embulk-core/src/main/java/org/embulk/config/DataSourceImpl.java +1 -4
  15. data/embulk-core/src/main/java/org/embulk/config/DataSourceSerDe.java +6 -3
  16. data/embulk-core/src/main/java/org/embulk/config/ModelManager.java +0 -2
  17. data/embulk-core/src/main/java/org/embulk/config/TaskReport.java +29 -0
  18. data/embulk-core/src/main/java/org/embulk/exec/BulkLoader.java +42 -45
  19. data/embulk-core/src/main/java/org/embulk/exec/ExecModule.java +0 -1
  20. data/embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java +4 -7
  21. data/embulk-core/src/main/java/org/embulk/exec/LocalExecutorPlugin.java +5 -6
  22. data/embulk-core/src/main/java/org/embulk/exec/LoggerProvider.java +0 -1
  23. data/embulk-core/src/main/java/org/embulk/exec/PooledBufferAllocator.java +0 -3
  24. data/embulk-core/src/main/java/org/embulk/exec/PreviewExecutor.java +2 -2
  25. data/embulk-core/src/main/java/org/embulk/exec/ResumeState.java +26 -9
  26. data/embulk-core/src/main/java/org/embulk/exec/SamplingParserPlugin.java +2 -4
  27. data/embulk-core/src/main/java/org/embulk/guice/Bootstrap.java +12 -5
  28. data/embulk-core/src/main/java/org/embulk/guice/CloseableInjector.java +1 -1
  29. data/embulk-core/src/main/java/org/embulk/guice/LifeCycleInjector.java +26 -0
  30. data/embulk-core/src/main/java/org/embulk/guice/{CloseableInjectorProxy.java → LifeCycleInjectorProxy.java} +20 -6
  31. data/embulk-core/src/main/java/org/embulk/jruby/JRubyScriptingModule.java +10 -12
  32. data/embulk-core/src/main/java/org/embulk/plugin/PluginClassLoaderModule.java +0 -1
  33. data/embulk-core/src/main/java/org/embulk/plugin/PluginManager.java +14 -1
  34. data/embulk-core/src/main/java/org/embulk/plugin/compat/InputPluginWrapper.java +102 -0
  35. data/embulk-core/src/main/java/org/embulk/plugin/compat/PluginWrappers.java +30 -0
  36. data/embulk-core/src/main/java/org/embulk/plugin/compat/TransactionalFileInputWrapper.java +96 -0
  37. data/embulk-core/src/main/java/org/embulk/plugin/compat/TransactionalFileOutputWrapper.java +102 -0
  38. data/embulk-core/src/main/java/org/embulk/plugin/compat/TransactionalPageOutputWrapper.java +95 -0
  39. data/embulk-core/src/main/java/org/embulk/spi/ColumnConfig.java +0 -2
  40. data/embulk-core/src/main/java/org/embulk/spi/Exec.java +8 -2
  41. data/embulk-core/src/main/java/org/embulk/spi/ExecSession.java +7 -1
  42. data/embulk-core/src/main/java/org/embulk/spi/Extension.java +2 -2
  43. data/embulk-core/src/main/java/org/embulk/spi/FileInputPlugin.java +3 -3
  44. data/embulk-core/src/main/java/org/embulk/spi/FileInputRunner.java +12 -10
  45. data/embulk-core/src/main/java/org/embulk/spi/FileOutputPlugin.java +3 -3
  46. data/embulk-core/src/main/java/org/embulk/spi/FileOutputRunner.java +11 -9
  47. data/embulk-core/src/main/java/org/embulk/spi/FilterPlugin.java +0 -3
  48. data/embulk-core/src/main/java/org/embulk/spi/InputPlugin.java +4 -4
  49. data/embulk-core/src/main/java/org/embulk/spi/OutputPlugin.java +3 -3
  50. data/embulk-core/src/main/java/org/embulk/spi/PageReader.java +0 -1
  51. data/embulk-core/src/main/java/org/embulk/spi/ProcessTask.java +0 -5
  52. data/embulk-core/src/main/java/org/embulk/spi/SchemaConfig.java +0 -1
  53. data/embulk-core/src/main/java/org/embulk/spi/TaskState.java +19 -4
  54. data/embulk-core/src/main/java/org/embulk/spi/TempFileSpace.java +0 -3
  55. data/embulk-core/src/main/java/org/embulk/spi/Transactional.java +2 -2
  56. data/embulk-core/src/main/java/org/embulk/spi/TransactionalFileInput.java +2 -2
  57. data/embulk-core/src/main/java/org/embulk/spi/TransactionalFileOutput.java +2 -2
  58. data/embulk-core/src/main/java/org/embulk/spi/TransactionalPageOutput.java +2 -2
  59. data/embulk-core/src/main/java/org/embulk/spi/time/DateTimeZoneSerDe.java +0 -2
  60. data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormat.java +0 -3
  61. data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormatter.java +0 -1
  62. data/embulk-core/src/main/java/org/embulk/spi/time/TimestampParser.java +0 -1
  63. data/embulk-core/src/main/java/org/embulk/spi/time/TimestampSerDe.java +0 -1
  64. data/embulk-core/src/main/java/org/embulk/spi/type/TypeDeserializer.java +0 -3
  65. data/embulk-core/src/main/java/org/embulk/spi/unit/LocalFileSerDe.java +0 -3
  66. data/embulk-core/src/main/java/org/embulk/spi/unit/ToStringMap.java +0 -1
  67. data/embulk-core/src/main/java/org/embulk/spi/util/Executors.java +15 -12
  68. data/embulk-core/src/main/java/org/embulk/spi/util/Filters.java +0 -1
  69. data/embulk-core/src/test/java/org/embulk/spi/TestFileInputRunner.java +7 -7
  70. data/embulk-core/src/test/java/org/embulk/spi/TestFileOutputRunner.java +8 -8
  71. data/embulk-docs/src/built-in.rst +27 -30
  72. data/embulk-docs/src/conf.py +2 -2
  73. data/embulk-docs/src/release.rst +1 -2
  74. data/embulk-docs/src/release/release-0.7.0.rst +96 -0
  75. data/embulk-standards/src/main/java/org/embulk/standards/CsvFormatterPlugin.java +0 -4
  76. data/embulk-standards/src/main/java/org/embulk/standards/CsvParserPlugin.java +0 -10
  77. data/embulk-standards/src/main/java/org/embulk/standards/CsvTokenizer.java +1 -5
  78. data/embulk-standards/src/main/java/org/embulk/standards/LocalFileInputPlugin.java +4 -5
  79. data/embulk-standards/src/main/java/org/embulk/standards/LocalFileOutputPlugin.java +4 -5
  80. data/embulk-standards/src/main/java/org/embulk/standards/NullOutputPlugin.java +4 -4
  81. data/embulk-standards/src/main/java/org/embulk/standards/StandardPluginModule.java +0 -3
  82. data/embulk-standards/src/main/java/org/embulk/standards/StdoutOutputPlugin.java +4 -6
  83. data/embulk.gemspec +14 -1
  84. data/lib/embulk.rb +59 -4
  85. data/lib/embulk/command/embulk_bundle.rb +56 -0
  86. data/lib/embulk/command/embulk_main.rb +2 -0
  87. data/lib/embulk/command/embulk_migrate_plugin.rb +170 -0
  88. data/lib/embulk/command/embulk_new_plugin.rb +4 -1
  89. data/lib/embulk/command/embulk_run.rb +188 -227
  90. data/lib/embulk/data/bundle/.ruby-version +1 -0
  91. data/lib/embulk/data/bundle/Gemfile +4 -1
  92. data/lib/embulk/data/bundle/embulk/input/example.rb +4 -4
  93. data/lib/embulk/data/bundle/embulk/output/example.rb +4 -4
  94. data/lib/embulk/data/new/README.md.erb +1 -1
  95. data/lib/embulk/data/new/java/file_input.java.erb +4 -4
  96. data/lib/embulk/data/new/java/file_output.java.erb +2 -2
  97. data/lib/embulk/data/new/java/gradle/wrapper/gradle-wrapper.jar +0 -0
  98. data/lib/embulk/data/new/java/gradle/wrapper/gradle-wrapper.properties +2 -2
  99. data/lib/embulk/data/new/java/input.java.erb +3 -3
  100. data/lib/embulk/data/new/java/output.java.erb +2 -2
  101. data/lib/embulk/data/new/ruby/.ruby-version +1 -0
  102. data/lib/embulk/data/new/ruby/gemspec.erb +1 -0
  103. data/lib/embulk/data/new/ruby/input.rb.erb +3 -3
  104. data/lib/embulk/data/new/ruby/output.rb.erb +4 -4
  105. data/lib/embulk/data/package_data.rb +1 -15
  106. data/lib/embulk/guess/charset.rb +10 -1
  107. data/lib/embulk/input_plugin.rb +12 -12
  108. data/lib/embulk/java/bootstrap.rb +7 -4
  109. data/lib/embulk/java/imports.rb +34 -2
  110. data/lib/embulk/logger.rb +2 -0
  111. data/lib/embulk/output_plugin.rb +12 -12
  112. data/lib/embulk/page_builder.rb +1 -1
  113. data/lib/embulk/plugin.rb +0 -1
  114. data/lib/embulk/runner.rb +184 -0
  115. data/lib/embulk/version.rb +1 -1
  116. metadata +76 -55
  117. data/embulk-core/src/main/java/org/embulk/command/LiquidTemplate.java +0 -8
  118. data/embulk-core/src/main/java/org/embulk/command/Runner.java +0 -369
  119. data/embulk-docs/src/release/release-0.6.26.rst +0 -17
  120. data/embulk-docs/src/release/release-0.6.27.rst +0 -11
  121. data/lib/embulk/command/embulk.rb +0 -47
  122. data/lib/embulk/data/bundle/Gemfile.lock +0 -8
  123. data/lib/embulk/exec.rb +0 -8
  124. data/lib/embulk/gems.rb +0 -29
  125. data/lib/embulk/java/liquid_helper.rb +0 -16
@@ -4,7 +4,7 @@ import java.util.List;
4
4
  import org.embulk.config.ConfigSource;
5
5
  import org.embulk.config.TaskSource;
6
6
  import org.embulk.config.ConfigDiff;
7
- import org.embulk.config.CommitReport;
7
+ import org.embulk.config.TaskReport;
8
8
  import org.embulk.spi.Schema;
9
9
  import org.embulk.spi.Page;
10
10
  import org.embulk.spi.Exec;
@@ -32,7 +32,7 @@ public class NullOutputPlugin
32
32
 
33
33
  public void cleanup(TaskSource taskSource,
34
34
  Schema schema, int taskCount,
35
- List<CommitReport> successCommitReports)
35
+ List<TaskReport> successTaskReports)
36
36
  { }
37
37
 
38
38
  @Override
@@ -50,9 +50,9 @@ public class NullOutputPlugin
50
50
 
51
51
  public void abort() { }
52
52
 
53
- public CommitReport commit()
53
+ public TaskReport commit()
54
54
  {
55
- return Exec.newCommitReport();
55
+ return Exec.newTaskReport();
56
56
  }
57
57
  };
58
58
  }
@@ -3,8 +3,6 @@ package org.embulk.standards;
3
3
  import com.google.common.base.Preconditions;
4
4
  import com.google.inject.Binder;
5
5
  import com.google.inject.Module;
6
- import com.google.inject.name.Names;
7
- import com.google.inject.multibindings.Multibinder;
8
6
  import org.embulk.spi.FilterPlugin;
9
7
  import org.embulk.spi.FormatterPlugin;
10
8
  import org.embulk.spi.InputPlugin;
@@ -12,7 +10,6 @@ import org.embulk.spi.OutputPlugin;
12
10
  import org.embulk.spi.ParserPlugin;
13
11
  import org.embulk.spi.DecoderPlugin;
14
12
  import org.embulk.spi.EncoderPlugin;
15
- import org.embulk.exec.GuessExecutor;
16
13
  import org.embulk.plugin.PluginType;
17
14
  import static org.embulk.plugin.InjectedPluginSource.registerPluginTo;
18
15
  import static org.embulk.exec.GuessExecutor.registerDefaultGuessPluginTo;
@@ -4,12 +4,10 @@ import java.util.List;
4
4
  import org.embulk.config.ConfigSource;
5
5
  import org.embulk.config.TaskSource;
6
6
  import org.embulk.config.ConfigDiff;
7
- import org.embulk.config.CommitReport;
7
+ import org.embulk.config.TaskReport;
8
8
  import org.embulk.config.Task;
9
9
  import org.embulk.spi.time.TimestampFormatter;
10
10
  import org.embulk.spi.Schema;
11
- import org.embulk.spi.ColumnVisitor;
12
- import org.embulk.spi.Column;
13
11
  import org.embulk.spi.Page;
14
12
  import org.embulk.spi.Exec;
15
13
  import org.embulk.spi.OutputPlugin;
@@ -45,7 +43,7 @@ public class StdoutOutputPlugin
45
43
 
46
44
  public void cleanup(TaskSource taskSource,
47
45
  Schema schema, int taskCount,
48
- List<CommitReport> successCommitReports)
46
+ List<TaskReport> successTaskReports)
49
47
  { }
50
48
 
51
49
  @Override
@@ -78,9 +76,9 @@ public class StdoutOutputPlugin
78
76
 
79
77
  public void abort() { }
80
78
 
81
- public CommitReport commit()
79
+ public TaskReport commit()
82
80
  {
83
- return Exec.newCommitReport();
81
+ return Exec.newTaskReport();
84
82
  }
85
83
  };
86
84
  }
data/embulk.gemspec CHANGED
@@ -12,12 +12,25 @@ Gem::Specification.new do |gem|
12
12
  gem.license = "Apache 2.0"
13
13
  gem.homepage = "https://github.com/embulk/embulk"
14
14
 
15
- gem.files = `git ls-files`.split("\n") + Dir["classpath/*.jar"]
15
+ provided_classpath = Dir["classpath/jruby-complete-*.jar"] + Dir["classpath/icu4j-*.jar"]
16
+ gem.files = `git ls-files`.split("\n") + Dir["classpath/*.jar"] - provided_classpath
16
17
  gem.test_files = gem.files.grep(%r"^(test|spec)/")
17
18
  gem.executables = gem.files.grep(%r"^bin/").map{ |f| File.basename(f) }
18
19
  gem.require_paths = ["lib"]
19
20
  gem.has_rdoc = false
20
21
 
22
+ if RUBY_PLATFORM =~ /java/i
23
+ gem.add_dependency "liquid", '~> 3.0.6'
24
+
25
+ # For embulk/guess/charset.rb. See also embulk-core/build.gradle
26
+ gem.add_dependency "rjack-icu", '~> 4.54.1.1'
27
+
28
+ gem.platform = 'java'
29
+
30
+ else
31
+ gem.add_dependency "jruby-jars", '= 9.0.0.0'
32
+ end
33
+
21
34
  gem.add_development_dependency "bundler", [">= 1.0"]
22
35
  gem.add_development_dependency "rake", [">= 0.10.0"]
23
36
  gem.add_development_dependency "test-unit", ["~> 3.0.9"]
data/lib/embulk.rb CHANGED
@@ -9,9 +9,64 @@ module Embulk
9
9
  end
10
10
  end
11
11
 
12
+ # logger should be setup first
12
13
  require 'embulk/logger'
13
- require 'embulk/error'
14
- require 'embulk/buffer'
15
- require 'embulk/data_source'
16
- require 'embulk/plugin'
14
+
15
+ def self.lib_path(path)
16
+ path = '' if path == '/'
17
+ jar, resource = __FILE__.split("!", 2)
18
+ if resource
19
+ lib = resource.split("/")[0..-2].join("/")
20
+ "#{jar}!#{lib}/#{path}"
21
+ elsif __FILE__ =~ /^classpath:/
22
+ lib = __FILE__.split("/")[0..-2].join("/")
23
+ "#{lib}/#{path}"
24
+ else
25
+ lib = File.expand_path File.dirname(__FILE__)
26
+ File.join(lib, *path.split("/"))
27
+ end
28
+ end
29
+
30
+ def self.require_classpath
31
+ if __FILE__.include?("!")
32
+ # single jar
33
+ jar, resource = __FILE__.split("!", 2)
34
+ require jar
35
+
36
+ elsif __FILE__ =~ /^classpath:/
37
+ # already in classpath
38
+
39
+ else
40
+ # gem package
41
+ gem_root = File.expand_path('..', File.dirname(__FILE__))
42
+ classpath_dir = File.join(gem_root, "classpath")
43
+ jars = Dir.entries(classpath_dir).select{|f| f =~ /\.jar$/ }.sort
44
+ jars.each do |jar|
45
+ require File.join(classpath_dir, jar)
46
+ end
47
+ end
48
+ end
49
+
50
+ def self.setup(system_config={})
51
+ unless RUBY_PLATFORM =~ /java/i
52
+ raise "Embulk.setup works only with JRuby."
53
+ end
54
+
55
+ require_classpath
56
+
57
+ systemConfigJson = system_config.merge({
58
+ # use the global ruby runtime for all ScriptingContainer
59
+ # injected by org.embulk.jruby.JRubyScriptingModule
60
+ use_global_ruby_runtime: true
61
+ }).to_json
62
+
63
+ bootstrap = org.embulk.EmbulkEmbed::Bootstrap.new
64
+ systemConfig = bootstrap.getSystemConfigLoader.fromJsonString(systemConfigJson)
65
+ bootstrap.setSystemConfig(systemConfig)
66
+ embed = bootstrap.java_method(:initialize).call # see embulk-core/src/main/java/org/embulk/jruby/JRubyScriptingModule.
67
+
68
+ # see also embulk/java/bootstrap.rb loaded by JRubyScriptingModule
69
+
70
+ Embulk.const_set :Runner, EmbulkRunner.new(embed)
71
+ end
17
72
  end
@@ -0,0 +1,56 @@
1
+
2
+ bundle_path = ENV['EMBULK_BUNDLE_PATH'].to_s
3
+ bundle_path = nil if bundle_path.empty?
4
+
5
+ # search -b, --bundle BUNDLE_DIR
6
+ bundle_path_index = ARGV.find_index {|arg| arg == '-b' || arg == '--bundle' }
7
+ if bundle_path_index
8
+ bundle_path = ARGV.slice!(bundle_path_index, 2)[1]
9
+ end
10
+
11
+ if bundle_path
12
+ # use bundler installed at bundle_path
13
+ ENV['EMBULK_BUNDLE_PATH'] = bundle_path
14
+ ENV['GEM_HOME'] = File.expand_path File.join(bundle_path, Gem.ruby_engine, RbConfig::CONFIG['ruby_version'])
15
+ ENV['GEM_PATH'] = ''
16
+ Gem.clear_paths # force rubygems to reload GEM_HOME
17
+
18
+ ENV['BUNDLE_GEMFILE'] = File.expand_path File.join(bundle_path, "Gemfile")
19
+
20
+ begin
21
+ require 'bundler'
22
+ rescue LoadError => e
23
+ raise "#{e}\nBundler is not installed. Did you run \`$ embulk bundle #{bundle_path}\` ?"
24
+ end
25
+ Bundler.load.setup_environment
26
+ require 'bundler/setup'
27
+ # since here, `require` may load files of different (newer) embulk versions
28
+ # especially following 'embulk/command/embulk_main'.
29
+
30
+ # add bundle directory path to load local plugins at ./embulk
31
+ $LOAD_PATH << File.expand_path(bundle_path)
32
+
33
+ begin
34
+ require 'embulk/command/embulk_main'
35
+ rescue LoadError
36
+ $LOAD_PATH << File.expand_path('../../', File.dirname(__FILE__))
37
+ require 'embulk/command/embulk_main'
38
+ end
39
+
40
+ else
41
+ # default GEM_HOME is ~/.embulk/jruby/1.9/. If -b option is set,
42
+ # GEM_HOME is already set by embulk/command/embulk_main.rb
43
+ ENV.delete('EMBULK_BUNDLE_PATH')
44
+ user_home = java.lang.System.properties["user.home"] || ENV['HOME']
45
+ unless user_home
46
+ raise "HOME environment variable is not set."
47
+ end
48
+ ENV['GEM_HOME'] = File.expand_path File.join(user_home, '.embulk', Gem.ruby_engine, RbConfig::CONFIG['ruby_version'])
49
+ ENV['GEM_PATH'] = ''
50
+
51
+ ENV.delete('BUNDLE_GEMFILE')
52
+ Gem.clear_paths # force rubygems to reload GEM_HOME
53
+
54
+ $LOAD_PATH << File.expand_path('../../', File.dirname(__FILE__))
55
+ require 'embulk/command/embulk_main'
56
+ end
@@ -0,0 +1,2 @@
1
+ require 'embulk/command/embulk_run'
2
+ Embulk.run(ARGV)
@@ -0,0 +1,170 @@
1
+ module Embulk
2
+ def self.migrate_plugin(path)
3
+ migrator = Migrator.new(path)
4
+
5
+ if ms = migrator.match("**/build.gradle", /org\.embulk:embulk-core:([\d\.]+)?/)
6
+ lang = :java
7
+ from_ver = version(ms[0][1])
8
+ puts "Detected Java plugin for Embulk #{from_ver}..."
9
+
10
+ elsif ms = migrator.match("**/*.gemspec", /add_(?:development_)?dependency\s+\W+embulk\W+\s+([\d\.]+)\W+/)
11
+ lang = :ruby
12
+ from_ver = version(ms[0][1])
13
+ puts "Detected Ruby plugin for Embulk #{from_ver}..."
14
+
15
+ elsif ms = migrator.match("**/*.gemspec", /embulk-/)
16
+ lang = :ruby
17
+ from_ver = version("0.1.0")
18
+ puts "Detected Ruby plugin for unknown Embulk version..."
19
+
20
+ else
21
+ raise "Failed to detect plugin language and dependency version"
22
+ end
23
+
24
+ case lang
25
+ when :java
26
+ migrate_java_plugin(migrator, from_ver)
27
+ when :ruby
28
+ migrate_ruby_plugin(migrator, from_ver)
29
+ end
30
+
31
+ if migrator.modified_files.empty?
32
+ puts "Done. No files are modified."
33
+ else
34
+ puts "Done. Please check modifieid files."
35
+ end
36
+ end
37
+
38
+ def self.migrate_java_plugin(migrator, from_ver)
39
+ if from_ver < version("0.7.0")
40
+ # rename CommitReport to TaskReport
41
+ migrator.replace("**/*.java", /(CommitReport)/, "TaskReport")
42
+ migrator.replace("**/*.java", /(commitReport)/, "taskReport")
43
+ end
44
+
45
+ if migrator.match("gradle/wrapper/gradle-wrapper.properties", /gradle-2\.[12345]\W+/)
46
+ # gradle < 2.6
47
+ require 'embulk/data/package_data'
48
+ data = PackageData.new("new", migrator.path)
49
+ migrator.write "gradle/wrapper/gradle-wrapper.jar", data.content("java/gradle/wrapper/gradle-wrapper.jar")
50
+ migrator.write "gradle/wrapper/gradle-wrapper.properties", data.content("java/gradle/wrapper/gradle-wrapper.properties")
51
+ end
52
+
53
+ #
54
+ # add rules...
55
+ ##
56
+
57
+ # update version at the end
58
+ migrator.replace("**/build.gradle", /org\.embulk:embulk-(?:core|standards):([\d\.]+)?/, Embulk::VERSION)
59
+ end
60
+
61
+ def self.migrate_ruby_plugin(migrator, from_ver)
62
+ #
63
+ # add rules...
64
+ ##
65
+
66
+ migrator.write(".ruby-version", "jruby-9.0.0.0")
67
+
68
+ # update version at the end
69
+ if from_ver <= version("0.1.0")
70
+ # add add_development_dependency
71
+ migrator.insert_line("**/*.gemspec", /([ \t]*\w+)\.add_development_dependency/) {|m|
72
+ "#{m[1]}.add_development_dependency 'embulk', ['~> #{Embulk::VERSION}']"
73
+ }
74
+ else
75
+ migrator.replace("**/*.gemspec", /add_(?:development_)?dependency\s+\W+embulk\W+\s+([\d\.]+)\W+/, Embulk::VERSION)
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def self.version(str)
82
+ Gem::Version.new(str)
83
+ end
84
+
85
+ class Migrator
86
+ def initialize(path)
87
+ @path = path
88
+ @modified_files = {}
89
+ end
90
+
91
+ attr_reader :path
92
+
93
+ def modified_files
94
+ @modified_files.keys
95
+ end
96
+
97
+ def match(glob, pattern)
98
+ ms = Dir[File.join(@path, glob)].map do |file|
99
+ File.read(file).match(pattern)
100
+ end.compact
101
+ return nil if ms.empty?
102
+ ms
103
+ end
104
+
105
+ def replace(glob, pattern, text=nil)
106
+ ms = Dir[File.join(@path, glob)].map do |file|
107
+ data = File.read(file)
108
+ first = nil
109
+ pos = 0
110
+ while pos < data.length
111
+ m = data.match(pattern, pos)
112
+ break unless m
113
+ first ||= m
114
+ replace = text || yield(m)
115
+ data = m.pre_match + data[m.begin(0)..(m.begin(1)-1)] + replace + data[m.end(1)..(m.end(0)-1)] + m.post_match
116
+ pos = m.begin(1) + replace.length + (m.end(0) - m.end(1))
117
+ end
118
+ if first
119
+ modify(file, data)
120
+ end
121
+ first
122
+ end.compact
123
+ return nil if ms.empty?
124
+ ms
125
+ end
126
+
127
+ def insert_line(glob, pattern, text=nil)
128
+ ms = Dir[File.join(@path, glob)].map do |file|
129
+ data = File.read(file)
130
+ if m = data.match(pattern)
131
+ ln = m.pre_match.split("\n").count
132
+ replace = text || yield(m)
133
+ lines = data.split("\n")
134
+ lines.insert(ln + 1, replace)
135
+ data = lines.join("\n")
136
+ modify(file, data)
137
+ m
138
+ end
139
+ end.compact
140
+ return nil if ms.empty?
141
+ ms
142
+ end
143
+
144
+ def data(file)
145
+ File.read(File.join(@path, file))
146
+ end
147
+
148
+ def write(file, data)
149
+ modify(File.join(@path, file), data)
150
+ end
151
+
152
+ private
153
+
154
+ def modify(path, data)
155
+ orig = File.read(path) rescue nil
156
+ if orig != data
157
+ File.write(path, data)
158
+ unless @modified_files.has_key?(path)
159
+ if orig
160
+ puts " Modified #{path.sub(/^#{Regexp.escape(@path)}/, '')}"
161
+ else
162
+ puts " Created #{path.sub(/^#{Regexp.escape(@path)}/, '')}"
163
+ end
164
+ @modified_files[path] = true
165
+ end
166
+ end
167
+ nil
168
+ end
169
+ end
170
+ end
@@ -77,6 +77,7 @@ module Embulk
77
77
  when :ruby
78
78
  pkg.cp("ruby/Rakefile", "Rakefile")
79
79
  pkg.cp("ruby/Gemfile", "Gemfile")
80
+ pkg.cp("ruby/.ruby-version", ".ruby-version")
80
81
  pkg.cp_erb("ruby/gemspec.erb", "#{full_project_name}.gemspec")
81
82
  pkg.cp_erb("ruby/#{category}.rb.erb", plugin_path)
82
83
 
@@ -104,7 +105,9 @@ module Embulk
104
105
  puts "Next steps:"
105
106
  puts ""
106
107
  puts " $ cd #{full_project_name}"
107
- puts " $ rake"
108
+ puts " $ bundle install # install one using rbenv & rbenv-build"
109
+ puts " $ bundle exec rake # build gem to be released"
110
+ puts " $ bundle exec embulk run config.yml # you can run plugin using this command"
108
111
  when :java
109
112
  puts "Next steps:"
110
113
  puts ""
@@ -1,37 +1,26 @@
1
+ require 'embulk'
2
+
1
3
  module Embulk
2
4
  def self.run(argv)
3
- # default_bundle_path
4
- default_bundle_path = nil
5
- gemfile_path = ENV['BUNDLE_GEMFILE'].to_s
6
- gemfile_path = nil if gemfile_path.empty?
7
- default_bundle_path = File.dirname(gemfile_path) if gemfile_path
8
-
9
- # default GEM_HOME is ~/.embulk/jruby/1.9/. If -b option is set,
10
- # GEM_HOME is already set by embulk/command/embulk.rb
11
- gem_home = ENV['GEM_HOME'].to_s
12
- if gem_home.empty?
13
- ENV['GEM_HOME'] = default_gem_home
14
- Gem.clear_paths # force rubygems to reload GEM_HOME
15
- end
5
+ # reset context class loader set by org.jruby.Main.main to nil. embulk manages
6
+ # multiple classloaders. default classloader should be Plugin.class.getClassloader().
7
+ java.lang.Thread.current_thread.set_context_class_loader(nil)
16
8
 
17
9
  # Gem.path is called when GemRunner installs a gem with native extension.
18
10
  # Running extconf.rb fails without this hack.
19
11
  fix_gem_ruby_path
20
12
 
21
- # to make sure org.embulk.jruby.JRubyScriptingModule can require 'embulk/java/bootstrap'
22
- $LOAD_PATH << Embulk.home('lib')
23
-
24
13
  require 'embulk/version'
25
14
 
26
15
  i = argv.find_index {|arg| arg !~ /^\-/ }
27
16
  unless i
28
17
  if argv.include?('--version')
29
18
  puts "embulk #{Embulk::VERSION}"
30
- exit 0
19
+ system_exit_success
31
20
  end
32
21
  usage nil
33
22
  end
34
- subcmd = argv.slice!(i)
23
+ subcmd = argv.slice!(i).to_sym
35
24
 
36
25
  require 'java'
37
26
  require 'optparse'
@@ -46,32 +35,25 @@ module Embulk
46
35
  classpath_separator = java.io.File.pathSeparator
47
36
 
48
37
  options = {
49
- # use the global ruby runtime (the jruby Runtime running this embulk_run.rb script) for all
50
- # ScriptingContainer injected by the org.embulk.command.Runner.
51
- useGlobalRubyRuntime: true,
52
- systemProperty: {},
38
+ system_config: {}
53
39
  }
54
40
 
55
- op.on('-b', '--bundle BUNDLE_DIR', 'Path to a Gemfile directory') do |path|
56
- # only for help message. implemented at lib/embulk/command/embulk.rb
57
- end
58
-
59
- case subcmd.to_sym
60
- when :bundle
61
- op.remove # remove --bundle
62
- if default_bundle_path
63
- op.banner = "Usage: bundle [directory=#{default_bundle_path}]"
64
- args = 0..1
65
- else
66
- op.banner = "Usage: bundle <directory>"
67
- args = 1..1
68
- end
69
-
70
- when :run
71
- op.banner = "Usage: run <config.yml>"
41
+ java_embed_ops = lambda do
42
+ op.separator ""
43
+ op.separator " Other options:"
72
44
  op.on('-l', '--log-level LEVEL', 'Log level (error, warn, info, debug or trace)') do |level|
73
- options[:logLevel] = level
45
+ options[:system_config][:log_level] = level
46
+ end
47
+ op.on('-X KEY=VALUE', 'Add a performance system config') do |kv|
48
+ k, v = kv.split('=', 2)
49
+ v ||= "true"
50
+ options[:system_config][k] = v
74
51
  end
52
+ end
53
+
54
+ plugin_load_ops = lambda do
55
+ op.separator ""
56
+ op.separator " Plugin load options:"
75
57
  op.on('-L', '--load PATH', 'Add a local plugin path') do |plugin_path|
76
58
  plugin_paths << plugin_path
77
59
  end
@@ -81,96 +63,83 @@ module Embulk
81
63
  op.on('-C', '--classpath PATH', "Add java classpath separated by #{classpath_separator} (CLASSPATH)") do |classpath|
82
64
  classpaths.concat classpath.split(classpath_separator)
83
65
  end
84
- op.on('-o', '--output PATH', 'Path to a file to write the next configuration') do |path|
85
- options[:nextConfigOutputPath] = path
66
+ op.on('-b', '--bundle BUNDLE_DIR', 'Path to a Gemfile directory (create one using "embulk bundle new" command)') do |path|
67
+ # only for help message. implemented at lib/embulk/command/embulk_bundle.rb
86
68
  end
69
+ end
70
+
71
+ case subcmd
72
+ when :run
73
+ op.banner = "Usage: run <config.yml>"
74
+ op.separator " Options:"
87
75
  op.on('-r', '--resume-state PATH', 'Path to a file to write or read resume state') do |path|
88
- options[:resumeStatePath] = path
76
+ options[:resume_state_path] = path
89
77
  end
90
- op.on('-X KEY=VALUE', 'Add a performance system config') do |kv|
91
- k, v = kv.split('=', 2)
92
- v ||= "true"
93
- options[:systemProperty][k] = v
78
+ op.on('-o', '--output PATH', 'Path to a file to write the next configuration') do |path|
79
+ options[:next_config_output_path] = path
94
80
  end
81
+ plugin_load_ops.call
82
+ java_embed_ops.call
95
83
  args = 1..1
96
84
 
97
85
  when :cleanup
98
86
  op.banner = "Usage: cleanup <config.yml>"
99
- op.on('-l', '--log-level LEVEL', 'Log level (error, warn, info, debug or trace)') do |level|
100
- options[:logLevel] = level
101
- end
102
- op.on('-L', '--load PATH', 'Add a local plugin path') do |plugin_path|
103
- plugin_paths << plugin_path
104
- end
105
- op.on('-I', '--load-path PATH', 'Add ruby script directory path ($LOAD_PATH)') do |load_path|
106
- load_paths << load_path
107
- end
108
- op.on('-C', '--classpath PATH', "Add java classpath separated by #{classpath_separator} (CLASSPATH)") do |classpath|
109
- classpaths.concat classpath.split(classpath_separator)
110
- end
87
+ op.separator " Options:"
111
88
  op.on('-r', '--resume-state PATH', 'Path to a file to write or read resume state') do |path|
112
- options[:resumeStatePath] = path
113
- end
114
- op.on('-X KEY=VALUE', 'Add a performance system config') do |kv|
115
- k, v = kv.split('=', 2)
116
- v ||= "true"
117
- options[:systemProperty][k] = v
89
+ options[:resume_state_path] = path
118
90
  end
91
+ plugin_load_ops.call
92
+ java_embed_ops.call
119
93
  args = 1..1
120
94
 
121
95
  when :preview
122
96
  op.banner = "Usage: preview <config.yml>"
123
- op.on('-l', '--log-level LEVEL', 'Log level (error, warn, info, debug or trace)') do |level|
124
- options[:logLevel] = level
125
- end
126
- op.on('-L', '--load PATH', 'Add a local plugin path') do |plugin_path|
127
- plugin_paths << plugin_path
128
- end
129
- op.on('-I', '--load-path PATH', 'Add ruby script directory path ($LOAD_PATH)') do |load_path|
130
- load_paths << load_path
131
- end
132
- op.on('-C', '--classpath PATH', "Add java classpath separated by #{classpath_separator} (CLASSPATH)") do |classpath|
133
- classpaths.concat classpath.split(classpath_separator)
134
- end
97
+ op.separator " Options:"
135
98
  op.on('-G', '--vertical', "Use vertical output format", TrueClass) do |b|
136
- options[:previewOutputFormat] = "vertical"
137
- end
138
- op.on('-X KEY=VALUE', 'Add a performance system config') do |kv|
139
- k, v = kv.split('=', 2)
140
- v ||= "true"
141
- options[:systemProperty][k] = v
99
+ options[:format] = "vertical"
142
100
  end
101
+ plugin_load_ops.call
102
+ java_embed_ops.call
143
103
  args = 1..1
144
104
 
145
105
  when :guess
146
106
  op.banner = "Usage: guess <partial-config.yml>"
147
- op.on('-l', '--log-level LEVEL', 'Log level (error, warn, info, debug or trace)') do |level|
148
- options[:logLevel] = level
149
- end
107
+ op.separator " Options:"
150
108
  op.on('-o', '--output PATH', 'Path to a file to write the guessed configuration') do |path|
151
- options[:nextConfigOutputPath] = path
152
- end
153
- op.on('-L', '--load PATH', 'Add a local plugin path') do |plugin_path|
154
- plugin_paths << plugin_path
155
- end
156
- op.on('-I', '--load-path PATH', 'Add ruby script directory path ($LOAD_PATH)') do |load_path|
157
- load_paths << load_path
158
- end
159
- op.on('-C', '--classpath PATH', "Add java classpath separated by #{classpath_separator} (CLASSPATH)") do |classpath|
160
- classpaths.concat classpath.split(classpath_separator)
109
+ options[:next_config_output_path] = path
161
110
  end
162
111
  op.on('-g', '--guess NAMES', "Comma-separated list of guess plugin names") do |names|
163
- (options[:guessPlugins] ||= []).concat names.split(",")
164
- end
165
- op.on('-X KEY=VALUE', 'Add a performance system config') do |kv|
166
- k, v = kv.split('=', 2)
167
- v ||= "true"
168
- options[:systemProperty][k] = v
112
+ (options[:system_config][:guess_plugins] ||= []).concat names.split(",") # TODO
169
113
  end
114
+ plugin_load_ops.call
115
+ java_embed_ops.call
170
116
  args = 1..1
171
117
 
118
+ when :bundle
119
+ if argv[0] == 'new'
120
+ usage nil if argv.length != 2
121
+ new_bundle(argv[1])
122
+ else
123
+ gemfile_path = ENV['BUNDLE_GEMFILE'].to_s
124
+
125
+ if !gemfile_path.empty?
126
+ bundle_path = File.dirname(gemfile_path)
127
+ elsif File.exists?('Gemfile')
128
+ bundle_path = '.'
129
+ else
130
+ system_exit "'#{path}' already exists. You already ran 'embulk bundle new'. Please remove it, or run \"cd #{path}\" and \"embulk bundle\" instead"
131
+ end
132
+
133
+ run_bundler(argv)
134
+ end
135
+ system_exit_success
136
+
137
+ when :gem
138
+ require 'rubygems/gem_runner'
139
+ Gem::GemRunner.new.run argv
140
+ system_exit_success
141
+
172
142
  when :new
173
- op.remove # remove --bundle
174
143
  op.banner = "Usage: new <category> <name>" + %[
175
144
  categories:
176
145
  ruby-input Ruby record input plugin (like "mysql")
@@ -198,20 +167,16 @@ examples:
198
167
  ]
199
168
  args = 2..2
200
169
 
170
+ when :migrate
171
+ op.banner = "Usage: migrate <directory>"
172
+ args = 1..1
173
+
201
174
  when :selfupdate
202
- op.remove # remove --bundle
203
175
  op.on('-f', "Skip corruption check", TrueClass) do |b|
204
- options[:force] = true
176
+ system[:force] = true
205
177
  end
206
178
  args = 0..0
207
179
 
208
- when :gem
209
- #require 'embulk/gems'
210
- #Embulk.add_embedded_gem_path
211
- require 'rubygems/gem_runner'
212
- Gem::GemRunner.new.run argv
213
- exit 0
214
-
215
180
  when :example
216
181
  args = 0..1
217
182
 
@@ -222,10 +187,10 @@ examples:
222
187
  when :irb
223
188
  require 'irb'
224
189
  IRB.start
225
- exit 0
190
+ system_exit_success
226
191
 
227
192
  else
228
- usage "Unknown subcommand #{subcmd.dump}."
193
+ usage "Unknown subcommand #{subcmd.to_s.dump}."
229
194
  end
230
195
 
231
196
  begin
@@ -237,76 +202,9 @@ examples:
237
202
  usage_op op, e.to_s
238
203
  end
239
204
 
240
- case subcmd.to_sym
241
- when :bundle
242
- path = argv[0] || default_bundle_path
243
-
244
- require 'fileutils'
245
- require 'rubygems/gem_runner'
246
- setup_plugin_paths(plugin_paths)
247
- setup_load_paths(load_paths)
248
- setup_classpaths(classpaths)
249
-
250
- unless File.exists?(path)
251
- puts "Initializing #{path}..."
252
- FileUtils.mkdir_p File.dirname(path)
253
- begin
254
- success = false
255
-
256
- # copy embulk/data/bundle/ directory
257
- require 'embulk/data/package_data'
258
- pkg = PackageData.new("bundle", path)
259
- %w[.bundle/config embulk/input/example.rb embulk/output/example.rb embulk/filter/example.rb Gemfile].each do |file|
260
- pkg.cp(file, file)
261
- end
262
-
263
- ## TODO this is disabled for now. enable this if you want to use
264
- ## create bin/embulk
265
- #bin_embulk_path = File.join(path, 'bin', 'embulk')
266
- #FileUtils.mkdir_p File.dirname(bin_embulk_path)
267
- #require 'embulk/command/embulk_generate_bin' # defines Embulk.generate_bin
268
- #File.open(bin_embulk_path, 'wb', 0755) {|f| f.write Embulk.generate_bin(bundle_path: :here) }
269
-
270
- # install bundler
271
- setup_gem_paths(path)
272
- Gem::GemRunner.new.run %w[install bundler]
273
-
274
- success = true
275
- rescue Gem::SystemExitException => e
276
- raise e if e.exit_code != 0
277
- success = true
278
- ensure
279
- FileUtils.rm_rf path unless success
280
- end
281
- else
282
- setup_gem_paths(path)
283
- end
284
-
285
- ENV['BUNDLE_GEMFILE'] = File.expand_path File.join(path, "Gemfile")
286
- Dir.chdir(path) do
287
- begin
288
- require 'bundler'
289
- rescue LoadError
290
- require 'rubygems/gem_runner'
291
- begin
292
- puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%3N %z")}: installing bundler..."
293
- Gem::GemRunner.new.run %w[install bundler]
294
- rescue Gem::SystemExitException => e
295
- raise e if e.exit_code != 0
296
- end
297
- Gem.clear_paths
298
- require 'bundler'
299
- end
300
- require 'bundler/friendly_errors'
301
- require 'bundler/cli'
302
- Bundler.with_friendly_errors do
303
- # run > bundle install
304
- Bundler::CLI.start(%w[install], debug: true)
305
- end
306
- end
307
-
205
+ case subcmd
308
206
  when :example
309
- require_relative 'embulk_example'
207
+ require 'embulk/command/embulk_example'
310
208
  path = ARGV[0] || "embulk-example"
311
209
  puts "Creating #{path} directory..."
312
210
  Embulk.create_example(path)
@@ -348,26 +246,33 @@ examples:
348
246
  require 'embulk/command/embulk_new_plugin'
349
247
  Embulk.new_plugin(name, language, category)
350
248
 
249
+ when :migrate
250
+ path = ARGV[0]
251
+ require 'embulk/command/embulk_migrate_plugin'
252
+ Embulk.migrate_plugin(path)
253
+
351
254
  when :selfupdate
352
255
  require 'embulk/command/embulk_selfupdate'
353
- Embulk.selfupdate(options)
256
+ Embulk.selfupdate(system)
354
257
 
355
258
  else
356
259
  require 'json'
357
260
 
358
- begin
359
- java.lang.Class.forName('org.embulk.command.Runner')
360
- rescue java.lang.ClassNotFoundException
361
- # load classpath
362
- Embulk.require_classpath
363
- end
261
+ Embulk.setup(options.delete(:system_config))
364
262
 
365
263
  setup_plugin_paths(plugin_paths)
366
264
  setup_load_paths(load_paths)
367
265
  setup_classpaths(classpaths)
368
266
 
369
267
  begin
370
- org.embulk.command.Runner.new(options.to_json).main(subcmd, argv.to_java(:string))
268
+ case subcmd
269
+ when :guess
270
+ Embulk::Runner.guess(argv[0], options)
271
+ when :preview
272
+ Embulk::Runner.preview(argv[0], options)
273
+ when :run
274
+ Embulk::Runner.run(argv[0], options)
275
+ end
371
276
  rescue => ex
372
277
  print_exception(ex)
373
278
  puts ""
@@ -377,25 +282,6 @@ examples:
377
282
  end
378
283
  end
379
284
 
380
- def self.home(dir)
381
- jar, resource = __FILE__.split("!")
382
- if resource && jar =~ /^file:/
383
- home = resource.split("/")[0..-3].join("/")
384
- "#{jar}!#{home}/#{dir}"
385
- else
386
- home = File.expand_path('../../..', File.dirname(__FILE__))
387
- File.join(home, dir)
388
- end
389
- end
390
-
391
- def self.require_classpath
392
- classpath_dir = Embulk.home("classpath")
393
- jars = Dir.entries(classpath_dir).select{|f| f =~ /\.jar$/ }.sort
394
- jars.each do |jar|
395
- require File.join(classpath_dir, jar)
396
- end
397
- end
398
-
399
285
  def self.default_gem_home
400
286
  if RUBY_PLATFORM =~ /java/i
401
287
  user_home = java.lang.System.properties["user.home"]
@@ -426,13 +312,6 @@ examples:
426
312
  end
427
313
  end
428
314
 
429
- def self.setup_gem_paths(path)
430
- # install bundler gem here & use bundler installed here
431
- ENV['GEM_HOME'] = File.expand_path File.join(path, Gem.ruby_engine, RbConfig::CONFIG['ruby_version'])
432
- ENV['GEM_PATH'] = ''
433
- Gem.clear_paths # force rubygems to reload GEM_HOME
434
- end
435
-
436
315
  def self.setup_plugin_paths(plugin_paths)
437
316
  plugin_paths.each do |path|
438
317
  unless File.directory?(path)
@@ -444,9 +323,12 @@ examples:
444
323
  end
445
324
  specs.each do |spec|
446
325
  gem_path = File.dirname(spec)
447
- stub = Gem::StubSpecification.new(spec)
448
- stub.define_singleton_method(:full_gem_path) { gem_path }
449
- Gem::Specification.add_spec(stub)
326
+ Dir.chdir(path) do
327
+ # cd to path because spec could include `git ...`
328
+ stub = Gem::StubSpecification.new(spec)
329
+ stub.define_singleton_method(:full_gem_path) { gem_path }
330
+ Gem::Specification.add_spec(stub)
331
+ end
450
332
  end
451
333
  end
452
334
  end
@@ -465,6 +347,79 @@ examples:
465
347
  end
466
348
  end
467
349
 
350
+ def self.new_bundle(path)
351
+ require 'fileutils'
352
+ require 'rubygems/gem_runner'
353
+
354
+ if File.exists?(path)
355
+ error = "'#{path}' already exists. You already ran 'embulk bundle new'. Please remove it, or run \"cd #{path}\" and \"embulk bundle\" instead"
356
+ STDERR.puts error
357
+ raise SystemExit.new(1, error)
358
+ end
359
+
360
+ puts "Initializing #{path}..."
361
+ FileUtils.mkdir_p path
362
+ begin
363
+ success = false
364
+
365
+ # copy embulk/data/bundle/ contents
366
+ require 'embulk/data/package_data'
367
+ pkg = PackageData.new("bundle", path)
368
+ %w[Gemfile .ruby-version .bundle/config embulk/input/example.rb embulk/output/example.rb embulk/filter/example.rb].each do |file|
369
+ pkg.cp(file, file)
370
+ end
371
+
372
+ # run the first bundle-install
373
+ Dir.chdir(path) do
374
+ run_bundler(['install', '--path', '.'])
375
+ end
376
+
377
+ success = true
378
+ rescue Gem::SystemExitException => e
379
+ raise e if e.exit_code != 0
380
+ success = true
381
+ ensure
382
+ FileUtils.rm_rf path unless success
383
+ end
384
+ end
385
+
386
+ def self.run_bundler(argv)
387
+ # try to load bundler from LOAD_PATH and ./jruby
388
+ begin
389
+ require 'bundler'
390
+ bundler_provided = true
391
+ rescue LoadError
392
+ ENV['GEM_HOME'] = File.expand_path File.join(".", Gem.ruby_engine, RbConfig::CONFIG['ruby_version'])
393
+ ENV['GEM_PATH'] = ''
394
+ ENV.delete('BUNDLE_GEMFILE')
395
+ Gem.clear_paths # force rubygems to reload GEM_HOME
396
+ begin
397
+ require 'bundler'
398
+ bundler_provided = true
399
+ rescue LoadError
400
+ end
401
+ end
402
+
403
+ unless bundler_provided
404
+ # install bundler to the path (bundler is not included in embulk-core.jar)
405
+ require 'rubygems/gem_runner'
406
+ begin
407
+ puts "Installing bundler..."
408
+ Gem::GemRunner.new.run %w[install bundler]
409
+ rescue Gem::SystemExitException => e
410
+ raise e if e.exit_code != 0
411
+ end
412
+ Gem.clear_paths
413
+ require 'bundler'
414
+ end
415
+
416
+ require 'bundler/friendly_errors'
417
+ require 'bundler/cli'
418
+ Bundler.with_friendly_errors do
419
+ Bundler::CLI.start(argv, debug: true)
420
+ end
421
+ end
422
+
468
423
  def self.usage(message)
469
424
  STDERR.puts "Embulk v#{Embulk::VERSION}"
470
425
  STDERR.puts "usage: <command> [--options]"
@@ -476,24 +431,21 @@ examples:
476
431
  STDERR.puts " gem <install | list | help> # install a plugin or show installed plugins."
477
432
  STDERR.puts " # plugin path is #{ENV['GEM_HOME']}"
478
433
  STDERR.puts " new <category> <name> # generates new plugin template"
434
+ STDERR.puts " migrate <path> # modify plugin code to use the latest Embulk plugin API"
479
435
  STDERR.puts " example [path] # creates an example config file and csv file to try embulk."
480
436
  STDERR.puts " selfupdate # upgrades embulk to the latest released version."
481
437
  STDERR.puts ""
482
438
  if message
483
- STDERR.puts "error: #{message}"
439
+ system_exit "error: #{message}"
484
440
  else
485
- STDERR.puts "Use \`<command> --help\` to see description of the commands."
441
+ system_exit "Use \`<command> --help\` to see description of the commands."
486
442
  end
487
- exit 1
488
443
  end
489
444
 
490
445
  def self.usage_op(op, message)
491
446
  STDERR.puts op.help
492
447
  STDERR.puts
493
- if message
494
- STDERR.puts message
495
- end
496
- exit 1
448
+ system_exit message
497
449
  end
498
450
 
499
451
  def self.print_exception(ex)
@@ -506,4 +458,13 @@ examples:
506
458
  end
507
459
  end
508
460
  end
461
+
462
+ def self.system_exit(message=nil)
463
+ STDERR.puts message if message
464
+ raise SystemExit.new(1, message)
465
+ end
466
+
467
+ def self.system_exit_success
468
+ raise SystemExit.new(0)
469
+ end
509
470
  end