foreman 0.88.1 → 0.90.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/data/export/bluepill/master.pill.erb +1 -1
  3. data/lib/foreman/cli.rb +13 -9
  4. data/lib/foreman/export/base.rb +0 -36
  5. data/lib/foreman/version.rb +1 -1
  6. data/man/foreman.1 +1 -1
  7. data/spec/foreman/cli_spec.rb +5 -5
  8. data/spec/foreman/process_spec.rb +0 -1
  9. metadata +18 -39
  10. data/lib/foreman/vendor/thor/lib/thor/actions/create_file.rb +0 -103
  11. data/lib/foreman/vendor/thor/lib/thor/actions/create_link.rb +0 -59
  12. data/lib/foreman/vendor/thor/lib/thor/actions/directory.rb +0 -118
  13. data/lib/foreman/vendor/thor/lib/thor/actions/empty_directory.rb +0 -135
  14. data/lib/foreman/vendor/thor/lib/thor/actions/file_manipulation.rb +0 -327
  15. data/lib/foreman/vendor/thor/lib/thor/actions/inject_into_file.rb +0 -103
  16. data/lib/foreman/vendor/thor/lib/thor/actions.rb +0 -318
  17. data/lib/foreman/vendor/thor/lib/thor/base.rb +0 -656
  18. data/lib/foreman/vendor/thor/lib/thor/command.rb +0 -133
  19. data/lib/foreman/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +0 -85
  20. data/lib/foreman/vendor/thor/lib/thor/core_ext/io_binary_read.rb +0 -12
  21. data/lib/foreman/vendor/thor/lib/thor/core_ext/ordered_hash.rb +0 -129
  22. data/lib/foreman/vendor/thor/lib/thor/error.rb +0 -32
  23. data/lib/foreman/vendor/thor/lib/thor/group.rb +0 -281
  24. data/lib/foreman/vendor/thor/lib/thor/invocation.rb +0 -177
  25. data/lib/foreman/vendor/thor/lib/thor/line_editor/basic.rb +0 -35
  26. data/lib/foreman/vendor/thor/lib/thor/line_editor/readline.rb +0 -88
  27. data/lib/foreman/vendor/thor/lib/thor/line_editor.rb +0 -17
  28. data/lib/foreman/vendor/thor/lib/thor/parser/argument.rb +0 -70
  29. data/lib/foreman/vendor/thor/lib/thor/parser/arguments.rb +0 -175
  30. data/lib/foreman/vendor/thor/lib/thor/parser/option.rb +0 -146
  31. data/lib/foreman/vendor/thor/lib/thor/parser/options.rb +0 -220
  32. data/lib/foreman/vendor/thor/lib/thor/parser.rb +0 -4
  33. data/lib/foreman/vendor/thor/lib/thor/rake_compat.rb +0 -71
  34. data/lib/foreman/vendor/thor/lib/thor/runner.rb +0 -322
  35. data/lib/foreman/vendor/thor/lib/thor/shell/basic.rb +0 -436
  36. data/lib/foreman/vendor/thor/lib/thor/shell/color.rb +0 -149
  37. data/lib/foreman/vendor/thor/lib/thor/shell/html.rb +0 -126
  38. data/lib/foreman/vendor/thor/lib/thor/shell.rb +0 -81
  39. data/lib/foreman/vendor/thor/lib/thor/util.rb +0 -268
  40. data/lib/foreman/vendor/thor/lib/thor/version.rb +0 -3
  41. data/lib/foreman/vendor/thor/lib/thor.rb +0 -492
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0dfe6fcff4e6a0293ccee732ad38fe72e7a05b2beb662ba2bdf8cc54437e7242
4
- data.tar.gz: 2abc2ad27e0c30aebf936508467b7a74217d9c6f1fbabeaf80e1c771247f22cd
3
+ metadata.gz: e5361d21cc82555a253f0ddeb76d8ddc3a3c099fcbb3bc217491fdd5bc1cc3d5
4
+ data.tar.gz: a9eeb94380ccbf6b021bcd8be79e7a827f44767f8f563b5e00c2d429050cbeb4
5
5
  SHA512:
6
- metadata.gz: d5f8cdb2f096a15c7f83e7ee3d8c870b37d2a3e1c7085af59e8c34810f88110a87d1db30e44e2f4bf5beb4abede9f0976456e675b174512cee5745d4c8223345
7
- data.tar.gz: ed5640039e33ef6a492449ddeae69718f8a8a6a333ddce677f21860e707620f730fd124f19cac9687849783372115eba1e846c72d198325346234ed5c146ed4f
6
+ metadata.gz: 72f23c7afd63aa9bf625cfca6892e7bbed7792edb246a263fae16d4b3d574e527ed52ba0a356091c00ecc9252c1b553f88dbc7c788354f565890e3e2304c6687
7
+ data.tar.gz: 488872c4619b43bd911dd328462a204d1b431f246745d8d2c1539d441bd245e5228ca6a311597bd7c28865d6dc289c68c35f94f0dae34dc1d5d6e8888ef39e26
@@ -11,7 +11,7 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
11
11
 
12
12
  process.working_dir = "<%= engine.root %>"
13
13
  process.daemonize = true
14
- process.environment = <%= engine.env.merge("PORT" => port.to_s).inspect %>
14
+ process.environment = {<%= engine.env.merge("PORT" => port.to_s).map { |k,v| "#{k.inspect}=>#{v.inspect}" }.join(",") %>}
15
15
  process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
16
16
  process.stop_grace_time = 45.seconds
17
17
 
data/lib/foreman/cli.rb CHANGED
@@ -5,10 +5,10 @@ require "foreman/engine/cli"
5
5
  require "foreman/export"
6
6
  require "foreman/version"
7
7
  require "shellwords"
8
+ require "thor"
8
9
  require "yaml"
9
- require "foreman/vendor/thor/lib/thor"
10
10
 
11
- class Foreman::CLI < Foreman::Thor
11
+ class Foreman::CLI < Thor
12
12
 
13
13
  include Foreman::Helpers
14
14
 
@@ -27,6 +27,10 @@ class Foreman::CLI < Foreman::Thor
27
27
  method_option :timestamp, :type => :boolean, :default => true, :desc => "Include timestamp in output"
28
28
 
29
29
  class << self
30
+ def exit_on_failure?
31
+ true
32
+ end
33
+
30
34
  # Hackery. Take the run method away from Thor so that we can redefine it.
31
35
  def is_thor_reserved_word?(word, type)
32
36
  return false if word == "run"
@@ -126,6 +130,13 @@ class Foreman::CLI < Foreman::Thor
126
130
  engine
127
131
  end
128
132
  end
133
+
134
+ def options
135
+ original_options = super
136
+ return original_options unless File.file?(".foreman")
137
+ defaults = ::YAML::load_file(".foreman") || {}
138
+ Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
139
+ end
129
140
  end
130
141
 
131
142
  private ######################################################################
@@ -157,11 +168,4 @@ private ######################################################################
157
168
  else "Procfile"
158
169
  end
159
170
  end
160
-
161
- def options
162
- original_options = super
163
- return original_options unless File.file?(".foreman")
164
- defaults = ::YAML::load_file(".foreman") || {}
165
- Foreman::Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
166
- end
167
171
  end
@@ -1,5 +1,4 @@
1
1
  require "foreman/export"
2
- require "ostruct"
3
2
  require "pathname"
4
3
  require "shellwords"
5
4
 
@@ -18,29 +17,6 @@ class Foreman::Export::Base
18
17
  @engine = engine
19
18
  @options = options.dup
20
19
  @formation = engine.formation
21
-
22
- # deprecated
23
- def port
24
- Foreman::Export::Base.warn_deprecation!
25
- engine.base_port
26
- end
27
-
28
- # deprecated
29
- def template
30
- Foreman::Export::Base.warn_deprecation!
31
- options[:template]
32
- end
33
-
34
- # deprecated
35
- def @engine.procfile
36
- Foreman::Export::Base.warn_deprecation!
37
- @processes.map do |process|
38
- OpenStruct.new(
39
- :name => @names[process],
40
- :process => process
41
- )
42
- end
43
- end
44
20
  end
45
21
 
46
22
  def export
@@ -68,18 +44,6 @@ class Foreman::Export::Base
68
44
 
69
45
  private ######################################################################
70
46
 
71
- def self.warn_deprecation!
72
- @@deprecation_warned ||= false
73
- return if @@deprecation_warned
74
- puts "WARNING: Using deprecated exporter interface. Please update your exporter"
75
- puts "the interface shown in the upstart exporter:"
76
- puts
77
- puts "https://github.com/ddollar/foreman/blob/main/lib/foreman/export/upstart.rb"
78
- puts "https://github.com/ddollar/foreman/blob/main/data/export/upstart/process.conf.erb"
79
- puts
80
- @@deprecation_warned = true
81
- end
82
-
83
47
  def chown user, dir
84
48
  FileUtils.chown user, nil, dir
85
49
  rescue
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.88.1"
3
+ VERSION = "0.90.0"
4
4
 
5
5
  end
data/man/foreman.1 CHANGED
@@ -1,6 +1,6 @@
1
1
  .\" generated with Ronn-NG/v0.10.1
2
2
  .\" http://github.com/apjanke/ronn-ng/tree/0.10.1
3
- .TH "FOREMAN" "1" "April 2024" "Foreman 0.88.1" "Foreman Manual"
3
+ .TH "FOREMAN" "1" "July 2025" "Foreman 0.90.0" "Foreman Manual"
4
4
  .SH "NAME"
5
5
  \fBforeman\fR \- manage Procfile\-based applications
6
6
  .SH "SYNOPSIS"
@@ -77,15 +77,15 @@ describe "Foreman::CLI", :fakefs do
77
77
 
78
78
  describe "run" do
79
79
  it "can run a command" do
80
- expect(forked_foreman("run echo 1")).to eq("1\n")
80
+ expect(forked_foreman("run -f #{resource_path("Procfile")} echo 1")).to eq("1\n")
81
81
  end
82
82
 
83
83
  it "doesn't parse options for the command" do
84
- expect(forked_foreman("run grep -e FOO #{resource_path(".env")}")).to eq("FOO=bar\n")
84
+ expect(forked_foreman("run -f #{resource_path("Procfile")} grep -e FOO #{resource_path(".env")}")).to eq("FOO=bar\n")
85
85
  end
86
86
 
87
87
  it "includes the environment" do
88
- expect(forked_foreman("run -e #{resource_path(".env")} #{resource_path("bin/env FOO")}")).to eq("bar\n")
88
+ expect(forked_foreman("run -f #{resource_path("Procfile")} -e #{resource_path(".env")} #{resource_path("bin/env FOO")}")).to eq("bar\n")
89
89
  end
90
90
 
91
91
  it "can run a command from the Procfile" do
@@ -93,8 +93,8 @@ describe "Foreman::CLI", :fakefs do
93
93
  end
94
94
 
95
95
  it "exits with the same exit code as the command" do
96
- expect(fork_and_get_exitstatus("run echo 1")).to eq(0)
97
- expect(fork_and_get_exitstatus("run date 'invalid_date'")).to eq(1)
96
+ expect(fork_and_get_exitstatus("run -f #{resource_path("Procfile")} echo 1")).to eq(0)
97
+ expect(fork_and_get_exitstatus("run -f #{resource_path("Procfile")} date 'invalid_date'")).to eq(1)
98
98
  end
99
99
  end
100
100
 
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
2
  require 'foreman/process'
3
- require 'ostruct'
4
3
  require 'timeout'
5
4
  require 'tmpdir'
6
5
 
metadata CHANGED
@@ -1,15 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.88.1
4
+ version: 0.90.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Dollar
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-04-12 00:00:00.000000000 Z
12
- dependencies: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: thor
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.4'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.4'
13
26
  description: Process manager for applications with multiple components
14
27
  email: ddollar@gmail.com
15
28
  executables:
@@ -60,38 +73,6 @@ files:
60
73
  - lib/foreman/helpers.rb
61
74
  - lib/foreman/process.rb
62
75
  - lib/foreman/procfile.rb
63
- - lib/foreman/vendor/thor/lib/thor.rb
64
- - lib/foreman/vendor/thor/lib/thor/actions.rb
65
- - lib/foreman/vendor/thor/lib/thor/actions/create_file.rb
66
- - lib/foreman/vendor/thor/lib/thor/actions/create_link.rb
67
- - lib/foreman/vendor/thor/lib/thor/actions/directory.rb
68
- - lib/foreman/vendor/thor/lib/thor/actions/empty_directory.rb
69
- - lib/foreman/vendor/thor/lib/thor/actions/file_manipulation.rb
70
- - lib/foreman/vendor/thor/lib/thor/actions/inject_into_file.rb
71
- - lib/foreman/vendor/thor/lib/thor/base.rb
72
- - lib/foreman/vendor/thor/lib/thor/command.rb
73
- - lib/foreman/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
74
- - lib/foreman/vendor/thor/lib/thor/core_ext/io_binary_read.rb
75
- - lib/foreman/vendor/thor/lib/thor/core_ext/ordered_hash.rb
76
- - lib/foreman/vendor/thor/lib/thor/error.rb
77
- - lib/foreman/vendor/thor/lib/thor/group.rb
78
- - lib/foreman/vendor/thor/lib/thor/invocation.rb
79
- - lib/foreman/vendor/thor/lib/thor/line_editor.rb
80
- - lib/foreman/vendor/thor/lib/thor/line_editor/basic.rb
81
- - lib/foreman/vendor/thor/lib/thor/line_editor/readline.rb
82
- - lib/foreman/vendor/thor/lib/thor/parser.rb
83
- - lib/foreman/vendor/thor/lib/thor/parser/argument.rb
84
- - lib/foreman/vendor/thor/lib/thor/parser/arguments.rb
85
- - lib/foreman/vendor/thor/lib/thor/parser/option.rb
86
- - lib/foreman/vendor/thor/lib/thor/parser/options.rb
87
- - lib/foreman/vendor/thor/lib/thor/rake_compat.rb
88
- - lib/foreman/vendor/thor/lib/thor/runner.rb
89
- - lib/foreman/vendor/thor/lib/thor/shell.rb
90
- - lib/foreman/vendor/thor/lib/thor/shell/basic.rb
91
- - lib/foreman/vendor/thor/lib/thor/shell/color.rb
92
- - lib/foreman/vendor/thor/lib/thor/shell/html.rb
93
- - lib/foreman/vendor/thor/lib/thor/util.rb
94
- - lib/foreman/vendor/thor/lib/thor/version.rb
95
76
  - lib/foreman/version.rb
96
77
  - man/foreman.1
97
78
  - spec/foreman/cli_spec.rb
@@ -155,7 +136,6 @@ homepage: https://github.com/ddollar/foreman
155
136
  licenses:
156
137
  - MIT
157
138
  metadata: {}
158
- post_install_message:
159
139
  rdoc_options: []
160
140
  require_paths:
161
141
  - lib
@@ -170,8 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
150
  - !ruby/object:Gem::Version
171
151
  version: '0'
172
152
  requirements: []
173
- rubygems_version: 3.4.19
174
- signing_key:
153
+ rubygems_version: 3.6.9
175
154
  specification_version: 4
176
155
  summary: Process manager for applications with multiple components
177
156
  test_files: []
@@ -1,103 +0,0 @@
1
- require "foreman/vendor/thor/lib/thor/actions/empty_directory"
2
-
3
- class Foreman::Thor
4
- module Actions
5
- # Create a new file relative to the destination root with the given data,
6
- # which is the return value of a block or a data string.
7
- #
8
- # ==== Parameters
9
- # destination<String>:: the relative path to the destination root.
10
- # data<String|NilClass>:: the data to append to the file.
11
- # config<Hash>:: give :verbose => false to not log the status.
12
- #
13
- # ==== Examples
14
- #
15
- # create_file "lib/fun_party.rb" do
16
- # hostname = ask("What is the virtual hostname I should use?")
17
- # "vhost.name = #{hostname}"
18
- # end
19
- #
20
- # create_file "config/apache.conf", "your apache config"
21
- #
22
- def create_file(destination, *args, &block)
23
- config = args.last.is_a?(Hash) ? args.pop : {}
24
- data = args.first
25
- action CreateFile.new(self, destination, block || data.to_s, config)
26
- end
27
- alias_method :add_file, :create_file
28
-
29
- # CreateFile is a subset of Template, which instead of rendering a file with
30
- # ERB, it gets the content from the user.
31
- #
32
- class CreateFile < EmptyDirectory #:nodoc:
33
- attr_reader :data
34
-
35
- def initialize(base, destination, data, config = {})
36
- @data = data
37
- super(base, destination, config)
38
- end
39
-
40
- # Checks if the content of the file at the destination is identical to the rendered result.
41
- #
42
- # ==== Returns
43
- # Boolean:: true if it is identical, false otherwise.
44
- #
45
- def identical?
46
- exists? && File.binread(destination) == render
47
- end
48
-
49
- # Holds the content to be added to the file.
50
- #
51
- def render
52
- @render ||= if data.is_a?(Proc)
53
- data.call
54
- else
55
- data
56
- end
57
- end
58
-
59
- def invoke!
60
- invoke_with_conflict_check do
61
- FileUtils.mkdir_p(File.dirname(destination))
62
- File.open(destination, "wb") { |f| f.write render }
63
- end
64
- given_destination
65
- end
66
-
67
- protected
68
-
69
- # Now on conflict we check if the file is identical or not.
70
- #
71
- def on_conflict_behavior(&block)
72
- if identical?
73
- say_status :identical, :blue
74
- else
75
- options = base.options.merge(config)
76
- force_or_skip_or_conflict(options[:force], options[:skip], &block)
77
- end
78
- end
79
-
80
- # If force is true, run the action, otherwise check if it's not being
81
- # skipped. If both are false, show the file_collision menu, if the menu
82
- # returns true, force it, otherwise skip.
83
- #
84
- def force_or_skip_or_conflict(force, skip, &block)
85
- if force
86
- say_status :force, :yellow
87
- yield unless pretend?
88
- elsif skip
89
- say_status :skip, :yellow
90
- else
91
- say_status :conflict, :red
92
- force_or_skip_or_conflict(force_on_collision?, true, &block)
93
- end
94
- end
95
-
96
- # Shows the file collision menu to the user and gets the result.
97
- #
98
- def force_on_collision?
99
- base.shell.file_collision(destination) { render }
100
- end
101
- end
102
- end
103
- end
@@ -1,59 +0,0 @@
1
- require "foreman/vendor/thor/lib/thor/actions/create_file"
2
-
3
- class Foreman::Thor
4
- module Actions
5
- # Create a new file relative to the destination root from the given source.
6
- #
7
- # ==== Parameters
8
- # destination<String>:: the relative path to the destination root.
9
- # source<String|NilClass>:: the relative path to the source root.
10
- # config<Hash>:: give :verbose => false to not log the status.
11
- # :: give :symbolic => false for hard link.
12
- #
13
- # ==== Examples
14
- #
15
- # create_link "config/apache.conf", "/etc/apache.conf"
16
- #
17
- def create_link(destination, *args)
18
- config = args.last.is_a?(Hash) ? args.pop : {}
19
- source = args.first
20
- action CreateLink.new(self, destination, source, config)
21
- end
22
- alias_method :add_link, :create_link
23
-
24
- # CreateLink is a subset of CreateFile, which instead of taking a block of
25
- # data, just takes a source string from the user.
26
- #
27
- class CreateLink < CreateFile #:nodoc:
28
- attr_reader :data
29
-
30
- # Checks if the content of the file at the destination is identical to the rendered result.
31
- #
32
- # ==== Returns
33
- # Boolean:: true if it is identical, false otherwise.
34
- #
35
- def identical?
36
- exists? && File.identical?(render, destination)
37
- end
38
-
39
- def invoke!
40
- invoke_with_conflict_check do
41
- FileUtils.mkdir_p(File.dirname(destination))
42
- # Create a symlink by default
43
- config[:symbolic] = true if config[:symbolic].nil?
44
- File.unlink(destination) if exists?
45
- if config[:symbolic]
46
- File.symlink(render, destination)
47
- else
48
- File.link(render, destination)
49
- end
50
- end
51
- given_destination
52
- end
53
-
54
- def exists?
55
- super || File.symlink?(destination)
56
- end
57
- end
58
- end
59
- end
@@ -1,118 +0,0 @@
1
- require "foreman/vendor/thor/lib/thor/actions/empty_directory"
2
-
3
- class Foreman::Thor
4
- module Actions
5
- # Copies recursively the files from source directory to root directory.
6
- # If any of the files finishes with .tt, it's considered to be a template
7
- # and is placed in the destination without the extension .tt. If any
8
- # empty directory is found, it's copied and all .empty_directory files are
9
- # ignored. If any file name is wrapped within % signs, the text within
10
- # the % signs will be executed as a method and replaced with the returned
11
- # value. Let's suppose a doc directory with the following files:
12
- #
13
- # doc/
14
- # components/.empty_directory
15
- # README
16
- # rdoc.rb.tt
17
- # %app_name%.rb
18
- #
19
- # When invoked as:
20
- #
21
- # directory "doc"
22
- #
23
- # It will create a doc directory in the destination with the following
24
- # files (assuming that the `app_name` method returns the value "blog"):
25
- #
26
- # doc/
27
- # components/
28
- # README
29
- # rdoc.rb
30
- # blog.rb
31
- #
32
- # <b>Encoded path note:</b> Since Foreman::Thor internals use Object#respond_to? to check if it can
33
- # expand %something%, this `something` should be a public method in the class calling
34
- # #directory. If a method is private, Foreman::Thor stack raises PrivateMethodEncodedError.
35
- #
36
- # ==== Parameters
37
- # source<String>:: the relative path to the source root.
38
- # destination<String>:: the relative path to the destination root.
39
- # config<Hash>:: give :verbose => false to not log the status.
40
- # If :recursive => false, does not look for paths recursively.
41
- # If :mode => :preserve, preserve the file mode from the source.
42
- # If :exclude_pattern => /regexp/, prevents copying files that match that regexp.
43
- #
44
- # ==== Examples
45
- #
46
- # directory "doc"
47
- # directory "doc", "docs", :recursive => false
48
- #
49
- def directory(source, *args, &block)
50
- config = args.last.is_a?(Hash) ? args.pop : {}
51
- destination = args.first || source
52
- action Directory.new(self, source, destination || source, config, &block)
53
- end
54
-
55
- class Directory < EmptyDirectory #:nodoc:
56
- attr_reader :source
57
-
58
- def initialize(base, source, destination = nil, config = {}, &block)
59
- @source = File.expand_path(base.find_in_source_paths(source.to_s))
60
- @block = block
61
- super(base, destination, {:recursive => true}.merge(config))
62
- end
63
-
64
- def invoke!
65
- base.empty_directory given_destination, config
66
- execute!
67
- end
68
-
69
- def revoke!
70
- execute!
71
- end
72
-
73
- protected
74
-
75
- def execute!
76
- lookup = Util.escape_globs(source)
77
- lookup = config[:recursive] ? File.join(lookup, "**") : lookup
78
- lookup = file_level_lookup(lookup)
79
-
80
- files(lookup).sort.each do |file_source|
81
- next if File.directory?(file_source)
82
- next if config[:exclude_pattern] && file_source.match(config[:exclude_pattern])
83
- file_destination = File.join(given_destination, file_source.gsub(source, "."))
84
- file_destination.gsub!("/./", "/")
85
-
86
- case file_source
87
- when /\.empty_directory$/
88
- dirname = File.dirname(file_destination).gsub(%r{/\.$}, "")
89
- next if dirname == given_destination
90
- base.empty_directory(dirname, config)
91
- when /#{TEMPLATE_EXTNAME}$/
92
- base.template(file_source, file_destination[0..-4], config, &@block)
93
- else
94
- base.copy_file(file_source, file_destination, config, &@block)
95
- end
96
- end
97
- end
98
-
99
- if RUBY_VERSION < "2.0"
100
- def file_level_lookup(previous_lookup)
101
- File.join(previous_lookup, "{*,.[a-z]*}")
102
- end
103
-
104
- def files(lookup)
105
- Dir[lookup]
106
- end
107
- else
108
- def file_level_lookup(previous_lookup)
109
- File.join(previous_lookup, "*")
110
- end
111
-
112
- def files(lookup)
113
- Dir.glob(lookup, File::FNM_DOTMATCH)
114
- end
115
- end
116
- end
117
- end
118
- end
@@ -1,135 +0,0 @@
1
- class Foreman::Thor
2
- module Actions
3
- # Creates an empty directory.
4
- #
5
- # ==== Parameters
6
- # destination<String>:: the relative path to the destination root.
7
- # config<Hash>:: give :verbose => false to not log the status.
8
- #
9
- # ==== Examples
10
- #
11
- # empty_directory "doc"
12
- #
13
- def empty_directory(destination, config = {})
14
- action EmptyDirectory.new(self, destination, config)
15
- end
16
-
17
- # Class which holds create directory logic. This is the base class for
18
- # other actions like create_file and directory.
19
- #
20
- # This implementation is based in Templater actions, created by Jonas Nicklas
21
- # and Michael S. Klishin under MIT LICENSE.
22
- #
23
- class EmptyDirectory #:nodoc:
24
- attr_reader :base, :destination, :given_destination, :relative_destination, :config
25
-
26
- # Initializes given the source and destination.
27
- #
28
- # ==== Parameters
29
- # base<Foreman::Thor::Base>:: A Foreman::Thor::Base instance
30
- # source<String>:: Relative path to the source of this file
31
- # destination<String>:: Relative path to the destination of this file
32
- # config<Hash>:: give :verbose => false to not log the status.
33
- #
34
- def initialize(base, destination, config = {})
35
- @base = base
36
- @config = {:verbose => true}.merge(config)
37
- self.destination = destination
38
- end
39
-
40
- # Checks if the destination file already exists.
41
- #
42
- # ==== Returns
43
- # Boolean:: true if the file exists, false otherwise.
44
- #
45
- def exists?
46
- ::File.exist?(destination)
47
- end
48
-
49
- def invoke!
50
- invoke_with_conflict_check do
51
- ::FileUtils.mkdir_p(destination)
52
- end
53
- end
54
-
55
- def revoke!
56
- say_status :remove, :red
57
- ::FileUtils.rm_rf(destination) if !pretend? && exists?
58
- given_destination
59
- end
60
-
61
- protected
62
-
63
- # Shortcut for pretend.
64
- #
65
- def pretend?
66
- base.options[:pretend]
67
- end
68
-
69
- # Sets the absolute destination value from a relative destination value.
70
- # It also stores the given and relative destination. Let's suppose our
71
- # script is being executed on "dest", it sets the destination root to
72
- # "dest". The destination, given_destination and relative_destination
73
- # are related in the following way:
74
- #
75
- # inside "bar" do
76
- # empty_directory "baz"
77
- # end
78
- #
79
- # destination #=> dest/bar/baz
80
- # relative_destination #=> bar/baz
81
- # given_destination #=> baz
82
- #
83
- def destination=(destination)
84
- return unless destination
85
- @given_destination = convert_encoded_instructions(destination.to_s)
86
- @destination = ::File.expand_path(@given_destination, base.destination_root)
87
- @relative_destination = base.relative_to_original_destination_root(@destination)
88
- end
89
-
90
- # Filenames in the encoded form are converted. If you have a file:
91
- #
92
- # %file_name%.rb
93
- #
94
- # It calls #file_name from the base and replaces %-string with the
95
- # return value (should be String) of #file_name:
96
- #
97
- # user.rb
98
- #
99
- # The method referenced can be either public or private.
100
- #
101
- def convert_encoded_instructions(filename)
102
- filename.gsub(/%(.*?)%/) do |initial_string|
103
- method = $1.strip
104
- base.respond_to?(method, true) ? base.send(method) : initial_string
105
- end
106
- end
107
-
108
- # Receives a hash of options and just execute the block if some
109
- # conditions are met.
110
- #
111
- def invoke_with_conflict_check(&block)
112
- if exists?
113
- on_conflict_behavior(&block)
114
- else
115
- say_status :create, :green
116
- yield unless pretend?
117
- end
118
-
119
- destination
120
- end
121
-
122
- # What to do when the destination file already exists.
123
- #
124
- def on_conflict_behavior
125
- say_status :exist, :blue
126
- end
127
-
128
- # Shortcut to say_status shell method.
129
- #
130
- def say_status(status, color)
131
- base.shell.say_status status, relative_destination, color if config[:verbose]
132
- end
133
- end
134
- end
135
- end