rexer 0.2.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd717744bdbbcbb0470f21f2cf7c8345b4852901a7cd86088751ca971d07b5cf
4
- data.tar.gz: ec7eac6cb58e0eed5ad5ad58de7479fc6223521497deb49728fb62a6fc2616dd
3
+ metadata.gz: 4086f1f1bc3ef9be9579087c03f189f311e98276cadb9295acb2d33ae319e28e
4
+ data.tar.gz: 23b848de6c3e635b312ef127e5d7f6e616ee8d1a64d5e21dc4d90dc5196b48a2
5
5
  SHA512:
6
- metadata.gz: f9db79d00f966ffa25c12cc5978103169e796f621e7e5e7dc842225067dbce3dcded6453cd61caa15e13434725bfc74da416b9c196a287279627359de3db5e2d
7
- data.tar.gz: 1d02b36a1baf9a5350d6729dd565f0cad4327a99c07ed28694d89f34253f2fcc8c08dd7bb68e978a4ace19c9ff3985d45a1041595c9c05dc8e40226484da5f84
6
+ metadata.gz: 1b0067a5d35d0ef2646f9e0a46da872be4b58bcce261be2a23cb9f57b314a612879af881628244dffa0dab11b4a2afc947317de2f0265e41807a62fd29cb85e1
7
+ data.tar.gz: 45fde51fb5bdf467cb0a8b00ef20d9498f7a06ebf39b555da6fa0435a0aef9a82ca2baa77ee9b8143e5200ab93ca36f516629b62c07f9c611a2320fae1ea1aef
data/README.md CHANGED
@@ -117,13 +117,21 @@ plugin :redmica_s3, github: { repo: "redmica/redmica_s3" } do
117
117
  uninstalled do
118
118
  Pathname.new("config", "s3.yml").delete
119
119
  end
120
-
121
- updated do
122
- puts "updated"
123
- end
124
120
  end
125
121
  ```
126
122
 
123
+ ## Configuring the command prefix
124
+
125
+ You can configure the command prefix for the commands that Rexer runs such as `bundle install` and `bin/rails redmine:plugins:migrate`.
126
+
127
+ ```ruby
128
+ config command_prefix: "docker compose exec -T app"
129
+
130
+ plugin :some_plugin_with_db_migration, github: { repo: "some_plugin" }
131
+ ```
132
+
133
+ In the above example, the `bin/rails redmine:plugins:migrate` command is executed as `docker compose exec -T app bin/rails redmine:plugins:migrate`.
134
+
127
135
  ## Developing
128
136
 
129
137
  ### Running tests
@@ -17,7 +17,7 @@ module Rexer
17
17
  private
18
18
 
19
19
  def install_initially(definition)
20
- install(definition.themes, definition.plugins)
20
+ install(definition.themes, definition.plugins, definition.config)
21
21
 
22
22
  create_lock_file(definition.env)
23
23
  print_state
@@ -26,9 +26,9 @@ module Rexer
26
26
  def apply_diff(lock_definition, definition)
27
27
  diff = lock_definition.diff(definition)
28
28
 
29
- install(diff.added_themes, diff.added_plugins)
30
- uninstall(diff.deleted_themes, diff.deleted_plugins)
31
- update(diff.changed_themes, diff.changed_plugins)
29
+ install(diff.added_themes, diff.added_plugins, definition.config)
30
+ uninstall(diff.deleted_themes, diff.deleted_plugins, definition.config)
31
+ reload_source(diff.source_changed_themes, diff.source_changed_plugins)
32
32
 
33
33
  create_lock_file(definition.env)
34
34
  print_state
@@ -44,33 +44,33 @@ module Rexer
44
44
  Definition::Lock.load_data if Definition::Lock.file.exist?
45
45
  end
46
46
 
47
- def install(themes, plugins)
47
+ def install(themes, plugins, config)
48
48
  themes.each do
49
49
  Extension::Theme::Installer.new(_1).install
50
50
  end
51
51
 
52
52
  plugins.each do
53
- Extension::Plugin::Installer.new(_1).install
53
+ Extension::Plugin::Installer.new(_1, config).install
54
54
  end
55
55
  end
56
56
 
57
- def uninstall(themes, plugins)
57
+ def uninstall(themes, plugins, config)
58
58
  themes.each do
59
59
  Extension::Theme::Uninstaller.new(_1).uninstall
60
60
  end
61
61
 
62
62
  plugins.each do
63
- Extension::Plugin::Uninstaller.new(_1).uninstall
63
+ Extension::Plugin::Uninstaller.new(_1, config).uninstall
64
64
  end
65
65
  end
66
66
 
67
- def update(themes, plugins)
67
+ def reload_source(themes, plugins)
68
68
  themes.each do
69
- Extension::Theme::Updater.new(_1).update
69
+ Extension::Theme::SourceReloader.new(_1).reload
70
70
  end
71
71
 
72
72
  plugins.each do
73
- Extension::Plugin::Updater.new(_1).update
73
+ Extension::Plugin::SourceReloader.new(_1).reload
74
74
  end
75
75
  end
76
76
 
@@ -39,10 +39,8 @@ module Rexer
39
39
  end
40
40
  end
41
41
 
42
- def source_info(source_def)
43
- source_def.then {
44
- Source.const_get(_1.type.capitalize).new(**_1.options).info
45
- }
42
+ def source_info(definition_source)
43
+ Source.from_definition(definition_source).info
46
44
  end
47
45
 
48
46
  def no_lock_file_found
@@ -2,11 +2,12 @@ module Rexer
2
2
  module Definition
3
3
  class Data
4
4
  attr_accessor :env
5
- attr_reader :version
5
+ attr_reader :config, :version
6
6
 
7
- def initialize(plugins, themes, env: nil, version: nil)
7
+ def initialize(plugins, themes, config, env: nil, version: nil)
8
8
  @plugins = plugins
9
9
  @themes = themes
10
+ @config = config
10
11
  @env = env
11
12
  @version = version
12
13
  end
@@ -22,21 +22,21 @@ module Rexer
22
22
  old_data.themes - new_data.themes
23
23
  end
24
24
 
25
- def changed_plugins
25
+ def source_changed_plugins
26
26
  old_plugins = old_data.plugins
27
27
 
28
28
  (new_data.plugins & old_plugins).select do |new_plugin|
29
29
  old_plugin = old_plugins.find { _1.name == new_plugin.name }
30
- plugin_changed?(old_plugin, new_plugin)
30
+ plugin_source_changed?(old_plugin, new_plugin)
31
31
  end
32
32
  end
33
33
 
34
- def changed_themes
34
+ def source_changed_themes
35
35
  old_themes = old_data.themes
36
36
 
37
37
  (new_data.themes & old_themes).select do |new_theme|
38
38
  old_theme = old_themes.find { _1.name == new_theme.name }
39
- theme_changed?(old_theme, new_theme)
39
+ theme_source_changed?(old_theme, new_theme)
40
40
  end
41
41
  end
42
42
 
@@ -44,11 +44,11 @@ module Rexer
44
44
 
45
45
  attr_reader :old_data, :new_data
46
46
 
47
- def plugin_changed?(old_plugin, new_plugin)
47
+ def plugin_source_changed?(old_plugin, new_plugin)
48
48
  old_plugin.source != new_plugin.source
49
49
  end
50
50
 
51
- def theme_changed?(old_theme, new_theme)
51
+ def theme_source_changed?(old_theme, new_theme)
52
52
  old_theme.source != new_theme.source
53
53
  end
54
54
  end
@@ -5,13 +5,14 @@ module Rexer
5
5
  @plugins = []
6
6
  @themes = []
7
7
  @env = env
8
+ @config = nil
8
9
  end
9
10
 
10
11
  def plugin(name, **opts, &hooks)
11
12
  @plugins << Definition::Plugin.new(
12
13
  name: name,
13
14
  source: build_source(opts),
14
- hooks: build_hooks(hooks, %i[installed uninstalled updated]),
15
+ hooks: build_hooks(hooks, %i[installed uninstalled]),
15
16
  env: @env
16
17
  )
17
18
  end
@@ -20,7 +21,7 @@ module Rexer
20
21
  @themes << Definition::Theme.new(
21
22
  name: name,
22
23
  source: build_source(opts),
23
- hooks: build_hooks(hooks, %i[installed uninstalled updated]),
24
+ hooks: build_hooks(hooks, %i[installed uninstalled]),
24
25
  env: @env
25
26
  )
26
27
  end
@@ -32,8 +33,12 @@ module Rexer
32
33
  @themes += data.themes
33
34
  end
34
35
 
36
+ def config(command_prefix: nil)
37
+ @config = Definition::Config.new(command_prefix)
38
+ end
39
+
35
40
  def to_data
36
- Definition::Data.new(@plugins, @themes)
41
+ Definition::Data.new(@plugins, @themes, @config)
37
42
  end
38
43
 
39
44
  private
@@ -54,7 +59,7 @@ module Rexer
54
59
  end
55
60
 
56
61
  def build_source(opts)
57
- type = opts.keys.find { Rexer::Source::Base.source_names.include?(_1) }
62
+ type = opts.keys.find { Rexer::Source.names.include?(_1) }
58
63
  Source.new(type, opts[type]) if type
59
64
  end
60
65
  end
@@ -27,7 +27,7 @@ module Rexer
27
27
  end
28
28
 
29
29
  def to_data
30
- Definition::Data.new(@plugins, @themes, **lock_state)
30
+ Definition::Data.new(@plugins, @themes, @config, **lock_state)
31
31
  end
32
32
 
33
33
  private
@@ -10,6 +10,17 @@ module Rexer
10
10
  end
11
11
  end
12
12
 
13
+ Config = ::Data.define(
14
+ # The prefix of the command such as bundle install and bin/rails redmine:plugins:migrate.
15
+ #
16
+ # For example, if the command_prefix is set "docker compose exec -T app",
17
+ # then bundle install will be executed as follows:
18
+ #
19
+ # docker compose exec -T app bundle install
20
+ #
21
+ :command_prefix
22
+ )
23
+
13
24
  Source = ::Data.define(:type, :options)
14
25
 
15
26
  Plugin = ::Data.define(:name, :source, :hooks, :env) do
@@ -8,15 +8,16 @@ module Rexer
8
8
  end
9
9
 
10
10
  class Base
11
- def initialize(definition)
11
+ def initialize(definition, config = nil)
12
12
  @definition = definition
13
13
  @name = definition.name
14
14
  @hooks = definition.hooks || {}
15
+ @config = config
15
16
  end
16
17
 
17
18
  private
18
19
 
19
- attr_reader :name, :hooks, :definition
20
+ attr_reader :name, :hooks, :definition, :config
20
21
 
21
22
  def plugin_dir
22
23
  @plugin_dir ||= Plugin.dir.join(name.to_s)
@@ -36,15 +37,17 @@ module Rexer
36
37
  return unless needs_db_migration?
37
38
 
38
39
  envs = {"NAME" => name.to_s}.merge(extra_envs)
39
- _, error, status = Open3.capture3(envs, "bin/rails redmine:plugins:migrate")
40
+ _, error, status = Open3.capture3(envs, cmd_with_prefix("bin/rails redmine:plugins:migrate"))
40
41
 
41
42
  raise error unless status.success?
42
43
  end
43
44
 
44
45
  def source
45
- @source ||= definition.source.then do |src|
46
- Source.const_get(src.type.capitalize).new(**src.options)
47
- end
46
+ @source ||= Source.from_definition(definition.source)
47
+ end
48
+
49
+ def cmd_with_prefix(command)
50
+ [config&.command_prefix, command].compact.join(" ")
48
51
  end
49
52
  end
50
53
 
@@ -53,6 +56,7 @@ module Rexer
53
56
  return if plugin_exists?
54
57
 
55
58
  load_from_source
59
+ run_bundle_install
56
60
  run_db_migrate
57
61
  hooks[:installed]&.call
58
62
  end
@@ -62,6 +66,13 @@ module Rexer
62
66
  def load_from_source
63
67
  source.load(plugin_dir.to_s)
64
68
  end
69
+
70
+ def run_bundle_install
71
+ return unless plugin_dir.join("Gemfile").exist?
72
+
73
+ _, error, status = Open3.capture3(cmd_with_prefix("bundle install"))
74
+ raise error unless status.success?
75
+ end
65
76
  end
66
77
 
67
78
  class Uninstaller < Base
@@ -90,7 +101,6 @@ module Rexer
90
101
 
91
102
  update_source
92
103
  run_db_migrate
93
- hooks[:updated]&.call
94
104
  end
95
105
 
96
106
  private
@@ -99,6 +109,24 @@ module Rexer
99
109
  source.update(plugin_dir.to_s)
100
110
  end
101
111
  end
112
+
113
+ class SourceReloader < Base
114
+ def reload
115
+ return unless plugin_exists?
116
+
117
+ reload_source
118
+ run_db_migrate
119
+ end
120
+
121
+ private
122
+
123
+ def reload_source
124
+ plugin_dir.to_s.then { |dir|
125
+ FileUtils.rm_rf(dir)
126
+ source.load(dir)
127
+ }
128
+ end
129
+ end
102
130
  end
103
131
  end
104
132
  end
@@ -32,9 +32,7 @@ module Rexer
32
32
  end
33
33
 
34
34
  def source
35
- @source ||= definition.source.then do |src|
36
- Source.const_get(src.type.capitalize).new(**src.options)
37
- end
35
+ @source ||= Source.from_definition(definition.source)
38
36
  end
39
37
  end
40
38
 
@@ -73,7 +71,6 @@ module Rexer
73
71
  return unless theme_exists?
74
72
 
75
73
  update_source
76
- hooks[:updated]&.call
77
74
  end
78
75
 
79
76
  private
@@ -82,6 +79,23 @@ module Rexer
82
79
  source.update(theme_dir.to_s)
83
80
  end
84
81
  end
82
+
83
+ class SourceReloader < Base
84
+ def reload
85
+ return unless theme_exists?
86
+
87
+ reload_source
88
+ end
89
+
90
+ private
91
+
92
+ def reload_source
93
+ theme_dir.to_s.then { |dir|
94
+ FileUtils.rm_rf(dir)
95
+ source.load(dir)
96
+ }
97
+ end
98
+ end
85
99
  end
86
100
  end
87
101
  end
@@ -1,16 +1,16 @@
1
1
  module Rexer
2
2
  module Source
3
3
  class Base
4
- def self.source_names = @source_names ||= []
5
-
6
4
  def self.inherited(subclass)
7
- source_names << subclass.name.split("::").last.downcase.to_sym
5
+ Source.names << subclass.name.split("::").last.downcase.to_sym
8
6
  end
9
7
 
8
+ # Load the source to the given path.
10
9
  def load(_path)
11
10
  raise "Not implemented"
12
11
  end
13
12
 
13
+ # Update to the latest version of the source.
14
14
  def update(_path)
15
15
  raise "Not implemented"
16
16
  end
@@ -0,0 +1,9 @@
1
+ module Rexer
2
+ module Source
3
+ def self.names = @names ||= []
4
+
5
+ def self.from_definition(source)
6
+ const_get(source.type.capitalize).new(**source.options)
7
+ end
8
+ end
9
+ end
data/lib/rexer/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rexer
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rexer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katsuya Hidaka
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-14 00:00:00.000000000 Z
11
+ date: 2024-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -82,6 +82,7 @@ files:
82
82
  - lib/rexer/definition/lock.rb
83
83
  - lib/rexer/extension/plugin.rb
84
84
  - lib/rexer/extension/theme.rb
85
+ - lib/rexer/source.rb
85
86
  - lib/rexer/source/base.rb
86
87
  - lib/rexer/source/git.rb
87
88
  - lib/rexer/source/github.rb