planter-cli 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +9 -0
- data/.gitignore +44 -0
- data/.irbrc +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +78 -0
- data/.travis.yml +7 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +45 -0
- data/Gemfile +6 -0
- data/Guardfile +25 -0
- data/LICENSE.txt +20 -0
- data/README.md +208 -0
- data/Rakefile +132 -0
- data/bin/plant +106 -0
- data/debug.log +0 -0
- data/docker/Dockerfile +12 -0
- data/docker/Dockerfile-2.6 +12 -0
- data/docker/Dockerfile-2.7 +12 -0
- data/docker/Dockerfile-3.0 +11 -0
- data/docker/bash_profile +15 -0
- data/docker/inputrc +57 -0
- data/lib/.rubocop.yml +1 -0
- data/lib/planter/array.rb +28 -0
- data/lib/planter/color.rb +370 -0
- data/lib/planter/errors.rb +59 -0
- data/lib/planter/file.rb +11 -0
- data/lib/planter/fileentry.rb +87 -0
- data/lib/planter/filelist.rb +144 -0
- data/lib/planter/hash.rb +103 -0
- data/lib/planter/plant.rb +228 -0
- data/lib/planter/prompt.rb +352 -0
- data/lib/planter/script.rb +59 -0
- data/lib/planter/string.rb +383 -0
- data/lib/planter/symbol.rb +28 -0
- data/lib/planter/version.rb +7 -0
- data/lib/planter.rb +222 -0
- data/planter-cli.gemspec +48 -0
- data/scripts/deploy.rb +97 -0
- data/scripts/runtests.sh +5 -0
- data/spec/.rubocop.yml +4 -0
- data/spec/planter/plant_spec.rb +14 -0
- data/spec/planter/string_spec.rb +20 -0
- data/spec/spec_helper.rb +20 -0
- data/src/_README.md +214 -0
- metadata +400 -0
data/lib/planter/file.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Planter
|
4
|
+
# A single file entry in a FileList
|
5
|
+
class FileEntry < Hash
|
6
|
+
# Operation to execute on the file
|
7
|
+
attr_accessor :operation
|
8
|
+
|
9
|
+
# File path and target path
|
10
|
+
attr_reader :file, :target
|
11
|
+
|
12
|
+
##
|
13
|
+
## Initialize a FileEntry object
|
14
|
+
##
|
15
|
+
## @param file [String] The source file path
|
16
|
+
## @param target [String] The target path
|
17
|
+
## @param operation [Symbol] The operation to perform
|
18
|
+
##
|
19
|
+
## @return [FileEntry] a Hash of parameters
|
20
|
+
##
|
21
|
+
def initialize(file, target, operation)
|
22
|
+
@file = file
|
23
|
+
@target = target
|
24
|
+
@operation = operation
|
25
|
+
|
26
|
+
super()
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
## Test if file matches any pattern in config
|
31
|
+
##
|
32
|
+
## @return [Boolean] file matches pattern
|
33
|
+
##
|
34
|
+
def matches_pattern?
|
35
|
+
Planter.patterns.filter { |pattern, _| @file =~ pattern }.count.positive?
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
## Determine operators based on configured filters,
|
40
|
+
## asking for input if necessary
|
41
|
+
##
|
42
|
+
## @return [Symbol] Operator
|
43
|
+
##
|
44
|
+
def test_operator
|
45
|
+
operator = Planter.overwrite ? :overwrite : :copy
|
46
|
+
Planter.patterns.each do |pattern, op|
|
47
|
+
next unless @file =~ pattern
|
48
|
+
|
49
|
+
operator = op == :ask && !Planter.overwrite ? ask_operation : op
|
50
|
+
break
|
51
|
+
end
|
52
|
+
operator
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
## Prompt for file handling. If File exists, offer a merge/overwrite/ignore,
|
57
|
+
## otherwise simply ask whether or not to copy.
|
58
|
+
##
|
59
|
+
def ask_operation
|
60
|
+
if File.exist?(@target)
|
61
|
+
Prompt.file_what?(self)
|
62
|
+
else
|
63
|
+
res = Prompt.yn("Copy #{File.basename(@file)} to #{File.basename(@target)}",
|
64
|
+
default_response: true)
|
65
|
+
res ? :copy : :ignore
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
## Returns a string representation of the object.
|
71
|
+
##
|
72
|
+
## @return [String] String representation of the object.
|
73
|
+
##
|
74
|
+
def inspect
|
75
|
+
"<FileEntry: @file: #{@file}, @target: #{@target}, @operation: #{@operation}>"
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
## Returns a string representation of the object contents.
|
80
|
+
##
|
81
|
+
## @return [String] String representation of the object.
|
82
|
+
##
|
83
|
+
def to_s
|
84
|
+
File.binary?(@file) ? 'Binary file' : IO.read(@file).to_s
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Planter
|
4
|
+
# File listing class
|
5
|
+
class FileList
|
6
|
+
attr_reader :files
|
7
|
+
|
8
|
+
##
|
9
|
+
## Initialize a new FileList object
|
10
|
+
##
|
11
|
+
## @param path [String] The base path for template
|
12
|
+
##
|
13
|
+
def initialize(path)
|
14
|
+
@basedir = File.realdirpath(path)
|
15
|
+
|
16
|
+
search_path = File.join(@basedir, '**/*')
|
17
|
+
files = Dir.glob(search_path, File::FNM_DOTMATCH).reject do |file|
|
18
|
+
file =~ %r{/(_scripts|\.git|_config\.yml$|\.{1,2}$)}
|
19
|
+
end
|
20
|
+
|
21
|
+
files.sort_by!(&:length)
|
22
|
+
|
23
|
+
@files = files.map do |file|
|
24
|
+
new_file = "#{Planter.target}#{file.sub(/^#{@basedir}/, '').apply_variables.apply_regexes}"
|
25
|
+
operation = Planter.overwrite ? :overwrite : :copy
|
26
|
+
FileEntry.new(file, new_file, operation)
|
27
|
+
end
|
28
|
+
|
29
|
+
prepare_copy
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
## Public method for copying files based on their operator
|
34
|
+
##
|
35
|
+
## @return [Boolean] success
|
36
|
+
##
|
37
|
+
def copy
|
38
|
+
@files.each do |file|
|
39
|
+
handle_operator(file)
|
40
|
+
end
|
41
|
+
rescue StandardError => e
|
42
|
+
Planter.notify("#{e}\n#{e.backtrace}", :debug)
|
43
|
+
Planter.notify('Error copying files/directories', :error, exit_code: 128)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
##
|
49
|
+
## Perform operations
|
50
|
+
##
|
51
|
+
## @param entry [FileEntry] The file entry
|
52
|
+
##
|
53
|
+
def handle_operator(entry)
|
54
|
+
case entry.operation
|
55
|
+
when :ignore
|
56
|
+
false
|
57
|
+
when :overwrite
|
58
|
+
copy_file(entry, overwrite: true)
|
59
|
+
when :merge
|
60
|
+
File.exist?(entry.target) ? merge(entry) : copy_file(entry)
|
61
|
+
else
|
62
|
+
copy_file(entry)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
## Copy template files to new directory
|
68
|
+
##
|
69
|
+
## @return [Boolean] success
|
70
|
+
##
|
71
|
+
def prepare_copy
|
72
|
+
@files.each do |entry|
|
73
|
+
if entry.matches_pattern?
|
74
|
+
entry.operation = entry.test_operator
|
75
|
+
propogate_operation(entry)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
## Apply a parent operation to children
|
82
|
+
##
|
83
|
+
## @param entry [FileEntry] The file entry
|
84
|
+
##
|
85
|
+
def propogate_operation(entry)
|
86
|
+
@files.each do |file|
|
87
|
+
file.operation = entry.operation if file.file =~ /^#{entry.file}/
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
## Copy tagged merge sections from source to target
|
93
|
+
##
|
94
|
+
## @param entry [FileEntry] The file entry
|
95
|
+
##
|
96
|
+
def merge(entry)
|
97
|
+
return copy_file(entry) if File.directory?(entry.file)
|
98
|
+
|
99
|
+
type = `file #{entry.file}`
|
100
|
+
case type.sub(/^#{Regexp.escape(entry.file)}: /, '').split(/:/).first
|
101
|
+
when /Apple binary property list/
|
102
|
+
`plutil -convert xml1 #{entry.file}`
|
103
|
+
`plutil -convert xml1 #{entry.target}`
|
104
|
+
content = IO.read(entry.file)
|
105
|
+
when /data/
|
106
|
+
return copy_file(entry)
|
107
|
+
else
|
108
|
+
return copy_file(entry) if File.binary?(entry.file)
|
109
|
+
|
110
|
+
content = IO.read(entry.file)
|
111
|
+
end
|
112
|
+
|
113
|
+
merges = content.scan(%r{(?<=\A|\n).{,4}merge *\n(.*?)\n.{,4}/merge}m)
|
114
|
+
&.map { |m| m[0].strip.apply_variables.apply_regexes }
|
115
|
+
merges = [content] if !merges || merges.empty?
|
116
|
+
new_content = IO.read(entry.target)
|
117
|
+
merges.delete_if { |m| new_content =~ /#{Regexp.escape(m)}/ }
|
118
|
+
if merges.count.positive?
|
119
|
+
File.open(entry.target, 'w') { |f| f.puts "#{new_content.chomp}\n\n#{merges.join("\n\n")}" }
|
120
|
+
Planter.notify("Merged #{entry.file} => #{entry.target} (#{merges.count} merges)", :debug)
|
121
|
+
else
|
122
|
+
copy_file(entry)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
## Perform file copy based on operator
|
128
|
+
##
|
129
|
+
## @param file [FileEntry] The file entry
|
130
|
+
## @param overwrite [Boolean] Force overwrite
|
131
|
+
##
|
132
|
+
def copy_file(file, overwrite: false)
|
133
|
+
if !File.exist?(file.target) || overwrite || Planter.overwrite
|
134
|
+
FileUtils.mkdir_p(File.dirname(file.target))
|
135
|
+
FileUtils.cp(file.file, file.target) unless File.directory?(file.file)
|
136
|
+
Planter.notify("Copied #{file.file} => #{file.target}", :debug)
|
137
|
+
true
|
138
|
+
else
|
139
|
+
Planter.notify("Skipped #{file.file} => #{file.target}", :debug)
|
140
|
+
false
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
data/lib/planter/hash.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Hash helpers
|
4
|
+
class ::Hash
|
5
|
+
## Turn all keys into string
|
6
|
+
##
|
7
|
+
## @return [Hash] copy of the hash where all its keys are strings
|
8
|
+
##
|
9
|
+
def stringify_keys
|
10
|
+
each_with_object({}) do |(k, v), hsh|
|
11
|
+
hsh[k.to_s] = if v.is_a?(Hash)
|
12
|
+
v.stringify_keys
|
13
|
+
elsif v.is_a?(Array)
|
14
|
+
v.map(&:symbolize_keys)
|
15
|
+
else
|
16
|
+
v
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
## Turn all keys into symbols
|
23
|
+
##
|
24
|
+
## @return [Hash] hash with symbolized keys
|
25
|
+
##
|
26
|
+
def symbolize_keys
|
27
|
+
each_with_object({}) do |(k, v), hsh|
|
28
|
+
hsh[k.to_sym] = if v.is_a?(Hash)
|
29
|
+
v.symbolize_keys
|
30
|
+
elsif v.is_a?(Array)
|
31
|
+
v.map(&:symbolize_keys)
|
32
|
+
else
|
33
|
+
v
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
## Deep merge a hash
|
40
|
+
##
|
41
|
+
## @param second [Hash] The hash to merge into self
|
42
|
+
##
|
43
|
+
def deep_merge(second)
|
44
|
+
merger = proc do |_, v1, v2|
|
45
|
+
if v1.is_a?(Hash) && v2.is_a?(Hash)
|
46
|
+
v1.merge(v2, &merger)
|
47
|
+
elsif v1.is_a?(Array) && v2.is_a?(Array)
|
48
|
+
v1 | v2
|
49
|
+
elsif [:undefined, nil, :nil].include?(v2)
|
50
|
+
v1
|
51
|
+
else
|
52
|
+
v2
|
53
|
+
end
|
54
|
+
end
|
55
|
+
merge(second.to_h, &merger)
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
## Freeze all values in a hash
|
60
|
+
##
|
61
|
+
## @return [Hash] Hash with all values frozen
|
62
|
+
##
|
63
|
+
def deep_freeze
|
64
|
+
chilled = {}
|
65
|
+
each do |k, v|
|
66
|
+
chilled[k] = v.is_a?(Hash) ? v.deep_freeze : v.freeze
|
67
|
+
end
|
68
|
+
|
69
|
+
chilled.freeze
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
## Destructive version of #deep_freeze
|
74
|
+
##
|
75
|
+
## @return [Hash] Hash with all values frozen
|
76
|
+
##
|
77
|
+
def deep_freeze!
|
78
|
+
replace deep_thaw.deep_freeze
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
## Unfreeze a hash and all nested values
|
83
|
+
##
|
84
|
+
## @return [Hash] unfrozen hash
|
85
|
+
##
|
86
|
+
def deep_thaw
|
87
|
+
chilled = {}
|
88
|
+
each do |k, v|
|
89
|
+
chilled[k] = v.is_a?(Hash) ? v.deep_thaw : v.dup
|
90
|
+
end
|
91
|
+
|
92
|
+
chilled.dup
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
## Destructive version of #deep_thaw
|
97
|
+
##
|
98
|
+
## @return [Hash] unfrozen hash
|
99
|
+
##
|
100
|
+
def deep_thaw!
|
101
|
+
replace deep_thaw
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Planter
|
4
|
+
# Primary class
|
5
|
+
class Plant
|
6
|
+
##
|
7
|
+
## Initialize a new Plant object
|
8
|
+
##
|
9
|
+
## @param template [String] the template name
|
10
|
+
## @param variables [Hash] Pre-populated variables
|
11
|
+
##
|
12
|
+
def initialize(template = nil, variables = nil)
|
13
|
+
Planter.variables = variables if variables.is_a?(Hash)
|
14
|
+
Planter.config = template if template
|
15
|
+
|
16
|
+
@basedir = File.join(Planter::BASE_DIR, 'templates', Planter.template)
|
17
|
+
@target = Planter.target || Dir.pwd
|
18
|
+
|
19
|
+
@git = Planter.config[:git_init] || false
|
20
|
+
@debug = Planter.debug
|
21
|
+
@repo = Planter.config[:repo] || false
|
22
|
+
|
23
|
+
# Coerce any existing variables (like from the command line) to the types
|
24
|
+
# defined in configuration
|
25
|
+
coerced = {}
|
26
|
+
Planter.variables.each do |k, v|
|
27
|
+
cfg_var = Planter.config[:variables].select { |var| k = var[:key] }
|
28
|
+
next unless cfg_var.count.positive?
|
29
|
+
|
30
|
+
var = cfg_var.first
|
31
|
+
type = var[:type].normalize_type
|
32
|
+
coerced[k] = v.coerce(type)
|
33
|
+
end
|
34
|
+
coerced.each { |k, v| Planter.variables[k] = v }
|
35
|
+
|
36
|
+
# Ask user for any variables not already defined
|
37
|
+
Planter.config[:variables].each do |var|
|
38
|
+
key = var[:key].to_var
|
39
|
+
next if Planter.variables.keys.include?(key)
|
40
|
+
|
41
|
+
q = Planter::Prompt::Question.new(
|
42
|
+
key: key,
|
43
|
+
prompt: var[:prompt] || var[:key],
|
44
|
+
type: var[:type].normalize_type || :string,
|
45
|
+
default: var[:default],
|
46
|
+
value: var[:value],
|
47
|
+
min: var[:min],
|
48
|
+
max: var[:max]
|
49
|
+
)
|
50
|
+
answer = q.ask
|
51
|
+
if answer.nil?
|
52
|
+
Planter.notify("Missing value #{key}", :error, exit_code: 15) unless var[:default]
|
53
|
+
|
54
|
+
answer = var[:default]
|
55
|
+
end
|
56
|
+
|
57
|
+
Planter.variables[key] = answer
|
58
|
+
end
|
59
|
+
|
60
|
+
git_pull if @repo
|
61
|
+
|
62
|
+
@files = FileList.new(@basedir)
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
## Expand GitHub name to full path
|
67
|
+
##
|
68
|
+
## @example Pass a GitHub-style repo path and get full url
|
69
|
+
## expand_repo("ttscoff/planter-cli") #=> https://github.com/ttscoff/planter-cli.git
|
70
|
+
##
|
71
|
+
## @return { description_of_the_return_value }
|
72
|
+
##
|
73
|
+
def expand_repo(repo)
|
74
|
+
repo =~ %r{(?!=http)\w+/\w+} ? "https://github.com/#{repo}.git" : repo
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
## Directory for repo, subdirectory of template
|
79
|
+
##
|
80
|
+
## @return [String] repo path
|
81
|
+
##
|
82
|
+
def repo_dir
|
83
|
+
File.join(@basedir, File.basename(@repo).sub(/\.git$/, ''))
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
## Pull or clone a git repo
|
88
|
+
##
|
89
|
+
## @return [String] new base directory
|
90
|
+
##
|
91
|
+
def git_pull
|
92
|
+
Planter.spinner.update(title: 'Pulling git repo')
|
93
|
+
|
94
|
+
raise Errors::GitError.new('`git` executable not found') unless TTY::Which.exist?('git')
|
95
|
+
|
96
|
+
pwd = Dir.pwd
|
97
|
+
@repo = expand_repo(@repo)
|
98
|
+
|
99
|
+
if File.exist?(repo_dir)
|
100
|
+
Dir.chdir(repo_dir)
|
101
|
+
raise Errors::GitError.new("Directory #{repo_dir} exists but is not git repo") unless File.exist?('.git')
|
102
|
+
|
103
|
+
res = `git pull`
|
104
|
+
raise Errors::GitError.new("Error pulling #{@repo}:\n#{res}") unless $?.success?
|
105
|
+
else
|
106
|
+
Dir.chdir(@basedir)
|
107
|
+
res = `git clone "#{@repo}" "#{repo_dir}"`
|
108
|
+
raise Errors::GitError.new("Error cloning #{@repo}:\n#{res}") unless $?.success?
|
109
|
+
end
|
110
|
+
Dir.chdir(pwd)
|
111
|
+
@basedir = repo_dir
|
112
|
+
rescue StandardError => e
|
113
|
+
raise Errors::GitError.new("Error pulling #{@repo}:\n#{e.message}")
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
## Plant the template to current directory
|
118
|
+
##
|
119
|
+
def plant
|
120
|
+
Dir.chdir(@target)
|
121
|
+
|
122
|
+
Planter.spinner.auto_spin
|
123
|
+
Planter.spinner.update(title: 'Copying files')
|
124
|
+
res = copy_files
|
125
|
+
if res.is_a?(String)
|
126
|
+
Planter.spinner.error("(#{res})")
|
127
|
+
Process.exit 1
|
128
|
+
end
|
129
|
+
|
130
|
+
Planter.spinner.update(title: 'Applying variables')
|
131
|
+
|
132
|
+
res = update_files
|
133
|
+
if res.is_a?(String)
|
134
|
+
Planter.spinner.error('(Error)')
|
135
|
+
Planter.notify(res, :error, exit_code: 1)
|
136
|
+
end
|
137
|
+
|
138
|
+
if @git
|
139
|
+
raise Errors::GitError.new('`git` executable not found') unless TTY::Which.exist?('git')
|
140
|
+
|
141
|
+
Planter.spinner.update(title: 'Initializing git repo')
|
142
|
+
res = add_git
|
143
|
+
if res.is_a?(String)
|
144
|
+
Planter.spinner.error('(Error)')
|
145
|
+
Planter.notify(res, :error, exit_code: 1)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
if Planter.config[:script]
|
150
|
+
Planter.spinner.update(title: 'Running script')
|
151
|
+
|
152
|
+
scripts = Planter.config[:script]
|
153
|
+
scripts = [scripts] if scripts.is_a?(String)
|
154
|
+
scripts.each do |script|
|
155
|
+
s = Planter::Script.new(@basedir, Dir.pwd, script)
|
156
|
+
s.run
|
157
|
+
end
|
158
|
+
end
|
159
|
+
Planter.spinner.update(title: '😄')
|
160
|
+
Planter.spinner.success(' Planting complete!')
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
## Copy files from template directory, renaming if %%template vars%% exist in title
|
165
|
+
##
|
166
|
+
## @return true if successful, otherwise error description
|
167
|
+
##
|
168
|
+
def copy_files
|
169
|
+
@files.copy
|
170
|
+
true
|
171
|
+
end
|
172
|
+
|
173
|
+
##
|
174
|
+
## Update content of files in new directory using template variables
|
175
|
+
##
|
176
|
+
def update_files
|
177
|
+
files = Dir.glob('**/*', File::FNM_DOTMATCH).reject { |f| File.directory?(f) || f =~ /^(\.git|config\.yml)/ }
|
178
|
+
|
179
|
+
files.each do |file|
|
180
|
+
type = `file #{file}`
|
181
|
+
case type.sub(/^#{Regexp.escape(file)}: /, '').split(/:/).first
|
182
|
+
when /Apple binary property list/
|
183
|
+
`plutil -convert xml1 #{file}`
|
184
|
+
when /data/
|
185
|
+
next
|
186
|
+
else
|
187
|
+
next if File.binary?(file)
|
188
|
+
end
|
189
|
+
|
190
|
+
content = IO.read(file)
|
191
|
+
new_content = content.apply_variables.apply_regexes
|
192
|
+
|
193
|
+
new_content.gsub!(%r{^.{.4}/?merge *.{,4}\n}, '') if new_content =~ /^.{.4}merge *\n/
|
194
|
+
|
195
|
+
unless content == new_content
|
196
|
+
Planter.notify("Applying variables to #{file}", :debug)
|
197
|
+
File.open(file, 'w') { |f| f.puts new_content }
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
true
|
202
|
+
rescue StandardError => e
|
203
|
+
Planter.notify("#{e}\n#{e.backtrace}", :debug)
|
204
|
+
'Error updating files/directories'
|
205
|
+
end
|
206
|
+
|
207
|
+
##
|
208
|
+
## Initialize a git repo and create initial commit/tag
|
209
|
+
##
|
210
|
+
## @return true if successful, otherwise an error description
|
211
|
+
##
|
212
|
+
def add_git
|
213
|
+
return if File.directory?('.git')
|
214
|
+
|
215
|
+
res = pass_fail('git init')
|
216
|
+
res = pass_fail('git add .') if res
|
217
|
+
res = pass_fail('git commit -a -m "initial commit"') if res
|
218
|
+
res = pass_fail('git tag -a 0.0.1 -m "v0.0.1"') if res
|
219
|
+
|
220
|
+
raise StandardError unless res
|
221
|
+
|
222
|
+
true
|
223
|
+
rescue StandardError => e
|
224
|
+
Planter.notify("#{e}\n#{e.backtrace}", :debug)
|
225
|
+
'Error initializing git'
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|